pub fn get_conflicted_files() -> io::Result<Vec<String>> {
let repo = git2::Repository::discover(".").map_err(|e| git2_to_io_error(&e))?;
get_conflicted_files_impl(&repo)
}
fn get_conflicted_files_impl(repo: &git2::Repository) -> io::Result<Vec<String>> {
let index = repo.index().map_err(|e| git2_to_io_error(&e))?;
if !index.has_conflicts() {
return Ok(Vec::new());
}
let conflicts = index.conflicts().map_err(|e| git2_to_io_error(&e))?;
Ok(conflicts
.filter_map(|conflict| {
conflict.ok().and_then(|c| c.our).and_then(|our_entry| {
std::str::from_utf8(&our_entry.path)
.ok()
.map(|path| path.to_string())
})
})
.collect::<std::collections::HashSet<_>>()
.into_iter()
.collect::<Vec<_>>())
}
pub fn get_conflict_markers_for_file(path: &Path) -> io::Result<String> {
use std::fs;
let mut file = fs::File::open(path)?;
let mut content = String::new();
std::io::Read::read_to_string(&mut file, &mut content)?;
let lines: Vec<&str> = content.lines().collect();
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParseState {
Normal,
InConflict,
InOurs,
InTheirs,
}
let conflict_sections: Vec<String> = lines
.iter()
.enumerate()
.scan(
(ParseState::Normal, Vec::new()),
|(state, section), (_i, line)| {
let trimmed = line.trim_start();
match (
*state,
trimmed.starts_with("<<<<<<<"),
trimmed.starts_with("======="),
trimmed.starts_with(">>>>>>>"),
) {
(_, true, _, _) => {
*state = ParseState::InConflict;
section.clear();
section.push(*line);
None
}
(ParseState::InConflict, _, true, _) => {
*state = ParseState::InOurs;
section.push(*line);
None
}
(ParseState::InOurs, _, _, true) => {
*state = ParseState::InTheirs;
section.push(*line);
None
}
(ParseState::InTheirs, _, _, true) => {
*state = ParseState::Normal;
section.push(*line);
let result = Some(section.join("\n"));
section.clear();
result
}
(
ParseState::InConflict | ParseState::InOurs | ParseState::InTheirs,
_,
_,
_,
) => {
section.push(*line);
None
}
_ => None,
}
},
)
.filter_map(Some)
.collect::<Vec<_>>();
if conflict_sections.is_empty() {
Ok(String::new())
} else {
Ok(conflict_sections.join("\n\n"))
}
}