mercurial/copies.py
changeset 42227 d1c2688eda80
parent 42226 a6be3af3a397
child 42228 df7ad90edbd4
equal deleted inserted replaced
42226:a6be3af3a397 42227:d1c2688eda80
   106     # back far enough unless we also look at the a and b as candidates.
   106     # back far enough unless we also look at the a and b as candidates.
   107     # This only occurs when a is a descendent of b or visa-versa.
   107     # This only occurs when a is a descendent of b or visa-versa.
   108     return min(limit, a, b)
   108     return min(limit, a, b)
   109 
   109 
   110 def _chain(src, dst, a, b):
   110 def _chain(src, dst, a, b):
   111     """chain two sets of copies a->b"""
   111     """chain two sets of copies 'a' and 'b'"""
       
   112 
       
   113     # When chaining copies in 'a' (from 'src' via some other commit 'mid') with
       
   114     # copies in 'b' (from 'mid' to 'dst'), we can get the different cases in the
       
   115     # following table (not including trivial cases). For example, case 2 is
       
   116     # where a file existed in 'src' and remained under that name in 'mid' and
       
   117     # then was renamed between 'mid' and 'dst'.
       
   118     #
       
   119     # case src mid dst result
       
   120     #   1   x   y   -    -
       
   121     #   2   x   y   y   x->y
       
   122     #   3   x   y   x    -
       
   123     #   4   x   y   z   x->z
       
   124     #   5   -   x   y    -
       
   125     #   6   x   x   y   x->y
       
   126 
       
   127     # Initialize result ('t') from 'a'. This catches cases 1 & 2. We'll remove
       
   128     # case 1 later. We'll also catch cases 3 & 4 here. Case 4 will be
       
   129     # overwritten later, and case 3 will be removed later.
   112     t = a.copy()
   130     t = a.copy()
   113     for k, v in b.iteritems():
   131     for k, v in b.iteritems():
   114         if v in t:
   132         if v in t:
   115             # found a chain
   133             # found a chain, i.e. cases 3 & 4.
   116             if t[v] != k:
   134             if t[v] != k:
   117                 # file wasn't renamed back to itself
   135                 # file wasn't renamed back to itself (i.e. case 4, not 3)
   118                 t[k] = t[v]
   136                 t[k] = t[v]
   119             if v not in dst:
   137             if v not in dst:
   120                 # chain was a rename, not a copy
   138                 # chain was a rename, not a copy
       
   139                 # this deletes the copy for 'y' in case 4
   121                 del t[v]
   140                 del t[v]
   122         if v in src:
   141         if v in src:
   123             # file is a copy of an existing file
   142             # file is a copy of an existing file, i.e. case 6.
   124             t[k] = v
   143             t[k] = v
   125 
   144 
   126     for k, v in list(t.items()):
   145     for k, v in list(t.items()):
   127         # remove criss-crossed copies
   146         # remove criss-crossed copies, i.e. case 3
   128         if k in src and v in dst:
   147         if k in src and v in dst:
   129             del t[k]
   148             del t[k]
   130         # remove copies to files that were then removed
   149         # remove copies to files that were then removed, i.e. case 1
       
   150         # and file 'y' in cases 3 & 4 (in case of rename)
   131         elif k not in dst:
   151         elif k not in dst:
   132             del t[k]
   152             del t[k]
   133 
   153 
   134     return t
   154     return t
   135 
   155