post-receive-email: optional message line count limit
[git/git.git] / contrib / hooks / post-receive-email
CommitLineData
4557e0de
AP
1#!/bin/sh
2#
3# Copyright (c) 2007 Andy Parkins
4#
15a2f530
GP
5# An example hook script to mail out commit update information. This hook
6# sends emails listing new revisions to the repository introduced by the
7# change being reported. The rule is that (for branch updates) each commit
8# will appear on one email and one email only.
4557e0de 9#
15a2f530
GP
10# This hook is stored in the contrib/hooks directory. Your distribution
11# will have put this somewhere standard. You should make this script
12# executable then link to it in the repository you would like to use it in.
13# For example, on debian the hook is stored in
14# /usr/share/doc/git-core/contrib/hooks/post-receive-email:
4557e0de
AP
15#
16# chmod a+x post-receive-email
17# cd /path/to/your/repository.git
18# ln -sf /usr/share/doc/git-core/contrib/hooks/post-receive-email hooks/post-receive
19#
15a2f530
GP
20# This hook script assumes it is enabled on the central repository of a
21# project, with all users pushing only to it and not between each other. It
22# will still work if you don't operate in that style, but it would become
23# possible for the email to be from someone other than the person doing the
24# push.
4557e0de 25#
cc24a1d8
JN
26# To help with debugging and use on pre-v1.5.1 git servers, this script will
27# also obey the interface of hooks/update, taking its arguments on the
28# command line. Unfortunately, hooks/update is called once for each ref.
29# To avoid firing one email per ref, this script just prints its output to
30# the screen when used in this mode. The output can then be redirected if
31# wanted.
32#
4557e0de
AP
33# Config
34# ------
35# hooks.mailinglist
36# This is the list that all pushes will go to; leave it blank to not send
37# emails for every ref update.
38# hooks.announcelist
39# This is the list that all pushes of annotated tags will go to. Leave it
15a2f530
GP
40# blank to default to the mailinglist field. The announce emails lists
41# the short log summary of the changes since the last annotated tag.
b5786c82 42# hooks.envelopesender
15a2f530
GP
43# If set then the -f option is passed to sendmail to allow the envelope
44# sender address to be set
e7509ee3
GP
45# hooks.emailprefix
46# All emails have their subjects prefixed with this prefix, or "[SCM]"
47# if emailprefix is unset, to aid filtering
b0a7d111
PH
48# hooks.showrev
49# The shell command used to format each revision in the email, with
50# "%s" replaced with the commit id. Defaults to "git rev-list -1
51# --pretty %s", displaying the commit id, author, date and log
52# message. To list full patches separated by a blank line, you
53# could set this to "git show -C %s; echo".
5ffd3113
JM
54# To list a gitweb/cgit URL *and* a full patch for each change set, use this:
55# "t=%s; printf 'http://.../?id=%%s' \$t; echo;echo; git show -C \$t; echo"
56# Be careful if "..." contains things that will be expanded by shell "eval"
57# or printf.
b03e7b7d
KF
58# hooks.emailmaxlines
59# The maximum number of lines that should be included in the generated
60# email body. If not specified, there is no limit.
61# Lines beyond the limit are suppressed and counted, and a final
62# line is added indicating the number of suppressed lines.
4557e0de
AP
63#
64# Notes
65# -----
4557e0de
AP
66# All emails include the headers "X-Git-Refname", "X-Git-Oldrev",
67# "X-Git-Newrev", and "X-Git-Reftype" to enable fine tuned filtering and
68# give information for debugging.
69#
70
71# ---------------------------- Functions
72
73#
74# Top level email generation function. This decides what type of update
75# this is and calls the appropriate body-generation routine after outputting
76# the common header
77#
15a2f530
GP
78# Note this function doesn't actually generate any email output, that is
79# taken care of by the functions it calls:
4557e0de
AP
80# - generate_email_header
81# - generate_create_XXXX_email
82# - generate_update_XXXX_email
83# - generate_delete_XXXX_email
84# - generate_email_footer
85#
86generate_email()
87{
88 # --- Arguments
89 oldrev=$(git rev-parse $1)
90 newrev=$(git rev-parse $2)
91 refname="$3"
b03e7b7d 92 maxlines=$4
4557e0de
AP
93
94 # --- Interpret
95 # 0000->1234 (create)
96 # 1234->2345 (update)
97 # 2345->0000 (delete)
98 if expr "$oldrev" : '0*$' >/dev/null
99 then
100 change_type="create"
101 else
102 if expr "$newrev" : '0*$' >/dev/null
103 then
104 change_type="delete"
105 else
106 change_type="update"
107 fi
108 fi
109
110 # --- Get the revision types
111 newrev_type=$(git cat-file -t $newrev 2> /dev/null)
112 oldrev_type=$(git cat-file -t "$oldrev" 2> /dev/null)
113 case "$change_type" in
114 create|update)
115 rev="$newrev"
116 rev_type="$newrev_type"
117 ;;
118 delete)
119 rev="$oldrev"
120 rev_type="$oldrev_type"
121 ;;
122 esac
123
124 # The revision type tells us what type the commit is, combined with
125 # the location of the ref we can decide between
126 # - working branch
127 # - tracking branch
128 # - unannoted tag
129 # - annotated tag
130 case "$refname","$rev_type" in
131 refs/tags/*,commit)
132 # un-annotated tag
133 refname_type="tag"
134 short_refname=${refname##refs/tags/}
135 ;;
136 refs/tags/*,tag)
137 # annotated tag
138 refname_type="annotated tag"
139 short_refname=${refname##refs/tags/}
140 # change recipients
141 if [ -n "$announcerecipients" ]; then
142 recipients="$announcerecipients"
143 fi
144 ;;
145 refs/heads/*,commit)
146 # branch
147 refname_type="branch"
148 short_refname=${refname##refs/heads/}
149 ;;
150 refs/remotes/*,commit)
151 # tracking branch
152 refname_type="tracking branch"
153 short_refname=${refname##refs/remotes/}
154 echo >&2 "*** Push-update of tracking branch, $refname"
155 echo >&2 "*** - no email generated."
156 exit 0
157 ;;
158 *)
159 # Anything else (is there anything else?)
160 echo >&2 "*** Unknown type of update to $refname ($rev_type)"
161 echo >&2 "*** - no email generated"
162 exit 1
163 ;;
164 esac
165
166 # Check if we've got anyone to send to
167 if [ -z "$recipients" ]; then
fdfeb87c
JM
168 case "$refname_type" in
169 "annotated tag")
170 config_name="hooks.announcelist"
171 ;;
172 *)
173 config_name="hooks.mailinglist"
174 ;;
175 esac
176 echo >&2 "*** $config_name is not set so no email will be sent"
4557e0de
AP
177 echo >&2 "*** for $refname update $oldrev->$newrev"
178 exit 0
179 fi
180
181 # Email parameters
4557e0de
AP
182 # The email subject will contain the best description of the ref
183 # that we can build from the parameters
184 describe=$(git describe $rev 2>/dev/null)
185 if [ -z "$describe" ]; then
186 describe=$rev
187 fi
188
189 generate_email_header
190
191 # Call the correct body generation function
192 fn_name=general
193 case "$refname_type" in
194 "tracking branch"|branch)
195 fn_name=branch
196 ;;
197 "annotated tag")
198 fn_name=atag
199 ;;
200 esac
b03e7b7d
KF
201
202 if [ -z "$maxlines" ]; then
203 generate_${change_type}_${fn_name}_email
204 else
205 generate_${change_type}_${fn_name}_email | limit_lines $maxlines
206 fi
4557e0de
AP
207
208 generate_email_footer
209}
210
211generate_email_header()
212{
213 # --- Email (all stdout will be the email)
214 # Generate header
215 cat <<-EOF
4557e0de 216 To: $recipients
e7509ee3 217 Subject: ${emailprefix}$projectdesc $refname_type, $short_refname, ${change_type}d. $describe
4557e0de
AP
218 X-Git-Refname: $refname
219 X-Git-Reftype: $refname_type
220 X-Git-Oldrev: $oldrev
221 X-Git-Newrev: $newrev
222
223 This is an automated email from the git hooks/post-receive script. It was
224 generated because a ref change was pushed to the repository containing
225 the project "$projectdesc".
226
227 The $refname_type, $short_refname has been ${change_type}d
228 EOF
229}
230
231generate_email_footer()
232{
71bd81ad 233 SPACE=" "
4557e0de
AP
234 cat <<-EOF
235
236
237 hooks/post-receive
71bd81ad 238 --${SPACE}
4557e0de
AP
239 $projectdesc
240 EOF
241}
242
243# --------------- Branches
244
245#
246# Called for the creation of a branch
247#
248generate_create_branch_email()
249{
250 # This is a new branch and so oldrev is not valid
251 echo " at $newrev ($newrev_type)"
252 echo ""
253
254 echo $LOGBEGIN
4471649f 255 show_new_revisions
4557e0de
AP
256 echo $LOGEND
257}
258
259#
260# Called for the change of a pre-existing branch
261#
262generate_update_branch_email()
263{
264 # Consider this:
265 # 1 --- 2 --- O --- X --- 3 --- 4 --- N
266 #
267 # O is $oldrev for $refname
268 # N is $newrev for $refname
269 # X is a revision pointed to by some other ref, for which we may
270 # assume that an email has already been generated.
271 # In this case we want to issue an email containing only revisions
272 # 3, 4, and N. Given (almost) by
273 #
22fa97d4 274 # git rev-list N ^O --not --all
4557e0de
AP
275 #
276 # The reason for the "almost", is that the "--not --all" will take
277 # precedence over the "N", and effectively will translate to
278 #
22fa97d4 279 # git rev-list N ^O ^X ^N
4557e0de 280 #
22fa97d4
DM
281 # So, we need to build up the list more carefully. git rev-parse
282 # will generate a list of revs that may be fed into git rev-list.
15a2f530
GP
283 # We can get it to make the "--not --all" part and then filter out
284 # the "^N" with:
4557e0de 285 #
22fa97d4 286 # git rev-parse --not --all | grep -v N
4557e0de 287 #
22fa97d4 288 # Then, using the --stdin switch to git rev-list we have effectively
4557e0de
AP
289 # manufactured
290 #
22fa97d4 291 # git rev-list N ^O ^X
4557e0de
AP
292 #
293 # This leaves a problem when someone else updates the repository
15a2f530
GP
294 # while this script is running. Their new value of the ref we're
295 # working on would be included in the "--not --all" output; and as
296 # our $newrev would be an ancestor of that commit, it would exclude
297 # all of our commits. What we really want is to exclude the current
298 # value of $refname from the --not list, rather than N itself. So:
4557e0de 299 #
22fa97d4 300 # git rev-parse --not --all | grep -v $(git rev-parse $refname)
4557e0de 301 #
15a2f530 302 # Get's us to something pretty safe (apart from the small time
22fa97d4 303 # between refname being read, and git rev-parse running - for that,
15a2f530 304 # I give up)
4557e0de
AP
305 #
306 #
307 # Next problem, consider this:
308 # * --- B --- * --- O ($oldrev)
309 # \
310 # * --- X --- * --- N ($newrev)
311 #
15a2f530
GP
312 # That is to say, there is no guarantee that oldrev is a strict
313 # subset of newrev (it would have required a --force, but that's
314 # allowed). So, we can't simply say rev-list $oldrev..$newrev.
315 # Instead we find the common base of the two revs and list from
316 # there.
4557e0de 317 #
15a2f530
GP
318 # As above, we need to take into account the presence of X; if
319 # another branch is already in the repository and points at some of
320 # the revisions that we are about to output - we don't want them.
22fa97d4 321 # The solution is as before: git rev-parse output filtered.
4557e0de 322 #
15a2f530 323 # Finally, tags: 1 --- 2 --- O --- T --- 3 --- 4 --- N
4557e0de
AP
324 #
325 # Tags pushed into the repository generate nice shortlog emails that
326 # summarise the commits between them and the previous tag. However,
327 # those emails don't include the full commit messages that we output
328 # for a branch update. Therefore we still want to output revisions
329 # that have been output on a tag email.
330 #
22fa97d4 331 # Luckily, git rev-parse includes just the tool. Instead of using
15a2f530
GP
332 # "--all" we use "--branches"; this has the added benefit that
333 # "remotes/" will be ignored as well.
334
335 # List all of the revisions that were removed by this update, in a
a75d7b54
FC
336 # fast-forward update, this list will be empty, because rev-list O
337 # ^N is empty. For a non-fast-forward, O ^N is the list of removed
15a2f530 338 # revisions
8e404f82 339 fast_forward=""
4557e0de
AP
340 rev=""
341 for rev in $(git rev-list $newrev..$oldrev)
342 do
343 revtype=$(git cat-file -t "$rev")
344 echo " discards $rev ($revtype)"
345 done
346 if [ -z "$rev" ]; then
347 fast_forward=1
348 fi
349
350 # List all the revisions from baserev to newrev in a kind of
15a2f530
GP
351 # "table-of-contents"; note this list can include revisions that
352 # have already had notification emails and is present to show the
353 # full detail of the change from rolling back the old revision to
354 # the base revision and then forward to the new revision
4557e0de
AP
355 for rev in $(git rev-list $oldrev..$newrev)
356 do
357 revtype=$(git cat-file -t "$rev")
358 echo " via $rev ($revtype)"
359 done
360
a2d6b872 361 if [ "$fast_forward" ]; then
4557e0de
AP
362 echo " from $oldrev ($oldrev_type)"
363 else
15a2f530
GP
364 # 1. Existing revisions were removed. In this case newrev
365 # is a subset of oldrev - this is the reverse of a
366 # fast-forward, a rewind
367 # 2. New revisions were added on top of an old revision,
368 # this is a rewind and addition.
024e5b31 369
15a2f530
GP
370 # (1) certainly happened, (2) possibly. When (2) hasn't
371 # happened, we set a flag to indicate that no log printout
372 # is required.
024e5b31 373
4557e0de 374 echo ""
024e5b31 375
15a2f530
GP
376 # Find the common ancestor of the old and new revisions and
377 # compare it with newrev
024e5b31
AP
378 baserev=$(git merge-base $oldrev $newrev)
379 rewind_only=""
380 if [ "$baserev" = "$newrev" ]; then
381 echo "This update discarded existing revisions and left the branch pointing at"
382 echo "a previous point in the repository history."
383 echo ""
384 echo " * -- * -- N ($newrev)"
385 echo " \\"
386 echo " O -- O -- O ($oldrev)"
387 echo ""
388 echo "The removed revisions are not necessarilly gone - if another reference"
389 echo "still refers to them they will stay in the repository."
390 rewind_only=1
391 else
392 echo "This update added new revisions after undoing existing revisions. That is"
393 echo "to say, the old revision is not a strict subset of the new revision. This"
394 echo "situation occurs when you --force push a change and generate a repository"
395 echo "containing something like this:"
396 echo ""
397 echo " * -- * -- B -- O -- O -- O ($oldrev)"
398 echo " \\"
399 echo " N -- N -- N ($newrev)"
400 echo ""
401 echo "When this happens we assume that you've already had alert emails for all"
402 echo "of the O revisions, and so we here report only the revisions in the N"
403 echo "branch from the common base, B."
404 fi
4557e0de
AP
405 fi
406
407 echo ""
024e5b31
AP
408 if [ -z "$rewind_only" ]; then
409 echo "Those revisions listed above that are new to this repository have"
410 echo "not appeared on any other notification email; so we list those"
411 echo "revisions in full, below."
4557e0de 412
024e5b31
AP
413 echo ""
414 echo $LOGBEGIN
4471649f 415 show_new_revisions
4557e0de 416
15a2f530
GP
417 # XXX: Need a way of detecting whether git rev-list actually
418 # outputted anything, so that we can issue a "no new
419 # revisions added by this update" message
4557e0de 420
024e5b31
AP
421 echo $LOGEND
422 else
423 echo "No new revisions were added by this update."
424 fi
4557e0de 425
15a2f530
GP
426 # The diffstat is shown from the old revision to the new revision.
427 # This is to show the truth of what happened in this change.
428 # There's no point showing the stat from the base to the new
429 # revision because the base is effectively a random revision at this
430 # point - the user will be interested in what this revision changed
431 # - including the undoing of previous revisions in the case of
a75d7b54 432 # non-fast-forward updates.
4557e0de
AP
433 echo ""
434 echo "Summary of changes:"
435 git diff-tree --stat --summary --find-copies-harder $oldrev..$newrev
436}
437
438#
439# Called for the deletion of a branch
440#
441generate_delete_branch_email()
442{
443 echo " was $oldrev"
444 echo ""
445 echo $LOGEND
446 git show -s --pretty=oneline $oldrev
447 echo $LOGEND
448}
449
450# --------------- Annotated tags
451
452#
453# Called for the creation of an annotated tag
454#
455generate_create_atag_email()
456{
457 echo " at $newrev ($newrev_type)"
458
459 generate_atag_email
460}
461
462#
463# Called for the update of an annotated tag (this is probably a rare event
464# and may not even be allowed)
465#
466generate_update_atag_email()
467{
468 echo " to $newrev ($newrev_type)"
469 echo " from $oldrev (which is now obsolete)"
470
471 generate_atag_email
472}
473
474#
475# Called when an annotated tag is created or changed
476#
477generate_atag_email()
478{
22fa97d4 479 # Use git for-each-ref to pull out the individual fields from the
15a2f530 480 # tag
4557e0de
AP
481 eval $(git for-each-ref --shell --format='
482 tagobject=%(*objectname)
483 tagtype=%(*objecttype)
484 tagger=%(taggername)
485 tagged=%(taggerdate)' $refname
486 )
487
488 echo " tagging $tagobject ($tagtype)"
489 case "$tagtype" in
490 commit)
15a2f530 491
4557e0de 492 # If the tagged object is a commit, then we assume this is a
15a2f530
GP
493 # release, and so we calculate which tag this tag is
494 # replacing
4557e0de
AP
495 prevtag=$(git describe --abbrev=0 $newrev^ 2>/dev/null)
496
497 if [ -n "$prevtag" ]; then
498 echo " replaces $prevtag"
499 fi
500 ;;
501 *)
502 echo " length $(git cat-file -s $tagobject) bytes"
503 ;;
504 esac
505 echo " tagged by $tagger"
506 echo " on $tagged"
507
508 echo ""
509 echo $LOGBEGIN
510
15a2f530
GP
511 # Show the content of the tag message; this might contain a change
512 # log or release notes so is worth displaying.
4557e0de
AP
513 git cat-file tag $newrev | sed -e '1,/^$/d'
514
515 echo ""
516 case "$tagtype" in
517 commit)
15a2f530
GP
518 # Only commit tags make sense to have rev-list operations
519 # performed on them
4557e0de
AP
520 if [ -n "$prevtag" ]; then
521 # Show changes since the previous release
522 git rev-list --pretty=short "$prevtag..$newrev" | git shortlog
523 else
15a2f530
GP
524 # No previous tag, show all the changes since time
525 # began
4557e0de
AP
526 git rev-list --pretty=short $newrev | git shortlog
527 fi
528 ;;
529 *)
15a2f530
GP
530 # XXX: Is there anything useful we can do for non-commit
531 # objects?
4557e0de
AP
532 ;;
533 esac
534
535 echo $LOGEND
536}
537
538#
539# Called for the deletion of an annotated tag
540#
541generate_delete_atag_email()
542{
543 echo " was $oldrev"
544 echo ""
545 echo $LOGEND
546 git show -s --pretty=oneline $oldrev
547 echo $LOGEND
548}
549
550# --------------- General references
551
552#
553# Called when any other type of reference is created (most likely a
554# non-annotated tag)
555#
556generate_create_general_email()
557{
558 echo " at $newrev ($newrev_type)"
559
560 generate_general_email
561}
562
563#
564# Called when any other type of reference is updated (most likely a
565# non-annotated tag)
566#
567generate_update_general_email()
568{
569 echo " to $newrev ($newrev_type)"
570 echo " from $oldrev"
571
572 generate_general_email
573}
574
575#
576# Called for creation or update of any other type of reference
577#
578generate_general_email()
579{
15a2f530
GP
580 # Unannotated tags are more about marking a point than releasing a
581 # version; therefore we don't do the shortlog summary that we do for
582 # annotated tags above - we simply show that the point has been
583 # marked, and print the log message for the marked point for
584 # reference purposes
4557e0de 585 #
15a2f530
GP
586 # Note this section also catches any other reference type (although
587 # there aren't any) and deals with them in the same way.
4557e0de
AP
588
589 echo ""
590 if [ "$newrev_type" = "commit" ]; then
591 echo $LOGBEGIN
9225d7be 592 git show --no-color --root -s --pretty=medium $newrev
4557e0de
AP
593 echo $LOGEND
594 else
15a2f530
GP
595 # What can we do here? The tag marks an object that is not
596 # a commit, so there is no log for us to display. It's
22fa97d4 597 # probably not wise to output git cat-file as it could be a
15a2f530 598 # binary blob. We'll just say how big it is
4557e0de
AP
599 echo "$newrev is a $newrev_type, and is $(git cat-file -s $newrev) bytes long."
600 fi
601}
602
603#
604# Called for the deletion of any other type of reference
605#
606generate_delete_general_email()
607{
608 echo " was $oldrev"
609 echo ""
610 echo $LOGEND
611 git show -s --pretty=oneline $oldrev
612 echo $LOGEND
613}
614
4471649f
PH
615
616# --------------- Miscellaneous utilities
617
618#
619# Show new revisions as the user would like to see them in the email.
620#
621show_new_revisions()
622{
623 # This shows all log entries that are not already covered by
624 # another ref - i.e. commits that are now accessible from this
625 # ref that were previously not accessible
626 # (see generate_update_branch_email for the explanation of this
627 # command)
628
629 # Revision range passed to rev-list differs for new vs. updated
630 # branches.
631 if [ "$change_type" = create ]
632 then
633 # Show all revisions exclusive to this (new) branch.
634 revspec=$newrev
635 else
636 # Branch update; show revisions not part of $oldrev.
637 revspec=$oldrev..$newrev
638 fi
639
e5f5050e
PN
640 other_branches=$(git for-each-ref --format='%(refname)' refs/heads/ |
641 grep -F -v $refname)
642 git rev-parse --not $other_branches |
b0a7d111
PH
643 if [ -z "$custom_showrev" ]
644 then
645 git rev-list --pretty --stdin $revspec
646 else
647 git rev-list --stdin $revspec |
648 while read onerev
649 do
650 eval $(printf "$custom_showrev" $onerev)
651 done
652 fi
4471649f
PH
653}
654
655
b03e7b7d
KF
656limit_lines()
657{
658 lines=0
659 skipped=0
660 while IFS="" read -r line; do
661 lines=$((lines + 1))
662 if [ $lines -gt $1 ]; then
663 skipped=$((skipped + 1))
664 else
665 printf "%s\n" "$line"
666 fi
667 done
668 if [ $skipped -ne 0 ]; then
669 echo "... $skipped lines suppressed ..."
670 fi
671}
672
673
d1637a07
JM
674send_mail()
675{
676 if [ -n "$envelopesender" ]; then
677 /usr/sbin/sendmail -t -f "$envelopesender"
678 else
679 /usr/sbin/sendmail -t
680 fi
681}
682
4557e0de
AP
683# ---------------------------- main()
684
685# --- Constants
4557e0de
AP
686LOGBEGIN="- Log -----------------------------------------------------------------"
687LOGEND="-----------------------------------------------------------------------"
688
689# --- Config
690# Set GIT_DIR either from the working directory, or from the environment
691# variable.
692GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
693if [ -z "$GIT_DIR" ]; then
694 echo >&2 "fatal: post-receive: GIT_DIR not set"
695 exit 1
696fi
697
c855195c 698projectdesc=$(sed -ne '1p' "$GIT_DIR/description")
15a2f530
GP
699# Check if the description is unchanged from it's default, and shorten it to
700# a more manageable length if it is
4557e0de
AP
701if expr "$projectdesc" : "Unnamed repository.*$" >/dev/null
702then
703 projectdesc="UNNAMED PROJECT"
704fi
705
22fa97d4
DM
706recipients=$(git config hooks.mailinglist)
707announcerecipients=$(git config hooks.announcelist)
708envelopesender=$(git config hooks.envelopesender)
709emailprefix=$(git config hooks.emailprefix || echo '[SCM] ')
b0a7d111 710custom_showrev=$(git config hooks.showrev)
b03e7b7d 711maxlines=$(git config hooks.emailmaxlines)
4557e0de
AP
712
713# --- Main loop
15a2f530
GP
714# Allow dual mode: run from the command line just like the update hook, or
715# if no arguments are given then run as a hook script
4557e0de
AP
716if [ -n "$1" -a -n "$2" -a -n "$3" ]; then
717 # Output to the terminal in command line mode - if someone wanted to
15a2f530
GP
718 # resend an email; they could redirect the output to sendmail
719 # themselves
4557e0de
AP
720 PAGER= generate_email $2 $3 $1
721else
4557e0de
AP
722 while read oldrev newrev refname
723 do
b03e7b7d 724 generate_email $oldrev $newrev $refname $maxlines | send_mail
4557e0de
AP
725 done
726fi