--- a/hgext/obsolete.py Wed Aug 08 11:54:27 2012 +0200
+++ b/hgext/obsolete.py Wed Aug 08 12:59:32 2012 +0200
@@ -476,6 +476,18 @@
### Complete troubles computation logic ###
#####################################################################
+# there is two kind of trouble not handled by core right now:
+# - latecomer: (successors for public changeset)
+# - conflicting: (two changeset try to succeed to the same precursors)
+#
+# This section add support for those two addition trouble
+#
+# - Cache computation
+# - revset and ctx method
+# - push warning
+
+### Cache computation
+
@cachefor('latecomer')
def _computelatecomerset(repo):
"""the set of rev trying to obsolete public revision"""
@@ -502,6 +514,8 @@
toprocess.update(obsstore.successors.get(prec, ()))
return conflicting
+### changectx method
+
@eh.addattr(context.changectx, 'latecomer')
def latecomer(ctx):
"""is the changeset latecomer (Try to succeed to public change)"""
@@ -516,14 +530,34 @@
return False
return ctx.rev() in getobscache(ctx._repo, 'conflicting')
+### revset symbol
+
+@eh.revset('latecomer')
+def revsetlatecomer(repo, subset, x):
+ """``latecomer()``
+ Changesets marked as successors of public changesets.
+ """
+ args = revset.getargs(x, 0, 0, 'latecomer takes no arguments')
+ lates = getobscache(repo, 'latecomer')
+ return [r for r in subset if r in lates]
+
+@eh.revset('conflicting')
+def revsetconflicting(repo, subset, x):
+ """``conflicting()``
+ Changesets marked as successors of a same changeset.
+ """
+ args = revset.getargs(x, 0, 0, 'conflicting takes no arguments')
+ conf = getobscache(repo, 'conflicting')
+ return [r for r in subset if r in conf]
+
+
### Discovery wrapping
@eh.wrapfunction(discovery, 'checkheads')
def wrapcheckheads(orig, repo, remote, outgoing, *args, **kwargs):
"""wrap mercurial.discovery.checkheads
- * prevent unstability to be pushed
- * patch remote to ignore obsolete heads on remote
+ * prevent latecomer and unstable to be pushed
"""
# do not push instability
for h in outgoing.missingheads:
@@ -543,6 +577,53 @@
### Additional Utilities ###
#####################################################################
+# This section contains a lot of small utility function and method
+
+# - Function to create markers
+# - useful alias pstatus and pdiff (should probably go in evolve)
+# - "troubles" method on changectx
+# - function to travel throught the obsolescence graph
+# - function to find useful changeset to stabilize
+
+### Marker Create
+
+def createmarkers(repo, relations, metadata=None, flag=0):
+ """Add obsolete markers between changeset in a repo
+
+ <relations> must be an iterable of (<old>, (<new>, ...)) tuple.
+ `old` and `news` are changectx.
+
+ Current user and date are used except if specified otherwise in the
+ metadata attribute.
+
+ /!\ assume the repo have been locked byt the user /!\
+ """
+ # prepare metadata
+ if metadata is None:
+ metadata = {}
+ if 'date' not in metadata:
+ metadata['date'] = '%i %i' % util.makedate()
+ if 'user' not in metadata:
+ metadata['user'] = repo.ui.username()
+ # check future marker
+ tr = repo.transaction('add-obsolescence-marker')
+ try:
+ for prec, sucs in relations:
+ if not prec.mutable():
+ raise util.Abort("Cannot obsolete immutable changeset: %s" % prec)
+ nprec = prec.node()
+ nsucs = tuple(s.node() for s in sucs)
+ if nprec in nsucs:
+ raise util.Abort("Changeset %s cannot obsolete himself" % prec)
+ repo.obsstore.create(tr, nprec, nsucs, flag, metadata)
+ clearobscaches(repo)
+ tr.close()
+ finally:
+ tr.release()
+
+
+### Useful alias
+
@eh.uisetup
def _installalias(ui):
if ui.config('alias', 'pstatus', None) is None:
@@ -550,6 +631,26 @@
if ui.config('alias', 'pdiff', None) is None:
ui.setconfig('alias', 'pdiff', 'diff --rev .^')
+# - "troubles" method on changectx
+
+@eh.addattr(context.changectx, 'troubles')
+def troubles(ctx):
+ """Return a tuple listing all the troubles that affect a changeset
+
+ Troubles may be "unstable", "latecomer" or "conflicting".
+ """
+ troubles = []
+ if ctx.unstable():
+ troubles.append('unstable')
+ if ctx.latecomer():
+ troubles.append('latecomer')
+ if ctx.conflicting():
+ troubles.append('conflicting')
+ return tuple(troubles)
+
+
+### Obsolescence graph
+
def _precursors(repo, s):
"""Precursor of a changeset"""
cs = set()
@@ -616,11 +717,6 @@
return cs
-### diagnostique tools
-
-def unstables(repo):
- """Return all unstable changeset"""
- return scmutil.revrange(repo, ['obsolete():: and (not obsolete())'])
def newerversion(repo, obs):
"""Return the newer version of an obsolete changeset"""
@@ -644,39 +740,11 @@
newer.add(())
return sorted(newer)
-def createmarkers(repo, relations, metadata=None, flag=0):
- """Add obsolete markers between changeset in a repo
-
- <relations> must be an iterable of (<old>, (<new>, ...)) tuple.
- `old` and `news` are changectx.
-
- Current user and date are used except if specified otherwise in the
- metadata attribute.
+### diagnostique tools
- /!\ assume the repo have been locked byt the user /!\
- """
- # prepare metadata
- if metadata is None:
- metadata = {}
- if 'date' not in metadata:
- metadata['date'] = '%i %i' % util.makedate()
- if 'user' not in metadata:
- metadata['user'] = repo.ui.username()
- # check future marker
- tr = repo.transaction('add-obsolescence-marker')
- try:
- for prec, sucs in relations:
- if not prec.mutable():
- raise util.Abort("Cannot obsolete immutable changeset: %s" % prec)
- nprec = prec.node()
- nsucs = tuple(s.node() for s in sucs)
- if nprec in nsucs:
- raise util.Abort("Changeset %s cannot obsolete himself" % prec)
- repo.obsstore.create(tr, nprec, nsucs, flag, metadata)
- clearobscaches(repo)
- tr.close()
- finally:
- tr.release()
+def unstables(repo):
+ """Return all unstable changeset"""
+ return scmutil.revrange(repo, ['obsolete():: and (not obsolete())'])
#####################################################################
### Extending revset and template ###
@@ -701,24 +769,6 @@
suspended = getobscache(repo, 'suspended')
return [r for r in subset if r in suspended]
-@eh.revset('latecomer')
-def revsetlatecomer(repo, subset, x):
- """``latecomer()``
- Changesets marked as successors of public changesets.
- """
- args = revset.getargs(x, 0, 0, 'latecomer takes no arguments')
- lates = getobscache(repo, 'latecomer')
- return [r for r in subset if r in lates]
-
-@eh.revset('conflicting')
-def revsetconflicting(repo, subset, x):
- """``conflicting()``
- Changesets marked as successors of a same changeset.
- """
- args = revset.getargs(x, 0, 0, 'conflicting takes no arguments')
- conf = getobscache(repo, 'conflicting')
- return [r for r in subset if r in conf]
-
@eh.revset('precursors')
def revsetprecursors(repo, subset, x):