Mercurial > hg
changeset 24415:1cfded2fa1a9
merge with stable
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Fri, 20 Mar 2015 17:30:38 -0500 |
parents | f247fbfe07f3 (current diff) 9372180b8c9b (diff) |
children | f07047a506d1 |
files | mercurial/context.py mercurial/copies.py |
diffstat | 2 files changed, 48 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/context.py Fri Mar 20 16:39:07 2015 -0500 +++ b/mercurial/context.py Fri Mar 20 17:30:38 2015 -0500 @@ -775,13 +775,19 @@ # hack to reuse ancestor computation when searching for renames memberanc = getattr(self, '_ancestrycontext', None) iteranc = None + if srcrev is None: + # wctx case, used by workingfilectx during mergecopy + revs = [p.rev() for p in self._repo[None].parents()] + inclusive = True # we skipped the real (revless) source + else: + revs = [srcrev] if memberanc is None: - memberanc = iteranc = cl.ancestors([srcrev], lkr, + memberanc = iteranc = cl.ancestors(revs, lkr, inclusive=inclusive) # check if this linkrev is an ancestor of srcrev if lkr not in memberanc: if iteranc is None: - iteranc = cl.ancestors([srcrev], lkr, inclusive=inclusive) + iteranc = cl.ancestors(revs, lkr, inclusive=inclusive) for a in iteranc: ac = cl.read(a) # get changeset data (we avoid object creation) if path in ac[3]: # checking the 'files' field. @@ -914,6 +920,8 @@ introrev = self.introrev() if self.rev() != introrev: base = self.filectx(self.filenode(), changeid=introrev) + ac = self._repo.changelog.ancestors([introrev], inclusive=True) + base._ancestrycontext = ac # This algorithm would prefer to be recursive, but Python is a # bit recursion-hostile. Instead we do an iterative
--- a/mercurial/copies.py Fri Mar 20 16:39:07 2015 -0500 +++ b/mercurial/copies.py Fri Mar 20 17:30:38 2015 -0500 @@ -266,14 +266,41 @@ m2 = c2.manifest() ma = ca.manifest() - def makectx(f, n): - if len(n) != 20: # in a working context? - if c1.rev() is None: - return c1.filectx(f) - return c2.filectx(f) - return repo.filectx(f, fileid=n) + + def setupctx(ctx): + """return a 'makectx' function suitable for checkcopies usage from ctx + + We have to re-setup the function building 'filectx' for each + 'checkcopies' to ensure the linkrev adjustement is properly setup for + each. Linkrev adjustment is important to avoid bug in rename + detection. Moreover, having a proper '_ancestrycontext' setup ensures + the performance impact of this adjustment is kept limited. Without it, + each file could do a full dag traversal making the time complexity of + the operation explode (see issue4537). - ctx = util.lrucachefunc(makectx) + This function exists here mostly to limit the impact on stable. Feel + free to refactor on default. + """ + rev = ctx.rev() + ac = getattr(ctx, '_ancestrycontext', None) + if ac is None: + revs = [rev] + if rev is None: + revs = [p.rev() for p in ctx.parents()] + ac = ctx._repo.changelog.ancestors(revs, inclusive=True) + ctx._ancestrycontext = ac + def makectx(f, n): + if len(n) != 20: # in a working context? + if c1.rev() is None: + return c1.filectx(f) + return c2.filectx(f) + fctx = repo.filectx(f, fileid=n) + # setup only needed for filectx not create from a changectx + fctx._ancestrycontext = ac + fctx._descendantrev = rev + return fctx + return util.lrucachefunc(makectx) + copy = {} movewithdir = {} fullcopy = {} @@ -286,9 +313,11 @@ u1, u2 = _computenonoverlap(repo, m1, m2, addedinm1, addedinm2) for f in u1: + ctx = setupctx(c1) checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy) for f in u2: + ctx = setupctx(c2) checkcopies(ctx, f, m2, m1, ca, limit, diverge, copy, fullcopy) renamedelete = {} @@ -311,7 +340,9 @@ % "\n ".join(bothnew)) bothdiverge, _copy, _fullcopy = {}, {}, {} for f in bothnew: + ctx = setupctx(c1) checkcopies(ctx, f, m1, m2, ca, limit, bothdiverge, _copy, _fullcopy) + ctx = setupctx(c2) checkcopies(ctx, f, m2, m1, ca, limit, bothdiverge, _copy, _fullcopy) for of, fl in bothdiverge.items(): if len(fl) == 2 and fl[0] == fl[1]: