Browse Source

Meta: Add commit linting commit-hook

master
Riyyi 2 years ago
parent
commit
d39fd8d8e7
  1. 64
      script/lint-commit.sh
  2. 40
      script/pre-commit.sh

64
script/lint-commit.sh

@ -0,0 +1,64 @@
#!/bin/sh
# Lint commit message
# Depends: git
# ------------------------------------------
error() {
b="$(tput bold)"
red="$(tput setf 4)"
n="$(tput sgr0)"
echo "${b}${red}Error:${n} $1" >&2
exit 1
}
if [ ! -d ".git" ]; then
error "please run this script from the project root"
fi
# The file containing the commit message is passed as the first argument
file="$1"
message="$(cat "$file")"
newline="$(printf '\x0D')"
if grep -Uq "$newline" "$file"; then
error "commit message contains CRLF line breaks (only unix-style LF linebreaks are allowed)"
fi
lineNumber=0
echo "$message" | while read -r line; do
lineNumber=$((lineNumber + 1))
lineLength=${#line}
# Ignore comment lines
if echo "$line" | awk '$0 !~ /^#.*/ { exit 1 }'; then continue; fi
# Ignore overlong 'fixup!' commit descriptions
if echo "$line" | awk '$0 !~ /^fixup! .*/ { exit 1 }'; then continue; fi
if [ "$lineNumber" -eq 2 ] && [ "$lineLength" -ne 0 ]; then
error "empty line between commit title and body is missing"
fi
categoryPattern="^\S.*?\S: .+"
if [ $lineNumber -eq 1 ] && (echo "$line" | grep -Evq "$categoryPattern"); then
error "missing category in commit title (if this is a fix up of a previous commit, it should be squashed)"
fi
titleCasePattern="^\S.*?: [A-Z0-9]"
if [ $lineNumber -eq 1 ] && (echo "$line" | grep -Evq "$titleCasePattern"); then
error "first word of commit after the subsystem is not capitalized"
fi
if [ $lineNumber -eq 1 ] && (echo "$line" | awk '$0 !~ /\.$/ { exit 1 }' ); then
error "commit title ends in a period"
fi
urlPattern="([a-z]+:\/\/)?(([a-zA-Z0-9_]|-)+\.)+[a-z]{2,}(:\d+)?([a-zA-Z_0-9@:%\+.~\?&\/=]|-)+"
if [ "$lineLength" -gt 72 ] && (echo "$line" | grep -Evq "$urlPattern"); then
error "commit message lines are too long (maximum allowed is 72 characters)"
fi
done
exit 0

40
script/pre-commit.sh

@ -40,33 +40,37 @@ fi
# Get the path from the project root to the script # Get the path from the project root to the script
subDir="$(dirname -- "$0")" subDir="$(dirname -- "$0")"
hooks=" create() {
lint-ci.sh file="$1"
" if ! test -f "$file"; then
touch "$file"
chmod +x "$file"
echo "#!/bin/sh" > "$file"
fi
}
install() { install() {
echo "Installing pre-commit hooks" echo "Installing commit hooks"
preCommit=".git/hooks/pre-commit" preCommit=".git/hooks/pre-commit"
if ! test -f "$preCommit"; then create "$preCommit"
touch "$preCommit" sed -Ei "/lint-ci.sh/d" "$preCommit"
chmod +x "$preCommit" sed -Ei "\$ a $subDir/lint-ci.sh" "$preCommit"
echo "#!/bin/sh" > "$preCommit"
fi commitMsg=".git/hooks/commit-msg"
create "$commitMsg"
for hook in $hooks; do sed -Ei "/lint-commit.sh/d" "$commitMsg"
sed -Ei "/$hook/d" "$preCommit" sed -Ei "\$ a $subDir/lint-commit.sh" "$commitMsg"
sed -Ei "\$ a $subDir/$hook" "$preCommit"
done
} }
remove() { remove() {
echo "Removing pre-commit hooks" echo "Removing commit hooks"
preCommit=".git/hooks/pre-commit" preCommit=".git/hooks/pre-commit"
for hook in $hooks; do sed -Ei "/lint-ci.sh/d" "$preCommit"
sed -Ei "/$hook/d" "$preCommit"
done commitMsg=".git/hooks/commit-msg"
sed -Ei "/lint-commit.sh/d" "$commitMsg"
} }
# Command handling # Command handling

Loading…
Cancel
Save