diff options
Diffstat (limited to 'hooks/commit-msg')
| -rwxr-xr-x | hooks/commit-msg | 218 |
1 files changed, 45 insertions, 173 deletions
diff --git a/hooks/commit-msg b/hooks/commit-msg index d9bb188b..70d67eaf 100755 --- a/hooks/commit-msg +++ b/hooks/commit-msg | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | #!/bin/sh | 1 | #!/bin/sh |
| 2 | # From Gerrit Code Review 2.14.6 | 2 | # From Gerrit Code Review 3.1.3 |
| 3 | # | 3 | # |
| 4 | # Part of Gerrit Code Review (https://www.gerritcodereview.com/) | 4 | # Part of Gerrit Code Review (https://www.gerritcodereview.com/) |
| 5 | # | 5 | # |
| @@ -16,176 +16,48 @@ | |||
| 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 17 | # See the License for the specific language governing permissions and | 17 | # See the License for the specific language governing permissions and |
| 18 | # limitations under the License. | 18 | # limitations under the License. |
| 19 | # | ||
| 20 | |||
| 21 | unset GREP_OPTIONS | ||
| 22 | |||
| 23 | CHANGE_ID_AFTER="Bug|Depends-On|Issue|Test|Feature|Fixes|Fixed" | ||
| 24 | MSG="$1" | ||
| 25 | |||
| 26 | # Check for, and add if missing, a unique Change-Id | ||
| 27 | # | ||
| 28 | add_ChangeId() { | ||
| 29 | clean_message=`sed -e ' | ||
| 30 | /^diff --git .*/{ | ||
| 31 | s/// | ||
| 32 | q | ||
| 33 | } | ||
| 34 | /^Signed-off-by:/d | ||
| 35 | /^#/d | ||
| 36 | ' "$MSG" | git stripspace` | ||
| 37 | if test -z "$clean_message" | ||
| 38 | then | ||
| 39 | return | ||
| 40 | fi | ||
| 41 | |||
| 42 | # Do not add Change-Id to temp commits | ||
| 43 | if echo "$clean_message" | head -1 | grep -q '^\(fixup\|squash\)!' | ||
| 44 | then | ||
| 45 | return | ||
| 46 | fi | ||
| 47 | |||
| 48 | if test "false" = "`git config --bool --get gerrit.createChangeId`" | ||
| 49 | then | ||
| 50 | return | ||
| 51 | fi | ||
| 52 | |||
| 53 | # Does Change-Id: already exist? if so, exit (no change). | ||
| 54 | if grep -i '^Change-Id:' "$MSG" >/dev/null | ||
| 55 | then | ||
| 56 | return | ||
| 57 | fi | ||
| 58 | |||
| 59 | id=`_gen_ChangeId` | ||
| 60 | T="$MSG.tmp.$$" | ||
| 61 | AWK=awk | ||
| 62 | if [ -x /usr/xpg4/bin/awk ]; then | ||
| 63 | # Solaris AWK is just too broken | ||
| 64 | AWK=/usr/xpg4/bin/awk | ||
| 65 | fi | ||
| 66 | |||
| 67 | # Get core.commentChar from git config or use default symbol | ||
| 68 | commentChar=`git config --get core.commentChar` | ||
| 69 | commentChar=${commentChar:-#} | ||
| 70 | |||
| 71 | # How this works: | ||
| 72 | # - parse the commit message as (textLine+ blankLine*)* | ||
| 73 | # - assume textLine+ to be a footer until proven otherwise | ||
| 74 | # - exception: the first block is not footer (as it is the title) | ||
| 75 | # - read textLine+ into a variable | ||
| 76 | # - then count blankLines | ||
| 77 | # - once the next textLine appears, print textLine+ blankLine* as these | ||
| 78 | # aren't footer | ||
| 79 | # - in END, the last textLine+ block is available for footer parsing | ||
| 80 | $AWK ' | ||
| 81 | BEGIN { | ||
| 82 | # while we start with the assumption that textLine+ | ||
| 83 | # is a footer, the first block is not. | ||
| 84 | isFooter = 0 | ||
| 85 | footerComment = 0 | ||
| 86 | blankLines = 0 | ||
| 87 | } | ||
| 88 | |||
| 89 | # Skip lines starting with commentChar without any spaces before it. | ||
| 90 | /^'"$commentChar"'/ { next } | ||
| 91 | |||
| 92 | # Skip the line starting with the diff command and everything after it, | ||
| 93 | # up to the end of the file, assuming it is only patch data. | ||
| 94 | # If more than one line before the diff was empty, strip all but one. | ||
| 95 | /^diff --git / { | ||
| 96 | blankLines = 0 | ||
| 97 | while (getline) { } | ||
| 98 | next | ||
| 99 | } | ||
| 100 | |||
| 101 | # Count blank lines outside footer comments | ||
| 102 | /^$/ && (footerComment == 0) { | ||
| 103 | blankLines++ | ||
| 104 | next | ||
| 105 | } | ||
| 106 | |||
| 107 | # Catch footer comment | ||
| 108 | /^\[[a-zA-Z0-9-]+:/ && (isFooter == 1) { | ||
| 109 | footerComment = 1 | ||
| 110 | } | ||
| 111 | |||
| 112 | /]$/ && (footerComment == 1) { | ||
| 113 | footerComment = 2 | ||
| 114 | } | ||
| 115 | |||
| 116 | # We have a non-blank line after blank lines. Handle this. | ||
| 117 | (blankLines > 0) { | ||
| 118 | print lines | ||
| 119 | for (i = 0; i < blankLines; i++) { | ||
| 120 | print "" | ||
| 121 | } | ||
| 122 | |||
| 123 | lines = "" | ||
| 124 | blankLines = 0 | ||
| 125 | isFooter = 1 | ||
| 126 | footerComment = 0 | ||
| 127 | } | ||
| 128 | |||
| 129 | # Detect that the current block is not the footer | ||
| 130 | (footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/ || /^[a-zA-Z0-9-]+:\/\//) { | ||
| 131 | isFooter = 0 | ||
| 132 | } | ||
| 133 | |||
| 134 | { | ||
| 135 | # We need this information about the current last comment line | ||
| 136 | if (footerComment == 2) { | ||
| 137 | footerComment = 0 | ||
| 138 | } | ||
| 139 | if (lines != "") { | ||
| 140 | lines = lines "\n"; | ||
| 141 | } | ||
| 142 | lines = lines $0 | ||
| 143 | } | ||
| 144 | |||
| 145 | # Footer handling: | ||
| 146 | # If the last block is considered a footer, splice in the Change-Id at the | ||
| 147 | # right place. | ||
| 148 | # Look for the right place to inject Change-Id by considering | ||
| 149 | # CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first, | ||
| 150 | # then Change-Id, then everything else (eg. Signed-off-by:). | ||
| 151 | # | ||
| 152 | # Otherwise just print the last block, a new line and the Change-Id as a | ||
| 153 | # block of its own. | ||
| 154 | END { | ||
| 155 | unprinted = 1 | ||
| 156 | if (isFooter == 0) { | ||
| 157 | print lines "\n" | ||
| 158 | lines = "" | ||
| 159 | } | ||
| 160 | changeIdAfter = "^(" tolower("'"$CHANGE_ID_AFTER"'") "):" | ||
| 161 | numlines = split(lines, footer, "\n") | ||
| 162 | for (line = 1; line <= numlines; line++) { | ||
| 163 | if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) { | ||
| 164 | unprinted = 0 | ||
| 165 | print "Change-Id: I'"$id"'" | ||
| 166 | } | ||
| 167 | print footer[line] | ||
| 168 | } | ||
| 169 | if (unprinted) { | ||
| 170 | print "Change-Id: I'"$id"'" | ||
| 171 | } | ||
| 172 | }' "$MSG" > "$T" && mv "$T" "$MSG" || rm -f "$T" | ||
| 173 | } | ||
| 174 | _gen_ChangeIdInput() { | ||
| 175 | echo "tree `git write-tree`" | ||
| 176 | if parent=`git rev-parse "HEAD^0" 2>/dev/null` | ||
| 177 | then | ||
| 178 | echo "parent $parent" | ||
| 179 | fi | ||
| 180 | echo "author `git var GIT_AUTHOR_IDENT`" | ||
| 181 | echo "committer `git var GIT_COMMITTER_IDENT`" | ||
| 182 | echo | ||
| 183 | printf '%s' "$clean_message" | ||
| 184 | } | ||
| 185 | _gen_ChangeId() { | ||
| 186 | _gen_ChangeIdInput | | ||
| 187 | git hash-object -t commit --stdin | ||
| 188 | } | ||
| 189 | |||
| 190 | 19 | ||
| 191 | add_ChangeId | 20 | # avoid [[ which is not POSIX sh. |
| 21 | if test "$#" != 1 ; then | ||
| 22 | echo "$0 requires an argument." | ||
| 23 | exit 1 | ||
| 24 | fi | ||
| 25 | |||
| 26 | if test ! -f "$1" ; then | ||
| 27 | echo "file does not exist: $1" | ||
| 28 | exit 1 | ||
| 29 | fi | ||
| 30 | |||
| 31 | # Do not create a change id if requested | ||
| 32 | if test "false" = "`git config --bool --get gerrit.createChangeId`" ; then | ||
| 33 | exit 0 | ||
| 34 | fi | ||
| 35 | |||
| 36 | # $RANDOM will be undefined if not using bash, so don't use set -u | ||
| 37 | random=$( (whoami ; hostname ; date; cat $1 ; echo $RANDOM) | git hash-object --stdin) | ||
| 38 | dest="$1.tmp.${random}" | ||
| 39 | |||
| 40 | trap 'rm -f "${dest}"' EXIT | ||
| 41 | |||
| 42 | if ! git stripspace --strip-comments < "$1" > "${dest}" ; then | ||
| 43 | echo "cannot strip comments from $1" | ||
| 44 | exit 1 | ||
| 45 | fi | ||
| 46 | |||
| 47 | if test ! -s "${dest}" ; then | ||
| 48 | echo "file is empty: $1" | ||
| 49 | exit 1 | ||
| 50 | fi | ||
| 51 | |||
| 52 | # Avoid the --in-place option which only appeared in Git 2.8 | ||
| 53 | # Avoid the --if-exists option which only appeared in Git 2.15 | ||
| 54 | if ! git -c trailer.ifexists=doNothing interpret-trailers \ | ||
| 55 | --trailer "Change-Id: I${random}" < "$1" > "${dest}" ; then | ||
| 56 | echo "cannot insert change-id line in $1" | ||
| 57 | exit 1 | ||
| 58 | fi | ||
| 59 | |||
| 60 | if ! mv "${dest}" "$1" ; then | ||
| 61 | echo "cannot mv ${dest} to $1" | ||
| 62 | exit 1 | ||
| 63 | fi | ||
