# HG changeset patch # User Pierre-Yves David # Date 1344423572 -7200 # Node ID dc1bd3595075cf63f93f8265eb814527bd542164 # Parent 4d18739b506b3730673584011c67ab4fc8cc98c2 more doc and cleanup diff -r 4d18739b506b -r dc1bd3595075 hgext/obsolete.py --- 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 + + must be an iterable of (, (, ...)) 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 - - must be an iterable of (, (, ...)) 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):