blob: ceb58a85338226799106a7c04120bf91f1b5aa0e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#!/bin/sh
# Git Trach, track the state of multiple repos from a single file.
# dependencies:
# - git
# - $EDITOR: -e
repos=$HOME/sync/share/git-track.txt
# prevent file not found errors
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 '/^*/!d;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) f_command=1; f_arg="$OPTARG" ;;
s) f_status=1 ;;
l) cat "$repos" ;;
e) $EDITOR "$repos" ;;
f) repos="$OPTARG" ;;
h) help ;;
:) >&2 printf -- '-%s requires argument\n' "$OPTARG"; exit 1 ;;
?) >&2 printf -- 'Invalid option: -%s\n' "$OPTARG"; exit 1 ;;
esac
done
# commands hereafter must happen in order
[ "$(wc -l < "$repos")" -gt 0 ] || exit 0
if [ "$f_command" ]
then
repos_cmd "$f_arg"
fi
if [ "$f_status" ]
then
status
fi
# eval "herbe $(status | sed 's/"/\"/g;s/.*/"&"/' | tr '\n' ' ')"
|