mirror of
https://github.com/simonmichael/hledger.git
synced 2024-12-25 19:31:44 +03:00
153 lines
5.0 KiB
Bash
Executable File
153 lines
5.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# commitlint [GITRANGE|FILE]
|
|
|
|
# Check unpushed commits, or commits in the specified range, or a
|
|
# commit message in FILE, for compliance with hledger's conventions
|
|
# (see https://hledger.org/COMMITS.html or the code below).
|
|
# If the argument contains - or .. or ^! it's a range, otherwise
|
|
# a file containing a proposed commit message.
|
|
# Run interactively, or symlink as .git/hooks/commit-msg to check
|
|
# your messages before commit.
|
|
#
|
|
# Examples:
|
|
# commitlint foo # commit message in ./foo
|
|
# commitlint HEAD^! # last commit
|
|
# commitlint d5d19f841^! # this commit
|
|
# commitlint -20 # last 20 commits
|
|
# commitlint master.. # commits in this branch
|
|
# commitlint 1.21..1.22 | grep -F [FAIL] # bad commits in 1.22 release cycle
|
|
# commitlint # unpushed commits
|
|
|
|
set -e
|
|
|
|
if [[ -n ${NO_COLOR+set} ]]
|
|
then
|
|
RED=""
|
|
GRN=""
|
|
NRM=""
|
|
else
|
|
RED="\033[31m"
|
|
GRN="\033[32m"
|
|
NRM="\033[0m"
|
|
fi
|
|
|
|
# checkcommit GITHASH - check this commit's message and print result
|
|
function checkcommit()
|
|
{
|
|
HASH=${1}
|
|
MSG=$(git log -1 "$HASH" --pretty=format:"%s%n%b")
|
|
checkmsg "$MSG"
|
|
}
|
|
|
|
# checkmsg MSG [GITHASH] - check this commit message and print result
|
|
function checkmsg()
|
|
{
|
|
MSG=${1}
|
|
HASH=${2}
|
|
if [[ -n $HASH ]]
|
|
then
|
|
HASH="$HASH "
|
|
fi
|
|
|
|
SUMMARY=$(echo "$MSG" | head -1)
|
|
FMT="%s%-60s %b${NRM}\n"
|
|
|
|
# Ignore certain boring commits, like a github merge commit
|
|
# or a temporary "git commit --fixup" commit.
|
|
if echo "$SUMMARY" | grep -qE '^(Merge|fixup!)'
|
|
then
|
|
# shellcheck disable=SC2059
|
|
printf "$FMT" "$HASH" "$SUMMARY" "[ignored]"
|
|
|
|
# Does the summary follow the conventions described in COMMITS.md ? Roughly:
|
|
# [;][feat|imp|fix[!]:] topic: Summary
|
|
#
|
|
# Some passing examples:
|
|
# feat: accounts: --types shows account types (#1820)
|
|
# imp!: journal: Remove deprecated account type code syntax from account directives.
|
|
# fix: types: Ensure auto postings can match against and be matched by type: queries.
|
|
# tools: commitlint: allow a git "fixup! " prefix
|
|
# doc: releasing: tweaks
|
|
#
|
|
# Some failing examples:
|
|
# Revert "imp: ui: accounts: also show declared accounts, even if unused"
|
|
# Update description of hledger-check-tagfiles.hs
|
|
# ; PR-template: Change comment syntax
|
|
# ; cabal.project: Drop compatibility comment
|
|
#
|
|
# At least one type/topic prefix is required. The first must be all word characters,
|
|
# others may contain commas/slashes/spaces.
|
|
# Spaces are allowed around the ; (and before the ! and :, though it's not preferred).
|
|
elif ! echo "$SUMMARY" | grep -qE '^( *[;!] *)?\w+ *!? *:( *\w[\w,/ ]* *:)*' # keep synced with COMMITS.md:
|
|
then
|
|
# shellcheck disable=SC2059
|
|
printf "$FMT" "$HASH" "$SUMMARY" "${RED}[FAIL]"
|
|
STATUS=1
|
|
|
|
# Looks like a good commit.
|
|
else
|
|
# shellcheck disable=SC2059
|
|
printf "$FMT" "$HASH" "$SUMMARY" "${GRN}[ok]"
|
|
fi
|
|
}
|
|
|
|
STATUS=
|
|
RANGE=${*:-"@{u}.."} # @{u} = upstream
|
|
|
|
if [[ $RANGE =~ (-|\.\.|\^!) ]]
|
|
then
|
|
HASHES=$(git log --abbrev-commit --pretty=format:%h "$RANGE")
|
|
for HASH in $HASHES; do checkcommit "$HASH"; done
|
|
else
|
|
MSG=$(cat "$1")
|
|
checkmsg "$MSG"
|
|
fi
|
|
|
|
if [[ -z $STATUS ]]
|
|
then
|
|
printf "" # "${GRN}Ok${NRM}\n"
|
|
else
|
|
# shellcheck disable=SC2059
|
|
printf "\n${RED}Commit(s) not in preferred style.${NRM}\n"
|
|
cat <<EOF
|
|
---------------------------------------------------------------------------
|
|
Commit messages should follow this format:
|
|
|
|
[;]type[!]: [topic:] summary
|
|
|
|
[Optional description, ready for release notes/changelog.]
|
|
|
|
Explanation:
|
|
|
|
The subject line should have a type: prefix. Common types:
|
|
feat imp fix - end-user changes (->release notes & changelogs)
|
|
cha pkg lib - packager/builder/lib-user changes (->changelogs)
|
|
dev doc test ci ref cln - developer changes (->just commit log, mostly)
|
|
|
|
It can additionally have a topic prefix (and optionally subtopics), such as:
|
|
bin examples install cli ui web print reg bal bs balcmds journal csv ...
|
|
(see https://hledger.org/CONTRIBUTING.html#open-issues -> COMPONENT)
|
|
Space, comma and slash are also tolerated inside topics for now. Eg:
|
|
imp: bs, cf, is: cli/doc: blah blah blah
|
|
|
|
Mention any related issues, usually parenthesised at end of summary: (#1234)
|
|
! indicates a breaking change.
|
|
; skips expensive CI tests.
|
|
|
|
These conventions are evolving. In practice, any type or topic will do.
|
|
Use your best judgement and we'll polish during code review.
|
|
More context: https://hledger.org/CONTRIBUTING.html#commit-messages
|
|
|
|
You can set up this script to check your commit messages locally:
|
|
1. before committing:
|
|
a. safer but must redo: cp tools/commitlint .git/hooks/commit-msg
|
|
b. more convenient: ln -s ../../tools/commitlint .git/hooks/commit-msg
|
|
2. before pushing: tools/commitlint && git push
|
|
---------------------------------------------------------------------------
|
|
EOF
|
|
|
|
fi
|
|
|
|
exit 0"$STATUS"
|