summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2022-11-15 09:50:43 -0500
committerBen Sima <ben@bsima.me>2022-11-15 09:50:43 -0500
commit8723010e43c7eb10d047692f9ae6d613a0d629ef (patch)
treea575b38573e9b69b0eb8d9ab0f030a10530783f4
parent3f9ad400be3988244586cfae0c2181181b18c41d (diff)
add git activity script
-rwxr-xr-xgit-activity139
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"