Whamcloud - gitweb
LU-553 build: Lustre style commit hooks for Git
[fs/lustre-release.git] / build / commit-msg
1 #!/bin/bash
2 #
3 # A hook script to check the commit log message to ensure that it has
4 # a well-formed commit summary and body, a valid Signed-off-by: line,
5 # and a Gerrit Change-Id: line (added automatically if missing).
6 #
7 # Called by git-commit with one argument, the name of the file
8 # that has the commit message.  The hook should exit with non-zero
9 # status after issuing an appropriate message if it wants to stop the
10 # commit.  The hook is allowed to edit the commit message file.
11 #
12 # Should be installed as .git/hooks/commit-msg.
13 #
14
15 ORIGINAL="$1"
16 REVISED="$(mktemp "$1.XXXXXX")"
17 SIGNOFF="Signed-off-by:"
18 CHANGEID="Change-Id:"
19
20 # Check for, and add if missing, a unique Change-Id
21 new_changeid() {
22         {
23                 git var GIT_AUTHOR_IDENT
24                 git var GIT_COMMITTER_IDENT
25                 git write-tree
26                 git rev-parse HEAD 2>/dev/null
27                 grep -v "$SIGNOFF" "$ORIGINAL" | git stripspace -s
28         } | git hash-object -t commit --stdin
29 }
30
31 usage() {
32         [ "$LINE" ] && echo "error:$NUM: $LINE" 1>&2 && echo "" 1>&2
33
34         cat 1>&2 <<- EOF
35         Commit message $1
36         $2
37         See http://wiki.whamcloud.com/display/PUB/Submitting+Changes
38         for full details.  An example valid commit comment is:
39
40         LU-nnn component: short description of change under 64 columns
41
42         A more detailed explanation.  This can be as detailed as you'd like.
43         Please explain both what problem was solved and a good high-level
44         description of how it was solved.  Wrap lines at 70 columns or less.
45
46         $SIGNOFF Your Real Name <your_email@domain.name>
47         $CHANGEID Ixxxx(added automatically if missing)xxxx
48         EOF
49
50         exit 1
51 }
52
53 export HAS_SIGNOFF=false
54 export HAS_SUMMARY=false
55 export HAS_BLANK=false
56 export HAS_COMMENTS=false
57
58 grep -q "^$CHANGEID" "$ORIGINAL" && HAS_CHANGEID=true || HAS_CHANGEID=false
59
60 export LINE=""
61 export NUM=1
62
63 IFS=""
64 while read LINE; do
65         LENGTH=$(echo $LINE | wc -c)
66
67         case "$LINE" in
68         $SIGNOFF*)
69                 $HAS_SUMMARY || usage "missing summary before $SIGNOFF."
70                 $HAS_BLANK || usage "missing blank line before $SIGNOFF."
71                 GOOD=$(echo "$LINE" | grep "^$SIGNOFF .* .* <.*@.*>")
72                 [ -z "$GOOD" ] &&
73                         usage "missing valid commit summary line to show" \
74                               "agreement with code submission requirements at"
75                 HAS_SIGNOFF=true
76                 echo $LINE
77                 $HAS_CHANGEID || echo "$CHANGEID I$(new_changeid)"
78                 ;;
79         $CHANGEID*)
80                 $HAS_SUMMARY || usage "missing summary before $CHANGEID line."
81                 $HAS_BLANK || usage "missing blank line before $CHANGEID line."
82                 HAS_CHANGEID=true
83                 echo $LINE
84                 ;;
85         "")     [ $HAS_SUMMARY -a $NUM -eq 2 ] && HAS_BLANK=true
86                 echo $LINE
87                 ;;
88         \#*)    HAS_COMMENTS=true
89                 continue
90                 ;;
91         *)      if [ $NUM -eq 1 ]; then
92                         FMT="^[A-Z]\{2,5\}-[0-9]\{1,5\} [-a-z0-9]\{2,9\}: "
93                         GOOD=$(echo "$LINE" | grep "$FMT")
94                         [ $LENGTH -gt 64 ] &&
95                                 usage "summary longer than 64 columns."
96                         if [ -z "$GOOD" ]; then
97                                 FMT="^[A-Z]\{2,5\}-[0-9]\{1,5\} "
98                                 NO_SUBSYS=$(echo "$LINE" | grep "$FMT")
99                                 [ "$NO_SUBSYS" ] &&
100                                         usage "has no subsys: in commit summary"
101                                 usage "missing valid commit summary line."
102                         fi
103                         HAS_SUMMARY=true
104                 elif [ $LENGTH -gt 70 ]; then
105                         usage "has lines longer than 70 columns."
106                 fi
107                 echo $LINE
108                 ;;
109         esac
110
111         NUM=$((NUM + 1))
112 done < "$ORIGINAL" > "$REVISED"
113
114 [ $NUM -eq 1 ] && exit 1 # empty file
115
116 LINE=""
117 $HAS_SUMMARY || usage "missing commit summary line."
118 $HAS_SIGNOFF || usage "missing $SIGNOFF line."
119 $HAS_CHANGEID && rm "$REVISED" || mv "$REVISED" "$ORIGINAL"