diff --git a/rust/hg-core/src/copy_tracing.rs b/rust/hg-core/src/copy_tracing.rs index e4384b8f4858e129bd2f9b7702fb8a669e881d62_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM=..bb731461b4c96eae26db66e9e4ca3c810c036c63_cnVzdC9oZy1jb3JlL3NyYy9jb3B5X3RyYWNpbmcucnM= 100644 --- a/rust/hg-core/src/copy_tracing.rs +++ b/rust/hg-core/src/copy_tracing.rs @@ -47,6 +47,19 @@ Copied(&'a HgPath, &'a HgPath), } +/// This express the possible "special" case we can get in a merge +/// +/// See mercurial/metadata.py for details on these values. +#[derive(PartialEq)] +enum MergeCase { + /// Merged: file had history on both side that needed to be merged + Merged, + /// Salvaged: file was candidate for deletion, but survived the merge + Salvaged, + /// Normal: Not one of the two cases above + Normal, +} + impl ChangedFiles { pub fn new( removed: HashSet<HgPathBuf>, @@ -86,6 +99,17 @@ let remove_iter = remove_iter.map(|x| Action::Removed(x)); copies_iter.chain(remove_iter) } + + /// return the MergeCase value associated with a filename + fn get_merge_case(&self, path: &HgPath) -> MergeCase { + if self.salvaged.contains(path) { + return MergeCase::Salvaged; + } else if self.merged.contains(path) { + return MergeCase::Merged; + } else { + return MergeCase::Normal; + } + } } /// A struct responsible for answering "is X ancestors of Y" quickly @@ -318,4 +342,5 @@ // same rev. So this is the same value. unreachable!(); } else { + let action = changes.get_merge_case(&dest); if src_major.path.is_none() @@ -321,7 +346,7 @@ if src_major.path.is_none() - && changes.salvaged.contains(dest) + && action == MergeCase::Salvaged { // If the file is "deleted" in the major side but was // salvaged by the merge, we keep the minor side alive pick_minor(); } else if src_minor.path.is_none() @@ -323,11 +348,11 @@ { // If the file is "deleted" in the major side but was // salvaged by the merge, we keep the minor side alive pick_minor(); } else if src_minor.path.is_none() - && changes.salvaged.contains(dest) + && action == MergeCase::Salvaged { // If the file is "deleted" in the minor side but was // salvaged by the merge, unconditionnaly preserve the // major side. pick_major(); @@ -329,9 +354,9 @@ { // If the file is "deleted" in the minor side but was // salvaged by the merge, unconditionnaly preserve the // major side. pick_major(); - } else if changes.merged.contains(dest) { + } else if action == MergeCase::Merged { // If the file was actively merged, copy information // from each side might conflict. The major side will // win such conflict.