use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::git;
use crate::worktree::Workspace;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileConflict {
pub file: String,
pub worktrees: Vec<String>, }
pub fn detect(workspaces: &[Workspace]) -> Result<Vec<FileConflict>> {
let mut file_map: HashMap<String, Vec<String>> = HashMap::new();
for ws in workspaces {
if ws.status != crate::worktree::WorkspaceStatus::Active {
continue;
}
let merge_base = match git::get_merge_base(&ws.path, &ws.base_branch, "HEAD") {
Ok(base) => base,
Err(_) => continue, };
let changed = match git::get_changed_files(&ws.path, &merge_base, "HEAD") {
Ok(files) => files,
Err(_) => continue,
};
for file in changed {
file_map.entry(file).or_default().push(ws.ticket.clone());
}
}
let mut conflicts: Vec<FileConflict> = file_map
.into_iter()
.filter(|(_, tickets)| tickets.len() > 1)
.map(|(file, worktrees)| FileConflict { file, worktrees })
.collect();
conflicts.sort_by(|a, b| {
b.worktrees
.len()
.cmp(&a.worktrees.len())
.then_with(|| a.file.cmp(&b.file))
});
Ok(conflicts)
}