mirror of
https://github.com/tj/git-extras.git
synced 2026-09-10 15:36:21 -04:00
218 lines
3.9 KiB
Bash
Executable file
218 lines
3.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
tmp=$(git_extra_mktemp)
|
|
above=0
|
|
color=
|
|
|
|
#
|
|
# get dates for the given <commit>
|
|
#
|
|
dates() {
|
|
eval "git log --pretty='format: %ad' --date=short $args_to_git_log \"$1\""
|
|
}
|
|
|
|
#
|
|
# hide cursor
|
|
#
|
|
|
|
hide_cursor() {
|
|
printf '\033[?25l'
|
|
}
|
|
|
|
#
|
|
# show cursor, and remove temporary file
|
|
#
|
|
|
|
show_cursor_and_cleanup() {
|
|
printf '\033[?25h'
|
|
printf '\033[m\n'
|
|
rm "$tmp" > /dev/null 2>&1
|
|
exit 0
|
|
}
|
|
|
|
#
|
|
# get active days for the given <commit>
|
|
#
|
|
|
|
active_days() {
|
|
echo "$1" | uniq | wc -l
|
|
}
|
|
|
|
#
|
|
# set 'color' based on the given <num>
|
|
#
|
|
|
|
color_for() {
|
|
test $1 -gt 10 && color='33'
|
|
test $1 -gt 25 && color='33;1'
|
|
test $1 -gt 50 && color='93'
|
|
test $1 -gt 75 && color='93;1'
|
|
test $1 -gt 100 && color='31'
|
|
test $1 -gt 125 && color='31;1'
|
|
test $1 -gt 150 && color='91'
|
|
test $1 -gt 200 && color='91;1'
|
|
}
|
|
|
|
#
|
|
# compute the effort of the given <path ...>
|
|
#
|
|
|
|
effort() {
|
|
path=$1
|
|
local commit_dates
|
|
commit_dates=`dates "$path"`
|
|
[ $? -gt 0 ] && exit 255
|
|
|
|
# Ensure it's not just an empty line
|
|
if [ -z "`head -c 1 <<<$(echo $commit_dates)`" ]
|
|
then
|
|
exit 0
|
|
fi
|
|
|
|
commits=`wc -l <<<"$(echo "$commit_dates")"`
|
|
color='90'
|
|
|
|
# ignore <= --above
|
|
test $commits -le $above && exit 0
|
|
|
|
# commits
|
|
color_for $(( $commits - $above ))
|
|
len=${#path}
|
|
dot="."
|
|
f_dot="$path"
|
|
i=0 ; while test $i -lt $((45-$len)) ; do
|
|
f_dot=$f_dot$dot
|
|
i=$(($i+1))
|
|
done
|
|
|
|
msg=$(printf " \033[${color}m%s %-10d" "$f_dot" $commits)
|
|
|
|
# active days
|
|
active=`active_days "$commit_dates"`
|
|
color_for $(( $active - $above ))
|
|
msg="$msg $(printf "\033[${color}m %d\033[0m\n" $active)"
|
|
echo "$msg"
|
|
}
|
|
|
|
#
|
|
# print heading
|
|
#
|
|
|
|
heading() {
|
|
echo
|
|
printf " %-45s %-10s %s\n" 'path' 'commits' 'active days'
|
|
echo
|
|
}
|
|
|
|
#
|
|
# output sorted results
|
|
#
|
|
|
|
sort_effort() {
|
|
clear
|
|
echo
|
|
heading
|
|
< $tmp sort -rn -k 2
|
|
}
|
|
|
|
above_index=0
|
|
has_above=false
|
|
next_is_above=false
|
|
num_paths=0
|
|
|
|
# Some implementations of `seq` gives "1\n0" for seq 0
|
|
if [ $# -gt 0 ] ; then
|
|
for i in `seq ${#@}`
|
|
do
|
|
cur="${!i}"
|
|
|
|
if "$next_is_above" ; then
|
|
above="$cur"
|
|
next_is_above=false
|
|
continue
|
|
fi
|
|
|
|
case "$cur" in
|
|
--above)
|
|
if "$has_above" ; then
|
|
echo "error: --above can only be specified one time" 1>&2
|
|
exit 1
|
|
fi
|
|
next_is_above=true
|
|
has_above=true
|
|
above_index=$(( i - 1 ))
|
|
;;
|
|
--*)
|
|
;;
|
|
*)
|
|
num_paths=$(( num_paths + 1 ))
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
|
|
# Exit if above-value is not an int
|
|
if [ -z "${above##*[!0-9]*}" ] ; then
|
|
echo "error: argument to --above was not an integer" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
args_before_above=`printf " %q" "${@:1:$above_index}"`
|
|
|
|
num_args=$(( i - num_paths ))
|
|
if $has_above ; then offset=2 ; else offset=0 ; fi
|
|
from=$(( 1 + above_index + offset ))
|
|
len=$(( num_args - $(( above_index + offset)) ))
|
|
args_after_above=`printf " %q" "${@:$from:$len}"`
|
|
|
|
args_to_git_log="${args_before_above#\ \'\'}${args_after_above#\ \'\'}"
|
|
|
|
shift $num_args
|
|
|
|
export args_to_git_log
|
|
|
|
# [path ...]
|
|
|
|
declare -a paths=()
|
|
if test $# -ge 1; then
|
|
paths=("$@")
|
|
else
|
|
save_ifs=$IFS
|
|
IFS=`echo -en "\n\b"`
|
|
paths=(`git ls-files`)
|
|
IFS=$safe_ifs
|
|
unset save_ifs
|
|
fi
|
|
|
|
# hide cursor
|
|
|
|
hide_cursor
|
|
trap show_cursor_and_cleanup INT
|
|
|
|
# export functions so subshells can call them
|
|
export -f effort
|
|
export -f color_for
|
|
export -f active_days
|
|
export -f dates
|
|
export above
|
|
export log_args
|
|
|
|
|
|
bash_params=
|
|
# If bash exits sucessfully with --import-functions,
|
|
# then we need to pass it (FreeBSD probably)
|
|
bash --import-functions -c ":" 1>/dev/null 2>&1
|
|
if [ $? -eq 0 ] ; then
|
|
bash_params="--import-functions"
|
|
fi
|
|
|
|
heading
|
|
# send paths to effort
|
|
printf "%s\0" "${paths[@]}" | xargs -0 -n 1 -P 4 -I % bash $bash_params -c "effort \"%\"" | tee $tmp
|
|
|
|
# if more than one path, sort and print
|
|
test "$(wc -l $tmp | awk '{print $1}')" -gt 1 && sort_effort
|
|
echo
|
|
|
|
show_cursor_and_cleanup
|