# HG changeset patch # User Pierre-Yves David # Date 1315498801 -7200 # Node ID ad1a4fb0fc49b8cd611d1f113f2ab2d423a5c5b6 # Parent 0bcbf690dfcada9b65bc64c3590d7611b25e995e Make states more resilient to missing head In particuliar pushkey is now more robust (with a very naif approach) diff -r 0bcbf690dfca -r ad1a4fb0fc49 hgext/obsolete.py --- a/hgext/obsolete.py Thu Sep 08 17:46:54 2011 +0200 +++ b/hgext/obsolete.py Thu Sep 08 18:20:01 2011 +0200 @@ -6,6 +6,11 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. import os +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + from mercurial import util from mercurial import context @@ -84,10 +89,14 @@ # Pushkey mechanism for mutable ######################################### -def pushobsolete(repo, key, old, relations): +def pushobsolete(repo, key, old, raw): assert key == "relations" w = repo.wlock() try: + tmp = StringIO() + tmp.write(raw) + tmp.seek(0) + relations = repo._obsdeserialise(tmp) for sub, objs in relations.iteritems(): for obj in objs: repo.addobsolete(sub, obj) @@ -95,7 +104,9 @@ w.release() def listobsolete(repo): - return {'relations': repo._obssubrels} + tmp = StringIO() + repo._obsserialise(tmp) + return {'relations': tmp.getvalue()} pushkey.register('obsolete', pushobsolete, listobsolete) @@ -170,32 +181,42 @@ """{ -> set()}""" return self._readobsrels() + ### serialisation + # XXX get this out the repo + + def _obsserialise(self, flike): + for sub, objs in self._obssubrels.iteritems(): + for obj in objs: + flike.write('%s %s\n' % (hex(sub), hex(obj))) + + def _obsdeserialise(self,flike): + rels = {} + for line in flike: + subhex, objhex = line.split() + rels.setdefault(bin(subhex), set()).add(bin(objhex)) + return rels + + ### Disk IO def _readobsrels(self): """Write obsolete relation on disk""" # XXX handle lock - rels = {} try: f = self.opener('obsolete-relations') try: - for line in f: - subhex, objhex = line.split() - rels.setdefault(bin(subhex), set()).add(bin(objhex)) + return self._obsdeserialise(f) finally: f.close() except IOError: - pass - return rels + return {} def _writeobsrels(self): """Write obsolete relation on disk""" # XXX handle lock f = self.opener('obsolete-relations', 'w', atomictemp=True) try: - for sub, objs in self._obssubrels.iteritems(): - for obj in objs: - f.write('%s %s\n' % (hex(sub), hex(obj))) + self._obsserialise(f) f.rename() finally: f.close() @@ -221,7 +242,10 @@ obssupport = 'relations' in obskey result = opush(remote, *args, **opts) if obssupport: - remote.pushkey('obsolete', 'relations', {}, self._obssubrels) + tmp = StringIO() + repo._obsserialise(tmp) + remote.pushkey('obsolete', 'relations', {}, tmp.getvalue()) + return result diff -r 0bcbf690dfca -r ad1a4fb0fc49 hgext/states.py --- a/hgext/states.py Thu Sep 08 17:46:54 2011 +0200 +++ b/hgext/states.py Thu Sep 08 18:20:01 2011 +0200 @@ -33,6 +33,7 @@ from mercurial import extensions from mercurial import wireproto from mercurial import pushkey +from mercurial import error from mercurial.lock import release @@ -69,7 +70,12 @@ assert self.trackheads def revsetheads(repo, subset, x): args = revset.getargs(x, 0, 0, 'publicheads takes no arguments') - heads = map(repo.changelog.rev, repo._statesheads[self]) + heads = [] + for h in repo._statesheads[self]: + try: + heads.append(repo.changelog.rev(h)) + except error.LookupError: + pass heads.sort() return heads return revsetheads @@ -175,8 +181,9 @@ st = ST0 w = repo.wlock() try: - #print 'pushing', key - repo.setstate(ST0, [node.bin(key)]) + newhead = node.bin(key) + repo[newhead] + repo.setstate(ST0, [newhead]) finally: w.release() @@ -389,9 +396,12 @@ def _pushimmutableheads(self, remote, remoteheads): missing = set(self.stateheads(ST0)) - set(remoteheads) - for h in missing: - #print 'missing', node.short(h) - remote.pushkey('immutableheads', node.hex(h), '', '1') + while missing: + h = missing.pop() + try: + remote.pushkey('immutableheads', node.hex(h), '', '1') + except error.RepoLookupError: + missing.update(p.node() for p in repo[h].parents()) def _pullimmutableheads(self, remote):