diff -r 0b714c4ad9ff -r 8f18c7b3af14 hgext/evolve.py --- a/hgext/evolve.py Mon Jun 22 19:24:21 2015 -0700 +++ b/hgext/evolve.py Tue Jun 23 00:02:23 2015 -0700 @@ -1410,7 +1410,7 @@ elif anyopt: revs = repo.revs('first(%s())' % (targetcat)) elif targetcat == 'unstable': - revs = set(_aspiringchildren(repo, repo['.'])) + revs = set(_aspiringchildren(repo, repo.revs('(.::) - obsolete()::'))) if 1 < len(revs): msg = "multiple evolve candidates" hint = (_("select one of %s with --rev") @@ -1589,29 +1589,37 @@ progresscb() _cleanup(ui, repo, startnode, showprogress) -def _aspiringchildren(repo, pctx): +def _possibledestination(repo, rev): + """return all changesets that may be a new parent for REV""" + tonode = repo.changelog.node + parents = repo.changelog.parentrevs + torev = repo.changelog.rev + dest = set() + tovisit = list(parents(rev)) + while tovisit: + r = tovisit.pop() + succsets = obsolete.successorssets(repo, tonode(r)) + if not succsets: + tovisit.extend(parents(r)) + else: + # We should probably pick only one destination from split + # (case where '1 < len(ss)'), This could be the currently tipmost + # but logic is less clear when result of the split are now on + # multiple branches. + for ss in succsets: + for n in ss: + dest.add(torev(n)) + return dest + +def _aspiringchildren(repo, revs): """Return a list of changectx which can be stabilized on top of pctx or - one of its descendants. Empty list if none can be found. - """ - def selfanddescendants(repo, pctx): - yield pctx - for prec in repo.set('allprecursors(%d)', pctx): - yield prec - for ctx in pctx.descendants(): - yield ctx - for prec in repo.set('allprecursors(%d)', ctx): - yield prec - - # Look for an unstable which can be stabilized as a child of - # node. The unstable must be a child of one of node predecessors. + one of its descendants. Empty list if none can be found.""" + target = set(revs) result = [] - directdesc = set([pctx.rev()]) - for ctx in selfanddescendants(repo, pctx): - for child in ctx.children(): - if ctx.rev() in directdesc and not child.obsolete(): - directdesc.add(child.rev()) - elif child.unstable(): - result.append(child) + for r in repo.revs('unstable() - %ld', revs): + dest = _possibledestination(repo, r) + if target & dest: + result.append(r) return result def _solveunstable(ui, repo, orig, dryrun=False, confirm=False,