summaryrefslogtreecommitdiff
path: root/bin/common/gt
diff options
context:
space:
mode:
authorRaymaekers Luca <raymaekers.luca@gmail.com>2024-06-20 12:04:39 +0200
committerRaymaekers Luca <raymaekers.luca@gmail.com>2024-06-20 12:04:39 +0200
commite5eb7f627f4632dab17e0cc0f727cb9b1f70d8a1 (patch)
tree75c7f8560539303e4a5c1f93241a1e8912bad4cc /bin/common/gt
parent05e1216b45340702f82a4946002015a05cebe9b1 (diff)
parent947f7df73f16981f170265a64a964142fc617023 (diff)
Merge branch 'main' of db:dotfiles
Diffstat (limited to 'bin/common/gt')
-rwxr-xr-xbin/common/gt111
1 files changed, 111 insertions, 0 deletions
diff --git a/bin/common/gt b/bin/common/gt
new file mode 100755
index 0000000..bdbd00f
--- /dev/null
+++ b/bin/common/gt
@@ -0,0 +1,111 @@
+#!/bin/sh
+
+# Git Trach, track the state of multiple repos from a single file.
+
+# dependencies:
+# - git
+# - $EDITOR: -e
+# - herbe (optional): -s
+
+repos="${XDG_DATA_HOME:-$HOME}"/git-track.txt
+touch "$repos"
+
+help() {
+ >&2 cat <<EOF
+usage: gt [OPTION]
+-a PATH add repo
+-s update and show status of each repo
+-c COMMAND run 'git COMMAND' in each repo
+-h show this help
+-l list repos
+-e edit repos in $EDITOR
+EOF
+}
+
+# fetch repository prettily, outputs nothing if failed
+fetch() {
+ # fetch with one-line printing of progress
+ git fetch --progress 2>/dev/null | while read -r line
+ # \r\033[0K : clear current line
+ do >&2 printf '\r\033[0K%s' "$line"
+ done
+}
+
+# Print repositories prettily
+# This function function prints animations (eg. clearing the line)
+# to stderr and the final status line is outputted to stdout.
+status() {
+ while read -r repo
+ do
+ repo_pretty="$(printf '%s' "$repo" | sed "s@$HOME@~@" )"
+
+ # absolute path
+ cd "$repo"
+
+ # replace line with status
+ >&2 printf '\r\033[0K'
+
+ status="$(git status --porcelain 2> /dev/null | awk '{print $1}' | uniq | tr -d '\n')"
+ remote="$(git branch -v 2>/dev/null | sed 's/ahead/↑/;s/behind/↓/;s/[^↓↑]*//g')"
+
+ printf '%s %s %s\n' "$repo_pretty" "$status" "$remote"
+ done < "$repos"
+}
+
+# run git command in each repo
+# $1: command
+repos_cmd() {
+ while read -r repo
+ do
+ repo_pretty="$(printf '%s' "$repo" | sed "s@$HOME@~@" )"
+ printf ''\''%s'\'' in %s' "$1" "$repo_pretty"
+ (
+ cd "$repo"
+ git "$1" > /dev/null 2>&1
+ [ $? -gt 0 ] && s="x" || s="o"
+ printf '\r\033[0K%s: %s\n' "$repo_pretty" "$s"
+ )
+ done < "$repos"
+}
+
+# no options
+if [ -z "$1" ]
+then
+ help
+ exit 1
+fi
+
+while getopts ":a:c:f:lshe" opt
+do
+ case "$opt" in
+ a)
+ cd "$OPTARG" || exit 1
+ r="$(git rev-parse --show-toplevel)"
+ [ "$r" ] || exit 2
+
+ if grep "$r" "$repos" > /dev/null 2>&1
+ then
+ >&2 printf 'added already.\n'
+ exit 2
+ fi
+
+ printf '%s\n' "$r" >> "$repos"
+
+ >&2 printf 'added.\n' ;;
+ c) repos_cmd "$OPTARG" ;;
+ s) status=1 ;;
+ l) cat "$repos" ;;
+ e) $EDITOR "$repos" ;;
+ f) repos="$OPTARG" ;;
+ T) help ;;
+ :) >&2 printf -- '-%s requires argument\n' "$OPTARG"; exit 1 ;;
+ ?) >&2 printf -- 'Invalid option: -%s\n' "$OPTARG"; exit 1 ;;
+ esac
+done
+
+if [ "$status" ]
+then
+ status
+ which herbe > /dev/null 2>&1 &&
+ eval "herbe $(status | sed 's/"/\"/g;s/.*/"&"/' | tr '\n' ' ')" &
+fi