--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/obsolete.py Fri Jul 29 18:54:05 2011 +0200
@@ -0,0 +1,104 @@
+# obsolete.py - introduce the obsolete concept in mercurial.
+#
+# Copyright 2011 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
+# Logilab SA <contact@logilab.fr>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from mercurial import util
+from mercurial import context
+from mercurial.node import hex, bin
+
+# Patch changectx
+#############################
+
+def obsolete(ctx):
+ if ctx.node()is None:
+ return False
+ return boolean(ctx._repo.obsoleteby(ctx.node()))
+
+context.changectx.obsolete = obsolete
+
+ohidden = context.changectx.hidden
+def hidden(ctx):
+ ctx._repo._obsobjrels # XXX hack to fill hiddenrevs
+ return ohidden(ctx)
+context.changectx.hidden = hidden
+
+# New commands
+#############################
+
+
+def cmddebugobsolete(ui, repo, subject, object):
+ """show enabled states"""
+ sub = repo[subject]
+ obj = repo[object]
+ repo.addobsolete(sub.node(), obj.node())
+ return 0
+
+cmdtable = {'debugobsolete': (cmddebugobsolete, [], '<subject> <object>')}
+
+def reposetup(ui, repo):
+
+ class obsoletingrepo(repo.__class__):
+
+ @util.propertycache
+ def hiddenrevs(self):
+ revs = set()
+ return revs
+
+ @util.propertycache
+ def _obsobjrels(self):
+ objrels = {}
+ for sub, objs in self._obssubrels.iteritems():
+ for obj in objs:
+ objrels.setdefault(obj, set()).add(sub)
+ for obj in objrels:
+ self.changelog.hiddenrevs.add(repo[obj].rev())
+ return objrels
+
+ @util.propertycache
+ def _obssubrels(self):
+ return self._readobsrels()
+
+
+ def _readobsrels(self):
+ rels = {}
+ try:
+ f = self.opener('obsolete-relations')
+ try:
+ for line in f:
+ subhex, objhex = line.split()
+ rels.setdefault(bin(subhex), set()).add(bin(objhex))
+ finally:
+ f.close()
+ except IOError:
+ pass
+ return rels
+
+ def _writeobsrels(self):
+ f = self.opener('obsolete-relations', 'w', atomictemp=True)
+ try:
+ for sub, objs in self._obssubrels.iteritems():
+ for obj in objs:
+ f.write('%s %s\n' % (hex(sub), hex(obj)))
+ f.rename()
+ finally:
+ f.close()
+
+ def obsoletedby(self, node):
+ return self._readobsrels.get(node, set())
+
+ def obsolete(self, node):
+ return self._readsubrels.get(node, set())
+
+ def addobsolete(self, sub, obj):
+ self._obssubrels.setdefault(sub, set()).add(obj)
+ self._obsobjrels.setdefault(obj, set()).add(sub)
+ self.changelog.hiddenrevs.add(repo[obj].rev())
+ self._writeobsrels()
+
+ repo.__class__ = obsoletingrepo
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-obsolete.t Fri Jul 29 18:54:05 2011 +0200
@@ -0,0 +1,64 @@
+ $ cat >> $HGRCPATH <<EOF
+ > [web]
+ > push_ssl = false
+ > allow_push = *
+ > [extensions]
+ > EOF
+ $ echo "states=$(echo $(dirname $TESTDIR))/obsolete.py" >> $HGRCPATH
+ $ mkcommit() {
+ > echo "$1" > "$1"
+ > hg add "$1"
+ > hg ci -m "add $1"
+ > }
+
+ $ hg init repo
+ $ cd repo
+ $ mkcommit a # 0
+ $ mkcommit b # 1
+ $ mkcommit c # 2
+ $ hg up 1
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ mkcommit obsol_c # 3
+ created new head
+ $ hg debugobsolete 3 2
+ $ hg log
+ changeset: 3:0d3f46688ccc
+ tag: tip
+ parent: 1:7c3bad9141dc
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: add obsol_c
+
+ changeset: 1:7c3bad9141dc
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: add b
+
+ changeset: 0:1f0dee641bb7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: add a
+
+ $ hg log --hidden
+ changeset: 3:0d3f46688ccc
+ tag: tip
+ parent: 1:7c3bad9141dc
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: add obsol_c
+
+ changeset: 2:4538525df7e2
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: add c
+
+ changeset: 1:7c3bad9141dc
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: add b
+
+ changeset: 0:1f0dee641bb7
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: add a
+