obsolete: add revset for various error case
authorPierre-Yves David <pierre-yves.david@logilab.fr>
Fri, 17 Feb 2012 17:53:00 +0100
changeset 135 1a08daef8a53
parent 134 70c9e415242b
child 136 915728be8afd
obsolete: add revset for various error case
hgext/obsolete.py
tests/test-obsolete.t
--- a/hgext/obsolete.py	Fri Feb 17 10:35:46 2012 +0100
+++ b/hgext/obsolete.py	Fri Feb 17 17:53:00 2012 +0100
@@ -22,6 +22,8 @@
 :obsolete:     a changeset that have been replace by another one.
 :unstable:     a non-obsolet changeset based on another one.
 :suspended:    an obsolete changeset with unstable descendant.
+:extinct:      an obsolete changeset without unstable descendant
+               (subject to garbage collection)
 
 Another name for unstable could be out of sync.
 
@@ -113,10 +115,25 @@
 
 
 def revsetobsolete(repo, subset, x):
-    """filter obsolet entry"""
-    args = revset.getargs(x, 0, 0, 'publicheads takes no arguments')
+    """obsolete changesets"""
+    args = revset.getargs(x, 0, 0, 'obsolete takes no argument')
     return [r for r in subset if r in repo._obsoleteset and repo._phaserev[r] > 0]
 
+def revsetunstable(repo, subset, x):
+    """non obsolete changesets descendant of obsolete one"""
+    args = revset.getargs(x, 0, 0, 'unstable takes no arguments')
+    return [r for r in subset if r in repo._unstableset]
+
+def revsetsuspended(repo, subset, x):
+    """obsolete changesets with non obsolete descendants"""
+    args = revset.getargs(x, 0, 0, 'unstable takes no arguments')
+    return [r for r in subset if r in repo._suspendedset]
+
+def revsetextinct(repo, subset, x):
+    """obsolete changesets without obsolete descendants"""
+    args = revset.getargs(x, 0, 0, 'unstable takes no arguments')
+    return [r for r in subset if r in repo._extinctset]
+
 ### Other Extension compat
 ############################
 
@@ -140,6 +157,9 @@
 def extsetup(ui):
 
     revset.symbols["obsolete"] = revsetobsolete
+    revset.symbols["unstable"] = revsetunstable
+    revset.symbols["suspended"] = revsetsuspended
+    revset.symbols["extinct"] = revsetextinct
 
 
     try:
@@ -290,6 +310,7 @@
 
         @util.propertycache
         def _obsoleteset(self):
+            """the set of obsolete revision"""
             obs = set()
             nm = self.changelog.nodemap
             for obj in self._obsobjrels:
@@ -298,6 +319,35 @@
                     obs.add(rev)
             return obs
 
+        @util.propertycache
+        def _unstableset(self):
+            """the set of non obsolete revision with obsolete parent"""
+            return set(self.revs('(obsolete()::) - obsolete()'))
+
+        @util.propertycache
+        def _suspendedset(self):
+            """the set of obsolete parent with non obsolete descendant"""
+            return set(self.revs('obsolete() and obsolete()::unstable()'))
+
+        @util.propertycache
+        def _extinctset(self):
+            """the set of obsolete parent without non obsolete descendant"""
+            return set(self.revs('obsolete() - obsolete()::unstable()'))
+
+        def _clearobsoletecache(self):
+            if '_obsobjrels' in vars(self):
+                del self._obsobjrels
+            if '_obssubrels' in vars(self):
+                del self._obssubrels
+            if '_obsoleteset' in vars(self):
+                del self._obsoleteset
+            if '_unstableset' in vars(self):
+                del self._unstableset
+            if '_suspendedset' in vars(self):
+                del self._suspendedset
+            if '_extinct' in vars(self):
+                del self._extinctset
+
         def addobsolete(self, sub, obj):
             """Add a relation marking that node <sub> is a new version of <obj>"""
             if sub == nullid:
