use crate::model::{FileContent, Hunk, Patch};
fn anchor(start: u32, count: u32) -> i64 {
i64::from(start) + i64::from(count == 0)
}
pub fn expected_new_start(h: &Hunk, delta: i64) -> u32 {
let a = anchor(h.old_start, h.old_lines) + delta;
let start = if h.new_lines == 0 { a - 1 } else { a };
start.clamp(0, i64::from(u32::MAX)) as u32
}
pub fn renumber_new_side(patch: &mut Patch) {
for f in &mut patch.files {
let FileContent::Text(hunks) = &mut f.content else {
continue; };
let mut delta: i64 = 0;
for h in hunks.iter_mut() {
h.new_start = expected_new_start(h, delta);
let (add, del) = h.change_counts();
delta += i64::from(add) - i64::from(del);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::emit::emit;
use crate::parser::parse;
fn keep_hunks(src: &str, keep: &[usize]) -> String {
let mut p = parse(src.as_bytes()).unwrap();
for f in &mut p.files {
if let FileContent::Text(hunks) = &mut f.content {
let mut i = 0;
hunks.retain(|_| {
let k = keep.contains(&i);
i += 1;
k
});
}
}
renumber_new_side(&mut p);
String::from_utf8(emit(&p)).unwrap()
}
const INSERT_THEN_REPLACE: &str = "\
diff --git a/f b/f
--- a/f
+++ b/f
@@ -2,3 +2,4 @@
b
+new
c
d
@@ -17,3 +18,3 @@
q
-r
+R
s
";
#[test]
fn dropping_an_insertion_shifts_the_next_hunk_back() {
let out = keep_hunks(INSERT_THEN_REPLACE, &[1]);
assert!(out.contains("@@ -17,3 +17,3 @@"), "{out}");
}
#[test]
fn keeping_everything_reproduces_the_input_anchors() {
let out = keep_hunks(INSERT_THEN_REPLACE, &[0, 1]);
assert!(out.contains("@@ -2,3 +2,4 @@"), "{out}");
assert!(out.contains("@@ -17,3 +18,3 @@"), "{out}");
}
#[test]
fn dropping_a_deletion_shifts_the_next_hunk_forward() {
let src = "\
diff --git a/f b/f
--- a/f
+++ b/f
@@ -2,3 +2,2 @@
b
-c
d
@@ -17,3 +16,3 @@
q
-r
+R
s
";
let out = keep_hunks(src, &[1]);
assert!(out.contains("@@ -17,3 +17,3 @@"), "{out}");
}
#[test]
fn zero_count_sides_report_the_preceding_line() {
let src = "\
diff --git a/f b/f
--- a/f
+++ b/f
@@ -1,2 +1,0 @@
-a
-b
@@ -5,0 +4,2 @@
+x
+y
";
let out = keep_hunks(src, &[0, 1]);
assert!(out.contains("@@ -1,2 +0,0 @@"), "{out}");
assert!(out.contains("@@ -5,0 +4,2 @@"), "{out}");
let only_insert = keep_hunks(src, &[1]);
assert!(only_insert.contains("@@ -5,0 +6,2 @@"), "{only_insert}");
}
}