Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 64342f7258 | |||
| ecb386ebda | |||
| 570770cf48 | |||
| 0e167d7c94 | |||
| 21393833c3 | |||
| f474328f45 | |||
| 43d4d99e25 | |||
| 8a15c29a18 | |||
| 3b7844976f | |||
| 469f0b93c0 | |||
| e27a9b93f5 | |||
| c4e819bd2d | |||
| a3c96fc9df | |||
| c1efcdc443 | |||
| 34e1f0acdf | |||
| e5cade0ea6 | |||
| b27f866c0e | |||
| c0082b9095 | |||
| 4f5ecffabc | |||
| e897a35e38 | |||
| f810e470c4 | |||
| 087fd93def | |||
| 92197cacae | |||
| 228fd5f921 | |||
| f772fa4413 | |||
| b5c381ab71 | |||
| 33beac0889 | |||
| 1e4086d33c | |||
| 58ff331af3 | |||
| 77724aac7e | |||
| a1da8bb97d | |||
| b0b9dfab9f | |||
| 28ce772dff | |||
| dec64839ce | |||
| a204e6c900 | |||
| 614ea3ea35 | |||
| 53ddefdafd | |||
| 5637b2e5ed | |||
| 361465a570 |
42
.gitea/workflows/ci.yml
Normal file
42
.gitea/workflows/ci.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, master]
|
||||
pull_request:
|
||||
branches: [main, master]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends pkg-config libssl-dev
|
||||
|
||||
- name: Set up Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
- name: Check code formatting
|
||||
run: cargo fmt -- --check
|
||||
|
||||
- name: Run clippy
|
||||
run: cargo clippy -- -D warnings
|
||||
|
||||
- name: Build project
|
||||
run: cargo build --release
|
||||
|
||||
- name: Run tests
|
||||
run: cargo test
|
||||
|
||||
- name: Show binary info
|
||||
run: ls -la target/release/auto-commit
|
||||
136
app/auto-commit/src/prompt.rs
Normal file
136
app/auto-commit/src/prompt.rs
Normal file
@@ -0,0 +1,136 @@
|
||||
use anyhow::Result;
|
||||
use colored::Colorize;
|
||||
use dialoguer::{Confirm, Select};
|
||||
|
||||
use crate::analyzer::{analyze_changes, get_all_commit_types, AnalysisResult, CommitType};
|
||||
use crate::generator::{generate_alternative_messages, generate_message};
|
||||
use crate::git::{GitRepo, StagedChanges};
|
||||
|
||||
pub fn select_commit_type(suggested: CommitType) -> Result<CommitType> {
|
||||
let all_types = get_all_commit_types();
|
||||
let type_names: Vec<String> = all_types.iter().map(|t| format!("{}", t)).collect();
|
||||
|
||||
let suggested_idx = all_types.iter().position(|t| *t == suggested).unwrap_or(0);
|
||||
|
||||
println!("{}", "\nSuggested commit type:".bold().green());
|
||||
println!(" {}", format!("{}", suggested).green().bold());
|
||||
|
||||
let selection = Select::with_theme(&dialoguer::theme::ColorfulTheme::default())
|
||||
.with_prompt("Select commit type (use ↑/↓ to navigate, Enter to confirm)")
|
||||
.items(&type_names)
|
||||
.default(suggested_idx)
|
||||
.interact()?;
|
||||
|
||||
Ok(all_types[selection])
|
||||
}
|
||||
|
||||
pub fn confirm_message(message: &str, alternatives: &[String]) -> Result<(bool, Option<String>)> {
|
||||
println!("\n{}", "Generated commit message:".bold().green());
|
||||
println!("\n{}\n", message.bright_white().on_blue());
|
||||
|
||||
if !alternatives.is_empty() {
|
||||
println!("{}", "Alternative messages:".bold().yellow());
|
||||
for (i, alt) in alternatives.iter().enumerate() {
|
||||
println!(" {}: {}", (i + 1).to_string().yellow(), alt);
|
||||
}
|
||||
}
|
||||
|
||||
let confirm = Confirm::with_theme(&dialoguer::theme::ColorfulTheme::default())
|
||||
.with_prompt("Do you want to use this commit message?")
|
||||
.default(true)
|
||||
.interact()?;
|
||||
|
||||
if confirm {
|
||||
Ok((true, None))
|
||||
} else {
|
||||
let edit_prompt = Confirm::with_theme(&dialoguer::theme::ColorfulTheme::default())
|
||||
.with_prompt("Would you like to edit the message manually?")
|
||||
.default(false)
|
||||
.interact()?;
|
||||
|
||||
if edit_prompt {
|
||||
let edited = dialoguer::Editor::new()
|
||||
.edit(&format!("\n# Edit your commit message below:\n{}\n", message))
|
||||
.map_err(|e| anyhow::anyhow!("Failed to open editor: {}", e))?;
|
||||
|
||||
match edited {
|
||||
Some(content) => {
|
||||
let cleaned = content
|
||||
.lines()
|
||||
.filter(|l| !l.starts_with('#'))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
.trim()
|
||||
.to_string();
|
||||
|
||||
if cleaned.is_empty() {
|
||||
Ok((false, None))
|
||||
} else {
|
||||
Ok((true, Some(cleaned)))
|
||||
}
|
||||
}
|
||||
None => Ok((false, None)),
|
||||
}
|
||||
} else {
|
||||
Ok((false, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interactive_commit(
|
||||
git_repo: &GitRepo,
|
||||
suggested_type: CommitType,
|
||||
staged: &StagedChanges,
|
||||
) -> Result<Option<String>> {
|
||||
let selected_type = if git_repo.has_config()? {
|
||||
select_commit_type(suggested_type)?
|
||||
} else {
|
||||
suggested_type
|
||||
};
|
||||
|
||||
let analysis = analyze_changes(staged);
|
||||
let analysis = AnalysisResult {
|
||||
commit_type: selected_type,
|
||||
..analysis
|
||||
};
|
||||
|
||||
let message = generate_message(&analysis, staged);
|
||||
let alternatives = generate_alternative_messages(&analysis, staged);
|
||||
|
||||
let (confirmed, edited_message) = confirm_message(&message, &alternatives)?;
|
||||
|
||||
if !confirmed {
|
||||
println!("{}", "\nCommit aborted by user.".yellow());
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
Ok(edited_message.or(Some(message)))
|
||||
}
|
||||
|
||||
pub fn print_staged_summary(staged: &StagedChanges) {
|
||||
if staged.files.is_empty() {
|
||||
println!("{}", "No staged changes found.".yellow());
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{}", "\nStaged changes:".bold().green());
|
||||
for file in &staged.files {
|
||||
let status_str = match file.status {
|
||||
crate::git::FileStatus::Added => "A".green(),
|
||||
crate::git::FileStatus::Deleted => "D".red(),
|
||||
crate::git::FileStatus::Modified => "M".yellow(),
|
||||
crate::git::FileStatus::Renamed => "R".cyan(),
|
||||
crate::git::FileStatus::Unknown => "?".white(),
|
||||
};
|
||||
|
||||
println!(
|
||||
" {} {:>6} {:>6} {}",
|
||||
status_str,
|
||||
format!("+{}", file.additions).green(),
|
||||
format!("-{}", file.deletions).red(),
|
||||
file.path
|
||||
);
|
||||
}
|
||||
|
||||
println!();
|
||||
}
|
||||
@@ -25,7 +25,7 @@ pub fn select_commit_type(suggested: CommitType) -> Result<CommitType> {
|
||||
}
|
||||
|
||||
pub fn confirm_message(message: &str, alternatives: &[String]) -> Result<(bool, Option<String>)> {
|
||||
println!("\n{}", "Generated commit message:".bold().green());
|
||||
println!("{}", "\nGenerated commit message:".bold().green());
|
||||
println!("\n{}\n", message.bright_white().on_blue());
|
||||
|
||||
if !alternatives.is_empty() {
|
||||
|
||||
Reference in New Issue
Block a user