use crate::bare::GitBare; use crate::error::GitResult; use crate::pb::*; impl GitBare { /// Get raw changes between two revisions (file-level changes only, no diff content). pub fn get_raw_changes( &self, request: GetRawChangesRequest, ) -> GitResult { crate::sanitize::validate_revision(&request.base)?; crate::sanitize::validate_revision(&request.head)?; let output = std::process::Command::new("git") .args([ "--git-dir", &self.bare_dir.to_string_lossy(), "diff-tree", "--raw", "-r", "--root", &request.base, &request.head, ]) .stdout(std::process::Stdio::piped()) .stderr(std::process::Stdio::piped()) .output() .map_err(|e| crate::error::GitError::CommandFailed { status_code: None, stderr: e.to_string(), })?; let stdout = String::from_utf8_lossy(&output.stdout); let mut changes = Vec::new(); for line in stdout.lines() { let line = line.trim(); if !line.starts_with(':') { continue; } let line = &line[1..]; let parts: Vec<&str> = line.split_whitespace().collect(); if parts.len() < 5 { continue; } let old_mode = u32::from_str_radix(parts[0], 8).unwrap_or(0); let new_mode = u32::from_str_radix(parts[1], 8).unwrap_or(0); let old_oid = parts[2].to_string(); let new_oid = parts[3].to_string(); let status_str = parts[4]; let status_letter = status_str.chars().next().unwrap_or('M'); let operation = match status_letter { 'A' => raw_change::Operation::RawChangeOperationAdded as i32, 'D' => raw_change::Operation::RawChangeOperationDeleted as i32, 'R' => raw_change::Operation::RawChangeOperationRenamed as i32, 'C' => raw_change::Operation::RawChangeOperationCopied as i32, 'M' | 'T' => raw_change::Operation::RawChangeOperationModified as i32, _ => raw_change::Operation::RawChangeOperationUnspecified as i32, }; let (old_path, new_path) = if parts.len() >= 6 { ( parts[5].to_string(), if status_letter == 'R' || status_letter == 'C' { parts.get(6).map(|s| s.to_string()).unwrap_or_default() } else { String::new() }, ) } else { (String::new(), String::new()) }; changes.push(RawChange { operation, old_path, new_path, old_mode, new_mode, old_oid, new_oid, similarity: 0.0, }); } Ok(GetRawChangesResponse { changes }) } }