diff options
author | Ben Sima <ben@bsima.me> | 2022-11-15 09:50:43 -0500 |
---|---|---|
committer | Ben Sima <ben@bsima.me> | 2022-11-15 09:50:43 -0500 |
commit | 8723010e43c7eb10d047692f9ae6d613a0d629ef (patch) | |
tree | a575b38573e9b69b0eb8d9ab0f030a10530783f4 | |
parent | 3f9ad400be3988244586cfae0c2181181b18c41d (diff) |
add git activity script
-rwxr-xr-x | git-activity | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/git-activity b/git-activity new file mode 100755 index 0000000..45135a4 --- /dev/null +++ b/git-activity @@ -0,0 +1,139 @@ +#!/usr/bin/env bash + +set -o nounset + +function usage() { + cat <<EOF +Usage: $0 [-h] [-n] [-s style] + +Display an activity graph (like the contribution graph on GitHub) for the +current git repository and branch + +Available options: + +-h, --help Print this help and exit +-n, --no-space Remove spaces between week columns +-s, --style Sets style of the graph: square (default), block, or plus +EOF +} + +# Parse options +space=" " +style=square +while [[ $# -gt 0 ]]; do + case "$1" in + -s|--style) + style="$2" + shift 2 + ;; + -n|--no-space) space="" ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unexpected option ${1}" >&2 + usage + exit 1 + ;; + esac + shift +done + +# Style argument +case "${style}" in +square) + char_full="■" + char_void="${char_full}" + ;; +block) + char_full="█" + char_void="${char_full}" + ;; +plus) + char_full="✚" + char_void="•" + ;; +*) + echo "error: style '${style}' not recognized (square block plus)" >&2; + exit 1;; +esac + +# Use GNU date if available +if date --version >/dev/null 2>&1 ; then + function _date { date "$@" ;} +elif gdate >/dev/null 2>&1 ; then + function _date { gdate "$@" ;} +else + echo "You need to install coreutils to run this script (command 'gdate' is not available)."; + exit 1; +fi + +# Process commits per day +declare -A commits_per_day +commits_max=0 +since=$(_date -d "$(_date -d '1 year ago + 1 day' +"%F -%u day")" +"%s") +while read -r commits_n commits_date; do + (( commits_n > commits_max )) && commits_max=$commits_n + date_diff=$(( ($(_date --date="${commits_date} 13:00 UTC" "+%s") - since) / (60*60*24) )) + commits_per_day["${date_diff}"]=$commits_n +done <<< $(git log --since="${since}" --date=short --pretty=format:'%ad' | uniq -c) + +# Print name of months +current_month=$(_date "+%b") +limit_columns=$(( 2 - ${#space} )) +weeks_in_month=$(( limit_columns + 1 )) +printf "\e[m " +for week_n in $(seq 0 52); do + month_week=$(_date -d "1 year ago + ${week_n} weeks" "+%b") + if [[ "${current_month}" != "${month_week}" ]]; then + current_month=$month_week + weeks_in_month=0 + printf "%-3s%s" "${current_month:0:3}" "$space" + elif [[ $weeks_in_month -gt $limit_columns ]]; then + printf " %s" "$space" + fi + weeks_in_month=$(( weeks_in_month + 1 )) +done +printf "\n" + +# Print activity +last_day=$(( ($(_date "+%s") - since) / (60*60*24) )) +name_of_days=("" "Mon" "" "Wed" "" "Fri" "" "") +for day_n in $(seq 0 6); do + printf '\e[m%-4s' "${name_of_days[day_n]}" + for week_n in $(seq 0 52); do + key=$(( week_n * 7 + day_n )) + if [[ -v commits_per_day["${key}"] ]]; then + value=$(( ${commits_per_day["${key}"]}00 / commits_max)) + if (( value <= 25 )); then + # Low activity + printf "\x1b[38;5;22m%s%s" "$char_full" "$space" + elif (( value <= 50 )); then + # Mid-low activity + printf "\x1b[38;5;28m%s%s" "$char_full" "$space" + elif (( value <= 75 )); then + # Mid-high activity + printf "\x1b[38;5;34m%s%s" "$char_full" "$space" + else + # High activity + printf "\x1b[38;5;40m%s%s" "$char_full" "$space" + fi + elif [ $key -lt $last_day ]; then + # No activity + printf "\x1b[38;5;250m%s%s" "$char_void" "$space" + fi + done + printf "\n" +done +printf "\n" + +# Print legend +printf "\e[m Less " +printf "\x1b[38;5;250m%s " "$char_void" +printf "\x1b[38;5;22m%s " "$char_full" +printf "\x1b[38;5;28m%s " "$char_full" +printf "\x1b[38;5;34m%s " "$char_full" +printf "\x1b[38;5;40m%s " "$char_full" +printf "\e[mMore" +printf "\n" |