summaryrefslogtreecommitdiff
path: root/.git-hooks/commit-msg
blob: 027c37510ff6051f218adbb2cd732322b79738c0 (plain)
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
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by git-commit with one argument, the name of the file
# that has the commit message.  The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit.  The hook is allowed to edit the commit message file.
#
# To enable this hook, make this file executable.

# Uncomment the below to add a Signed-off-by line to the message.
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"

# This example catches duplicate Signed-off-by lines.

base_dir=$(dirname $0)
MSG="$1"

abort() {
    cp $1 $1.save
    cat >&2 <<EOF
Commit aborted, your commit message was saved as '$1.save'.

Reason: $2

EOF
    exit 1
}

test "" = "$(grep '^Signed-off-by: ' "$1" |
         sort | uniq -c | sed -e '/^[         ]*1[         ]/d')" || {
        abort "$1" "Duplicate Signed-off-by lines."
}

# Check that the first line exists, and is not an asterisk

if [ -z "`head -n 1 $1 | grep -v '^[[:blank:]]*\*$'`" ] ; then
    abort "$1" "Please provide the general description on the first line."
fi

# ...and that it is not too long

len="`head -n 1 $1 | tr -d '\n' | wc -c`"
if [ "$len" -gt 79 ] ; then
    abort "$1" "The first line is $len characters, please try to fit into 79 characters."
fi

fdo_regex='fdo#[0-9]+'
if egrep -q "$fdo_regex" $1; then
    for bugid in `head -n 1 $1 |egrep -o "$fdo_regex" |sed 's/fdo#//'`
    do
        if [ "`echo $bugid |sed 's/fdo#//'`" -gt 88775 ]; then
            abort "$1" "The first line contains a suspicious fdo# rereference: 'fdo#$bugid', did you mean tdf#?"
        fi
    done
fi

# ...and that it does not continue on the second line
if [ "`wc -l < $1`" -gt 1 -a -n "`head -n 2 $1 | tail -n 1 | sed 's/^#.*//'`" ] ; then
    abort "$1" "The second line is not empty - maybe the first line continues there?"
fi

# Check that the message is not a ChangeLog-like one

if [ -n "`head -n 1 $1 | grep '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}.*<.*@.*>'`" ] ; then
    abort "$1" "The commit message looks like ChangeLog, please use the git form."
fi

# Check that lines do not start with '#<something>' (possibly accidental commit,
# such as starting the message with '#ifdef', git commits start with '#<whitespace>'.

if [ -n "`grep '^#[^[:blank:]]' $1`" ] ; then
    abort "$1" "Possible accidental comment in the commit message (leading # without space)."
fi


#------------------ copied gerrit commit-msg hook to handle ChangeId -->
# From Gerrit Code Review 2.3
#
# Part of Gerrit Code Review (http://code.google.com/p/gerrit/)
#
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

CHANGE_ID_AFTER="Bug|Issue"

# Check for, and add if missing, a unique Change-Id
#
add_ChangeId() {
        clean_message=`sed -e '
                /^diff --git .*/{
                        s///
                        q
                }
                /^Signed-off-by:/d
                /^#/d
        ' "$MSG" | git stripspace`
        if test -z "$clean_message"
        then
                return
        fi

        if test "false" = "`git config --bool --get gerrit.createChangeId`"
        then
                return
        fi

        # Does Change-Id: already exist? if so, exit (no change).
        if grep -i '^Change-Id:' "$MSG" >/dev/null
        then
                return
        fi

        id=`_gen_ChangeId`
        T="$MSG.tmp.$$"
        AWK=awk
        if [ -x /usr/xpg4/bin/awk ]; then
                # Solaris AWK is just too broken
                AWK=/usr/xpg4/bin/awk
        fi

        # How this works:
        # - parse the commit message as (textLine+ blankLine*)*
        # - assume textLine+ to be a footer until proven otherwise
        # - exception: the first block is not footer (as it is the title)
        # - read textLine+ into a variable
        # - then count blankLines
        # - once the next textLine appears, print textLine+ blankLine* as these
        #   aren't footer
        # - in END, the last textLine+ block is available for footer parsing
        $AWK '
        BEGIN {
                # while we start with the assumption that textLine+
                # is a footer, the first block is not.
                isFooter = 0
                footerComment = 0
                blankLines = 0
        }

        # Skip lines starting with "#" without any spaces before it.
        /^#/ { next }

        # Skip the line starting with the diff command and everything after it,
        # up to the end of the file, assuming it is only patch data.
        # If more than one line before the diff was empty, strip all but one.
        /^diff --git / {
                blankLines = 0
                while (getline) { }
                next
        }

        # Count blank lines outside footer comments
        /^$/ && (footerComment == 0) {
                blankLines++
                next
        }

        # Catch footer comment
        /^\[[a-zA-Z0-9-]+:/ && (isFooter == 1) {
                footerComment = 1
        }

        /]$/ && (footerComment == 1) {
                footerComment = 2
        }

        # We have a non-blank line after blank lines. Handle this.
        (blankLines > 0) {
                print lines
                for (i = 0; i < blankLines; i++) {
                        print ""
                }

                lines = ""
                blankLines = 0
                isFooter = 1
                footerComment = 0
        }

        # Detect that the current block is not the footer
        (footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/ || /^[a-zA-Z0-9-]+:\/\//) {
                isFooter = 0
        }

        {
                # We need this information about the current last comment line
                if (footerComment == 2) {
                        footerComment = 0
                }
                if (lines != "") {
                        lines = lines "\n";
                }
                lines = lines $0
        }

        # Footer handling:
        # If the last block is considered a footer, splice in the Change-Id at the
        # right place.
        # Look for the right place to inject Change-Id by considering
        # CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first,
        # then Change-Id, then everything else (eg. Signed-off-by:).
        #
        # Otherwise just print the last block, a new line and the Change-Id as a
        # block of its own.
        END {
                unprinted = 1
                if (isFooter == 0) {
                        print lines "\n"
                        lines = ""
                }
                changeIdAfter = "^(" tolower("'"$CHANGE_ID_AFTER"'") "):"
                numlines = split(lines, footer, "\n")
                for (line = 1; line <= numlines; line++) {
                        if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) {
                                unprinted = 0
                                print "Change-Id: I'"$id"'"
                        }
                        print footer[line]
                }
                if (unprinted) {
                        print "Change-Id: I'"$id"'"
                }
        }' "$MSG" > "$T" && mv "$T" "$MSG" || rm -f "$T"
}
_gen_ChangeIdInput() {
        echo "tree `git write-tree`"
        if parent=`git rev-parse "HEAD^0" 2>/dev/null`
        then
                echo "parent $parent"
        fi
        echo "author `git var GIT_AUTHOR_IDENT`"
        echo "committer `git var GIT_COMMITTER_IDENT`"
        echo
        printf '%s' "$clean_message"
}
_gen_ChangeId() {
        _gen_ChangeIdInput |
        git hash-object -t commit --stdin
}


add_ChangeId
#------------------ copied gerrit commit-msg hook to handle ChangeId <--


exit 0

# vi:set shiftwidth=4 expandtab: