#![allow(dead_code)]
use similar::{ChangeTag, TextDiff};
use std::path::Path;
#[derive(Debug, Clone, Default)]
pub struct DiffSummary {
pub insertions: usize,
pub deletions: usize,
pub summary: String,
pub unchanged: usize,
}
pub fn compute_diff(previous: &str, current: &str) -> DiffSummary {
let diff = TextDiff::from_lines(previous, current);
let mut insertions = 0;
let mut deletions = 0;
let mut unchanged = 0;
for change in diff.iter_all_changes() {
match change.tag() {
ChangeTag::Insert => insertions += 1,
ChangeTag::Delete => deletions += 1,
ChangeTag::Equal => unchanged += 1,
}
}
let summary = if insertions == 0 && deletions == 0 {
String::new()
} else {
format!("+{insertions} -{deletions}")
};
DiffSummary {
insertions,
deletions,
summary,
unchanged,
}
}
pub fn diff_files(previous_path: &Path, current_path: &Path) -> Option<DiffSummary> {
let previous = std::fs::read_to_string(previous_path).ok()?;
let current = std::fs::read_to_string(current_path).ok()?;
Some(compute_diff(&previous, ¤t))
}
pub fn format_diff_lines<'a>(previous: &'a str, current: &'a str) -> Vec<(char, &'a str)> {
let diff = TextDiff::from_lines(previous, current);
diff.iter_all_changes()
.map(|change| {
let symbol = match change.tag() {
ChangeTag::Insert => '+',
ChangeTag::Delete => '-',
ChangeTag::Equal => ' ',
};
(symbol, change.value())
})
.collect()
}