115 lines
2.2 KiB
Bash
Executable File
115 lines
2.2 KiB
Bash
Executable File
#!/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
|
|
|
|
}
|