Skip to content

[Refactor] Extract diff processing traits into src/diff/processor.rs #67

@oleander

Description

@oleander

Context

Continue breaking down hook.rs by extracting the PatchDiff and PatchRepository traits and their implementations into the diff module.

Priority

🟠 MEDIUM - Continues module restructuring

Steps

1. Create src/diff/processor.rs

//! Diff processing traits and implementations.
//!
//! Provides traits for converting git diffs into patches with
//! token management and truncation.

use std::collections::HashMap;
use std::path::PathBuf;
use anyhow::{Context, Result};
use git2::{Diff, DiffOptions, Repository, Tree};

use crate::model::Model;
use crate::diff::traits::DiffDeltaPath;
use super::optimization::process_files_for_patch;

/// Extension trait for git2::Diff to convert to patch with token limits
pub trait PatchDiff {
    /// Convert diff to patch string with token limit
    fn to_patch(&self, max_token_count: usize, model: Model) -> Result<String>;
    
    /// Collect diff data into a HashMap of file paths to content
    fn collect_diff_data(&self) -> Result<HashMap<PathBuf, String>>;
    
    /// Check if diff is empty
    fn is_empty(&self) -> Result<bool>;
}

impl PatchDiff for Diff<'_> {
    // Move implementation from hook.rs lines 161-444
}

/// Extension trait for Repository to create patches from trees
pub trait PatchRepository {
    /// Create patch from tree with token limit
    fn to_patch(&self, tree: Option<Tree<'_>>, max_token_count: usize, model: Model) -> Result<String>;
    
    /// Create diff from tree
    fn to_diff(&self, tree: Option<Tree<'_>>) -> Result<git2::Diff<'_>>;
    
    /// Create commit diff from tree (staged changes only)
    fn to_commit_diff(&self, tree: Option<Tree<'_>>) -> Result<git2::Diff<'_>>;
    
    /// Configure diff options
    fn configure_diff_options(&self, opts: &mut DiffOptions);
    
    /// Configure commit diff options  
    fn configure_commit_diff_options(&self, opts: &mut DiffOptions);
}

impl PatchRepository for Repository {
    // Move implementation from hook.rs lines 589-678
}

#[cfg(test)]
mod tests {
    use super::*;
    // Add tests for patch generation
}

2. Create src/diff/optimization.rs (stub for now)

//! Optimization utilities for diff processing.
//!
//! Handles parallel processing and token allocation for large diffs.

use std::path::PathBuf;
use anyhow::Result;
use crate::model::Model;

/// Type alias for diff data (path, content, token count)
pub type DiffData = Vec<(PathBuf, String, usize)>;

/// Process files and generate patch with token limits
/// 
/// This is extracted from the complex to_patch implementation
/// and will be refactored further in a future issue.
pub fn process_files_for_patch(
    files: DiffData,
    max_tokens: usize,
    model: &Model,
) -> Result<String> {
    // For now, keep simplified implementation
    // Full optimization will be tackled in separate issue
    unimplemented!("To be implemented in optimization refactor")
}

3. Update src/diff/mod.rs

pub mod parser;
pub mod processor;
pub mod optimization;
pub mod traits;

pub use parser::{ParsedFile, parse_diff};
pub use processor::{PatchDiff, PatchRepository};
pub use traits::{FilePath, Utf8String, DiffDeltaPath};

4. Update src/hook.rs

// Add imports
use crate::diff::processor::{PatchDiff, PatchRepository};

// Remove trait definitions and implementations (lines 154-678)
// Keep the constants and types that aren't moved yet

5. Update imports in other files

Search for uses of these traits:

rg "PatchDiff" src/ -l
rg "PatchRepository" src/ -l

Update imports to use crate::diff::processor::*

Verification Criteria

Pass:

  • src/diff/processor.rs created with both traits
  • src/diff/optimization.rs created (stub)
  • Traits moved from hook.rs without duplication
  • All implementations moved
  • All imports updated in dependent files
  • cargo build succeeds
  • cargo test passes
  • Hook functionality still works (test with actual git commit)
  • hook.rs further reduced in size (should be ~450 lines now)
  • cargo clippy shows no warnings

Test manually

# Create test commit to verify patch generation works
cd test-repo
echo "new change" >> test.txt
git add test.txt
git commit --no-edit

# Should generate commit message successfully

Estimated Time

3-4 hours

Dependencies

Labels

  • refactor
  • module-structure
  • diff-processing

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions