Mercurial > evolve
changeset 1:beabde937e36
Add "private" concept (2). private changeset are hiden suppose to be hidden for
pull and push. For now it works for out and push
author | Pierre-Yves David <pierre-yves.david@logilab.fr> |
---|---|
date | Fri, 20 May 2011 19:14:19 +0200 |
parents | bbeef801409c |
children | 166694e62daf |
files | states.py tests/test-state.t |
diffstat | 2 files changed, 198 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/states.py Fri May 20 16:16:34 2011 +0200 +++ b/states.py Fri May 20 19:14:19 2011 +0200 @@ -17,22 +17,39 @@ name are not fixed yet. ''' +from functools import partial +from mercurial.i18n import _ +from mercurial import cmdutil +from mercurial import scmutil +from mercurial import context +from mercurial import revset +from mercurial import templatekw +from mercurial import util +from mercurial import node +from mercurial.node import nullid +from mercurial import discovery +from mercurial import extensions -STATES = (0, ) +_NOPULLPUSH=2 + +STATES = (0, _NOPULLPUSH) def statename(state): return str(STATES) -import mercurial.context -import mercurial.templatekw +# util function +############################# +def noderange(repo, revsets): + return map(repo.changelog.node, + scmutil.revrange(repo, revsets)) # Patch changectx ############################# def state(ctx): return ctx._repo.nodestate(ctx.node()) -mercurial.context.changectx.state = state +context.changectx.state = state # improve template ############################# @@ -40,16 +57,126 @@ def showstate(ctx, **args): return ctx.state() +# New revset predicate +############################# -mercurial.templatekw.keywords['state'] = showstate +def revsetpublicheads(repo, subset, x): + args = revset.getargs(x, 0, 0, 'publicheads takes no arguments') + heads = map(repo.changelog.rev, repo._statesheads[0]) + heads.sort() + return heads + +def extsetup(ui): + revset.symbols['publicheads'] = revsetpublicheads + +REVSETHEADS = {0: 'publicheads()'} + +# New commands +############################# + +def cmdsetstate(ui, repo, state, *changesets): + """turn private changesets into public ones""" + #assert repo.ui.configbool('private', 'enable', False) + state = int(state) #for now + revs = scmutil.revrange(repo, changesets) + repo.setstate(state, [repo.changelog.node(rev) for rev in revs]) + return 0 + +cmdtable = { + 'setstate': (cmdsetstate, [], _('state <revset>')), + } + + +templatekw.keywords['state'] = showstate + + + + + + +def uisetup(ui): + def filter_private(orig, repo, *args,**kwargs): + common, heads = orig(repo, *args, **kwargs) + return common, repo._reducehead(heads, repo._publicheads) + extensions.wrapfunction(discovery, 'findcommonoutgoing', filter_private) def reposetup(ui, repo): if not repo.local(): return + class statefulrepo(repo.__class__): def nodestate(self, node): + rev = self.changelog.rev(node) + for head in self._publicheads: + revhead = self.changelog.rev(head) + if self.changelog.descendant(revhead, rev): + return STATES[1] return STATES[0] + @property + def _publicheads(self): + if self.ui.configbool('states', 'private', False): + return self._statesheads[0] + return self.heads() + + @util.propertycache + def _statesheads(self): + return self._readstatesheads() + + + def _readstatesheads(self): + statesheads = {} + try: + f = self.opener('publicheads') + try: + heads = sorted([node.bin(n) for n in f.read().split() if n]) + finally: + f.close() + except IOError: + heads = [nullid] + statesheads[0] = heads + return statesheads + + def _writestateshead(self): + # transaction! + f = self.opener('publicheads', 'w', atomictemp=True) + try: + for h in self._statesheads[0]: + f.write(node.hex(h) + '\n') + f.rename() + finally: + f.close() + + def setstate(self, state, nodes): + """freeze targets changeset and it's ancestors. + + Simplify the list of head.""" + heads = self._statesheads[state] + olds = heads[:] + heads.extend(nodes) + heads[:] = set(heads) + heads.sort() + if olds != heads: + heads[:] = noderange(repo, ["heads(::%s)" % REVSETHEADS[state]]) + heads.sort() + if olds != heads: + self._writestateshead() + + def _reducehead(self, candidates, max): + selected = set() + for candidate in candidates: + rev = self.changelog.rev(candidate) + ok = True + for h in max: + revh = self.changelog.rev(h) + if self.changelog.descendant(revh, rev): + ok = False + selected.add(h) + if ok: + selected.add(candidate) + return sorted(selected) + repo.__class__ = statefulrepo +
--- a/tests/test-state.t Fri May 20 16:16:34 2011 +0200 +++ b/tests/test-state.t Fri May 20 19:14:19 2011 +0200 @@ -3,11 +3,73 @@ > EOF $ echo "states=$(echo $(dirname $TESTDIR))/states.py" >> $HGRCPATH - $ hg init repo - $ cd repo + $ hg init local + $ hg init remote1 + $ hg init remote2 + $ cd local $ echo "celestine" > babar $ hg add babar $ hg ci -m "add babar" - $ hg log --template='{node}: {state}\n' - 5caa672bac265926428463f2bee6e8903972ce31: 0 + $ echo "la veille dame" > babar + $ hg ci -m "add dame" + $ hg log --template='{rev}:{node|short}: {state}\n' + 1:710fe444b3b0: 0 + 0:5caa672bac26: 0 + $ hg out ../remote1 --template='{rev}:{node|short}\n' + comparing with ../remote1 + searching for changes + 0:5caa672bac26 + 1:710fe444b3b0 + $ hg push ../remote1 + pushing to ../remote1 + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 1 files + $ hg setstate 0 1 # until we fix push + $ echo "cornelius" >> babar + $ hg ci -m "great old one" + $ echo "flore" >> babar + $ hg ci -m "children" + $ hg log --template='{rev}:{node|short}: {state}\n' + 3:3f5e297fd1c6: 0 + 2:dc0a5281e2d9: 0 + 1:710fe444b3b0: 0 + 0:5caa672bac26: 0 + $ cat >> $HGRCPATH <<EOF + > [states] + > private=yes + > EOF + $ hg log --template='{rev}:{node|short}: {state}\n' + 3:3f5e297fd1c6: 2 + 2:dc0a5281e2d9: 2 + 1:710fe444b3b0: 0 + 0:5caa672bac26: 0 + $ hg out ../remote1 --template='{rev}:{node|short}\n' + comparing with ../remote1 + searching for changes + no changes found + [1] + $ hg push ../remote1 + pushing to ../remote1 + searching for changes + no changes found + + $ hg out ../remote2 --template='{rev}:{node|short}\n' + comparing with ../remote2 + searching for changes + 0:5caa672bac26 + 1:710fe444b3b0 + $ hg push ../remote2 + pushing to ../remote2 + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 1 files + + + +