Skip to content

Commit b1b90f5

Browse files
committed
refactor(git): enhance author info retrieval with validation
- add constants for default email and author names - validate email format using regex and fallback if invalid - leverage utils get_env for centralized environment access Signed-off-by: mingcheng <mingcheng@apache.org>
1 parent 2fc5f4c commit b1b90f5

7 files changed

Lines changed: 149 additions & 176 deletions

File tree

.gitea/workflows/rust.yml

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

Cargo.lock

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ version = "2.0.1"
88
source = "registry+https://github.com/rust-lang/crates.io-index"
99
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
1010

11+
[[package]]
12+
name = "aho-corasick"
13+
version = "1.1.4"
14+
source = "registry+https://github.com/rust-lang/crates.io-index"
15+
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
16+
dependencies = [
17+
"memchr",
18+
]
19+
1120
[[package]]
1221
name = "aigitcommit"
1322
version = "1.6.5"
@@ -20,6 +29,7 @@ dependencies = [
2029
"cliclack",
2130
"git2",
2231
"log",
32+
"regex",
2333
"reqwest",
2434
"serde",
2535
"serde_json",
@@ -1754,6 +1764,35 @@ dependencies = [
17541764
"bitflags",
17551765
]
17561766

1767+
[[package]]
1768+
name = "regex"
1769+
version = "1.12.2"
1770+
source = "registry+https://github.com/rust-lang/crates.io-index"
1771+
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
1772+
dependencies = [
1773+
"aho-corasick",
1774+
"memchr",
1775+
"regex-automata",
1776+
"regex-syntax",
1777+
]
1778+
1779+
[[package]]
1780+
name = "regex-automata"
1781+
version = "0.4.13"
1782+
source = "registry+https://github.com/rust-lang/crates.io-index"
1783+
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
1784+
dependencies = [
1785+
"aho-corasick",
1786+
"memchr",
1787+
"regex-syntax",
1788+
]
1789+
1790+
[[package]]
1791+
name = "regex-syntax"
1792+
version = "0.8.8"
1793+
source = "registry+https://github.com/rust-lang/crates.io-index"
1794+
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
1795+
17571796
[[package]]
17581797
name = "reqwest"
17591798
version = "0.12.24"

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ tracing-subscriber = "0.3"
3636
arboard = "3.6"
3737
tabled = "0.20"
3838
cliclack = "0.3.6"
39+
regex = "1.12.2"
3940

4041
[[bin]]
4142
name = "aigitcommit"

README.md

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
![screenshots](./assets/screenshots.png)
88

9-
`AIGitCommit` is a command-line tool that generates meaningful, semantic commit messages from your staged Git changes using AI.
9+
`AIGitCommit` is a command-line tool that generates meaningful, semantic commit messages from your staged Git changes using AI.
1010

1111
It inspects your diffs, summarizes the intent of your changes, and produces clear, concise commit messages that follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification.
1212

@@ -83,18 +83,42 @@ Use `--yes` to skip interactive confirmations.
8383

8484
### Git hook
8585

86-
AIGitCommit ships a `hooks/prepare-commit-msg` hook you can copy into a repository's `.git/hooks/prepare-commit-msg` to automatically generate commit messages during `git commit`.
86+
AIGitCommit ships a `hooks/prepare-commit-msg` hook that pauses your commit workflow, looks at the staged diff, and pre-populates `COMMIT_EDITMSG` with an AI-generated summary. This lets you fine-tune the final message instead of writing it from scratch.
8787

88-
To install globally:
88+
**Prerequisites**
89+
- `aigitcommit` must be installed and discoverable on your `PATH`.
90+
- Required environment variables (`OPENAI_API_TOKEN`, `OPENAI_API_BASE`, etc.) should be configured in your shell before running `git commit`.
91+
92+
**Project-level installation**
93+
94+
Install the hook in the current repository only:
95+
96+
```bash
97+
cp hooks/prepare-commit-msg .git/hooks/prepare-commit-msg
98+
chmod +x .git/hooks/prepare-commit-msg
99+
```
100+
101+
After copying, stage some changes and run `git commit`. The hook prints progress messages, writes the suggested commit text, and drops you into your editor so you can adjust the result. To verify the hook without creating a new commit, try `git commit --amend` against a throwaway repository.
102+
103+
If you need to disable the hook for a single commit, use `git commit --no-verify`.
104+
105+
**Global installation**
106+
107+
Install once and reuse across repositories:
89108

90109
```bash
91110
mkdir -p ~/.git-hooks
92-
# copy the file from this project into ~/.git-hooks/prepare-commit-msg
111+
cp hooks/prepare-commit-msg ~/.git-hooks/prepare-commit-msg
93112
chmod +x ~/.git-hooks/prepare-commit-msg
94113
git config --global core.hooksPath ~/.git-hooks
95114
```
96115

97-
After installing the hook, `git commit` will run the hook and populate the commit message. Use `--no-verify` to bypass hooks when necessary.
116+
This approach lets every repository automatically pick up the hook as long as `core.hooksPath` remains set.
117+
118+
**Troubleshooting**
119+
- If the hook exits early with a warning about missing staged changes, make sure you have run `git add`.
120+
- A message about missing configuration usually means the OpenAI-related environment variables are not exported in your shell session.
121+
- Hook output is written to stderr; if you prefer a quieter experience, redirect or silence stderr in your Git configuration.
98122

99123
## Configuration
100124

@@ -114,9 +138,9 @@ After setting the environment variables, you can check if they are set correctly
114138
aigitcommit --check-env
115139
```
116140

117-
This will print the current configuration and verify that the required variables are set.
141+
This will print the current configuration and verify that the required variables are set.
118142

119-
Then you can run
143+
Then you can run
120144

121145
```bash
122146
aigitcommit --check-model

hooks/prepare-commit-msg

Lines changed: 49 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,58 @@
11
#!/bin/sh
22

3-
# This script is a Git hook that generates a commit message using the `aigitcommit` command.
4-
# It is triggered before the commit message editor is opened.
5-
# Usage: Place this script in the `.git/hooks/` directory of your repository and make it executable.
6-
COMMIT_MSG_FILE=$1
7-
COMMIT_MSG_TYPE=$2
8-
REPO_ROOT=$(git rev-parse --show-toplevel)
9-
10-
# Check the repository root directory is valid
11-
# The `git rev-parse --show-toplevel` command returns the absolute path to the root of the repository
12-
# If the command fails, it means we are not in a Git repository
13-
if [ ! -d "$REPO_ROOT" ]; then
14-
echo "Error: Repository root not found."
3+
set -eu
4+
5+
log() {
6+
printf '%s\n' "$1" >&2
7+
}
8+
9+
COMMIT_MSG_FILE=${1:-}
10+
COMMIT_MSG_TYPE=${2:-}
11+
12+
if [ -z "$COMMIT_MSG_FILE" ] || [ ! -f "$COMMIT_MSG_FILE" ]; then
13+
log "Error: commit message file missing."
1514
exit 1
1615
fi
1716

18-
# Check if aigitcommit is installed
19-
if ! type aigitcommit >/dev/null 2>&1; then
20-
echo "Error: aigitcommit is not installed. Please install it first."
21-
exit 0
17+
if ! REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null); then
18+
log "Error: repository root not found."
19+
exit 1
2220
fi
2321

