Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions scripts/commit-msg.hook
Original file line number Diff line number Diff line change
Expand Up @@ -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
# ------------------------------------------------------------------------------
Expand All @@ -282,16 +290,29 @@ 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
if [[ $candidate =~ \.(c|h)$ ]]; then
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
Expand Down
3 changes: 3 additions & 0 deletions scripts/install-git-hooks
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 40 additions & 0 deletions scripts/prepare-commit-msg.hook
Original file line number Diff line number Diff line change
@@ -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