-
Notifications
You must be signed in to change notification settings - Fork 0
/
git-bunch
275 lines (211 loc) · 5.65 KB
/
git-bunch
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#!/usr/bin/env bash
# =========================================================================
ME="$( basename "$0" )"
GITCONFIG=~/.gitconfig
# =========================================================================
print_usage() {
cat - <<USAGE
Usage:
git-bunch -h | --help
git-bunch -l | --list
git-bunch NAME
git-bunch NAME ls
git-bunch NAME config -l | --list
git-bunch NAME config name value
git-bunch NAME config --unset name
git-bunch NAME [--] COMMAND [OPTIONS]
USAGE
exit
}
print_help() {
cat - <<HELP
NAME
git-bunch - manage bunch directories which contain git repositories
SYNOPSIS
git-bunch -h | --help
git-bunch -l | --list
git-bunch NAME
git-bunch NAME ls
git-bunch NAME config -l | --list
git-bunch NAME config name value
git-bunch NAME config --unset name
git-bunch NAME [--] COMMAND [OPTIONS]
DESCRIPTION
git-bunch or bunch is a term to refer to a directory which is supposed
to be a container for other directories being containers of git
repositories.
If you keep your repos under some directory...
If you need to execute (sometimes, not so often) some particular git
commands over these repos...
... this script for you!
CONFIGURE BUNCHES
The script assumes that all bunches and their settings are stored
globally in the "~/.gitconfig" file.
You can declare more than one bunch. Each directory containing git
repositories can be called a bunch. Each bunch has a name, path and
options. The name is used to refer the bunch. The path is used to locate
the bunch. Options are used to tune the bunch. There is no restriction
to declare more than one name per a bunch. In this case both names are
synonyms, but they could have different options.
CONFIGURATION FILE
Git bunch is per-user configuration only. That means that all bunches
are configured via user's "~/.gitconfig". The syntax is almost the same
as for "gitconfig".
Syntax
In this example two bunches called "one" and "two" are created and setup
to particular directories:
[bunch "one"]
path = /var/git/bunch-1
stoponerror = no
[bunch "two"]
path = /var/git/bunch-2
stoponerror = no
Values
pathname
A pathname follows Bash syntax.
boolean
The following words stand for true and false:
true
Boolean true literals are "yes", "on", "true", 1.
In contrast to git itself, the single name (without "= value")
is treated as false.
false
Boolean false literals are "no", "off", "false", 0 and the emtpy
string.
Variables
The following variables are supported for bunches:
"path" (string)
The only mandatory variable defining the bunch location.
"stoponerror" (boolean)
True means stop immediately if a command exits with a non-zero
status. Defaults to false (i.e., "set +o errexit").
REQUIREMENTS
"bash" 4.4+
"sed"
"ls"
SEE ALSO
Something similar...
https://metacpan.org/pod/Git::Bunch
Something very similar, implemented in pure Perl.
https://github.com/salewski/ads-github-tools
That sounds promising: *The project providing command line tools for
managing a large number of GitHub repositories...*.
COPYRIGHT
Copyright (c) 2020 Ildar Shaimordanov. MIT License.
HELP
exit
}
# =========================================================================
main() {
case "$1" in
'' ) print_usage ;;
-h | --help ) print_help ;;
-l | --list ) bunch_list ;;
* ) bunch_exec "$@" ;;
esac
}
# =========================================================================
bunch_list() {
sed -n 's/^\[bunch "\([^"]*\)"\].*/\1/p' "$GITCONFIG"
}
bunch_configure() {
case "$1" in
-l | --list )
sed -n "/./ s/^/bunch.$BUNCH_NAME./p" <<<"$BUNCH_RAW"
;;
--unset )
git config --global --unset "bunch.$BUNCH_NAME.$2"
;;
path | stoponerror )
git config --global "bunch.$BUNCH_NAME.$1" "$2"
;;
* )
print_usage
;;
esac
}
bunch_raw_config() {
sed -n '
/^\[bunch "'"$1"'"\]/,/^\[/ {
/^\[/d;
s/^\s*//;
s/\s*=\s*/=/;
s/\s*$//;
p;
}
' "$GITCONFIG"
}
bunch_exec() {
BUNCH_NAME="$1"
BUNCH_ERREXIT="+o"
unset BUNCH_PATH BUNCH_STOP
# Read raw bunch config
BUNCH_RAW="$( bunch_raw_config "$BUNCH_NAME" )"
# Parse the bunch
while IFS="=" read -r k v
do
case "$k" in
path )
BUNCH_PATH="$v"
;;
stoponerror )
BUNCH_STOP="$v"
case "$v" in
0 | no | off | false | '' ) BUNCH_ERREXIT="+o" ;;
1 | yes | on | true ) BUNCH_ERREXIT="-o" ;;
esac
;;
esac
done <<<"$BUNCH_RAW"
# Print the bunch path
# git-bunch NAME
shift
[ $# -gt 0 ] || {
echo "$BUNCH_PATH"
return
}
# Configure the bunch
# git-bunch NAME config ...
if [ "$1" = "config" ]
then
shift
bunch_configure "$@"
return
fi
[ -d "$BUNCH_PATH" ] || die "Not bunch directory: $BUNCH_PATH"
# List the bunch
# git-bunch NAME ls
if [ "$1" = "ls" ]
then
ls "$BUNCH_PATH" --color=tty
return
fi
# Work through the bunch and execute the git command
# git-bunch NAME ...
[ "$1" = "--" ] && shift
set "$BUNCH_ERREXIT" errexit
for f in "$BUNCH_PATH"/*
do
[ -d "$f" ] || continue
(
set "$BUNCH_ERREXIT" errexit
builtin cd "$f"
git "$@"
)
done
}
# =========================================================================
catecho() {
[ $# -eq 0 ] && cat - || echo "$@"
}
warn() {
catecho "$@" >&2
}
die() {
warn "$@"
exit 1
}
# =========================================================================
main "$@"
# =========================================================================
# EOF