evolvecmd: move more code from __init__.py to evolvecmd.py
authorPulkit Goyal <7895pulkit@gmail.com>
Fri, 19 Jan 2018 15:55:38 +0530
changeset 3464 908d2b5dfa7e
parent 3463 f994c480cea9
child 3465 ffe566999920
evolvecmd: move more code from __init__.py to evolvecmd.py We are now very close to have most of the evolve related code in evolvecmd.py.
hgext3rd/evolve/__init__.py
hgext3rd/evolve/evolvecmd.py
--- a/hgext3rd/evolve/__init__.py	Fri Jan 19 15:22:28 2018 +0530
+++ b/hgext3rd/evolve/__init__.py	Fri Jan 19 15:55:38 2018 +0530
@@ -347,7 +347,6 @@
 aliases, entry = cmdutil.findcmd('commit', commands.table)
 commitopts3 = cmdrewrite.commitopts3
 interactiveopt = cmdrewrite.interactiveopt
-_bookmarksupdater = rewriteutil.bookmarksupdater
 rewrite = rewriteutil.rewrite
 
 # This extension contains the following code
@@ -1113,60 +1112,6 @@
                 rdependencies[succ].add(r)
     return dependencies, rdependencies
 
-def _dedupedivergents(repo, revs):
-    """Dedupe the divergents revs in revs to get one from each group with the
-    lowest revision numbers
-    """
-    repo = repo.unfiltered()
-    res = set()
-    # To not reevaluate divergents of the same group once one is encountered
-    discarded = set()
-    for rev in revs:
-        if rev in discarded:
-            continue
-        divergent = repo[rev]
-        base, others = divergentdata(divergent)
-        othersrevs = [o.rev() for o in others]
-        res.add(min([divergent.rev()] + othersrevs))
-        discarded.update(othersrevs)
-    return res
-
-instabilities_map = {
-    'contentdivergent': "content-divergent",
-    'phasedivergent': "phase-divergent"
-}
-
-def _selectrevs(repo, allopt, revopt, anyopt, targetcat):
-    """select troubles in repo matching according to given options"""
-    revs = set()
-    if allopt or revopt:
-        revs = repo.revs("%s()" % targetcat)
-        if revopt:
-            revs = scmutil.revrange(repo, revopt) & revs
-        elif not anyopt:
-            topic = getattr(repo, 'currenttopic', '')
-            if topic:
-                revs = repo.revs('topic(%s)', topic) & revs
-            elif targetcat == 'orphan':
-                revs = _aspiringdescendant(repo,
-                                           repo.revs('(.::) - obsolete()::'))
-                revs = set(revs)
-        if targetcat == 'contentdivergent':
-            # Pick one divergent per group of divergents
-            revs = _dedupedivergents(repo, revs)
-    elif anyopt:
-        revs = repo.revs('first(%s())' % (targetcat))
-    elif targetcat == 'orphan':
-        revs = set(_aspiringchildren(repo, repo.revs('(.::) - obsolete()::')))
-        if 1 < len(revs):
-            msg = "multiple evolve candidates"
-            hint = (_("select one of %s with --rev")
-                    % ', '.join([str(repo[r]) for r in sorted(revs)]))
-            raise error.Abort(msg, hint=hint)
-    elif instabilities_map.get(targetcat, targetcat) in repo['.'].instabilities():
-        revs = set([repo['.'].rev()])
-    return revs
-
 
 def _orderrevs(repo, revs):
     """Compute an ordering to solve instability for the given revs
@@ -1505,7 +1450,7 @@
 
     cmdutil.bailifchanged(repo)
 
-    revs = _selectrevs(repo, allopt, revopt, anyopt, targetcat)
+    revs = evolvecmd._selectrevs(repo, allopt, revopt, anyopt, targetcat)
 
     if not revs:
         return _handlenotrouble(ui, repo, allopt, revopt, anyopt, targetcat)
@@ -1567,75 +1512,6 @@
 
     return opts
 
-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 = compat.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."""
-    target = set(revs)
-    result = []
-    for r in repo.revs('orphan() - %ld', revs):
-        dest = _possibledestination(repo, r)
-        if target & dest:
-            result.append(r)
-    return result
-
-def _aspiringdescendant(repo, revs):
-    """Return a list of changectx which can be stabilized on top of pctx or
-    one of its descendants recursively. Empty list if none can be found."""
-    target = set(revs)
-    result = set(target)
-    paths = collections.defaultdict(set)
-    for r in repo.revs('orphan() - %ld', revs):
-        for d in _possibledestination(repo, r):
-            paths[d].add(r)
-
-    result = set(target)
-    tovisit = list(revs)
-    while tovisit:
-        base = tovisit.pop()
-        for unstable in paths[base]:
-            if unstable not in result:
-                tovisit.append(unstable)
-                result.add(unstable)
-    return sorted(result - target)
-
-def divergentdata(ctx):
-    """return base, other part of a conflict
-
-    This only return the first one.
-
-    XXX this woobly function won't survive XXX
-    """
-    repo = ctx._repo.unfiltered()
-    for base in repo.set('reverse(allprecursors(%d))', ctx):
-        newer = compat.successorssets(ctx._repo, base.node())
-        # drop filter and solution including the original ctx
-        newer = [n for n in newer if n and ctx.node() not in n]
-        if newer:
-            return base, tuple(ctx._repo[o] for o in newer[0])
-    raise error.Abort("base of divergent changeset %s not found" % ctx,
-                      hint='this case is not yet handled')
 
 def _gettopic(ctx):
     """handle topic fetching with or without the extension"""
