[states] add --exact option to `hg <state> <nodes>` that allows to backward states bondaries
--- a/hgext/states.py Wed Sep 21 03:52:13 2011 +0200
+++ b/hgext/states.py Sun Sep 25 12:43:00 2011 +0200
@@ -197,8 +197,6 @@
TODO:
-- implement --exact
-
- implement consistency check
- implement --force
@@ -533,20 +531,30 @@
# automatic generation of command that set state
def makecmd(state):
- def cmdmoveheads(ui, repo, *changesets):
+ def cmdmoveheads(ui, repo, *changesets, **opts):
"""set revisions in %s state
This command also alter state of ancestors if necessary.
""" % state
+ if not state in repo._enabledstates:
+ raise error.Abort(
+ _('state %s is not activated' % state),
+ hint=_('try ``hg states %s`` before' % state))
+ if opts.get('exact'):
+ repo.setstate_unsafe(state, changesets)
+ return 0
revs = scmutil.revrange(repo, changesets)
repo.setstate(state, [repo.changelog.node(rev) for rev in revs])
return 0
return cmdmoveheads
for state in STATES:
- if state.trackheads:
- cmdmoveheads = makecmd(state)
- cmdtable[state.name] = (cmdmoveheads, [], '<revset>')
+ cmdmoveheads = makecmd(state)
+ cmdtable[state.name] = (cmdmoveheads, [
+ ('e', 'exact', False, _('move boundary so that revs are exactly in '
+ 'state <state> ( all([rev.state == <state> for '
+ 'rev in revs]))'))
+ ], '<revset>')
# Pushkey mechanism for mutable
#########################################
@@ -795,6 +803,32 @@
"""{ state-object -> set(defining head)} mapping"""
return _readstatesheads(self)
+ def setstate_unsafe(self, state, changesets):
+ """Change state of targets changesets and it's ancestors.
+
+ Simplify the list of heads.
+
+ Unlike ``setstate``, the "lower" states are also changed
+ """
+ #modify "lower" states
+ req_nodes_rst = '|'.join('((%s)::)' % rst for rst in changesets)
+ for st in STATES:
+ if st >= state: # only modify lower state heads for now
+ continue
+ try:
+ heads = self._statesheads[st]
+ except KeyError: # forget non-activated states
+ continue
+ olds = heads[:]
+ rst = "heads((::%s()) - (%s))" % (st.headssymbol, req_nodes_rst)
+ heads[:] = noderange(repo, [rst])
+ if olds != heads:
+ _writestateshead(self)
+ #modify the state
+ if state in self._statesheads:
+ revs = scmutil.revrange(repo, changesets)
+ repo.setstate(state, [repo.changelog.node(rev) for rev in revs])
+
def setstate(self, state, nodes):
"""change state of targets changeset and it's ancestors.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-states-exact.t Sun Sep 25 12:43:00 2011 +0200
@@ -0,0 +1,282 @@
+ $ cat >> $HGRCPATH <<EOF
+ > [web]
+ > push_ssl = false
+ > allow_push = *
+ > [extensions]
+ > EOF
+ $ echo "states=$(echo $(dirname $TESTDIR))/hgext/states.py" >> $HGRCPATH
+
+ $ mkcommit() {
+ > echo "$1" > "$1"
+ > hg add "$1"
+ > hg ci -m "$1"
+ > }
+ $ alias hglog='hg log --template "{desc|short} {rev} {state}\n"'
+
+ $ hg init alpha
+ $ cd alpha
+ $ hg states ready draft
+ $ mkcommit a
+ $ mkcommit b
+ $ mkcommit c
+ $ mkcommit d
+ $ mkcommit e
+ $ mkcommit f
+
+|0 - 1 - 2 - 3 - 4 - 5
+
+ $ hg ready 3
+ $ hg published 1
+ $ hglog
+ f 5 draft
+ e 4 draft
+ d 3 ready
+ c 2 ready
+ b 1 published
+ a 0 published
+
+very simple case
+ $ hg ready --exact 1
+ $ hglog
+ f 5 draft
+ e 4 draft
+ d 3 ready
+ c 2 ready
+ b 1 ready
+ a 0 published
+
+required state not in statesheads
+ $ hg draft --exact 3
+ $ hglog
+ f 5 draft
+ e 4 draft
+ d 3 draft
+ c 2 ready
+ b 1 ready
+ a 0 published
+
+remove all other states
+ $ hg draft --exact 0
+ $ hglog
+ f 5 draft
+ e 4 draft
+ d 3 draft
+ c 2 draft
+ b 1 draft
+ a 0 draft
+
+draft was not there before
+ $ hg ready 5
+ $ hg draft --exact 4
+ $ hglog
+ f 5 draft
+ e 4 draft
+ d 3 ready
+ c 2 ready
+ b 1 ready
+ a 0 ready
+
+already in the required state
+ $ hg draft --exact 5
+ $ hglog
+ f 5 draft
+ e 4 draft
+ d 3 ready
+ c 2 ready
+ b 1 ready
+ a 0 ready
+
+backward and foreward
+ $ hg published 1
+ $ hg ready --exact 1:4
+ $ hglog
+ f 5 draft
+ e 4 ready
+ d 3 ready
+ c 2 ready
+ b 1 ready
+ a 0 published
+
+with complex revset
+ $ hg draft --exact 'readyheads()'
+ $ hglog
+ f 5 draft
+ e 4 draft
+ d 3 ready
+ c 2 ready
+ b 1 ready
+ a 0 published
+ $ hg ready --exact 'publishedheads()'
+ $ hglog
+ f 5 draft
+ e 4 draft
+ d 3 ready
+ c 2 ready
+ b 1 ready
+ a 0 ready
+
+Work with branches now
+ $ hg up 1
+ 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
+ $ mkcommit g
+ created new head
+ $ mkcommit h
+ $ hg up 3
+ 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
+ $ mkcommit i
+ created new head
+ $ mkcommit j
+
+| / - - - - 6 - 7
+|0 - 1 - 2 - 3 - 4 - 5
+| \ - - - - - - - - - - - - 8 - 9
+
+Set the new branches as ready
+ $ hg ready 9 7
+ $ hglog
+ j 9 ready
+ i 8 ready
+ h 7 ready
+ g 6 ready
+ f 5 draft
+ e 4 draft
+ d 3 ready
+ c 2 ready
+ b 1 ready
+ a 0 ready
+
+with composite revset
+ $ hg draft --exact 5:5 7:8
+ $ hglog
+ j 9 draft
+ i 8 draft
+ h 7 draft
+ g 6 ready
+ f 5 draft
+ e 4 draft
+ d 3 ready
+ c 2 ready
+ b 1 ready
+ a 0 ready
+
+cross braches
+ $ hg published 5 7 9
+ $ hg draft --exact 4:6
+ $ hglog
+ j 9 published
+ i 8 published
+ h 7 draft
+ g 6 draft
+ f 5 draft
+ e 4 draft
+ d 3 published
+ c 2 published
+ b 1 published
+ a 0 published
+
+Ok more complicated stuffs
+ $ hg up 7
+ 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
+ $ mkcommit k
+ $ hg published 5 9 10
+
+| / - - - - 6 - 7 - - - - - 10
+|0 - 1 - 2 - 3 - 4 - 5
+| \ - - - - - - - - - - - - 8 - 9
+
+cross branches and propagation on the same branche
+ $ hg draft --exact 5:8
+ $ hglog
+ k 10 draft
+ j 9 draft
+ i 8 draft
+ h 7 draft
+ g 6 draft
+ f 5 draft
+ e 4 published
+ d 3 published
+ c 2 published
+ b 1 published
+ a 0 published
+
+
+cross branches and propagation on multiple branches
+ $ hg published 10
+ $ hg ready --exact 3 6:8
+ $ hglog
+ k 10 ready
+ j 9 draft
+ i 8 ready
+ h 7 ready
+ g 6 ready
+ f 5 draft
+ e 4 ready
+ d 3 ready
+ c 2 published
+ b 1 published
+ a 0 published
+
+propagate ready on multiple branches taht contains draft states
+ $ hg ready --exact 1
+ $ hglog
+ k 10 ready
+ j 9 draft
+ i 8 ready
+ h 7 ready
+ g 6 ready
+ f 5 draft
+ e 4 ready
+ d 3 ready
+ c 2 ready
+ b 1 ready
+ a 0 published
+
+brute propagation
+ $ hg draft --exact 0
+ $ hglog
+ k 10 draft
+ j 9 draft
+ i 8 draft
+ h 7 draft
+ g 6 draft
+ f 5 draft
+ e 4 draft
+ d 3 draft
+ c 2 draft
+ b 1 draft
+ a 0 draft
+
+forget non activated state
+ $ hg init beta
+ $ cd beta
+ $ hg states draft
+ $ mkcommit a
+ $ mkcommit b
+ $ mkcommit c
+ $ mkcommit d
+ $ mkcommit e
+ $ mkcommit f
+ $ hg published 5
+ $ hg draft --exact 3
+ $ hglog
+ f 5 draft
+ e 4 draft
+ d 3 draft
+ c 2 published
+ b 1 published
+ a 0 published
+ $ hg states
+ published
+ draft
+ $ hg ready 3
+ abort: state ready is not activated
+ (try ``hg states ready`` before)
+ [255]
+ $ hglog
+ f 5 draft
+ e 4 draft
+ d 3 draft
+ c 2 published
+ b 1 published
+ a 0 published
+