--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/evolution.py Wed Sep 14 22:29:19 2011 +0200
@@ -0,0 +1,70 @@
+# states.py - introduce the state concept for mercurial changeset
+#
+# Copyright 2011 Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
+# Logilab SA <contact@logilab.fr>
+# Pierre-Yves David <pierre-yves.david@ens-lyon.org>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+'''A set of command to make changeset evolve.'''
+
+from mercurial import cmdutil
+from mercurial import scmutil
+from mercurial import node
+from mercurial import error
+from mercurial import extensions
+from mercurial import commands
+from mercurial.i18n import _
+
+### util function
+#############################
+def noderange(repo, revsets):
+ """The same as revrange but return node"""
+ return map(repo.changelog.node,
+ scmutil.revrange(repo, revsets))
+
+### extension check
+#############################
+
+def extsetup(ui):
+ try:
+ rebase = extensions.find('obsolete')
+ except KeyError:
+ raise error.Abort(_('evolution extension require obsolete extension.'))
+
+### new command
+#############################
+cmdtable = {}
+command = cmdutil.command(cmdtable)
+
+@command('^kill',
+ [],
+ '<revs>')
+def kill(ui, repo, *revs):
+ """mark a changeset as obsolete
+
+ This update the parent directory to a not-killed parent if the current
+ working directory parent are killed.
+
+ XXX bookmark support
+ XXX handle merge
+ XXX check immutable first
+ """
+ wlock = repo.wlock()
+ try:
+ targetnodes = set(noderange(repo, revs))
+ for n in targetnodes:
+ repo.addobsolete(node.nullid, n)
+ # update to an unkilled parent
+ wdp = repo['.']
+ newnode = wdp
+ while newnode.obsolete():
+ newnode = newnode.parents()[0]
+ if newnode.node() != wdp.node():
+ commands.update(ui, repo, newnode.rev())
+ ui.status(_('working directory now at %s\n') % newnode)
+
+ finally:
+ wlock.release()
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-evolution.t Wed Sep 14 22:29:19 2011 +0200
@@ -0,0 +1,61 @@
+ $ cat >> $HGRCPATH <<EOF
+ > [web]
+ > push_ssl = false
+ > allow_push = *
+ > [alias]
+ > qlog = log --template='{rev} - {node|short} {desc} ({state})\n'
+ > [extensions]
+ > EOF
+ $ echo "states=$(echo $(dirname $TESTDIR))/hgext/states.py" >> $HGRCPATH
+ $ echo "obsolete=$(echo $(dirname $TESTDIR))/hgext/obsolete.py" >> $HGRCPATH
+ $ echo "evolution=$(echo $(dirname $TESTDIR))/hgext/evolution.py" >> $HGRCPATH
+ $ mkcommit() {
+ > echo "$1" > "$1"
+ > hg add "$1"
+ > hg ci -m "add $1"
+ > }
+
+various init
+
+ $ hg init local
+ $ cd local
+ $ hg states ready # XXX should be put in default config when state support it
+ $ mkcommit a
+ $ mkcommit b
+ $ mkcommit c
+ $ mkcommit d
+ $ hg up 1
+ 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+ $ mkcommit e -q
+ created new head
+ $ mkcommit f
+ $ hg published 1
+ $ hg qlog
+ 5 - e44648563c73 add f (ready)
+ 4 - fbb94e3a0ecf add e (ready)
+ 3 - 47d2a3944de8 add d (ready)
+ 2 - 4538525df7e2 add c (ready)
+ 1 - 7c3bad9141dc add b (published)
+ 0 - 1f0dee641bb7 add a (published)
+
+test simple kill
+
+ $ hg kill 5
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ working directory now at fbb94e3a0ecf
+ $ hg qlog
+ 4 - fbb94e3a0ecf add e (ready)
+ 3 - 47d2a3944de8 add d (ready)
+ 2 - 4538525df7e2 add c (ready)
+ 1 - 7c3bad9141dc add b (published)
+ 0 - 1f0dee641bb7 add a (published)
+
+test multiple kill
+
+ $ hg kill 4 3
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ working directory now at 7c3bad9141dc
+ $ hg qlog
+ 2 - 4538525df7e2 add c (ready)
+ 1 - 7c3bad9141dc add b (published)
+ 0 - 1f0dee641bb7 add a (published)