diff -r 9983f240ac63 -r aa0870d093b8 states.py --- 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, [], '') +# 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