Details
Details
- Reviewers
yuja - Group Reviewers
hg-reviewers - Commits
- rHG9cf37d111acb: copies: consistently use """ for docstrings
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Lint
Lint Skipped - Unit
Unit Tests Skipped
( )
yuja |
hg-reviewers |
Lint Skipped |
Unit Tests Skipped |
Path | Packages | |||
---|---|---|---|---|
M | mercurial/copies.py (14 lines) |
Status | Author | Revision | |
---|---|---|---|
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz | ||
Closed | martinvonz |
# | # | ||||
# When _findlimit is called, a and b are revs 3 and 0, so limit will be 2, | # When _findlimit is called, a and b are revs 3 and 0, so limit will be 2, | ||||
# yet the filelog has the copy information in rev 1 and we will not look | # yet the filelog has the copy information in rev 1 and we will not look | ||||
# back far enough unless we also look at the a and b as candidates. | # back far enough unless we also look at the a and b as candidates. | ||||
# This only occurs when a is a descendent of b or visa-versa. | # This only occurs when a is a descendent of b or visa-versa. | ||||
return min(limit, a, b) | return min(limit, a, b) | ||||
def _chain(src, dst, a, b): | def _chain(src, dst, a, b): | ||||
'''chain two sets of copies a->b''' | """chain two sets of copies a->b""" | ||||
t = a.copy() | t = a.copy() | ||||
for k, v in b.iteritems(): | for k, v in b.iteritems(): | ||||
if v in t: | if v in t: | ||||
# found a chain | # found a chain | ||||
if t[v] != k: | if t[v] != k: | ||||
# file wasn't renamed back to itself | # file wasn't renamed back to itself | ||||
t[k] = t[v] | t[k] = t[v] | ||||
if v not in dst: | if v not in dst: | ||||
# chain was a rename, not a copy | # chain was a rename, not a copy | ||||
del t[v] | del t[v] | ||||
if v in src: | if v in src: | ||||
# file is a copy of an existing file | # file is a copy of an existing file | ||||
t[k] = v | t[k] = v | ||||
# remove criss-crossed copies | # remove criss-crossed copies | ||||
for k, v in t.items(): | for k, v in t.items(): | ||||
if k in src and v in dst: | if k in src and v in dst: | ||||
del t[k] | del t[k] | ||||
return t | return t | ||||
def _tracefile(fctx, am, limit=-1): | def _tracefile(fctx, am, limit=-1): | ||||
'''return file context that is the ancestor of fctx present in ancestor | """return file context that is the ancestor of fctx present in ancestor | ||||
manifest am, stopping after the first ancestor lower than limit''' | manifest am, stopping after the first ancestor lower than limit""" | ||||
for f in fctx.ancestors(): | for f in fctx.ancestors(): | ||||
if am.get(f.path(), None) == f.filenode(): | if am.get(f.path(), None) == f.filenode(): | ||||
return f | return f | ||||
if limit >= 0 and f.linkrev() < limit and f.rev() < limit: | if limit >= 0 and f.linkrev() < limit and f.rev() < limit: | ||||
return None | return None | ||||
def _dirstatecopies(d, match=None): | def _dirstatecopies(d, match=None): | ||||
This is its own function so extensions can easily wrap this call to see what | This is its own function so extensions can easily wrap this call to see what | ||||
files _forwardcopies is about to process. | files _forwardcopies is about to process. | ||||
""" | """ | ||||
ma = a.manifest() | ma = a.manifest() | ||||
mb = b.manifest() | mb = b.manifest() | ||||
return mb.filesnotin(ma, match=match) | return mb.filesnotin(ma, match=match) | ||||
def _forwardcopies(a, b, match=None): | def _forwardcopies(a, b, match=None): | ||||
'''find {dst@b: src@a} copy mapping where a is an ancestor of b''' | """find {dst@b: src@a} copy mapping where a is an ancestor of b""" | ||||
# check for working copy | # check for working copy | ||||
w = None | w = None | ||||
if b.rev() is None: | if b.rev() is None: | ||||
w = b | w = b | ||||
b = w.p1() | b = w.p1() | ||||
if a == b: | if a == b: | ||||
# short-circuit to avoid issues with merge states | # short-circuit to avoid issues with merge states | ||||
for k, v in sorted(f.iteritems()): | for k, v in sorted(f.iteritems()): | ||||
# remove copies | # remove copies | ||||
if v in a: | if v in a: | ||||
continue | continue | ||||
r[v] = k | r[v] = k | ||||
return r | return r | ||||
def pathcopies(x, y, match=None): | def pathcopies(x, y, match=None): | ||||
'''find {dst@y: src@x} copy mapping for directed compare''' | """find {dst@y: src@x} copy mapping for directed compare""" | ||||
if x == y or not x or not y: | if x == y or not x or not y: | ||||
return {} | return {} | ||||
a = y.ancestor(x) | a = y.ancestor(x) | ||||
if a == x: | if a == x: | ||||
return _forwardcopies(x, y, match=match) | return _forwardcopies(x, y, match=match) | ||||
if a == y: | if a == y: | ||||
return _backwardrenames(x, y) | return _backwardrenames(x, y) | ||||
return _chain(x, y, _backwardrenames(x, a), | return _chain(x, y, _backwardrenames(x, a), | ||||
if sf in mb: | if sf in mb: | ||||
if tca == base: | if tca == base: | ||||
data['diverge'].setdefault(sf, []).append(f) | data['diverge'].setdefault(sf, []).append(f) | ||||
else: | else: | ||||
data['incompletediverge'][sf] = [of, f] | data['incompletediverge'][sf] = [of, f] | ||||
return | return | ||||
def duplicatecopies(repo, wctx, rev, fromrev, skiprev=None): | def duplicatecopies(repo, wctx, rev, fromrev, skiprev=None): | ||||
'''reproduce copies from fromrev to rev in the dirstate | """reproduce copies from fromrev to rev in the dirstate | ||||
If skiprev is specified, it's a revision that should be used to | If skiprev is specified, it's a revision that should be used to | ||||
filter copy records. Any copies that occur between fromrev and | filter copy records. Any copies that occur between fromrev and | ||||
skiprev will not be duplicated, even if they appear in the set of | skiprev will not be duplicated, even if they appear in the set of | ||||
copies between fromrev and rev. | copies between fromrev and rev. | ||||
''' | """ | ||||
exclude = {} | exclude = {} | ||||
if (skiprev is not None and | if (skiprev is not None and | ||||
repo.ui.config('experimental', 'copytrace') != 'off'): | repo.ui.config('experimental', 'copytrace') != 'off'): | ||||
# copytrace='off' skips this line, but not the entire function because | # copytrace='off' skips this line, but not the entire function because | ||||
# the line below is O(size of the repo) during a rebase, while the rest | # the line below is O(size of the repo) during a rebase, while the rest | ||||
# of the function is much faster (and is required for carrying copy | # of the function is much faster (and is required for carrying copy | ||||
# metadata across the rebase anyway). | # metadata across the rebase anyway). | ||||
exclude = pathcopies(repo[fromrev], repo[skiprev]) | exclude = pathcopies(repo[fromrev], repo[skiprev]) | ||||
for dst, src in pathcopies(repo[fromrev], repo[rev]).iteritems(): | for dst, src in pathcopies(repo[fromrev], repo[rev]).iteritems(): | ||||
# copies.pathcopies returns backward renames, so dst might not | # copies.pathcopies returns backward renames, so dst might not | ||||
# actually be in the dirstate | # actually be in the dirstate | ||||
if dst in exclude: | if dst in exclude: | ||||
continue | continue | ||||
wctx[dst].markcopied(src) | wctx[dst].markcopied(src) |