--- a/states.py Mon Jun 06 16:52:03 2011 +0200
+++ b/states.py Mon Jun 06 16:42:56 2011 +0200
@@ -30,6 +30,7 @@
from mercurial import discovery
from mercurial import extensions
from mercurial import wireproto
+from mercurial import pushkey
_NOSHARE=2
@@ -88,6 +89,7 @@
STATES = (ST0, ST1, ST2)
+@util.cachefunc
def laststatewithout(prop):
for state in STATES:
if not state.properties & prop:
@@ -131,7 +133,22 @@
cmdmoveheads = makecmd(state)
cmdtable[state.name] = (cmdmoveheads, [], '<revset>')
+# Pushkey mechanism for mutable
+#########################################
+def pushimmutableheads(repo, key, old, new):
+ st = ST0
+ w = repo.wlock()
+ try:
+ #print 'pushing', key
+ repo.setstate(ST0, [node.bin(key)])
+ finally:
+ w.release()
+
+def listimmutableheads(repo):
+ return dict.fromkeys(map(node.hex, repo.stateheads(ST0)), '1')
+
+pushkey.register('immutableheads', pushimmutableheads, listimmutableheads)
@@ -175,7 +192,9 @@
if not repo.local():
return
- o_cancopy =repo.cancopy
+ ocancopy =repo.cancopy
+ opull =repo.pull
+ opush =repo.push
class statefulrepo(repo.__class__):
def nodestate(self, node):
@@ -241,9 +260,10 @@
self._writeheadsfile(filename, self._statesheads[state])
def setstate(self, state, nodes):
- """freeze targets changeset and it's ancestors.
+ """change state of targets changeset and it's ancestors.
Simplify the list of head."""
+ assert not isinstance(nodes, basestring)
heads = self._statesheads[state]
olds = heads[:]
heads.extend(nodes)
@@ -274,7 +294,43 @@
def cancopy(self):
st = laststatewithout(_NOSHARE)
- return o_cancopy() and (self.stateheads(st) == self.heads())
+ return ocancopy() and (self.stateheads(st) == self.heads())
+
+ def pull(self, remote, *args, **kwargs):
+ result = opull(remote, *args, **kwargs)
+ remoteheads = self._pullimmutableheads(remote)
+ #print [node.short(h) for h in remoteheads]
+ self.setstate(ST0, remoteheads)
+ return result
+
+ def push(self, remote, *args, **opts):
+ result = opush(remote, *args, **opts)
+ remoteheads = self._pullimmutableheads(remote)
+ self.setstate(ST0, remoteheads)
+ if remoteheads != self.stateheads(ST0):
+ #print 'stuff to push'
+ #print 'remote', [node.short(h) for h in remoteheads]
+ #print 'local', [node.short(h) for h in self._statesheads[ST0]]
+ self._pushimmutableheads(remote, remoteheads)
+ return result
+
+ 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')
+
+
+ def _pullimmutableheads(self, remote):
+ self.ui.debug('checking for immutableheadshg on server')
+ if 'immutableheads' not in remote.listkeys('namespaces'):
+ self.ui.debug('immutableheads not enabled on the remote server, '
+ 'marking everything as frozen')
+ remote = remote.heads()
+ else:
+ self.ui.debug('server has immutableheads enabled, merging lists')
+ remote = map(node.bin, remote.listkeys('immutableheads'))
+ return remote
repo.__class__ = statefulrepo