D6274: copies: document cases in _chain()
martinvonz (Martin von Zweigbergk)
phabricator at mercurial-scm.org
Thu Apr 18 12:55:20 EDT 2019
martinvonz created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
diff --git a/mercurial/copies.py b/mercurial/copies.py
@@ -108,26 +108,46 @@
return min(limit, a, b)
def _chain(src, dst, a, b):
- """chain two sets of copies a->b"""
+ """chain two sets of copies 'a' and 'b'"""
+ # When chaining copies in 'a' (from 'src' via some other commit 'mid') with
+ # copies in 'b' (from 'mid' to 'dst'), we can get the different cases in the
+ # following table (not including trivial cases). For example, case 2 is
+ # where a file existed in 'src' and remained under that name in 'mid' and
+ # then was renamed between 'mid' and 'dst'.
+ # case src mid dst result
+ # 1 a b - -
+ # 2 a b b a->b
+ # 3 a b a -
+ # 4 a b c a->c
+ # 5 - a b -
+ # 6 a a b a->b
+ # Initialize result ('t') from 'a'. This catches cases 1 & 2. We'll remove
+ # case 1 later. We'll also catch cases 3 & 4 here. Case 4 will be
+ # overwritten later, and case 3 will be removed later.
t = a.copy()
for k, v in b.iteritems():
if v in t:
- # found a chain
+ # found a chain, i.e. cases 3 & 4.
if t[v] != k:
- # file wasn't renamed back to itself
+ # file wasn't renamed back to itself (i.e. case 4, not 3)
t[k] = t[v]
if v not in dst:
# chain was a rename, not a copy
+ # this deletes the copy for 'b' in case 4
if v in src:
- # file is a copy of an existing file
+ # file is a copy of an existing file, i.e. case 6.
t[k] = v
for k, v in list(t.items()):
- # remove criss-crossed copies
+ # remove criss-crossed copies, i.e. case 3
if k in src and v in dst:
- # remove copies to files that were then removed
+ # remove copies to files that were then removed, i.e. case 1
+ # and file 'b' in cases 3 & 4 (in case of rename)
elif k not in dst:
To: martinvonz, #hg-reviewers
More information about the Mercurial-devel