Created
September 3, 2025 20:53
-
-
Save Cosmo/ce00bb601fe8003067ea4784b10f88ae to your computer and use it in GitHub Desktop.
git-logger with macOS Support, Original: https://gitlab.com/CrazyBaboon/git-logger/-/blob/master/git-logger.sh?ref_type=heads
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -euo pipefail | |
# git-logger is free software and is licensed under the GNU GPLv2+. | |
# (C) 2018-2019 Nuno Ferreira and contributors | |
# Contributors: James Brown, | |
# qZeta | |
# boweeb1011 | |
# Mathias Weber | |
# macOS-compatible tweaks by Devran Cosmo Uenal and ChatGPT (2025) | |
# ------- setup / cleanup ------- | |
tmp_file="$(mktemp -t gitlogger1)" | |
tmp_file_2="$(mktemp -t gitlogger2)" | |
on_exit() { | |
status=$? | |
[[ -f "$tmp_file" ]] && rm -f "$tmp_file" | |
[[ -f "$tmp_file_2" ]] && rm -f "$tmp_file_2" | |
exit $status | |
} | |
trap on_exit EXIT SIGINT SIGTERM | |
# Force predictable weekday abbreviations (Mon..Sun) | |
export LC_ALL=C | |
# ------- constants ------- | |
# Fixed order avoids GNU/BSD date differences | |
days=' Mon Tue Wed Thu Fri Sat Sun ' | |
hours='01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 00' | |
colors=(19 21 23 25 27 30 36 39 41 49 51 154 178 172 166 202 196) | |
max_hourly_commit=0 | |
total_commits=0 | |
total_daily_commits=0 | |
# ------- collect data ------- | |
if [ -d ".git" ]; then | |
# %a = weekday abbrev, %H = hour (00..23) | |
git log --pretty=format:"%ad" --date=local --date=format:'%a %H' > "$tmp_file" | |
elif [ -d ".hg" ]; then | |
# Mercurial on macOS: parse ISO dates via Python for portability | |
# Outputs "Mon 13" style lines in C-locale | |
hg log --template "{date|isodate}\n" | python3 - "$tmp_file" <<'PY' | |
import sys, datetime, locale | |
locale.setlocale(locale.LC_ALL, 'C') | |
for line in sys.stdin: | |
line=line.strip() | |
if not line: continue | |
# Accept e.g. 2021-03-22 14:55 +0100 or 2021-03-22T14:55:00+01:00 | |
for fmt in ("%Y-%m-%d %H:%M %z","%Y-%m-%d %H:%M:%S %z","%Y-%m-%dT%H:%M %z","%Y-%m-%dT%H:%M:%S%z","%Y-%m-%dT%H:%M:%S%z"): | |
try: | |
dt=datetime.datetime.strptime(line, fmt) | |
break | |
except ValueError: | |
dt=None | |
if dt is None: | |
continue | |
print(dt.strftime("%a %H")) | |
PY | |
else | |
echo "Could not find a git or mercurial repository" >&2 | |
exit 1 | |
fi | |
# ------- functions ------- | |
find_max() { | |
local day hour number_hourly_commits | |
for day in $days; do | |
grep -F "$day" "$tmp_file" > "$tmp_file_2" || true | |
for hour in $hours; do | |
number_hourly_commits=$(grep -c -F " $hour" "$tmp_file_2" || true) | |
if [ "$number_hourly_commits" -gt "$max_hourly_commit" ]; then | |
max_hourly_commit="$number_hourly_commits" | |
fi | |
done | |
done | |
} | |
no_color=$(tput sgr0 2>/dev/null || echo "") | |
display_256() { | |
local day hour number_hourly_commits idx color | |
printf "\n%s\n" " ****** Punch card for $(basename "$PWD") ****** " | |
printf "\n%s\n%s" " ------------------------------------time of day (hours)-----------------------------------------" " " | |
for hour in $hours; do printf "%s" "| $hour"; done | |
printf "| Total" | |
for day in $days; do | |
printf "\n%s" " $day -" | |
grep -F "$day" "$tmp_file" > "$tmp_file_2" || true | |
for hour in $hours; do | |
number_hourly_commits=$(grep -c -F " $hour" "$tmp_file_2" || true) | |
# Guard against divide-by-zero and clamp index 0..15 | |
if [ "$max_hourly_commit" -gt 0 ]; then | |
idx=$(( 16*number_hourly_commits / max_hourly_commit )) | |
else | |
idx=0 | |
fi | |
[ "$idx" -gt 15 ] && idx=15 | |
color=$(tput setab "${colors[$idx]}" 2>/dev/null || echo "") | |
if [ "$number_hourly_commits" -eq 0 ]; then | |
printf "%s" " $number_hourly_commits " | |
elif [ "$number_hourly_commits" -lt 1000 ]; then | |
printf "%s%4s%s" "${color}$(tput setaf 0 2>/dev/null)" "$number_hourly_commits" "${no_color}" | |
else | |
printf "%s%4sk%s" "${color}$(tput setaf 0 2>/dev/null)" "$((number_hourly_commits/1000))" "${no_color}" | |
fi | |
(( total_commits=total_commits+number_hourly_commits )) | |
(( total_daily_commits=total_daily_commits+number_hourly_commits )) | |
done | |
printf "%s" "| $total_daily_commits " | |
total_daily_commits=0 | |
done | |
printf "\n\n%s\n\n" "total_commits = $total_commits" | |
} | |
display_8() { | |
local day hour number_hourly_commits | |
for day in $days; do | |
printf "\n%s" " $day -" | |
grep -F "$day" "$tmp_file" > "$tmp_file_2" || true | |
for hour in $hours; do | |
number_hourly_commits=$(grep -c -F " $hour" "$tmp_file_2" || true) | |
if [ "$number_hourly_commits" -eq 0 ]; then | |
printf "%s" " $number_hourly_commits " | |
elif [ "$number_hourly_commits" -lt 10 ]; then | |
printf "%4s" "$(tput setab 2 2>/dev/null) $(tput setaf 0 2>/dev/null) $number_hourly_commits $(tput sgr0 2>/dev/null)" | |
elif [ "$number_hourly_commits" -lt 100 ]; then | |
printf "%4s" "$(tput setab 3 2>/dev/null) $(tput setaf 0 2>/dev/null) $number_hourly_commits $(tput sgr0 2>/dev/null)" | |
else | |
printf "%4s" "$(tput setab 1 2>/dev/null) $(tput setaf 0 2>/dev/null) $number_hourly_commits $(tput sgr0 2>/dev/null)" | |
fi | |
(( total_commits=total_commits+number_hourly_commits )) | |
(( total_daily_commits=total_daily_commits+number_hourly_commits )) | |
done | |
printf "%s" "| $total_daily_commits " | |
total_daily_commits=0 | |
done | |
printf "\n\n%s\n\n" "Total number of commits is $total_commits" | |
} | |
# ------- render ------- | |
colors_supported=$(tput colors 2>/dev/null || echo 0) | |
if [ "${colors_supported:-0}" -ge 256 ]; then | |
find_max | |
display_256 | |
else | |
display_8 | |
printf "\n%s\n\n" "####### 8 color display detected. For best results try 256 color display #######" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment