Fixed up git update/mailing script
[mirror-monitor.git] / bin / git-feed-mail-list.sh
1 #!/usr/bin/env bash
2 #
3 # Generate a mail feed for a commits list.
4 #
5 # Author: David Woodhouse <dwmw2@infradead.org>
6
7 # Environment variables used by this script...
8 #
9 # $SENDMAIL and $MLIST must be set appropriately if you intend to
10 # actually send mail to a mailing list (or other recipient). Otherwise,
11 # an mbox file named 'git commits-mail.out' will be created in the 
12 # current directory.
13 #
14 # $FROM specifies the From: header used in the mails. It'll default
15 # to GIT_COMMITTER_EMAIL if that exists, or to `whoami`@`hostname`
16 #
17 # $EXCLUDEHEAD is given as additional arguments to the git rev-list
18 # invocation, and is intended to allow other branches to be excluded.
19 # For example, subsystem trees might avoid mailing changes which were
20 # merged in from Linus' tree by setting EXCLUDEHEAD=^linus
21 #
22 # $GIT_DIR has the obvious effect.
23 #
24 # $MAILTAG specifies the file in which the 'last commit mailed' information
25 # is stored. By default, this will be $GIT_DIR/refs/tags/MailDone, or
26 # just the relative path '.git/refs/tags/MailDone' if $GIT_DIR is not specified
27 #
28 # GITWEB specifies the base URL to gitweb for this repository
29
30 if [ -z "SENDMAIL" -o -z "$MLIST" ]; then 
31     SENDMAIL="tee --append"
32     MLIST=git commits-mail.out
33 fi
34
35 if [ -z "$FROM" ]; then
36     if [ -n "$GIT_COMMITTER_EMAIL" ]; then 
37         FROM="$GIT_COMMITTER_EMAIL"
38     else
39         FROM=`whoami`@`hostname`
40     fi
41 fi
42
43 if [ -z "$MAILTAG" ]; then
44     if [ "$GIT_DIR" = "" ]; then
45         MAILTAG=.git/refs/tags/MailDone
46     else
47         MAILTAG=$GIT_DIR/refs/tags/MailDone
48     fi
49 fi
50
51 # Command line arguments. The first specifies the commit or branch to treat
52 # as HEAD, and the second is the starting commit. Defaults to HEAD and 
53 # whatever's in $MAILTAG, resp.
54
55 if [ -z $2 ]; then
56     lastmail=$(git rev-parse `cat $MAILTAG`)
57     if [ -z "$lastmail" ]; then
58         echo "No last tag"
59         exit 1
60     fi
61 else
62     lastmail=$(git rev-parse $2)
63 fi
64
65 if [ -z $1 ]; then
66     base=$(git rev-parse HEAD) || exit 1
67 else
68     base=$(git rev-parse $1) || exit 1
69 fi
70
71
72 if [ "$base" != "$lastmail" ]; then
73     git rev-list --topo-order --no-merges $lastmail..$base $EXCLUDEHEAD | tac |
74     while read COMMIT ; do (
75         PARENT=`git rev-parse $COMMIT^1`
76 #       SUBJECT="`git show --pretty=oneline $COMMIT | head -2 | tail -1`"
77         SUBJECT="`git cat-file commit $COMMIT | grep -A1 ^\$ | head -2 | tail -1`"
78         echo Mail: $SUBJECT >&2
79
80         SUBHEX="`echo -n "$SUBJECT" | od -t x1 -A none | tr a-f A-F`"
81         if echo $SUBHEX | egrep -q ' [8-9A-F]' ; then
82             # Subject contains non-ASCII.
83             WORDLEN=10
84             NEWSUB="=?UTF-8?Q?"
85             for CHR in $SUBHEX ; do
86                 if [ $WORDLEN -gt 70 ]; then
87                     NEWSUB="${NEWSUB}?=
88  =?UTF-8?Q?"
89                     WORDLEN=10
90                 fi
91                 case $CHR in
92                     20)
93                         NEWSUB="${NEWSUB}_"
94                         WORDLEN=$((WORDLEN+1))
95                         ;;
96                     0*|1*|3D|3F|5F|7F|8*|9*|A*|B*|C*|D*|E*|F*)
97                         NEWSUB="${NEWSUB}=$CHR"
98                         WORDLEN=$(($WORDLEN+3))
99                         ;;
100                     *)
101                         NEWSUB="${NEWSUB}`echo -en \\\\x$CHR`"
102                         WORDLEN=$((WORDLEN+1))
103                         ;;
104                 esac
105             done
106             SUBJECT="$NEWSUB?="
107         fi
108         cat <<EOF 
109 From: $FROM
110 To: $MLIST
111 Subject: $SUBJECT
112 MIME-Version: 1.0
113 Content-Type: text/plain; charset=UTF-8
114 Content-Transfer-Encoding: 8bit
115 X-Git-Commit: $COMMIT
116 X-Git-Parent: $PARENT
117
118 Gitweb:     $GITWEB;a=commit;h=$COMMIT
119 Commit:     $COMMIT
120 Parent:     $PARENT
121 EOF
122         git show -M -C --patch-with-stat --pretty=fuller $COMMIT | 
123             egrep -v '^diff-tree [A-Fa-f0-9]{40} \(from [A-Fa-z0-9]{40}\)$' |
124             egrep -v '^commit [A-Fa-f0-9]{40}$' | sed 's/^Commit:   /Committer:/'
125         ) | $SENDMAIL $MLIST
126     done
127
128     echo $base > $MAILTAG
129 fi