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) | ||||