You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
2.2 KiB
114 lines
2.2 KiB
#!/bin/sh |
|
# How much of the very original version from Linus survive? |
|
|
|
_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' |
|
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" |
|
|
|
summary= |
|
while case $# in 0) break ;; esac |
|
do |
|
case "$1" in |
|
-s | --summary) |
|
summary=t |
|
;; |
|
-*) |
|
echo >&2 "$1: unknown option" |
|
exit 1 |
|
;; |
|
*) |
|
break |
|
;; |
|
esac |
|
shift |
|
done |
|
|
|
if test $# = 0 |
|
then |
|
this=HEAD |
|
else |
|
this=$1 |
|
shift |
|
fi |
|
|
|
if test $# = 0 |
|
then |
|
initial=e83c5163316f89bfbde7d9ab23ca2e25604af290 |
|
range="..$this" |
|
else |
|
initial=$1 |
|
range="$initial..$this" |
|
shift |
|
fi |
|
|
|
this=$(git rev-parse --verify "$this^0") && |
|
initial=$(git rev-parse --verify "$initial^0") || exit |
|
|
|
tmp="/var/tmp/Linus.$$" |
|
trap 'rm -f "$tmp".*' 0 |
|
|
|
# We blame each file in the initial revision pretending as if it is a |
|
# direct descendant of the given version, and also pretend that the |
|
# latter is a root commit. This way, lines in the initial revision |
|
# that survived to the other version can be identified (they will be |
|
# attributed to the other version). |
|
graft="$tmp.graft" && |
|
{ |
|
echo "$initial $this" |
|
echo "$this" |
|
} >"$graft" || exit |
|
|
|
opts='-C -C -C -w' |
|
|
|
show () { |
|
s=$1 t=$2 n=$3 |
|
p=$(($s * 100 / $t)) |
|
c=$(($s * 10000 / $t - $p * 100)) |
|
printf "%12d %12d %s (%d.%02d%%)\n" $s $t $n $p $c |
|
} |
|
|
|
empty_tree=$(git hash-object -t tree -w --stdin </dev/null) |
|
|
|
git diff-tree -r --raw $empty_tree $initial -- "$@" | |
|
while read mode_old mode_new sha1_old sha1_new op name |
|
do |
|
git blame $opts --porcelain -S "$graft" "$this..$initial" -- "$name" | |
|
sed -ne "s/^\($_x40\) .*/\1/p" | |
|
sort | |
|
uniq -c | { |
|
# There are only two commits in the fake history, so |
|
# there will be at most two output from the above. |
|
read cnt1 commit1 |
|
read cnt2 commit2 |
|
if test -z "$commit2" |
|
then |
|
cnt2=0 |
|
fi |
|
if test "$initial" != "$commit1" |
|
then |
|
cnt_surviving=$cnt1 |
|
else |
|
cnt_surviving=$cnt2 |
|
fi |
|
cnt_total=$(( $cnt1 + $cnt2 )) |
|
echo "$cnt_surviving $cnt_total $name" |
|
} |
|
done | { |
|
total=0 |
|
surviving=0 |
|
test -n "$summary" || |
|
printf "%12s %12s %s (survival%%)\n" surviving original path |
|
while read s t n |
|
do |
|
total=$(( $total + $t )) surviving=$(( $surviving + $s )) |
|
test -n "$summary" || |
|
show $s $t $n |
|
done |
|
if test -n "$summary" |
|
then |
|
echo $surviving $total |
|
else |
|
label=Total |
|
show $surviving $total $label |
|
fi |
|
|
|
}
|
|
|