comparison mercurial/copies.py @ 18136:f23dea2b296e

copies: do not track backward copies, only renames (issue3739) The inverse of a rename is a rename, but the inverse of a copy is not a copy. Presenting it as such -- in particular, stuffing it into the same dict as real copies -- causes bugs because other code starts believing the inverse copies are real. The only test whose output changes is test-mv-cp-st-diff.t. When a backwards status -C command is run where a copy is involved, the inverse copy (which was hitherto presented as a real copy) is no longer displayed. Keeping track of inverse copies is useful in some situations -- composability of diffs, for example, since adding "a" followed by an inverse copy "b" to "a" is equivalent to a rename "b" to "a". However, representing them would require a more complex data structure than the same dict in which real copies are also stored.
author Siddharth Agarwal <sid0@fb.com>
date Wed, 26 Dec 2012 15:04:07 -0800
parents a6fe1b9cc68f
children 2330d97e7707
comparison
equal deleted inserted replaced
18135:a6fe1b9cc68f 18136:f23dea2b296e
143 if w is not None: 143 if w is not None:
144 cm = _chain(a, w, cm, _dirstatecopies(w)) 144 cm = _chain(a, w, cm, _dirstatecopies(w))
145 145
146 return cm 146 return cm
147 147
148 def _backwardcopies(a, b): 148 def _backwardrenames(a, b):
149 # because the forward mapping is 1:n, we can lose renames here 149 # Even though we're not taking copies into account, 1:n rename situations
150 # in particular, we find renames better than copies 150 # can still exist (e.g. hg cp a b; hg mv a c). In those cases we
151 # arbitrarily pick one of the renames.
151 f = _forwardcopies(b, a) 152 f = _forwardcopies(b, a)
152 r = {} 153 r = {}
153 for k, v in f.iteritems(): 154 for k, v in f.iteritems():
155 # remove copies
156 if v in a:
157 continue
154 r[v] = k 158 r[v] = k
155 return r 159 return r
156 160
157 def pathcopies(x, y): 161 def pathcopies(x, y):
158 '''find {dst@y: src@x} copy mapping for directed compare''' 162 '''find {dst@y: src@x} copy mapping for directed compare'''
160 return {} 164 return {}
161 a = y.ancestor(x) 165 a = y.ancestor(x)
162 if a == x: 166 if a == x:
163 return _forwardcopies(x, y) 167 return _forwardcopies(x, y)
164 if a == y: 168 if a == y:
165 return _backwardcopies(x, y) 169 return _backwardrenames(x, y)
166 return _chain(x, y, _backwardcopies(x, a), _forwardcopies(a, y)) 170 return _chain(x, y, _backwardrenames(x, a), _forwardcopies(a, y))
167 171
168 def mergecopies(repo, c1, c2, ca): 172 def mergecopies(repo, c1, c2, ca):
169 """ 173 """
170 Find moves and copies between context c1 and c2 that are relevant 174 Find moves and copies between context c1 and c2 that are relevant
171 for merging. 175 for merging.