Generate detailed diff between checkpoints
(&self, from: &str, to: &str)
| 287 | |
| 288 | /// Generate detailed diff between checkpoints |
| 289 | pub fn diff(&self, from: &str, to: &str) -> Result<String> { |
| 290 | let mut result = String::new(); |
| 291 | |
| 292 | // Get file changes |
| 293 | let output = run_git(&self.shadow_repo_path, None, &["diff", "--name-status", from, to])?; |
| 294 | |
| 295 | for line in String::from_utf8_lossy(&output.stdout).lines() { |
| 296 | if let Some((status, file)) = line.split_once('\t') { |
| 297 | match status.chars().next() { |
| 298 | Some('A') => result.push_str(&format!(" + {} (added)\n", file).green().to_string()), |
| 299 | Some('M') => result.push_str(&format!(" ~ {} (modified)\n", file).yellow().to_string()), |
| 300 | Some('D') => result.push_str(&format!(" - {} (deleted)\n", file).red().to_string()), |
| 301 | Some('R' | 'C') => result.push_str(&format!(" ~ {} (renamed)\n", file).yellow().to_string()), |
| 302 | _ => {}, |
| 303 | } |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | // Add statistics |
| 308 | let stat_output = run_git(&self.shadow_repo_path, None, &[ |
| 309 | "diff", |
| 310 | from, |
| 311 | to, |
| 312 | "--stat", |
| 313 | "--color=always", |
| 314 | ])?; |
| 315 | |
| 316 | if stat_output.status.success() { |
| 317 | result.push('\n'); |
| 318 | result.push_str(&String::from_utf8_lossy(&stat_output.stdout)); |
| 319 | } |
| 320 | |
| 321 | Ok(result) |
| 322 | } |
| 323 | |
| 324 | /// Check for uncommitted changes |
| 325 | pub fn has_changes(&self) -> Result<bool> { |
no test coverage detected