From 2cb046bae71d38bf075285d177ab2f80045a5424 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Wed, 19 Oct 2011 14:24:56 -0600 Subject: [PATCH] LU-553 build: Lustre style commit hooks for Git Adds recommended commit hooks for Lustre commit messages, that can/should be installed into lustre/.git/hooks for all Lustre trees. prepare-commit-msg: adds the output of checkpatch.pl as a comment to the commit message, to "soft" validate the new patch is matching the Lustre coding style. It doesn't check 100% of the Lustre coding style, but at least finds most of the obvious errors so that they can be fixed locally before any manual inspection time is spent on the patch. commit-msg: verifies the format of the commit message (somewhat). Checks that there is a valid-looking Signed-off-by: line. Adds the Gerrit Change-Id: line for change tracking, or validates that the existing Change-Id: line is well formed. Signed-off-by: Andreas Dilger Change-Id: I1fb7db8b29d01b6820a5468f59e4df55bb5fe00e Reviewed-on: http://review.whamcloud.com/1555 Reviewed-by: Johann Lombardi Tested-by: Hudson Tested-by: Maloo --- build/autoMakefile.am.toplevel | 3 +- build/commit-msg | 126 +++++++++++++++++++++++++++++++++++++++++ build/prepare-commit-msg | 33 +++++++++++ 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100755 build/commit-msg create mode 100755 build/prepare-commit-msg diff --git a/build/autoMakefile.am.toplevel b/build/autoMakefile.am.toplevel index 9405399..5e52245 100644 --- a/build/autoMakefile.am.toplevel +++ b/build/autoMakefile.am.toplevel @@ -108,7 +108,8 @@ EXTRA_DIST = @PACKAGE_TARNAME@.spec \ build/autoconf/lustre-build.m4 build/rdac_spec \ build/mptlinux.spec.patch build/patches \ build/funcs.sh build/find_linux_rpms build/exit_traps.sh \ - build/extract_patches build/checkpatch.pl + build/extract_patches build/checkpatch.pl build/commit-msg \ + build/prepare-commit-msg rpms-real: @PACKAGE_TARNAME@.spec dist Makefile CONFIGURE_ARGS=$$(echo $$(eval echo $(ac_configure_args)) | sed -re 's/--(en|dis)able-tests//'); \ diff --git a/build/commit-msg b/build/commit-msg new file mode 100755 index 0000000..a59a23a --- /dev/null +++ b/build/commit-msg @@ -0,0 +1,126 @@ +#!/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_SUMMARY=64 +WIDTH_REGULAR=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 lines at 70 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 + +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 + ;; + \#*) 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_SUMMARY ] && + usage "summary longer than 64 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_REGULAR ]; then + usage "has lines longer than 70 columns." + fi + 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" diff --git a/build/prepare-commit-msg b/build/prepare-commit-msg new file mode 100755 index 0000000..b84609e --- /dev/null +++ b/build/prepare-commit-msg @@ -0,0 +1,33 @@ +#!/bin/bash +# +# A Git hook script to prepare the commit log message. Install into +# lustre/.git/hooks/prepare-commit-msg to enable for Lustre commits. +# +# Called by git-commit with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# Commit hook to check the patch against the Lustre coding style. +# It adds any checkpatch warnings/errors as commit comments, which +# means that they can currently be ignored, but are at least visible. + +CHECKPATCH=build/checkpatch.pl +CHECKPATCH_OPTS="--no-signoff --no-tree --no-tabs" +[ -r "$CHECKPATCH" ] || exit 0 + +# If there are no comments in the commit, it is likely a rebase and +# this shouldn't be adding new comments, or they appear in the commit. +grep -q "^#" "$1" || exit 0 + +# Add a commented-out Signed-off-by: line. This shouldn't be added in an +# uncommented form, otherwise sanity checking for an emtpy commit fails. +SIGNOFF=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +grep -qs "^$SIGNOFF" "$1" || echo "# $SIGNOFF" >> "$1" + +# Add the checkpatch.pl output as comments, but don't cause a commit error +# yet, until there is more certainty that it is working correctly. +echo "" >> "$1" +echo "#" >> "$1" +git diff --cached | $CHECKPATCH $CHECKPATCH_OPTS - | sed -e 's/^/# /' >> "$1" -- 1.8.3.1