Make states more resilient to missing head
In particuliar pushkey is now more robust (with a very naif approach)
--- 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 @@
"""{<new-node> -> set(<old-node>)}"""
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
--- 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):