# HG changeset patch # User Pierre-Yves David # Date 1335451755 -7200 # Node ID ace5608350b61dd794f86b7e72f5d57aa1fe4d51 # Parent 786eb34d93eaa318af5b90d3d5ac311d0e93b3f9 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). diff -r 786eb34d93ea -r ace5608350b6 hgext/obsolete.py --- 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 ############################# diff -r 786eb34d93ea -r ace5608350b6 tests/test-obsolete.t --- 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)