changeset 29346:38e0c83c7ee4

revset: record if a set is in topographical order A later revision adds actual topographical sorting. Recording if a set is in this order allows hg log -G to avoid re-sorting the revset.
author Martijn Pieters <mjpieters@fb.com>
date Tue, 14 Jun 2016 11:05:36 +0100
parents 62b890496de5
children 98535ad46fc0
files mercurial/cmdutil.py mercurial/revset.py
diffstat 2 files changed, 38 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/cmdutil.py	Mon Jun 13 21:30:14 2016 +0100
+++ b/mercurial/cmdutil.py	Tue Jun 14 11:05:36 2016 +0100
@@ -2147,7 +2147,7 @@
     if opts.get('rev'):
         # User-specified revs might be unsorted, but don't sort before
         # _makelogrevset because it might depend on the order of revs
-        if not revs.isdescending():
+        if not (revs.isdescending() or revs.istopo()):
             revs.sort(reverse=True)
     if expr:
         # Revset matchers often operate faster on revisions in changelog
--- a/mercurial/revset.py	Mon Jun 13 21:30:14 2016 +0100
+++ b/mercurial/revset.py	Tue Jun 14 11:05:36 2016 +0100
@@ -2508,6 +2508,10 @@
         """True if the set will iterate in descending order"""
         raise NotImplementedError()
 
+    def istopo(self):
+        """True if the set will iterate in topographical order"""
+        raise NotImplementedError()
+
     @util.cachefunc
     def min(self):
         """return the minimum element in the set"""
@@ -2593,12 +2597,13 @@
 
     Every method in this class should be implemented by any smartset class.
     """
-    def __init__(self, data=(), datarepr=None):
+    def __init__(self, data=(), datarepr=None, istopo=False):
         """
         datarepr: a tuple of (format, obj, ...), a function or an object that
                   provides a printable representation of the given data.
         """
         self._ascending = None
+        self._istopo = istopo
         if not isinstance(data, list):
             if isinstance(data, set):
                 self._set = data
@@ -2641,12 +2646,14 @@
 
     def sort(self, reverse=False):
         self._ascending = not bool(reverse)
+        self._istopo = False
 
     def reverse(self):
         if self._ascending is None:
             self._list.reverse()
         else:
             self._ascending = not self._ascending
+        self._istopo = False
 
     def __len__(self):
         return len(self._list)
@@ -2667,6 +2674,14 @@
             return True
         return self._ascending is not None and not self._ascending
 
+    def istopo(self):
+        """Is the collection is in topographical order or not.
+
+        This is part of the mandatory API for smartset."""
+        if len(self) <= 1:
+            return True
+        return self._istopo
+
     def first(self):
         if self:
             if self._ascending is None:
@@ -2782,6 +2797,9 @@
     def isdescending(self):
         return self._subset.isdescending()
 
+    def istopo(self):
+        return self._subset.istopo()
+
     def first(self):
         for x in self:
             return x
@@ -3028,6 +3046,12 @@
     def isdescending(self):
         return self._ascending is not None and not self._ascending
 
+    def istopo(self):
+        # not worth the trouble asserting if the two sets combined are still
+        # in topographical order. Use the sort() predicate to explicitly sort
+        # again instead.
+        return False
+
     def reverse(self):
         if self._ascending is None:
             self._list.reverse()
@@ -3195,6 +3219,12 @@
     def isdescending(self):
         return not self._ascending
 
+    def istopo(self):
+        # not worth the trouble asserting if the two sets combined are still
+        # in topographical order. Use the sort() predicate to explicitly sort
+        # again instead.
+        return False
+
     def first(self):
         if self._ascending:
             it = self.fastasc
@@ -3257,6 +3287,12 @@
     def reverse(self):
         self._ascending = not self._ascending
 
+    def istopo(self):
+        # not worth the trouble asserting if the two sets combined are still
+        # in topographical order. Use the sort() predicate to explicitly sort
+        # again instead.
+        return False
+
     def _iterfilter(self, iterrange):
         s = self._hiddenrevs
         for r in iterrange: