mercurial/copies.py
changeset 42595 819712deac69
parent 42594 d013099c551b
child 42645 8c5a36805d5d
equal deleted inserted replaced
42594:d013099c551b 42595:819712deac69
   148             t[k] = t[v]
   148             t[k] = t[v]
   149         else:
   149         else:
   150             t[k] = v
   150             t[k] = v
   151     return t
   151     return t
   152 
   152 
   153 def _tracefile(fctx, am, limit):
   153 def _tracefile(fctx, am, basemf, limit):
   154     """return file context that is the ancestor of fctx present in ancestor
   154     """return file context that is the ancestor of fctx present in ancestor
   155     manifest am, stopping after the first ancestor lower than limit"""
   155     manifest am, stopping after the first ancestor lower than limit"""
   156 
   156 
   157     for f in fctx.ancestors():
   157     for f in fctx.ancestors():
   158         path = f.path()
   158         path = f.path()
   159         if am.get(path, None) == f.filenode():
   159         if am.get(path, None) == f.filenode():
       
   160             return path
       
   161         if basemf and basemf.get(path, None) == f.filenode():
   160             return path
   162             return path
   161         if not f.isintroducedafter(limit):
   163         if not f.isintroducedafter(limit):
   162             return None
   164             return None
   163 
   165 
   164 def _dirstatecopies(repo, match=None):
   166 def _dirstatecopies(repo, match=None):
   181 def usechangesetcentricalgo(repo):
   183 def usechangesetcentricalgo(repo):
   182     """Checks if we should use changeset-centric copy algorithms"""
   184     """Checks if we should use changeset-centric copy algorithms"""
   183     return (repo.ui.config('experimental', 'copies.read-from') in
   185     return (repo.ui.config('experimental', 'copies.read-from') in
   184             ('changeset-only', 'compatibility'))
   186             ('changeset-only', 'compatibility'))
   185 
   187 
   186 def _committedforwardcopies(a, b, match):
   188 def _committedforwardcopies(a, b, base, match):
   187     """Like _forwardcopies(), but b.rev() cannot be None (working copy)"""
   189     """Like _forwardcopies(), but b.rev() cannot be None (working copy)"""
   188     # files might have to be traced back to the fctx parent of the last
   190     # files might have to be traced back to the fctx parent of the last
   189     # one-side-only changeset, but not further back than that
   191     # one-side-only changeset, but not further back than that
   190     repo = a._repo
   192     repo = a._repo
   191 
   193 
   199             % (a, b))
   201             % (a, b))
   200     limit = _findlimit(repo, a, b)
   202     limit = _findlimit(repo, a, b)
   201     if debug:
   203     if debug:
   202         dbg('debug.copies:      search limit: %d\n' % limit)
   204         dbg('debug.copies:      search limit: %d\n' % limit)
   203     am = a.manifest()
   205     am = a.manifest()
       
   206     basemf = None if base is None else base.manifest()
   204 
   207 
   205     # find where new files came from
   208     # find where new files came from
   206     # we currently don't try to find where old files went, too expensive
   209     # we currently don't try to find where old files went, too expensive
   207     # this means we can miss a case like 'hg rm b; hg cp a b'
   210     # this means we can miss a case like 'hg rm b; hg cp a b'
   208     cm = {}
   211     cm = {}
   230         fctx = b[f]
   233         fctx = b[f]
   231         fctx._ancestrycontext = ancestrycontext
   234         fctx._ancestrycontext = ancestrycontext
   232 
   235 
   233         if debug:
   236         if debug:
   234             start = util.timer()
   237             start = util.timer()
   235         opath = _tracefile(fctx, am, limit)
   238         opath = _tracefile(fctx, am, basemf, limit)
   236         if opath:
   239         if opath:
   237             if debug:
   240             if debug:
   238                 dbg('debug.copies:          rename of: %s\n' % opath)
   241                 dbg('debug.copies:          rename of: %s\n' % opath)
   239             cm[f] = opath
   242             cm[f] = opath
   240         if debug:
   243         if debug:
   309                 if f in newcopies:
   312                 if f in newcopies:
   310                     del newcopies[f]
   313                     del newcopies[f]
   311             heapq.heappush(work, (c, parent, newcopies))
   314             heapq.heappush(work, (c, parent, newcopies))
   312     assert False
   315     assert False
   313 
   316 
   314 def _forwardcopies(a, b, match=None):
   317 def _forwardcopies(a, b, base=None, match=None):
   315     """find {dst@b: src@a} copy mapping where a is an ancestor of b"""
   318     """find {dst@b: src@a} copy mapping where a is an ancestor of b"""
   316 
   319 
       
   320     if base is None:
       
   321         base = a
   317     match = a.repo().narrowmatch(match)
   322     match = a.repo().narrowmatch(match)
   318     # check for working copy
   323     # check for working copy
   319     if b.rev() is None:
   324     if b.rev() is None:
   320         cm = _committedforwardcopies(a, b.p1(), match)
   325         cm = _committedforwardcopies(a, b.p1(), base, match)
   321         # combine copies from dirstate if necessary
   326         # combine copies from dirstate if necessary
   322         copies = _chain(cm, _dirstatecopies(b._repo, match))
   327         copies = _chain(cm, _dirstatecopies(b._repo, match))
   323     else:
   328     else:
   324         copies  = _committedforwardcopies(a, b, match)
   329         copies  = _committedforwardcopies(a, b, base, match)
   325     return copies
   330     return copies
   326 
   331 
   327 def _backwardrenames(a, b, match):
   332 def _backwardrenames(a, b, match):
   328     if a._repo.ui.config('experimental', 'copytrace') == 'off':
   333     if a._repo.ui.config('experimental', 'copytrace') == 'off':
   329         return {}
   334         return {}
   367             repo.ui.debug('debug.copies: search mode: backward\n')
   372             repo.ui.debug('debug.copies: search mode: backward\n')
   368         copies = _backwardrenames(x, y, match=match)
   373         copies = _backwardrenames(x, y, match=match)
   369     else:
   374     else:
   370         if debug:
   375         if debug:
   371             repo.ui.debug('debug.copies: search mode: combined\n')
   376             repo.ui.debug('debug.copies: search mode: combined\n')
       
   377         base = None
       
   378         if a.rev() != node.nullrev:
       
   379             base = x
   372         copies = _chain(_backwardrenames(x, a, match=match),
   380         copies = _chain(_backwardrenames(x, a, match=match),
   373                         _forwardcopies(a, y, match=match))
   381                         _forwardcopies(a, y, base, match=match))
   374     _filter(x, y, copies)
   382     _filter(x, y, copies)
   375     return copies
   383     return copies
   376 
   384 
   377 def mergecopies(repo, c1, c2, base):
   385 def mergecopies(repo, c1, c2, base):
   378     """
   386     """