@@ -322,12 +372,7 @@
             except (error.RepoLookupError, error.LookupError):
                 pass #unknow revision (but keep propagating the data
             self._writeobsrels()
-            if '_obsobjrels' in vars(self):
-                del self._obsobjrels
-            if '_obssubrels' in vars(self):
-                del self._obssubrels
-            if '_obsoleteset' in vars(self):
-                del self._obsoleteset
+            self._clearobsoletecache()
             return 1
 
         ### obsolete storage
@@ -477,12 +522,16 @@
 
     repo.__class__ = obsoletingrepo
     if repo.ui.configbool('obsolete', 'secret-unstable', True):
-        expobs = [c.node() for c in repo.set('obsolete() - secret()')]
-        if expobs: # do not lock in nothing move. locking for peanut make hgview reload on any command
-            lock = repo.lock()
-            try:
-                phases.retractboundary(repo, 2, expobs)
-            finally:
-                lock.release()
+        symbol = 'obsolete()'
+    else:
+        symbol = 'extinct()'
+
+    expobs = [c.node() for c in repo.set('%s - secret()' % symbol)]
+    if expobs: # do not lock in nothing move. locking for peanut make hgview reload on any command
+        lock = repo.lock()
+        try:
+            phases.retractboundary(repo, 2, expobs)
+        finally:
+            lock.release()
 
 
--- a/tests/test-obsolete.t	Fri Feb 17 10:35:46 2012 +0100
+++ b/tests/test-obsolete.t	Fri Feb 17 17:53:00 2012 +0100
@@ -4,6 +4,8 @@
   > allow_push = *
   > [phases]
   > publish=False
+  > [obsolete]
+  > secret-unstable=no
   > [extensions]
   > EOF
   $ echo "obsolete=$(echo $(dirname $TESTDIR))/hgext/obsolete.py" >> $HGRCPATH
@@ -17,7 +19,7 @@
   $ hg init local
   $ cd local
   $ mkcommit a # 0
-  $ hg pull -q . #hg published 0
+  $ hg phase -p .
   $ mkcommit b # 1
   $ mkcommit c # 2
   $ hg up 1
@@ -76,6 +78,7 @@
 Test communication of obsolete relation with a compatible client
 
   $ hg init ../other-new
+  $ hg phase --draft 'secret() - extinct()' # until we fix exclusion
   $ hg push --traceback ../other-new
   pushing to ../other-new
   searching for changes
@@ -148,10 +151,10 @@
   adding changesets
   adding manifests
   adding file changes
-  added 2 changesets with 2 changes to 2 files (+2 heads)
+  added 1 changesets with 1 changes to 1 files (+1 heads)
   (run 'hg heads .' to see heads, 'hg merge' to merge)
   $ qlog -R ../other-new
-  7
+  6
   - 909a0fb57e5d
   3
   - 725c380fe99b
@@ -196,16 +199,16 @@
   adding changesets
   adding manifests
   adding file changes
-  added 8 changesets with 8 changes to 8 files (+4 heads)
+  added 5 changesets with 5 changes to 5 files (+1 heads)
   updating to branch default
   4 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ qlog -R ../cloned
-  7
+  4
   - 909a0fb57e5d
-  4
+  3
   - 725c380fe99b
-  3
+  2
   - 0d3f46688ccc
   1
   - 7c3bad9141dc
@@ -229,7 +232,7 @@
   (run 'hg heads .' to see heads, 'hg merge' to merge)
 
   $ qlog -R ../other-new
-  8
+  7
   - 159dfc9fa5d3
   3
   - 725c380fe99b
@@ -240,9 +243,9 @@
   0
   - 1f0dee641bb7
   $ hg -R ../other-new rollback
-  repository tip rolled back to revision 7 (undo pull)
+  repository tip rolled back to revision 6 (undo pull)
   $ qlog -R ../other-new
-  7
+  6
   - 909a0fb57e5d
   3
   - 725c380fe99b