1use crate::note::Note;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct HunkAnchor {
5 pub file: String,
6 pub line_start: u32,
7 pub line_end: u32,
8 pub commit: String,
9}
10
11impl HunkAnchor {
12 pub fn matches_note(&self, note: &Note) -> bool {
13 if note.commit != self.commit {
14 return false;
15 }
16 if let Some(ref f) = note.file {
17 if f != &self.file {
18 return false;
19 }
20 }
21 if let (Some(ns), Some(ne)) = (note.line_start, note.line_end) {
22 if ne < self.line_start || ns > self.line_end {
24 return false;
25 }
26 }
27 true
28 }
29}
30
31pub fn parse_diff_hunks(patch: &str) -> Vec<HunkAnchor> {
32 let mut anchors = Vec::new();
33 let mut current_file = String::new();
34 let current_commit = "pending".to_string(); for line in patch.lines() {
37 if let Some(f) = line.strip_prefix("+++ b/") {
38 current_file = f.to_string();
39 } else if line.starts_with("@@ ") {
40 if let Some(end_idx) = line[3..].find(" @@") {
42 let hunk_info = &line[3..3 + end_idx];
43 let parts: Vec<&str> = hunk_info.split_whitespace().collect();
44 if parts.len() >= 2 {
45 let added = parts[1]; let added_nums = &added[1..];
47 let line_parts: Vec<&str> = added_nums.split(',').collect();
48 if !line_parts.is_empty() {
49 if let Ok(start) = line_parts[0].parse::<u32>() {
50 let count = if line_parts.len() > 1 {
51 line_parts[1].parse::<u32>().unwrap_or(1)
52 } else {
53 1
54 };
55 anchors.push(HunkAnchor {
56 file: current_file.clone(),
57 line_start: start,
58 line_end: start + count.saturating_sub(1),
59 commit: current_commit.clone(),
60 });
61 }
62 }
63 }
64 }
65 }
66 }
67
68 anchors
69}