# HG changeset patch # User Anton Shestakov # Date 1590905357 -28800 # Node ID e9d187e87678a6a1039034f5dc450e3a82f16390 # Parent c5a92ab4d2de765ff0f3ff7f834e6b719883f887# Parent 3c5bcb8ecf3a366aa1b652ff5630a799f53f15a2 branching: merge with stable diff -r 3c5bcb8ecf3a -r e9d187e87678 .gitlab-ci.yml --- 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 diff -r 3c5bcb8ecf3a -r e9d187e87678 CHANGELOG --- 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 -------------------- diff -r 3c5bcb8ecf3a -r e9d187e87678 hgext3rd/evolve/compat.py --- 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, ) diff -r 3c5bcb8ecf3a -r e9d187e87678 hgext3rd/evolve/evolvecmd.py --- 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'): diff -r 3c5bcb8ecf3a -r e9d187e87678 hgext3rd/evolve/templatekw.py --- 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 diff -r 3c5bcb8ecf3a -r e9d187e87678 hgext3rd/topic/revset.py --- 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 diff -r 3c5bcb8ecf3a -r e9d187e87678 tests/hghaveaddon.py --- 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') diff -r 3c5bcb8ecf3a -r e9d187e87678 tests/test-check-flake8.t --- 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 diff -r 3c5bcb8ecf3a -r e9d187e87678 tests/test-check-pyflakes.t --- 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 diff -r 3c5bcb8ecf3a -r e9d187e87678 tests/test-check-setup-manifest.t --- 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 diff -r 3c5bcb8ecf3a -r e9d187e87678 tests/test-import.t --- 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 diff -r 3c5bcb8ecf3a -r e9d187e87678 tests/test-topic-stack.t --- 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]' diff -r 3c5bcb8ecf3a -r e9d187e87678 tests/test-topic.t --- 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: