docs: update readme with new installation methods and cli options
This commit is contained in:
234
README.md
234
README.md
@@ -4,6 +4,8 @@ English | [中文文档](README_zh.md)
|
|||||||
|
|
||||||
A powerful AI-powered Git assistant for generating conventional commits, tags, and changelogs. Manage multiple Git profiles for different work contexts.
|
A powerful AI-powered Git assistant for generating conventional commits, tags, and changelogs. Manage multiple Git profiles for different work contexts.
|
||||||
|
|
||||||
|
[Still in early development, some features may not be complete. Feedback and contributions are welcome.]
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
@@ -19,9 +21,19 @@ A powerful AI-powered Git assistant for generating conventional commits, tags, a
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
### Cargo Install
|
||||||
|
|
||||||
|
The cargo-installed version may temporarily lag behind the source code progress.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/yourusername/quicommit.git
|
cargo install quicommit
|
||||||
cd quicommit
|
```
|
||||||
|
|
||||||
|
### Install from Source
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.lyz.one/SidneyZhang/QuiCommit.git
|
||||||
|
cd QuiCommit
|
||||||
cargo build --release
|
cargo build --release
|
||||||
cargo install --path .
|
cargo install --path .
|
||||||
```
|
```
|
||||||
@@ -50,6 +62,12 @@ quicommit commit -a
|
|||||||
|
|
||||||
# Skip confirmation
|
# Skip confirmation
|
||||||
quicommit commit --yes
|
quicommit commit --yes
|
||||||
|
|
||||||
|
# Use date-based commit message
|
||||||
|
quicommit commit --date
|
||||||
|
|
||||||
|
# Push after committing
|
||||||
|
quicommit commit --push
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create Tag
|
### Create Tag
|
||||||
@@ -63,6 +81,12 @@ quicommit tag --bump minor
|
|||||||
|
|
||||||
# Custom tag name
|
# Custom tag name
|
||||||
quicommit tag -n v1.0.0
|
quicommit tag -n v1.0.0
|
||||||
|
|
||||||
|
# AI-generate tag message
|
||||||
|
quicommit tag --generate
|
||||||
|
|
||||||
|
# Create tag and push to remote
|
||||||
|
quicommit tag --push
|
||||||
```
|
```
|
||||||
|
|
||||||
### Generate Changelog
|
### Generate Changelog
|
||||||
@@ -73,6 +97,15 @@ quicommit changelog
|
|||||||
|
|
||||||
# Generate for specific version
|
# Generate for specific version
|
||||||
quicommit changelog -v 1.0.0
|
quicommit changelog -v 1.0.0
|
||||||
|
|
||||||
|
# AI-generate changelog
|
||||||
|
quicommit changelog --generate
|
||||||
|
|
||||||
|
# Initialize new changelog file
|
||||||
|
quicommit changelog --init
|
||||||
|
|
||||||
|
# Specify output file
|
||||||
|
quicommit changelog -o RELEASE_NOTES.md
|
||||||
```
|
```
|
||||||
|
|
||||||
### Manage Profiles
|
### Manage Profiles
|
||||||
@@ -84,11 +117,41 @@ quicommit profile add
|
|||||||
# List profiles
|
# List profiles
|
||||||
quicommit profile list
|
quicommit profile list
|
||||||
|
|
||||||
|
# Show profile details
|
||||||
|
quicommit profile show
|
||||||
|
|
||||||
# Switch profile
|
# Switch profile
|
||||||
quicommit profile switch
|
quicommit profile switch
|
||||||
|
|
||||||
|
# Set default profile
|
||||||
|
quicommit profile set-default personal
|
||||||
|
|
||||||
# Set profile for current repo
|
# Set profile for current repo
|
||||||
quicommit profile set-repo personal
|
quicommit profile set-repo personal
|
||||||
|
|
||||||
|
# Apply profile to current repo
|
||||||
|
quicommit profile apply
|
||||||
|
|
||||||
|
# Apply profile globally
|
||||||
|
quicommit profile apply --global
|
||||||
|
|
||||||
|
# Copy profile
|
||||||
|
quicommit profile copy personal work
|
||||||
|
|
||||||
|
# Edit profile
|
||||||
|
quicommit profile edit personal
|
||||||
|
|
||||||
|
# Remove profile
|
||||||
|
quicommit profile remove old-profile
|
||||||
|
|
||||||
|
# Check profile
|
||||||
|
quicommit profile check
|
||||||
|
|
||||||
|
# View usage statistics
|
||||||
|
quicommit profile stats
|
||||||
|
|
||||||
|
# Manage profile tokens
|
||||||
|
quicommit profile token
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configure LLM
|
### Configure LLM
|
||||||
@@ -109,17 +172,41 @@ quicommit config set-anthropic-key YOUR_API_KEY
|
|||||||
# Configure Kimi (Moonshot AI)
|
# Configure Kimi (Moonshot AI)
|
||||||
quicommit config set-llm kimi
|
quicommit config set-llm kimi
|
||||||
quicommit config set-kimi-key YOUR_API_KEY
|
quicommit config set-kimi-key YOUR_API_KEY
|
||||||
|
quicommit config set-kimi --base-url https://api.moonshot.cn/v1 --model moonshot-v1-8k
|
||||||
|
|
||||||
# Configure DeepSeek
|
# Configure DeepSeek
|
||||||
quicommit config set-llm deepseek
|
quicommit config set-llm deepseek
|
||||||
quicommit config set-deepseek-key YOUR_API_KEY
|
quicommit config set-deepseek-key YOUR_API_KEY
|
||||||
|
quicommit config set-deepseek --base-url https://api.deepseek.com/v1 --model deepseek-chat
|
||||||
|
|
||||||
# Configure OpenRouter
|
# Configure OpenRouter
|
||||||
quicommit config set-llm openrouter
|
quicommit config set-llm openrouter
|
||||||
quicommit config set-openrouter-key YOUR_API_KEY
|
quicommit config set-openrouter-key YOUR_API_KEY
|
||||||
|
quicommit config set-openrouter --base-url https://openrouter.ai/api/v1 --model openai/gpt-4
|
||||||
|
|
||||||
|
# Set commit format
|
||||||
|
quicommit config set-commit-format conventional
|
||||||
|
|
||||||
|
# Set version prefix
|
||||||
|
quicommit config set-version-prefix v
|
||||||
|
|
||||||
|
# Set changelog path
|
||||||
|
quicommit config set-changelog-path CHANGELOG.md
|
||||||
|
|
||||||
|
# Set output language
|
||||||
|
quicommit config set-language en
|
||||||
|
|
||||||
|
# Set keep commit types in English
|
||||||
|
quicommit config set-keep-types-english true
|
||||||
|
|
||||||
|
# Set keep changelog types in English
|
||||||
|
quicommit config set-keep-changelog-types-english true
|
||||||
|
|
||||||
# Test LLM connection
|
# Test LLM connection
|
||||||
quicommit config test-llm
|
quicommit config test-llm
|
||||||
|
|
||||||
|
# Reset configuration to defaults
|
||||||
|
quicommit config reset
|
||||||
```
|
```
|
||||||
|
|
||||||
## Command Reference
|
## Command Reference
|
||||||
@@ -137,17 +224,23 @@ quicommit config test-llm
|
|||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `-t, --commit-type` | Commit type (feat, fix, etc.) |
|
| `--commit-type` | Commit type (feat, fix, etc.) |
|
||||||
| `-s, --scope` | Commit scope |
|
| `-s, --scope` | Commit scope |
|
||||||
| `-m, --message` | Commit description |
|
| `-m, --message` | Commit description |
|
||||||
| `--body` | Commit body |
|
| `--body` | Commit body |
|
||||||
| `--breaking` | Mark as breaking change |
|
| `-b, --breaking` | Mark as breaking change |
|
||||||
|
| `-d, --date` | Use date-based commit message |
|
||||||
| `--manual` | Manual input, skip AI |
|
| `--manual` | Manual input, skip AI |
|
||||||
| `-a, --all` | Stage all changes |
|
| `-a, --all` | Stage all changes |
|
||||||
| `-S, --sign` | GPG sign commit |
|
| `-S, --sign` | GPG sign commit |
|
||||||
| `--amend` | Amend previous commit |
|
| `--amend` | Amend previous commit |
|
||||||
| `--dry-run` | Show without committing |
|
| `--dry-run` | Show without committing |
|
||||||
|
| `--conventional` | Use Conventional Commits format |
|
||||||
|
| `--commitlint` | Use commitlint format |
|
||||||
|
| `--no-verify` | Skip commit message verification |
|
||||||
| `-y, --yes` | Skip confirmation |
|
| `-y, --yes` | Skip confirmation |
|
||||||
|
| `--push` | Push after committing |
|
||||||
|
| `--remote` | Specify remote repository (default: origin) |
|
||||||
|
|
||||||
### Tag Options
|
### Tag Options
|
||||||
|
|
||||||
@@ -158,14 +251,35 @@ quicommit config test-llm
|
|||||||
| `-m, --message` | Tag message |
|
| `-m, --message` | Tag message |
|
||||||
| `-g, --generate` | AI-generate message |
|
| `-g, --generate` | AI-generate message |
|
||||||
| `-S, --sign` | GPG sign tag |
|
| `-S, --sign` | GPG sign tag |
|
||||||
| `--lightweight` | Create lightweight tag |
|
| `-l, --lightweight` | Create lightweight tag |
|
||||||
| `--push` | Push to remote |
|
| `-f, --force` | Force overwrite existing tag |
|
||||||
|
| `-p, --push` | Push to remote |
|
||||||
|
| `-r, --remote` | Specify remote repository (default: origin) |
|
||||||
|
| `--dry-run` | Dry run |
|
||||||
|
| `-y, --yes` | Skip confirmation |
|
||||||
|
|
||||||
|
### Changelog Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `-o, --output` | Output file path |
|
||||||
|
| `-v, --version` | Generate for specific version |
|
||||||
|
| `-f, --from` | Generate from specific tag |
|
||||||
|
| `-t, --to` | Generate to specific ref (default: HEAD) |
|
||||||
|
| `-i, --init` | Initialize new changelog file |
|
||||||
|
| `-g, --generate` | AI-generate changelog |
|
||||||
|
| `--prepend` | Prepend to existing changelog |
|
||||||
|
| `--include-hashes` | Include commit hashes |
|
||||||
|
| `--include-authors` | Include authors |
|
||||||
|
| `--format` | Format (keep-a-changelog, github-releases) |
|
||||||
|
| `--dry-run` | Dry run (output to stdout) |
|
||||||
| `-y, --yes` | Skip confirmation |
|
| `-y, --yes` | Skip confirmation |
|
||||||
|
|
||||||
## Configuration File
|
## Configuration File
|
||||||
|
|
||||||
Location:
|
Location:
|
||||||
- Linux/macOS: `~/.config/quicommit/config.toml`
|
- Linux: `~/.config/quicommit/config.toml`
|
||||||
|
- macOS: `~/Library/Application Support/quicommit/config.toml`
|
||||||
- Windows: `%APPDATA%\quicommit\config.toml`
|
- Windows: `%APPDATA%\quicommit\config.toml`
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
@@ -174,15 +288,27 @@ default_profile = "personal"
|
|||||||
|
|
||||||
[profiles.personal]
|
[profiles.personal]
|
||||||
name = "personal"
|
name = "personal"
|
||||||
user_name = "John Doe"
|
user_name = "Your Name"
|
||||||
user_email = "john@example.com"
|
user_email = "your.email@example.com"
|
||||||
|
description = "Personal projects"
|
||||||
|
is_work = false
|
||||||
|
|
||||||
[profiles.work]
|
[profiles.work]
|
||||||
name = "work"
|
name = "work"
|
||||||
user_name = "John Doe"
|
user_name = "Your Name"
|
||||||
user_email = "john@company.com"
|
user_email = "your.name@company.com"
|
||||||
|
description = "Work projects"
|
||||||
is_work = true
|
is_work = true
|
||||||
organization = "Acme Corp"
|
organization = "Your Company"
|
||||||
|
|
||||||
|
[profiles.work.ssh]
|
||||||
|
private_key_path = "/home/user/.ssh/id_rsa_work"
|
||||||
|
agent_forwarding = true
|
||||||
|
|
||||||
|
[profiles.work.gpg]
|
||||||
|
key_id = "YOUR_GPG_KEY_ID"
|
||||||
|
program = "gpg"
|
||||||
|
use_agent = true
|
||||||
|
|
||||||
[llm]
|
[llm]
|
||||||
provider = "ollama"
|
provider = "ollama"
|
||||||
@@ -198,19 +324,50 @@ model = "llama2"
|
|||||||
model = "gpt-4"
|
model = "gpt-4"
|
||||||
base_url = "https://api.openai.com/v1"
|
base_url = "https://api.openai.com/v1"
|
||||||
|
|
||||||
|
[llm.anthropic]
|
||||||
|
model = "claude-3-sonnet-20240229"
|
||||||
|
|
||||||
|
[llm.kimi]
|
||||||
|
model = "moonshot-v1-8k"
|
||||||
|
|
||||||
|
[llm.deepseek]
|
||||||
|
model = "deepseek-chat"
|
||||||
|
|
||||||
|
[llm.openrouter]
|
||||||
|
model = "openai/gpt-4"
|
||||||
|
|
||||||
[commit]
|
[commit]
|
||||||
format = "conventional"
|
format = "conventional"
|
||||||
auto_generate = true
|
auto_generate = true
|
||||||
|
allow_empty = false
|
||||||
|
gpg_sign = false
|
||||||
max_subject_length = 100
|
max_subject_length = 100
|
||||||
|
require_scope = false
|
||||||
|
require_body = false
|
||||||
|
body_required_types = ["feat", "fix"]
|
||||||
|
|
||||||
[tag]
|
[tag]
|
||||||
version_prefix = "v"
|
version_prefix = "v"
|
||||||
auto_generate = true
|
auto_generate = true
|
||||||
|
gpg_sign = false
|
||||||
|
include_changelog = true
|
||||||
|
|
||||||
[changelog]
|
[changelog]
|
||||||
path = "CHANGELOG.md"
|
path = "CHANGELOG.md"
|
||||||
auto_generate = true
|
auto_generate = true
|
||||||
|
format = "keep-a-changelog"
|
||||||
|
include_hashes = false
|
||||||
|
include_authors = false
|
||||||
group_by_type = true
|
group_by_type = true
|
||||||
|
|
||||||
|
[theme]
|
||||||
|
colors = true
|
||||||
|
icons = true
|
||||||
|
date_format = "%Y-%m-%d"
|
||||||
|
|
||||||
|
[repo_profiles]
|
||||||
|
"/path/to/work/project" = "work"
|
||||||
|
"/path/to/personal/project" = "personal"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
@@ -227,14 +384,32 @@ group_by_type = true
|
|||||||
# View current configuration
|
# View current configuration
|
||||||
quicommit config list
|
quicommit config list
|
||||||
|
|
||||||
|
# Show configuration details
|
||||||
|
quicommit config show
|
||||||
|
|
||||||
|
# Edit configuration file
|
||||||
|
quicommit config edit
|
||||||
|
|
||||||
|
# Set configuration value
|
||||||
|
quicommit config set llm.provider ollama
|
||||||
|
|
||||||
|
# Get configuration value
|
||||||
|
quicommit config get llm.provider
|
||||||
|
|
||||||
# Test LLM connection
|
# Test LLM connection
|
||||||
quicommit config test-llm
|
quicommit config test-llm
|
||||||
|
|
||||||
# List available models
|
# List available models
|
||||||
quicommit config list-models
|
quicommit config list-models
|
||||||
|
|
||||||
# Edit configuration
|
# Export configuration
|
||||||
quicommit config edit
|
quicommit config export -o config-backup.toml
|
||||||
|
|
||||||
|
# Import configuration
|
||||||
|
quicommit config import -i config-backup.toml
|
||||||
|
|
||||||
|
# Reset configuration
|
||||||
|
quicommit config reset --force
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
@@ -253,8 +428,8 @@ Contributions are welcome! Please follow these steps:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Clone repository
|
# Clone repository
|
||||||
git clone https://github.com/YOUR_USERNAME/quicommit.git
|
git clone https://git.lyz.one/SidneyZhang/QuiCommit.git
|
||||||
cd quicommit
|
cd QuiCommit
|
||||||
|
|
||||||
# Fetch dependencies
|
# Fetch dependencies
|
||||||
cargo fetch
|
cargo fetch
|
||||||
@@ -282,11 +457,36 @@ cargo fmt --check
|
|||||||
```
|
```
|
||||||
src/
|
src/
|
||||||
├── commands/ # CLI command implementations
|
├── commands/ # CLI command implementations
|
||||||
|
│ ├── commit.rs
|
||||||
|
│ ├── tag.rs
|
||||||
|
│ ├── changelog.rs
|
||||||
|
│ ├── profile.rs
|
||||||
|
│ ├── config.rs
|
||||||
|
│ └── init.rs
|
||||||
├── config/ # Configuration management
|
├── config/ # Configuration management
|
||||||
|
│ ├── manager.rs
|
||||||
|
│ └── profile.rs
|
||||||
├── generator/ # AI content generation
|
├── generator/ # AI content generation
|
||||||
├── git/ # Git operations
|
├── git/ # Git operations
|
||||||
|
│ ├── commit.rs
|
||||||
|
│ ├── tag.rs
|
||||||
|
│ └── changelog.rs
|
||||||
├── llm/ # LLM provider implementations
|
├── llm/ # LLM provider implementations
|
||||||
└── utils/ # Utility functions
|
│ ├── ollama.rs
|
||||||
|
│ ├── openai.rs
|
||||||
|
│ ├── anthropic.rs
|
||||||
|
│ ├── kimi.rs
|
||||||
|
│ ├── deepseek.rs
|
||||||
|
│ └── openrouter.rs
|
||||||
|
├── i18n/ # Internationalization support
|
||||||
|
│ ├── messages.rs
|
||||||
|
│ └── translator.rs
|
||||||
|
├── utils/ # Utility functions
|
||||||
|
│ ├── validators.rs
|
||||||
|
│ ├── formatter.rs
|
||||||
|
│ ├── crypto.rs
|
||||||
|
│ └── editor.rs
|
||||||
|
└── main.rs # Program entry point
|
||||||
```
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|||||||
240
readme_zh.md
240
readme_zh.md
@@ -4,8 +4,10 @@
|
|||||||
|
|
||||||
一款强大的AI驱动的Git助手,用于生成规范化的提交信息、标签和变更日志,并支持管理多个Git配置。
|
一款强大的AI驱动的Git助手,用于生成规范化的提交信息、标签和变更日志,并支持管理多个Git配置。
|
||||||
|
|
||||||

