#!/bin/bash # # A hook script to check the commit log message to ensure that it has # a well-formed commit summary and body, a valid Signed-off-by: line, # and a Gerrit Change-Id: line (added automatically if missing). # # 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. # # Should be installed as .git/hooks/commit-msg. # ORIGINAL="$1" REVISED="$(mktemp "$1.XXXXXX")" SIGNOFF="Signed-off-by:" CHANGEID="Change-Id:" WIDTH_SUM=64 WIDTH_REG=70 # Check for, and add if missing, a unique Change-Id new_changeid() { { git var GIT_AUTHOR_IDENT git var GIT_COMMITTER_IDENT git write-tree git rev-parse HEAD 2>/dev/null grep -v "$SIGNOFF" "$ORIGINAL" | git stripspace -s } | git hash-object --stdin } usage() { [ "$LINE" ] && echo "error:$NUM: $LINE" 1>&2 && echo "" 1>&2 cat 1>&2 <<- EOF Commit message $1 $2 See http://wiki.whamcloud.com/display/PUB/Submitting+Changes for full details. An example valid commit comment is: LU-nnn component: short description of change under 64 columns A more detailed explanation. This can be as detailed as you'd like. Please explain both what problem was solved and a good high-level description of how it was solved. Wrap at $WIDTH_REG columns or less. $SIGNOFF Your Real Name $CHANGEID Ixxxx(added automatically if missing)xxxx EOF exit 1 } export HAS_SIGNOFF=false export HAS_SUMMARY=false export HAS_BLANK=false export HAS_COMMENTS=false export HAS_DIFF=false grep -q "^$CHANGEID" "$ORIGINAL" && HAS_CHANGEID=true || HAS_CHANGEID=false export LINE="" export NUM=1 IFS="" while read LINE; do WIDTH=$(($(echo $LINE | wc -c) - 1)) # -1 for end-of-line character case "$LINE" in $SIGNOFF*) $HAS_SUMMARY || usage "missing summary before $SIGNOFF." $HAS_BLANK || usage "missing blank line before $SIGNOFF." # Signed-off-by: First Last GOOD=$(echo "$LINE" | grep "^$SIGNOFF .* .* <.*@[^.]*\..*>") [ -z "$GOOD" ] && usage "missing valid commit summary line to show" \ "agreement with code submission requirements at" HAS_SIGNOFF=true echo $LINE $HAS_CHANGEID || echo "$CHANGEID I$(new_changeid)" ;; $CHANGEID*) $HAS_SUMMARY || usage "missing summary before $CHANGEID line." $HAS_BLANK || usage "missing blank line before $CHANGEID line." # Change-Id: I762ab50568f25527176ae54e92c446cf06112097 GOOD=$(echo "$LINE" | grep "^$CHANGEID I[0-9a-fA-F]\{40\}") [ -z "$GOOD" ] && usage "missing valid $CHANGEID line for Gerrit tracking" HAS_CHANGEID=true echo $LINE ;; "") [ $HAS_SUMMARY -a $NUM -eq 2 ] && HAS_BLANK=true echo $LINE ;; diff*|index*) # beginning of uncommented diffstat from "commit -v" # diff --git a/build/commit-msg b/build/commit-msg # index 80a3442..acb4c50 100755 DIFF=$(echo "$LINE" | grep -- "^diff --git a/") [ "$DIFF" ] && HAS_DIFF=true && continue INDEX=$(echo "$LINE" | grep -- "^index [0-9a-fA-F]\{6,\}\.\.") [ $HAS_DIFF -a "$INDEX" ] && break || HAS_DIFF=false ;; \#*) HAS_COMMENTS=true continue ;; *) if [ $NUM -eq 1 ]; then FMT="^[A-Z]\{2,5\}-[0-9]\{1,5\} [-a-z0-9]\{2,9\}: " GOOD=$(echo "$LINE" | grep "$FMT") [ $WIDTH -gt $WIDTH_SUM ] && usage "summary longer than $WIDTH_SUM columns." if [ -z "$GOOD" ]; then FMT="^[A-Z]\{2,5\}-[0-9]\{1,5\} " NO_SUBSYS=$(echo "$LINE" | grep "$FMT") [ "$NO_SUBSYS" ] && usage "has no subsys: in commit summary" usage "missing valid commit summary line." fi HAS_SUMMARY=true elif [ $WIDTH -gt $WIDTH_REG ]; then usage "has lines longer than $WIDTH_REG columns." fi HAS_DIFF=false echo $LINE ;; esac NUM=$((NUM + 1)) done < "$ORIGINAL" > "$REVISED" [ $NUM -eq 1 ] && exit 1 # empty file LINE="" $HAS_SUMMARY || usage "missing commit summary line." $HAS_SIGNOFF || usage "missing $SIGNOFF line." $HAS_CHANGEID && rm "$REVISED" || mv "$REVISED" "$ORIGINAL"