In Git2 error fixing, opening the repo is still currently unavailable.
This commit is contained in:
@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Initial release of QuicCommit
|
- Initial release of QuiCommit
|
||||||
- AI-powered commit message generation using LLM APIs (OpenAI, Anthropic) or local Ollama
|
- AI-powered commit message generation using LLM APIs (OpenAI, Anthropic) or local Ollama
|
||||||
- Support for Conventional Commits and @commitlint formats
|
- Support for Conventional Commits and @commitlint formats
|
||||||
- Multiple Git profile management with SSH and GPG support
|
- Multiple Git profile management with SSH and GPG support
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ toml = "0.8"
|
|||||||
dirs = "5.0"
|
dirs = "5.0"
|
||||||
|
|
||||||
# Git operations
|
# Git operations
|
||||||
git2 = "0.18"
|
git2 = "0.20.3"
|
||||||
which = "6.0"
|
which = "6.0"
|
||||||
|
|
||||||
# HTTP client for LLM APIs
|
# HTTP client for LLM APIs
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# QuiCommit
|
# QuiCommit
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# QuiCommit
|
# QuiCommit
|
||||||
|
|
||||||
|
[English](README.md) | 简体中文
|
||||||
|
|
||||||
一款强大的AI驱动的Git助手,用于生成规范化的提交信息、标签和变更日志,并支持管理多个Git配置。
|
一款强大的AI驱动的Git助手,用于生成规范化的提交信息、标签和变更日志,并支持管理多个Git配置。
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ pub struct ChangelogCommand {
|
|||||||
|
|
||||||
impl ChangelogCommand {
|
impl ChangelogCommand {
|
||||||
pub async fn execute(&self) -> Result<()> {
|
pub async fn execute(&self) -> Result<()> {
|
||||||
let repo = find_repo(".")?;
|
let repo = find_repo(std::env::current_dir()?.as_path())?;
|
||||||
let manager = ConfigManager::new()?;
|
let manager = ConfigManager::new()?;
|
||||||
let config = manager.config();
|
let config = manager.config();
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ pub struct CommitCommand {
|
|||||||
impl CommitCommand {
|
impl CommitCommand {
|
||||||
pub async fn execute(&self) -> Result<()> {
|
pub async fn execute(&self) -> Result<()> {
|
||||||
// Find git repository
|
// Find git repository
|
||||||
let repo = find_repo(".")?;
|
let repo = find_repo(std::env::current_dir()?.as_path())?;
|
||||||
|
|
||||||
// Check for changes
|
// Check for changes
|
||||||
let status = repo.status_summary()?;
|
let status = repo.status_summary()?;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Result};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use dialoguer::{Confirm, Input, Select};
|
use dialoguer::{Confirm, Input, Select};
|
||||||
|
|
||||||
use crate::config::manager::ConfigManager;
|
use crate::config::manager::ConfigManager;
|
||||||
use crate::config::{CommitFormat, LlmConfig};
|
use crate::config::CommitFormat;
|
||||||
|
|
||||||
/// Mask API key with asterisks for security
|
/// Mask API key with asterisks for security
|
||||||
fn mask_api_key(key: Option<&str>) -> String {
|
fn mask_api_key(key: Option<&str>) -> String {
|
||||||
@@ -821,9 +821,16 @@ impl ConfigCommand {
|
|||||||
if client.is_available().await {
|
if client.is_available().await {
|
||||||
println!("{} LLM connection successful!", "✓".green());
|
println!("{} LLM connection successful!", "✓".green());
|
||||||
|
|
||||||
// Test generation
|
// Test generation with a sample diff
|
||||||
println!("Testing generation...");
|
println!("Testing generation...");
|
||||||
match client.generate_commit_message("test", crate::config::CommitFormat::Conventional).await {
|
let sample_diff = r#"diff --git a/src/main.rs b/src/main.rs
|
||||||
|
--- a/src/main.rs
|
||||||
|
+++ b/src/main.rs
|
||||||
|
@@ -1,3 +1,4 @@
|
||||||
|
fn main() {
|
||||||
|
+ println!("Hello, World!");
|
||||||
|
}"#;
|
||||||
|
match client.generate_commit_message(sample_diff, crate::config::CommitFormat::Conventional).await {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
println!("{} Generation test passed", "✓".green());
|
println!("{} Generation test passed", "✓".green());
|
||||||
println!("Response: {}", response.description.dimmed());
|
println!("Response: {}", response.description.dimmed());
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ impl ProfileCommand {
|
|||||||
|
|
||||||
async fn set_repo(&self, name: &str) -> Result<()> {
|
async fn set_repo(&self, name: &str) -> Result<()> {
|
||||||
let mut manager = ConfigManager::new()?;
|
let mut manager = ConfigManager::new()?;
|
||||||
let repo = find_repo(".")?;
|
let repo = find_repo(std::env::current_dir()?.as_path())?;
|
||||||
|
|
||||||
let repo_path = repo.path().to_string_lossy().to_string();
|
let repo_path = repo.path().to_string_lossy().to_string();
|
||||||
|
|
||||||
@@ -381,7 +381,7 @@ impl ProfileCommand {
|
|||||||
profile.apply_global()?;
|
profile.apply_global()?;
|
||||||
println!("{} Applied profile '{}' globally", "✓".green(), profile.name.cyan());
|
println!("{} Applied profile '{}' globally", "✓".green(), profile.name.cyan());
|
||||||
} else {
|
} else {
|
||||||
let repo = find_repo(".")?;
|
let repo = find_repo(std::env::current_dir()?.as_path())?;
|
||||||
profile.apply_to_repo(repo.inner())?;
|
profile.apply_to_repo(repo.inner())?;
|
||||||
println!("{} Applied profile '{}' to current repository", "✓".green(), profile.name.cyan());
|
println!("{} Applied profile '{}' to current repository", "✓".green(), profile.name.cyan());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ pub struct TagCommand {
|
|||||||
|
|
||||||
impl TagCommand {
|
impl TagCommand {
|
||||||
pub async fn execute(&self) -> Result<()> {
|
pub async fn execute(&self) -> Result<()> {
|
||||||
let repo = find_repo(".")?;
|
let repo = find_repo(std::env::current_dir()?.as_path())?;
|
||||||
let manager = ConfigManager::new()?;
|
let manager = ConfigManager::new()?;
|
||||||
let config = manager.config();
|
let config = manager.config();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use git2::{Repository, Signature, StatusOptions, DiffOptions};
|
use git2::{Repository, Signature, StatusOptions, DiffOptions};
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub mod changelog;
|
pub mod changelog;
|
||||||
pub mod commit;
|
pub mod commit;
|
||||||
@@ -19,13 +19,27 @@ pub struct GitRepo {
|
|||||||
impl GitRepo {
|
impl GitRepo {
|
||||||
/// Open a git repository
|
/// Open a git repository
|
||||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
|
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||||||
let path = path.as_ref().canonicalize()
|
let path = path.as_ref();
|
||||||
.unwrap_or_else(|_| path.as_ref().to_path_buf());
|
|
||||||
|
|
||||||
let repo = Repository::open(&path)
|
if let Ok(repo) = Repository::discover(&path) {
|
||||||
.with_context(|| format!("Failed to open git repository: {:?}", path))?;
|
return Ok(Self {
|
||||||
|
repo,
|
||||||
|
path: path.to_path_buf()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Self { repo, path })
|
if let Ok(repo) = Repository::open(path) {
|
||||||
|
return Ok(Self { repo, path: path.to_path_buf() });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果依然失败,给出明确的错误提示
|
||||||
|
bail!(
|
||||||
|
"Failed to open git repository at '{:?}'. Please ensure:\n\
|
||||||
|
1. The directory is set as safe (run: git config --global --add safe.directory \"{}\")\n\
|
||||||
|
2. The path is correct and contains a valid '.git' folder.",
|
||||||
|
path,
|
||||||
|
path.display()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get repository path
|
/// Get repository path
|
||||||
|
|||||||
Reference in New Issue
Block a user