# HG changeset patch # User Boris Feld # Date 2018-06-21 23:05:20 # Node ID 6db38c9d7e0057fb2c29e95b048253a9a0ed163f # Parent 99f864b3445163e77f600bb854bf3b6bf6b1f91d revlog: efficient implementation of 'descendant' Iterating over descendants is costly, because there are no "parent -> children" pointers. Walking the other way around is much more efficient, especially on large repositories, where descendant walks can cost seconds. And the other hand, common ancestors code follows links in the right direction and has a compiled implementation. In real life usage, this saved up to 80s during some pull operations, where descendant test happens in extension code. diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -1376,16 +1376,14 @@ class revlog(object): return c def descendant(self, start, end): + """True if revision 'end' is an descendant of revision 'start' + + A revision is considered as a descendant of itself.""" if start == nullrev: return True elif start == end: return True - for i in self.descendants([start]): - if i == end: - return True - elif i > end: - break - return False + return start in self._commonancestorsheads(start, end) def commonancestorsheads(self, a, b): """calculate all the heads of the common ancestors of nodes a and b"""