changeset 5345:e9d187e87678

branching: merge with stable
author Anton Shestakov <av6@dwimlabs.net>
date Sun, 31 May 2020 14:09:17 +0800
parents c5a92ab4d2de (diff) 3c5bcb8ecf3a (current diff)
children f06c76832c81
files
diffstat 13 files changed, 106 insertions(+), 171 deletions(-) [+]
line wrap: on
line diff
--- a/.gitlab-ci.yml	Thu May 21 09:51:24 2020 +0800
+++ b/.gitlab-ci.yml	Sun May 31 14:09:17 2020 +0800
@@ -13,37 +13,45 @@
         - pytype -P /ci/repos/mercurial/:hgext3rd -k hgext3rd -x hgext3rd/evolve/thirdparty -j $jobs || true
     when: manual
 
-tests-py2-cext:
-    image: octobus/ci-py2-hgext3rd
-    script:
-        - hg pull -R /ci/repos/mercurial/
-        - hg_rev=$(tests/testlib/map-hg-rev.sh "$(hg log -r . -T '{branch}')")
-        - hg -R /ci/repos/mercurial/ update "$hg_rev"
-        - (cd tests; /ci/repos/mercurial/tests/run-tests.py --color=always)
+variables:
+    PY: py2
+    PYTHON: python
+    RUNTEST_ARGS: ""
+    TEST_HGMODULEPOLICY: "allow"
 
-tests-py2-pure:
-    image: octobus/ci-py2-hgext3rd
+.runtests_template: &runtests
+    image: octobus/ci-$PY-hgext3rd
     script:
         - hg pull -R /ci/repos/mercurial/
         - hg_rev=$(tests/testlib/map-hg-rev.sh "$(hg log -r . -T '{branch}')")
         - hg -R /ci/repos/mercurial/ update "$hg_rev"
-        - (cd tests; /ci/repos/mercurial/tests/run-tests.py --color=always --pure)
+        - (cd tests; set -x; HGMODULEPOLICY="$TEST_HGMODULEPOLICY" "$PYTHON" /ci/repos/mercurial/tests/run-tests.py --color=always $RUNTEST_ARGS)
+
+tests-py2-cext:
+    <<: *runtests
+    variables:
+        TEST_HGMODULEPOLICY: "c"
+
+tests-py2-pure:
+    <<: *runtests
+    variables:
+        RUNTEST_ARGS: "--pure"
+        TEST_HGMODULEPOLICY: "py"
 
 tests-py3-cext:
-    image: octobus/ci-py3-hgext3rd
-    script:
-        - hg pull -R /ci/repos/mercurial/
-        - hg_rev=$(tests/testlib/map-hg-rev.sh "$(hg log -r . -T '{branch}')")
-        - hg -R /ci/repos/mercurial/ update "$hg_rev"
-        - (cd tests; python3 /ci/repos/mercurial/tests/run-tests.py --color=always)
+    <<: *runtests
+    variables:
+        PY: py3
+        PYTHON: python3
+        TEST_HGMODULEPOLICY: "c"
 
 tests-py3-pure:
-    image: octobus/ci-py3-hgext3rd
-    script:
-        - hg pull -R /ci/repos/mercurial/
-        - hg_rev=$(tests/testlib/map-hg-rev.sh "$(hg log -r . -T '{branch}')")
-        - hg -R /ci/repos/mercurial/ update "$hg_rev"
-        - (cd tests; python3 /ci/repos/mercurial/tests/run-tests.py --color=always --pure)
+    <<: *runtests
+    variables:
+        PY: py3
+        PYTHON: python3
+        RUNTEST_ARGS: "--pure"
+        TEST_HGMODULEPOLICY: "py"
 
 doc:
     image: octobus/ci-py2-evolve-doc
--- a/CHANGELOG	Thu May 21 09:51:24 2020 +0800
+++ b/CHANGELOG	Sun May 31 14:09:17 2020 +0800
@@ -1,6 +1,13 @@
 Changelog
 =========
 
+10.1.0 - in progress
+--------------------
+
+topic (0.20.0)
+
+  * stack: support foo#stack relation revset (hg-5.4+ only)
+
 10.0.0 -- 2020-05-09
 --------------------
 
