D9584: copies: avoid early return in _combine_changeset_copies

marmoute (Pierre-Yves David) phabricator at mercurial-scm.org
Mon Dec 14 11:17:41 UTC 2020


marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  We have to change how we deal with matching (see next changeset) and that
  processing is common. So we shuffle things around before doing the semantic
  change for clarity.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D9584

AFFECTED FILES
  mercurial/copies.py

CHANGE DETAILS

diff --git a/mercurial/copies.py b/mercurial/copies.py
--- a/mercurial/copies.py
+++ b/mercurial/copies.py
@@ -356,98 +356,96 @@
     alwaysmatch = match.always()
 
     if rustmod is not None and alwaysmatch:
-        return rustmod.combine_changeset_copies(
+        final_copies = rustmod.combine_changeset_copies(
             list(revs), children_count, targetrev, revinfo, isancestor
         )
-
-    isancestor = cached_is_ancestor(isancestor)
-
-    all_copies = {}
-    # iterate over all the "children" side of copy tracing "edge"
-    for current_rev in revs:
-        p1, p2, changes = revinfo(current_rev)
-        current_copies = None
+    else:
+        isancestor = cached_is_ancestor(isancestor)
 
-        # iterate over all parents to chain the existing data with the
-        # data from the parent → child edge.
-        for parent, parent_rev in ((1, p1), (2, p2)):
-            if parent_rev == node.nullrev:
-                continue
-            remaining_children = children_count.get(parent_rev)
-            if remaining_children is None:
-                continue
-            remaining_children -= 1
-            children_count[parent_rev] = remaining_children
-            if remaining_children:
-                copies = all_copies.get(parent_rev, None)
-            else:
-                copies = all_copies.pop(parent_rev, None)
+        all_copies = {}
+        # iterate over all the "children" side of copy tracing "edge"
+        for current_rev in revs:
+            p1, p2, changes = revinfo(current_rev)
+            current_copies = None
+            # iterate over all parents to chain the existing data with the
+            # data from the parent → child edge.
+            for parent, parent_rev in ((1, p1), (2, p2)):
+                if parent_rev == node.nullrev:
+                    continue
+                remaining_children = children_count.get(parent_rev)
+                if remaining_children is None:
+                    continue
+                remaining_children -= 1
+                children_count[parent_rev] = remaining_children
+                if remaining_children:
+                    copies = all_copies.get(parent_rev, None)
+                else:
+                    copies = all_copies.pop(parent_rev, None)
 
-            if copies is None:
-                # this is a root
-                copies = {}
+                if copies is None:
+                    # this is a root
+                    copies = {}
 
-            newcopies = copies
-            # chain the data in the edge with the existing data
-            if changes is not None:
-                childcopies = {}
-                if parent == 1:
-                    childcopies = changes.copied_from_p1
-                elif parent == 2:
-                    childcopies = changes.copied_from_p2
+                newcopies = copies
+                # chain the data in the edge with the existing data
+                if changes is not None:
+                    childcopies = {}
+                    if parent == 1:
+                        childcopies = changes.copied_from_p1
+                    elif parent == 2:
+                        childcopies = changes.copied_from_p2
 
-                if not alwaysmatch:
-                    childcopies = {
-                        dst: src
-                        for dst, src in childcopies.items()
-                        if match(dst)
-                    }
-                if childcopies:
-                    newcopies = copies.copy()
-                    for dest, source in pycompat.iteritems(childcopies):
-                        prev = copies.get(source)
-                        if prev is not None and prev[1] is not None:
-                            source = prev[1]
-                        newcopies[dest] = (current_rev, source)
-                    assert newcopies is not copies
-                if changes.removed:
-                    if newcopies is copies:
+                    if not alwaysmatch:
+                        childcopies = {
+                            dst: src
+                            for dst, src in childcopies.items()
+                            if match(dst)
+                        }
+                    if childcopies:
                         newcopies = copies.copy()
-                    for f in changes.removed:
-                        if f in newcopies:
-                            if newcopies is copies:
-                                # copy on write to avoid affecting potential other
-                                # branches.  when there are no other branches, this
-                                # could be avoided.
-                                newcopies = copies.copy()
-                            newcopies[f] = (current_rev, None)
+                        for dest, source in pycompat.iteritems(childcopies):
+                            prev = copies.get(source)
+                            if prev is not None and prev[1] is not None:
+                                source = prev[1]
+                            newcopies[dest] = (current_rev, source)
+                        assert newcopies is not copies
+                    if changes.removed:
+                        if newcopies is copies:
+                            newcopies = copies.copy()
+                        for f in changes.removed:
+                            if f in newcopies:
+                                if newcopies is copies:
+                                    # copy on write to avoid affecting potential other
+                                    # branches.  when there are no other branches, this
+                                    # could be avoided.
+                                    newcopies = copies.copy()
+                                newcopies[f] = (current_rev, None)
+                # check potential need to combine the data from another parent (for
+                # that child). See comment below for details.
+                if current_copies is None:
+                    current_copies = newcopies
+                elif current_copies is newcopies:
+                    # nothing to merge:
+                    pass
+                else:
+                    # we are the second parent to work on c, we need to merge our
+                    # work with the other.
+                    #
+                    # In case of conflict, parent 1 take precedence over parent 2.
+                    # This is an arbitrary choice made anew when implementing
+                    # changeset based copies. It was made without regards with
+                    # potential filelog related behavior.
+                    assert parent == 2
+                    current_copies = _merge_copies_dict(
+                        newcopies, current_copies, isancestor, changes
+                    )
+            all_copies[current_rev] = current_copies
 
-            # check potential need to combine the data from another parent (for
-            # that child). See comment below for details.
-            if current_copies is None:
-                current_copies = newcopies
-            elif current_copies is newcopies:
-                # nothing to merge:
-                pass
-            else:
-                # we are the second parent to work on c, we need to merge our
-                # work with the other.
-                #
-                # In case of conflict, parent 1 take precedence over parent 2.
-                # This is an arbitrary choice made anew when implementing
-                # changeset based copies. It was made without regards with
-                # potential filelog related behavior.
-                assert parent == 2
-                current_copies = _merge_copies_dict(
-                    newcopies, current_copies, isancestor, changes
-                )
-        all_copies[current_rev] = current_copies
-
-    # filter out internal details and return a {dest: source mapping}
-    final_copies = {}
-    for dest, (tt, source) in all_copies[targetrev].items():
-        if source is not None:
-            final_copies[dest] = source
+        # filter out internal details and return a {dest: source mapping}
+        final_copies = {}
+        for dest, (tt, source) in all_copies[targetrev].items():
+            if source is not None:
+                final_copies[dest] = source
     return final_copies
 
 



To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel


More information about the Mercurial-devel mailing list