1use crate::objects::ObjectId;
4
5#[must_use]
16pub fn merge_object_ids_hex(input: &str) -> Vec<String> {
17 let mut out = Vec::new();
18 for line in input.lines() {
19 if line.trim().is_empty() {
20 continue;
21 }
22 let Some(first_tab) = line.find('\t') else {
23 continue;
24 };
25 let oid = &line[..first_tab];
26 if !ObjectId::is_full_hex(oid) {
27 continue;
28 }
29 let rest = &line[first_tab + 1..];
30 if rest.starts_with("not-for-merge") {
31 continue;
32 }
33 let desc = rest.strip_prefix('\t').unwrap_or(rest);
34 if desc.is_empty() {
35 continue;
36 }
37 out.push(oid.to_owned());
38 }
39 out
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45
46 #[test]
47 fn double_tab_for_merge_branch() {
48 let input = "a".repeat(40);
49 let line = format!("{input}\t\tbranch 'main' of ../repo2\n");
50 let oids = merge_object_ids_hex(&line);
51 assert_eq!(oids, vec![input]);
52 }
53
54 #[test]
55 fn not_for_merge_skipped() {
56 let input = format!(
57 "{}\tnot-for-merge\tbranch 'other' of ../x\n",
58 "b".repeat(40)
59 );
60 assert!(merge_object_ids_hex(&input).is_empty());
61 }
62
63 #[test]
64 fn bare_url_line_for_merge() {
65 let oid = "c".repeat(40);
66 let line = format!("{oid}\t\t../repo2\n");
67 assert_eq!(merge_object_ids_hex(&line), vec![oid]);
68 }
69}