--- a/hgext3rd/evolve/compat.py	Thu May 21 09:51:24 2020 +0800
+++ b/hgext3rd/evolve/compat.py	Sun May 31 14:09:17 2020 +0800
@@ -12,6 +12,7 @@
 from mercurial import (
     context,
     copies,
+    merge as mergemod,
     obsolete,
     pycompat,
     registrar,
@@ -35,6 +36,13 @@
 except (AttributeError, ImportError):
     dirs = util.dirs  # pytype: disable=module-attr
 
+# hg <= 5.4 (b7808443ed6a)
+try:
+    from mercurial import mergestate as mergestatemod
+    mergestate = mergestatemod.mergestate
+except (AttributeError, ImportError):
+    mergestate = mergemod.mergestate  # pytype: disable=module-attr
+
 from . import (
     exthelper,
 )
--- a/hgext3rd/evolve/evolvecmd.py	Thu May 21 09:51:24 2020 +0800
+++ b/hgext3rd/evolve/evolvecmd.py	Sun May 31 14:09:17 2020 +0800
@@ -493,7 +493,7 @@
     divergent, other, resolutionparent, relocatereq = datatoproceed[1:]
 
     if relocatereq:
-        evolvestate['relocation-req'] = True
+        evolvestate[b'relocation-req'] = True
     evolvestate[b'resolutionparent'] = resolutionparent
 
     if not ui.quiet or confirm:
@@ -515,10 +515,6 @@
         ui.write((b'hg commit -m "`hg log -r %s --template={desc}`";\n'
                   % divergent))
         return (False, b".")
-
-    if relocatereq:
-        evolvestate[b'relocation-req'] = True
-    evolvestate[b'resolutionparent'] = resolutionparent
     try:
         succsdivp1 = utility._singlesuccessor(repo, divergent.p1())
     except utility.MultipleSuccessorsError:
@@ -1981,7 +1977,7 @@
 def continueevolve(ui, repo, evolvestate):
     """logic for handling of `hg evolve --continue`"""
 
-    ms = merge.mergestate.read(repo)
+    ms = compat.mergestate.read(repo)
     mergeutil.checkunresolved(ms)
     if (evolvestate[b'command'] == b'next'
         or evolvestate[b'category'] == b'orphan'):
--- a/hgext3rd/evolve/templatekw.py	Thu May 21 09:51:24 2020 +0800
+++ b/hgext3rd/evolve/templatekw.py	Sun May 31 14:09:17 2020 +0800
@@ -9,7 +9,6 @@
 """
 
 from . import (
-    error,
     exthelper,
     obshistory,
 )
@@ -23,15 +22,6 @@
 
 ### template keywords
 
-@eh.templatekeyword(b'instabilities', requires={b'ctx', b'templ'})
-def showinstabilities(context, mapping):
-    """List of strings. Evolution instabilities affecting the changeset
-    (zero or more of "orphan", "content-divergent" or "phase-divergent")."""
-    ctx = context.resource(mapping, b'ctx')
-    return templatekw.compatlist(context, mapping, b'instability',
-                                 ctx.instabilities(),
-                                 plural=b'instabilities')
-
 @eh.templatekeyword(b'troubles', requires={b'ctx', b'templ'})
 def showtroubles(context, mapping):   # legacy name for instabilities
     ctx = context.resource(mapping, b'ctx')
@@ -60,12 +50,6 @@
 else:
     templatekw.keywords[b"precursors"] = _sp
 
-
-def closestsuccessors(repo, nodeid):
-    """ returns the closest visible successors sets instead.
-    """
-    return directsuccessorssets(repo, nodeid)
-
 _ss = templatekw.showsuccessorssets
 if util.safehasattr(_ss, '_requires'):
     def showsuccessors(context, mapping):
@@ -75,98 +59,3 @@
     _tk(showsuccessors)
 else:
     templatekw.keywords[b"successors"] = _ss
-
-def _getusername(ui):
-    """the default username in the config or None"""
-    try:
-        return ui.username()
-    except error.Abort: # no easy way to avoid ui raising Abort here :-/
-        return None
-
-# copy from mercurial.obsolete with a small change to stop at first known changeset.
-
-def directsuccessorssets(repo, initialnode, cache=None):
-    """return set of all direct successors of initial nodes
-    """
-
-    succmarkers = repo.obsstore.successors
-
-    # Stack of nodes we search successors sets for
-    toproceed = [initialnode]
-    # set version of above list for fast loop detection
-    # element added to "toproceed" must be added here
-    stackedset = set(toproceed)
-
-    pathscache = {}
-
-    if cache is None:
-        cache = {}
-    while toproceed:
-        current = toproceed[-1]
-        if current in cache:
-            stackedset.remove(toproceed.pop())
-        elif current != initialnode and current in repo:
-            # We have a valid direct successors.
-            cache[current] = [(current,)]
-        elif current not in succmarkers:
-            if current in repo:
-                # We have a valid last successors.
-                cache[current] = [(current,)]
-            else:
-                # Final obsolete version is unknown locally.
-                # Do not count that as a valid successors
-                cache[current] = []
-        else:
-            for mark in sorted(succmarkers[current]):
-                for suc in mark[1]:
-                    if suc not in cache:
-                        if suc in stackedset:
-                            # cycle breaking
-                            cache[suc] = []
-                        else:
-                            # case (3) If we have not computed successors sets
-                            # of one of those successors we add it to the
-                            # `toproceed` stack and stop all work for this
-                            # iteration.
-                            pathscache.setdefault(suc, []).append((current, mark))
-                            toproceed.append(suc)
-                            stackedset.add(suc)
-                            break
-                else:
-                    continue
-                break
-            else:
-                succssets = []
-                for mark in sorted(succmarkers[current]):
-                    # successors sets contributed by this marker
-                    markss = [[]]
-                    for suc in mark[1]:
-                        # cardinal product with previous successors
-                        productresult = []
-                        for prefix in markss:
-                            for suffix in cache[suc]:
-                                newss = list(prefix)
-                                for part in suffix:
-                                    # do not duplicated entry in successors set
-                                    # first entry wins.
-                                    if part not in newss:
-                                        newss.append(part)
-                                productresult.append(newss)
-                        markss = productresult
-                    succssets.extend(markss)
-                # remove duplicated and subset
-                seen = []
-                final = []
-                candidate = sorted(((set(s), s) for s in succssets if s),
-                                   key=lambda x: len(x[1]), reverse=True)
-                for setversion, listversion in candidate:
-                    for seenset in seen:
-                        if setversion.issubset(seenset):
-                            break
-                    else:
-                        final.append(listversion)
-                        seen.append(setversion)
-                final.reverse() # put small successors set first
-                cache[current] = final
-
-    return cache[initialnode], pathscache
--- a/hgext3rd/topic/revset.py	Thu May 21 09:51:24 2020 +0800
+++ b/hgext3rd/topic/revset.py	Sun May 31 14:09:17 2020 +0800
@@ -107,8 +107,10 @@
         branch = repo[None].branch()
     return revset.baseset(stack.stack(repo, branch=branch, topic=topic)[1:]) & subset
 
+# x#y[z] revset operator support (no support for older version)
+# hg <= 4.8 (e54bfde922f2)
 if util.safehasattr(revset, 'subscriptrelations'):
-    def stackrel(repo, subset, x, rel, z, order):
+    def stacksubrel(repo, subset, x, rel, z, order):
         """This is a revset-flavored implementation of stack aliases.
 
         The syntax is: rev#stack[n] or rev#s[n]. Plenty of logic is borrowed
@@ -160,15 +162,25 @@
 
         return subset & revset.baseset(revs)
 
-    revset.subscriptrelations[b'stack'] = stackrel
-    revset.subscriptrelations[b's'] = stackrel
+    revset.subscriptrelations[b'stack'] = stacksubrel
+    revset.subscriptrelations[b's'] = stacksubrel
 
-    def topicrel(repo, subset, x, *args):
+    def topicsubrel(repo, subset, x, *args):
         subset &= topicset(repo, subset, x)
         # not using revset.generationssubrel directly because it was renamed
         # hg <= 5.3 (8859de3e83dc)
         generationssubrel = revset.subscriptrelations[b'generations']
         return generationssubrel(repo, subset, x, *args)
 
-    revset.subscriptrelations[b'topic'] = topicrel
-    revset.subscriptrelations[b't'] = topicrel
+    revset.subscriptrelations[b'topic'] = topicsubrel
+    revset.subscriptrelations[b't'] = topicsubrel
+
+    # x#y revset operator support (no support for older version)
+    # hg <= 5.3 (eca82eb9d777)
+    if util.safehasattr(revset, 'relations'):
+        def stackrel(repo, subset, x, rel, order):
+            z = (b'rangeall', None)
+            return stacksubrel(repo, subset, x, rel, z, order)
+
+        revset.relations[b'stack'] = stackrel
+        revset.relations[b's'] = stackrel
--- a/tests/hghaveaddon.py	Thu May 21 09:51:24 2020 +0800
+++ b/tests/hghaveaddon.py	Sun May 31 14:09:17 2020 +0800
@@ -12,3 +12,19 @@
         except ImportError:
             return False
     return True
+
+@hghave.check("flake8", "Flake8 python linter")
+def has_flake8():
+    try:
+        import flake8
+
+        flake8.__version__
+    except ImportError:
+        return False
+    else:
+        return True
+
+@hghave.check("check-manifest", "check-manifest MANIFEST.in checking tool")
+def has_check_manifest():
+    return hghave.matchoutput('check-manifest --version 2>&1',
+                              br'check-manifest version')
--- a/tests/test-check-flake8.t	Thu May 21 09:51:24 2020 +0800
+++ b/tests/test-check-flake8.t	Sun May 31 14:09:17 2020 +0800
@@ -1,12 +1,4 @@
-#require test-repo
-
-  $ checkflake8() {
-  >   if ! (which flake8 > /dev/null); then
-  >     echo skipped: missing tool: flake8;
-  >     exit 80;
-  >   fi;
-  > };
-  $ checkflake8
+#require test-repo flake8
 
 Copied from Mercurial core (60ee2593a270)
 
@@ -17,4 +9,4 @@
   $ hg files -0 'set:(**.py or grep("^#!.*python")) - removed()' \
   > -X hgext3rd/evolve/thirdparty \
   > 2>/dev/null \
-  > | xargs -0 flake8
+  > | xargs -0 "$PYTHON" -m flake8
--- a/tests/test-check-pyflakes.t	Thu May 21 09:51:24 2020 +0800
+++ b/tests/test-check-pyflakes.t	Sun May 31 14:09:17 2020 +0800
@@ -7,5 +7,7 @@
 run pyflakes on all tracked files ending in .py or without a file ending
 (skipping binary file random-seed)
 
-  $ hg locate -I 'set:(**.py or grep("^#!.*python")) - removed()' 2>/dev/null \
-  > | xargs pyflakes 2>/dev/null
+  $ hg files -0 'set:(**.py or grep("^#!.*python")) - removed()' \
+  > -X hgext3rd/evolve/thirdparty \
+  > 2>/dev/null \
+  > | xargs -0 "$PYTHON" -m pyflakes 2>/dev/null
--- a/tests/test-check-setup-manifest.t	Thu May 21 09:51:24 2020 +0800
+++ b/tests/test-check-setup-manifest.t	Sun May 31 14:09:17 2020 +0800
@@ -1,12 +1,5 @@
-#require test-repo
+#require test-repo check-manifest
 
-  $ checkcm() {
-  >   if ! (which check-manifest > /dev/null); then
-  >     echo skipped: missing tool: check-manifest;
-  >     exit 80;
-  >   fi;
-  > };
-  $ checkcm
   $ cat << EOF >> $HGRCPATH
   > [experimental]
   > evolution=all
--- a/tests/test-import.t	Thu May 21 09:51:24 2020 +0800
+++ b/tests/test-import.t	Sun May 31 14:09:17 2020 +0800
@@ -1,9 +1,3 @@
-
-This feature requires mercurial 3.0
-(and the `only()` revset is 3.0 specific)
-
-  $ (hg help revset | grep '"only(' > /dev/null) || exit 80
-
 Test creation of obsolescence marker by path import
 
   $ hg init auto-obsolete
--- a/tests/test-topic-stack.t	Thu May 21 09:51:24 2020 +0800
+++ b/tests/test-topic-stack.t	Sun May 31 14:09:17 2020 +0800
@@ -385,6 +385,14 @@
   hg: parse error: stack takes no arguments, it works on current topic
   [255]
 
+Stack relation:
+
+  $ hg log -r 'foo#stack'
+  2 default {foo} draft c_c
+  4 default {foo} draft c_e
+  5 default {foo} draft c_f
+  6 default {foo} draft c_d
+
 Stack relation subscript:
 
   $ hg log -r 'foo#stack[0]'
--- a/tests/test-topic.t	Thu May 21 09:51:24 2020 +0800
+++ b/tests/test-topic.t	Sun May 31 14:09:17 2020 +0800
@@ -910,6 +910,10 @@
     ^ 3
   s1: 0
 
+  $ tlog 'tip#s'
+  0: 
+  4: 
+
   $ tlog 'tip#stack[0]'
   $ tlog 'tip#stack[1]'
   0: 
@@ -928,6 +932,11 @@
   s1: 1
   s0^ 0 (base)
 
+  $ tlog 'featureA#s'
+  1: featureA
+  2: featureA
+  3: featureA
+
   $ tlog 'featureA#s[0]'
   0: 
   $ tlog 'featureA#s[0:0]'
@@ -978,6 +987,7 @@
   ### target: default (branch)
   (stack is empty)
   s0^ 4 (base current)
+  $ tlog 'wdir()#s'
   $ tlog 'wdir()#s[0]'
   4: