use crate::surface::Surface;
#[derive(Debug, Default)]
pub struct SurfaceDiff {
pub added: Vec<String>,
pub removed: Vec<String>,
pub changed: Vec<(String, bool)>,
}
impl SurfaceDiff {
pub fn is_empty(&self) -> bool {
self.added.is_empty() && self.removed.is_empty() && self.changed.is_empty()
}
}
pub fn compare(old: &Surface, new: &Surface) -> SurfaceDiff {
let mut diff = SurfaceDiff::default();
for (path, info) in &new.items {
match old.items.get(path) {
None => diff.added.push(path.clone()),
Some(prev) => {
if info.kind != "module" && prev.fingerprint != info.fingerprint {
diff.changed
.push((path.clone(), prev.signature != info.signature));
}
}
}
}
for path in old.items.keys() {
if !new.items.contains_key(path) {
diff.removed.push(path.clone());
}
}
diff
}
pub fn render(diff: &SurfaceDiff) -> String {
if diff.is_empty() {
return "surface: no public API changes\n".into();
}
let mut out = String::new();
for p in &diff.added {
out.push_str(&format!("ADDED {p}\n"));
}
for p in &diff.removed {
out.push_str(&format!("REMOVED {p}\n"));
}
for (p, sig) in &diff.changed {
let what = if *sig { "signature" } else { "body" };
out.push_str(&format!("CHANGED {p} ({what})\n"));
}
out
}