File: git-utimes

package info (click to toggle)
git-extras 7.4.0-1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 2,120 kB
  • sloc: sh: 4,312; python: 994; makefile: 146
file content (131 lines) | stat: -rwxr-xr-x 2,885 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env bash
#
# Change files modification time to their last commit date
#

# Bash unofficial strict mode
set -euo pipefail
IFS=$'\n\t'

if [[ "${1:-}" == "--newer" ]]; then
  op=le
  shift
else
  op=eq
fi

# BSD systems
if date -j &>/dev/null; then
  stat_flags="-f %m"
  date_flags="-r"
else
  # Non-BSD systems
  stat_flags="-c %Y"
  date_flags="-d@"
fi

bash_opts=()
if bash --help 2>&1 | grep -q -- '--noprofile'; then
  bash_opts+=(--noprofile)
fi
if bash --help 2>&1 | grep -q -- '--norc'; then
  bash_opts+=(--norc)
fi

status_opts=(--porcelain --short)
# %ct: committer date, UNIX timestamp / %at: author date, UNIX timestamp
whatchanged_opts=(--format='%ct')
if git status --help 2>&1 | grep -q -- "--no-renames"; then
  status_opts+=(--no-renames)
  whatchanged_opts+=(--no-renames)
fi
if git status --help 2>&1 | grep -q -- "--untracked-files"; then
  status_opts+=(--untracked-files=no)
fi
if git status --help 2>&1 | grep -q -- "--ignored"; then
  status_opts+=(--ignored=no)
fi

prefix="$(git rev-parse --show-prefix) "
strip="${#prefix}"

tmpfile=$(mktemp)
# shellcheck disable=SC2064
trap "rm -f '${tmpfile}'" 0

awk_flags=(
  -F'\t'
  -v date_flags="${date_flags}"
  -v op="${op}"
  -v stat_flags="${stat_flags}"
  -v strip="${strip}"
  -v tmpfile="${tmpfile}"
)

# sanity check, not required:
if awk --help 2>&1 | grep -q -- '--posix'; then
  awk_flags+=(--posix)
fi

read -r -d '' awk_script <<"EOF" || true
BEGIN {
  seen[""]=1
  print "#!/usr/bin/env bash"
  print "set +e"
  print "t() {"
  print " test -e \"$2\" || return 0"
  printf(" test \"$(stat %s \"$2\" 2>/dev/null)\" -%s \"$1\" && return 0\n", stat_flags, op)
  if (date_flags == "-d@") {
    print " echo \"+ touch -h -d@$1 $2\""
    print " touch -h -d@$1 \"$2\""
  } else {
    print " t=$(date -r$1 \"+%Y%m%d%H%M.%S\")"
    print " echo \"+ touch -h -t $t $2\""
    print " touch -h -t $t \"$2\""
  }
  print "}"
}
FILENAME==tmpfile {
  skip[$1]=1
  next
}
# skip blank lines
!/^$/ {
  # skip deletes
  if (substr($1, length($1), 1) ~ /D/) {
    next
  }
  if (NF == 1) {
    ct=$1
    next
  }
  $2 = substr($2, strip, length($2)- strip + 1)
  if ($2 in seen) {
    next
  }
  if ($2 in skip) {
    next
  }
  seen[$2]=1
  # remove enclosing double quotes that git adds:
  if (substr($2, 1, 1) == "\"" && substr($2, length($2), 1) == "\"") {
    $2 = substr($2, 2, length($2) - 2)
    # unescape remaining double quotes
    gsub(/\\"/, "\"", $2)
    # unescape escaped backslashes
    gsub(/\\\\/, "\\", $2)
  }
  # escape apostrophes: ' => '\''
  gsub(/'/, "'\\''", $2)
  printf("t %s '%s'\n", ct, $2)
}
EOF

# prefix is stripped:
git --no-pager status "${status_opts[@]}" . \
  | cut -c 4- >"${tmpfile}"

# prefix is not stripped:
git --no-pager whatchanged "${whatchanged_opts[@]}" . \
  | awk "${awk_flags[@]}" "${awk_script}" "${tmpfile}" - \
  | BASH_ENV='' bash "${bash_opts[@]}" -