|
【目前还处在早期开发阶段,依然有一些功能未完善,欢迎反馈和贡献。】
|
||||||

|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
## 主要功能
|
## 主要功能
|
||||||
|
|
||||||
@@ -19,11 +21,19 @@
|
|||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
目前,整体工具还在开发,并不保证各项功能准确达到既定目标。但依然十分欢迎参与贡献、反馈问题和建议。
|
### cargo安装
|
||||||
|
|
||||||
|
cargo安装版本可能暂时不如源码进展快速。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/yourusername/quicommit.git
|
cargo install quicommit
|
||||||
cd quicommit
|
```
|
||||||
|
|
||||||
|
### 从源代码安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.lyz.one/SidneyZhang/QuiCommit.git
|
||||||
|
cd QuiCommit
|
||||||
cargo build --release
|
cargo build --release
|
||||||
cargo install --path .
|
cargo install --path .
|
||||||
```
|
```
|
||||||
@@ -52,6 +62,12 @@ quicommit commit -a
|
|||||||
|
|
||||||
# 跳过确认直接提交
|
# 跳过确认直接提交
|
||||||
quicommit commit --yes
|
quicommit commit --yes
|
||||||
|
|
||||||
|
# 使用日期格式的提交信息
|
||||||
|
quicommit commit --date
|
||||||
|
|
||||||
|
# 提交后推送到远程
|
||||||
|
quicommit commit --push
|
||||||
```
|
```
|
||||||
|
|
||||||
### 创建标签
|
### 创建标签
|
||||||
@@ -65,6 +81,12 @@ quicommit tag --bump minor
|
|||||||
|
|
||||||
# 自定义标签名
|
# 自定义标签名
|
||||||
quicommit tag -n v1.0.0
|
quicommit tag -n v1.0.0
|
||||||
|
|
||||||
|
# AI生成标签信息
|
||||||
|
quicommit tag --generate
|
||||||
|
|
||||||
|
# 创建标签并推送到远程
|
||||||
|
quicommit tag --push
|
||||||
```
|
```
|
||||||
|
|
||||||
### 生成变更日志
|
### 生成变更日志
|
||||||
@@ -75,6 +97,15 @@ quicommit changelog
|
|||||||
|
|
||||||
# 为特定版本生成
|
# 为特定版本生成
|
||||||
quicommit changelog -v 1.0.0
|
quicommit changelog -v 1.0.0
|
||||||
|
|
||||||
|
# AI生成变更日志
|
||||||
|
quicommit changelog --generate
|
||||||
|
|
||||||
|
# 初始化新的变更日志文件
|
||||||
|
quicommit changelog --init
|
||||||
|
|
||||||
|
# 指定输出文件
|
||||||
|
quicommit changelog -o RELEASE_NOTES.md
|
||||||
```
|
```
|
||||||
|
|
||||||
### 配置管理
|
### 配置管理
|
||||||
@@ -86,11 +117,41 @@ quicommit profile add
|
|||||||
# 查看配置列表
|
# 查看配置列表
|
||||||
quicommit profile list
|
quicommit profile list
|
||||||
|
|
||||||
|
# 显示配置详情
|
||||||
|
quicommit profile show
|
||||||
|
|
||||||
# 切换配置
|
# 切换配置
|
||||||
quicommit profile switch
|
quicommit profile switch
|
||||||
|
|
||||||
|
# 设置默认配置
|
||||||
|
quicommit profile set-default personal
|
||||||
|
|
||||||
# 设置当前仓库的配置
|
# 设置当前仓库的配置
|
||||||
quicommit profile set-repo personal
|
quicommit profile set-repo personal
|
||||||
|
|
||||||
|
# 应用配置到当前仓库
|
||||||
|
quicommit profile apply
|
||||||
|
|
||||||
|
# 全局应用配置
|
||||||
|
quicommit profile apply --global
|
||||||
|
|
||||||
|
# 复制配置
|
||||||
|
quicommit profile copy personal work
|
||||||
|
|
||||||
|
# 编辑配置
|
||||||
|
quicommit profile edit personal
|
||||||
|
|
||||||
|
# 删除配置
|
||||||
|
quicommit profile remove old-profile
|
||||||
|
|
||||||
|
# 检查配置
|
||||||
|
quicommit profile check
|
||||||
|
|
||||||
|
# 查看使用统计
|
||||||
|
quicommit profile stats
|
||||||
|
|
||||||
|
# 管理配置的令牌
|
||||||
|
quicommit profile token
|
||||||
```
|
```
|
||||||
|
|
||||||
### LLM配置
|
### LLM配置
|
||||||
@@ -111,17 +172,41 @@ quicommit config set-anthropic-key YOUR_API_KEY
|
|||||||
# 配置Kimi
|
# 配置Kimi
|
||||||
quicommit config set-llm kimi
|
quicommit config set-llm kimi
|
||||||
quicommit config set-kimi-key YOUR_API_KEY
|
quicommit config set-kimi-key YOUR_API_KEY
|
||||||
|
quicommit config set-kimi --base-url https://api.moonshot.cn/v1 --model moonshot-v1-8k
|
||||||
|
|
||||||
# 配置DeepSeek
|
# 配置DeepSeek
|
||||||
quicommit config set-llm deepseek
|
quicommit config set-llm deepseek
|
||||||
quicommit config set-deepseek-key YOUR_API_KEY
|
quicommit config set-deepseek-key YOUR_API_KEY
|
||||||
|
quicommit config set-deepseek --base-url https://api.deepseek.com/v1 --model deepseek-chat
|
||||||
|
|
||||||
# 配置OpenRouter
|
# 配置OpenRouter
|
||||||
quicommit config set-llm openrouter
|
quicommit config set-llm openrouter
|
||||||
quicommit config set-openrouter-key YOUR_API_KEY
|
quicommit config set-openrouter-key YOUR_API_KEY
|
||||||
|
quicommit config set-openrouter --base-url https://openrouter.ai/api/v1 --model openai/gpt-4
|
||||||
|
|
||||||
|
# 设置提交格式
|
||||||
|
quicommit config set-commit-format conventional
|
||||||
|
|
||||||
|
# 设置版本前缀
|
||||||
|
quicommit config set-version-prefix v
|
||||||
|
|
||||||
|
# 设置变更日志路径
|
||||||
|
quicommit config set-changelog-path CHANGELOG.md
|
||||||
|
|
||||||
|
# 设置输出语言
|
||||||
|
quicommit config set-language zh
|
||||||
|
|
||||||
|
# 设置保持提交类型为英文
|
||||||
|
quicommit config set-keep-types-english true
|
||||||
|
|
||||||
|
# 设置保持变更日志类型为英文
|
||||||
|
quicommit config set-keep-changelog-types-english true
|
||||||
|
|
||||||
# 测试LLM连接
|
# 测试LLM连接
|
||||||
quicommit config test-llm
|
quicommit config test-llm
|
||||||
|
|
||||||
|
# 重置配置为默认值
|
||||||
|
quicommit config reset
|
||||||
```
|
```
|
||||||
|
|
||||||
## 命令参考
|
## 命令参考
|
||||||
@@ -139,17 +224,23 @@ quicommit config test-llm
|
|||||||
|
|
||||||
| 选项 | 说明 |
|
| 选项 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `-t, --commit-type` | 提交类型(feat、fix等) |
|
| `--commit-type` | 提交类型(feat、fix等) |
|
||||||
| `-s, --scope` | 提交范围 |
|
| `-s, --scope` | 提交范围 |
|
||||||
| `-m, --message` | 提交描述 |
|
| `-m, --message` | 提交描述 |
|
||||||
| `--body` | 提交正文 |
|
| `--body` | 提交正文 |
|
||||||
| `--breaking` | 标记为破坏性变更 |
|
| `-b, --breaking` | 标记为破坏性变更 |
|
||||||
|
| `-d, --date` | 使用日期格式的提交信息 |
|
||||||
| `--manual` | 手动输入,跳过AI生成 |
|
| `--manual` | 手动输入,跳过AI生成 |
|
||||||
| `-a, --all` | 暂存所有更改 |
|
| `-a, --all` | 暂存所有更改 |
|
||||||
| `-S, --sign` | GPG签名提交 |
|
| `-S, --sign` | GPG签名提交 |
|
||||||
| `--amend` | 修改上一次提交 |
|
| `--amend` | 修改上一次提交 |
|
||||||
| `--dry-run` | 试运行,不实际提交 |
|
| `--dry-run` | 试运行,不实际提交 |
|
||||||
|
| `--conventional` | 使用Conventional Commits格式 |
|
||||||
|
| `--commitlint` | 使用commitlint格式 |
|
||||||
|
| `--no-verify` | 不验证提交信息 |
|
||||||
| `-y, --yes` | 跳过确认提示 |
|
| `-y, --yes` | 跳过确认提示 |
|
||||||
|
| `--push` | 提交后推送到远程 |
|
||||||
|
| `--remote` | 指定远程仓库(默认:origin) |
|
||||||
|
|
||||||
### tag命令选项
|
### tag命令选项
|
||||||
|
|
||||||
@@ -160,15 +251,36 @@ quicommit config test-llm
|
|||||||
| `-m, --message` | 标签信息 |
|
| `-m, --message` | 标签信息 |
|
||||||
| `-g, --generate` | AI生成标签信息 |
|
| `-g, --generate` | AI生成标签信息 |
|
||||||
| `-S, --sign` | GPG签名标签 |
|
| `-S, --sign` | GPG签名标签 |
|
||||||
| `--lightweight` | 创建轻量标签 |
|
| `-l, --lightweight` | 创建轻量标签 |
|
||||||
| `--push` | 推送到远程 |
|
| `-f, --force` | 强制覆盖已存在的标签 |
|
||||||
|
| `-p, --push` | 推送到远程 |
|
||||||
|
| `-r, --remote` | 指定远程仓库(默认:origin) |
|
||||||
|
| `--dry-run` | 试运行 |
|
||||||
|
| `-y, --yes` | 跳过确认提示 |
|
||||||
|
|
||||||
|
### changelog命令选项
|
||||||
|
|
||||||
|
| 选项 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `-o, --output` | 输出文件路径 |
|
||||||
|
| `-v, --version` | 为特定版本生成 |
|
||||||
|
| `-f, --from` | 从指定标签生成 |
|
||||||
|
| `-t, --to` | 生成到指定引用(默认:HEAD) |
|
||||||
|
| `-i, --init` | 初始化新的变更日志文件 |
|
||||||
|
| `-g, --generate` | AI生成变更日志 |
|
||||||
|
| `--prepend` | 添加到现有变更日志开头 |
|
||||||
|
| `--include-hashes` | 包含提交哈希 |
|
||||||
|
| `--include-authors` | 包含作者信息 |
|
||||||
|
| `--format` | 格式(keep-a-changelog、github-releases) |
|
||||||
|
| `--dry-run` | 试运行(输出到stdout) |
|
||||||
| `-y, --yes` | 跳过确认提示 |
|
| `-y, --yes` | 跳过确认提示 |
|
||||||
|
|
||||||
## 配置文件
|
## 配置文件
|
||||||
|
|
||||||
配置文件位置:
|
配置文件位置:
|
||||||
- Linux/macOS: `~/.config/quicommit/config.toml`
|
- Linux: `~/.config/quicommit/config.toml`
|
||||||
- Windows: `%APPDATA%\quicommit\config.toml`
|
- macOS: `~/Library/Application Support/quicommit/config.toml`
|
||||||
|
- Windows: `%APPDATA%\quicommit/config.toml`
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
version = "1"
|
version = "1"
|
||||||
@@ -176,15 +288,27 @@ default_profile = "personal"
|
|||||||
|
|
||||||
[profiles.personal]
|
[profiles.personal]
|
||||||
name = "personal"
|
name = "personal"
|
||||||
user_name = "John Doe"
|
user_name = "Your Name"
|
||||||
user_email = "john@example.com"
|
user_email = "your.email@example.com"
|
||||||
|
description = "个人项目"
|
||||||
|
is_work = false
|
||||||
|
|
||||||
[profiles.work]
|
[profiles.work]
|
||||||
name = "work"
|
name = "work"
|
||||||
user_name = "John Doe"
|
user_name = "Your Name"
|
||||||
user_email = "john@company.com"
|
user_email = "your.name@company.com"
|
||||||
|
description = "工作项目"
|
||||||
is_work = true
|
is_work = true
|
||||||
organization = "Acme Corp"
|
organization = "Your Company"
|
||||||
|
|
||||||
|
[profiles.work.ssh]
|
||||||
|
private_key_path = "/home/user/.ssh/id_rsa_work"
|
||||||
|
agent_forwarding = true
|
||||||
|
|
||||||
|
[profiles.work.gpg]
|
||||||
|
key_id = "YOUR_GPG_KEY_ID"
|
||||||
|
program = "gpg"
|
||||||
|
use_agent = true
|
||||||
|
|
||||||
[llm]
|
[llm]
|
||||||
provider = "ollama"
|
provider = "ollama"
|
||||||
@@ -200,19 +324,50 @@ model = "llama2"
|
|||||||
model = "gpt-4"
|
model = "gpt-4"
|
||||||
base_url = "https://api.openai.com/v1"
|
base_url = "https://api.openai.com/v1"
|
||||||
|
|
||||||
|
[llm.anthropic]
|
||||||
|
model = "claude-3-sonnet-20240229"
|
||||||
|
|
||||||
|
[llm.kimi]
|
||||||
|
model = "moonshot-v1-8k"
|
||||||
|
|
||||||
|
[llm.deepseek]
|
||||||
|
model = "deepseek-chat"
|
||||||
|
|
||||||
|
[llm.openrouter]
|
||||||
|
model = "openai/gpt-4"
|
||||||
|
|
||||||
[commit]
|
[commit]
|
||||||
format = "conventional"
|
format = "conventional"
|
||||||
auto_generate = true
|
auto_generate = true
|
||||||
|
allow_empty = false
|
||||||
|
gpg_sign = false
|
||||||
max_subject_length = 100
|
max_subject_length = 100
|
||||||
|
require_scope = false
|
||||||
|
require_body = false
|
||||||
|
body_required_types = ["feat", "fix"]
|
||||||
|
|
||||||
[tag]
|
[tag]
|
||||||
version_prefix = "v"
|
version_prefix = "v"
|
||||||
auto_generate = true
|
auto_generate = true
|
||||||
|
gpg_sign = false
|
||||||
|
include_changelog = true
|
||||||
|
|
||||||
[changelog]
|
[changelog]
|
||||||
path = "CHANGELOG.md"
|
path = "CHANGELOG.md"
|
||||||
auto_generate = true
|
auto_generate = true
|
||||||
|
format = "keep-a-changelog"
|
||||||
|
include_hashes = false
|
||||||
|
include_authors = false
|
||||||
group_by_type = true
|
group_by_type = true
|
||||||
|
|
||||||
|
[theme]
|
||||||
|
colors = true
|
||||||
|
icons = true
|
||||||
|
date_format = "%Y-%m-%d"
|
||||||
|
|
||||||
|
[repo_profiles]
|
||||||
|
"/path/to/work/project" = "work"
|
||||||
|
"/path/to/personal/project" = "personal"
|
||||||
```
|
```
|
||||||
|
|
||||||
## 环境变量
|
## 环境变量
|
||||||
@@ -229,14 +384,32 @@ group_by_type = true
|
|||||||
# 查看当前配置
|
# 查看当前配置
|
||||||
quicommit config list
|
quicommit config list
|
||||||
|
|
||||||
|
# 显示配置详情
|
||||||
|
quicommit config show
|
||||||
|
|
||||||
|
# 编辑配置文件
|
||||||
|
quicommit config edit
|
||||||
|
|
||||||
|
# 设置配置值
|
||||||
|
quicommit config set llm.provider ollama
|
||||||
|
|
||||||
|
# 获取配置值
|
||||||
|
quicommit config get llm.provider
|
||||||
|
|
||||||
# 测试LLM连接
|
# 测试LLM连接
|
||||||
quicommit config test-llm
|
quicommit config test-llm
|
||||||
|
|
||||||
# 列出可用模型
|
# 列出可用模型
|
||||||
quicommit config list-models
|
quicommit config list-models
|
||||||
|
|
||||||
# 编辑配置文件
|
# 导出配置
|
||||||
quicommit config edit
|
quicommit config export -o config-backup.toml
|
||||||
|
|
||||||
|
# 导入配置
|
||||||
|
quicommit config import -i config-backup.toml
|
||||||
|
|
||||||
|
# 重置配置
|
||||||
|
quicommit config reset --force
|
||||||
```
|
```
|
||||||
|
|
||||||
## 贡献
|
## 贡献
|
||||||
@@ -255,8 +428,8 @@ quicommit config edit
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 克隆仓库
|
# 克隆仓库
|
||||||
git clone https://github.com/YOUR_USERNAME/quicommit.git
|
git clone https://git.lyz.one/SidneyZhang/QuiCommit.git
|
||||||
cd quicommit
|
cd QuiCommit
|
||||||
|
|
||||||
# 安装依赖
|
# 安装依赖
|
||||||
cargo fetch
|
cargo fetch
|
||||||
@@ -284,11 +457,36 @@ cargo fmt --check
|
|||||||
```
|
```
|
||||||
src/
|
src/
|
||||||
├── commands/ # CLI命令实现
|
├── commands/ # CLI命令实现
|
||||||
|
│ ├── commit.rs
|
||||||
|
│ ├── tag.rs
|
||||||
|
│ ├── changelog.rs
|
||||||
|
│ ├── profile.rs
|
||||||
|
│ ├── config.rs
|
||||||
|
│ └── init.rs
|
||||||
├── config/ # 配置管理
|
├── config/ # 配置管理
|
||||||
|
│ ├── manager.rs
|
||||||
|
│ └── profile.rs
|
||||||
├── generator/ # AI内容生成
|
├── generator/ # AI内容生成
|
||||||
├── git/ # Git操作封装
|
├── git/ # Git操作封装
|
||||||
|
│ ├── commit.rs
|
||||||
|
│ ├── tag.rs
|
||||||
|
│ └── changelog.rs
|
||||||
├── llm/ # LLM提供商实现
|
├── llm/ # LLM提供商实现
|
||||||
└── utils/ # 工具函数
|
│ ├── ollama.rs
|
||||||
|
│ ├── openai.rs
|
||||||
|
│ ├── anthropic.rs
|
||||||
|
│ ├── kimi.rs
|
||||||
|
│ ├── deepseek.rs
|
||||||
|
│ └── openrouter.rs
|
||||||
|
├── i18n/ # 国际化支持
|
||||||
|
│ ├── messages.rs
|
||||||
|
│ └── translator.rs
|
||||||
|
├── utils/ # 工具函数
|
||||||
|
│ ├── validators.rs
|
||||||
|
│ ├── formatter.rs
|
||||||
|
│ ├── crypto.rs
|
||||||
|
│ └── editor.rs
|
||||||
|
└── main.rs # 程序入口
|
||||||
```
|
```
|
||||||
|
|
||||||
## 许可证
|
## 许可证
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::path::PathBuf;
|
|||||||
use crate::config::{Language, manager::ConfigManager};
|
use crate::config::{Language, manager::ConfigManager};
|
||||||
use crate::generator::ContentGenerator;
|
use crate::generator::ContentGenerator;
|
||||||
use crate::git::find_repo;
|
use crate::git::find_repo;
|
||||||
use crate::git::{changelog::*, CommitInfo, GitRepo};
|
use crate::git::{changelog::*, CommitInfo};
|
||||||
use crate::i18n::{Messages, translate_changelog_category};
|
use crate::i18n::{Messages, translate_changelog_category};
|
||||||
|
|
||||||
/// Generate changelog
|
/// Generate changelog
|
||||||
@@ -120,7 +120,7 @@ impl ChangelogCommand {
|
|||||||
|
|
||||||
// Generate changelog
|
// Generate changelog
|
||||||
let changelog = if self.generate || (config.changelog.auto_generate && !self.yes) {
|
let changelog = if self.generate || (config.changelog.auto_generate && !self.yes) {
|
||||||
self.generate_with_ai(&repo, &version, &commits, &messages).await?
|
self.generate_with_ai(&version, &commits, &messages).await?
|
||||||
} else {
|
} else {
|
||||||
self.generate_with_template(format, &version, &commits, language)?
|
self.generate_with_template(format, &version, &commits, language)?
|
||||||
};
|
};
|
||||||
@@ -173,18 +173,18 @@ impl ChangelogCommand {
|
|||||||
|
|
||||||
async fn generate_with_ai(
|
async fn generate_with_ai(
|
||||||
&self,
|
&self,
|
||||||
repo: &GitRepo,
|
|
||||||
version: &str,
|
version: &str,
|
||||||
commits: &[CommitInfo],
|
commits: &[CommitInfo],
|
||||||
messages: &Messages,
|
messages: &Messages,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let manager = ConfigManager::new()?;
|
let manager = ConfigManager::new()?;
|
||||||
let config = manager.config();
|
let config = manager.config();
|
||||||
|
let language = manager.get_language().unwrap_or(Language::English);
|
||||||
|
|
||||||
println!("{}", messages.ai_generating_changelog());
|
println!("{}", messages.ai_generating_changelog());
|
||||||
|
|
||||||
let generator = ContentGenerator::new(&config.llm).await?;
|
let generator = ContentGenerator::new(&config.llm).await?;
|
||||||
generator.generate_changelog_entry(version, commits).await
|
generator.generate_changelog_entry(version, commits, language).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_with_template(
|
fn generate_with_template(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::config::CommitFormat;
|
|||||||
use crate::generator::ContentGenerator;
|
use crate::generator::ContentGenerator;
|
||||||
use crate::git::{find_repo, GitRepo};
|
use crate::git::{find_repo, GitRepo};
|
||||||
use crate::git::commit::{CommitBuilder, create_date_commit_message};
|
use crate::git::commit::{CommitBuilder, create_date_commit_message};
|
||||||
use crate::i18n::{Messages, translate_commit_type};
|
use crate::i18n::Messages;
|
||||||
use crate::utils::validators::get_commit_types;
|
use crate::utils::validators::get_commit_types;
|
||||||
|
|
||||||
/// Generate and execute conventional commits
|
/// Generate and execute conventional commits
|
||||||
@@ -114,6 +114,12 @@ impl CommitCommand {
|
|||||||
println!("{}", messages.auto_stage_changes().yellow());
|
println!("{}", messages.auto_stage_changes().yellow());
|
||||||
repo.stage_all()?;
|
repo.stage_all()?;
|
||||||
println!("{}", messages.staged_all().green());
|
println!("{}", messages.staged_all().green());
|
||||||
|
|
||||||
|
// Re-check status after staging to ensure changes are detected
|
||||||
|
let new_status = repo.status_summary()?;
|
||||||
|
if new_status.staged == 0 {
|
||||||
|
bail!("Failed to stage changes. Please try running 'git add -A' manually.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stage all if requested
|
// Stage all if requested
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ impl TagCommand {
|
|||||||
async fn generate_tag_message(&self, repo: &GitRepo, version: &str, messages: &Messages) -> Result<String> {
|
async fn generate_tag_message(&self, repo: &GitRepo, version: &str, messages: &Messages) -> Result<String> {
|
||||||
let manager = ConfigManager::new()?;
|
let manager = ConfigManager::new()?;
|
||||||
let config = manager.config();
|
let config = manager.config();
|
||||||
|
let language = manager.get_language().unwrap_or(Language::English);
|
||||||
|
|
||||||
// Get commits since last tag
|
// Get commits since last tag
|
||||||
let tags = repo.get_tags()?;
|
let tags = repo.get_tags()?;
|
||||||
@@ -282,7 +283,7 @@ impl TagCommand {
|
|||||||
println!("{}", messages.ai_generating_tag(commits.len()));
|
println!("{}", messages.ai_generating_tag(commits.len()));
|
||||||
|
|
||||||
let generator = ContentGenerator::new(&config.llm).await?;
|
let generator = ContentGenerator::new(&config.llm).await?;
|
||||||
generator.generate_tag_message(version, &commits).await
|
generator.generate_tag_message(version, &commits, language).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn input_message_interactive(&self, version: &str, messages: &Messages) -> Result<String> {
|
fn input_message_interactive(&self, version: &str, messages: &Messages) -> Result<String> {
|
||||||
|
|||||||
@@ -62,13 +62,14 @@ impl ContentGenerator {
|
|||||||
&self,
|
&self,
|
||||||
version: &str,
|
version: &str,
|
||||||
commits: &[CommitInfo],
|
commits: &[CommitInfo],
|
||||||
|
language: Language,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let commit_messages: Vec<String> = commits
|
let commit_messages: Vec<String> = commits
|
||||||
.iter()
|
.iter()
|
||||||
.map(|c| c.subject().to_string())
|
.map(|c| c.subject().to_string())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
self.llm_client.generate_tag_message(version, &commit_messages).await
|
self.llm_client.generate_tag_message(version, &commit_messages, language).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate changelog entry
|
/// Generate changelog entry
|
||||||
@@ -76,6 +77,7 @@ impl ContentGenerator {
|
|||||||
&self,
|
&self,
|
||||||
version: &str,
|
version: &str,
|
||||||
commits: &[CommitInfo],
|
commits: &[CommitInfo],
|
||||||
|
language: Language,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let typed_commits: Vec<(String, String)> = commits
|
let typed_commits: Vec<(String, String)> = commits
|
||||||
.iter()
|
.iter()
|
||||||
@@ -85,7 +87,7 @@ impl ContentGenerator {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
self.llm_client.generate_changelog_entry(version, &typed_commits).await
|
self.llm_client.generate_changelog_entry(version, &typed_commits, language).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate changelog from repository
|
/// Generate changelog from repository
|
||||||
@@ -94,6 +96,7 @@ impl ContentGenerator {
|
|||||||
repo: &GitRepo,
|
repo: &GitRepo,
|
||||||
version: &str,
|
version: &str,
|
||||||
from_tag: Option<&str>,
|
from_tag: Option<&str>,
|
||||||
|
language: Language,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let commits = if let Some(tag) = from_tag {
|
let commits = if let Some(tag) = from_tag {
|
||||||
repo.get_commits_between(tag, "HEAD")?
|
repo.get_commits_between(tag, "HEAD")?
|
||||||
@@ -101,7 +104,7 @@ impl ContentGenerator {
|
|||||||
repo.get_commits(50)?
|
repo.get_commits(50)?
|
||||||
};
|
};
|
||||||
|
|
||||||
self.generate_changelog_entry(version, &commits).await
|
self.generate_changelog_entry(version, &commits, language).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interactive commit generation with user feedback
|
/// Interactive commit generation with user feedback
|
||||||
|
|||||||
@@ -157,28 +157,19 @@ impl GitRepo {
|
|||||||
|
|
||||||
/// Get staged diff
|
/// Get staged diff
|
||||||
pub fn get_staged_diff(&self) -> Result<String> {
|
pub fn get_staged_diff(&self) -> Result<String> {
|
||||||
let head = self.repo.head().ok();
|
// Use git CLI to get staged diff for better compatibility
|
||||||
let head_tree = head.as_ref()
|
let output = std::process::Command::new("git")
|
||||||
.and_then(|h| h.peel_to_tree().ok());
|
.args(&["diff", "--cached"])
|
||||||
|
.current_dir(&self.path)
|
||||||
|
.output()
|
||||||
|
.with_context(|| "Failed to get staged diff with git command")?;
|
||||||
|
|
||||||
let mut index = self.repo.index()?;
|
if !output.status.success() {
|
||||||
let index_tree = index.write_tree()?;
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
let index_tree = self.repo.find_tree(index_tree)?;
|
bail!("Failed to get staged diff: {}", stderr);
|
||||||
|
|
||||||
let diff = if let Some(head) = head_tree {
|
|
||||||
self.repo.diff_tree_to_index(Some(&head), Some(&index), None)?
|
|
||||||
} else {
|
|
||||||
self.repo.diff_tree_to_index(None, Some(&index), None)?
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut diff_text = String::new();
|
|
||||||
diff.print(git2::DiffFormat::Patch, |_delta, _hunk, line| {
|
|
||||||
if let Ok(content) = std::str::from_utf8(line.content()) {
|
|
||||||
diff_text.push_str(content);
|
|
||||||
}
|
}
|
||||||
true
|
|
||||||
})?;
|
|
||||||
|
|
||||||
|
let diff_text = String::from_utf8_lossy(&output.stdout).to_string();
|
||||||
Ok(diff_text)
|
Ok(diff_text)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,6 +268,9 @@ impl GitRepo {
|
|||||||
bail!("Failed to stage changes: {}", stderr);
|
bail!("Failed to stage changes: {}", stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force refresh the git2 index to pick up changes from git CLI
|
||||||
|
let _ = self.repo.index()?.write();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,35 +556,52 @@ impl GitRepo {
|
|||||||
|
|
||||||
/// Get repository status summary
|
/// Get repository status summary
|
||||||
pub fn status_summary(&self) -> Result<StatusSummary> {
|
pub fn status_summary(&self) -> Result<StatusSummary> {
|
||||||
let statuses = self.repo.statuses(Some(StatusOptions::new().include_untracked(true)))?;
|
// Use git CLI for more reliable status detection
|
||||||
|
let output = std::process::Command::new("git")
|
||||||
|
.args(&["status", "--porcelain"])
|
||||||
|
.current_dir(&self.path)
|
||||||
|
.output()
|
||||||
|
.with_context(|| "Failed to get status with git command")?;
|
||||||
|
|
||||||
|
if !output.status.success() {
|
||||||
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
|
bail!("Failed to get status: {}", stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
let mut staged = 0;
|
let mut staged = 0;
|
||||||
let mut unstaged = 0;
|
let mut unstaged = 0;
|
||||||
let mut untracked = 0;
|
let mut untracked = 0;
|
||||||
let mut conflicted = 0;
|
let mut conflicted = 0;
|
||||||
|
|
||||||
for entry in statuses.iter() {
|
for line in stdout.lines() {
|
||||||
let status = entry.status();
|
if line.len() >= 2 {
|
||||||
|
let index_status = line.chars().next().unwrap();
|
||||||
|
let worktree_status = line.chars().nth(1).unwrap();
|
||||||
|
|
||||||
if status.is_index_new() || status.is_index_modified() ||
|
// Staged changes (first column not space)
|
||||||
status.is_index_deleted() || status.is_index_renamed() ||
|
if index_status != ' ' && index_status != '?' {
|
||||||
status.is_index_typechange() {
|
|
||||||
staged += 1;
|
staged += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.is_wt_modified() || status.is_wt_deleted() ||
|
// Unstaged changes (second column not space)
|
||||||
status.is_wt_renamed() || status.is_wt_typechange() {
|
if worktree_status != ' ' && worktree_status != '?' {
|
||||||
unstaged += 1;
|
unstaged += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.is_wt_new() {
|
// Untracked files (both columns are ?)
|
||||||
|
if index_status == '?' && worktree_status == '?' {
|
||||||
untracked += 1;
|
untracked += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.is_conflicted() {
|
// Conflicted files (both columns are U or DD, AA, etc.)
|
||||||
|
if (index_status == 'U' || worktree_status == 'U') ||
|
||||||
|
(index_status == 'A' && worktree_status == 'A') ||
|
||||||
|
(index_status == 'D' && worktree_status == 'D') {
|
||||||
conflicted += 1;
|
conflicted += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(StatusSummary {
|
Ok(StatusSummary {
|
||||||
staged,
|
staged,
|
||||||
|
|||||||
@@ -136,8 +136,9 @@ impl LlmClient {
|
|||||||
&self,
|
&self,
|
||||||
version: &str,
|
version: &str,
|
||||||
commits: &[String],
|
commits: &[String],
|
||||||
|
language: Language,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let system_prompt = TAG_MESSAGE_SYSTEM_PROMPT;
|
let system_prompt = get_tag_system_prompt(language);
|
||||||
let commits_text = commits.join("\n");
|
let commits_text = commits.join("\n");
|
||||||
let prompt = format!("Version: {}\n\nCommits:\n{}", version, commits_text);
|
let prompt = format!("Version: {}\n\nCommits:\n{}", version, commits_text);
|
||||||
|
|
||||||
@@ -149,8 +150,9 @@ impl LlmClient {
|
|||||||
&self,
|
&self,
|
||||||
version: &str,
|
version: &str,
|
||||||
commits: &[(String, String)], // (type, message)
|
commits: &[(String, String)], // (type, message)
|
||||||
|
language: Language,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let system_prompt = CHANGELOG_SYSTEM_PROMPT;
|
let system_prompt = get_changelog_system_prompt(language);
|
||||||
|
|
||||||
let commits_text = commits
|
let commits_text = commits
|
||||||
.iter()
|
.iter()
|
||||||
@@ -385,6 +387,30 @@ fn get_commit_system_prompt(format: crate::config::CommitFormat, language: Langu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_tag_system_prompt(language: Language) -> &'static str {
|
||||||
|
match language {
|
||||||
|
Language::Chinese => TAG_MESSAGE_SYSTEM_PROMPT_ZH,
|
||||||
|
Language::Japanese => TAG_MESSAGE_SYSTEM_PROMPT_JA,
|
||||||
|
Language::Korean => TAG_MESSAGE_SYSTEM_PROMPT_KO,
|
||||||
|
Language::Spanish => TAG_MESSAGE_SYSTEM_PROMPT_ES,
|
||||||
|
Language::French => TAG_MESSAGE_SYSTEM_PROMPT_FR,
|
||||||
|
Language::German => TAG_MESSAGE_SYSTEM_PROMPT_DE,
|
||||||
|
_ => TAG_MESSAGE_SYSTEM_PROMPT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_changelog_system_prompt(language: Language) -> &'static str {
|
||||||
|
match language {
|
||||||
|
Language::Chinese => CHANGELOG_SYSTEM_PROMPT_ZH,
|
||||||
|
Language::Japanese => CHANGELOG_SYSTEM_PROMPT_JA,
|
||||||
|
Language::Korean => CHANGELOG_SYSTEM_PROMPT_KO,
|
||||||
|
Language::Spanish => CHANGELOG_SYSTEM_PROMPT_ES,
|
||||||
|
Language::French => CHANGELOG_SYSTEM_PROMPT_FR,
|
||||||
|
Language::German => CHANGELOG_SYSTEM_PROMPT_DE,
|
||||||
|
_ => CHANGELOG_SYSTEM_PROMPT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// System prompts for LLM
|
// System prompts for LLM
|
||||||
|
|
||||||
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT: &str = r#"You are a helpful assistant that generates conventional commit messages.
|
const CONVENTIONAL_COMMIT_SYSTEM_PROMPT: &str = r#"You are a helpful assistant that generates conventional commit messages.
|
||||||
|
|||||||
Reference in New Issue
Block a user