forked from fabbione/fedgithook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cluster-update
344 lines (305 loc) · 8.48 KB
/
cluster-update
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
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
#!/bin/bash
set -e
# cmd line
cmd="$0"
refname="$1"
oldrev="$2"
newrev="$3"
sanity_checks() {
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $cmd <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "Usage: $cmd <ref> <oldrev> <newrev>" >&2
exit 1
fi
}
get_defaults() {
# Check if there are frozen branches
frozenbranchesfilter="no"
[ -f $GIT_DIR/frozenbranches ] && frozenbranchesfilter="yes"
# Check for protected branches
protectedbranchesfilter="no"
[ -f $GIT_DIR/protectedbranches ] && protectedbranchesfilter="yes"
# Check if we should enable or not tag filter protection
protectedtagfilter="no"
[ -f $GIT_DIR/protectedtagfilter ] && protectedtagfilter="yes"
# Check if there are branches we want to mail (private branches can be quiet)
mailbranchesfilter="no"
[ -f $GIT_DIR/mailbranches ] && mailbranchesfilter="yes"
[ -f $GIT_DIR/commit-list ] && recipients=$(cat $GIT_DIR/commit-list)
# XXX remember to change default recipients
[ -n "$recipients" ] || [email protected]
# Don't add shortmodule name to Subject in output email
skip_shortmodule=""
[ -f $GIT_DIR/skip_shortmodule ] && skip_shortmodule=yes
projectdesc=$(sed -ne '1p' "$GIT_DIR/description")
if expr "$projectdesc" : "Unnamed repository.*$" >/dev/null; then
projectdesc="UNNAMED PROJECT"
fi
if [ -z "$mailer" ]; then
mailer="/usr/bin/send-unicode-email.py"
fi
}
# this sets change_type and rev_type vars to something we can use
get_commit_type() {
if expr "$oldrev" : '0*$' >/dev/null; then
change_type="create"
else
if expr "$newrev" : '0*$' >/dev/null; then
change_type="delete"
else
change_type="update"
fi
fi
case "$change_type" in
create|update)
rev_type="$(git cat-file -t $newrev 2> /dev/null)"
;;
delete)
rev_type="delete"
;;
esac
}
# set very_short_name, short_refname and refname_type.
# very_short_name is handy for branch filtering.
get_short_refname() {
very_short_name="$(echo $refname | awk -F "/" '{print $NF}')"
case "$refname" in
refs/tags/*)
short_refname=${refname##refs/tags/}
;;
refs/heads/*)
short_refname=${refname##refs/heads}
;;
refs/remotes/*)
short_refname=${refname##refs/remotes/}
;;
esac
case "$refname","$rev_type" in
refs/tags/*,commit|refs/tags/*,delete)
# un-annotated tag
refname_type="tag"
;;
refs/tags/*,tag)
# annotated tag
refname_type="annotated tag"
;;
refs/heads/*,commit|refs/heads/*,delete)
# branch
refname_type="branch"
;;
refs/remotes/*,commit|refs/remotes/*,delete)
# tracking branch
refname_type="tracking branch"
;;
esac
}
filter_frozen_branches() {
if [ "$frozenbranchesfilter" = "yes" ]; then
if grep -q ^${very_short_name}$ $GIT_DIR/frozenbranches; then
echo "*** $very_short_name branch is frozen and cannot be changed" >&2
exit 1
fi
fi
}
# this policy filter makes sure that selected branches cannot be deleted
# and that tags cannot be removed
filter_delete_type() {
case "$refname","$change_type" in
refs/tags/*,delete)
if [ "$protectedtagfilter" = "yes" ]; then
# we don't allow tag removal
echo "*** Deleting a tag is not allowed in this repository" >&2
exit 1
fi
;;
refs/heads/*,delete|refs/remotes/*,delete)
# delete branch
if [ "$protectedbranchesfilter" = "yes" ]; then
if grep -q ^${very_short_name}$ $GIT_DIR/protectedbranches; then
echo "*** $very_short_name branch cannot be deleted" >&2
exit 1
fi
fi
;;
esac
}
# tell us if we should mail about a certain branch or not
filter_mail_branches() {
if [ "$refname_type" = "branch" ] || [ "$refname_type" = "tracking branch" ]; then
if [ "$mailbranchesfilter" = "yes" ]; then
if ! grep -q ^${very_short_name}$ $GIT_DIR/mailbranches; then
# no mail for this branch. We exit clean, it's not a failure
exit 0
fi
fi
fi
}
# generate_email_* functions look aweful but it is only a lot of
# escaping to format the emails nicely.
generate_email_branch_commit() {
base=$(git-merge-base "$oldrev" "$newrev")
commits=$(git-rev-list --reverse "$newrev" "^$base")
for i in $commits; do
git show --patch-with-stat --pretty=format:"\
\
Subject: ${shortmodule}$very_short_name - %s%n\
To: $recipient%n\
X-Project: $projectdesc%n\
X-Git-Module: $module%n\
X-Git-Refname: $refname%n\
X-Git-Reftype: $refname_type%n\
X-Git-Oldrev: %P%n\
X-Git-Newrev: %H%n\
%n\
Gitweb: http://git.fedorahosted.org/git/?p=$module;a=commitdiff;h=%H%n\
Commit: %H%n\
Parent: %P%n\
Author: %an <%ae>%n\
AuthorDate: %ad%n\
Committer: %cn <%ce>%n\
CommitterDate: %cd%n\
%n%s%n%n%b" \
$i | $mailer $recipient
# try to serialize outgoing emails without flooding when pushing
# lots of commits at once
sleep 2
done
}
generate_email_delete() {
(echo -e "\
Subject: ${shortmodule}$very_short_name $refname_type - deleted\n\
To: $recipient\n\
X-Project: $projectdesc\n\
X-Git-Module: $module\n\
X-Git-Refname: $refname\n\
X-Git-Reftype: $refname_type\n\
X-Git-Oldrev: $oldrev
X-Git-Newrev: $newrev\n\
\n\
$refname_type: $very_short_name - deleted with refnum:\n";
git show -s --pretty=oneline $oldrev) | $mailer $recipient
}
generate_email_atag() {
taginfo="$(git cat-file tag $newrev)"
eval $(echo "$taginfo" | sed -n '1s/ /=/p')
eval $(echo "$taginfo" | sed -n '2s/ /=/p')
eval $(echo "$taginfo" | sed -n '3s/ /=/p')
tagger=$(echo "$taginfo" | sed -n '4s/tagger \([^>]*>\)[^0-9]*\([0-9]*\).*/\1/p')
ts=$(echo "$taginfo" | sed -n '4s/tagger \([^>]*>\)[^0-9]*\([0-9]*\).*/\2/p')
date=$(date --date="1970-01-01 00:00:00 $ts seconds" +"%F %R %z")
(echo -e "\
Subject: ${shortmodule}$very_short_name $refname_type has been ${change_type}d\n\
To: $recipient\n\
X-Project: $projectdesc\n\
X-Git-Module: $module\n\
X-Git-Refname: $refname\n\
X-Git-Reftype: $refname_type\n\
X-Git-Oldrev: $oldrev
X-Git-Newrev: $newrev\n\
\n\
Gitweb: http://git.fedorahosted.org/git/?p=$module;a=commitdiff;h=$newrev\n\
Commit: $newrev\n\
Parent: $oldrev\n\
Author: $tagger\n\
AuthorDate: $date\n\
Committer: $tagger\n\
CommitterDate: $date\n\
\n\
$refname_type: $very_short_name has been ${change_type}d
$(if [ $change_type = create ]; then
echo -e "\t at $newrev ($rev_type)\n";
else
echo -e "\t to $newrev ($rev_type)\n\tfrom $oldrev (which is now obsolete)\n";
fi)
tagging $object ($type)\n\
$(if [ $type = commit ]; then
prevtag=$(git describe --abbrev=0 $newrev^ 2>/dev/null);
if [ -n "$prevtag" ]; then
echo " replaces $prevtag";
fi
fi)
$(git cat-file tag $newrev | sed -n '5,$p')
\n\
$(if [ $type = commit ]; then
prevtag=$(git describe --abbrev=0 $newrev^ 2>/dev/null);
if [ -n "$prevtag" ]; then
git rev-list --pretty=short "$prevtag..$newrev" | git shortlog
else
git rev-list --pretty=short $newrev | git shortlog
fi
fi)\
";) | $mailer $recipient
}
generate_email_uatag() {
git show --summary --pretty=format:"\
\
Subject: ${shortmodule}$very_short_name $refname_type has been ${change_type}d%n\
To: $recipient%n\
X-Project: $projectdesc%n\
X-Git-Module: $module%n\
X-Git-Refname: $refname%n\
X-Git-Reftype: $refname_type%n" \
| $mailer $recipient
}
generate_email() {
# common stuff
module=$(basename `readlink -f $GIT_DIR`)
shortmodule=""
[ -z "$skip_shortmodule" ] && shortmodule="${module%%.git}: "
# like all the other scripts around we need to generate emails
# according to the type of chance. No kidding.. it's a mess of
# combinations
case "$refname","$rev_type" in
refs/tags/*,commit)
# un-annotated tag
generate_email_uatag
;;
refs/tags/*,tag)
# annotated tag
generate_email_atag
;;
refs/tags/*,delete)
# delete tag
generate_email_delete
;;
refs/heads/*,commit)
# branch
generate_email_branch_commit
;;
refs/heads/*,delete)
# delete branch
generate_email_delete
;;
refs/remotes/*,commit)
# tracking branch
echo "*** Push-update of tracking branch, $refname" >&2
echo "*** - no email generated." >&2
# This can be made quiet.. ???
;;
refs/remotes/*,delete)
# delete tracking branch
generate_email_delete
;;
esac
}
### main
sanity_checks
# get some info around
get_defaults
get_commit_type
get_short_refname
# apply filters
filter_frozen_branches
filter_delete_type
filter_mail_branches
# if we are here we need to send an email.. go figure.. :)
set +e # we don't want to kill a commit if we fail to send an email
for recipient in $recipients; do
generate_email
done
exit 0