Patchwork [1,of,2,V3] changelog: prefilter in headrevs()

login
register
mail settings
Submitter Georges Racinet
Date Feb. 21, 2019, 10:27 a.m.
Message ID <1c1f122821291657b33b.1550744844@purity.tombe.racinet.fr>
Download mbox | patch
Permalink /patch/38852/
State Accepted
Headers show

Comments

Georges Racinet - Feb. 21, 2019, 10:27 a.m.
# HG changeset patch
# User Georges Racinet <georges.racinet@octobus.net>
# Date 1550659746 -3600
#      Wed Feb 20 11:49:06 2019 +0100
# Node ID 1c1f122821291657b33b447e89dc4420b3f833b5
# Parent  0c7b353ce100e9125251f4ae37a8739242ce537c
# EXP-Topic revset.predicates
changelog: prefilter in headrevs()

In case where headrevs() is called on some revisions, we perform
the check that aren't filtered in advance, and switch revlog to
use its unchecked form.

This allows to work with alternative implementations that don't have knowledge
of the filtering system, such as the Rust one.
Yuya Nishihara - Feb. 21, 2019, 10:59 p.m.
On Thu, 21 Feb 2019 11:27:24 +0100, Georges Racinet wrote:
> # HG changeset patch
> # User Georges Racinet <georges.racinet@octobus.net>
> # Date 1550659746 -3600
> #      Wed Feb 20 11:49:06 2019 +0100
> # Node ID 1c1f122821291657b33b447e89dc4420b3f833b5
> # Parent  0c7b353ce100e9125251f4ae37a8739242ce537c
> # EXP-Topic revset.predicates
> changelog: prefilter in headrevs()

Queued, thanks.

Patch

diff -r 0c7b353ce100 -r 1c1f12282129 mercurial/changelog.py
--- a/mercurial/changelog.py	Thu Jan 10 18:25:18 2019 +0100
+++ b/mercurial/changelog.py	Wed Feb 20 11:49:06 2019 +0100
@@ -22,6 +22,7 @@ 
     error,
     pycompat,
     revlog,
+    util,
 )
 from .utils import (
     dateutil,
@@ -350,6 +351,27 @@ 
     def reachableroots(self, minroot, heads, roots, includepath=False):
         return self.index.reachableroots2(minroot, heads, roots, includepath)
 
+    def _checknofilteredinrevs(self, revs):
+        """raise the appropriate error if 'revs' contains a filtered revision
+
+        This returns a version of 'revs' to be used thereafter by the caller.
+        In particular, if revs is an iterator, it is converted into a set.
+        """
+        safehasattr = util.safehasattr
+        if safehasattr(revs, '__next__'):
+            # Note that inspect.isgenerator() is not true for iterators,
+            revs = set(revs)
+
+        filteredrevs = self.filteredrevs
+        if safehasattr(revs, 'first'):  # smartset
+            offenders = revs & filteredrevs
+        else:
+            offenders = filteredrevs.intersection(revs)
+
+        for rev in offenders:
+            raise error.FilteredIndexError(rev)
+        return revs
+
     def headrevs(self, revs=None):
         if revs is None and self.filteredrevs:
             try:
@@ -359,6 +381,8 @@ 
             except AttributeError:
                 return self._headrevs()
 
+        if self.filteredrevs:
+            revs = self._checknofilteredinrevs(revs)
         return super(changelog, self).headrevs(revs)
 
     def strip(self, *args, **kwargs):
diff -r 0c7b353ce100 -r 1c1f12282129 mercurial/revlog.py
--- a/mercurial/revlog.py	Thu Jan 10 18:25:18 2019 +0100
+++ b/mercurial/revlog.py	Wed Feb 20 11:49:06 2019 +0100
@@ -1121,7 +1121,7 @@ 
                 return self.index.headrevs()
             except AttributeError:
                 return self._headrevs()
-        return dagop.headrevs(revs, self.parentrevs)
+        return dagop.headrevs(revs, self._uncheckedparentrevs)
 
     def computephases(self, roots):
         return self.index.computephasesmapsets(roots)