obsolete: do no complain when push create a new head but obsolete an old one.
authorPierre-Yves David <pierre-yves.david@ens-lyon.org>
Thu, 26 Apr 2012 16:49:15 +0200
changeset 218 ace5608350b6
parent 217 786eb34d93ea
child 219 cfdab01ca8a0
obsolete: do no complain when push create a new head but obsolete an old one. Do not read the code or your eyes will burn. The (+1 heads) message still appear (see mercurial issue 3394).
hgext/obsolete.py
tests/test-obsolete.t
--- a/hgext/obsolete.py	Tue Apr 24 16:30:58 2012 +0200
+++ b/hgext/obsolete.py	Thu Apr 26 16:49:15 2012 +0200
@@ -305,7 +305,12 @@
     return outgoing
 
 def wrapcheckheads(orig, repo, remote, outgoing, *args, **kwargs):
-    """wrap mercurial.discovery.checkheads to prevent unstability to be pushed"""
+    """wrap mercurial.discovery.checkheads
+
+    * prevent unstability to be pushed
+    * patch remote to ignore obsolete heads on remote
+    """
+    # do not push instability
     for h in outgoing.missingheads:
         # checking heads only is enought because any thing base on obsolete
         # changeset is either obsolete or unstable.
@@ -317,7 +322,58 @@
         if ctx.obsolete():
             raise util.Abort(_("Trying to push obsolete changeset: %s!") % ctx,
                              hint=hint)
-    return orig(repo, remote, outgoing, *args, **kwargs)
+    ### patch remote branch map
+    # do not read it this burn eyes
+    try:
+        if 'oldbranchmap' not in vars(remote):
+            remote.oldbranchmap = remote.branchmap
+            def branchmap():
+                newbm = {}
+                oldbm = None
+                if (util.safehasattr(phases, 'visiblebranchmap')
+                    and not util.safehasattr(remote, 'ignorevisiblebranchmap')
+                   ):
+                    remote.ignorevisiblebranchmap = False
+                    remote.branchmap = remote.oldbranchmap
+                    oldbm = phases.visiblebranchmap(remote)
+                    remote.branchmap = remote.newbranchmap
+                    remote.ignorevisiblebranchmap = True
+                if oldbm is None:
+                    oldbm = remote.oldbranchmap()
+                for branch, nodes in oldbm.iteritems():
+                    nodes = list(nodes)
+                    new = set()
+                    while nodes:
+                        n = nodes.pop()
+                        if n in repo._obsobjrels:
+                            newernodes = repo._obsobjrels[n]
+                            for newernode in newernodes:
+                                if newernode is not None:
+                                    nodes.append(newernode)
+                        else:
+                            new.add(n)
+                    if new:
+                        newbm[branch] = list(new)
+                return newbm
+            remote.ignorevisiblebranchmap = True
+            remote.branchmap = branchmap
+            remote.newbranchmap = branchmap
+        return orig(repo, remote, outgoing, *args, **kwargs)
+    finally:
+        remote.__dict__.pop('branchmap', None) # restore class one
+        remote.__dict__.pop('oldbranchmap', None)
+        remote.__dict__.pop('newbranchmap', None)
+        remote.__dict__.pop('ignorevisiblebranchmap', None)
+
+# eye are still burning
+def wrapvisiblebranchmap(orig, repo):
+    ignore = getattr(repo, 'ignorevisiblebranchmap', None)
+    if ignore is None:
+        return orig(repo)
+    elif ignore:
+        return repo.branchmap()
+    else:
+        return None # break recursion
 
 
 ### New commands
@@ -349,6 +405,8 @@
     extensions.wrapcommand(commands.table, "pull", wrapmayobsoletewc)
     extensions.wrapfunction(discovery, 'findcommonoutgoing', wrapfindcommonoutgoing)
     extensions.wrapfunction(discovery, 'checkheads', wrapcheckheads)
+    if util.safehasattr(phases, 'visiblebranchmap'):
+        extensions.wrapfunction(phases, 'visiblebranchmap', wrapvisiblebranchmap)
 
 ### serialisation
 #############################
--- a/tests/test-obsolete.t	Tue Apr 24 16:30:58 2012 +0200
+++ b/tests/test-obsolete.t	Thu Apr 26 16:49:15 2012 +0200
@@ -433,3 +433,24 @@
   o  0 - 1f0dee641bb7
   
 
+Does not complain about new head if you obsolete the old one
+
+  $ hg push ../other-new --traceback
+  pushing to ../other-new
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 1 changes to 1 files
+  83b5778897ad try to obsolete immutable changeset 1f0dee641bb7
+  $ hg up -q 10
+  $ mkcommit "obsol_d'''"
+  created new head
+  $ hg debugobsolete 12 11
+  $ hg push ../other-new --traceback
+  pushing to ../other-new
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)