mercurial/copies.py
changeset 46158 1fcfff09cac5
parent 46150 a132aa5979ec
child 46159 929054848d6c
equal deleted inserted replaced
46157:021925827c60 46158:1fcfff09cac5
   355     """
   355     """
   356 
   356 
   357     alwaysmatch = match.always()
   357     alwaysmatch = match.always()
   358 
   358 
   359     if rustmod is not None and alwaysmatch:
   359     if rustmod is not None and alwaysmatch:
   360         return rustmod.combine_changeset_copies(
   360         final_copies = rustmod.combine_changeset_copies(
   361             list(revs), children_count, targetrev, revinfo, isancestor
   361             list(revs), children_count, targetrev, revinfo, isancestor
   362         )
   362         )
   363 
   363     else:
   364     isancestor = cached_is_ancestor(isancestor)
   364         isancestor = cached_is_ancestor(isancestor)
   365 
   365 
   366     all_copies = {}
   366         all_copies = {}
   367     # iterate over all the "children" side of copy tracing "edge"
   367         # iterate over all the "children" side of copy tracing "edge"
   368     for current_rev in revs:
   368         for current_rev in revs:
   369         p1, p2, changes = revinfo(current_rev)
   369             p1, p2, changes = revinfo(current_rev)
   370         current_copies = None
   370             current_copies = None
   371 
   371             # iterate over all parents to chain the existing data with the
   372         # iterate over all parents to chain the existing data with the
   372             # data from the parent → child edge.
   373         # data from the parent → child edge.
   373             for parent, parent_rev in ((1, p1), (2, p2)):
   374         for parent, parent_rev in ((1, p1), (2, p2)):
   374                 if parent_rev == nullrev:
   375             if parent_rev == nullrev:
   375                     continue
   376                 continue
   376                 remaining_children = children_count.get(parent_rev)
   377             remaining_children = children_count.get(parent_rev)
   377                 if remaining_children is None:
   378             if remaining_children is None:
   378                     continue
   379                 continue
   379                 remaining_children -= 1
   380             remaining_children -= 1
   380                 children_count[parent_rev] = remaining_children
   381             children_count[parent_rev] = remaining_children
   381                 if remaining_children:
   382             if remaining_children:
   382                     copies = all_copies.get(parent_rev, None)
   383                 copies = all_copies.get(parent_rev, None)
   383                 else:
   384             else:
   384                     copies = all_copies.pop(parent_rev, None)
   385                 copies = all_copies.pop(parent_rev, None)
   385 
   386 
   386                 if copies is None:
   387             if copies is None:
   387                     # this is a root
   388                 # this is a root
   388                     copies = {}
   389                 copies = {}
   389 
   390 
   390                 newcopies = copies
   391             newcopies = copies
   391                 # chain the data in the edge with the existing data
   392             # chain the data in the edge with the existing data
   392                 if changes is not None:
   393             if changes is not None:
   393                     childcopies = {}
   394                 childcopies = {}
   394                     if parent == 1:
   395                 if parent == 1:
   395                         childcopies = changes.copied_from_p1
   396                     childcopies = changes.copied_from_p1
   396                     elif parent == 2:
   397                 elif parent == 2:
   397                         childcopies = changes.copied_from_p2
   398                     childcopies = changes.copied_from_p2
   398 
   399 
   399                     if not alwaysmatch:
   400                 if not alwaysmatch:
   400                         childcopies = {
   401                     childcopies = {
   401                             dst: src
   402                         dst: src
   402                             for dst, src in childcopies.items()
   403                         for dst, src in childcopies.items()
   403                             if match(dst)
   404                         if match(dst)
   404                         }
   405                     }
   405                     if childcopies:
   406                 if childcopies:
       
   407                     newcopies = copies.copy()
       
   408                     for dest, source in pycompat.iteritems(childcopies):
       
   409                         prev = copies.get(source)
       
   410                         if prev is not None and prev[1] is not None:
       
   411                             source = prev[1]
       
   412                         newcopies[dest] = (current_rev, source)
       
   413                     assert newcopies is not copies
       
   414                 if changes.removed:
       
   415                     if newcopies is copies:
       
   416                         newcopies = copies.copy()
   406                         newcopies = copies.copy()
   417                     for f in changes.removed:
   407                         for dest, source in pycompat.iteritems(childcopies):
   418                         if f in newcopies:
   408                             prev = copies.get(source)
   419                             if newcopies is copies:
   409                             if prev is not None and prev[1] is not None:
   420                                 # copy on write to avoid affecting potential other
   410                                 source = prev[1]
   421                                 # branches.  when there are no other branches, this
   411                             newcopies[dest] = (current_rev, source)
   422                                 # could be avoided.
   412                         assert newcopies is not copies
   423                                 newcopies = copies.copy()
   413                     if changes.removed:
   424                             newcopies[f] = (current_rev, None)
   414                         if newcopies is copies:
   425 
   415                             newcopies = copies.copy()
   426             # check potential need to combine the data from another parent (for
   416                         for f in changes.removed:
   427             # that child). See comment below for details.
   417                             if f in newcopies:
   428             if current_copies is None:
   418                                 if newcopies is copies:
   429                 current_copies = newcopies
   419                                     # copy on write to avoid affecting potential other
   430             elif current_copies is newcopies:
   420                                     # branches.  when there are no other branches, this
   431                 # nothing to merge:
   421                                     # could be avoided.
   432                 pass
   422                                     newcopies = copies.copy()
   433             else:
   423                                 newcopies[f] = (current_rev, None)
   434                 # we are the second parent to work on c, we need to merge our
   424                 # check potential need to combine the data from another parent (for
   435                 # work with the other.
   425                 # that child). See comment below for details.
   436                 #
   426                 if current_copies is None:
   437                 # In case of conflict, parent 1 take precedence over parent 2.
   427                     current_copies = newcopies
   438                 # This is an arbitrary choice made anew when implementing
   428                 elif current_copies is newcopies:
   439                 # changeset based copies. It was made without regards with
   429                     # nothing to merge:
   440                 # potential filelog related behavior.
   430                     pass
   441                 assert parent == 2
   431                 else:
   442                 current_copies = _merge_copies_dict(
   432                     # we are the second parent to work on c, we need to merge our
   443                     newcopies, current_copies, isancestor, changes
   433                     # work with the other.
   444                 )
   434                     #
   445         all_copies[current_rev] = current_copies
   435                     # In case of conflict, parent 1 take precedence over parent 2.
   446 
   436                     # This is an arbitrary choice made anew when implementing
   447     # filter out internal details and return a {dest: source mapping}
   437                     # changeset based copies. It was made without regards with
   448     final_copies = {}
   438                     # potential filelog related behavior.
   449     for dest, (tt, source) in all_copies[targetrev].items():
   439                     assert parent == 2
   450         if source is not None:
   440                     current_copies = _merge_copies_dict(
   451             final_copies[dest] = source
   441                         newcopies, current_copies, isancestor, changes
       
   442                     )
       
   443             all_copies[current_rev] = current_copies
       
   444 
       
   445         # filter out internal details and return a {dest: source mapping}
       
   446         final_copies = {}
       
   447         for dest, (tt, source) in all_copies[targetrev].items():
       
   448             if source is not None:
       
   449                 final_copies[dest] = source
   452     return final_copies
   450     return final_copies
   453 
   451 
   454 
   452 
   455 def _merge_copies_dict(minor, major, isancestor, changes):
   453 def _merge_copies_dict(minor, major, isancestor, changes):
   456     """merge two copies-mapping together, minor and major
   454     """merge two copies-mapping together, minor and major