[PATCH 3 of 7] context: fix introrev to avoid computation as initially intended
Boris Feld
boris.feld at octobus.net
Fri Sep 7 11:04:07 EDT 2018
# HG changeset patch
# User Boris Feld <boris.feld at octobus.net>
# Date 1536254177 14400
# Thu Sep 06 13:16:17 2018 -0400
# Node ID a4c3eb6c1a36cbbf64fa8930b173154b2e77ef2b
# Parent 9a18509c522deeb62a7b244dcf4c7b79a8dc1132
# EXP-Topic copy-perf
# Available At https://bitbucket.org/octobus/mercurial-devel/
# hg pull https://bitbucket.org/octobus/mercurial-devel/ -r a4c3eb6c1a36
context: fix introrev to avoid computation as initially intended
The `filerev.introrev()` method has various logic be as efficient as possible.
In particular, it tries to restrict the range covered by the
`ctx._adjustlinkrev(...)` call. However, it does so using the value returned by
`ctx.rev()`. In some case (eg: copy tracing), that `ctx.rev()` call would do an
`_adjustlinkrev(...)` call on its own, defeating the optimization purpose and
doing the computation twice.
We are about to improve graph traversal associated with copy tracing using code
based on `ctx.introrev()`, so we need this fixed before proceeding further.
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -829,6 +829,23 @@ class basefilectx(object):
# result is crash somewhere else at to some point.
return lkr
+ def _lazyrev(self):
+ """return self.rev() if it is available without computation,
+
+ If finding the rev would trigger a possibly expensive computation, we
+ return None."""
+ attrs = vars(self)
+ if r'_changeid' in attrs:
+ # We have a cached value already
+ return self.rev()
+ elif r'_changectx' in attrs:
+ # We know which changelog entry we are coming from
+ return self.rev()
+ elif r'_descendantrev' not in attrs:
+ # we have no context, so linkrev will be used
+ return self.rev()
+ return None
+
def introrev(self):
"""return the rev of the changeset which introduced this file revision
@@ -839,11 +856,14 @@ class basefilectx(object):
changesets.
"""
lkr = self.linkrev()
- attrs = vars(self)
- noctx = not (r'_changeid' in attrs or r'_changectx' in attrs)
- if noctx or self.rev() == lkr:
- return self.linkrev()
- return self._adjustlinkrev(self.rev(), inclusive=True)
+ lazyrev = self._lazyrev()
+ if lazyrev is not None:
+ if lazyrev == lkr:
+ return lazyrev
+ else:
+ return self._adjustlinkrev(lazyrev, inclusive=True)
+ else:
+ return self.rev()
def introfilectx(self):
"""Return filectx having identical contents, but pointing to the
More information about the Mercurial-devel
mailing list