diff --git a/extras/scripts/commit-msg b/extras/scripts/commit-msg index 81edbe8c91aeaa3816d47cc127319f271414506c..2e1040ae59a913b7db63ccf1b02a0d5fc47dbe6a 100755 --- a/extras/scripts/commit-msg +++ b/extras/scripts/commit-msg @@ -1,7 +1,7 @@ #!/bin/sh -# From Gerrit Code Review 2.11.3 +# From Gerrit Code Review 3.6.1 # -# Part of Gerrit Code Review (http://code.google.com/p/gerrit/) +# Part of Gerrit Code Review (https://www.gerritcodereview.com/) # # Copyright (C) 2009 The Android Open Source Project # @@ -16,166 +16,66 @@ # 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. -# - -unset GREP_OPTIONS - -CHANGE_ID_AFTER="Bug|Issue" -MSG="$1" - -# 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 +set -u + +# avoid [[ which is not POSIX sh. +if test "$#" != 1 ; then + echo "$0 requires an argument." + exit 1 +fi + +if test ! -f "$1" ; then + echo "file does not exist: $1" + exit 1 +fi + +# Do not create a change id if requested +if test "false" = "$(git config --bool --get gerrit.createChangeId)" ; then + exit 0 +fi + +if git rev-parse --verify HEAD >/dev/null 2>&1; then + refhash="$(git rev-parse HEAD)" +else + refhash="$(git hash-object -t tree /dev/null)" +fi + +random=$({ git var GIT_COMMITTER_IDENT ; echo "$refhash" ; cat "$1"; } | git hash-object --stdin) +dest="$1.tmp.${random}" + +trap 'rm -f "${dest}"' EXIT + +if ! git stripspace --strip-comments < "$1" > "${dest}" ; then + echo "cannot strip comments from $1" + exit 1 +fi + +if test ! -s "${dest}" ; then + echo "file is empty: $1" + exit 1 +fi + +reviewurl="$(git config --get gerrit.reviewUrl)" +if test -n "${reviewurl}" ; then + if ! git interpret-trailers --parse < "$1" | grep -q '^Link:.*/id/I[0-9a-f]\{40\}$' ; then + if ! git interpret-trailers \ + --trailer "Link: ${reviewurl%/}/id/I${random}" < "$1" > "${dest}" ; then + echo "cannot insert link footer in $1" + exit 1 + fi + fi +else + # Avoid the --in-place option which only appeared in Git 2.8 + # Avoid the --if-exists option which only appeared in Git 2.15 + if ! git -c trailer.ifexists=doNothing interpret-trailers \ + --trailer "Change-Id: I${random}" < "$1" > "${dest}" ; then + echo "cannot insert change-id line in $1" + exit 1 + fi +fi + +if ! mv "${dest}" "$1" ; then + echo "cannot mv ${dest} to $1" + exit 1 +fi