From f767fa04ca94c596b87010b1f2cb88783de46c21 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 5 Oct 2025 20:14:09 +0000 Subject: [PATCH 1/3] Initial plan From f0599d6ebdfaf3d5991bf3c1156457d5a4f91e00 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 5 Oct 2025 20:30:11 +0000 Subject: [PATCH 2/3] Remove dead code markers and fix all clippy warnings Co-authored-by: oleander <220827+oleander@users.noreply.github.com> --- src/bin/hook.rs | 40 ++-------------------- src/hook.rs | 88 +++---------------------------------------------- 2 files changed, 6 insertions(+), 122 deletions(-) diff --git a/src/bin/hook.rs b/src/bin/hook.rs index c04afe60..482a9742 100644 --- a/src/bin/hook.rs +++ b/src/bin/hook.rs @@ -1,4 +1,4 @@ -#![allow(dead_code)] + // .git/hooks/prepare-commit-msg // @@ -54,7 +54,7 @@ use anyhow::{bail, Context, Result}; use git2::{Oid, Repository}; use ai::{commit, config, debug_output}; use ai::hook::*; -use ai::model::Model; + #[derive(Debug, PartialEq)] enum Source { @@ -90,43 +90,7 @@ struct Args { } impl Args { - async fn handle_commit(&self, repo: &Repository, pb: &ProgressBar, model: Model, remaining_tokens: usize) -> Result<()> { - let tree = match self.sha1.as_deref() { - Some("HEAD") | None => repo.head().ok().and_then(|head| head.peel_to_tree().ok()), - Some(sha1) => { - // Try to resolve the reference first - if let Ok(obj) = repo.revparse_single(sha1) { - obj.peel_to_tree().ok() - } else { - // If not a reference, try as direct OID - repo - .find_object(Oid::from_str(sha1)?, None) - .ok() - .and_then(|obj| obj.peel_to_tree().ok()) - } - } - }; - let diff = repo.to_diff(tree.clone())?; - if diff.is_empty()? { - if self.sha1.as_deref() == Some("HEAD") { - // For amend operations, we want to keep the existing message - return Ok(()); - } - bail!("No changes to commit"); - } - - let patch = repo - .to_patch(tree, remaining_tokens, model) - .context("Failed to get patch")?; - - let response = commit::generate(patch.to_string(), remaining_tokens, model, None).await?; - std::fs::write(&self.commit_msg_file, response.response.trim())?; - - pb.finish_and_clear(); - - Ok(()) - } async fn execute(&self) -> Result<()> { use Source::*; diff --git a/src/hook.rs b/src/hook.rs index 23341534..388610c7 100644 --- a/src/hook.rs +++ b/src/hook.rs @@ -1,4 +1,4 @@ -#![allow(dead_code)] + use std::collections::HashMap; use std::io::{Read, Write}; use std::path::PathBuf; @@ -7,7 +7,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use rayon::prelude::*; -use structopt::StructOpt; + use git2::{Diff, DiffFormat, DiffOptions, Repository, Tree}; use anyhow::{Context, Result}; use thiserror::Error; @@ -17,7 +17,7 @@ use crate::model::Model; use crate::profile; // Constants -const MAX_POOL_SIZE: usize = 1000; + const DEFAULT_STRING_CAPACITY: usize = 8192; const PARALLEL_CHUNK_SIZE: usize = 25; const ESTIMATED_FILES_COUNT: usize = 100; @@ -44,45 +44,9 @@ pub enum HookError { Anyhow(#[from] anyhow::Error) } -// CLI Arguments -#[derive(StructOpt, Debug)] -#[structopt(name = "commit-msg-hook", about = "A tool for generating commit messages.")] -pub struct Args { - pub commit_msg_file: PathBuf, - #[structopt(short = "t", long = "type")] - pub commit_type: Option, - #[structopt(short = "s", long = "sha1")] - pub sha1: Option -} -// Memory management -#[derive(Debug)] -struct StringPool { - strings: Vec, - capacity: usize -} - -impl StringPool { - fn new(capacity: usize) -> Self { - Self { strings: Vec::with_capacity(capacity), capacity } - } - - fn get(&mut self) -> String { - self - .strings - .pop() - .unwrap_or_else(|| String::with_capacity(self.capacity)) - } - - fn put(&mut self, mut string: String) { - string.clear(); - if self.strings.len() < MAX_POOL_SIZE { - self.strings.push(string); - } - } -} // File operations traits pub trait FilePath { @@ -364,9 +328,7 @@ impl PatchDiff for Diff<'_> { // Pre-allocate HashMap with estimated capacity let mut files = HashMap::with_capacity(ESTIMATED_FILES_COUNT); - // Use pre-sized buffers to avoid reallocations - const BUFFER_SIZE: usize = 64; // Hold context prefix strings - static CONTEXT_PREFIX: &str = "context: "; + // Create thread-local cache for paths to avoid allocations thread_local! { @@ -677,48 +639,6 @@ impl PatchRepository for Repository { } } -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_string_pool_new() { - let pool = StringPool::new(100); - assert_eq!(pool.strings.len(), 0); - assert_eq!(pool.capacity, 100); - } - #[test] - fn test_string_pool_put_and_get() { - let mut pool = StringPool::new(10); - let mut s1 = String::with_capacity(10); - s1.push_str("test"); - pool.put(s1); - - assert_eq!(pool.strings.len(), 1); - - let s2 = pool.get(); - assert_eq!(s2.capacity(), 10); - assert_eq!(s2.len(), 0); - assert_eq!(pool.strings.len(), 0); - } - #[test] - fn test_string_pool_limit() { - let mut pool = StringPool::new(10); - for _ in 0..150 { - pool.put(String::with_capacity(10)); - } - - assert_eq!(pool.strings.len(), 150); - } -} - -#[test] -fn test_string_pool_get() { - let mut pool = StringPool::new(10); - let s1 = pool.get(); - assert_eq!(s1.capacity(), 10); - assert_eq!(s1.len(), 0); -} From 095d35e7e54a0416a7674ced9edee3fea956e181 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 5 Oct 2025 20:44:16 +0000 Subject: [PATCH 3/3] Fix formatting issues that caused CI failure Co-authored-by: oleander <220827+oleander@users.noreply.github.com> --- src/bin/hook.rs | 5 ----- src/hook.rs | 12 ------------ 2 files changed, 17 deletions(-) diff --git a/src/bin/hook.rs b/src/bin/hook.rs index 482a9742..d9ebd913 100644 --- a/src/bin/hook.rs +++ b/src/bin/hook.rs @@ -1,5 +1,3 @@ - - // .git/hooks/prepare-commit-msg // // git commit --amend --no-edit @@ -55,7 +53,6 @@ use git2::{Oid, Repository}; use ai::{commit, config, debug_output}; use ai::hook::*; - #[derive(Debug, PartialEq)] enum Source { Message, @@ -90,8 +87,6 @@ struct Args { } impl Args { - - async fn execute(&self) -> Result<()> { use Source::*; diff --git a/src/hook.rs b/src/hook.rs index 388610c7..f554c653 100644 --- a/src/hook.rs +++ b/src/hook.rs @@ -1,4 +1,3 @@ - use std::collections::HashMap; use std::io::{Read, Write}; use std::path::PathBuf; @@ -7,7 +6,6 @@ use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use rayon::prelude::*; - use git2::{Diff, DiffFormat, DiffOptions, Repository, Tree}; use anyhow::{Context, Result}; use thiserror::Error; @@ -44,10 +42,6 @@ pub enum HookError { Anyhow(#[from] anyhow::Error) } - - - - // File operations traits pub trait FilePath { fn is_empty(&self) -> Result { @@ -328,8 +322,6 @@ impl PatchDiff for Diff<'_> { // Pre-allocate HashMap with estimated capacity let mut files = HashMap::with_capacity(ESTIMATED_FILES_COUNT); - - // Create thread-local cache for paths to avoid allocations thread_local! { static PATH_CACHE: std::cell::RefCell> = @@ -638,7 +630,3 @@ impl PatchRepository for Repository { .minimal(true); } } - - - -