rust/hg-core/src/copy_tracing.rs
changeset 46567 b6f65d90e8af
parent 46566 3c5a8b13206a
child 46568 0d840b9d200d
--- a/rust/hg-core/src/copy_tracing.rs	Wed Dec 23 03:04:33 2020 +0100
+++ b/rust/hg-core/src/copy_tracing.rs	Wed Dec 23 03:04:43 2020 +0100
@@ -15,7 +15,7 @@
 
 type PathToken = usize;
 
-#[derive(Clone, Debug, PartialEq, Copy)]
+#[derive(Clone, Debug, PartialEq)]
 struct CopySource {
     /// revision at which the copy information was added
     rev: Revision,
@@ -24,6 +24,42 @@
     path: Option<PathToken>,
 }
 
+impl CopySource {
+    /// create a new CopySource
+    ///
+    /// Use this when no previous copy source existed.
+    fn new(rev: Revision, path: Option<PathToken>) -> Self {
+        Self { rev, path }
+    }
+
+    /// create a new CopySource from merging two others
+    ///
+    /// Use this when merging two InternalPathCopies requires active merging of
+    /// some entries.
+    fn new_from_merge(rev: Revision, winner: &Self, loser: &Self) -> Self {
+        Self {
+            rev,
+            path: winner.path,
+        }
+    }
+
+    /// Update the value of a pre-existing CopySource
+    ///
+    /// Use this when recording copy information from  parent → child edges
+    fn overwrite(&mut self, rev: Revision, path: Option<PathToken>) {
+        self.rev = rev;
+        self.path = path;
+    }
+
+    /// Mark pre-existing copy information as "dropped" by a file deletion
+    ///
+    /// Use this when recording copy information from  parent → child edges
+    fn mark_delete(&mut self, rev: Revision) {
+        self.rev = rev;
+        self.path = None;
+    }
+}
+
 /// maps CopyDestination to Copy Source (+ a "timestamp" for the operation)
 type InternalPathCopies = OrdMap<PathToken, CopySource>;
 
@@ -521,17 +557,13 @@
                 // information. See merge_copies_dict for details.
                 match copies.entry(dest) {
                     Entry::Vacant(slot) => {
-                        let ttpc = CopySource {
-                            rev: current_rev,
-                            path: entry,
-                        };
+                        let ttpc = CopySource::new(current_rev, entry);
                         slot.insert(ttpc);
                     }
                     Entry::Occupied(mut slot) => {
-                        let mut ttpc = slot.get_mut();
+                        let ttpc = slot.get_mut();
                         oracle.record_overwrite(ttpc.rev, current_rev);
-                        ttpc.rev = current_rev;
-                        ttpc.path = entry;
+                        ttpc.overwrite(current_rev, entry);
                     }
                 }
             }
@@ -544,8 +576,7 @@
                 let deleted = path_map.tokenize(deleted_path);
                 copies.entry(deleted).and_modify(|old| {
                     oracle.record_overwrite(old.rev, current_rev);
-                    old.rev = current_rev;
-                    old.path = None;
+                    old.mark_delete(current_rev);
                 });
             }
         }
@@ -614,14 +645,22 @@
                     if overwrite {
                         oracle.record_overwrite(src_minor.rev, current_merge);
                         oracle.record_overwrite(src_major.rev, current_merge);
-                        let path = match pick {
-                            MergePick::Major => src_major.path,
-                            MergePick::Minor => src_minor.path,
-                            MergePick::Any => src_major.path,
-                        };
-                        let src = CopySource {
-                            rev: current_merge,
-                            path,
+                        let src = match pick {
+                            MergePick::Major => CopySource::new_from_merge(
+                                current_merge,
+                                src_major,
+                                &src_minor,
+                            ),
+                            MergePick::Minor => CopySource::new_from_merge(
+                                current_merge,
+                                &src_minor,
+                                src_major,
+                            ),
+                            MergePick::Any => CopySource::new_from_merge(
+                                current_merge,
+                                src_major,
+                                &src_minor,
+                            ),
                         };
                         major.insert(dest, src);
                     } else {
@@ -649,14 +688,22 @@
                     if overwrite {
                         oracle.record_overwrite(src_minor.rev, current_merge);
                         oracle.record_overwrite(src_major.rev, current_merge);
-                        let path = match pick {
-                            MergePick::Major => src_minor.path,
-                            MergePick::Minor => src_major.path,
-                            MergePick::Any => src_major.path,
-                        };
-                        let src = CopySource {
-                            rev: current_merge,
-                            path,
+                        let src = match pick {
+                            MergePick::Major => CopySource::new_from_merge(
+                                current_merge,
+                                &src_major,
+                                src_minor,
+                            ),
+                            MergePick::Minor => CopySource::new_from_merge(
+                                current_merge,
+                                src_minor,
+                                &src_major,
+                            ),
+                            MergePick::Any => CopySource::new_from_merge(
+                                current_merge,
+                                &src_major,
+                                src_minor,
+                            ),
                         };
                         minor.insert(dest, src);
                     } else {
@@ -706,16 +753,22 @@
                     if overwrite {
                         oracle.record_overwrite(src_minor.rev, current_merge);
                         oracle.record_overwrite(src_major.rev, current_merge);
-                        let path = match pick {
-                            MergePick::Major => src_major.path,
-                            MergePick::Minor => src_minor.path,
-                            // If the two entry are identical, no need to do
-                            // anything (but diff should not have yield them)
-                            MergePick::Any => src_major.path,
-                        };
-                        let src = CopySource {
-                            rev: current_merge,
-                            path,
+                        let src = match pick {
+                            MergePick::Major => CopySource::new_from_merge(
+                                current_merge,
+                                src_major,
+                                src_minor,
+                            ),
+                            MergePick::Minor => CopySource::new_from_merge(
+                                current_merge,
+                                src_minor,
+                                src_major,
+                            ),
+                            MergePick::Any => CopySource::new_from_merge(
+                                current_merge,
+                                src_major,
+                                src_minor,
+                            ),
                         };
                         to_minor(dest, &src);
                         to_major(dest, &src);