24-
# Only proceed if this is a regular commit (message type is empty or "message")
25-
if [ "$COMMIT_MSG_TYPE" = "message" ] || [ -z "$COMMIT_MSG_TYPE" ]; then
26-
# Get only the diff of what has already been staged
27-
GIT_DIFF_OUTPUT=$(git diff --cached)
28-
29-
# Check if there are any staged changes to commit
30-
if [ -z "$GIT_DIFF_OUTPUT" ]; then
31-
echo "No staged changes detected. Aborting."
32-
exit 1
33-
fi
34-
35-
# Generate a temporary file for the commit message
36-
TEMP_FILE=$(mktemp)
37-
38-
# Execute aigitcommit to generate the commit message
39-
# Redirecting output to the commit message file
40-
# and suppressing any error messages
41-
# The --save option is used to save the generated commit message to the file
42-
echo "Generating commit message by using AIGitCommit..."
43-
echo "This may take a few seconds..."
44-
aigitcommit $REPO_ROOT --save $TEMP_FILE >/dev/null 2>&1
45-
if [ $? -ne 0 ]; then
46-
echo "Error: aigitcommit failed to generate commit message."
47-
rm -f $TEMP_FILE
48-
exit 1
49-
fi
50-
51-
# Append the generated commit message to the temporary file
52-
cat $COMMIT_MSG_FILE >>$TEMP_FILE && mv -f $TEMP_FILE $COMMIT_MSG_FILE
53-
else
54-
# For other commit types (merge, template, etc.), exit without doing anything
22+
if ! command -v aigitcommit >/dev/null 2>&1; then
23+
log "Warning: aigitcommit not installed; skipping hook."
5524
exit 0
5625
fi
26+
27+
case "$COMMIT_MSG_TYPE" in
28+
""|"message") ;;
29+
*) exit 0 ;;
30+
esac
31+
32+
if git diff --cached --quiet --exit-code; then
33+
log "Warning: no staged changes detected; aborting commit."
34+
exit 1
35+
fi
36+
37+
TEMP_FILE=$(mktemp) || exit 1
38+
39+
cleanup() {
40+
rm -f "$TEMP_FILE"
41+
}
42+
43+
trap cleanup EXIT INT TERM
44+
45+
log "Generating commit message with aigitcommit..."
46+
47+
if ! aigitcommit "$REPO_ROOT" --save "$TEMP_FILE" >/dev/null 2>&1; then
48+
log "Error: aigitcommit failed to generate commit message."
49+
exit 1
50+
fi
51+
52+
if [ -s "$COMMIT_MSG_FILE" ]; then
53+
printf '\n' >>"$TEMP_FILE"
54+
cat "$COMMIT_MSG_FILE" >>"$TEMP_FILE"
55+
fi
56+
57+
mv -f "$TEMP_FILE" "$COMMIT_MSG_FILE"
58+
trap - EXIT INT TERM

src/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
* Last Modified: 2025-03-05 00:25:24
1313
*/
1414

15-
use clap::Parser;
1615
use crate::built_info;
16+
use clap::Parser;
1717

1818
#[derive(Debug, Parser)]
1919
#[command(name = built_info::PKG_NAME, about = built_info::PKG_DESCRIPTION, version = built_info::PKG_VERSION, author = built_info::PKG_AUTHORS)]

0 commit comments

Comments
 (0)