@@ -1826,7 +1702,7 @@
             ui.warn(_('explicitly update to one of them\n'))
             result = 1
         else:
-            aspchildren = _aspiringchildren(repo, [repo['.'].rev()])
+            aspchildren = evolvecmd._aspiringchildren(repo, [repo['.'].rev()])
             if topic:
                 filtered.extend(repo[c] for c in children
                                 if repo[c].topic() != topic)
--- a/hgext3rd/evolve/evolvecmd.py	Fri Jan 19 15:22:28 2018 +0530
+++ b/hgext3rd/evolve/evolvecmd.py	Fri Jan 19 15:55:38 2018 +0530
@@ -8,6 +8,7 @@
 
 """logic related to hg evolve command"""
 
+import collections
 import re
 
 from mercurial import (
@@ -22,6 +23,7 @@
     node,
     obsolete,
     phases,
+    scmutil,
     util,
 )
 
@@ -40,7 +42,7 @@
 _bookmarksupdater = rewriteutil.bookmarksupdater
 sha1re = re.compile(r'\b[0-9a-f]{6,40}\b')
 
-from . import divergentdata
+_bookmarksupdater = rewriteutil.bookmarksupdater
 
 def _solveone(ui, repo, ctx, dryrun, confirm, progresscb, category):
     """Resolve the troubles affecting one revision
@@ -526,3 +528,127 @@
                 f.write(orig.topic())
 
     return merge.graft(repo, orig, pctx, ['destination', 'evolving'], True)
+
+instabilities_map = {
+    'contentdivergent': "content-divergent",
+    'phasedivergent': "phase-divergent"
+}
+
+def _selectrevs(repo, allopt, revopt, anyopt, targetcat):
+    """select troubles in repo matching according to given options"""
+    revs = set()
+    if allopt or revopt:
+        revs = repo.revs("%s()" % targetcat)
+        if revopt:
+            revs = scmutil.revrange(repo, revopt) & revs
+        elif not anyopt:
+            topic = getattr(repo, 'currenttopic', '')
+            if topic:
+                revs = repo.revs('topic(%s)', topic) & revs
+            elif targetcat == 'orphan':
+                revs = _aspiringdescendant(repo,
+                                           repo.revs('(.::) - obsolete()::'))
+                revs = set(revs)
+        if targetcat == 'contentdivergent':
+            # Pick one divergent per group of divergents
+            revs = _dedupedivergents(repo, revs)
+    elif anyopt:
+        revs = repo.revs('first(%s())' % (targetcat))
+    elif targetcat == 'orphan':
+        revs = set(_aspiringchildren(repo, repo.revs('(.::) - obsolete()::')))
+        if 1 < len(revs):
+            msg = "multiple evolve candidates"
+            hint = (_("select one of %s with --rev")
+                    % ', '.join([str(repo[r]) for r in sorted(revs)]))
+            raise error.Abort(msg, hint=hint)
+    elif instabilities_map.get(targetcat, targetcat) in repo['.'].instabilities():
+        revs = set([repo['.'].rev()])
+    return revs
+
+def _dedupedivergents(repo, revs):
+    """Dedupe the divergents revs in revs to get one from each group with the
+    lowest revision numbers
+    """
+    repo = repo.unfiltered()
+    res = set()
+    # To not reevaluate divergents of the same group once one is encountered
+    discarded = set()
+    for rev in revs:
+        if rev in discarded:
+            continue
+        divergent = repo[rev]
+        base, others = divergentdata(divergent)
+        othersrevs = [o.rev() for o in others]
+        res.add(min([divergent.rev()] + othersrevs))
+        discarded.update(othersrevs)
+    return res
+
+def divergentdata(ctx):
+    """return base, other part of a conflict
+
+    This only return the first one.
+
+    XXX this woobly function won't survive XXX
+    """
+    repo = ctx._repo.unfiltered()
+    for base in repo.set('reverse(allprecursors(%d))', ctx):
+        newer = compat.successorssets(ctx._repo, base.node())
+        # drop filter and solution including the original ctx
+        newer = [n for n in newer if n and ctx.node() not in n]
+        if newer:
+            return base, tuple(ctx._repo[o] for o in newer[0])
+    raise error.Abort("base of divergent changeset %s not found" % ctx,
+                      hint='this case is not yet handled')
+
+def _aspiringdescendant(repo, revs):
+    """Return a list of changectx which can be stabilized on top of pctx or
+    one of its descendants recursively. Empty list if none can be found."""
+    target = set(revs)
+    result = set(target)
+    paths = collections.defaultdict(set)
+    for r in repo.revs('orphan() - %ld', revs):
+        for d in _possibledestination(repo, r):
+            paths[d].add(r)
+
+    result = set(target)
+    tovisit = list(revs)
+    while tovisit:
+        base = tovisit.pop()
+        for unstable in paths[base]:
+            if unstable not in result:
+                tovisit.append(unstable)
+                result.add(unstable)
+    return sorted(result - target)
+
+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."""
+    target = set(revs)
+    result = []
+    for r in repo.revs('orphan() - %ld', revs):
+        dest = _possibledestination(repo, r)
+        if target & dest:
+            result.append(r)
+    return result
+
+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 = compat.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