Mercurial > hg
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. |