pub fn contains_line_start_conflict_markers(content: &[u8]) -> bool {
content.split(|byte| *byte == b'\n').any(|line| {
line.starts_with(b"<<<<<<<") || line.starts_with(b"=======") || line.starts_with(b">>>>>>>")
})
}
pub fn unresolved_conflict_paths(conflicts: &[String], resolved: &[String]) -> Vec<String> {
conflicts
.iter()
.filter(|path| !resolved.iter().any(|r| r == *path))
.cloned()
.collect()
}
pub fn path_is_active_conflict(conflicts: &[String], path: &str) -> bool {
conflicts.iter().any(|c| c == path)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ResolveSideSelection {
Worktree,
Ours,
Theirs,
}
pub fn plan_resolve_side(ours: bool, theirs: bool) -> Option<ResolveSideSelection> {
match (ours, theirs) {
(true, true) => None,
(true, false) => Some(ResolveSideSelection::Ours),
(false, true) => Some(ResolveSideSelection::Theirs),
(false, false) => Some(ResolveSideSelection::Worktree),
}
}
pub fn resolve_requires_marker_check(side: ResolveSideSelection, force: bool) -> bool {
matches!(side, ResolveSideSelection::Worktree) && !force
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn line_start_markers_detect_git_style_lines() {
assert!(contains_line_start_conflict_markers(
b"keep\n<<<<<<< HEAD\nours\n=======\ntheirs\n>>>>>>> branch\n"
));
assert!(contains_line_start_conflict_markers(b"=======\n"));
assert!(!contains_line_start_conflict_markers(b"no markers here\n"));
assert!(!contains_line_start_conflict_markers(b"x<<<<<<<\n"));
}
#[test]
fn unresolved_paths_filter_resolved() {
let conflicts = vec!["a.rs".into(), "b.rs".into(), "c.rs".into()];
let resolved = vec!["b.rs".into()];
assert_eq!(
unresolved_conflict_paths(&conflicts, &resolved),
vec!["a.rs".to_string(), "c.rs".to_string()]
);
assert!(path_is_active_conflict(&conflicts, "a.rs"));
assert!(!path_is_active_conflict(&conflicts, "z.rs"));
}
#[test]
fn plan_resolve_side_and_marker_gate() {
assert_eq!(
plan_resolve_side(false, false),
Some(ResolveSideSelection::Worktree)
);
assert_eq!(
plan_resolve_side(true, false),
Some(ResolveSideSelection::Ours)
);
assert_eq!(
plan_resolve_side(false, true),
Some(ResolveSideSelection::Theirs)
);
assert_eq!(plan_resolve_side(true, true), None);
assert!(resolve_requires_marker_check(
ResolveSideSelection::Worktree,
false
));
assert!(!resolve_requires_marker_check(
ResolveSideSelection::Worktree,
true
));
assert!(!resolve_requires_marker_check(
ResolveSideSelection::Ours,
false
));
}
}