# HG changeset patch # User Pierre-Yves David # Date 1307371376 -7200 # Node ID aa0870d093b85e8a776b8cbe419210346f6c912e # Parent 9983f240ac6316150e629ef46754507a2fb1c4da Add pull and push support for relevant heads. This use pushkey. 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 diff -r 9983f240ac63 -r aa0870d093b8 tests/run-tests.py --- a/tests/run-tests.py Mon Jun 06 16:52:03 2011 +0200 +++ b/tests/run-tests.py Mon Jun 06 16:42:56 2011 +0200 @@ -277,8 +277,12 @@ return missing, failed def showdiff(expected, output, ref, err): - for line in difflib.unified_diff(expected, output, ref, err): - sys.stdout.write(line) + try: + for line in difflib.unified_diff(expected, output, ref, err): + sys.stdout.write(line) + except IOError, ex: + print >>sys.stderr, 'BORKEN PIPE', ex.errno + pass def findprogram(program): """Search PATH for a executable program""" @@ -765,8 +769,12 @@ fail("returned error code %d" % ret) if not options.verbose: - sys.stdout.write(mark) - sys.stdout.flush() + try: + sys.stdout.write(mark) + sys.stdout.flush() + except IOError, ex: + print >>sys.stderr, 'BORKEN PIPE', ex.errno + pass killdaemons() diff -r 9983f240ac63 -r aa0870d093b8 tests/test-draft.t --- a/tests/test-draft.t Mon Jun 06 16:52:03 2011 +0200 +++ b/tests/test-draft.t Mon Jun 06 16:42:56 2011 +0200 @@ -30,7 +30,6 @@ adding manifests adding file changes added 2 changesets with 2 changes to 1 files - $ hg publish 1 # until we fix push $ echo "tree" >> savanna $ hg add savanna $ hg ci -m "terrain" @@ -59,7 +58,7 @@ searching for changes no changes found [1] - $ hg push ../remote1 + $ hg push --traceback ../remote1 pushing to ../remote1 searching for changes no changes found @@ -101,7 +100,7 @@ comparing with ../local 0:5caa672bac26 1:710fe444b3b0 - $ hg pull ../local + $ hg pull ../local pulling from ../local requesting all changes adding changesets diff -r 9983f240ac63 -r aa0870d093b8 tests/test-ready.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-ready.t Mon Jun 06 16:42:56 2011 +0200 @@ -0,0 +1,129 @@ + $ cat >> $HGRCPATH < [liquid] + > publish = False + > [extensions] + > graphlog= + > EOF + $ echo "states=$(echo $(dirname $TESTDIR))/states.py" >> $HGRCPATH + + $ mkcommit() { + > echo "$1" > "$1" + > hg add "$1" + > hg ci -m "add $1" + > } + + $ hg init alpha + $ cd alpha + $ cat > .hg/hgrc << EOF + > [states] + > ready=yes + > EOF + $ mkcommit z + $ mkcommit a + $ mkcommit b + $ mkcommit c + $ hg published 1 + $ hg log --graph + @ changeset: 3:090483935bca + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: add c + | + o changeset: 2:720fd97246d7 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: add b + | + o changeset: 1:7a344d213ee2 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: add a + | + o changeset: 0:d32fd17cb041 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add z + + $ cat .hg/states/published-heads + 7a344d213ee2eb3359d94630d4e076460d59dbf0 + +publishedheads() should return only revision 1: + $ hg log -r 'publishedheads()' --graph + o changeset: 1:7a344d213ee2 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: add a + | + +ancestors of publishedheads shows all frozen revisions: + $ hg log -r '::publishedheads()' --graph + o changeset: 1:7a344d213ee2 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: add a + | + o changeset: 0:d32fd17cb041 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add z + + $ cd .. + $ hg init beta + $ cd beta + $ cat > .hg/hgrc << EOF + > [states] + > ready=yes + > EOF + $ hg pull ../alpha --update + pulling from ../alpha + requesting all changes + adding changesets + adding manifests + adding file changes + added 4 changesets with 4 changes to 4 files + 4 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg log --graph -r 'publishedheads()' + o changeset: 1:7a344d213ee2 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: add a + | + +Freeze in beta and push to alpha: + $ hg published 3 + $ mkcommit d + $ hg push --traceback ../alpha + pushing to ../alpha + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + $ cd ../alpha + $ hg debugrevspec 'publishedheads()' + 3 + $ hg log --graph -r 'publishedheads()' + @ changeset: 3:090483935bca + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: add c + | + + $ hg log -r tip + changeset: 4:fb98f3f5bba0 + tag: tip + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add d + + $ mkcommit e + created new head + $ hg up -C 4 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg log -r 'publishedheads()' + changeset: 3:090483935bca + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add c +