diff --git a/scripts/commit-msg.hook b/scripts/commit-msg.hook index 8a84f19e5..17629cc1a 100755 --- a/scripts/commit-msg.hook +++ b/scripts/commit-msg.hook @@ -249,13 +249,21 @@ validate_commit_message() { # 6. Wrap the body at 72 characters # ------------------------------------------------------------------------------ - URL_REGEX='^[[:blank:]]*(https?|ftp|file)://[-A-Za-z0-9\+&@#/%?=~_|!:,.;]*[-A-Za-z0-9\+&@#/%=~_|]' - - 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 $? -eq 0 || add_warning $LINE_NUMBER "Wrap the body at 72 characters (${#COMMIT_MSG_LINES[$i]} chars)" - done +URL_REGEX='^[[:blank:]]*(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]*[-A-Za-z0-9+&@#/%=~_|]' + +# Ensure the commit message lines are loaded into an array. +readarray -t COMMIT_MSG_LINES < "$COMMIT_MSG_FILE" + +for i in "${!COMMIT_MSG_LINES[@]}"; do + LINE="${COMMIT_MSG_LINES[$i]}" + # Trim leading and trailing whitespace. + TRIMMED_LINE="${LINE#"${LINE%%[![:space:]]*}"}" + TRIMMED_LINE="${TRIMMED_LINE%"${TRIMMED_LINE##*[![:space:]]}"}" + LINE_NUMBER=$((i+1)) + if [ "${#TRIMMED_LINE}" -gt 72 ] && ! [[ "$TRIMMED_LINE" =~ $URL_REGEX ]]; then + add_warning "$LINE_NUMBER" "Wrap the body at 72 characters (${#TRIMMED_LINE} chars)" + fi +done # 7. Use the body to explain what and why vs. how # ------------------------------------------------------------------------------ @@ -282,9 +290,11 @@ validate_commit_message() { word_count=$(echo "$COMMIT_SUBJECT_TO_PROCESS" | wc -w) test "$word_count" -gt 1 - test $? -eq 0 || add_warning 1 "Commit subject should contain more than one word (e.g. 'Update dependencies' instead of 'Update')" + test $? -eq 0 || add_warning 1 "Commit subject should contain more than one word. Summarize your changes" # 11. Avoid commit subject that simply states a file update (e.g. "Update console.c") + # ------------------------------------------------------------------------------ + if [[ $COMMIT_SUBJECT_TO_PROCESS =~ ^Update[[:space:]]+([^[:space:]]+)$ ]]; then candidate="${BASH_REMATCH[1]}" # Only warn if the candidate filename ends with .c or .h @@ -292,6 +302,17 @@ validate_commit_message() { add_warning 1 "Avoid using just a filename like '$candidate'. Provide a functional, meaningful description" fi fi + + # 12. Avoid abusive language in commit message content + # ------------------------------------------------------------------------------ + + FULL_COMMIT_MSG=$(sed '/^#/d;/^[[:space:]]*$/d' "$COMMIT_MSG_FILE") + # Extended list of abusive words (case-insensitive). + # Adjust the list as needed. + ABUSIVE_WORDS_REGEX='\b(fuck|fucking|dick|shit|bitch|asshole|cunt|motherfucker|damn|crap|dumbass|piss)\b' + if echo "$FULL_COMMIT_MSG" | grep -Eiq "$ABUSIVE_WORDS_REGEX"; then + add_warning 1 "Commit message contains inappropriate language. Avoid using abusive words" + fi } unset GREP_OPTIONS diff --git a/scripts/install-git-hooks b/scripts/install-git-hooks index 613c3dee4..7fec80501 100755 --- a/scripts/install-git-hooks +++ b/scripts/install-git-hooks @@ -68,6 +68,9 @@ chmod +x .git/hooks/commit-msg ln -sf ../../scripts/pre-push.hook .git/hooks/pre-push || exit 1 chmod +x .git/hooks/pre-push +ln -sf ../../scripts/prepare-commit-msg.hook .git/hooks/prepare-commit-msg || exit 1 +chmod +x .git/hooks/prepare-commit-msg + touch .git/hooks/applied || exit 1 echo diff --git a/scripts/prepare-commit-msg.hook b/scripts/prepare-commit-msg.hook new file mode 100755 index 000000000..44839edc0 --- /dev/null +++ b/scripts/prepare-commit-msg.hook @@ -0,0 +1,40 @@ +#!/bin/bash + +COMMIT_MSG_FILE="$1" + +# Only proceed if the commit message file is empty (ignoring comment or blank lines). +if grep -qE '^[^[:space:]#]' "$COMMIT_MSG_FILE"; then + exit 0 +fi + +# Define the inline message with commit guidelines. +INLINE_MSG=$(cat <<'EOF' +# 🎉Check the rules before writing commit messages. +# https://cbea.ms/git-commit/ +# +# Seven Rules for a Great Git Commit Message: +# 1. Separate subject from body with a blank line +# 2. Limit the subject line to 50 characters +# 3. Capitalize the subject line +# 4. Do not end the subject line with a period +# 5. Use the imperative mood in the subject line +# 6. Wrap the body at 72 characters +# 7. Use the body to explain what and why vs. how +# +# You may modify this commit message. +# To abort this commit, exit the editor without saving. +EOF +) + +# Write the inline guidelines into the commit message file. +echo > "$COMMIT_MSG_FILE" +echo -e "$INLINE_MSG" >> "$COMMIT_MSG_FILE" + +# Prompt the user to optionally abort the commit. +read -rp "Do you want to abort this commit? (y/N): " answer +if [[ "$answer" =~ ^[Yy]$ ]]; then + echo "Commit aborted by user." >&2 + exit 1 +fi + +exit 0