copies-rust: encapsulate internal sets on `changes`
authorPierre-Yves David <pierre-yves.david@octobus.net>
Mon, 05 Oct 2020 01:49:04 +0200
changeset 45975 2367937982ba
parent 45974 10bb0856bb9f
child 45976 cf04af3a5ef1
copies-rust: encapsulate internal sets on `changes` The goal is to eventually stop creating the underlying set. So we need to encapsulate the call first. Differential Revision: https://phab.mercurial-scm.org/D9306
rust/hg-core/src/copy_tracing.rs
--- a/rust/hg-core/src/copy_tracing.rs	Fri Oct 30 19:06:12 2020 +0100
+++ b/rust/hg-core/src/copy_tracing.rs	Mon Oct 05 01:49:04 2020 +0200
@@ -49,6 +49,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>,
@@ -88,6 +101,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
@@ -322,20 +346,21 @@
                     // same rev. So this is the same value.
                     unreachable!();
                 } else {
+                    let action = changes.get_merge_case(&dest);
                     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()
-                        && 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();
-                    } 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.