Skip to content

Commit b60587e

Browse files
committed
Add git hooks for Cloudberry Database development
For better development quality, we customize the Git hooks to remind developers to check their work. We use pre-commit, prepare-commit-msg, commit-msg, and pre-push hooks to trigger automatic checks when running `git commit` and `git push`.
1 parent 70ad653 commit b60587e

File tree

8 files changed

+269
-54
lines changed

8 files changed

+269
-54
lines changed

hooks/install

Lines changed: 0 additions & 6 deletions
This file was deleted.

hooks/pre-push

Lines changed: 0 additions & 47 deletions
This file was deleted.

.gitmessage renamed to src/tools/hooks/.gitmessage

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,4 @@ Add your commit body here
4444
#
4545
#
4646
#
47-
#
47+
#

src/tools/hooks/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
## Configure the Git hooks for local CloudberryDB development
2+
3+
Git hooks are scripts that run automatically every time a particular
4+
Git event occurs in a Git repository. We customize our CloudberryDB
5+
Git’s behavior by these hooks to check or remind us how to improve our
6+
code and commit.
7+
8+
## List of hooks
9+
10+
| Type | Description |
11+
|--|--|
12+
| `pre-commit` | This hook is to verify what is about to be committed and executed every time you run git commit before writing a commit message, including if the code has been properly indented and if has a trailing whitespace. |
13+
| `prepare-commit-msg` | This hook is called after the `pre-commit` hook to populate the text editor with a commit message template. |
14+
| `commit-msg` | This hook is to check the commit log message and called after the user enters a commit message. |
15+
| `pre-push` | This hook is to verify what is about to be pushed, and called by `git push` after it has checked the remote status, but before anything has been pushed. |
16+
17+
## Install
18+
19+
You can configure these Git hooks in one of the following three ways
20+
as you like:
21+
22+
* Run the command to configure the file path for Git hooks:
23+
24+
```
25+
# Run the command under src/tools/hooks dir
26+
27+
git config core.hooksPath $PWD
28+
```
29+
30+
* Or link the hook files to the `.git/hooks` relative files:
31+
32+
```
33+
# Run the command under src/tool/hooks dir
34+
35+
ln -sf ./pre-commit ../../../.git/hooks/pre-commit
36+
ln -sf ./prepare-commit-msg ../../../.git/hooks/prepare-commit-msg
37+
ln -sf ./commit-msg ../../../.git/hooks/commit-msg
38+
ln -sf ./pre-push ../../../.git/hooks/pre-push
39+
```
40+
41+
* Or you can copy these hooks to the `.git/hooks` directory directly.
42+
43+
> [!NOTE]
44+
> If you want to bypass these hooks, you can run the `git commit`/`git
45+
> push` command with `--no-verify` or `-n` option.
46+
47+
## Useful links
48+
49+
- [Git Hooks](https://git-scm.com/docs/githooks)

src/tools/hooks/commit-msg

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/bin/sh
2+
#
3+
# A hook script to check the commit log message. Called by "git commit" with
4+
# one argument, the name of the file that has the commit message. The hook
5+
# should exit with non-zero status after issuing an appropriate message if it
6+
# wants to stop the commit. The hook is allowed to edit the commit message
7+
# file.
8+
#
9+
# Define the color
10+
readonly reset=$(tput sgr0)
11+
readonly red=$(tput bold; tput setaf 1)
12+
readonly green=$(tput bold; tput setaf 2)
13+
14+
# Initialize exit code as 0
15+
exit_code=0
16+
17+
# Function to check if a string starts with a specific prefix
18+
startsWith() {
19+
case $1 in
20+
"$2"*) return 0;;
21+
*) return 1;;
22+
esac
23+
}
24+
25+
# Read the commit message from the commit-msg hook input
26+
commit_msg_file=$1
27+
commit_msg=$(cat "$commit_msg_file")
28+
29+
echo -n "Check if the commit message is written... "
30+
if [ -z "$commit_msg" ]; then
31+
echo -e "\n ${red}Error: Commit message is empty. Please write a commit message."
32+
exit_code=1
33+
else
34+
echo "${green}Done"
35+
fi
36+
echo "${reset}"
37+
38+
echo -n "Check the commit title format... "
39+
commit_title=$(echo "$commit_msg" | head -n 1)
40+
if [[ ! "$commit_title" =~ ^[A-Z] ]]; then
41+
echo -e "\n ${red}Error: Commit title must start with an uppercase letter!"
42+
exit_code=1
43+
elif [[ "$commit_title" =~ [^\x00-\x7F] ]]; then
44+
echo -e "\n ${red}Error: Commit title cannot contain fullwidth characters."
45+
exit_code=1
46+
elif [ ${#commit_title} -gt 50 ]; then
47+
echo -e "\n ${red}Error: Commit title length cannot exceeds 50 characters."
48+
exit_code=1
49+
else
50+
echo "${green}Done"
51+
fi
52+
echo "${reset}"
53+
54+
echo -n "Check the commit body... "
55+
commit_body=$(echo "$commit_msg" | sed -n '2,$p')
56+
while IFS= read -r line; do
57+
if [ ${#line} -gt 72 ]; then
58+
echo -e "\n ${red}Error: Commit body line length cannot exceed 72 characters."
59+
echo -e "\n ${red}For Vim editor, you can use `:set textwidth=72` to autowrap. Then you can input `:normal gqG` to apply the warp rule for existing body text."
60+
exit_code=1
61+
elif [[ "$line" =~ [^\x00-\x7F] ]]; then
62+
echo -e "\n ${red}Error: Commit body line cannot contain fullwidth characters."
63+
exit_code=1
64+
else
65+
echo "${green}Done"
66+
fi
67+
done
68+
echo "${reset}"
69+
70+
# Check the commit tailer and allow its length longer than 72
71+
commit_tailer=$(echo "$commit_msg" | tail -n 2)
72+
if startsWith "$commit_tailer" "See:" && [ ${#commit_tailer} -gt 72 ]; then
73+
exit ${exit_code}
74+
fi
75+
76+
# If any checks fail, exit the commit process.
77+
# If all checks pass, go with no exit.
78+
if [[ "${exit_code}" != 0 ]]; then
79+
echo "${red}---------------------------------------------------"
80+
echo "All Checks have been performed. Warnings/Errors happened!"
81+
echo "Update your commit message before running `git commit` again!"
82+
echo "---------------------------------------------------"
83+
exit ${exit_code}
84+
echo ${reset}
85+
else
86+
echo "${green}---------------------------------------------------"
87+
echo "All Checks have passed. Bingo!"
88+
echo "---------------------------------------------------"
89+
exit ${exit_code}
90+
echo ${reset}
91+
fi

src/tools/hooks/pre-commit

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/bin/sh
2+
#
3+
# A hook script to verify what is about to be committed. Called by
4+
# "git commit" with no arguments. The hook should exit with non-zero
5+
# status after issuing an appropriate message if it wants to stop the
6+
# commit.
7+
8+
readonly reset=$(tput sgr0)
9+
readonly red=$(tput bold; tput setaf 1)
10+
readonly green=$(tput bold; tput setaf 2)
11+
12+
exit_code=0
13+
14+
echo -n "Checking if new commits exits... "
15+
if git rev-parse --verify HEAD >/dev/null 2>&1
16+
then
17+
against=HEAD
18+
else
19+
# Initial commit: diff against an empty tree object
20+
against=$(git hash-object -t tree /dev/null)
21+
fi
22+
echo "${green}Done"
23+
echo "${reset}"
24+
25+
# The following script is copied from pre-commit.sample to avoid
26+
# non-ASCII filenames from being added to the repository.
27+
28+
echo -n "Running non-ASCII filenames check..."
29+
allownonascii=$(git config --type=bool hooks.allownonascii)
30+
exec 1>&2
31+
if [ "$allownonascii" != "true" ] &&
32+
test $(git diff --cached --name-only --diff-filter=A -z $against |
33+
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
34+
then
35+
cat <<\EOF
36+
${red}Error: Attempt to add a non-ASCII file name.
37+
This can cause problems if you want to work with people on other platforms.
38+
To be portable it is advisable to rename the file.
39+
If you know what you are doing you can disable this check using:
40+
git config hooks.allownonascii true
41+
EOF
42+
echo "${reset}"
43+
exit_code=1
44+
else
45+
echo "${green}Done"
46+
fi
47+
echo "${reset}"
48+
49+
# If there are whitespace errors, print the offending file names and fail.
50+
echo -n "Running whitespace checks... "
51+
exec git diff-index --check --cached $against --
52+
echo "${green}Done"
53+
echo "${reset}"
54+
55+
# This following hook is modified from PostgreSQL wiki, which is used
56+
# to check the changed code by pgindent. See the original link:
57+
# https://wiki.postgresql.org/wiki/Working_with_Git#Using_git_hooks
58+
59+
set -u
60+
: ${PGAUTOINDENT:=no}
61+
62+
branch=$(git rev-parse --abbrev-ref HEAD)
63+
files=$(git diff --cached --name-only --diff-filter=ACMR)
64+
65+
check_indent () {
66+
# no need to filter files - pgindent ignores everything that isn't a
67+
# .c or .h file
68+
src/tools/pgindent/pgindent --silent-diff $files && return 0
69+
exec 2>&1
70+
if [ "$PGAUTOINDENT" = yes ] ; then
71+
echo "Running pgindent on changed files... "
72+
src/tools/pgindent/pgindent $files
73+
echo "${red}Commit abandoned! Rerun git commit to adopt pgindent changes."
74+
else
75+
echo 'You need a pgindent run, e.g:'
76+
echo -n 'src/tools/pgindent/pgindent '
77+
echo '`git diff --name-only --diff-filter=ACMR`'
78+
fi
79+
exit_code=1
80+
}
81+
82+
# nothing to do if there are no files
83+
test -z "$files" && exit 0
84+
check_indent
85+
86+
if [[ "${exit_code}" != 0 ]]; then
87+
echo "${red}Please update your commits again per the errors.${reset}"
88+
fi
89+
exit ${exit_code}

src/tools/hooks/pre-push

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/bash
2+
# A hook for the reminder before pushing to the original repo.
3+
4+
remote="$1"
5+
url="$2"
6+
7+
z40=0000000000000000000000000000000000000000
8+
9+
function user_input_to_proceed() {
10+
read -p 'Proceed with push? (y/N): ' yesno </dev/tty
11+
case "$yesno" in
12+
y|Y|yes|Yes|YES) ;;
13+
*) echo "Aborting push" >&2; exit 1 ;;
14+
esac
15+
}
16+
17+
while read local_ref local_sha remote_ref remote_sha ; do
18+
if [ "$local_sha" = $z40 ] ; then
19+
# Handle delete
20+
continue
21+
fi
22+
if [ "$remote_sha" = $z40 ] ; then
23+
# New branch
24+
continue
25+
fi
26+
# Update to existing branch, examine new commits
27+
range="$remote_sha..$local_sha"
28+
29+
exit 0

src/tools/hooks/prepare-commit-msg

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/sh
2+
#
3+
# A hook script to prepare the commit log message. Called by "git commit" with
4+
# the name of the file that has the commit message, followed by the
5+
# description of the commit message's source. The hook's purpose is to edit
6+
# the commit message file. If the hook fails with a non-zero status, the
7+
# commit is aborted.
8+
#
9+
10+
cat ./src/tools/hooks/.gitmessage > $1

0 commit comments

Comments
 (0)