use std::collections::BTreeMap;
use super::LineRange;
#[must_use]
pub fn added_lines(patch: &str) -> BTreeMap<String, Vec<LineRange>> {
let mut out: BTreeMap<String, Vec<LineRange>> = BTreeMap::new();
let mut current: Option<String> = None;
for line in patch.lines() {
if line.starts_with("diff --git ") {
current = None;
} else if let Some(name) = line.strip_prefix("+++ ") {
current = name
.strip_prefix("b/")
.filter(|_| !name.starts_with('"'))
.map(str::to_owned);
} else if let (Some(path), Some(header)) = (¤t, line.strip_prefix("@@ "))
&& let Some(range) = new_range(header)
{
out.entry(path.clone()).or_default().push(range);
}
}
out
}
fn new_range(header: &str) -> Option<LineRange> {
let plus = header.split(' ').find_map(|w| w.strip_prefix('+'))?;
let (start, count) = match plus.split_once(',') {
Some((start, count)) => (start.parse::<u32>().ok()?, count.parse::<u32>().ok()?),
None => (plus.parse::<u32>().ok()?, 1),
};
if count == 0 || start == 0 {
return None;
}
Some(LineRange {
start,
end: start.saturating_add(count - 1),
})
}