git-apply: Do not free the wrong buffer when we convert the data for writeout
[git/gitweb.git] / templates / hooks--update
blob1a60773890cfcbaa5727636e6eda8280feb23bc1
1 #!/bin/sh
3 # An example hook script to mail out commit update information.
4 # It can also blocks tags that aren't annotated.
5 # Called by git-receive-pack with arguments: refname sha1-old sha1-new
7 # To enable this hook, make this file executable by "chmod +x update".
9 # Config
10 # ------
11 # hooks.mailinglist
12 # This is the list that all pushes will go to; leave it blank to not send
13 # emails frequently. The log email will list every log entry in full between
14 # the old ref value and the new ref value.
15 # hooks.announcelist
16 # This is the list that all pushes of annotated tags will go to. Leave it
17 # blank to just use the mailinglist field. The announce emails list the
18 # short log summary of the changes since the last annotated tag
19 # hooks.allowunannotated
20 # This boolean sets whether unannotated tags will be allowed into the
21 # repository. By default they won't be.
23 # Notes
24 # -----
25 # All emails have their subjects prefixed with "[SCM]" to aid filtering.
26 # All emails include the headers "X-Git-Refname", "X-Git-Oldrev",
27 # "X-Git-Newrev", and "X-Git-Reftype" to enable fine tuned filtering and info.
29 # --- Constants
30 EMAILPREFIX="[SCM] "
31 LOGBEGIN="- Log -----------------------------------------------------------------"
32 LOGEND="-----------------------------------------------------------------------"
33 DATEFORMAT="%F %R %z"
35 # --- Command line
36 refname="$1"
37 oldrev="$2"
38 newrev="$3"
40 # --- Safety check
41 if [ -z "$GIT_DIR" ]; then
42 echo "Don't run this script from the command line." >&2
43 echo " (if you want, you could supply GIT_DIR then run" >&2
44 echo " $0 <ref> <oldrev> <newrev>)" >&2
45 exit 1
48 if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
49 echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
50 exit 1
53 # --- Config
54 projectdesc=$(cat $GIT_DIR/description)
55 recipients=$(git-repo-config hooks.mailinglist)
56 announcerecipients=$(git-repo-config hooks.announcelist)
57 allowunannotated=$(git-repo-config --bool hooks.allowunannotated)
59 # check for no description
60 if [ -z "$projectdesc" -o "$projectdesc" = "Unnamed repository; edit this file to name it for gitweb" ]; then
61 echo "*** Project description file hasn't been set" >&2
62 exit 1
65 # --- Check types
66 newrev_type=$(git-cat-file -t $newrev)
68 case "$refname","$newrev_type" in
69 refs/tags/*,commit)
70 # un-annotated tag
71 refname_type="tag"
72 short_refname=${refname##refs/tags/}
73 if [ "$allowunannotated" != "true" ]; then
74 echo "*** The un-annotated tag, $short_refname is not allowed in this repository" >&2
75 echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
76 exit 1
79 refs/tags/*,tag)
80 # annotated tag
81 refname_type="annotated tag"
82 short_refname=${refname##refs/tags/}
83 # change recipients
84 if [ -n "$announcerecipients" ]; then
85 recipients="$announcerecipients"
88 refs/heads/*,commit)
89 # branch
90 refname_type="branch"
91 short_refname=${refname##refs/heads/}
93 refs/remotes/*,commit)
94 # tracking branch
95 refname_type="tracking branch"
96 short_refname=${refname##refs/remotes/}
97 # Should this even be allowed?
98 echo "*** Push-update of tracking branch, $refname. No email generated." >&2
99 exit 0
102 # Anything else (is there anything else?)
103 echo "*** Update hook: unknown type of update, \"$newrev_type\", to ref $refname" >&2
104 exit 1
106 esac
108 # Check if we've got anyone to send to
109 if [ -z "$recipients" ]; then
110 # If the email isn't sent, then at least give the user some idea of what command
111 # would generate the email at a later date
112 echo "*** No recipients found - no email will be sent, but the push will continue" >&2
113 echo "*** for $0 $1 $2 $3" >&2
114 exit 0
117 # --- Email parameters
118 committer=$(git show --pretty=full -s $newrev | grep "^Commit: " | sed -e "s/^Commit: //")
119 describe=$(git describe $newrev 2>/dev/null)
120 if [ -z "$describe" ]; then
121 describe=$newrev
124 # --- Email (all stdout will be the email)
126 # Generate header
127 cat <<-EOF
128 From: $committer
129 To: $recipients
130 Subject: ${EMAILPREFIX}$projectdesc $refname_type, $short_refname now at $describe
131 X-Git-Refname: $refname
132 X-Git-Reftype: $refname_type
133 X-Git-Oldrev: $oldrev
134 X-Git-Newrev: $newrev
136 Hello,
138 This is an automated email from the git hooks/update script, it was
139 generated because a ref change was pushed to the repository.
141 Updating $refname_type, $short_refname,
144 case "$refname_type" in
145 "tracking branch"|branch)
146 if expr "$oldrev" : '0*$' >/dev/null
147 then
148 # If the old reference is "0000..0000" then this is a new branch
149 # and so oldrev is not valid
150 echo " as a new $refname_type"
151 echo " to $newrev ($newrev_type)"
152 echo ""
153 echo $LOGBEGIN
154 # This shows all log entries that are not already covered by
155 # another ref - i.e. commits that are now accessible from this
156 # ref that were previously not accessible
157 git log $newrev --not --all
158 echo $LOGEND
159 else
160 # oldrev is valid
161 oldrev_type=$(git-cat-file -t "$oldrev")
163 # Now the problem is for cases like this:
164 # * --- * --- * --- * (oldrev)
166 # * --- * --- * (newrev)
167 # i.e. there is no guarantee that newrev is a strict subset
168 # of oldrev - (would have required a force, but that's allowed).
169 # So, we can't simply say rev-list $oldrev..$newrev. Instead
170 # we find the common base of the two revs and list from there
171 baserev=$(git-merge-base $oldrev $newrev)
173 # Commit with a parent
174 for rev in $(git-rev-list $newrev --not $baserev --all)
176 revtype=$(git-cat-file -t "$rev")
177 echo " via $rev ($revtype)"
178 done
179 if [ "$baserev" = "$oldrev" ]; then
180 echo " from $oldrev ($oldrev_type)"
181 else
182 echo " based on $baserev"
183 echo " from $oldrev ($oldrev_type)"
184 echo ""
185 echo "This ref update crossed a branch point; i.e. the old rev is not a strict subset"
186 echo "of the new rev. This occurs, when you --force push a change in a situation"
187 echo "like this:"
188 echo ""
189 echo " * -- * -- B -- O -- O -- O ($oldrev)"
190 echo " \\"
191 echo " N -- N -- N ($newrev)"
192 echo ""
193 echo "Therefore, we assume that you've already had alert emails for all of the O"
194 echo "revisions, and now give you all the revisions in the N branch from the common"
195 echo "base, B ($baserev), up to the new revision."
197 echo ""
198 echo $LOGBEGIN
199 git log $newrev --not $baserev --all
200 echo $LOGEND
201 echo ""
202 echo "Diffstat:"
203 git-diff-tree --no-color --stat -M -C --find-copies-harder $baserev..$newrev
206 "annotated tag")
207 # Should we allow changes to annotated tags?
208 if expr "$oldrev" : '0*$' >/dev/null
209 then
210 # If the old reference is "0000..0000" then this is a new atag
211 # and so oldrev is not valid
212 echo " to $newrev ($newrev_type)"
213 else
214 echo " to $newrev ($newrev_type)"
215 echo " from $oldrev"
218 # If this tag succeeds another, then show which tag it replaces
219 prevtag=$(git describe --abbrev=0 $newrev^ 2>/dev/null)
220 if [ -n "$prevtag" ]; then
221 echo " replaces $prevtag"
224 # Read the tag details
225 eval $(git cat-file tag $newrev | \
226 sed -n '4s/tagger \([^>]*>\)[^0-9]*\([0-9]*\).*/tagger="\1" ts="\2"/p')
227 tagged=$(date --date="1970-01-01 00:00:00 +0000 $ts seconds" +"$DATEFORMAT")
229 echo " tagged by $tagger"
230 echo " on $tagged"
232 echo ""
233 echo $LOGBEGIN
234 echo ""
236 if [ -n "$prevtag" ]; then
237 git rev-list --pretty=short "$prevtag..$newrev" | git shortlog
238 else
239 git rev-list --pretty=short $newrev | git shortlog
242 echo $LOGEND
243 echo ""
246 # By default, unannotated tags aren't allowed in; if
247 # they are though, it's debatable whether we would even want an
248 # email to be generated; however, I don't want to add another config
249 # option just for that.
251 # Unannotated tags are more about marking a point than releasing
252 # a version; therefore we don't do the shortlog summary that we
253 # do for annotated tags above - we simply show that the point has
254 # been marked, and print the log message for the marked point for
255 # reference purposes
257 # Note this section also catches any other reference type (although
258 # there aren't any) and deals with them in the same way.
259 if expr "$oldrev" : '0*$' >/dev/null
260 then
261 # If the old reference is "0000..0000" then this is a new tag
262 # and so oldrev is not valid
263 echo " as a new $refname_type"
264 echo " to $newrev ($newrev_type)"
265 else
266 echo " to $newrev ($newrev_type)"
267 echo " from $oldrev"
269 echo ""
270 echo $LOGBEGIN
271 git-show --no-color --root -s $newrev
272 echo $LOGEND
273 echo ""
275 esac
277 # Footer
278 cat <<-EOF
280 hooks/update
282 Git Source Code Management System
283 $0 $1 \\
284 $2 \\
287 #) | cat >&2
288 ) | /usr/sbin/sendmail -t
290 # --- Finished
291 exit 0