mercurial/copies.py
changeset 46148 70a9eb899637
parent 46113 59fa3890d40a
child 46149 294d5aca4ff5
equal deleted inserted replaced
46146:d109dda4a3e7 46148:70a9eb899637
       
     1 # coding: utf8
     1 # copies.py - copy detection for Mercurial
     2 # copies.py - copy detection for Mercurial
     2 #
     3 #
     3 # Copyright 2008 Matt Mackall <mpm@selenic.com>
     4 # Copyright 2008 Matt Mackall <mpm@selenic.com>
     4 #
     5 #
     5 # This software may be used and distributed according to the terms of the
     6 # This software may be used and distributed according to the terms of the
   349         )
   350         )
   350 
   351 
   351     isancestor = cached_is_ancestor(isancestor)
   352     isancestor = cached_is_ancestor(isancestor)
   352 
   353 
   353     all_copies = {}
   354     all_copies = {}
       
   355     # iterate over all the "parent" side of copy tracing "edge"
   354     for r in revs:
   356     for r in revs:
       
   357         # fetch potential previously computed data for that parent
   355         copies = all_copies.pop(r, None)
   358         copies = all_copies.pop(r, None)
   356         if copies is None:
   359         if copies is None:
   357             # this is a root
   360             # this is a root
   358             copies = {}
   361             copies = {}
       
   362 
       
   363         # iterate over all known children to chain the existing data with the
       
   364         # data from the parent → child edge.
   359         for i, c in enumerate(children[r]):
   365         for i, c in enumerate(children[r]):
   360             p1, p2, changes = revinfo(c)
   366             p1, p2, changes = revinfo(c)
   361             childcopies = {}
   367             childcopies = {}
       
   368 
       
   369             # select the right parent → child edge
   362             if r == p1:
   370             if r == p1:
   363                 parent = 1
   371                 parent = 1
   364                 if changes is not None:
   372                 if changes is not None:
   365                     childcopies = changes.copied_from_p1
   373                     childcopies = changes.copied_from_p1
   366             else:
   374             else:
   370                     childcopies = changes.copied_from_p2
   378                     childcopies = changes.copied_from_p2
   371             if not alwaysmatch:
   379             if not alwaysmatch:
   372                 childcopies = {
   380                 childcopies = {
   373                     dst: src for dst, src in childcopies.items() if match(dst)
   381                     dst: src for dst, src in childcopies.items() if match(dst)
   374                 }
   382                 }
       
   383 
       
   384             # chain the data in the edge with the existing data
   375             newcopies = copies
   385             newcopies = copies
   376             if childcopies:
   386             if childcopies:
   377                 newcopies = copies.copy()
   387                 newcopies = copies.copy()
   378                 for dest, source in pycompat.iteritems(childcopies):
   388                 for dest, source in pycompat.iteritems(childcopies):
   379                     prev = copies.get(source)
   389                     prev = copies.get(source)
   390                             # copy on write to avoid affecting potential other
   400                             # copy on write to avoid affecting potential other
   391                             # branches.  when there are no other branches, this
   401                             # branches.  when there are no other branches, this
   392                             # could be avoided.
   402                             # could be avoided.
   393                             newcopies = copies.copy()
   403                             newcopies = copies.copy()
   394                         newcopies[f] = (c, None)
   404                         newcopies[f] = (c, None)
       
   405 
       
   406             # check potential need to combine the data from another parent (for
       
   407             # that child). See comment below for details.
   395             othercopies = all_copies.get(c)
   408             othercopies = all_copies.get(c)
   396             if othercopies is None:
   409             if othercopies is None:
   397                 all_copies[c] = newcopies
   410                 all_copies[c] = newcopies
   398             elif newcopies is othercopies:
   411             elif newcopies is othercopies:
   399                 # nothing to merge:
   412                 # nothing to merge:
   416                     # unnecessary.
   429                     # unnecessary.
   417                     minor, major = newcopies, othercopies.copy()
   430                     minor, major = newcopies, othercopies.copy()
   418                 copies = _merge_copies_dict(minor, major, isancestor, changes)
   431                 copies = _merge_copies_dict(minor, major, isancestor, changes)
   419                 all_copies[c] = copies
   432                 all_copies[c] = copies
   420 
   433 
       
   434     # filter out internal details and return a {dest: source mapping}
   421     final_copies = {}
   435     final_copies = {}
   422     for dest, (tt, source) in all_copies[targetrev].items():
   436     for dest, (tt, source) in all_copies[targetrev].items():
   423         if source is not None:
   437         if source is not None:
   424             final_copies[dest] = source
   438             final_copies[dest] = source
   425     return final_copies
   439     return final_copies