diff --git a/hook.sh b/hook.sh index 0cc1bc5..a482679 100755 --- a/hook.sh +++ b/hook.sh @@ -36,6 +36,88 @@ set_colors() { fi } +# +# Build regex for detecting commit trailers +# + +build_commit_trailer_regex() { + local -a keys specials standalones trailers + local _ each key seperators + seperators=$(git config --get trailer.separators || echo ':') + trailers=( + 'Acked-by' 'Bug' 'CC' + 'Change-Id' 'Closes' 'Closes-Bug' + 'Co-Authored-By' 'Implements' 'Partial-Bug' + 'Related-Bug' 'Reported-by' 'Reviewed-by' + 'Signed-off-by' 'Suggested-by' 'Tested-by' + 'Thanks' + ) + standalones=( + '(Doc|Upgrade|Security)Impact' + "Git-Dch[$seperators] (Ignore|Short|Full)" + ) + + # read custom trailers + while read -r _ key;do + for each in "${trailers[@]}" "${specials[@]}";do + test "$key" = "$each" && continue 2 + done + if [[ $key =~ [$seperators]$ ]];then + specials+=("$key") + else + trailers+=("$key") + fi + done < <(git config --get-regexp 'trailer.*.key') + + # read custom trailer keys + while IFS=. read -r _ key _;do + for each in "${keys[@]}";do + test "$key" = "$each" && continue 2 + done + keys+=("$key") + done < <(git config --get-regexp 'trailer.*.key') + + # start + TRAILER_REGEX='^(' + + # trailers + if ((${#trailers[@]}>0));then + TRAILER_REGEX+='((' + for each in "${trailers[@]}";do + TRAILER_REGEX+="$each|" + done + TRAILER_REGEX="${TRAILER_REGEX%|*})[$seperators][[:blank:]]*)" + fi + if ((${#standalones[@]}>0));then + TRAILER_REGEX+='|((' + for each in "${standalones[@]}";do + TRAILER_REGEX+="$each|" + done + TRAILER_REGEX="${TRAILER_REGEX%|*})$)" + fi + + # specials + if ((${#specials[@]}>0));then + TRAILER_REGEX+='|(' + for each in "${specials[@]}";do + TRAILER_REGEX+="$each|" + done + TRAILER_REGEX="${TRAILER_REGEX%|*})" + fi + + # keys + if ((${#keys[@]}>0));then + TRAILER_REGEX+='|((' + for each in "${keys[@]}";do + TRAILER_REGEX+="$each|" + done + TRAILER_REGEX="${TRAILER_REGEX%|*})[${seperators:1:1}[:blank:]])" + fi + + # end + TRAILER_REGEX+=")" +} + # # Set the hook editor, using the same approach as git. # @@ -242,7 +324,7 @@ validate_commit_message() { for i in "${!COMMIT_MSG_LINES[@]}"; do LINE_NUMBER=$((i+1)) - test "${#COMMIT_MSG_LINES[$i]}" -le 72 || [[ ${COMMIT_MSG_LINES[$i]} =~ $URL_REGEX ]] + test "${#COMMIT_MSG_LINES[$i]}" -le 72 || [[ ${COMMIT_MSG_LINES[$i]} =~ $URL_REGEX ]] || [[ ${COMMIT_MSG_LINES[$i]} =~ $TRAILER_REGEX ]] test $? -eq 0 || add_warning $LINE_NUMBER "Wrap the body at 72 characters (${#COMMIT_MSG_LINES[$i]} chars)" done @@ -273,6 +355,8 @@ set_colors set_editor +build_commit_trailer_regex + if tty >/dev/null 2>&1; then TTY=$(tty) else diff --git a/test/test_helper.bash b/test/test_helper.bash index cab7c52..f7dccaf 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -20,6 +20,7 @@ setup() { git -c "init.templatedir=$TMP_DIRECTORY/templates" init git config user.email "test@git-good-commit" git config user.name "Git Good Commit Tests" + git config core.hooksPath '.git/hooks' echo "Foo bar" > my_file git add my_file mkdir -p .git/hooks diff --git a/test/validation.bats b/test/validation.bats index 0b6600e..7f350a2 100644 --- a/test/validation.bats +++ b/test/validation.bats @@ -95,6 +95,31 @@ EOF assert_success } + +@test "validation: auto generated trailers does not show warnings" { + echo "n" > $FAKE_TTY + run git commit -m "$(cat < +Acked-by: Jane Doe +Reference-to: f000e67 (Merge pull request #2 from tommarshall/ignore-trailing-whitespace, 2016-09-29) +See-also: f000e679cfe3ac (Merge pull request #2 from tommarshall/ignore-trailing-whitespace) +EOF +)" + + assert_success +} # 1. Separate subject from body with a blank line # ------------------------------------------------------------------------------