# HG changeset patch # User Anton Shestakov # Date 1604140632 -28800 # Node ID ee18173c54a295400feddd5db49281f2469070c9 # Parent 72d88e491a199e6ab1aef9a8a7613ad5e6749a09# Parent af0458d91d10e0cb77fe15dac725a6cf05edfe22 test-compat: merge mercurial-5.4 into mercurial-5.3 # no-check-commit diff -r af0458d91d10 -r ee18173c54a2 .gitlab-ci.yml --- a/.gitlab-ci.yml Sun Sep 06 05:38:24 2020 +0800 +++ b/.gitlab-ci.yml Sat Oct 31 18:37:12 2020 +0800 @@ -1,49 +1,73 @@ -flake8: - image: octobus/ci-py2-hgext3rd - script: - - hg files -0 'set:(**.py or grep("^#!.*python")) - removed()' -X hgext3rd/evolve/thirdparty | xargs -0 flake8 +.prepare_hg: &prepare_hg + - hg pull -R /ci/repos/mercurial/ + - hg_branch=$(tests/testlib/map-hg-rev.sh "$(hg identify --branch)") + - hg -R /ci/repos/mercurial/ update "$hg_branch" + - hg_rev=$(hg log -R /ci/repos/mercurial/ -r . -T '{node}') + - echo testing with mercurial branch="$hg_branch", revision="$hg_rev" pytype: 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" + - *prepare_hg + - pytype --version - jobs=$(python -c 'import multiprocessing; print multiprocessing.cpu_count()') - 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 +variables: + PY: py2 + PYTHON: python + RUNTEST_ARGS: "" + TEST_HGMODULEPOLICY: "allow" + +.runtests_template: &runtests + image: octobus/ci-$PY-hgext3rd + before_script: + - (cd tests; ls -1 test-check-*.t > /tmp/check-tests.txt) 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) + - *prepare_hg + - ("$PYTHON" --version) + - (cd tests; set -x; HGMODULEPOLICY="$TEST_HGMODULEPOLICY" "$PYTHON" /ci/repos/mercurial/tests/run-tests.py --color=always $RUNTEST_ARGS) + +checks-py2: + <<: *runtests + variables: + RUNTEST_ARGS: "--test-list /tmp/check-tests.txt" + +checks-py3: + <<: *runtests + variables: + PY: py3 + PYTHON: python3 + RUNTEST_ARGS: "--test-list /tmp/check-tests.txt" + +tests-py2-cext: + <<: *runtests + variables: + RUNTEST_ARGS: "--blacklist /tmp/check-tests.txt" + TEST_HGMODULEPOLICY: "c" tests-py2-pure: - 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 --pure) + <<: *runtests + variables: + RUNTEST_ARGS: "--pure --blacklist /tmp/check-tests.txt" + 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 + RUNTEST_ARGS: "--blacklist /tmp/check-tests.txt" + 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 --blacklist /tmp/check-tests.txt" + TEST_HGMODULEPOLICY: "py" doc: image: octobus/ci-py2-evolve-doc diff -r af0458d91d10 -r ee18173c54a2 .gitlab/issue_templates/new-version.md --- a/.gitlab/issue_templates/new-version.md Sun Sep 06 05:38:24 2020 +0800 +++ b/.gitlab/issue_templates/new-version.md Sat Oct 31 18:37:12 2020 +0800 @@ -1,6 +1,6 @@ This is the actual check list for releasing evolve version X.Y.Z -More details in the [README file](README#L179). +More details in the [README.rst file](README.rst#L199). Preparation diff -r af0458d91d10 -r ee18173c54a2 .hgtags --- a/.hgtags Sun Sep 06 05:38:24 2020 +0800 +++ b/.hgtags Sat Oct 31 18:37:12 2020 +0800 @@ -88,3 +88,4 @@ 8d955635cf457aaa4810d77740721d4275001f74 9.3.1 27d57ca8686590867e62e3d42c96bad84a5f56ef 10.0.0 fb543438704b73b22023a493c9ef76fc8746b796 10.0.1 +1cce884c944830a7b331a17fd18614b93cbac987 10.0.2 diff -r af0458d91d10 -r ee18173c54a2 CHANGELOG --- a/CHANGELOG Sun Sep 06 05:38:24 2020 +0800 +++ b/CHANGELOG Sat Oct 31 18:37:12 2020 +0800 @@ -1,7 +1,33 @@ Changelog ========= -10.0.2 - in progress +10.1.0 -- 2020-10-31 +-------------------- + + * compatibility with Mercurial 5.6 + + * numerous minor changes to packaging, Makefile, README moved to README.rst + + * evolve: various improvements to content-divergence resolution + * evolve: fix various issues with --continue when solving content-divergence + * evolve: specify the source of config override for `server.bundle1=no` + * evolve: avoid leaving mergestate after instability resolution + * evolve: while resolving conflicts, the evolved node will no longer be a + dirstate parent (won't show up in `hg parents` and not as `@` in `hg log -G`, + but it will show up as `%` with hg >= 5.4) + + * metaedit: update bookmark location when applicable + + * rewind: add a --dry-run flag + * rewind: properly record rewind of splits as folds + +topic (0.20.0) + + * stack: support foo#stack relation revset (hg-5.4+ only) + * merge: add a experimental.topic.linear-merge option to allow oedipus merges + in some cases + +10.0.2 -- 2020-09-08 -------------------- * py3: use '%d' for formatting revision numbers in stable range cache warning diff -r af0458d91d10 -r ee18173c54a2 MANIFEST.in --- a/MANIFEST.in Sun Sep 06 05:38:24 2020 +0800 +++ b/MANIFEST.in Sat Oct 31 18:37:12 2020 +0800 @@ -2,7 +2,7 @@ include COPYING include hgext3rd/topic/README include MANIFEST.in -include README +include README.rst include setup.py recursive-include tests *.py *.sh *.t @@ -22,7 +22,6 @@ exclude .hg-format-source exclude Makefile exclude tests/test-drop.t -exclude tests/test-inhibit.t exclude tests/test-oldconvert.t prune contrib diff -r af0458d91d10 -r ee18173c54a2 Makefile --- a/Makefile Sun Sep 06 05:38:24 2020 +0800 +++ b/Makefile Sat Oct 31 18:37:12 2020 +0800 @@ -1,9 +1,19 @@ -VERSION=$(shell python setup.py --version) +PYTHON ?= python +VERSION = $(shell python setup.py --version) +TESTFLAGS ?= $(shell echo $$HGTESTFLAGS) +HGTESTS = $(HGROOT)/tests -PYTHON=python +.PHONY: help +help: + @echo 'Commonly used make targets:' + @echo ' deb-prepare - prepare the build of a debian package' + @echo ' install-home - install with setup.py install --home=$$HOME ($(HOME))' + @echo ' tests - run all tests in the automatic test suite' +.PHONY: all all: help +.PHONY: deb-prepare deb-prepare: python setup.py sdist --dist-dir .. mv -f ../hg-evolve-$(VERSION).tar.gz ../mercurial-evolve_$(VERSION).orig.tar.gz @@ -13,42 +23,23 @@ cp -r debian/ ../mercurial-evolve_$(VERSION).orig/ @cd ../mercurial-evolve_$(VERSION).orig && echo 'debian build directory ready at' `pwd` +.PHONY: install-home install-home: $(PYTHON) setup.py install --home="$(HOME)" --prefix="" --force -# test targets -TESTFLAGS ?= $(shell echo $$HGTESTFLAGS) - -HGTESTS=$(HGROOT)/tests +.PHONY: doc +doc: + $(MAKE) -C docs -help: - @echo 'Commonly used make targets:' - @echo ' deb-prepare - prepare the build of a debian package' - @echo ' tests - run all tests in the automatic test suite' - @echo ' all-version-tests - run all tests against many hg versions' - @echo ' tests-%s - run all tests in the specified hg version' - -all: help - +.PHONY: _check_hgroot _check_hgroot: ifeq ($(HGROOT),) $(error HGROOT is not set to the root of the hg source tree) endif +.PHONY: tests tests: _check_hgroot cd tests && $(PYTHON) $(HGTESTS)/run-tests.py $(TESTFLAGS) -# /!\ run outside of the compatibility branch output test will likely fails - test-%: _check_hgroot cd tests && $(PYTHON) $(HGTESTS)/run-tests.py $(TESTFLAGS) $@ - -tests-%: _check_hgroot - hg -R $(HGROOT) checkout $$(echo $@ | sed s/tests-//) && \ - (cd $(HGROOT) ; $(MAKE) clean ) && \ - cd tests && $(PYTHON) $(HGTESTS)/run-tests.py $(TESTFLAGS) - -# build a script to extract declared version -all-version-tests: tests-@ - -.PHONY: tests all-version-tests diff -r af0458d91d10 -r ee18173c54a2 README --- a/README Sun Sep 06 05:38:24 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,247 +0,0 @@ -============================= -Mutable History For Mercurial -============================= - -Evolve Extension -================= - -This package supplies the ``evolve`` extension for Mercurial, - -**The full implementation of the changeset evolution concept is still in -progress.** Please subscribe to the `evolve-testers mailing list -`_ to stay up to -date with changes. - -This extension: - -* enables the "changeset evolution" feature of Mercurial core, - -* provides a set of commands to mutate your history, - -* issues several warning messages when troubles from some mutable appears in - your repository, - -* provides an ``hg evolve`` command to deal with such "troubles", - -* improves performance of obsolescence marker exchanges and discovery during - push and pull. - -Documentation -------------- - -We recommend reading the documentation first. An online version is -available here: - - https://www.mercurial-scm.org/doc/evolution/ - -How to Install -============== - -Using Pip ---------- - -You can install the latest evolution version usin pip:: - - $ pip install --user hg-evolve - -Then just enable it in you hgrc:: - - $ hg config --edit # adds the two line below: - [extensions] - evolve = - -From Source ------------ - -To install a local version from source:: - - $ hg clone https://www.mercurial-scm.org/repo/evolve/ - $ cd evolve - $ pip install --user . - -Then just enable it in you hgrc:: - - $ hg config --edit # adds the two line below: - [extensions] - evolve = - -Documentation lives in ``doc/``. - -Server Only Setup -================= - -It is possible to enable a smaller subset of the extensions aimed at server -serving repository. It skips the additions of the new commands and local UI -messages that might add performance overheads. To use the server only -extension, install the package and use:: - - $ hg config --edit # adds the two line below: - [extensions] - evolve.serveronly = - -Extension Purpose -================= - -The goal of this extension is to provide an appropriate place for code and -concept related to changeset evolution to mature. In this extension we allow -for hackier code, unlocking quick experimentation and faster iterations. - -In addition, the evolve extensions support a wider set of Mercurial version, -allowing us to reach a larger user base for feedback. The Evolve extension is -not tight to the Mercurial release cycle and can release new feature and bug -fix at a higher rate if necessary. - -Once a concept is ready enough, its implementation is moved into Mercurial -core. The maturation period helped us to get a clearer picture of what was -needed. During the upstreaming process, we can use this clearer picture to -clean up the code and upgrade it to an appropriate quality for Mercurial core. - -Python 3 support -================ - -Mercurial announced beta support for Python 3 starting with its 5.0 release. -Since 9.1.0, ``evolve`` has beta support for Python 3.6+. - -Support will stay in beta while Mercurial's support for Python 3 remains in -beta and until it is a bit more battle-tested. - -How to Contribute -================= - -Discussion happens on the #hg-evolve IRC on freenode_. - -.. _freenode: https://freenode.net/ - -Bugs are to be reported on the mercurial's bug tracker (component: `evolution`_): - -.. _evolution: https://bz.mercurial-scm.org/buglist.cgi?component=evolution&query_format=advanced&resolution=--- - -The recommended way is to create Merge Request on -https://foss.heptapod.net/mercurial/evolve. To do so, create an account and -request access. You'll then be able to create topic based merge request. - -Alternatively, you can use the patchbomb extension to send email to `mercurial -devel `_. -Please make sure to use the evolve-ext flag when doing so. You can use a -command like this:: - - $ hg email --to mercurial-devel@mercurial-scm.org --flag evolve-ext --rev '' - - -For guidelines on the patch description, see the `official Mercurial guideline`_. - -.. _`official Mercurial guideline`: https://mercurial-scm.org/wiki/ContributingChanges#Patch_descriptions - -Please don't forget to update and run the tests when you fix a bug or -add a feature. To run the tests, you need a working copy of Mercurial, -say in $HGSRC:: - - $ cd tests - $ python $HGSRC/tests/run-tests.py - -When certain blocks of code need to cope with API changes in core Mercurial, -they should have comments in the ``hg <= x.y (commit hash)`` format. For -example, if a function needs another code path because of changes introduced in -02802fa87b74 that was first included in Mercurial 5.3, then the comment should -be:: - - # hg <= 5.2 (02802fa87b74) - -See also tests/test-check-compat-strings.t. - -Branch policy -------------- - -The evolve tests are highly impacted by changes in core. To deal with this, we -use named branches. - -There are two main branches: "stable" and "default". Tests on these branches -are supposed to pass with the corresponding "default" and "stable" branch from -core Mercurial. The documentation is built from the tip of stable. - -In addition, we have compatibility branches to check tests on older versions of -Mercurial. They are the "mercurial-x.y" branches. They are used to apply -expected test changes only, no code changes should happen there. - -Test output changes from a changeset in core should add the following line to -their patch description: - -CORE-TEST-OUTPUT-UPDATE: - - -Format-source config -==================== - -Format source helps smooth out the pain of merging after auto-formatting. -Follow the instructions for install here: - -.. _`format-source`: https://bitbucket.org/octobus/format-source - -Then update both your global and repo config files:: - - $ hg config -l # add the lines below - [extensions] - formatsource = - - [format-source] - byteify-strings = python3 ~/workspace/octobus/mercurial-devel/contrib/byteify-strings.py --dictiter --treat-as-kwargs kwargs opts commitopts TROUBLES --allow-attr-methods - byteify-strings:mode.input = file - byteify-strings:mode.output = pipe - -Release Checklist -================= - -* make sure the tests are happy on all supported versions, - - You can use the `contrib/merge-test-compat.sh` to merge with the test - compatibility branches. - -* make sure there is no code difference between the compat branches and stable - (no diff within `hgext3rd/`), - -* update the `testedwith` variable for all extensions (remove '.dev'): - - - hgext3rd/evolve/metadata.py - - hgext3rd/topic/__init__.py - - hgext3rd/pullbundle.py - -* make sure the changelog is up to date, - -* add a date to the changelog entry for the target version, - -* update the `__version__` field of all relevant extensions: - - - hgext3rd/evolve/metadata.py - - hgext3rd/topic/__init__.py - - hgext3rd/pullbundle.py (if touched) - -* create a new Debian entry: - - - debchange --newversion x.y.z-1 "new upstream release" - - debchange --release - -* sanity check install and sdist targets of setup.py: - - - python setup.py install --home=$(mktemp -d) - - python setup.py sdist - -* tag the commit, - -* push and publish the tag, - -* upload the tarball to PyPI, - -* make an announcement on evolve-testers@mercurial-scm.org (possibly on - mercurial@mercurial-scm.org too), - -* bump versions of all extensions and add '.dev' (see existing commits as an - example): - - - hgext3rd/evolve/metadata.py - - hgext3rd/topic/__init__.py - - hgext3rd/pullbundle.py - - The version we use on the stable branch during development should be - `x.y.z+1.dev`. The version of the default branch should be `x.y+1.0.dev`. - -* merge stable into default. diff -r af0458d91d10 -r ee18173c54a2 README.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.rst Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,255 @@ +============================= +Mutable History For Mercurial +============================= + +Evolve Extension +================ + +This package supplies the evolve extension for Mercurial, + +**The full implementation of the changeset evolution concept is still in +progress.** Please subscribe to the `evolve-testers mailing list +`_ to stay up to +date with changes. + +This extension: + +* enables the "`changeset evolution`_" feature of core Mercurial, + +* provides a set of commands to rewrite history in a distributed way, + +* issues various warning messages when "troubles" from changeset evolution + appear in your repository, + +* provides an ``hg evolve`` command to deal with such troubles, + +* improves performance of obsolescence marker exchange and discovery during + push and pull. + +.. _`changeset evolution`: https://www.mercurial-scm.org/wiki/ChangesetEvolution + +Documentation +------------- + +We recommend reading the documentation first. An online version is available +here: + + https://www.mercurial-scm.org/doc/evolution/ + +Source of the documentation can be found in ``docs/``. + +How to Install +============== + +Using Pip +--------- + +You can install the latest released version using pip:: + + $ pip install --user hg-evolve + +Then enable it in your hgrc:: + + $ hg config --edit # add these two lines: + [extensions] + evolve = + +From Source +----------- + +To install a local version from source:: + + $ hg clone https://www.mercurial-scm.org/repo/evolve/ + $ cd evolve + # optionally `hg update ` + $ pip install --user . + +Then enable it in your hgrc:: + + $ hg config --edit # add these two lines: + [extensions] + evolve = + +It's also possible to use evolve without installing it, in which case you will +need to provide the full path to ``hgext3rd/evolve/``, for example:: + + [extensions] + evolve = ~/evolve/hgext3rd/evolve + +Server-only Setup +================= + +It is possible to enable a smaller subset of the features aimed at servers that +simply serve repositories:: + + $ hg config --edit # add these two lines: + [extensions] + evolve.serveronly = + +It skips the additions of the new commands and local UI messages that might add +performance overhead. + +Extension Purpose +================= + +The goal of this extension is to provide an appropriate place for code and +concepts related to `changeset evolution`_ to mature. In this extension we +allow hackier code, unlocking quick experimentation and faster iterations. + +In addition, evolve extension supports a wide range of Mercurial versions, +allowing us to reach a larger user base for feedback. The extension is not tied +to the Mercurial release cycle and can release new features and bug fixes at a +higher rate if necessary. + +Once a concept is deemed ready, its implementation is moved into core +Mercurial. The maturation period helped us to get a clearer picture of what was +needed. During the upstreaming process, we can use this clearer picture to +clean up the code and upgrade it to an appropriate quality for core Mercurial. + +Python 3 Support +================ + +Mercurial announced official `support for Python 3`_ starting with its 5.2 +release. Since 9.3.0, evolve has official support for Python 3.6+. + +.. _`support for Python 3`: https://www.mercurial-scm.org/wiki/Python3 + +How to Contribute +================= + +Discussion happens on the #hg-evolve IRC on freenode_. + +.. _freenode: https://freenode.net/ + +Bugs are to be reported on the Mercurial's bug tracker (component: +`evolution`_). + +.. _evolution: https://bz.mercurial-scm.org/buglist.cgi?component=evolution&query_format=advanced&resolution=--- + +The recommended way to submit a patch is to create a Merge Request on +https://foss.heptapod.net/mercurial/evolve. To do so, create an account and +request access. You'll then be able to create a topic-based merge request. + +Alternatively, you can use the patchbomb extension to send email to `mercurial +devel `_. +Please make sure to use the evolve-ext flag when doing so. You can use a +command like this:: + + $ hg email --to mercurial-devel@mercurial-scm.org --flag evolve-ext --rev '' + +For guidelines on the patch description, see the `official Mercurial guideline`_. + +.. _`official Mercurial guideline`: https://mercurial-scm.org/wiki/ContributingChanges#Patch_descriptions + +Please don't forget to update and run the tests when you fix a bug or add a +feature. To run the tests, you need a working copy of Mercurial, say in +$HGSRC:: + + $ cd tests + $ python $HGSRC/tests/run-tests.py + +When certain blocks of code need to cope with API changes in core Mercurial, +they should have comments in the ``hg <= x.y (commit hash)`` format. For +example, if a function needs another code path because of changes introduced in +02802fa87b74 that was first included in Mercurial 5.3, then the comment should +be:: + + # hg <= 5.2 (02802fa87b74) + +See also tests/test-check-compat-strings.t. + +Branch policy +------------- + +The evolve tests are highly impacted by changes in core Mercurial. To deal with +this, we use named branches. + +There are two main branches: "stable" and "default". Tests on these branches +are supposed to pass with the corresponding "default" and "stable" branch from +core Mercurial. The documentation is built from the tip of stable. + +In addition, we have compatibility branches to check tests on older versions of +Mercurial. They are the "mercurial-x.y" branches. They are used to apply +expected test changes only, no code changes should happen there. + +Test output changes from a changeset in core should add the following line to +their patch description:: + + CORE-TEST-OUTPUT-UPDATE: + +Format-source config +==================== + +Format-source helps smooth out the pain of merging after auto-formatting. +Follow the installation instructions at the `format-source`_ repo. + +.. _`format-source`: https://foss.heptapod.net/mercurial/format-source + +Then update your per-repo config file:: + + $ hg config --local --edit # add these lines: + [extensions] + formatsource = + + [format-source] + byteify-strings = python3 ~/hg/contrib/byteify-strings.py --dictiter --treat-as-kwargs kwargs opts commitopts TROUBLES --allow-attr-methods + byteify-strings:mode.input = file + byteify-strings:mode.output = pipe + +Release Checklist +================= + +* make sure the tests are happy on all supported versions, + + You can use the `contrib/merge-test-compat.sh` to merge with the test + compatibility branches. + +* make sure there is no code difference between the compat branches and stable + (no diff within `hgext3rd/`), + +* update the `testedwith` variable for all extensions (remove '.dev'): + + - hgext3rd/evolve/metadata.py + - hgext3rd/topic/__init__.py + - hgext3rd/pullbundle.py + +* make sure the changelog is up to date, + +* add a date to the changelog entry for the target version, + +* update the `__version__` field of all relevant extensions: + + - hgext3rd/evolve/metadata.py + - hgext3rd/topic/__init__.py + - hgext3rd/pullbundle.py (if touched) + +* create a new Debian entry: + + - debchange --newversion x.y.z-1 "new upstream release" + - debchange --release + +* sanity check install and sdist targets of setup.py: + + - python setup.py install --home=$(mktemp -d) + - python setup.py sdist + +* tag the commit, + +* push and publish the tag, + +* upload the tarball to PyPI, + +* make an announcement on evolve-testers@mercurial-scm.org (possibly on + mercurial@mercurial-scm.org too), + +* bump versions of all extensions and add '.dev' (see existing commits as an + example): + + - hgext3rd/evolve/metadata.py + - hgext3rd/topic/__init__.py + - hgext3rd/pullbundle.py + + The version we use on the stable branch during development should be + `x.y.z+1.dev`. The version of the default branch should be `x.y+1.0.dev`. + +* merge stable into default. diff -r af0458d91d10 -r ee18173c54a2 debian/changelog --- a/debian/changelog Sun Sep 06 05:38:24 2020 +0800 +++ b/debian/changelog Sat Oct 31 18:37:12 2020 +0800 @@ -1,3 +1,9 @@ +mercurial-evolve (10.0.2-1) unstable; urgency=medium + + * new upstream release + + -- Anton Shestakov Tue, 08 Sep 2020 11:18:54 +0800 + mercurial-evolve (10.0.1-1) unstable; urgency=medium * new upstream release @@ -164,9 +170,9 @@ -- Pierre-Yves David Mon, 23 Oct 2017 15:41:03 +0200 mercurial-evolve (6.7.1-1) unstable; urgency=medium - + * new upstream release - + -- Pierre-Yves David Tue, 10 Oct 2017 16:03:23 +0200 mercurial-evolve (6.7.0-1) unstable; urgency=medium diff -r af0458d91d10 -r ee18173c54a2 debian/control --- a/debian/control Sun Sep 06 05:38:24 2020 +0800 +++ b/debian/control Sat Oct 31 18:37:12 2020 +0800 @@ -5,21 +5,21 @@ Uploaders: Julien Cristau , Pierre-Yves David , -Standards-Version: 3.9.3 +Standards-Version: 4.3.0 Build-Depends: mercurial (>= 4.6), python, python3, debhelper (>= 10), dh-python, - python-sphinx (>= 1.0.8), + python-sphinx, imagemagick, librsvg2-bin, - wget, - sphinx-common, -X-Python-Version: >= 2.7 + graphviz, X-Python3-Version: >= 3.6 Homepage: https://www.mercurial-scm.org/doc/evolution/ +Vcs-Browser: https://www.mercurial-scm.org/repo/evolve/ +Vcs-Hg: https://www.mercurial-scm.org/repo/evolve/ Package: mercurial-evolve Architecture: all @@ -36,5 +36,3 @@ . This extension provides several commands to mutate history and deal with issues it may raise. - - diff -r af0458d91d10 -r ee18173c54a2 debian/docs --- a/debian/docs Sun Sep 06 05:38:24 2020 +0800 +++ b/debian/docs Sat Oct 31 18:37:12 2020 +0800 @@ -1,2 +1,2 @@ html -README +README.rst diff -r af0458d91d10 -r ee18173c54a2 debian/rules --- a/debian/rules Sun Sep 06 05:38:24 2020 +0800 +++ b/debian/rules Sat Oct 31 18:37:12 2020 +0800 @@ -30,12 +30,7 @@ find debian -path '*/hgext3rd/__init__.py' -delete dh_python3 -override_dh_auto_clean: clean-docs +override_dh_auto_clean: dh_auto_clean rm -f tests/*.err - -clean-docs: - rm -rf html - rm -f docs/static/logo-evolve.ico - rm -f docs/tutorials/tutorial.rst - rm -f docs/tutorials/topic-tutorial.rst + $(MAKE) -C docs clean diff -r af0458d91d10 -r ee18173c54a2 debian/source/options --- a/debian/source/options Sun Sep 06 05:38:24 2020 +0800 +++ b/debian/source/options Sat Oct 31 18:37:12 2020 +0800 @@ -1,1 +1,1 @@ -extend-diff-ignore = "^(contrib/|.gitlab-ci.yml|.hg-format-source|MANIFEST|Makefile|docs/tutorial/.netlify|hgext3rd/evolve/hack/|tests/.testtimes)" +extend-diff-ignore = "^(contrib/|\.gitlab/|\.gitlab-ci.yml|\.hg-format-source|MANIFEST|Makefile|docs/tutorial/\.netlify|hgext3rd/evolve/hack/|tests/\.testtimes|tests/test-drop\.t|tests/test-oldconvert\.t)" diff -r af0458d91d10 -r ee18173c54a2 debian/test-blacklist --- a/debian/test-blacklist Sun Sep 06 05:38:24 2020 +0800 +++ b/debian/test-blacklist Sat Oct 31 18:37:12 2020 +0800 @@ -1,4 +1,1 @@ test-drop.t -test-inhibit.t -test-simple4server.t -tests/test-simple4server-bundle2.t diff -r af0458d91d10 -r ee18173c54a2 docs/makefile --- a/docs/makefile Sun Sep 06 05:38:24 2020 +0800 +++ b/docs/makefile Sat Oct 31 18:37:12 2020 +0800 @@ -1,5 +1,6 @@ SPHINXBUILD ?= sphinx-build +.PHONY: all all: tutorials/tutorial.rst tutorials/topic-tutorial.rst static/logo-evolve.ico $(SPHINXBUILD) . ../html/ @@ -10,4 +11,11 @@ python test2rst.py tutorials/ static/logo-evolve.ico: static/logo-evolve.svg - convert -resize 36x36 static/logo-evolve.svg static/logo-evolve.ico + convert -resize 36x36 $< $@ + +.PHONY: clean +clean: + rm -rf ../html + rm -f static/logo-evolve.ico + rm -f tutorials/tutorial.rst + rm -f tutorials/topic-tutorial.rst diff -r af0458d91d10 -r ee18173c54a2 docs/troubles-handling.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/troubles-handling.rst Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,425 @@ +########################################################### +Possible troubles in rewriting history and their resolution +########################################################### + +.. Copyright 2020 Sushil Khanchi +.. Octobus SAS + + +Rewriting history, and especially rewriting draft history that have been +exchanged can lead to "unstable" situation. + +This document is intended for developer of the changeset evolution concept. It +cover through the technical aspects of each "instability" a changeset can get +into. It aims at building an exhaustive list of each cases and sub-cases and the +status of automatic resolution for these cases. + +Public changeset are part of the permanent history and are never considered +unstable. + +.. contents:: :depth: 4 + +****** +Orphan +****** + +Basics +====== + +A changeset is orphan when there is at least one obsolete ancestor. + +As a resolution, we need to find a new appropriate parents for the +changeset and rebase the orphan there. + +If the parents of an orphan changeset are orphan themself, they will have to be +"stabilised" fist. + +Cause of trouble +================ + +Orphan can appears because the user locally rewrite changeset with descendants. +In this case the orphan are created when the command run. They are few real use +case for such action and the user interface should focus on discouraging it. + +Orphan can also happens when the users created new changeset on draft that got +rewritten in another repository. The orphan are then "discovered" when the +obsolescence information of the ancestors is pulled in the local repository. +This is the most common way to create phase divergences. + +Source of Complexity +==================== + +There can be different situations we need to take care of when dealing with +resolution of an orphan changeset, like: + +* parents might not be obsolete (yet) and orphan themself. They will need to be + resolved first. +* obsolete parent has conflicting rewrites (content-divergence), so there might + not be an obvious "good spot" to rebase the changeset too. +* obsolete parent could have been prune, so it has not direct successors, +* obsolete parent was split in multiple changesets. This comes with multiple + variants: + + * successors could be linear of spread across multiple branches, + * successors could have been reordered after the initial split, + * Some of the successors could have been pruned. +* the orphan changeset can be a merge and orphan may come any numbers of parents +* rebasing might lead to conflict. + +Details of Sub cases +==================== + +.. contents:: + :local: + +O-A: Linear changeset (one parent) +---------------------------------- + +O-A1: parent has a single successors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +**Stabilisation Strategy** + +Solution is Clear. + +Relocate the orphan changeset onto the single successor of obsolete parent. + +**Current Support Level** + +Good: current implementation is expected to perform the planned stabilisation. + +O-A2: parent is pruned (no successors) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Find nearest "not-pruned" ancestor and treat it (or its successor, if apply) as +a resolution parent. (re-run Orphan resolution starting from these parent). +In some cases, there can be multiple "not-pruned" ancestor and it could be ambiguous +for us to decide which one to pick. + +O-A2.1: set of "not-pruned" ancestor has single head +"""""""""""""""""""""""""""""""""""""""""""""""""""" + + +**Stabilisation Strategy** + +This comes under `O-A3` and `O-A4` cases (since we re-run orphan resolution +assuming "not-pruned" ancestor as parent) + +**Current Support Level** + +Good: current implementation is expected to perform the planned stabilisation. + +O-A2.2: set of "not-pruned" ancestor has multiple heads +""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +If a merge is pruned, we have multiple "not-pruned" ancestor for its immediate +child to stabilise. + + +**Stabilisation Strategy** + +XXX: yet to decide resolution + +**Current Support Level** + +O-A3: parent has multiple successors sets (divergence case) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +**Stabilisation Strategy** + +XXX: yet to decide resolution + +**Current Support Level** + +O-A4: parent is split into multiple successors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +O-A4.1: successors of parent are all on the same topological branch +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + +**Stabilisation Strategy** + +Pick highest one as resolution parent. + +**Current Support Level** + +Good: current implementation is expected to perform the planned stabilisation. + +O-A4.2: parent is split into multiple topological branches (at least 2 heads) +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +In this case, the destination can be ambiguous. + +**Stabilisation Strategy** + +prompt user to choose one. + +(could we do better in some case?) + +**Current Support Level** + +Current implementation is expected to perform the planned stabilisation. + +O-M: Parent are Merge (multiple parent) +--------------------------------------- + +O-M1: Only one parent is obsolete +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +XXX Simple case are probably as good as any `O-A` case. However special case are +probably ignored right now (e.g: successors of the obsolete parent is linear with +the other parent). + +O-M2: both parent are obsolete +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +XXX currently we evolve one after the other. + +**************** +Phase-Divergence +**************** + +Basics +====== + + +It appears when a rewritten changeset got published. A phase-divergent changeset +has a public predecessor. + +Solving phase divergence is done by extracting the changes made between the +public predecessors and the latest evolution of the changesets into a new +changesets, descendants of the public predecessors. + +Cause of trouble +================ + +It can appear if a user locally change the phase of an obsolete changeset +(which has successors) to public. + +Phase-divergence can also happens when the users rewrite draft changeset that got +published in another repository. The phase divergence then "discovered" when the +publishing information of the predecessors is pulled in the local repository. + +Source of Complexity +==================== + +* public version is a merge +* phase-divergent changeset is a merge +* public version was split (linear, over multiple topo branches, etc…) +* phase-divergent version was folded with others +* rebasing might lead to conflict. + +Details of Sub cases +==================== + +.. contents:: + :local: + +#TODO: yet to document + +****************** +Content-Divergence +****************** + +Basics +====== + + +Independent rewrites of same changeset leads to content-divergence. So an +obsolete changeset have multiple "sets" of successors. And the content-divergent +changeset have some predecessors in common without the situation being the +result of a split. + +To stabilise the situation, we need to "merge" the changes introduced in each +side of the divergence and create a new changeset, that will supersede both of +the unstable one. The merged information can be both about file content and +metadata (author, parent, etc). + +In practice there are a lot of corner case where this is "not that simple". + +Cause of trouble +================ + +It can appear locally if a user independently rewrite the same changeset multiple +times. + +Content-divergence can also happens when the users rewrite draft changesets that got +rewritten in another repository as well. The content divergence then "revealed" +when the rewriting information is shared (pulled/pushed) with another repository. + +Source of Complexity +==================== + + +Before we perform a 3-way merge between the divergent changesets and common +predecessor (which acts as the 3-way merge base), there are some situations we need to take care of, like: + +* if divergent changesets moved, check which side moved in which direction, + and proceed accordingly +* they moved on different unrelated branches +* divergent changeset can be orphan as well +* one side of divergence is in public phase +* divergent changeset is part of a split or fold + +Details of resolution +===================== + +Resolution of content-divergence can be understand by dividing it in stages: + +Special case: If one of the divergent changeset is part of a split or fold, we don't handle +it right now. But when we are going to support it, it will probably have its own logic and +seperate from generic resolution. + +Generic resolution: + +The first stage of solving content-divergence is to find the changeset where the resolution +changeset will be based on (which we call the resolution parent or the target parent) and +relocate the divergent changesets on the resolution parent, if apply. + +In second stage, we deal with merging files of two divergent changesets using the 3-way merge. + +In third stage, we deal with merging the metadata changes and creating the resultant changeset. + +Details of Sub cases +==================== + +.. contents:: + :local: + +D-S: One of the divergent changeset is part of a split or fold +-------------------------------------------------------------- + +XXX: yet to decide resolution + +D-A: Finding the resolution parent +---------------------------------- + +This section is responsible to decide where the resultant changeset should live. If it's unable to +find the resolution parent, we abort the content-divergence resolution. Following are the possible +situations between the two divergent changesets and current support for each situation. + +D-A1: one of the divergent changeset is public +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Set the parent of public changeset as resolution parent. + +Note: After we resolve content-divergence in this case, the resultant changeset will be +phase-divergent with the public side; so then we resolve phase-divergence to completely +resolve the instability. + +D-A2: both are on the same parent +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Set the parent (or its successor, if apply) as resolution parent. + +D-A3: both are on different parents +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +D-A3.1: one side moved +"""""""""""""""""""""" + +Set the parent of moved changeset as resolution parent. + +D-A3.2: both moved forward; same branch +""""""""""""""""""""""""""""""""""""""" + +Set the parent of ahead one as resolution parent. +As most obvious is that, ahead one has the latest changes. + +D-A3.3: both moved backward; same branch +"""""""""""""""""""""""""""""""""""""""" + +XXX: yet to decide resolution + +D-A3.4: both moved opposite; same branch +"""""""""""""""""""""""""""""""""""""""" + +XXX: yet to decide resolution + +D-A3.5: both moved; one moved on different unrelated branch +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +XXX: yet to decide resolution + +D-A3.6: both moved on two different unrelated branch +"""""""""""""""""""""""""""""""""""""""""""""""""""" + +XXX: yet to decide resolution + + +D-B: Merging files of divergent changesets +------------------------------------------ + +While merging the files, there are few sub-cases that could arise +like file content conflict, rename information conflict, multiple newest +predecessor. Let's see them in detail. + +D-B1: File content conflict +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If there is a conflict in merging content of files we let the user to +resolve the conflict. + +D-B2: Rename information conflict +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +XXX: yet to explore + +D-B3: Multiple newest predecessor +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +XXX: yet to explore + + +D-C: Merging metadata changes and create resultant changeset +------------------------------------------------------------ + +While merging the metadata, there are few sub-cases that could arise +like branch name conflict, commit message conflict, commit author conflict. +If everything goes fine, we create the resultant changeset as a resolution of +content-divergence. + +D-C1: Branch name conflict +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**Stabilisation Strategy** + +Merge branch names using the 3-way merge. If unable to merge, +we prompt the user to select a branch. + +Possible improvement: If we are solving a long streak of divergence, each +side having the same branch, we can probably infer the correct resolution +from previous resolution. + +**Current Support Level** + +Good: current implementation is expected to perform the planned stabilisation. + +D-C2: Commit description conflict +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**Stabilisation Strategy** + +Merge commit description using text merge tool from user. + +Possible improvement: They are currently no way to "interrupt" and resume that +conflict resolution. Having some way to do that would be nice. + +**Current Support Level** + +Good: current implementation is expected to perform the planned stabilisation. + +D-C3: Commit author conflict +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**Stabilisation Strategy** + +Merge authors using 3-way merge. If unable to merge we concatenate +the two, separated by comma. (for e.g. "John Doe, Malcolm X") + +**Current Support Level** + +Good: current implementation is expected to perform the planned stabilisation. diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/evolve/__init__.py --- a/hgext3rd/evolve/__init__.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/evolve/__init__.py Sat Oct 31 18:37:12 2020 +0800 @@ -367,7 +367,7 @@ if obsolete.isenabled(repo, b'exchange'): # if no config explicitly set, disable bundle1 if not isinstance(repo.ui.config(b'server', b'bundle1'), bytes): - repo.ui.setconfig(b'server', b'bundle1', False) + repo.ui.setconfig(b'server', b'bundle1', False, b'evolve') class trdescrepo(repo.__class__): diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/evolve/cmdrewrite.py --- a/hgext3rd/evolve/cmdrewrite.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/evolve/cmdrewrite.py Sat Oct 31 18:37:12 2020 +0800 @@ -169,11 +169,11 @@ metadata = {} if opts.get('note'): metadata[b'note'] = opts['note'] - replacements = {old.node(): [newnode]} - scmutil.cleanupnodes(repo, replacements, operation=b'amend', - metadata=metadata) + replacements = {(old.node(),): [newnode]} + compat.cleanupnodes(repo, replacements, operation=b'amend', + metadata=metadata) phases.retractboundary(repo, tr, old.phase(), [newnode]) - hg.updaterepo(repo, newnode, True) + compat.clean_update(repo[newnode]) def _editandapply(ui, repo, pats, old, p1, fp, diffopts): newnode = None @@ -508,12 +508,12 @@ if opts.get('note'): metadata[b'note'] = opts['note'] - replacements = {old.node(): [newid]} - scmutil.cleanupnodes(repo, replacements, operation=b"uncommit", - metadata=metadata) + replacements = {(old.node(),): [newid]} + compat.cleanupnodes(repo, replacements, operation=b"uncommit", + metadata=metadata) phases.retractboundary(repo, tr, oldphase, [newid]) if opts.get('revert'): - hg.updaterepo(repo, newid, True) + compat.clean_update(repo[newid]) else: with repo.dirstate.parentchange(), compat.parentchange(repo): movedirstate(repo, repo[newid], match) @@ -745,17 +745,9 @@ p2.node()], commitopts=commitopts) phases.retractboundary(repo, tr, targetphase, [newid]) - # Use this condition as a proxy since the commit we care about - # (b99903534e06) didn't change any signatures. - if util.safehasattr(scmutil, 'nullrev'): - replacements = {tuple(ctx.node() for ctx in allctx): [newid]} - scmutil.cleanupnodes(repo, replacements, operation=b"fold", - metadata=metadata) - else: - # hg <= 4.7 (b99903534e06) - replacements = {ctx.node(): [newid] for ctx in allctx} - scmutil.cleanupnodes(repo, replacements, operation=b"fold", - metadata=metadata) + replacements = {tuple(ctx.node() for ctx in allctx): [newid]} + compat.cleanupnodes(repo, replacements, operation=b"fold", + metadata=metadata) tr.close() finally: tr.release() @@ -883,14 +875,16 @@ phases.retractboundary(repo, tr, targetphase, [newid]) # Use this condition as a proxy since the commit we care about - # (6335c0de80fa) didn't change any signatures. - if not util.safehasattr(context, 'bin'): - obsolete.createmarkers(repo, [(tuple(allctx), (repo[newid],))], - metadata=metadata, operation=b"metaedit") + # (b99903534e06) didn't change any signatures. + if util.safehasattr(scmutil, 'nullrev'): + mapping = {tuple(ctx.node() for ctx in allctx): (newid,)} + scmutil.cleanupnodes(repo, mapping, operation=b"metaedit", + metadata=metadata) else: - # hg <= 4.7 (6335c0de80fa) - obsolete.createmarkers(repo, [(ctx, (repo[newid],)) for ctx in allctx], - metadata=metadata, operation=b"metaedit") + # hg <= 4.7 (b99903534e06) + mapping = {ctx.node(): (newid,) for ctx in allctx} + scmutil.cleanupnodes(repo, mapping, operation=b"metaedit", + metadata=metadata) else: ui.status(_(b"nothing changed\n")) tr.close() @@ -1029,9 +1023,9 @@ msg = b"please add --fold if you want to do a fold" raise error.Abort(msg) elif biject: - replacements = {p.node(): [s.node()] for p, s in zip(precs, sucs)} + replacements = {(p.node(),): [s.node()] for p, s in zip(precs, sucs)} else: - replacements = {p.node(): [s.node() for s in sucs] for p in precs} + replacements = {(p.node(),): [s.node() for s in sucs] for p in precs} wdp = repo[b'.'] @@ -1111,16 +1105,13 @@ # but then revset took a lazy arrow in the knee and became much # slower. The new forms makes as much sense and a much faster. for dest in ctx.ancestors(): - if not dest.obsolete() and dest.node() not in replacements: + if not dest.obsolete() and (dest.node(),) not in replacements: moves[ctx.node()] = dest.node() break if len(sucs) == 1 and len(precs) > 1 and fold: - # hg <= 4.7 (b99903534e06) - # Using a proxy condition to let people wrap cleanupnodes() - if util.safehasattr(scmutil, 'nullrev'): - replacements = {tuple(p.node() for p in precs): [s.node() for s in sucs]} - scmutil.cleanupnodes(repo, replacements, operation=b"prune", moves=moves, - metadata=metadata) + replacements = {tuple(p.node() for p in precs): [s.node() for s in sucs]} + compat.cleanupnodes(repo, replacements, operation=b"prune", moves=moves, + metadata=metadata) # informs that changeset have been pruned ui.status(_(b'%i changesets pruned\n') % len(precs)) @@ -1474,11 +1465,11 @@ if pickstate: pickstate.delete() if newnode is None: - replacements = {origctx.node(): []} + replacements = {(origctx.node(),): []} else: newctx = repo[newnode] - replacements = {origctx.node(): [newctx.node()]} - scmutil.cleanupnodes(repo, replacements, operation=b"pick") + replacements = {(origctx.node(),): [newctx.node()]} + compat.cleanupnodes(repo, replacements, operation=b"pick") if newnode is None: ui.warn(_(b"note: picking %d:%s created no changes to commit\n") % @@ -1495,7 +1486,7 @@ pctxnode = pickstate[b'oldpctx'] ui.status(_(b"aborting pick, updating to %s\n") % node.hex(pctxnode)[:12]) - hg.updaterepo(repo, pctxnode, True) + compat.clean_update(repo[pctxnode]) pickstate.delete() return 0 diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/evolve/compat.py --- a/hgext3rd/evolve/compat.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/evolve/compat.py Sat Oct 31 18:37:12 2020 +0800 @@ -12,6 +12,7 @@ from mercurial import ( context, copies, + hg, merge as mergemod, obsolete, pycompat, @@ -386,3 +387,42 @@ # hg <= 5.2 (85c4cd73996b) if util.safehasattr(repo, '_quick_access_changeid_invalidate'): repo._quick_access_changeid_invalidate() + +if util.safehasattr(mergemod, '_update'): + def _update(*args, **kwargs): + return mergemod._update(*args, **kwargs) +else: + # hg <= 5.5 (2c86b9587740) + def _update(*args, **kwargs): + return mergemod.update(*args, **kwargs) + +if (util.safehasattr(mergemod, '_update') + and util.safehasattr(mergemod, 'update')): + + def update(ctx): + mergemod.update(ctx) + + def clean_update(ctx): + mergemod.clean_update(ctx) +else: + # hg <= 5.5 (c1b603cdc95a) + def update(ctx): + hg.updaterepo(ctx.repo(), ctx.node(), overwrite=False) + + def clean_update(ctx): + hg.updaterepo(ctx.repo(), ctx.node(), overwrite=True) + +def cleanupnodes(repo, replacements, operation, moves=None, metadata=None): + # Use this condition as a proxy since the commit we care about + # (b99903534e06) didn't change any signatures. + if util.safehasattr(scmutil, 'nullrev'): + fixedreplacements = replacements + else: + # hg <= 4.7 (b99903534e06) + fixedreplacements = {} + for oldnodes, newnodes in replacements.items(): + for oldnode in oldnodes: + fixedreplacements[oldnode] = newnodes + + scmutil.cleanupnodes(repo, replacements=fixedreplacements, operation=operation, + moves=moves, metadata=metadata) diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/evolve/evolvecmd.py --- a/hgext3rd/evolve/evolvecmd.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/evolve/evolvecmd.py Sat Oct 31 18:37:12 2020 +0800 @@ -56,7 +56,7 @@ abortmessage = _(b"see `hg help evolve.interrupted`\n") def _solveone(ui, repo, ctx, evolvestate, dryrun, confirm, - progresscb, category, lastsolved=None, stacktmplt=False): + progresscb, category, stacktmplt=False): """Resolve the troubles affecting one revision returns a tuple (bool, newnode) where, @@ -68,16 +68,14 @@ tr = repo.currenttransaction() assert tr is not None displayer = None + template = shorttemplate if stacktmplt: - displayer = logcmdutil.changesetdisplayer(ui, repo, - {b'template': stacktemplate}) - else: - displayer = logcmdutil.changesetdisplayer(ui, repo, - {b'template': shorttemplate}) + template = stacktemplate + displayer = logcmdutil.changesetdisplayer(ui, repo, + {b'template': template}) if b'orphan' == category: - result = _solveunstable(ui, repo, ctx, evolvestate, displayer, - dryrun, confirm, progresscb, - lastsolved=lastsolved) + result = _solveorphan(ui, repo, ctx, evolvestate, displayer, + dryrun, confirm, progresscb) elif b'phasedivergent' == category: result = _solvephasedivergence(ui, repo, ctx, evolvestate, displayer, dryrun, confirm, @@ -89,8 +87,8 @@ assert False, b"unknown trouble category: %s" % (category) return result -def _solveunstable(ui, repo, orig, evolvestate, displayer, dryrun=False, - confirm=False, progresscb=None, lastsolved=None): +def _solveorphan(ui, repo, orig, evolvestate, displayer, dryrun=False, + confirm=False, progresscb=None): """ Tries to stabilize the changeset orig which is orphan. returns a tuple (bool, newnode) where, @@ -109,7 +107,7 @@ keepbranch = orig.p2().branch() != orig.branch() elif not p2obs and p1obs: pass - else: + elif p1obs and p2obs: # store that we are resolving an orphan merge with both parents # obsolete and proceed with first parent evolvestate[b'orphanmerge'] = True @@ -120,7 +118,7 @@ keepbranch = orig.p2().branch() != orig.branch() if not pctx.obsolete(): - ui.warn(_(b"cannot solve instability of %s, skipping\n") % orig) + ui.warn(_(b"skipping %s, consider including orphan ancestors\n") % orig) return (False, b".") obs = pctx try: @@ -148,6 +146,9 @@ if not ui.quiet or confirm: repo.ui.write(_(b'move:'), label=b'evolve.operation') displayer.show(orig) + # lastsolved: keep track of successor of last troubled cset we evolved + # to confirm that if atop msg should be suppressed to remove redundancy + lastsolved = evolvestate.get(b'lastsolved') if lastsolved is None or target != repo[lastsolved]: repo.ui.write(_(b'atop:')) displayer.show(target) @@ -257,8 +258,8 @@ # like reverting to the bumped node. wctx = context.overlayworkingctx(repo) wctx.setbase(prec) - merge.update(repo, bumped.node(), ancestor=prec, mergeancestor=True, - branchmerge=True, force=False, wc=wctx) + compat._update(repo, bumped.node(), ancestor=prec, mergeancestor=True, + branchmerge=False, force=False, wc=wctx) if not wctx.isempty(): text = b'%s update to %s:\n\n' % (TROUBLES['PHASEDIVERGENT'], prec) text += bumped.description() @@ -285,45 +286,9 @@ repo.dirstate.setparents(newid, nodemod.nullid) return (True, replacementnode) -def _prepcontentdivresolution(ui, repo, divergent, other, evolvestate): +def _pickresolutionparent(ui, repo, divergent, other, evolvestate): """ if relocation required, decide which divergent cset will be relocated to the other side""" - divergent = repo[divergent.rev()] - evolvestate[b'divergent'] = divergent.node() - evolvestate[b'orig-divergent'] = divergent.node() - # sometimes we will relocate a node in case of different parents and we can - # encounter conflicts after relocation is done while solving - # content-divergence and if the user calls `hg evolve --stop`, we need to - # strip that relocated commit. However if `--all` is passed, we need to - # reset this value for each content-divergence resolution which we are doing - # below. - evolvestate[b'relocated-other'] = None - evolvestate[b'relocating-other'] = False - evolvestate[b'relocated-div'] = None - evolvestate[b'relocating-div'] = False - evolvestate[b'relocation-req'] = False - # in case or relocation we get a new other node, we need to store the old - # other for purposes like `--abort` or `--stop` - evolvestate[b'old-other'] = None - evolvestate[b'old-divergent'] = None - - def swapnodes(div, other): - div, other = other, div - evolvestate[b'divergent'] = div.node() - evolvestate[b'other-divergent'] = other.node() - return div, other - # haspubdiv: to keep track if we are solving public content-divergence - haspubdiv = False - if not (divergent.mutable() and other.mutable()): - haspubdiv = True - # for simplicity, we keep public one to local side while merging - # (as divergent is kept at local side, pinning public -> divergent) - if divergent.mutable(): - publicdiv = other - divergent, other = swapnodes(divergent, other) - else: - publicdiv = divergent - evolvestate[b'public-divergent'] = publicdiv.node() # we don't handle merge content-divergent changesets yet if len(other.parents()) > 1: @@ -336,19 +301,39 @@ ui.write_err(hint) return (False, b".") + if not (divergent.mutable() and other.mutable()): + # Public divergence: we keep public one to local side while merging + # When public branch is behind to the mutable branch, for now we + # relocate mutable cset to public one's side in every case. + # + # This behaviour might be sub optimal when ancestors of mutable + # cset has changes its relocated descendant rely on. + # + # Otherwise, we are going to rebase the "behind" branch up to the new + # brancmap level. + publicdiv = divergent if other.mutable() else other + resolutionparent = publicdiv.p1().node() + evolvestate[b'public-divergent'] = publicdiv.node() + return (True, resolutionparent) + otherp1 = succsotherp1 = other.p1().rev() divp1 = succsdivp1 = divergent.p1().rev() - # finding single successors of otherp1 and divp1 + # finding single successors of divp1 and otherp1 + try: + succsdivp1 = utility._singlesuccessor(repo, divergent.p1()) + except utility.MultipleSuccessorsError: + msg = _(b"skipping %s: ambiguous orphan resolution parent for " + b"%s\n") % (divergent, divergent) + ui.write_err(msg) + return (False, b".") try: succsotherp1 = utility._singlesuccessor(repo, other.p1()) except utility.MultipleSuccessorsError: - pass - - try: - succsdivp1 = utility._singlesuccessor(repo, divergent.p1()) - except utility.MultipleSuccessorsError: - pass + msg = _(b"skipping %s: ambiguous orphan resolution parent for " + b"%s\n") % (divergent, other) + ui.write_err(msg) + return (False, b".") # the changeset on which resolution changeset will be based on resolutionparent = repo[succsdivp1].node() @@ -373,8 +358,6 @@ # make it exclusive set divonly = set(divonly) - {divergent.rev()} otheronly = set(otheronly) - {other.rev()} - # is relocation of one of the changeset required - relocatereq = False # testing how both the divergent changesets are arranged, there can be 4 # possible cases here: @@ -392,6 +375,9 @@ if otherp1 == divp1: # both are on the same parents pass + elif divergent == other.p1(): + # both are in parent-child relation + pass elif succsotherp1 in gca and succsdivp1 in gca: # both are not on the same parent but have same parents's succs. if otheronly and divonly: @@ -400,40 +386,23 @@ # to do in this case pass if otheronly: - relocatereq = True - if not haspubdiv: - # can't swap when public divergence, as public can't move - divergent, other = swapnodes(divergent, other) - resolutionparent = repo[succsotherp1].node() + resolutionparent = repo[succsotherp1].node() elif divonly: - relocatereq = True + pass else: - # no extra cset on either side; so not considering relocation + # no extra cset on either side pass elif succsotherp1 in gca and succsdivp1 not in gca: - relocatereq = True pass elif succsdivp1 in gca and succsotherp1 not in gca: - relocatereq = True - - # When public branch is behind to the mutable branch, for now we - # relocate mutable cset to public one's side in every case. - # - # This behaviour might be sub optimal when ancestors of mutable - # cset has changes its relocated descendant rely on. - # - # Otherwise, we are going to rebase the "behind" branch up to the new - # brancmap level. - if not haspubdiv: - divergent, other = swapnodes(divergent, other) - resolutionparent = divergent.p1().node() + resolutionparent = repo[succsotherp1].node() else: msg = _(b"skipping %s: have a different parent than %s " b"(not handled yet)\n") % (divergent, other) hint = _(b"| %(d)s, %(o)s are not based on the same changeset.\n" - b"| With the current state of its implementation, \n" + b"| With the current state of its implementation,\n" b"| evolve does not work in that case.\n" - b"| rebase one of them next to the other and run \n" + b"| rebase one of them next to the other and run\n" b"| this command again.\n" b"| - either: hg rebase --dest 'p1(%(d)s)' -r %(o)s\n" b"| - or: hg rebase --dest 'p1(%(o)s)' -r %(d)s\n" @@ -442,7 +411,7 @@ ui.write_err(hint) return (False, b".") - return (True, divergent, other, resolutionparent, relocatereq) + return (True, resolutionparent) def _relocatedivergent(repo, orig, dest, evolvestate): """relocates a divergent commit and saves the evolve state""" @@ -482,19 +451,39 @@ ui.write_err(msg) return (False, b".") other = others[0] + evolvestate[b'divergent'] = divergent.node() evolvestate[b'other-divergent'] = other.node() evolvestate[b'base'] = base.node() + evolvestate[b'orig-divergent'] = divergent.node() + + # sometimes we will relocate a node in case of different parents and we can + # encounter conflicts after relocation is done while solving + # content-divergence and if the user calls `hg evolve --stop`, we need to + # strip that relocated commit. However if `--all` is passed, we need to + # reset this value for each content-divergence resolution which we are doing + # below. + evolvestate[b'relocate-div'] = False + evolvestate[b'relocate-other'] = False + evolvestate[b'relocated-other'] = None + evolvestate[b'relocating-other'] = False + evolvestate[b'relocated-div'] = None + evolvestate[b'relocating-div'] = False + # in case or relocation we get a new other node, we need to store the old + # other for purposes like `--abort` or `--stop` + evolvestate[b'old-other'] = None + evolvestate[b'old-divergent'] = None # setup everything before merging two content-divergent csets - datatoproceed = _prepcontentdivresolution(ui, repo, divergent, other, - evolvestate) - if not datatoproceed[0]: + picked, resolutionparent = _pickresolutionparent(ui, repo, divergent, + other, evolvestate) + if not picked: return (False, b".") - divergent, other, resolutionparent, relocatereq = datatoproceed[1:] + evolvestate[b'resolutionparent'] = resolutionparent - if relocatereq: - evolvestate['relocation-req'] = True - evolvestate[b'resolutionparent'] = resolutionparent + if divergent.p1().node() != resolutionparent: + evolvestate[b'relocate-div'] = True + if other.p1().node() != resolutionparent: + evolvestate[b'relocate-other'] = True if not ui.quiet or confirm: ui.write(_(b'merge:'), label=b'evolve.operation') @@ -515,55 +504,45 @@ 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: - msg = _(b"ambiguous orphan resolution parent for %s") - raise error.Abort(msg % divergent.hex()[:12]) - # relocate divergent cset to its obsolete parent's successsor - if succsdivp1 != divergent.p1().rev(): + # relocate divergent cset to resolution parent + if evolvestate[b'relocate-div']: evolvestate[b'relocating-div'] = True ui.status(_(b'rebasing "divergent" content-divergent changeset %s on' - b' %s\n' % (divergent, repo[succsdivp1]))) - newdivergent = _relocatedivergent(repo, divergent, repo[succsdivp1], + b' %s\n' % (divergent, repo[resolutionparent]))) + newdivergent = _relocatedivergent(repo, divergent, repo[resolutionparent], evolvestate) evolvestate[b'old-divergent'] = divergent.node() + evolvestate[b'relocating-div'] = False + evolvestate[b'relocated-div'] = newdivergent + evolvestate[b'temprevs'].append(newdivergent) + evolvestate[b'divergent'] = newdivergent divergent = repo[newdivergent] - evolvestate[b'relocating-div'] = False - evolvestate[b'relocated-div'] = divergent.node() - evolvestate[b'temprevs'].append(divergent.node()) - evolvestate[b'divergent'] = divergent.node() - # Sometimes we already have the other cset where we want it - if relocatereq and other == divergent.p1(): - relocatereq = False - - # relocate the other divergent if required - if relocatereq: + # relocate the other divergent to resolution parent + if evolvestate[b'relocate-other']: # relocating will help us understand during the time of conflicts that # whether conflicts occur at reloacting or they occured at merging # content divergent changesets evolvestate[b'relocating-other'] = True ui.status(_(b'rebasing "other" content-divergent changeset %s on' - b' %s\n' % (other, divergent.p1()))) - newother = _relocatedivergent(repo, other, divergent.p1(), evolvestate) + b' %s\n' % (other, repo[resolutionparent]))) + newother = _relocatedivergent(repo, other, repo[resolutionparent], evolvestate) evolvestate[b'old-other'] = other.node() - other = repo[newother] evolvestate[b'relocating-other'] = False - evolvestate[b'relocated-other'] = other.node() - evolvestate[b'temprevs'].append(other.node()) - evolvestate[b'other-divergent'] = other.node() + evolvestate[b'relocated-other'] = newother + evolvestate[b'temprevs'].append(newother) + evolvestate[b'other-divergent'] = newother + other = repo[newother] - _mergecontentdivergents(repo, progresscb, divergent, other, base, + localside, otherside = divergent, other + if not otherside.mutable(): + localside, otherside = other, divergent + _mergecontentdivergents(repo, progresscb, localside, otherside, base, evolvestate) res, newnode = _completecontentdivergent(ui, repo, progresscb, divergent, other, base, evolvestate) - haspubdiv = not (divergent.mutable() and other.mutable()) - if not haspubdiv: + haspublicdiv = not (divergent.mutable() and other.mutable()) + if not haspublicdiv: return (res, newnode) else: publicdiv = repo[evolvestate[b'public-divergent']] @@ -579,7 +558,7 @@ if newnode == publicdiv.node(): # case 2) pubstr = bytes(publicdiv) - othstr = bytes(other) + othstr = bytes(otherside) msg = _(b'content divergence resolution between %s ' b'(public) and %s has same content as %s, ' b'discarding %s\n') @@ -591,26 +570,26 @@ bumped = repo[newnode] return _resolvephasedivergent(ui, repo, prec=prec, bumped=bumped) -def _mergecontentdivergents(repo, progresscb, divergent, other, base, +def _mergecontentdivergents(repo, progresscb, local, other, base, evolvestate): - if divergent not in repo[None].parents(): + assert local != other + if local not in repo[None].parents(): repo.ui.note(_(b"updating to \"local\" side of the conflict: %s\n") % - divergent.hex()[:12]) - hg.updaterepo(repo, divergent.node(), False) + local.hex()[:12]) + compat.update(local) # merging the two content-divergent changesets repo.ui.note(_(b"merging \"other\" %s changeset '%s'\n") % (TROUBLES['CONTENTDIVERGENT'], other.hex()[:12])) if progresscb: progresscb() with state.saver(evolvestate): - mergeancestor = repo.changelog.isancestor(divergent.node(), - other.node()) - stats = merge.update(repo, - other.node(), - branchmerge=True, - force=False, - ancestor=base.node(), - mergeancestor=mergeancestor) + mergeancestor = repo.changelog.isancestor(local.node(), other.node()) + stats = compat._update(repo, + other.node(), + branchmerge=True, + force=False, + ancestor=base.node(), + mergeancestor=mergeancestor) hg._showstats(repo, stats) # conflicts while merging content-divergent changesets @@ -633,13 +612,12 @@ resparent = evolvestate[b'resolutionparent'] # whether we are solving public divergence - haspubdiv = False + haspublicdiv = False if evolvestate.get(b'public-divergent'): - haspubdiv = True + haspublicdiv = True publicnode = evolvestate[b'public-divergent'] publicdiv = repo[publicnode] - othernode = evolvestate[b'other-divergent'] - otherdiv = repo[othernode] + otherdiv = other if other.mutable() else divergent with repo.dirstate.parentchange(), compat.parentchange(repo): cmdrewrite.movedirstate(repo, repo[publicnode]) @@ -651,6 +629,7 @@ # no changes, create markers to resolve divergence obsolete.createmarkers(repo, [(otherdiv, (publicdiv,))], operation=b'evolve') + compat.mergestate.clean(repo) return (True, publicnode) with repo.dirstate.parentchange(), compat.parentchange(repo): @@ -676,6 +655,9 @@ else: date = max(divergent.date(), other.date()) + localside, otherside = divergent, other + if not otherside.mutable(): + localside, otherside = other, divergent # We really want a new commit in order to avoid obsmarker cycles (otherwise # divergence resolutions done in separate repos may create markers in the # opposite directions). For that reason, we set ui.allowemptycommit and @@ -685,20 +667,20 @@ {(b'ui', b'allowemptycommit'): b'true'}, b'evolve' ): extra = { - b'divergence_source_local': divergent.hex(), - b'divergence_source_other': other.hex() + b'divergence_source_local': localside.hex(), + b'divergence_source_other': otherside.hex() } newnode = repo.commit(text=desc, user=user, date=date, extra=extra) new = repo[newnode] - hg.updaterepo(repo, new.rev(), False) - if haspubdiv and publicdiv == divergent: + compat.update(new) + if haspublicdiv and publicdiv == divergent: bypassphase(repo, (divergent, new), operation=b'evolve') else: obsolete.createmarkers(repo, [(divergent, (new,))], operation=b'evolve') # creating markers and moving phases post-resolution - if haspubdiv and publicdiv == other: + if haspublicdiv and publicdiv == other: bypassphase(repo, (other, new), operation=b'evolve') else: obsolete.createmarkers(repo, [(other, (new,))], operation=b'evolve') @@ -948,19 +930,34 @@ tr = repo.currenttransaction() assert tr is not None - r = _evolvemerge(repo, orig, dest, pctx, keepbranch) - if r.unresolvedcount: # some conflict - with repo.dirstate.parentchange(), compat.parentchange(repo): - repo.setparents(dest.node(), orig.node()) - repo.dirstate.write(tr) + if repo._activebookmark: + repo.ui.status(_(b"(leaving bookmark %s)\n") % repo._activebookmark) + bookmarksmod.deactivate(repo) + nodenew = _relocatecommit(repo, orig, dest, pctx, keepbranch, commitmsg) + _finalizerelocate(repo, orig, dest, nodenew, tr, category, evolvestate) + return nodenew + +def _relocatecommit(repo, orig, dest, pctx, keepbranch, commitmsg): + if repo[b'.'].rev() != dest.rev(): + compat._update(repo, dest, branchmerge=False, force=True) + if keepbranch: + repo.dirstate.setbranch(orig.branch()) + if util.safehasattr(repo, 'currenttopic'): + # uurrgs + # there no other topic setter yet + if not orig.topic() and repo.vfs.exists(b'topic'): + repo.vfs.unlink(b'topic') + else: + with repo.vfs.open(b'topic', b'w') as f: + f.write(orig.topic()) + + stats = merge.graft(repo, orig, pctx, [b'destination', b'evolving'], True) + + if stats.unresolvedcount: # some conflict hint = _(b"see 'hg help evolve.interrupted'") raise error.InterventionRequired(_(b"unresolved merge conflicts"), hint=hint) - nodenew = _relocatecommit(repo, orig, commitmsg) - _finalizerelocate(repo, orig, dest, nodenew, tr, category, evolvestate) - return nodenew -def _relocatecommit(repo, orig, commitmsg): if commitmsg is None: commitmsg = orig.description() extra = dict(orig.extra()) @@ -978,55 +975,27 @@ date=orig.date(), extra=extra) def _finalizerelocate(repo, orig, dest, nodenew, tr, category, evolvestate): - destbookmarks = repo.nodebookmarks(dest.node()) - nodesrc = orig.node() - oldbookmarks = repo.nodebookmarks(nodesrc) - bmchanges = [] - if nodenew is not None: obsolete.createmarkers(repo, [(orig, (repo[nodenew],))], operation=b'evolve') - for book in oldbookmarks: - bmchanges.append((book, nodenew)) - evolvestate[b'bookmarkchanges'].append((book, nodesrc)) + bmdest = nodenew else: if category == b'orphan': repo.ui.status(_(b"evolution of %d:%s created no changes " b"to commit\n") % (orig.rev(), orig)) obsolete.createmarkers(repo, [(orig, ())], operation=b'evolve') # Behave like rebase, move bookmarks to dest + bmdest = dest.node() + + nodesrc = orig.node() + oldbookmarks = repo.nodebookmarks(nodesrc) + if oldbookmarks: + bmchanges = [] for book in oldbookmarks: evolvestate[b'bookmarkchanges'].append((book, nodesrc)) - bmchanges.append((book, dest.node())) - for book in destbookmarks: # restore bookmark that rebase move - bmchanges.append((book, dest.node())) - if bmchanges: + bmchanges.append((book, bmdest)) repo._bookmarks.applychanges(repo, tr, bmchanges) -def _evolvemerge(repo, orig, dest, pctx, keepbranch): - """Used by the evolve function to merge dest on top of pctx. - return the same tuple as merge.graft""" - if repo[b'.'].rev() != dest.rev(): - merge.update(repo, - dest, - branchmerge=False, - force=True) - if repo._activebookmark: - repo.ui.status(_(b"(leaving bookmark %s)\n") % repo._activebookmark) - bookmarksmod.deactivate(repo) - if keepbranch: - repo.dirstate.setbranch(orig.branch()) - if util.safehasattr(repo, 'currenttopic'): - # uurrgs - # there no other topic setter yet - if not orig.topic() and repo.vfs.exists(b'topic'): - repo.vfs.unlink(b'topic') - else: - with repo.vfs.open(b'topic', b'w') as f: - f.write(orig.topic()) - - return merge.graft(repo, orig, pctx, [b'destination', b'evolving'], True) - instabilities_map = { b'contentdivergent': b"content-divergent", b'phasedivergent': b"phase-divergent" @@ -1423,7 +1392,7 @@ # obsolete (perhaps made obsolete by the current `hg evolve`) unfi = repo.unfiltered() succ = utility._singlesuccessor(repo, unfi[startnode]) - hg.updaterepo(repo, repo[succ].node(), False) + compat.update(repo[succ]) if repo[b'.'].node() != startnode: ui.status(_(b'working directory is now at %s\n') % repo[b'.']) @@ -1641,7 +1610,7 @@ # `hg next --evolve` in play if evolvestate[b'command'] != b'evolve': pctx = repo[b'.'] - hg.updaterepo(repo, pctx.node(), True) + compat.clean_update(pctx) ui.status(_(b'evolve aborted\n')) ui.status(_(b'working directory is now at %s\n') % pctx.hex()[:12]) @@ -1687,18 +1656,13 @@ b'bookmarkchanges': [], b'temprevs': [], b'obsmarkers': [], b'update': shouldupdate} evolvestate.addopts(stateopts) - # lastsolved: keep track of successor of last troubled cset we evolved - # to confirm that if atop msg should be suppressed to remove redundancy - lastsolved = None activetopic = getattr(repo, 'currenttopic', b'') tr = repo.transaction(b"evolve") with util.acceptintervention(tr): for rev in revs: - lastsolved = _solveonerev(ui, repo, rev, evolvestate, - activetopic, dryrunopt, - confirmopt, progresscb, - targetcat, lastsolved) + _solveonerev(ui, repo, rev, evolvestate, activetopic, dryrunopt, + confirmopt, progresscb, targetcat) seen += 1 if showprogress: @@ -1707,7 +1671,7 @@ _cleanup(ui, repo, startnode, shouldupdate) def _solveonerev(ui, repo, rev, evolvestate, activetopic, dryrunopt, confirmopt, - progresscb, targetcat, lastsolved): + progresscb, targetcat): """solves one trouble, including orphan merges Like _solveone(), this solves one trouble. Unlike _solveone(), it @@ -1724,10 +1688,10 @@ progresscb() ret = _solveone(ui, repo, curctx, evolvestate, dryrunopt, confirmopt, progresscb, targetcat, - lastsolved=lastsolved, stacktmplt=stacktmplt) + stacktmplt=stacktmplt) if ret[0]: evolvestate[b'replacements'][curctx.node()] = ret[1] - lastsolved = ret[1] + evolvestate[b'lastsolved'] = ret[1] else: evolvestate[b'skippedrevs'].append(curctx.node()) @@ -1739,12 +1703,11 @@ stacktmplt=stacktmplt) if ret[0]: evolvestate[b'replacements'][curctx.node()] = ret[1] - lastsolved = ret[1] + evolvestate[b'lastsolved'] = ret[1] else: evolvestate[b'skippedrevs'].append(curctx.node()) evolvestate[b'orphanmerge'] = False - return lastsolved def solveobswdp(ui, repo, opts): """this function updates to the successor of obsolete wdir parent""" @@ -1798,20 +1761,20 @@ if olddiv: with repo.wlock(), repo.lock(): repo = repo.unfiltered() - hg.updaterepo(repo, olddiv, True) + pctx = repo[olddiv] + compat.clean_update(pctx) repair.strip(ui, repo, strips, False) updated = True - pctx = repo[olddiv] elif oldother: with repo.wlock(), repo.lock(): repo = repo.unfiltered() - hg.updaterepo(repo, oldother, True) + pctx = repo[oldother] + compat.clean_update(pctx) repair.strip(ui, repo, strips, False) updated = True - pctx = repo[oldother] if not updated: pctx = repo[b'.'] - hg.updaterepo(repo, pctx.node(), True) + compat.clean_update(pctx) ui.status(_(b'stopped the interrupted evolve\n')) ui.status(_(b'working directory is now at %s\n') % pctx) @@ -1872,7 +1835,7 @@ for c in repo.set(b'roots(%ld)', evolvedrevs)] # updating the working directory - hg.updaterepo(repo, startnode, True) + compat.clean_update(repo[startnode]) # Strip from the first evolved revision if evolvedrevs: @@ -1900,7 +1863,7 @@ evolvestate.load() if evolvestate[b'command'] != b'evolve': pctx = repo[b'.'] - hg.updaterepo(repo, pctx.node(), True) + compat.clean_update(pctx) ui.status(_(b'evolve aborted\n')) ui.status(_(b'working directory is now at %s\n') % pctx.hex()[:12]) @@ -1940,10 +1903,6 @@ category = evolvestate[b'category'] confirm = evolvestate[b'confirm'] unfi = repo.unfiltered() - # lastsolved: keep track of successor of last troubled cset we - # evolved to confirm that if atop msg should be suppressed to remove - # redundancy - lastsolved = None activetopic = getattr(repo, 'currenttopic', b'') tr = repo.transaction(b"evolve") with util.acceptintervention(tr): @@ -1963,11 +1922,10 @@ and curctx.node() not in evolvestate[b'skippedrevs']): newnode = _solveone(ui, repo, curctx, evolvestate, False, confirm, progresscb, category, - lastsolved=lastsolved, stacktmplt=stacktmplt) if newnode[0]: evolvestate[b'replacements'][curctx.node()] = newnode[1] - lastsolved = newnode[1] + evolvestate[b'lastsolved'] = newnode[1] else: evolvestate[b'skippedrevs'].append(curctx.node()) seen += 1 @@ -1976,44 +1934,47 @@ """function to continue the interrupted content-divergence resolution.""" tr = repo.transaction(b'evolve') with util.acceptintervention(tr): - divergent = evolvestate[b'divergent'] - base = evolvestate[b'base'] repo = repo.unfiltered() + divergent = repo[evolvestate[b'divergent']] + other = repo[evolvestate[b'other-divergent']] + assert divergent != other + base = repo[evolvestate[b'base']] + resolutionparent = repo[evolvestate.get(b'resolutionparent')] if evolvestate[b'relocating-div']: newdiv = _completerelocation(ui, repo, evolvestate) current = repo[evolvestate[b'current']] obsolete.createmarkers(repo, [(current, (repo[newdiv],))], operation=b'evolve') - evolvestate[b'old-divergent'] = repo[divergent].node() + evolvestate[b'old-divergent'] = divergent.node() evolvestate[b'relocating-div'] = False evolvestate[b'relocated-div'] = newdiv evolvestate[b'temprevs'].append(newdiv) evolvestate[b'divergent'] = newdiv + divergent = repo[newdiv] - relocatereq = evolvestate[b'relocation-req'] - if relocatereq: + if evolvestate[b'relocate-other']: divergent = repo[evolvestate[b'divergent']] - other = repo[evolvestate[b'other-divergent']] evolvestate[b'relocating-other'] = True ui.status(_(b'rebasing "other" content-divergent changeset %s on' - b' %s\n' % (other, divergent.p1()))) - newother = _relocatedivergent(repo, other, divergent.p1(), + b' %s\n' % (other, resolutionparent))) + newother = _relocatedivergent(repo, other, resolutionparent, evolvestate) evolvestate[b'old-other'] = other.node() + evolvestate[b'relocating-other'] = False + evolvestate[b'relocated-other'] = newother + evolvestate[b'temprevs'].append(newother) + evolvestate[b'other-divergent'] = newother other = repo[newother] - evolvestate[b'relocating-other'] = False - evolvestate[b'relocated-other'] = other.node() - evolvestate[b'temprevs'].append(other.node()) - evolvestate[b'other-divergent'] = other.node() - # continue the resolution by merging the content-divergence - _mergecontentdivergents(repo, progresscb, - divergent, - repo[newother], - repo[base], - evolvestate) + # continue the resolution by merging the content-divergent csets + localside, otherside = divergent, other + if not otherside.mutable(): + localside, otherside = other, divergent + _mergecontentdivergents(repo, progresscb, localside, otherside, + base, evolvestate) if evolvestate[b'relocating-other']: newother = _completerelocation(ui, repo, evolvestate) + evolvestate[b'old-other'] = other.node() current = repo[evolvestate[b'current']] obsolete.createmarkers(repo, [(current, (repo[newother],))], operation=b'evolve') @@ -2021,20 +1982,17 @@ evolvestate[b'relocated-other'] = newother evolvestate[b'temprevs'].append(newother) evolvestate[b'other-divergent'] = newother - # continue the resolution by merging the content-divergence - _mergecontentdivergents(repo, progresscb, - repo[divergent], - repo[newother], - repo[base], - evolvestate) + other = repo[newother] + # continue the resolution by merging the content-divergent csets + localside, otherside = divergent, other + if not otherside.mutable(): + localside, otherside = other, divergent + _mergecontentdivergents(repo, progresscb, localside, otherside, + base, evolvestate) - divergent = evolvestate[b'divergent'] - other = evolvestate[b'other-divergent'] res, newnode = _completecontentdivergent(ui, repo, progresscb, - repo[divergent], - repo[other], - repo[base], - evolvestate) + divergent, other, + base, evolvestate) origdivergent = evolvestate[b'orig-divergent'] evolvestate[b'replacements'][origdivergent] = newnode ret = (res, newnode) @@ -2145,7 +2103,7 @@ repo.dirstate.setparents(ctxparents[0].node(), currentp1) - else: + elif p1obs and p2obs: # both the parents were obsoleted, if orphanmerge is set, we # are processing the second parent first (to keep parent order) if evolvestate.get(b'orphanmerge'): diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/evolve/metadata.py --- a/hgext3rd/evolve/metadata.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/evolve/metadata.py Sat Oct 31 18:37:12 2020 +0800 @@ -5,7 +5,7 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -__version__ = b'10.0.2.dev' -testedwith = b'4.6.2 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5' +__version__ = b'10.1.0' +testedwith = b'4.6.2 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6' minimumhgversion = b'4.6' buglink = b'https://bz.mercurial-scm.org/' diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/evolve/rewind.py --- a/hgext3rd/evolve/rewind.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/evolve/rewind.py Sat Oct 31 18:37:12 2020 +0800 @@ -6,10 +6,11 @@ from mercurial import ( cmdutil, error, - hg, + node as nodemod, obsolete, obsutil, scmutil, + util, ) from mercurial.utils import dateutil @@ -17,9 +18,9 @@ from mercurial.i18n import _ from . import ( + compat, exthelper, rewriteutil, - compat, ) eh = exthelper.exthelper() @@ -36,6 +37,8 @@ _(b"rewind these revisions to their predecessors"), _(b'REV')), (b'k', b'keep', None, _(b"do not modify working directory during rewind")), + (b'n', b'dry-run', False, + _(b'do not perform actions, just print what would be done')), ], _(b'[--as-divergence] [--exact] [--keep] [--to REV]... [--from REV]...'), helpbasic=True, @@ -88,25 +91,31 @@ # stay on the safe side: prevent local case in case we need to upgrade cmdutil.bailifchanged(repo) - rewinded = _select_rewinded(repo, opts) + targets = _select_rewind_targets(repo, opts) - if not opts['as_divergence']: - for rev in rewinded: - ctx = unfi[rev] - ssets = obsutil.successorssets(repo, ctx.node(), cache=sscache) - if 1 < len(ssets): - msg = _(b'rewind confused by divergence on %s') % ctx - hint = _(b'solve divergence first or use "--as-divergence"') - raise error.Abort(msg, hint=hint) - if ssets and ssets[0]: - for succ in ssets[0]: - successorsmap[succ].add(ctx.node()) + for rev in targets: + ctx = unfi[rev] + ssets = obsutil.successorssets(repo, ctx.node(), cache=sscache) + if not opts['as_divergence'] and len(ssets) > 1: + msg = _(b'rewind confused by divergence on %s') % ctx + hint = _(b'solve divergence first or use "--as-divergence"') + raise error.Abort(msg, hint=hint) + for sset in ssets: + for succ in sset: + successorsmap[succ].add(ctx.node()) + + if opts['as_divergence']: + successorsmap = {} + + if opts['dry_run']: + ui.status(dryrun(unfi, targets, successorsmap, opts)) + return # Check that we can rewind these changesets with repo.transaction(b'rewind'): oldctx = repo[b'.'] - for rev in sorted(rewinded): + for rev in sorted(targets): ctx = unfi[rev] rewindmap[ctx.node()] = _revive_revision(unfi, rev, rewindmap) @@ -120,10 +129,21 @@ relationships.append(rel) if wctxp.node() == source: update_target = newdest[-1] + # Use this condition as a proxy since the commit we care about + # (b99903534e06) didn't change any signatures. + if util.safehasattr(scmutil, 'nullrev'): + # hg <= 4.7 (b99903534e06) + destmap = util.sortdict() + for src, dest in relationships: + destmap.setdefault(dest, []).append(src) + relationships = [ + (tuple(src), dest) + for dest, src in destmap.items() + ] obsolete.createmarkers(unfi, relationships, operation=b'rewind') if update_target is not None: if opts.get('keep'): - hg.updaterepo(repo, oldctx, True) + compat.clean_update(oldctx) # This is largely the same as the implementation in # strip.stripcmd() and cmdrewrite.cmdprune(). @@ -160,36 +180,36 @@ else: cmdutil.revert(repo.ui, repo, oldctx, **revertopts) else: - hg.updaterepo(repo, update_target, False) + compat.update(repo[update_target]) - repo.ui.status(_(b'rewinded to %d changesets\n') % len(rewinded)) - if relationships: - repo.ui.status(_(b'(%d changesets obsoleted)\n') % len(relationships)) + ui.status(_(b'rewound to %d changesets\n') % len(targets)) + if successorsmap: + ui.status(_(b'(%d changesets obsoleted)\n') % len(successorsmap)) if update_target is not None and not opts.get('keep'): ui.status(_(b'working directory is now at %s\n') % repo[b'.']) -def _select_rewinded(repo, opts): - """select the revision we shoudl rewind to +def _select_rewind_targets(repo, opts): + """select the revisions we should rewind to """ unfi = repo.unfiltered() - rewinded = set() + targets = set() revsto = opts.get('to') revsfrom = opts.get('from') if not (revsto or revsfrom): revsfrom.append(b'.') if revsto: - rewinded.update(scmutil.revrange(repo, revsto)) + targets.update(scmutil.revrange(repo, revsto)) if revsfrom: succs = scmutil.revrange(repo, revsfrom) - rewinded.update(unfi.revs(b'predecessors(%ld)', succs)) + targets.update(unfi.revs(b'predecessors(%ld)', succs)) - if not rewinded: + if not targets: raise error.Abort(b'no revision to rewind to') if not opts['exact']: - rewinded = unfi.revs(b'obsolete() and ::%ld', rewinded) + targets = unfi.revs(b'obsolete() and ::%ld', targets) - return sorted(rewinded) + return sorted(targets) def _revive_revision(unfi, rev, rewindmap): """rewind a single revision rev. @@ -224,3 +244,51 @@ flag=identicalflag, operation=b'rewind') return new + +def formatstatus(sources, destinations, asdiv=False): + """format a status line for one group of changesets for rewind + + sources is a tuple of current successors, or None in case of rewinding to + an earlier version of a pruned commit or when --as-divergence is used. + + destinations is a tuple of predecessors to rewind to. + """ + if sources: + return b'rewinding %s to %d changesets: %s\n' % ( + b' '.join(nodemod.short(src) for src in sources), + len(destinations), + b' '.join(nodemod.short(dest) for dest in destinations) + ) + elif asdiv: + msg = b'recreating %d changesets: %s\n' + else: + msg = b'rewinding a pruned commit to %d changesets: %s\n' + return msg % ( + len(destinations), + b' '.join(nodemod.short(dest) for dest in destinations) + ) + +def dryrun(unfi, targets, successorsmap, opts): + """explain what would rewind do, given targets, successorsmap and opts + + Returns a bytestring with one line per predecessors<->successors relation. + """ + cl = unfi.changelog + todo = b'' + rsm = collections.defaultdict(set) # reverse successors map + for src, destinations in successorsmap.items(): + for dest in destinations: + rsm[dest].add(src) + if rsm and successorsmap: + if len(rsm) < len(successorsmap): + for dest in sorted(rsm, key=cl.rev): + sources = sorted(rsm[dest], key=cl.rev) + todo += formatstatus(sources, (dest,)) + else: + for src in sorted(successorsmap, key=cl.rev): + destinations = sorted(successorsmap[src], key=cl.rev) + todo += formatstatus((src,), destinations) + else: + destinations = [unfi[rev].node() for rev in sorted(targets)] + todo = formatstatus(None, destinations, opts['as_divergence']) + return todo diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/evolve/serveronly.py --- a/hgext3rd/evolve/serveronly.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/evolve/serveronly.py Sat Oct 31 18:37:12 2020 +0800 @@ -57,8 +57,8 @@ evolveopts = repo.ui.configlist(b'experimental', b'evolution') if not evolveopts: evolveopts = b'all' - repo.ui.setconfig(b'experimental', b'evolution', evolveopts) + repo.ui.setconfig(b'experimental', b'evolution', evolveopts, b'evolve') if obsolete.isenabled(repo, b'exchange'): # if no config explicitly set, disable bundle1 if not isinstance(repo.ui.config(b'server', b'bundle1'), bytes): - repo.ui.setconfig(b'server', b'bundle1', False) + repo.ui.setconfig(b'server', b'bundle1', False, b'evolve') diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/evolve/stablesort.py --- a/hgext3rd/evolve/stablesort.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/evolve/stablesort.py Sat Oct 31 18:37:12 2020 +0800 @@ -61,7 +61,7 @@ pl = stablemin(parents(m)) ph = stablemax(parents(m)) stablesort(::m) == stablesort(pl) - + [i for in in stablesort(ph) if in ph % pl] + + [i for i in stablesort(ph) if i in ph % pl] + m This is visible in the example above: @@ -113,7 +113,7 @@ stablesort(::F) = [A, B, C, E, F] stablesort(::G) - ::F = [A, B, C, D, E, G] - [A, B, C, E, F] = [D, G] -In this order, we reuse all of `stablesort(::H)`, but the subset of +In this order, we reuse all of `stablesort(::F)`, but the subset of `stablesort(::G)` we reuse is not contiguous, we had to skip over 'E' that is already contained inside ::F. diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/evolve/templatekw.py --- a/hgext3rd/evolve/templatekw.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/evolve/templatekw.py Sat Oct 31 18:37:12 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 af0458d91d10 -r ee18173c54a2 hgext3rd/evolve/utility.py --- a/hgext3rd/evolve/utility.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/evolve/utility.py Sat Oct 31 18:37:12 2020 +0800 @@ -209,8 +209,11 @@ return revs[intidx - 1] def mergeusers(ui, base, divergent, other): - """ merges the users from two divergent changesets using three-way merge - and return the user that will be used as the author of resolved cset""" + """Return the merged user from two divergent changesets. + + Perform merge using 3-way merge. If unable to merge, concatenate + the two users. + """ baseuser = base.user() divuser = divergent.user() othuser = other.user() diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/topic/__init__.py --- a/hgext3rd/topic/__init__.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/topic/__init__.py Sat Oct 31 18:37:12 2020 +0800 @@ -123,6 +123,36 @@ [experimental] topic.server-gate-topic-changesets = yes + +Explicitly merging in the target branch +======================================= + +By default, Mercurial will not let your merge a topic into its target branch if +that topic is already based on the head of that branch. In other word, +Mercurial will not let your create a merge that will eventually have two +parents in the same branches, one parent being the ancestors of the other +parent. This behavior can be lifted using the following config:: + + [experimental] + topic.linear-merge = allow-from-bare-branch + +When this option is set to `allow-from-bare-branch`, it is possible to merge a +topic branch from a bare branch (commit an active topic (eg: public one)) +regardless of the topology. The result would typically looks like that:: + + @ summary: resulting merge commit + |\\ branch: my-branch + | | + | o summary: some more change in a topic, the merge "target" + | | branch: my-branch + | | topic: my-topic + | | + | o summary: some change in a topic + |/ branch: my-branch + | topic: my-topic + | + o summary: previous head of the branch, the merge "source" + | branch: my-branch """ from __future__ import absolute_import @@ -202,9 +232,9 @@ b'topic.active': b'green', } -__version__ = b'0.19.2.dev' +__version__ = b'0.20.0' -testedwith = b'4.6.2 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5' +testedwith = b'4.6.2 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6' minimumhgversion = b'4.6' buglink = b'https://bz.mercurial-scm.org/' @@ -239,6 +269,9 @@ configitem(b'experimental', b'topic.server-gate-topic-changesets', default=False, ) + configitem(b'experimental', b'topic.linear-merge', + default="reject", + ) def extsetup(ui): # register config that strictly belong to other code (thg, core, etc) @@ -353,7 +386,11 @@ _(b"topic to push"), _(b'TOPIC'))) extensions.wrapfunction(cmdutil, 'buildcommittext', committextwrap) - extensions.wrapfunction(merge, 'update', mergeupdatewrap) + if util.safehasattr(merge, '_update'): + extensions.wrapfunction(merge, '_update', mergeupdatewrap) + else: + # hg <= 5.5 (2c86b9587740) + extensions.wrapfunction(merge, 'update', mergeupdatewrap) # We need to check whether t0 or b0 or s0 is passed to override the default update # behaviour of changing topic and I can't find a better way # to do that as scmutil.revsingle returns the rev number and hence we can't @@ -1284,7 +1321,37 @@ isrebase = False ist0 = False try: - ret = orig(repo, node, branchmerge, force, *args, **kwargs) + mergemode = repo.ui.config(b'experimental', b'topic.linear-merge') + + cleanup = lambda: None + oldrepo = repo + if mergemode == b'allow-from-bare-branch' and not repo[None].topic(): + unfi = repo.unfiltered() + oldrepo = repo + old = unfi.__class__ + + class overridebranch(old): + def __getitem__(self, rev): + ret = super(overridebranch, self).__getitem__(rev) + if rev == node: + b = ret.branch() + t = ret.topic() + if t: + ret.branch = lambda: b'%s//%s' % (b, t) + return ret + unfi.__class__ = overridebranch + if repo.filtername is not None: + repo = unfi.filtered(repo.filtername) + + def cleanup(): + unfi.__class__ = old + + try: + ret = orig(repo, node, branchmerge, force, *args, **kwargs) + finally: + cleanup() + repo = oldrepo + if not hastopicext(repo): return ret # The mergeupdatewrap function makes the destination's topic as the diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/topic/discovery.py --- a/hgext3rd/topic/discovery.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/topic/discovery.py Sat Oct 31 18:37:12 2020 +0800 @@ -10,6 +10,7 @@ error, exchange, extensions, + scmutil, util, ) from . import ( @@ -186,7 +187,7 @@ continue oldheads = [repo[n].rev() for n in b[1]] newheads = _filter_obsolete_heads(repo, oldheads) - data[b[0]] = len(newheads) + data[b[0]] = newheads return data def handlecheckheads(orig, op, inpart): @@ -211,15 +212,27 @@ repo.invalidatecaches() finalheads = _nbheads(repo) for branch, oldnb in tr._prepushheads.items(): - newnb = finalheads.pop(branch, 0) - if oldnb < newnb: - msg = _(b'push create a new head on branch "%s"' % branch) + newheads = finalheads.pop(branch, []) + if len(oldnb) < len(newheads): + cl = repo.changelog + newheads = sorted(set(newheads).difference(oldnb)) + heads = scmutil.nodesummaries(repo, [cl.node(r) for r in newheads]) + msg = _( + b"push creates new heads on branch '%s': %s" + % (branch, heads) + ) raise error.Abort(msg) for branch, newnb in finalheads.items(): - if 1 < newnb: - msg = _(b'push create more than 1 head on new branch "%s"' - % branch) - raise error.Abort(msg) + if 1 < len(newnb): + cl = repo.changelog + heads = scmutil.nodesummaries(repo, [cl.node(r) for r in newnb]) + msg = _( + b"push creates new branch '%s' with multiple heads: %s" + % (branch, heads) + ) + hint = _(b"merge or see 'hg help push' for details about " + b"pushing new heads") + raise error.Abort(msg, hint=hint) def validator(tr): _validate(tr) diff -r af0458d91d10 -r ee18173c54a2 hgext3rd/topic/revset.py --- a/hgext3rd/topic/revset.py Sun Sep 06 05:38:24 2020 +0800 +++ b/hgext3rd/topic/revset.py Sat Oct 31 18:37:12 2020 +0800 @@ -76,7 +76,7 @@ @revsetpredicate(b'ngtip([branch])') def ngtipset(repo, subset, x): - """The untopiced tip. + """The tip of a branch, ignoring changesets with a topic. Name is horrible so that people change it. """ @@ -85,7 +85,9 @@ branch = revset.getstring(args[0], b'ngtip requires a string') if branch == b'.': branch = repo[b'.'].branch() - return subset & revset.baseset(destination.ngtip(repo, branch)) + # list of length 1 + revs = [repo[node].rev() for node in destination.ngtip(repo, branch)] + return subset & revset.baseset(revs) @revsetpredicate(b'stack()') def stackset(repo, subset, x): @@ -105,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 @@ -158,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 af0458d91d10 -r ee18173c54a2 setup.py --- a/setup.py Sun Sep 06 05:38:24 2020 +0800 +++ b/setup.py Sat Oct 31 18:37:12 2020 +0800 @@ -1,4 +1,3 @@ -import os from distutils.core import setup from os.path import dirname, join @@ -34,10 +33,6 @@ py_versions = '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4' -if os.environ.get('INCLUDE_INHIBIT'): - py_modules.append('hgext3rd.evolve.hack.inhibit') - py_modules.append('hgext3rd.evolve.hack.directaccess') - setup( name='hg-evolve', version=get_version(), @@ -47,7 +42,7 @@ maintainer_email='pierre-yves.david@ens-lyon.org', url='https://www.mercurial-scm.org/doc/evolution/', description='Flexible evolution of Mercurial history.', - long_description=open(join(dirname(__file__), 'README')).read(), + long_description=open(join(dirname(__file__), 'README.rst')).read(), keywords='hg mercurial', license='GPLv2+', py_modules=py_modules, diff -r af0458d91d10 -r ee18173c54a2 tests/hghaveaddon.py --- a/tests/hghaveaddon.py Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/hghaveaddon.py Sat Oct 31 18:37:12 2020 +0800 @@ -23,3 +23,8 @@ 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 af0458d91d10 -r ee18173c54a2 tests/test-amend-patch.t --- a/tests/test-amend-patch.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-amend-patch.t Sat Oct 31 18:37:12 2020 +0800 @@ -256,13 +256,9 @@ @@ -0,0 +1,1 @@ +Gello - $ hg status + $ hg status -A ? editor.sh - - $ ls -A - .hg - changedfile - editor.sh + C changedfile Handling both deletions and additions ------------------------------------- diff -r af0458d91d10 -r ee18173c54a2 tests/test-check-compat-strings.t --- a/tests/test-check-compat-strings.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-check-compat-strings.t Sat Oct 31 18:37:12 2020 +0800 @@ -5,4 +5,5 @@ > evolution = all > EOF - $ $TESTDIR/testlib/check-compat-strings.sh "$TESTDIR/../hgext3rd/" "$RUNTESTDIR/.." + $ "$PYTHON" "$TESTDIR/testlib/check-compat-strings.py" \ + > "$TESTDIR/../hgext3rd/" "$RUNTESTDIR/.." diff -r af0458d91d10 -r ee18173c54a2 tests/test-check-debian.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-check-debian.t Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,12 @@ +Enable obsolescence to avoid the warning issue when obsmarkers are found + + $ cat << EOF >> $HGRCPATH + > [experimental] + > evolution = all + > EOF + + $ "$PYTHON" "$TESTDIR/testlib/check-min-versions.py" \ + > "$TESTDIR/../hgext3rd/evolve/metadata.py" "$TESTDIR/../debian/control" + + $ "$PYTHON" "$TESTDIR/testlib/check-min-versions.py" \ + > "$TESTDIR/../hgext3rd/topic/__init__.py" "$TESTDIR/../debian/control" diff -r af0458d91d10 -r ee18173c54a2 tests/test-check-setup-manifest.t --- a/tests/test-check-setup-manifest.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-check-setup-manifest.t Sat Oct 31 18:37:12 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 af0458d91d10 -r ee18173c54a2 tests/test-evolve-abort-orphan.t --- a/tests/test-evolve-abort-orphan.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-abort-orphan.t Sat Oct 31 18:37:12 2020 +0800 @@ -111,12 +111,6 @@ date: Thu Jan 01 00:00:00 1970 +0000 summary: added c - changeset: 4:c41c793e0ef1 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - instability: orphan - summary: added d - #if abortcommand when in dry-run mode $ hg abort --dry-run @@ -209,7 +203,7 @@ | () draft | * 6:e83de241f751 added d | | () draft - | @ 5:e93a9161a274 added c + | % 5:e93a9161a274 added c | | () draft | x 2:b1661037fa25 added b | | () draft @@ -303,7 +297,7 @@ |/ () draft @ 7:807e8e2ca559 added a | () draft - | @ 6:8f20d4390c21 foo to a + | % 6:8f20d4390c21 foo to a | | () draft | | * 5:bcb1c47f8520 added d | | | () draft @@ -367,7 +361,7 @@ |/ () draft @ 7:807e8e2ca559 added a | () draft - | @ 6:8f20d4390c21 foo to a + | % 6:8f20d4390c21 foo to a | | () draft | | * 5:bcb1c47f8520 added d | | | () draft @@ -452,7 +446,7 @@ |/ () draft @ 7:807e8e2ca559 added a | () draft - | @ 6:8f20d4390c21 foo to a + | % 6:8f20d4390c21 foo to a | | () draft | x 1:2f913b0c9220 added a |/ () draft @@ -520,7 +514,7 @@ | (bm1) draft o 4:a0086c17bfc7 added a | () draft - | @ 3:17509928e5bf added c + | % 3:17509928e5bf added c | | () draft | x 2:9f0c80a55ddc added b | | () draft diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-abort-phasediv.t --- a/tests/test-evolve-abort-phasediv.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-abort-phasediv.t Sat Oct 31 18:37:12 2020 +0800 @@ -123,14 +123,6 @@ date: Thu Jan 01 00:00:00 1970 +0000 summary: added c - changeset: 6:ddba58020bc0 - tag: tip - parent: 1:c7586e2a9264 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - instability: phase-divergent - summary: added d - $ hg abort evolve aborted diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-content-divergent-case-A1.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-content-divergent-case-A1.t Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,106 @@ +=============================================== +Testing content-divergence resolution: Case A.1 +=============================================== + +Independent rewrites of same changeset can lead to content-divergence. In most +common cases, it can occur when multiple users rewrite the same changeset +independently and push it. + +This test belongs to a series of tests checking the resolution of content-divergent +changesets. + +Category A: no parents are obsolete +Testcase 1: no conflict: independent metadata changes only + +A.1 No content changes on any side +================================== + +.. (Divergence reason): +.. local: changed the description of changeset +.. other: changed the date of changeset +.. Where we show that since there is no content change in divergent changesets +.. we should only merge the metadata of changesets in a 3-way merge +.. +.. (local): +.. +.. A ø⇠○ A' +.. |/ +.. ● O +.. +.. (other): +.. +.. A ø⇠○ A'' +.. |/ +.. ● O +.. +.. (Resolution): +.. +.. ○ A''' +.. | +.. ● O +.. + +Setup +----- + $ . $TESTDIR/testlib/content-divergence-util.sh + $ setuprepos A.1 + creating test repo for test case A.1 + - upstream + - local + - other + cd into `local` and proceed with env setup + +initial + + $ cd local + $ mkcommit A0 + $ hg push -q + $ hg amend -m "A1" + $ hg log -G --hidden + @ 2:0d8c87cec5fc (draft): A1 + | + | x 1:28b51eb45704 (draft): A0 + |/ + o 0:a9bdc8b26820 (public): O + + $ cd ../other + $ hg pull -uq + $ hg amend -d '0 1' + $ hg push -q + + $ cd ../local + $ hg pull -q + 2 new content-divergent changesets + +Actual test of resolution +------------------------- + $ hg evolve -l + 0d8c87cec5fc: A1 + content-divergent: ece7459c388a (draft) (precursor 28b51eb45704) + + ece7459c388a: A0 + content-divergent: 0d8c87cec5fc (draft) (precursor 28b51eb45704) + + $ hg log -G --hidden + * 3:ece7459c388a (draft): A0 [content-divergent] + | + | @ 2:0d8c87cec5fc (draft): A1 [content-divergent] + |/ + | x 1:28b51eb45704 (draft): A0 + |/ + o 0:a9bdc8b26820 (public): O + + + $ hg evolve --content-divergent + merge:[2] A1 + with: [3] A0 + base: [1] A0 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at 36c6c1f70ad9 + + $ hg log -G + @ 4:36c6c1f70ad9 (draft): A1 + | + o 0:a9bdc8b26820 (public): O + + $ hg evolve -l diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-content-divergent-case-A2.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-content-divergent-case-A2.t Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,121 @@ +=============================================== +Testing content-divergence resolution: Case A.2 +=============================================== + +Independent rewrites of same changeset can lead to content-divergence. In most +common cases, it can occur when multiple users rewrite the same changeset +independently and push it. + +This test belongs to a series of tests checking the resolution of content-divergent +changesets. + +Category A: no parents are obsolete +Testcase 2: no conflict: both sides amended content changes (non-conflicting changes in same file) + +A.2 both sides amended content changes +====================================== + +.. (Divergence reason): +.. local: amended some content changes in same file as "other" but non-conflicting +.. other: amended some content changes in same file as "local" but non-conflicting +.. Where we show that since both side amended some content changes without any relocation, +.. the most reasonable behaviour is to simply perform 3-way merge. +.. +.. (local): +.. +.. A ø⇠○ A' +.. |/ +.. ● O +.. +.. (other): +.. +.. A ø⇠○ A'' +.. |/ +.. ● O +.. +.. (Resolution): +.. +.. ○ A''' +.. | +.. ● O +.. + +Setup +----- + $ . $TESTDIR/testlib/content-divergence-util.sh + $ setuprepos A.2 + creating test repo for test case A.2 + - upstream + - local + - other + cd into `local` and proceed with env setup + +initial + + $ cd local + $ mkcommit A0 + $ hg push -q + $ sed -i '1ifoo' A0 + $ hg amend -m "A1" + $ hg log -G --hidden + @ 2:e1f7c24563ba (draft): A1 + | + | x 1:28b51eb45704 (draft): A0 + |/ + o 0:a9bdc8b26820 (public): O + + $ cd ../other + $ hg pull -uq + $ echo bar >> A0 + $ hg amend + $ hg push -q + + $ cd ../local + $ hg pull -q + 2 new content-divergent changesets + +Actual test of resolution +------------------------- + $ hg evolve -l + e1f7c24563ba: A1 + content-divergent: 5fbe90f37421 (draft) (precursor 28b51eb45704) + + 5fbe90f37421: A0 + content-divergent: e1f7c24563ba (draft) (precursor 28b51eb45704) + + $ hg log -G --hidden + * 3:5fbe90f37421 (draft): A0 [content-divergent] + | + | @ 2:e1f7c24563ba (draft): A1 [content-divergent] + |/ + | x 1:28b51eb45704 (draft): A0 + |/ + o 0:a9bdc8b26820 (public): O + + + $ hg evolve --content-divergent + merge:[2] A1 + with: [3] A0 + base: [1] A0 + merging A0 + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + working directory is now at 414367a5568a + + $ hg log -Gp + @ 4:414367a5568a (draft): A1 + | diff -r a9bdc8b26820 -r 414367a5568a A0 + | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 + | +++ b/A0 Thu Jan 01 00:00:00 1970 +0000 + | @@ -0,0 +1,3 @@ + | +foo + | +A0 + | +bar + | + o 0:a9bdc8b26820 (public): O + diff -r 000000000000 -r a9bdc8b26820 O + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 + +++ b/O Thu Jan 01 00:00:00 1970 +0000 + @@ -0,0 +1,1 @@ + +O + + $ hg evolve -l diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-content-divergent-case-A3.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-content-divergent-case-A3.t Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,201 @@ +=============================================== +Testing content-divergence resolution: Case A.3 +=============================================== + +Independent rewrites of same changeset can lead to content-divergence. In most +common cases, it can occur when multiple users rewrite the same changeset +independently and push it. + +This test belongs to a series of tests checking the resolution of content-divergent +changesets. + +Category A: no parents are obsolete +Testcase 3: one side relocated forward and other amended content changes +Variants: +# a: "local" is rebased forward +# b: "other" is rebased forward + +A.3 Relocated forward; other side amended content changes +========================================================= + +.. (Divergence reason): +.. local: relocated the changeset forward in the graph +.. other: amended some content changes +.. Where we show that since one side amended some changes and other just relocated, +.. the most reasonable behaviour is to relocate the amended one to the same parent as +.. relocated one and perform 3-way merge. +.. +.. (local): +.. +.. C ø⇠○ C' +.. | | +.. | ○ B +.. \ | +.. ○ A +.. | +.. ● O +.. +.. (other): +.. +.. C ø⇠○ C'' +.. | | +.. B ○ | | +.. \ | / +.. A ○ +.. | +.. ● O +.. +.. (Resolution): +.. +.. ○ C''' +.. | +.. ○ B +.. | +.. ○ A +.. | +.. ● O +.. + +Setup +----- + $ . $TESTDIR/testlib/content-divergence-util.sh + $ setuprepos A.3 + creating test repo for test case A.3 + - upstream + - local + - other + cd into `local` and proceed with env setup + +initial + + $ cd upstream + $ mkcommit A + $ mkcommit B + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [1] A + $ mkcommit C + created new head + $ cd ../local + $ hg pull -qu + $ hg rebase -r 'desc(C)' -d 'desc(B)' + rebasing 3:928c8849ec01 "C" (tip) + + $ cd ../other + $ hg pull -qu + $ echo newC > C + $ hg amend + $ hg push -q + + $ cd ../local + $ hg push -fq + 2 new content-divergent changesets + $ hg pull -q + 2 new content-divergent changesets + +Actual test of resolution +------------------------- + +Variant_a: when "local" is rebased forward +------------------------------------------ + $ hg evolve -l + 384129981c4b: C + content-divergent: 710d96992b40 (draft) (precursor 928c8849ec01) + + 710d96992b40: C + content-divergent: 384129981c4b (draft) (precursor 928c8849ec01) + + $ hg log -G --hidden + * 5:710d96992b40 (draft): C [content-divergent] + | + | @ 4:384129981c4b (draft): C [content-divergent] + | | + +---x 3:928c8849ec01 (draft): C + | | + | o 2:f6fbb35d8ac9 (draft): B + |/ + o 1:f5bc6836db60 (draft): A + | + o 0:a9bdc8b26820 (public): O + + + $ hg evolve --content-divergent + merge:[4] C + with: [5] C + base: [3] C + rebasing "other" content-divergent changeset 710d96992b40 on f6fbb35d8ac9 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at 3ad062d48137 + + $ hg log -G + @ 7:3ad062d48137 (draft): C + | + o 2:f6fbb35d8ac9 (draft): B + | + o 1:f5bc6836db60 (draft): A + | + o 0:a9bdc8b26820 (public): O + + $ hg log -pl 1 + 7:3ad062d48137 (draft): C + diff -r f6fbb35d8ac9 -r 3ad062d48137 C + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 + +++ b/C Thu Jan 01 00:00:00 1970 +0000 + @@ -0,0 +1,1 @@ + +newC + + $ hg evolve -l + +Variant_b: when "other" is rebased forward +------------------------------------------ + + $ cd ../other + $ hg pull -q + 2 new content-divergent changesets + $ hg evolve -l + 710d96992b40: C + content-divergent: 384129981c4b (draft) (precursor 928c8849ec01) + + 384129981c4b: C + content-divergent: 710d96992b40 (draft) (precursor 928c8849ec01) + + $ hg log -G --hidden + * 5:384129981c4b (draft): C [content-divergent] + | + | @ 4:710d96992b40 (draft): C [content-divergent] + | | + | | x 3:928c8849ec01 (draft): C + | |/ + o | 2:f6fbb35d8ac9 (draft): B + |/ + o 1:f5bc6836db60 (draft): A + | + o 0:a9bdc8b26820 (public): O + + $ hg evolve --content-divergent + merge:[4] C + with: [5] C + base: [3] C + rebasing "divergent" content-divergent changeset 710d96992b40 on f6fbb35d8ac9 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at 8f91b97f6f9a + + $ hg log -G + @ 7:8f91b97f6f9a (draft): C + | + o 2:f6fbb35d8ac9 (draft): B + | + o 1:f5bc6836db60 (draft): A + | + o 0:a9bdc8b26820 (public): O + + $ hg evolve -l + + $ hg log -pl1 + 7:8f91b97f6f9a (draft): C + diff -r f6fbb35d8ac9 -r 8f91b97f6f9a C + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 + +++ b/C Thu Jan 01 00:00:00 1970 +0000 + @@ -0,0 +1,1 @@ + +newC + diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-content-divergent-case-A4.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-content-divergent-case-A4.t Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,197 @@ +=============================================== +Testing content-divergence resolution: Case A.4 +=============================================== + +Independent rewrites of same changeset can lead to content-divergence. In most +common cases, it can occur when multiple users rewrite the same changeset +independently and push it. + +This test belongs to a series of tests checking the resolution of content-divergent +changesets. + +Category A: no parents are obsolete +Testcase 4: both sides relocated forward to different location but aligned +Variants: +# a: local is ahead of other +# b: other is ahead of local + +A.4 Both relocated forward +========================== + +.. (Divergence reason): +.. local: relocated the changeset forward in the graph but on the same topo branch +.. other: relocated the changeset forward in the graph but on the same topo branch +.. Where we show that since both changesets relocated forward in the graph, +.. we can assume the reason for ahead one being ahead is that it's rebased on the latest changes and +.. its parent should be the resolution parent. So, we will relocate the other changeset to resolution +.. parent and perform 3-way merge. +.. +.. (local): +.. +.. D ø⇠○ D' +.. | | +.. | ○ C +.. | | +.. | ○ B +.. \ | +.. ○ A +.. | +.. ● O +.. +.. (other): +.. +.. D ø⇠○ D'' +.. | | ○ C +.. | | / +.. | ○ B +.. \ | +.. ○ A +.. | +.. ● O +.. +.. (Resolution): +.. ○ D''' +.. | +.. ○ C +.. | +.. ○ B +.. | +.. ○ A +.. | +.. ● O +.. + +Setup +----- + $ . $TESTDIR/testlib/content-divergence-util.sh + $ setuprepos A.4 + creating test repo for test case A.4 + - upstream + - local + - other + cd into `local` and proceed with env setup + +initial + + $ cd upstream + $ mkcommit A + $ mkcommit B + $ mkcommit C + $ hg co -r 'desc(A)' + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ mkcommit D + created new head + $ cd ../local + $ hg pull -qu + $ hg rebase -r 'desc(D)' -d 'desc(C)' + rebasing 4:6a418860e87b "D" (tip) + + $ cd ../other + $ hg pull -qu + $ hg rebase -r 'desc(D)' -d 'desc(B)' + rebasing 4:6a418860e87b "D" (tip) + $ hg push -q + + $ cd ../local + $ hg push -q + 2 new content-divergent changesets + $ hg pull -q + 2 new content-divergent changesets + +Actual test of resolution +------------------------- + +Variant_a: when local is ahead of other +--------------------------------------- + + $ hg evolve -l + d203ddccc9cc: D + content-divergent: 5d3fd66cb347 (draft) (precursor 6a418860e87b) + + 5d3fd66cb347: D + content-divergent: d203ddccc9cc (draft) (precursor 6a418860e87b) + + $ hg log -G --hidden + * 6:5d3fd66cb347 (draft): D [content-divergent] + | + | @ 5:d203ddccc9cc (draft): D [content-divergent] + | | + | | x 4:6a418860e87b (draft): D + | | | + | o | 3:d90aa47aa5d3 (draft): C + |/ / + o / 2:f6fbb35d8ac9 (draft): B + |/ + o 1:f5bc6836db60 (draft): A + | + o 0:a9bdc8b26820 (public): O + + $ hg evolve --content-divergent + merge:[5] D + with: [6] D + base: [4] D + rebasing "other" content-divergent changeset 5d3fd66cb347 on d90aa47aa5d3 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at 898f6bbfb21e + + $ hg log -G + @ 8:898f6bbfb21e (draft): D + | + o 3:d90aa47aa5d3 (draft): C + | + o 2:f6fbb35d8ac9 (draft): B + | + o 1:f5bc6836db60 (draft): A + | + o 0:a9bdc8b26820 (public): O + + $ hg evolve -l + +Variant_b: when other is ahead of local +--------------------------------------- + + $ cd ../other + $ hg pull -q + 2 new content-divergent changesets + + $ hg evolve -l + 5d3fd66cb347: D + content-divergent: d203ddccc9cc (draft) (precursor 6a418860e87b) + + d203ddccc9cc: D + content-divergent: 5d3fd66cb347 (draft) (precursor 6a418860e87b) + + $ hg log -G --hidden + * 6:d203ddccc9cc (draft): D [content-divergent] + | + | @ 5:5d3fd66cb347 (draft): D [content-divergent] + | | + | | x 4:6a418860e87b (draft): D + | | | + o | | 3:d90aa47aa5d3 (draft): C + |/ / + o / 2:f6fbb35d8ac9 (draft): B + |/ + o 1:f5bc6836db60 (draft): A + | + o 0:a9bdc8b26820 (public): O + + $ hg evolve --content-divergent + merge:[5] D + with: [6] D + base: [4] D + rebasing "divergent" content-divergent changeset 5d3fd66cb347 on d90aa47aa5d3 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at b2ef9cafa8ac + + $ hg log -G + @ 8:b2ef9cafa8ac (draft): D + | + o 3:d90aa47aa5d3 (draft): C + | + o 2:f6fbb35d8ac9 (draft): B + | + o 1:f5bc6836db60 (draft): A + | + o 0:a9bdc8b26820 (public): O + diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-content-divergent-corner-cases.t diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-content-divergent-interrupted.t --- a/tests/test-evolve-content-divergent-interrupted.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-content-divergent-interrupted.t Sat Oct 31 18:37:12 2020 +0800 @@ -198,6 +198,7 @@ with: [7] added d base: [4] added d rebasing "divergent" content-divergent changeset e49523854bc8 on 4566502c0483 + rebasing "other" content-divergent changeset f0f1694f123e on 4566502c0483 merging d warning: conflicts while merging d! (edit, then use 'hg resolve --mark') 0 files updated, 0 files merged, 0 files removed, 1 files unresolved @@ -206,7 +207,7 @@ [1] $ hg evolve --abort - 1 new orphan changesets + 2 new orphan changesets 2 new content-divergent changesets evolve aborted working directory is now at 491e10505bae @@ -303,10 +304,10 @@ () draft $ hg evolve --content-divergent - merge:[7] added d - with: [6] added d + merge:[6] added d + with: [7] added d base: [4] added d - rebasing "other" content-divergent changeset 69bdd23a9b0d on ca1b80f7960a + rebasing "divergent" content-divergent changeset 69bdd23a9b0d on ca1b80f7960a merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved merge conflicts diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-content-divergent-relocation.t --- a/tests/test-evolve-content-divergent-relocation.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-content-divergent-relocation.t Sat Oct 31 18:37:12 2020 +0800 @@ -184,12 +184,12 @@ () [default] draft $ hg evolve --content-divergent - merge:[13] added x - with: [12] added foo to x + merge:[12] added foo to x + with: [13] added x base: [11] added x - rebasing "other" content-divergent changeset 5cf74a13db18 on be5a8b9faa8a - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory is now at 4e844ab5e814 + rebasing "divergent" content-divergent changeset 5cf74a13db18 on be5a8b9faa8a + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at 618f8bd245a8 $ hg exp # HG changeset patch @@ -197,11 +197,11 @@ # Date 0 0 # Thu Jan 01 00:00:00 1970 +0000 # Branch bar - # Node ID 4e844ab5e8142d26fb1f0990486379f2410b0358 + # Node ID 618f8bd245a8d1892954eb49a88a6ec5e500a5b5 # Parent be5a8b9faa8af54f115aa168a2c8564acb40c37d added foo to x - diff -r be5a8b9faa8a -r 4e844ab5e814 x + diff -r be5a8b9faa8a -r 618f8bd245a8 x --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/x Thu Jan 01 00:00:00 1970 +0000 @@ -0,0 +1,1 @@ @@ -210,7 +210,7 @@ The above `hg exp` and the following log call demonstrates that message, content and branch change is preserved in case of relocation $ hg glog - @ 15:4e844ab5e814 added foo to x + @ 15:618f8bd245a8 added foo to x | () [bar] draft o 10:be5a8b9faa8a added d | () [default] draft @@ -234,10 +234,10 @@ 801b5920c7ea8d4ebdbc9cfc1e79e665dea2f211 5cf74a13db180e33dc2df8cd2aa70b21252a2a64 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '73', 'operation': 'amend', 'user': 'test'} 801b5920c7ea8d4ebdbc9cfc1e79e665dea2f211 45e15d6e88f5bd23ba360dff0c7591eca2d99f43 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'} 5cf74a13db180e33dc2df8cd2aa70b21252a2a64 911c21adca136894a2b35f0a58fae7ee94fa5e61 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'evolve', 'user': 'test'} - 45e15d6e88f5bd23ba360dff0c7591eca2d99f43 4e844ab5e8142d26fb1f0990486379f2410b0358 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '73', 'operation': 'evolve', 'user': 'test'} - 911c21adca136894a2b35f0a58fae7ee94fa5e61 4e844ab5e8142d26fb1f0990486379f2410b0358 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'evolve', 'user': 'test'} + 911c21adca136894a2b35f0a58fae7ee94fa5e61 618f8bd245a8d1892954eb49a88a6ec5e500a5b5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'evolve', 'user': 'test'} + 45e15d6e88f5bd23ba360dff0c7591eca2d99f43 618f8bd245a8d1892954eb49a88a6ec5e500a5b5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '73', 'operation': 'evolve', 'user': 'test'} $ hg obslog --all - @ 4e844ab5e814 (15) added foo to x + @ 618f8bd245a8 (15) added foo to x |\ rewritten(description, branch, content) from 45e15d6e88f5 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) | | rewritten from 911c21adca13 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) | | @@ -283,11 +283,11 @@ $ hg amend $ hg glog - @ 19:0faa43228ee7 added y + @ 19:bfe170c9c964 added y | () [bar] draft | * 17:9c32d35206fb added y | | () [default] draft - o | 15:4e844ab5e814 added foo to x + o | 15:618f8bd245a8 added foo to x | | () [bar] draft o | 10:be5a8b9faa8a added d | | () [default] draft @@ -301,10 +301,10 @@ () [default] draft $ hg evolve --content-divergent - merge:[19] added y - with: [17] added y + merge:[17] added y + with: [19] added y base: [16] added y - rebasing "other" content-divergent changeset 9c32d35206fb on 4e844ab5e814 + rebasing "divergent" content-divergent changeset 9c32d35206fb on 618f8bd245a8 merging y warning: conflicts while merging y! (edit, then use 'hg resolve --mark') 0 files updated, 0 files merged, 0 files removed, 1 files unresolved @@ -317,12 +317,12 @@ (no more unresolved files) continue: hg evolve --continue $ hg evolve --continue - working directory is now at ba11a9f47a2e + working directory is now at 7411ed2cf7cf $ hg glog - @ 21:ba11a9f47a2e added y + @ 21:7411ed2cf7cf added y | () [bar] draft - o 15:4e844ab5e814 added foo to x + o 15:618f8bd245a8 added foo to x | () [bar] draft o 10:be5a8b9faa8a added d | () [default] draft @@ -346,29 +346,29 @@ 801b5920c7ea8d4ebdbc9cfc1e79e665dea2f211 5cf74a13db180e33dc2df8cd2aa70b21252a2a64 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '73', 'operation': 'amend', 'user': 'test'} 801b5920c7ea8d4ebdbc9cfc1e79e665dea2f211 45e15d6e88f5bd23ba360dff0c7591eca2d99f43 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'} 5cf74a13db180e33dc2df8cd2aa70b21252a2a64 911c21adca136894a2b35f0a58fae7ee94fa5e61 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'evolve', 'user': 'test'} - 45e15d6e88f5bd23ba360dff0c7591eca2d99f43 4e844ab5e8142d26fb1f0990486379f2410b0358 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '73', 'operation': 'evolve', 'user': 'test'} - 911c21adca136894a2b35f0a58fae7ee94fa5e61 4e844ab5e8142d26fb1f0990486379f2410b0358 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'evolve', 'user': 'test'} + 911c21adca136894a2b35f0a58fae7ee94fa5e61 618f8bd245a8d1892954eb49a88a6ec5e500a5b5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'evolve', 'user': 'test'} + 45e15d6e88f5bd23ba360dff0c7591eca2d99f43 618f8bd245a8d1892954eb49a88a6ec5e500a5b5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '73', 'operation': 'evolve', 'user': 'test'} ecf1d3992eb4d9700d441013fc4e89014692b461 9c32d35206fb5c3bf0ac814d410914d54a959a87 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} - ecf1d3992eb4d9700d441013fc4e89014692b461 1bb9315961377c18863281be7634ec8ff9b73ea9 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '68', 'operation': 'rebase', 'user': 'test'} - 1bb9315961377c18863281be7634ec8ff9b73ea9 0faa43228ee7fb9c993f076cef7e2ac14c85954b 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} - 9c32d35206fb5c3bf0ac814d410914d54a959a87 0fc12918c8daa12ca83ce1e2a38e252b063b6276 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'evolve', 'user': 'test'} - 0faa43228ee7fb9c993f076cef7e2ac14c85954b ba11a9f47a2e4a3380c4d5f80f64de41645a6681 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'evolve', 'user': 'test'} - 0fc12918c8daa12ca83ce1e2a38e252b063b6276 ba11a9f47a2e4a3380c4d5f80f64de41645a6681 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '72', 'operation': 'evolve', 'user': 'test'} + ecf1d3992eb4d9700d441013fc4e89014692b461 491e9c6e22a4f265fad54d2060b9c2fa45f4301d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '68', 'operation': 'rebase', 'user': 'test'} + 491e9c6e22a4f265fad54d2060b9c2fa45f4301d bfe170c9c96484157a071cd74e400426376c5e0e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} + 9c32d35206fb5c3bf0ac814d410914d54a959a87 7c47d5c3b6f5fb934723cdeb45c5819760988e1d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'evolve', 'user': 'test'} + 7c47d5c3b6f5fb934723cdeb45c5819760988e1d 7411ed2cf7cfbc23f17711a72570787569177d69 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '72', 'operation': 'evolve', 'user': 'test'} + bfe170c9c96484157a071cd74e400426376c5e0e 7411ed2cf7cfbc23f17711a72570787569177d69 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'evolve', 'user': 'test'} $ hg obslog -r . --all - @ ba11a9f47a2e (21) added y - |\ amended(content) from 0faa43228ee7 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) - | | rewritten(branch, content) from 0fc12918c8da using evolve by test (Thu Jan 01 00:00:00 1970 +0000) + @ 7411ed2cf7cf (21) added y + |\ rewritten(branch, content) from 7c47d5c3b6f5 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) + | | amended(content) from bfe170c9c964 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) | | - x | 0faa43228ee7 (19) added y - | | amended(content) from 1bb931596137 using amend by test (Thu Jan 01 00:00:00 1970 +0000) - | | - | x 0fc12918c8da (20) added y + x | 7c47d5c3b6f5 (20) added y | | rebased(parent) from 9c32d35206fb using evolve by test (Thu Jan 01 00:00:00 1970 +0000) | | - x | 1bb931596137 (18) added y + | x bfe170c9c964 (19) added y + | | amended(content) from 491e9c6e22a4 using amend by test (Thu Jan 01 00:00:00 1970 +0000) + | | + | x 491e9c6e22a4 (18) added y | | rewritten(branch, parent) from ecf1d3992eb4 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) | | - | x 9c32d35206fb (17) added y + x | 9c32d35206fb (17) added y |/ amended(content) from ecf1d3992eb4 using amend by test (Thu Jan 01 00:00:00 1970 +0000) | x ecf1d3992eb4 (16) added y @@ -380,11 +380,11 @@ # User test # Date 0 0 # Thu Jan 01 00:00:00 1970 +0000 - # Node ID 0fc12918c8daa12ca83ce1e2a38e252b063b6276 - # Parent 4e844ab5e8142d26fb1f0990486379f2410b0358 + # Node ID 7c47d5c3b6f5fb934723cdeb45c5819760988e1d + # Parent 618f8bd245a8d1892954eb49a88a6ec5e500a5b5 added y - diff -r 4e844ab5e814 -r 0fc12918c8da y + diff -r 618f8bd245a8 -r 7c47d5c3b6f5 y --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/y Thu Jan 01 00:00:00 1970 +0000 @@ -0,0 +1,1 @@ @@ -394,9 +394,9 @@ ---------------------------------------------------------------------- $ hg glog - @ 21:ba11a9f47a2e added y + @ 21:7411ed2cf7cf added y | () [bar] draft - o 15:4e844ab5e814 added foo to x + o 15:618f8bd245a8 added foo to x | () [bar] draft o 10:be5a8b9faa8a added d | () [default] draft @@ -436,13 +436,13 @@ $ hg amend $ hg glog - @ 25:ad2ec16eca1e added z + @ 25:40a21b3496bc added z | () [bar] draft | * 23:9bc2ace42175 added z | | () [default] draft - o | 21:ba11a9f47a2e added y + o | 21:7411ed2cf7cf added y | | () [bar] draft - o | 15:4e844ab5e814 added foo to x + o | 15:618f8bd245a8 added foo to x | | () [bar] draft o | 10:be5a8b9faa8a added d | | () [default] draft @@ -456,10 +456,10 @@ () [default] draft $ hg evolve --content-divergent --any - merge:[25] added z - with: [23] added z + merge:[23] added z + with: [25] added z base: [22] added z - rebasing "other" content-divergent changeset 9bc2ace42175 on ba11a9f47a2e + rebasing "divergent" content-divergent changeset 9bc2ace42175 on 7411ed2cf7cf merging y warning: conflicts while merging y! (edit, then use 'hg resolve --mark') unresolved merge conflicts @@ -467,16 +467,16 @@ [1] $ hg diff - diff -r ba11a9f47a2e y + diff -r 7411ed2cf7cf y --- a/y Thu Jan 01 00:00:00 1970 +0000 +++ b/y Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +1,5 @@ - +<<<<<<< destination: ba11a9f47a2e bar - test: added y + +<<<<<<< destination: 7411ed2cf7cf bar - test: added y watbar +======= +foo +>>>>>>> evolving: 9bc2ace42175 - test: added z - diff -r ba11a9f47a2e z + diff -r 7411ed2cf7cf z --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/z Thu Jan 01 00:00:00 1970 +0000 @@ -0,0 +1,1 @@ @@ -491,35 +491,41 @@ evolving 23:9bc2ace42175 "added z" merging y warning: conflicts while merging y! (edit, then use 'hg resolve --mark') - 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + 1 files updated, 0 files merged, 0 files removed, 1 files unresolved unresolved merge conflicts (see 'hg help evolve.interrupted') [1] $ hg diff - diff -r ad2ec16eca1e y + diff -r 635c0edd2e45 y --- a/y Thu Jan 01 00:00:00 1970 +0000 +++ b/y Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +1,5 @@ - +<<<<<<< local: ad2ec16eca1e bar - test: added z - watbar + +<<<<<<< local: 635c0edd2e45 - test: added z + foo +======= - +foo - +>>>>>>> other: a7326a078527 - test: added z + +watbar + +>>>>>>> other: 40a21b3496bc bar - test: added z + diff -r 635c0edd2e45 z + --- a/z Thu Jan 01 00:00:00 1970 +0000 + +++ b/z Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,1 @@ + -z + +bar $ echo foo > y $ hg resolve -m (no more unresolved files) continue: hg evolve --continue $ hg evolve --continue - working directory is now at 45e55c9ab3d0 + working directory is now at 664febd074c2 $ hg glog - @ 27:45e55c9ab3d0 added z + @ 27:664febd074c2 added z | () [bar] draft - o 21:ba11a9f47a2e added y + o 21:7411ed2cf7cf added y | () [bar] draft - o 15:4e844ab5e814 added foo to x + o 15:618f8bd245a8 added foo to x | () [bar] draft o 10:be5a8b9faa8a added d | () [default] draft @@ -538,17 +544,17 @@ # Date 0 0 # Thu Jan 01 00:00:00 1970 +0000 # Branch bar - # Node ID 45e55c9ab3d0b4746161fcbe5b6c062eb4647fdb - # Parent ba11a9f47a2e4a3380c4d5f80f64de41645a6681 + # Node ID 664febd074c2f9c5c4e03045dd688e93360f297c + # Parent 7411ed2cf7cfbc23f17711a72570787569177d69 added z - diff -r ba11a9f47a2e -r 45e55c9ab3d0 y + diff -r 7411ed2cf7cf -r 664febd074c2 y --- a/y Thu Jan 01 00:00:00 1970 +0000 +++ b/y Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +1,1 @@ -watbar +foo - diff -r ba11a9f47a2e -r 45e55c9ab3d0 z + diff -r 7411ed2cf7cf -r 664febd074c2 z --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/z Thu Jan 01 00:00:00 1970 +0000 @@ -0,0 +1,1 @@ @@ -565,36 +571,36 @@ 801b5920c7ea8d4ebdbc9cfc1e79e665dea2f211 5cf74a13db180e33dc2df8cd2aa70b21252a2a64 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '73', 'operation': 'amend', 'user': 'test'} 801b5920c7ea8d4ebdbc9cfc1e79e665dea2f211 45e15d6e88f5bd23ba360dff0c7591eca2d99f43 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'} 5cf74a13db180e33dc2df8cd2aa70b21252a2a64 911c21adca136894a2b35f0a58fae7ee94fa5e61 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'evolve', 'user': 'test'} - 45e15d6e88f5bd23ba360dff0c7591eca2d99f43 4e844ab5e8142d26fb1f0990486379f2410b0358 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '73', 'operation': 'evolve', 'user': 'test'} - 911c21adca136894a2b35f0a58fae7ee94fa5e61 4e844ab5e8142d26fb1f0990486379f2410b0358 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'evolve', 'user': 'test'} + 911c21adca136894a2b35f0a58fae7ee94fa5e61 618f8bd245a8d1892954eb49a88a6ec5e500a5b5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'evolve', 'user': 'test'} + 45e15d6e88f5bd23ba360dff0c7591eca2d99f43 618f8bd245a8d1892954eb49a88a6ec5e500a5b5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '73', 'operation': 'evolve', 'user': 'test'} ecf1d3992eb4d9700d441013fc4e89014692b461 9c32d35206fb5c3bf0ac814d410914d54a959a87 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} - ecf1d3992eb4d9700d441013fc4e89014692b461 1bb9315961377c18863281be7634ec8ff9b73ea9 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '68', 'operation': 'rebase', 'user': 'test'} - 1bb9315961377c18863281be7634ec8ff9b73ea9 0faa43228ee7fb9c993f076cef7e2ac14c85954b 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} - 9c32d35206fb5c3bf0ac814d410914d54a959a87 0fc12918c8daa12ca83ce1e2a38e252b063b6276 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'evolve', 'user': 'test'} - 0faa43228ee7fb9c993f076cef7e2ac14c85954b ba11a9f47a2e4a3380c4d5f80f64de41645a6681 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'evolve', 'user': 'test'} - 0fc12918c8daa12ca83ce1e2a38e252b063b6276 ba11a9f47a2e4a3380c4d5f80f64de41645a6681 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '72', 'operation': 'evolve', 'user': 'test'} + ecf1d3992eb4d9700d441013fc4e89014692b461 491e9c6e22a4f265fad54d2060b9c2fa45f4301d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '68', 'operation': 'rebase', 'user': 'test'} + 491e9c6e22a4f265fad54d2060b9c2fa45f4301d bfe170c9c96484157a071cd74e400426376c5e0e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} + 9c32d35206fb5c3bf0ac814d410914d54a959a87 7c47d5c3b6f5fb934723cdeb45c5819760988e1d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'evolve', 'user': 'test'} + 7c47d5c3b6f5fb934723cdeb45c5819760988e1d 7411ed2cf7cfbc23f17711a72570787569177d69 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '72', 'operation': 'evolve', 'user': 'test'} + bfe170c9c96484157a071cd74e400426376c5e0e 7411ed2cf7cfbc23f17711a72570787569177d69 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'evolve', 'user': 'test'} 2048a66e8834bda866dcc8c479f091897816833e 9bc2ace42175da7380251fca97730f62ff5b9185 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} - 2048a66e8834bda866dcc8c479f091897816833e ee19d6cc67048a1a7469268068a1413611720975 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '68', 'operation': 'rebase', 'user': 'test'} - ee19d6cc67048a1a7469268068a1413611720975 ad2ec16eca1eac4cf5045b496efa6205652e9a02 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} - 9bc2ace42175da7380251fca97730f62ff5b9185 a7326a0785271a7bef2e812a9a742fb4256b4a3c 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '12', 'operation': 'evolve', 'user': 'test'} - ad2ec16eca1eac4cf5045b496efa6205652e9a02 45e55c9ab3d0b4746161fcbe5b6c062eb4647fdb 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'evolve', 'user': 'test'} - a7326a0785271a7bef2e812a9a742fb4256b4a3c 45e55c9ab3d0b4746161fcbe5b6c062eb4647fdb 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '72', 'operation': 'evolve', 'user': 'test'} + 2048a66e8834bda866dcc8c479f091897816833e 8bf0130be95ef72377e39232335531426c2abcf9 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '68', 'operation': 'rebase', 'user': 'test'} + 8bf0130be95ef72377e39232335531426c2abcf9 40a21b3496bc55fd0c0ac92d81b2930cfa4d4bef 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} + 9bc2ace42175da7380251fca97730f62ff5b9185 635c0edd2e45de215b2061b30aae5168708238d3 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '12', 'operation': 'evolve', 'user': 'test'} + 635c0edd2e45de215b2061b30aae5168708238d3 664febd074c2f9c5c4e03045dd688e93360f297c 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '72', 'operation': 'evolve', 'user': 'test'} + 40a21b3496bc55fd0c0ac92d81b2930cfa4d4bef 664febd074c2f9c5c4e03045dd688e93360f297c 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'evolve', 'user': 'test'} $ hg obslog --all - @ 45e55c9ab3d0 (27) added z - |\ rewritten(branch, content) from a7326a078527 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) - | | amended(content) from ad2ec16eca1e using evolve by test (Thu Jan 01 00:00:00 1970 +0000) + @ 664febd074c2 (27) added z + |\ amended(content) from 40a21b3496bc using evolve by test (Thu Jan 01 00:00:00 1970 +0000) + | | rewritten(branch, content) from 635c0edd2e45 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) | | - x | a7326a078527 (26) added z + x | 40a21b3496bc (25) added z + | | amended(content) from 8bf0130be95e using amend by test (Thu Jan 01 00:00:00 1970 +0000) + | | + | x 635c0edd2e45 (26) added z | | rewritten(parent, content) from 9bc2ace42175 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) | | - | x ad2ec16eca1e (25) added z - | | amended(content) from ee19d6cc6704 using amend by test (Thu Jan 01 00:00:00 1970 +0000) + x | 8bf0130be95e (24) added z + | | rewritten(branch, parent) from 2048a66e8834 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) | | - x | 9bc2ace42175 (23) added z - | | amended(content) from 2048a66e8834 using amend by test (Thu Jan 01 00:00:00 1970 +0000) - | | - | x ee19d6cc6704 (24) added z - |/ rewritten(branch, parent) from 2048a66e8834 using rebase by test (Thu Jan 01 00:00:00 1970 +0000) + | x 9bc2ace42175 (23) added z + |/ amended(content) from 2048a66e8834 using amend by test (Thu Jan 01 00:00:00 1970 +0000) | x 2048a66e8834 (22) added z diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-content-divergent-stack.t --- a/tests/test-evolve-content-divergent-stack.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-content-divergent-stack.t Sat Oct 31 18:37:12 2020 +0800 @@ -149,30 +149,189 @@ with: [10] added b base: [2] added b rebasing "divergent" content-divergent changeset d5f148423c16 on df93a529fa42 + rebasing "other" content-divergent changeset 88516dccf68a on df93a529fa42 0 files updated, 0 files merged, 0 files removed, 0 files unresolved merge:[7] added c with: [11] added c base: [3] added c - rebasing "divergent" content-divergent changeset 3ce4be6d8e5e on 365f419742a3 + rebasing "divergent" content-divergent changeset 3ce4be6d8e5e on aca5a88a1692 + rebasing "other" content-divergent changeset 9e5fb1d5b955 on aca5a88a1692 0 files updated, 0 files merged, 0 files removed, 0 files unresolved merge:[8] added d with: [12] added d base: [4] added d - rebasing "divergent" content-divergent changeset c72d2885eb51 on a18171c7d9e7 + rebasing "divergent" content-divergent changeset c72d2885eb51 on 67e04919c9a4 + rebasing "other" content-divergent changeset 15c781f93cac on 67e04919c9a4 0 files updated, 0 files merged, 0 files removed, 0 files unresolved working directory is now at df93a529fa42 $ hg glog - o 19:59d49942cf47 added d + o 22:e72164a86fb4 added d | () [default] draft - o 17:a18171c7d9e7 added c + o 19:67e04919c9a4 added c | () [default] draft - o 15:365f419742a3 added b + o 16:aca5a88a1692 added b | () [default] draft @ 13:df93a529fa42 watbar to a | () [default] draft o 0:8fa14d15e168 added hgignore () [default] draft + +Testing --continue case when relocating "divergent" +--------------------------------------------------- +When no relocation is required for "other", but "divergent" +hit merge conflict in relocation. This test makes sure that +content of two divergent csets merged correctly after the +merge conflict. + + $ hg log -r "desc('added c')" -p + changeset: 19:67e04919c9a4 + parent: 16:aca5a88a1692 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: added c + + diff -r aca5a88a1692 -r 67e04919c9a4 c + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 + +++ b/c Thu Jan 01 00:00:00 1970 +0000 + @@ -0,0 +1,1 @@ + +foo + + $ hg strip -r 17: --hidden + saved backup bundle to $TESTTMP/stacktest/.hg/strip-backup/f1cd8f167491-3817ebd7-backup.hg + 4 new orphan changesets + 4 new content-divergent changesets + $ hg glog + o 16:aca5a88a1692 added b + | () [default] draft + @ 13:df93a529fa42 watbar to a + | () [default] draft + | * 12:15c781f93cac added d + | | () [default] draft + | * 11:9e5fb1d5b955 added c + | | () [default] draft + | x 10:88516dccf68a added b + | | () [default] draft + | x 9:82b74d5dc678 watbar to a + |/ () [default] draft + | * 8:c72d2885eb51 added d + | | () [default] draft + | * 7:3ce4be6d8e5e added c + | | () [default] draft + | x 6:d5f148423c16 added b + | | () [default] draft + | x 5:8e222f257bbf watbar to a + |/ () [default] draft + o 0:8fa14d15e168 added hgignore + () [default] draft + $ hg next + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + [16] added b + $ echo conflict > c + $ hg amend -A + adding c + +add some changes on "other" side, to check later that merging performed correctly + $ hg up -r 11 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo new_file > newfile + $ hg amend -Am "added c and newfile" + adding newfile + $ hg glog + @ 18:2ecfb60af48a added c and newfile + | () [default] draft + | o 17:5907cbc074a0 added b + | | () [default] draft + | o 13:df93a529fa42 watbar to a + | | () [default] draft + | | * 12:15c781f93cac added d + | | | () [default] draft + +---x 11:9e5fb1d5b955 added c + | | () [default] draft + x | 10:88516dccf68a added b + | | () [default] draft + x | 9:82b74d5dc678 watbar to a + |/ () [default] draft + | * 8:c72d2885eb51 added d + | | () [default] draft + | * 7:3ce4be6d8e5e added c + | | () [default] draft + | x 6:d5f148423c16 added b + | | () [default] draft + | x 5:8e222f257bbf watbar to a + |/ () [default] draft + o 0:8fa14d15e168 added hgignore + () [default] draft + + $ hg evolve --content-divergent -r 7 + merge:[7] added c + with: [18] added c and newfile + base: [3] added c + rebasing "divergent" content-divergent changeset 3ce4be6d8e5e on 5907cbc074a0 + merging c + warning: conflicts while merging c! (edit, then use 'hg resolve --mark') + unresolved merge conflicts + (see 'hg help evolve.interrupted') + [1] + $ echo c > c + $ hg res -m + (no more unresolved files) + continue: hg evolve --continue + + $ hg evolve --continue + evolving 7:3ce4be6d8e5e "added c" + rebasing "other" content-divergent changeset 2ecfb60af48a on 5907cbc074a0 + merging c + warning: conflicts while merging c! (edit, then use 'hg resolve --mark') + unresolved merge conflicts + (see 'hg help evolve.interrupted') + [1] + $ hg diff + diff -r 5907cbc074a0 c + --- a/c Thu Jan 01 00:00:00 1970 +0000 + +++ b/c Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,5 @@ + +<<<<<<< destination: 5907cbc074a0 - test: added b + conflict + +======= + +foo + +>>>>>>> evolving: 2ecfb60af48a - test: added c and newfile + diff -r 5907cbc074a0 newfile + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 + +++ b/newfile Thu Jan 01 00:00:00 1970 +0000 + @@ -0,0 +1,1 @@ + +new_file + + $ echo c > c + $ hg res -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve -c + evolving 18:2ecfb60af48a "added c and newfile" + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory is now at 7e8d59a0286a + + $ hg log -p -l1 + changeset: 21:7e8d59a0286a + tag: tip + parent: 17:5907cbc074a0 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: added c and newfile + + diff -r 5907cbc074a0 -r 7e8d59a0286a c + --- a/c Thu Jan 01 00:00:00 1970 +0000 + +++ b/c Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,1 @@ + -conflict + +c + diff -r 5907cbc074a0 -r 7e8d59a0286a newfile + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 + +++ b/newfile Thu Jan 01 00:00:00 1970 +0000 + @@ -0,0 +1,1 @@ + +new_file + + Resolving content-divergence of a stack with different parents --------------------------------------------------------- @@ -311,39 +470,39 @@ () [default] draft $ hg evolve --all --content-divergent - merge:[10] added a - with: [5] watbar to a + merge:[5] watbar to a + with: [10] added a base: [1] added a - rebasing "other" content-divergent changeset 8e222f257bbf on 2228e3b74514 - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - merge:[11] added b - with: [6] added b + rebasing "divergent" content-divergent changeset 8e222f257bbf on 2228e3b74514 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + merge:[6] added b + with: [11] added b base: [2] added b - rebasing "divergent" content-divergent changeset 6eb54b5af3fb on ebb749d2ace8 - rebasing "other" content-divergent changeset d5f148423c16 on ebb749d2ace8 + rebasing "divergent" content-divergent changeset d5f148423c16 on 7e67dfb7ee31 + rebasing "other" content-divergent changeset 6eb54b5af3fb on 7e67dfb7ee31 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - merge:[12] added c - with: [7] added c + merge:[7] added c + with: [12] added c base: [3] added c - rebasing "divergent" content-divergent changeset 8ed612937375 on 9437917ebe8d - rebasing "other" content-divergent changeset 3ce4be6d8e5e on 9437917ebe8d + rebasing "divergent" content-divergent changeset 3ce4be6d8e5e on 80cec1b1c90f + rebasing "other" content-divergent changeset 8ed612937375 on 80cec1b1c90f 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - merge:[13] added d - with: [8] added d + merge:[8] added d + with: [13] added d base: [4] added d - rebasing "divergent" content-divergent changeset d45f050514c2 on 8e574c12775a - rebasing "other" content-divergent changeset c72d2885eb51 on 8e574c12775a + rebasing "divergent" content-divergent changeset c72d2885eb51 on 7e370616fb2b + rebasing "other" content-divergent changeset d45f050514c2 on 7e370616fb2b 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory is now at ebb749d2ace8 + working directory is now at 7e67dfb7ee31 $ hg glog - o 24:5ab9b88fbead added d + o 24:469255caf534 added d | () [default] draft - o 21:8e574c12775a added c + o 21:7e370616fb2b added c | () [default] draft - o 18:9437917ebe8d added b + o 18:80cec1b1c90f added b | () [default] draft - @ 15:ebb749d2ace8 watbar to a + @ 15:7e67dfb7ee31 watbar to a | () [default] draft o 9:2228e3b74514 add newfile | () [default] draft @@ -355,30 +514,43 @@ $ hg strip 14: --hidden 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - saved backup bundle to $TESTTMP/stackrepo1/.hg/strip-backup/ebb749d2ace8-0585ef5a-backup.hg + saved backup bundle to $TESTTMP/stackrepo1/.hg/strip-backup/7e67dfb7ee31-ff5c6a6d-backup.hg 8 new content-divergent changesets Prepare repo to have merge conflicts $ hg up -r "max(desc('added a'))" 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg evolve -r . --content-divergent - merge:[10] added a - with: [5] watbar to a + merge:[5] watbar to a + with: [10] added a base: [1] added a - rebasing "other" content-divergent changeset 8e222f257bbf on 2228e3b74514 - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + rebasing "divergent" content-divergent changeset 8e222f257bbf on 2228e3b74514 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved 6 new orphan changesets - working directory is now at ebb749d2ace8 + working directory is now at 7e67dfb7ee31 $ echo b_conflict > b $ hg amend -A adding b Let's try to evolve stack $ hg evolve --content-divergent - merge:[11] added b - with: [6] added b + merge:[6] added b + with: [11] added b base: [2] added b - rebasing "divergent" content-divergent changeset 6eb54b5af3fb on 73a960350ce9 + rebasing "divergent" content-divergent changeset d5f148423c16 on c758af982013 + merging b + warning: conflicts while merging b! (edit, then use 'hg resolve --mark') + unresolved merge conflicts + (see 'hg help evolve.interrupted') + [1] + + $ echo b > b + $ hg res -m + (no more unresolved files) + continue: hg evolve --continue + $ hg evolve --continue + evolving 6:d5f148423c16 "added b" + rebasing "other" content-divergent changeset 6eb54b5af3fb on c758af982013 merging b warning: conflicts while merging b! (edit, then use 'hg resolve --mark') unresolved merge conflicts @@ -391,41 +563,28 @@ continue: hg evolve --continue $ hg evolve --continue evolving 11:6eb54b5af3fb "added b" - rebasing "other" content-divergent changeset d5f148423c16 on 73a960350ce9 - merging b - warning: conflicts while merging b! (edit, then use 'hg resolve --mark') - unresolved merge conflicts - (see 'hg help evolve.interrupted') - [1] - - $ echo b > b - $ hg res -m - (no more unresolved files) - continue: hg evolve --continue - $ hg evolve --continue - evolving 6:d5f148423c16 "added b" 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - merge:[12] added c - with: [7] added c + merge:[7] added c + with: [12] added c base: [3] added c - rebasing "divergent" content-divergent changeset 8ed612937375 on 1b637ec00f24 - rebasing "other" content-divergent changeset 3ce4be6d8e5e on 1b637ec00f24 + rebasing "divergent" content-divergent changeset 3ce4be6d8e5e on 1a79fc84e761 + rebasing "other" content-divergent changeset 8ed612937375 on 1a79fc84e761 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - merge:[13] added d - with: [8] added d + merge:[8] added d + with: [13] added d base: [4] added d - rebasing "divergent" content-divergent changeset d45f050514c2 on fbfadbe143d8 - rebasing "other" content-divergent changeset c72d2885eb51 on fbfadbe143d8 + rebasing "divergent" content-divergent changeset c72d2885eb51 on 6c228f1e5409 + rebasing "other" content-divergent changeset d45f050514c2 on 6c228f1e5409 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory is now at 73a960350ce9 + working directory is now at c758af982013 $ hg glog - o 25:bf2836f524a3 added d + o 25:957008d45543 added d | () [default] draft - o 22:fbfadbe143d8 added c + o 22:6c228f1e5409 added c | () [default] draft - o 19:1b637ec00f24 added b + o 19:1a79fc84e761 added b | () [default] draft - @ 16:73a960350ce9 watbar to a + @ 16:c758af982013 watbar to a | () [default] draft o 9:2228e3b74514 add newfile | () [default] draft @@ -436,7 +595,7 @@ -------------------------------------------------------------- $ hg strip 14: --hidden 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - saved backup bundle to $TESTTMP/stackrepo1/.hg/strip-backup/ebb749d2ace8-c2c1e937-backup.hg + saved backup bundle to $TESTTMP/stackrepo1/.hg/strip-backup/c758af982013-0af4fee9-backup.hg 8 new content-divergent changesets Insert conflicting changes in between the stack of content-div csets @@ -469,16 +628,16 @@ Now let's try to evolve stack $ hg evolve --content-divergent - merge:[10] added a - with: [5] watbar to a + merge:[5] watbar to a + with: [10] added a base: [1] added a - rebasing "other" content-divergent changeset 8e222f257bbf on 2228e3b74514 - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + rebasing "divergent" content-divergent changeset 8e222f257bbf on 2228e3b74514 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved merge:[14] added b with: [17] added b base: [2] added b - rebasing "divergent" content-divergent changeset 2a955e808c53 on ebb749d2ace8 - rebasing "other" content-divergent changeset 509103439e5e on ebb749d2ace8 + rebasing "divergent" content-divergent changeset 2a955e808c53 on 7e67dfb7ee31 + rebasing "other" content-divergent changeset 509103439e5e on 7e67dfb7ee31 merging b warning: conflicts while merging b! (edit, then use 'hg resolve --mark') 0 files updated, 0 files merged, 0 files removed, 1 files unresolved @@ -570,16 +729,16 @@ summary: added hgignore $ hg evolve --content-divergent - merge:[10] added a - with: [5] watbar to a + merge:[5] watbar to a + with: [10] added a base: [1] added a - rebasing "other" content-divergent changeset 8e222f257bbf on 2228e3b74514 - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + rebasing "divergent" content-divergent changeset 8e222f257bbf on 2228e3b74514 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved merge:[14] added b with: [17] added b base: [2] added b - rebasing "divergent" content-divergent changeset 2a955e808c53 on ebb749d2ace8 - rebasing "other" content-divergent changeset 509103439e5e on ebb749d2ace8 + rebasing "divergent" content-divergent changeset 2a955e808c53 on 7e67dfb7ee31 + rebasing "other" content-divergent changeset 509103439e5e on 7e67dfb7ee31 merging b warning: conflicts while merging b! (edit, then use 'hg resolve --mark') 0 files updated, 0 files merged, 0 files removed, 1 files unresolved @@ -593,7 +752,7 @@ stopped the interrupted evolve working directory is now at 2a955e808c53 $ hg log -G - o changeset: 21:ebb749d2ace8 + o changeset: 21:7e67dfb7ee31 | tag: tip | parent: 9:2228e3b74514 | user: test @@ -641,7 +800,7 @@ +---x changeset: 10:c04ff147ef79 | | user: test | | date: Thu Jan 01 00:00:00 1970 +0000 - | | obsolete: rewritten using evolve as 21:ebb749d2ace8 + | | obsolete: rewritten using evolve as 21:7e67dfb7ee31 | | summary: added a | | o | changeset: 9:2228e3b74514 @@ -654,7 +813,7 @@ |/ parent: 0:8fa14d15e168 | user: test | date: Thu Jan 01 00:00:00 1970 +0000 - | obsolete: rebased using evolve as 21:ebb749d2ace8 + | obsolete: rebased using evolve as 21:7e67dfb7ee31 | summary: watbar to a | o changeset: 0:8fa14d15e168 @@ -663,7 +822,7 @@ summary: added hgignore $ hg obslog -r 'desc("watbar to a")' --all - o ebb749d2ace8 (21) watbar to a + o 7e67dfb7ee31 (21) watbar to a |\ rewritten from 186bdc2cdfa2 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) | | rewritten(description, content) from c04ff147ef79 using evolve by test (Thu Jan 01 00:00:00 1970 +0000) | | @@ -699,8 +858,8 @@ merge:[14] added b with: [17] added b base: [2] added b - rebasing "divergent" content-divergent changeset 2a955e808c53 on ebb749d2ace8 - rebasing "other" content-divergent changeset 509103439e5e on ebb749d2ace8 + rebasing "divergent" content-divergent changeset 2a955e808c53 on 7e67dfb7ee31 + rebasing "other" content-divergent changeset 509103439e5e on 7e67dfb7ee31 merging b warning: conflicts while merging b! (edit, then use 'hg resolve --mark') 0 files updated, 0 files merged, 0 files removed, 1 files unresolved @@ -716,16 +875,16 @@ merge:[15] added c with: [18] added c base: [3] added c - rebasing "divergent" content-divergent changeset 48b0f803817a on 32bceb5bc91e - rebasing "other" content-divergent changeset eaf34afe4df3 on 32bceb5bc91e + rebasing "divergent" content-divergent changeset 48b0f803817a on ddfcba2aac91 + rebasing "other" content-divergent changeset eaf34afe4df3 on ddfcba2aac91 0 files updated, 0 files merged, 0 files removed, 0 files unresolved merge:[16] added d with: [19] added d base: [4] added d - rebasing "divergent" content-divergent changeset 91c8ccb9c241 on a87eb9f90df6 - rebasing "other" content-divergent changeset c351be27f199 on a87eb9f90df6 + rebasing "divergent" content-divergent changeset 91c8ccb9c241 on bb396302d792 + rebasing "other" content-divergent changeset c351be27f199 on bb396302d792 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory is now at 32bceb5bc91e + working directory is now at ddfcba2aac91 $ hg evolve -l @@ -852,16 +1011,16 @@ $ hg evolve --content-divergent - merge:[6] b - with: [3] b + merge:[3] b + with: [6] b base: [1] b - rebasing "other" content-divergent changeset 5b2d00df9c4e on 980f7dc84c29 - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - merge:[7] c - with: [4] c + rebasing "divergent" content-divergent changeset 5b2d00df9c4e on 980f7dc84c29 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + merge:[4] c + with: [7] c base: [2] c - rebasing "divergent" content-divergent changeset ef4885dea3da on 6813d99f0a9d - rebasing "other" content-divergent changeset fef59171875e on 6813d99f0a9d + rebasing "divergent" content-divergent changeset fef59171875e on bfba946a2829 + rebasing "other" content-divergent changeset ef4885dea3da on bfba946a2829 0 files updated, 0 files merged, 0 files removed, 0 files unresolved Expected result: @@ -869,15 +1028,15 @@ Changeset with description "c" only adds file "c" with content "c". $ hg glog -l2 -p - o 12:d5a8159e883f c - | () [default] draftdiff -r 6813d99f0a9d -r d5a8159e883f c + o 12:a5abd6c7f9d8 c + | () [default] draftdiff -r bfba946a2829 -r a5abd6c7f9d8 c | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 | +++ b/c Thu Jan 01 00:00:00 1970 +0000 | @@ -0,0 +1,1 @@ | +c | - o 9:6813d99f0a9d b - | () [default] draftdiff -r 980f7dc84c29 -r 6813d99f0a9d b + o 9:bfba946a2829 b + | () [default] draftdiff -r 980f7dc84c29 -r bfba946a2829 b ~ --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/b Thu Jan 01 00:00:00 1970 +0000 @@ -0,0 +1,1 @@ @@ -955,24 +1114,24 @@ () [default] draft $ hg evolve -r 4+5 --content-divergent - merge:[8] added foo - with: [4] added foo + merge:[4] added foo + with: [8] added foo base: [1] added foo - rebasing "other" content-divergent changeset 8a2d93492f59 on 9703820a7d5b - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - merge:[9] added bar and car - with: [5] added bar and car + rebasing "divergent" content-divergent changeset 8a2d93492f59 on 9703820a7d5b + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + merge:[5] added bar and car + with: [9] added bar and car base: [2] added bar and car - rebasing "divergent" content-divergent changeset 7dd5b9d42ef3 on 586526ab82c5 - rebasing "other" content-divergent changeset f4ed107810a7 on 586526ab82c5 + rebasing "divergent" content-divergent changeset f4ed107810a7 on 3e0693d8f69b + rebasing "other" content-divergent changeset 7dd5b9d42ef3 on 3e0693d8f69b 0 files updated, 0 files merged, 0 files removed, 0 files unresolved 2 new orphan changesets - working directory is now at 586526ab82c5 + working directory is now at 3e0693d8f69b $ hg glog - o 15:e905bb19fd7e added bar and car + o 15:5382795441b8 added bar and car | () [default] draft - @ 12:586526ab82c5 added foo + @ 12:3e0693d8f69b added foo | () [default] draft | * 10:9a1f460df8b5 added dar | | () [default] draft @@ -991,17 +1150,33 @@ o 0:bde1d2b6b5e5 added base () [default] draft + $ hg reb -r 10 -d 7 + rebasing 10:9a1f460df8b5 "added dar" + $ hg up 0 -q + $ echo alpha > alpha + $ hg ci -Am "added alpha" + adding alpha + created new head + $ hg reb -r 6 -d 'desc("added alpha")' + rebasing 6:57a3f8edf065 "added dar" + $ hg evolve --content-divergent + skipping 8b68d5104188: have a different parent than cf9a46e19942 (not handled yet) + | 8b68d5104188, cf9a46e19942 are not based on the same changeset. + | With the current state of its implementation, + | evolve does not work in that case. + | rebase one of them next to the other and run + | this command again. + | - either: hg rebase --dest 'p1(8b68d5104188)' -r cf9a46e19942 + | - or: hg rebase --dest 'p1(cf9a46e19942)' -r 8b68d5104188 + + $ hg strip -r 16: + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + saved backup bundle to $TESTTMP/multiplesuccs2/.hg/strip-backup/8b68d5104188-e72c2390-backup.hg + 2 new orphan changesets $ echo bar > bar; hg ci -Aqm "added bar" $ echo car > car; hg ci -Aqm "added car" $ hg prune --split -s 16+17 -r 15 1 changesets pruned $ hg evolve --content-divergent - skipping 57a3f8edf065: have a different parent than 9a1f460df8b5 (not handled yet) - | 57a3f8edf065, 9a1f460df8b5 are not based on the same changeset. - | With the current state of its implementation, - | evolve does not work in that case. - | rebase one of them next to the other and run - | this command again. - | - either: hg rebase --dest 'p1(57a3f8edf065)' -r 9a1f460df8b5 - | - or: hg rebase --dest 'p1(9a1f460df8b5)' -r 57a3f8edf065 + skipping 57a3f8edf065: ambiguous orphan resolution parent for 57a3f8edf065 diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-cycles.t --- a/tests/test-evolve-cycles.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-cycles.t Sat Oct 31 18:37:12 2020 +0800 @@ -358,7 +358,7 @@ Check the json output is valid in this case - $ hg obslog "desc(D)" --hidden --no-graph -Tjson | python -m json.tool + $ hg obslog "desc(D)" --hidden --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [ @@ -559,7 +559,7 @@ } ] - $ hg obslog "desc(D)" --hidden --no-graph --no-origin -Tjson | python -m json.tool + $ hg obslog "desc(D)" --hidden --no-graph --no-origin -Tjson | "$PYTHON" -m json.tool [ { "markers": [ diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-interrupted.t diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-issue5958.t --- a/tests/test-evolve-issue5958.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-issue5958.t Sat Oct 31 18:37:12 2020 +0800 @@ -86,9 +86,50 @@ x cc71ffbc7c00 (1) add foo.txt $ hg evolve --content-divergent - merge:[6] add foo.txt - with: [4] add foo.txt + merge:[4] add foo.txt + with: [6] add foo.txt base: [1] add foo.txt - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - 1 new orphan changesets - working directory is now at 5899f25049de + rebasing "other" content-divergent changeset 08bc7ba82799 on a24ed8ad918c + 2 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory is now at d519bd54a945 + + $ hg log -G + @ changeset: 8:d519bd54a945 + | tag: tip + | parent: 0:a24ed8ad918c + | user: test + | date: Wed Dec 31 23:59:58 1969 -0000 + | summary: add foo.txt + | + o changeset: 0:a24ed8ad918c + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add r0 + +test that resolution is consistent and independent of divergent changeset we initiate the resolution from + + $ hg strip . --config extensions.strip= + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + saved backup bundle to $TESTTMP/issue5958/.hg/strip-backup/d519bd54a945-5f6b2f65-backup.hg + 2 new content-divergent changesets + $ hg up 4 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg evolve --content-divergent + merge:[4] add foo.txt + with: [7] add foo.txt + base: [1] add foo.txt + 2 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory is now at d519bd54a945 + $ hg log -G + @ changeset: 8:d519bd54a945 + | tag: tip + | parent: 0:a24ed8ad918c + | user: test + | date: Wed Dec 31 23:59:58 1969 -0000 + | summary: add foo.txt + | + o changeset: 0:a24ed8ad918c + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add r0 + diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-obshistory-amend-then-fold.t --- a/tests/test-evolve-obshistory-amend-then-fold.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-obshistory-amend-then-fold.t Sat Oct 31 18:37:12 2020 +0800 @@ -185,7 +185,7 @@ | x 0dec01379d3b (2) B0 - $ hg obslog eb5a0daa2192 --no-graph --no-origin -Tjson | python -m json.tool + $ hg obslog eb5a0daa2192 --no-graph --no-origin -Tjson | "$PYTHON" -m json.tool [ { "markers": [], @@ -277,7 +277,7 @@ "shortdescription": "A0" } ] - $ hg obslog eb5a0daa2192 --no-graph -Tjson | python -m json.tool + $ hg obslog eb5a0daa2192 --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [ diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-obshistory-amend.t --- a/tests/test-evolve-obshistory-amend.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-obshistory-amend.t Sat Oct 31 18:37:12 2020 +0800 @@ -5,6 +5,12 @@ $ . $TESTDIR/testlib/obshistory_setup.sh + $ cat >> $HGRCPATH << EOF + > [templates] + > logdates = '{ifeq(min(dates), max(dates), "at {max(dates)|hgdate}", "between {min(dates)|hgdate} and {max(dates)|hgdate}")}' + > logmarkers = '{if(markers, join(markers % "{logdates} by {users} "))}' + > EOF + Test output on amended commit ============================= @@ -127,29 +133,29 @@ x 471f378eab4c A0 - $ hg obslog 4ae3a4151de9 --graph --no-origin -T'{label("log.summary", desc|firstline)} {if(markers, join(markers % "at {date|hgdate} by {user|person} ", " also "))}' + $ hg obslog 4ae3a4151de9 --graph --no-origin -T '{desc|firstline} {logmarkers}' @ A1 | x A0 at 0 0 by test - $ hg obslog 4ae3a4151de9 --graph -T'{label("log.summary", desc|firstline)} {if(markers, join(markers % "at {date|hgdate} by {user|person} ", " also "))}' + $ hg obslog 4ae3a4151de9 --graph -T '{desc|firstline} {logmarkers}' @ A1 at 0 0 by test | x A0 Check that the same thing works with the old {shortdescription} form - $ hg obslog 4ae3a4151de9 --graph --no-origin -T'{label("log.summary", shortdescription)} {if(markers, join(markers % "at {date|hgdate} by {user|person} ", " also "))}' + $ hg obslog 4ae3a4151de9 --graph --no-origin -T '{shortdescription} {logmarkers}' @ A1 | x A0 at 0 0 by test - $ hg obslog 4ae3a4151de9 --graph -T'{label("log.summary", shortdescription)} {if(markers, join(markers % "at {date|hgdate} by {user|person} ", " also "))}' + $ hg obslog 4ae3a4151de9 --graph -T '{shortdescription} {logmarkers}' @ A1 at 0 0 by test | x A0 - $ hg obslog 4ae3a4151de9 --no-graph -Tjson | python -m json.tool + $ hg obslog 4ae3a4151de9 --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [ @@ -188,7 +194,7 @@ $ hg obslog --hidden --patch 471f378eab4c x 471f378eab4c (1) A0 - $ hg obslog --hidden 471f378eab4c --no-graph -Tjson | python -m json.tool + $ hg obslog --hidden 471f378eab4c --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [], diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-obshistory-content-divergent.t --- a/tests/test-evolve-obshistory-content-divergent.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-obshistory-content-divergent.t Sat Oct 31 18:37:12 2020 +0800 @@ -137,7 +137,7 @@ reworded(description) as 65b757b745b9 using amend by test (Thu Jan 01 00:00:00 1970 +0000) reworded(description) as fdf9bde5129a using amend by test (Thu Jan 01 00:00:00 1970 +0000) - $ hg obslog --hidden 471f378eab4c --no-graph --no-origin -Tjson | python -m json.tool + $ hg obslog --hidden 471f378eab4c --no-graph --no-origin -Tjson | "$PYTHON" -m json.tool [ { "markers": [ @@ -188,7 +188,7 @@ "shortdescription": "A0" } ] - $ hg obslog --hidden 471f378eab4c --no-graph -Tjson | python -m json.tool + $ hg obslog --hidden 471f378eab4c --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [], @@ -315,7 +315,7 @@ | x 471f378eab4c (1) A0 - $ hg obslog '65b757b745b9+fdf9bde5129a' --no-graph --no-origin -Tjson | python -m json.tool + $ hg obslog '65b757b745b9+fdf9bde5129a' --no-graph --no-origin -Tjson | "$PYTHON" -m json.tool [ { "markers": [], @@ -376,7 +376,7 @@ "shortdescription": "A1" } ] - $ hg obslog '65b757b745b9+fdf9bde5129a' --no-graph -Tjson | python -m json.tool + $ hg obslog '65b757b745b9+fdf9bde5129a' --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [ diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-obshistory-fold.t --- a/tests/test-evolve-obshistory-fold.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-obshistory-fold.t Sat Oct 31 18:37:12 2020 +0800 @@ -166,7 +166,7 @@ +B0 - $ hg obslog eb5a0daa2192 --no-graph --no-origin -Tjson | python -m json.tool + $ hg obslog eb5a0daa2192 --no-graph --no-origin -Tjson | "$PYTHON" -m json.tool [ { "markers": [], @@ -241,7 +241,7 @@ / x 471f378eab4c (1) A0 - $ hg obslog eb5a0daa2192 --no-graph -Tjson | python -m json.tool + $ hg obslog eb5a0daa2192 --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [ diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-obshistory-lots-of-splits.t --- a/tests/test-evolve-obshistory-lots-of-splits.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-obshistory-lots-of-splits.t Sat Oct 31 18:37:12 2020 +0800 @@ -225,7 +225,7 @@ | x de7290d8b885 (1) A0 - $ hg obslog de7290d8b885 --hidden --no-graph --no-origin -Tjson | python -m json.tool + $ hg obslog de7290d8b885 --hidden --no-graph --no-origin -Tjson | "$PYTHON" -m json.tool [ { "markers": [ @@ -273,7 +273,7 @@ | x de7290d8b885 (1) A0 - $ hg obslog c7f044602e9b --no-graph --no-origin -Tjson | python -m json.tool + $ hg obslog c7f044602e9b --no-graph --no-origin -Tjson | "$PYTHON" -m json.tool [ { "markers": [], @@ -312,7 +312,7 @@ "shortdescription": "A0" } ] - $ hg obslog c7f044602e9b --no-graph -Tjson | python -m json.tool + $ hg obslog c7f044602e9b --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [ diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-obshistory-phase-divergent.t --- a/tests/test-evolve-obshistory-phase-divergent.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-obshistory-phase-divergent.t Sat Oct 31 18:37:12 2020 +0800 @@ -105,7 +105,7 @@ | @ 471f378eab4c (1) A0 - $ hg obslog --hidden 471f378eab4c --no-graph --no-origin -Tjson | python -m json.tool + $ hg obslog --hidden 471f378eab4c --no-graph --no-origin -Tjson | "$PYTHON" -m json.tool [ { "markers": [ @@ -135,7 +135,7 @@ "shortdescription": "A0" } ] - $ hg obslog --hidden 471f378eab4c --no-graph -Tjson | python -m json.tool + $ hg obslog --hidden 471f378eab4c --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [], @@ -186,7 +186,7 @@ | @ 471f378eab4c (1) A0 - $ hg obslog 'fdf9bde5129a+471f378eab4c' --no-graph --no-origin -Tjson | python -m json.tool + $ hg obslog 'fdf9bde5129a+471f378eab4c' --no-graph --no-origin -Tjson | "$PYTHON" -m json.tool [ { "markers": [], @@ -221,7 +221,7 @@ "shortdescription": "A0" } ] - $ hg obslog 'fdf9bde5129a+471f378eab4c' --no-graph -Tjson | python -m json.tool + $ hg obslog 'fdf9bde5129a+471f378eab4c' --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [ diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-obshistory-prune.t --- a/tests/test-evolve-obshistory-prune.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-obshistory-prune.t Sat Oct 31 18:37:12 2020 +0800 @@ -67,7 +67,7 @@ pruned using prune by test (Thu Jan 01 00:00:00 1970 +0000) (No patch available, no predecessors) - $ hg obslog 'desc(B0)' --hidden --no-graph -Tjson | python -m json.tool + $ hg obslog 'desc(B0)' --hidden --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [ @@ -94,7 +94,7 @@ $ hg obslog 'desc(A0)' --patch @ 471f378eab4c (1) A0 - $ hg obslog 'desc(A0)' --no-graph -Tjson | python -m json.tool + $ hg obslog 'desc(A0)' --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [], diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-obshistory-split.t --- a/tests/test-evolve-obshistory-split.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-obshistory-split.t Sat Oct 31 18:37:12 2020 +0800 @@ -109,7 +109,7 @@ note: testing split (No patch available, too many successors (2)) - $ hg obslog 471597cad322 --hidden --no-graph --no-origin -Tjson | python -m json.tool + $ hg obslog 471597cad322 --hidden --no-graph --no-origin -Tjson | "$PYTHON" -m json.tool [ { "markers": [ @@ -144,7 +144,7 @@ "shortdescription": "A0" } ] - $ hg obslog 471597cad322 --hidden --no-graph -Tjson | python -m json.tool + $ hg obslog 471597cad322 --hidden --no-graph -Tjson | "$PYTHON" -m json.tool [ { "markers": [], diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-order.t --- a/tests/test-evolve-order.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-order.t Sat Oct 31 18:37:12 2020 +0800 @@ -199,7 +199,7 @@ $ echo "(desc(_d)::) - desc(c3_)" (desc(_d)::) - desc(c3_) $ hg evolve --rev "(desc(_d)::) - desc(c3_)" - cannot solve instability of d096a2437fd0, skipping + skipping d096a2437fd0, consider including orphan ancestors move:[20] add c2prime atop:[21] add c1second move:[25] add b4_ diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-phase.t --- a/tests/test-evolve-phase.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-phase.t Sat Oct 31 18:37:12 2020 +0800 @@ -103,7 +103,7 @@ $ hg glog @ 3 - 87495ea7c9ec b (draft) | - | @ 2 - 13833940840c c (secret) + | % 2 - 13833940840c c (secret) | | | x 1 - 1e6c11564562 b (draft) |/ diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-progress.t --- a/tests/test-evolve-progress.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-progress.t Sat Oct 31 18:37:12 2020 +0800 @@ -125,6 +125,7 @@ branchmerge: True, force: True, partial: False ancestor: 152c368c622b, local: f8d7d38c0a88+, remote: df5d742141b0 preserving a for resolve of a + starting 4 threads for background file closing (?) a: versions differ -> m (premerge) updating: a 1/1 files (100.00%) picked tool ':merge' for a (binary False symlink False changedelete False) diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-public-content-divergent-corner-cases.t --- a/tests/test-evolve-public-content-divergent-corner-cases.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-public-content-divergent-corner-cases.t Sat Oct 31 18:37:12 2020 +0800 @@ -388,10 +388,10 @@ $ hg evolve --content-divergent --any --update - merge:[5] added d - with: [4] added c e + merge:[4] added c e + with: [5] added d base: [3] added d - rebasing "other" content-divergent changeset e568fd1029bb on 155349b645be + rebasing "divergent" content-divergent changeset e568fd1029bb on 155349b645be merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved merge conflicts @@ -660,7 +660,7 @@ $ hg evolve --list - $ hg log -G --patch + $ hg log -G --patch -l2 @ changeset: 8:a52ac76b45f5 | tag: tip | user: test @@ -675,70 +675,15 @@ | o changeset: 7:c7d2d47c7240 | parent: 2:eb1b4e1205b8 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: c_E - | - | diff -r eb1b4e1205b8 -r c7d2d47c7240 c_E - | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 - | +++ b/c_E Thu Jan 01 00:00:00 1970 +0000 - | @@ -0,0 +1,1 @@ - | +c_E - | - | o changeset: 4:dbb960d6c97c - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: c_D - | | - | | diff -r abb77b893f28 -r dbb960d6c97c c_D - | | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 - | | +++ b/c_D Thu Jan 01 00:00:00 1970 +0000 - | | @@ -0,0 +1,1 @@ - | | +c_D - | | - | o changeset: 3:abb77b893f28 - |/ user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: c_C - | - | diff -r eb1b4e1205b8 -r abb77b893f28 c_C - | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 - | +++ b/c_C Thu Jan 01 00:00:00 1970 +0000 - | @@ -0,0 +1,1 @@ - | +c_C - | - o changeset: 2:eb1b4e1205b8 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: c_B - | - | diff -r e31751786014 -r eb1b4e1205b8 c_B - | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 - | +++ b/c_B Thu Jan 01 00:00:00 1970 +0000 - | @@ -0,0 +1,1 @@ - | +c_B - | - o changeset: 1:e31751786014 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: c_A - | - | diff -r 1e4be0697311 -r e31751786014 c_A - | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 - | +++ b/c_A Thu Jan 01 00:00:00 1970 +0000 - | @@ -0,0 +1,1 @@ - | +c_A - | - o changeset: 0:1e4be0697311 - user: test + ~ user: test date: Thu Jan 01 00:00:00 1970 +0000 - summary: root + summary: c_E - diff -r 000000000000 -r 1e4be0697311 root + diff -r eb1b4e1205b8 -r c7d2d47c7240 c_E --- /dev/null Thu Jan 01 00:00:00 1970 +0000 - +++ b/root Thu Jan 01 00:00:00 1970 +0000 + +++ b/c_E Thu Jan 01 00:00:00 1970 +0000 @@ -0,0 +1,1 @@ - +root + +c_E $ hg export tip # HG changeset patch diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-public-content-divergent-discard.t --- a/tests/test-evolve-public-content-divergent-discard.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-public-content-divergent-discard.t Sat Oct 31 18:37:12 2020 +0800 @@ -89,8 +89,8 @@ public $ hg evolve --content-divergent --any - merge:[4] added c - with: [3] added ch + merge:[3] added ch + with: [4] added c base: [2] added c 0 files updated, 0 files merged, 0 files removed, 0 files unresolved other divergent changeset 90522bccf499 has same content as local f7c1071f1e7c and differs by "description" only, discarding 90522bccf499 @@ -180,10 +180,10 @@ public $ hg evolve --content-divergent --any - merge:[5] added d - with: [4] added dh + merge:[4] added dh + with: [5] added d base: [3] added d - rebasing "other" content-divergent changeset 5acd58ef5066 on 155349b645be + rebasing "divergent" content-divergent changeset 5acd58ef5066 on 155349b645be 0 files updated, 0 files merged, 0 files removed, 0 files unresolved other divergent changeset ae3429430ef1 has same content as local e800202333a4 and differs by "description" only, discarding ae3429430ef1 content divergence resolution between e800202333a4 (public) and ae3429430ef1 has same content as e800202333a4, discarding ae3429430ef1 @@ -265,8 +265,8 @@ public $ hg evolve --content-divergent --any - merge:[4] added c - with: [3] added ch + merge:[3] added ch + with: [4] added c base: [2] added c merging ch warning: conflicts while merging ch! (edit, then use 'hg resolve --mark') @@ -380,10 +380,10 @@ public $ hg evolve --content-divergent --any - merge:[5] added d - with: [4] added dh + merge:[4] added dh + with: [5] added d base: [3] added d - rebasing "other" content-divergent changeset f89a8e2f86ac on 155349b645be + rebasing "divergent" content-divergent changeset f89a8e2f86ac on 155349b645be merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved merge conflicts @@ -485,10 +485,10 @@ public $ hg evolve --content-divergent --any - merge:[5] added d - with: [4] added dh + merge:[4] added dh + with: [5] added d base: [3] added d - rebasing "other" content-divergent changeset db0b7bba0aae on 155349b645be + rebasing "divergent" content-divergent changeset db0b7bba0aae on 155349b645be merging dh warning: conflicts while merging dh! (edit, then use 'hg resolve --mark') 0 files updated, 0 files merged, 0 files removed, 1 files unresolved @@ -590,10 +590,10 @@ public $ hg evolve --content-divergent --any - merge:[5] added d - with: [4] added dh + merge:[4] added dh + with: [5] added d base: [3] added d - rebasing "other" content-divergent changeset 67b19bbd770f on 155349b645be + rebasing "divergent" content-divergent changeset 67b19bbd770f on 155349b645be merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved merge conflicts diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-public-content-divergent-main.t --- a/tests/test-evolve-public-content-divergent-main.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-public-content-divergent-main.t Sat Oct 31 18:37:12 2020 +0800 @@ -353,10 +353,10 @@ public $ hg evolve --content-divergent --any --update - merge:[5] added d - with: [4] added d c e + merge:[4] added d c e + with: [5] added d base: [3] added d - rebasing "other" content-divergent changeset f31bcc378766 on 155349b645be + rebasing "divergent" content-divergent changeset f31bcc378766 on 155349b645be merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved merge conflicts @@ -483,10 +483,10 @@ public $ hg evolve --content-divergent --any - merge:[5] added d - with: [4] added d + merge:[4] added d + with: [5] added d base: [3] added d - rebasing "other" content-divergent changeset 9411ad1fe615 on 155349b645be + rebasing "divergent" content-divergent changeset 9411ad1fe615 on 155349b645be merging d warning: conflicts while merging d! (edit, then use 'hg resolve --mark') 0 files updated, 0 files merged, 0 files removed, 1 files unresolved @@ -577,10 +577,10 @@ public $ hg evolve --content-divergent --any - merge:[5] added d - with: [4] added c e + merge:[4] added c e + with: [5] added d base: [3] added d - rebasing "other" content-divergent changeset 3c17c7afaf6e on 155349b645be + rebasing "divergent" content-divergent changeset 3c17c7afaf6e on 155349b645be merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved merge conflicts diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-serveronly-bundle2.t --- a/tests/test-evolve-serveronly-bundle2.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve-serveronly-bundle2.t Sat Oct 31 18:37:12 2020 +0800 @@ -85,12 +85,12 @@ Capacity testing =================== - $ curl -s http://localhost:$HGPORT/?cmd=hello + $ hg debugdownload http://localhost:$HGPORT/?cmd=hello capabilities: _evoext_getbundle_obscommon _evoext_obshashrange_v1 batch * (glob) - $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshashrange_v1 batch * (no-eol) (glob) + $ hg debugdownload http://localhost:$HGPORT/?cmd=capabilities + _evoext_getbundle_obscommon _evoext_obshashrange_v1 batch * (glob) - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort + $ hg debugpushkey http://localhost:$HGPORT namespaces bookmarks namespaces obsolete @@ -145,15 +145,15 @@ =========================================== (used by bitbucket to select which repo use evolve) - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort + $ hg debugpushkey http://localhost:$HGPORT namespaces bookmarks namespaces obsolete phases - $ curl -s http://localhost:$HGPORT/?cmd=hello + $ hg debugdownload http://localhost:$HGPORT/?cmd=hello capabilities: _evoext_getbundle_obscommon _evoext_obshashrange_v1 batch * (glob) - $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshashrange_v1 batch * (no-eol) (glob) + $ hg debugdownload http://localhost:$HGPORT/?cmd=capabilities + _evoext_getbundle_obscommon _evoext_obshashrange_v1 batch * (glob) $ echo '[experimental]' >> server/.hg/hgrc $ echo 'evolution=!' >> server/.hg/hgrc @@ -161,7 +161,7 @@ $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log $ cat hg.pid >> $DAEMON_PIDS - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort + $ hg debugpushkey http://localhost:$HGPORT namespaces bookmarks namespaces phases @@ -171,16 +171,16 @@ $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log $ cat hg.pid >> $DAEMON_PIDS - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort + $ hg debugpushkey http://localhost:$HGPORT namespaces bookmarks namespaces obsolete phases - $ curl -s http://localhost:$HGPORT/?cmd=hello + $ hg debugdownload http://localhost:$HGPORT/?cmd=hello capabilities: _evoext_getbundle_obscommon _evoext_obshashrange_v1 batch * (glob) - $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshashrange_v1 batch * (no-eol) (glob) + $ hg debugdownload http://localhost:$HGPORT/?cmd=capabilities + _evoext_getbundle_obscommon _evoext_obshashrange_v1 batch * (glob) Test obshashrange discover =========================================== diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve-templates.t diff -r af0458d91d10 -r ee18173c54a2 tests/test-evolve.t --- a/tests/test-evolve.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-evolve.t Sat Oct 31 18:37:12 2020 +0800 @@ -1231,7 +1231,7 @@ abort: cannot specify both "--rev" and "--any" [255] $ hg evolve --rev 89e4f7e8feb5 - cannot solve instability of 89e4f7e8feb5, skipping + skipping 89e4f7e8feb5, consider including orphan ancestors Check that uncommit respects the allowunstable option With only createmarkers we can only uncommit on a head @@ -1401,7 +1401,7 @@ | o 32:6ec468e4cb98@default(draft) amended | - | @ 31:5be050657ca5@default(draft) will cause conflict at evolve + | % 31:5be050657ca5@default(draft) will cause conflict at evolve | | | x 30:748126f98ff1@default(draft) will be evolved safely | | diff -r af0458d91d10 -r ee18173c54a2 tests/test-import.t --- a/tests/test-import.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-import.t Sat Oct 31 18:37:12 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 af0458d91d10 -r ee18173c54a2 tests/test-issue-6028.t --- a/tests/test-issue-6028.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-issue-6028.t Sat Oct 31 18:37:12 2020 +0800 @@ -165,6 +165,27 @@ evolve creates an obsolete changeset above as 11 + $ hg evolve -l + 61eff7f7bb6c: aa + orphan: 487c225d33af (obsolete parent) + + 2b5a7b3298d9: merged bb + orphan: 3f6f25057afb (obsolete parent) + + c920dd828523: merged aa + orphan: 61eff7f7bb6c (orphan parent) + $ hg evolve -r . - cannot solve instability of c920dd828523, skipping - cannot solve instability of c920dd828523, skipping + skipping c920dd828523, consider including orphan ancestors + +test that the suggestion works + + $ hg evolve -r 'parents(".")::' + move:[7] aa + atop:[1] a + switching to topic a + move:[11] merged aa + move:[10] merged bb + working directory is now at bdbfa73836d6 + + $ hg evolve -l diff -r af0458d91d10 -r ee18173c54a2 tests/test-metaedit.t --- a/tests/test-metaedit.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-metaedit.t Sat Oct 31 18:37:12 2020 +0800 @@ -3,7 +3,7 @@ $ cat >> $HGRCPATH < [alias] > glog = log -GT "{rev}:{node|short}@{branch}({phase}) {desc|firstline}" - > gluf = log -GT "{rev}: {desc|firstline} - {author|user} ({files})" + > gluf = log -GT "{separate(' ', rev, bookmarks)}: {desc|firstline} - {author|user} ({files})" > [extensions] > evolve = > EOF @@ -14,7 +14,7 @@ $ cat << EOF >> $HGRCPATH > [ui] - > logtemplate = "{rev}\t{bookmarks}: {desc|firstline} - {author|user}\n" + > logtemplate = "{separate(' ', rev, bookmarks)}: {desc|firstline} - {author|user}\n" > EOF HG METAEDIT @@ -36,9 +36,11 @@ created new head $ mkcommit "D" $ echo "D'" > D + $ hg bookmark bookmark-D $ hg amend -m "D2" $ hg up "desc(C)" 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + (leaving bookmark bookmark-D) $ mkcommit "E" created new head $ mkcommit "F" @@ -47,19 +49,19 @@ ---- $ hg log -G - @ 7 : F - test + @ 7: F - test | - o 6 : E - test + o 6: E - test | - | o 5 : D2 - test + | o 5 bookmark-D: D2 - test |/ - o 3 : C - test + o 3: C - test | - | o 2 : B - test + | o 2: B - test |/ - o 1 : A - test + o 1: A - test | - o 0 : ROOT - test + o 0: ROOT - test $ hg update --clean . 0 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -242,7 +244,7 @@ $ hg gluf @ 14: merge commit - someone-else () |\ - | o 12: D2 - foobar3 (D) + | o 12 bookmark-D: D2 - foobar3 (D) | | o | 11: E - foobar2 (E F) |/ @@ -263,7 +265,7 @@ A E A F $ hg gluf - @ 15: squashed - mr-squasher (C D E F) + @ 15 bookmark-D: squashed - mr-squasher (C D E F) | | o 2: B - test (B) |/ diff -r af0458d91d10 -r ee18173c54a2 tests/test-minitopic.t --- a/tests/test-minitopic.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-minitopic.t Sat Oct 31 18:37:12 2020 +0800 @@ -45,9 +45,9 @@ $ hg serve -R server-disabled -p $HGPORT2 -d --pid-file hg2.pid --errorlog hg2.error $ cat hg2.pid >> $DAEMON_PIDS - $ curl --silent http://localhost:$HGPORT/?cmd=capabilities | grep -o topics + $ hg debugdownload http://localhost:$HGPORT/?cmd=capabilities | grep -o topics topics - $ curl --silent http://localhost:$HGPORT2/?cmd=capabilities | grep -o topics + $ hg debugdownload http://localhost:$HGPORT2/?cmd=capabilities | grep -o topics [1] Pushing first changesets to the servers @@ -95,9 +95,9 @@ (merge or see 'hg help push' for details about pushing new heads) [255] - $ curl --silent http://localhost:$HGPORT/?cmd=branchmap | sort + $ hg debugdownload http://localhost:$HGPORT/?cmd=branchmap | sort default 0ab6d544d0efd629fda056601cfe95e73d1af210 - $ curl --silent http://localhost:$HGPORT2/?cmd=branchmap | sort + $ hg debugdownload http://localhost:$HGPORT2/?cmd=branchmap | sort default 0ab6d544d0efd629fda056601cfe95e73d1af210 $ cat $TESTTMP/hg1.error $ cat $TESTTMP/hg2.error @@ -162,10 +162,10 @@ remote: adding file changes remote: added 1 changesets with 1 changes to 1 files (+1 heads) - $ curl --silent http://localhost:$HGPORT/?cmd=branchmap | sort + $ hg debugdownload http://localhost:$HGPORT/?cmd=branchmap | sort default 9c660cf97499ae01ccb6894880455c6ffa4b19cf default%3Atopic_A f31af349535e413b6023f11b51a6afccf4139180 - $ curl --silent http://localhost:$HGPORT2/?cmd=branchmap | sort + $ hg debugdownload http://localhost:$HGPORT2/?cmd=branchmap | sort default 9c660cf97499ae01ccb6894880455c6ffa4b19cf f31af349535e413b6023f11b51a6afccf4139180 $ cat $TESTTMP/hg1.error $ cat $TESTTMP/hg2.error @@ -231,10 +231,10 @@ remote: adding file changes remote: added 1 changesets with 1 changes to 1 files - $ curl --silent http://localhost:$HGPORT/?cmd=branchmap | sort + $ hg debugdownload http://localhost:$HGPORT/?cmd=branchmap | sort default 9c660cf97499ae01ccb6894880455c6ffa4b19cf default%3Atopic_A f31af349535e413b6023f11b51a6afccf4139180 82c5842e047215160763f81ae93ae42c65b20a63 - $ curl --silent http://localhost:$HGPORT2/?cmd=branchmap | sort + $ hg debugdownload http://localhost:$HGPORT2/?cmd=branchmap | sort default f31af349535e413b6023f11b51a6afccf4139180 82c5842e047215160763f81ae93ae42c65b20a63 $ cat $TESTTMP/hg1.error $ cat $TESTTMP/hg2.error diff -r af0458d91d10 -r ee18173c54a2 tests/test-rewind.t --- a/tests/test-rewind.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-rewind.t Sat Oct 31 18:37:12 2020 +0800 @@ -1,14 +1,11 @@ -This test file test the rewind command in several situations. + $ . $TESTDIR/testlib/common.sh Global setup ============ - $ . $TESTDIR/testlib/common.sh - $ cat >> $HGRCPATH < [ui] - > interactive = true + $ cat >> $HGRCPATH << EOF > [phases] - > publish=False + > publish = false > [alias] > glf = log -GT "{rev}: {desc} ({files})" > [extensions] @@ -18,14 +15,12 @@ $ hg init rewind-testing-base $ cd rewind-testing-base $ echo a > root - $ hg add root - $ hg ci -m 'c_ROOT' + $ hg ci -qAm 'c_ROOT' $ echo a > A - $ hg add A - $ hg ci -m 'c_A0' + $ hg ci -qAm 'c_A0' $ echo a > B - $ hg add B - $ hg ci -m 'c_B0' + $ hg ci -qAm 'c_B0' + $ hg log -G @ changeset: 2:7e594302a05d | tag: tip @@ -46,26 +41,23 @@ $ cd .. -Test rewinding to single changesets -==================================== +Rewinding to a single changeset +=============================== - $ hg clone rewind-testing-base rewind-testing-simple-prune + $ hg clone rewind-testing-base rewind-testing-single-prunes updating to branch default 3 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cd rewind-testing-simple-prune + $ cd rewind-testing-single-prunes Prune changeset unrelated to the working copy --------------------------------------------- -Setup -````` - -Update to an unrelated changeset +update to an unrelated changeset $ hg up 'desc("c_ROOT")' 0 files updated, 0 files merged, 2 files removed, 0 files unresolved -Prune the head +prune the head $ hg prune -r 'desc("c_B0")' 1 changesets pruned @@ -82,11 +74,15 @@ summary: c_ROOT -Actual rewind -````````````` +target selection + + $ hg rewind --hidden --to 'desc("c_B0")' --dry-run + rewinding a pruned commit to 1 changesets: 7e594302a05d + +actual rewind $ hg rewind --hidden --to 'desc("c_B0")' - rewinded to 1 changesets + rewound to 1 changesets $ hg debugobsolete 7e594302a05d3769b27be88fc3cdfd39d7498498 0 {579f120ba91885449adc92eedf48ef3569742cee} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} 7e594302a05d3769b27be88fc3cdfd39d7498498 073989a581cf430a844192364fa37606357cbbc2 4 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '2', 'operation': 'rewind', 'user': 'test'} @@ -149,24 +145,26 @@ summary: c_ROOT -Other independant rewind create a different revision ----------------------------------------------------------- - -setup -````` +Other independent rewind creates a different revision +----------------------------------------------------- note: we use "default-date" to make it a "different rewind" $ echo '[devel]' >> $HGRCPATH $ echo 'default-date = 1 0' >> $HGRCPATH -Actual rewind -````````````` - $ hg prune 'desc("c_B0")' 1 changesets pruned + +target selection + + $ hg rewind --hidden --to 'min(desc("c_B0"))' --dry-run + rewinding a pruned commit to 1 changesets: 7e594302a05d + +actual rewind + $ hg rewind --hidden --to 'min(desc("c_B0"))' - rewinded to 1 changesets + rewound to 1 changesets $ hg debugobsolete 7e594302a05d3769b27be88fc3cdfd39d7498498 0 {579f120ba91885449adc92eedf48ef3569742cee} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'prune', 'user': 'test'} 7e594302a05d3769b27be88fc3cdfd39d7498498 073989a581cf430a844192364fa37606357cbbc2 4 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '2', 'operation': 'rewind', 'user': 'test'} @@ -246,16 +244,14 @@ $ cd .. -rewind a simple amend - creating content-divergence + $ hg clone rewind-testing-base rewind-testing-single-amends + updating to branch default + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd rewind-testing-single-amends + +Rewind a simple amend - creating content-divergence --------------------------------------------------- -Setup -````` - - $ hg clone rewind-testing-base rewind-testing-single-rewrite - updating to branch default - 3 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cd rewind-testing-single-rewrite $ echo BB > B $ hg amend -m 'c_B1' $ hg log -G @@ -277,12 +273,18 @@ summary: c_ROOT -Actual rewind -````````````` +target selection + + $ hg rewind --from 'desc("c_B1")' --as-divergence --dry-run + recreating 1 changesets: 7e594302a05d + $ hg rewind --hidden --to 'desc("c_B0")' --as-divergence --dry-run + recreating 1 changesets: 7e594302a05d + +actual rewind $ hg rewind --hidden --to 'desc("c_B0")' --as-divergence 2 new content-divergent changesets - rewinded to 1 changesets + rewound to 1 changesets $ hg debugobsolete 7e594302a05d3769b27be88fc3cdfd39d7498498 25c8f5ab0c3bb569ec672570f1a901be4c6f032b 0 (Thu Jan 01 00:00:01 1970 +0000) {'ef1': '9', 'operation': 'amend', 'user': 'test'} 7e594302a05d3769b27be88fc3cdfd39d7498498 b13b032065ef57a68d9a4cead38ba0f34f95529b 4 (Thu Jan 01 00:00:01 1970 +0000) {'ef1': '2', 'operation': 'rewind', 'user': 'test'} @@ -359,8 +361,17 @@ summary: c_ROOT -Cleanup -``````` +rewind --dry-run output when rewinding with relevant divergence + + $ hg rewind --to 'min(desc("c_B0"))' --hidden --dry-run + abort: rewind confused by divergence on 7e594302a05d + (solve divergence first or use "--as-divergence") + [255] + $ hg rewind --to 'min(desc("c_B0"))' --hidden --as-divergence --dry-run + recreating 1 changesets: 7e594302a05d + +cleanup + $ hg prune 'max(desc("c_B0"))' 1 changesets pruned $ hg log -G @@ -381,13 +392,20 @@ date: Thu Jan 01 00:00:00 1970 +0000 summary: c_ROOT - $ echo 'default-date = 2 0' >> $HGRCPATH + +Rewind a simple amend - obsoleting the current latest successor +--------------------------------------------------------------- + +target selection -rewind a simple amend - obsoleting the current latest successors ----------------------------------------------------------------- + $ hg rewind --hidden --to 'min(desc("c_B0"))' --dry-run + rewinding 25c8f5ab0c3b to 1 changesets: 7e594302a05d +actual rewind + + $ echo 'default-date = 2 0' >> $HGRCPATH $ hg rewind --hidden --to 'min(desc("c_B0"))' - rewinded to 1 changesets + rewound to 1 changesets (1 changesets obsoleted) working directory is now at 837cd997bb05 $ hg debugobsolete @@ -477,22 +495,18 @@ $ cd .. -rewind a simple split ---------------------- - -Setup -````` - - $ hg clone rewind-testing-base rewind-testing-split-fold + $ hg clone rewind-testing-base rewind-testing-single-split-fold updating to branch default 3 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cd rewind-testing-split-fold + $ cd rewind-testing-single-split-fold + +Rewind a simple split +--------------------- $ echo C > C $ echo D > D - $ hg add C D - $ hg ci -m 'c_CD0' - $ hg split << EOF + $ hg ci -qAm 'c_CD0' + $ hg split --config ui.interactive=yes << EOF > y > f > d @@ -566,28 +580,34 @@ x 49fb7d900906 (3) c_CD0 -Actual rewind -````````````` +target selection + + $ hg rewind --from 'desc("c_CD0")' --dry-run + rewinding a0316c4c5417 9576e80d6851 to 1 changesets: 49fb7d900906 + $ hg rewind --hidden --to 'min(desc("c_CD0"))' --dry-run + rewinding a0316c4c5417 9576e80d6851 to 1 changesets: 49fb7d900906 + +actual rewind $ hg rewind --hidden --to 'min(desc("c_CD0"))' - rewinded to 1 changesets + rewound to 1 changesets (2 changesets obsoleted) working directory is now at 4535d0af405c $ hg debugobsolete 49fb7d900906b0a3d329e90da4dcb0a7582d3b6e a0316c4c54179357e71d068fb8884678ebc7c351 9576e80d6851ce79cd535e2dc5fa01b444d89a39 0 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '12', 'operation': 'split', 'user': 'test'} 49fb7d900906b0a3d329e90da4dcb0a7582d3b6e 4535d0af405c1bf35f37b35f26ec6f9acfa6fe0b 4 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '2', 'operation': 'rewind', 'user': 'test'} - 9576e80d6851ce79cd535e2dc5fa01b444d89a39 4535d0af405c1bf35f37b35f26ec6f9acfa6fe0b 0 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '14', 'operation': 'rewind', 'user': 'test'} - a0316c4c54179357e71d068fb8884678ebc7c351 4535d0af405c1bf35f37b35f26ec6f9acfa6fe0b 0 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '10', 'operation': 'rewind', 'user': 'test'} + 9576e80d6851ce79cd535e2dc5fa01b444d89a39 4535d0af405c1bf35f37b35f26ec6f9acfa6fe0b 0 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '14', 'fold-id': 'eeda726b', 'fold-idx': '1', 'fold-size': '2', 'operation': 'rewind', 'user': 'test'} + a0316c4c54179357e71d068fb8884678ebc7c351 4535d0af405c1bf35f37b35f26ec6f9acfa6fe0b 0 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '10', 'fold-id': 'eeda726b', 'fold-idx': '2', 'fold-size': '2', 'operation': 'rewind', 'user': 'test'} $ hg obslog --no-origin @ 4535d0af405c (6) c_CD0 |\ | \ | |\ | x | 9576e80d6851 (5) c_CD0 - |/ / rewritten(meta, parent, content) as 4535d0af405c using rewind by test (Thu Jan 01 00:00:02 1970 +0000) + |/ / folded(meta, parent, content) as 4535d0af405c using rewind by test (Thu Jan 01 00:00:02 1970 +0000) | | | x a0316c4c5417 (4) c_CD0 - |/ rewritten(meta, content) as 4535d0af405c using rewind by test (Thu Jan 01 00:00:02 1970 +0000) + |/ folded(meta, content) as 4535d0af405c using rewind by test (Thu Jan 01 00:00:02 1970 +0000) | x 49fb7d900906 (3) c_CD0 meta-changed(meta) as 4535d0af405c using rewind by test (Thu Jan 01 00:00:02 1970 +0000) @@ -596,8 +616,7 @@ $ hg obslog @ 4535d0af405c (6) c_CD0 |\ meta-changed(meta) from 49fb7d900906 using rewind by test (Thu Jan 01 00:00:02 1970 +0000) - | | rewritten(meta, parent, content) from 9576e80d6851 using rewind by test (Thu Jan 01 00:00:02 1970 +0000) - | | rewritten(meta, content) from a0316c4c5417 using rewind by test (Thu Jan 01 00:00:02 1970 +0000) + | | folded(meta, parent, content) from 9576e80d6851, a0316c4c5417 using rewind by test (Thu Jan 01 00:00:02 1970 +0000) | | | \ | |\ @@ -633,26 +652,42 @@ summary: c_ROOT -rewind a fold +Rewind a fold ------------- -setup -````` - $ echo 'default-date = 3 0' >> $HGRCPATH -Actual Rewind -````````````` +target selection + + $ hg rewind --from . --hidden --dry-run + rewinding 4535d0af405c to 2 changesets: a0316c4c5417 9576e80d6851 + + $ hg rewind --to '9576e80d6851+a0316c4c5417' --hidden --dry-run + rewinding 4535d0af405c to 2 changesets: a0316c4c5417 9576e80d6851 + $ hg rewind --to '9576e80d6851' --hidden --dry-run + rewinding 4535d0af405c to 2 changesets: a0316c4c5417 9576e80d6851 + +XXX this should also give us 2 changesets + + $ hg rewind --to 'a0316c4c5417' --hidden --dry-run + rewinding 4535d0af405c to 1 changesets: a0316c4c5417 + + $ hg rewind --to '9576e80d6851' --exact --hidden --dry-run + rewinding 4535d0af405c to 1 changesets: 9576e80d6851 + $ hg rewind --to 'a0316c4c5417' --exact --hidden --dry-run + rewinding 4535d0af405c to 1 changesets: a0316c4c5417 + +actual rewind $ hg rewind --to '9576e80d6851+a0316c4c5417' --hidden - rewinded to 2 changesets + rewound to 2 changesets (1 changesets obsoleted) working directory is now at 95d72d892df7 $ hg debugobsolete 49fb7d900906b0a3d329e90da4dcb0a7582d3b6e a0316c4c54179357e71d068fb8884678ebc7c351 9576e80d6851ce79cd535e2dc5fa01b444d89a39 0 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '12', 'operation': 'split', 'user': 'test'} 49fb7d900906b0a3d329e90da4dcb0a7582d3b6e 4535d0af405c1bf35f37b35f26ec6f9acfa6fe0b 4 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '2', 'operation': 'rewind', 'user': 'test'} - 9576e80d6851ce79cd535e2dc5fa01b444d89a39 4535d0af405c1bf35f37b35f26ec6f9acfa6fe0b 0 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '14', 'operation': 'rewind', 'user': 'test'} - a0316c4c54179357e71d068fb8884678ebc7c351 4535d0af405c1bf35f37b35f26ec6f9acfa6fe0b 0 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '10', 'operation': 'rewind', 'user': 'test'} + 9576e80d6851ce79cd535e2dc5fa01b444d89a39 4535d0af405c1bf35f37b35f26ec6f9acfa6fe0b 0 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '14', 'fold-id': 'eeda726b', 'fold-idx': '1', 'fold-size': '2', 'operation': 'rewind', 'user': 'test'} + a0316c4c54179357e71d068fb8884678ebc7c351 4535d0af405c1bf35f37b35f26ec6f9acfa6fe0b 0 (Thu Jan 01 00:00:02 1970 +0000) {'ef1': '10', 'fold-id': 'eeda726b', 'fold-idx': '2', 'fold-size': '2', 'operation': 'rewind', 'user': 'test'} a0316c4c54179357e71d068fb8884678ebc7c351 e76375de0bfc9c59bdd91067c901f3eed7d6c8fe 4 (Thu Jan 01 00:00:03 1970 +0000) {'ef1': '2', 'operation': 'rewind', 'user': 'test'} 9576e80d6851ce79cd535e2dc5fa01b444d89a39 95d72d892df7fec59107e10914c5729bdf03665f 4 (Thu Jan 01 00:00:03 1970 +0000) {'ef1': '6', 'operation': 'rewind', 'user': 'test'} 4535d0af405c1bf35f37b35f26ec6f9acfa6fe0b e76375de0bfc9c59bdd91067c901f3eed7d6c8fe 95d72d892df7fec59107e10914c5729bdf03665f 0 (Thu Jan 01 00:00:03 1970 +0000) {'ef1': '14', 'operation': 'rewind', 'user': 'test'} @@ -665,11 +700,11 @@ |\| | split(meta, parent, content) as 95d72d892df7, e76375de0bfc using rewind by test (Thu Jan 01 00:00:03 1970 +0000) | | | | x | 9576e80d6851 (5) c_CD0 - |/ / rewritten(meta, parent, content) as 4535d0af405c using rewind by test (Thu Jan 01 00:00:02 1970 +0000) + |/ / folded(meta, parent, content) as 4535d0af405c using rewind by test (Thu Jan 01 00:00:02 1970 +0000) | | rewritten(meta, parent) as 95d72d892df7 using rewind by test (Thu Jan 01 00:00:03 1970 +0000) | | | x a0316c4c5417 (4) c_CD0 - |/ rewritten(meta, content) as 4535d0af405c using rewind by test (Thu Jan 01 00:00:02 1970 +0000) + |/ folded(meta, content) as 4535d0af405c using rewind by test (Thu Jan 01 00:00:02 1970 +0000) | meta-changed(meta) as e76375de0bfc using rewind by test (Thu Jan 01 00:00:03 1970 +0000) | x 49fb7d900906 (3) c_CD0 @@ -706,8 +741,8 @@ $ cd .. -Test rewinding stack -==================== +Rewinding a stack +================= $ hg clone rewind-testing-base rewind-testing-stack updating to branch default @@ -717,15 +752,12 @@ Rewinding the top of the stack only ----------------------------------- -setup -````` - $ hg up 'desc("c_A0")' 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ echo AA >> A $ hg amend -m 'c_A1' 1 new orphan changesets - $ hg evolve --all --update + $ hg evolve --update move:[2] c_B0 atop:[3] c_A1 working directory is now at a65fceb2324a @@ -773,12 +805,16 @@ summary: c_ROOT -Actual rewind -````````````` +target selection + + $ hg rewind --hidden --to 'min(desc(c_B0))' --exact --dry-run + rewinding a65fceb2324a to 1 changesets: 7e594302a05d + +actual rewind $ hg rewind --hidden --to 'min(desc(c_B0))' --exact 1 new orphan changesets - rewinded to 1 changesets + rewound to 1 changesets (1 changesets obsoleted) working directory is now at ac979e0aac4e $ hg debugobsolete @@ -833,17 +869,18 @@ summary: c_ROOT -Testing default argument (and cleanup) -`````````````````````````````````````` +Testing the defaults +-------------------- -rewind with no argument should be equivalent to `--from .` +rewind with no arguments should be equivalent to `--from .` $ echo 'default-date = 4 0' >> $HGRCPATH - $ hg rewind --from '.' - rewinded to 1 changesets + $ hg rewind --dry-run + rewinding ac979e0aac4e to 1 changesets: a65fceb2324a + $ hg rewind + rewound to 1 changesets (1 changesets obsoleted) working directory is now at a5dd64adbb2a - $ echo 'default-date = 5 0' >> $HGRCPATH $ hg log -G @ changeset: 6:a5dd64adbb2a | tag: tip @@ -887,8 +924,17 @@ Automatically rewinding the full stack (with --to) -------------------------------------------------- +target selection + + $ hg rewind --hidden --to 'predecessors(.)' --dry-run + rewinding d952d1794ff6 to 1 changesets: 579f120ba918 + rewinding a5dd64adbb2a to 1 changesets: ac979e0aac4e + +actual rewind + + $ echo 'default-date = 5 0' >> $HGRCPATH $ hg rewind --hidden --to 'predecessors(.)' - rewinded to 2 changesets + rewound to 2 changesets (2 changesets obsoleted) working directory is now at 3f2d8862657d $ hg debugobsolete @@ -942,9 +988,17 @@ Automatically rewinding the full stack (with --from) ---------------------------------------------------- +target selection + + $ hg rewind --from '.' --dry-run + rewinding 9c28b7ed3951 to 1 changesets: d952d1794ff6 + rewinding 3f2d8862657d to 1 changesets: a5dd64adbb2a + +actual rewind + $ echo 'default-date = 6 0' >> $HGRCPATH - $ hg rewind --hidden --from '.' - rewinded to 2 changesets + $ hg rewind --from '.' + rewound to 2 changesets (2 changesets obsoleted) working directory is now at d36d6d267714 $ hg debugobsolete @@ -1029,7 +1083,7 @@ A B $ hg rewind --from . - rewinded to 1 changesets + rewound to 1 changesets (1 changesets obsoleted) working directory is now at 9d325190bd87 $ hg st --change . @@ -1083,7 +1137,7 @@ Clean wdir $ hg rewind --keep --to 'desc("initial")' --hidden - rewinded to 1 changesets + rewound to 1 changesets (1 changesets obsoleted) $ hg debugobsolete 30704102d912d9d35a3d51400c4c93ad1e8bc7f3 2ea5be2f87510c7d26d5866dec83b57a7d939c4a 0 (Thu Jan 01 00:00:06 1970 +0000) {'ef1': '9', 'operation': 'amend', 'user': 'test'} diff -r af0458d91d10 -r ee18173c54a2 tests/test-stabilize-conflict.t --- a/tests/test-stabilize-conflict.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-stabilize-conflict.t Sat Oct 31 18:37:12 2020 +0800 @@ -141,7 +141,7 @@ | date: Thu Jan 01 00:00:00 1970 +0000 | summary: babar count up to ten | - | @ changeset: 4:71c18f70c34f + | % changeset: 4:71c18f70c34f | | user: test | | date: Thu Jan 01 00:00:00 1970 +0000 | | instability: orphan @@ -234,7 +234,7 @@ | date: Thu Jan 01 00:00:00 1970 +0000 | summary: babar count up to ten | - | @ changeset: 6:1836b91c6c1d + | % changeset: 6:1836b91c6c1d | | user: test | | date: Thu Jan 01 00:00:00 1970 +0000 | | instability: orphan diff -r af0458d91d10 -r ee18173c54a2 tests/test-stablesort-branchpoint-criss-cross.t --- a/tests/test-stablesort-branchpoint-criss-cross.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-stablesort-branchpoint-criss-cross.t Sat Oct 31 18:37:12 2020 +0800 @@ -21,16 +21,6 @@ > done; > } - $ cat << EOF >> random_rev.py - > import random - > import sys - > - > loop = int(sys.argv[1]) - > var = int(sys.argv[2]) - > for x in range(loop): - > print(x + random.randint(0, var)) - > EOF - Check criss cross merge ======================= @@ -708,14 +698,14 @@ updating to branch default 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd crisscross_random - $ for x in `python ../random_rev.py 50 44`; do + $ for x in `"$PYTHON" "$TESTDIR/testlib/random-revs.py" 50 44`; do > # using python to benefit from the random seed > hg pull -r $x --quiet > done; $ hg pull --quiet $ hg showsort --rev 'all()' > ../crisscross.random.order - $ python "$RUNTESTDIR/md5sum.py" ../crisscross.*.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" ../crisscross.*.order d9aab0d1907d5cf64d205a8b9036e959 ../crisscross.random.order d9aab0d1907d5cf64d205a8b9036e959 ../crisscross.source.order $ diff -u ../crisscross.*.order diff -r af0458d91d10 -r ee18173c54a2 tests/test-stablesort-branchpoint.t --- a/tests/test-stablesort-branchpoint.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-stablesort-branchpoint.t Sat Oct 31 18:37:12 2020 +0800 @@ -23,16 +23,6 @@ > done; > } - $ cat << EOF >> random_rev.py - > import random - > import sys - > - > loop = int(sys.argv[1]) - > var = int(sys.argv[2]) - > for x in range(loop): - > print(x + random.randint(0, var)) - > EOF - Basic tests =========== (no criss cross merge) @@ -386,7 +376,7 @@ check the log output are different - $ python "$RUNTESTDIR/md5sum.py" *.log + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.log 55919ebc9c02f28070cf3255b1690f8c A.log c6244b76a60d0707767dc71780e544f3 B.log 4d8b08b8c50ecbdd2460a62e5852d84d C.log @@ -408,7 +398,7 @@ C D - $ python "$RUNTESTDIR/md5sum.py" *.all.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.all.order 0c6b2e6f15249c0359b0f93e28c5bd1c A.all.order 0c6b2e6f15249c0359b0f93e28c5bd1c B.all.order 0c6b2e6f15249c0359b0f93e28c5bd1c C.all.order @@ -420,7 +410,7 @@ > hg -R repo_$x showsort --rev 'b4594d867745' > ${x}.b4594d867745.order; > done - $ python "$RUNTESTDIR/md5sum.py" *.b4594d867745.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.b4594d867745.order 5c40900a22008f24eab8dfe2f30ad79f A.b4594d867745.order 5c40900a22008f24eab8dfe2f30ad79f B.b4594d867745.order 5c40900a22008f24eab8dfe2f30ad79f C.b4594d867745.order @@ -432,7 +422,7 @@ > hg -R repo_$x showsort --rev '1d8d22637c2d' > ${x}.1d8d22637c2d.order; > done - $ python "$RUNTESTDIR/md5sum.py" *.1d8d22637c2d.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.1d8d22637c2d.order 77dc20a6f86db9103df8edaae9ad2754 A.1d8d22637c2d.order 77dc20a6f86db9103df8edaae9ad2754 B.1d8d22637c2d.order 77dc20a6f86db9103df8edaae9ad2754 C.1d8d22637c2d.order @@ -444,7 +434,7 @@ > hg -R repo_$x showsort --rev 'e7d9710d9fc6+43227190fef8' > ${x}.non-heads.order; > done - $ python "$RUNTESTDIR/md5sum.py" *.non-heads.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 A.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 B.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 C.non-heads.order @@ -519,7 +509,7 @@ > hg -R repo_$x showsort --rev 'e7d9710d9fc6+43227190fef8' > ${x}.non-heads.order; > done - $ python "$RUNTESTDIR/md5sum.py" *.non-heads.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 A.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 B.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 C.non-heads.order @@ -667,13 +657,13 @@ updating to branch default 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd recursion_random - $ for x in `python ../random_rev.py 15 5`; do + $ for x in `"$PYTHON" "$TESTDIR/testlib/random-revs.py" 15 5`; do > # using python to benefit from the random seed > hg pull -r $x --quiet > done; $ hg pull --quiet $ hg showsort --rev 'all()' > ../multiple.random.order - $ python "$RUNTESTDIR/md5sum.py" ../multiple.*.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" ../multiple.*.order 6ff802a0a5f0a3ddd82b25f860238fbd ../multiple.random.order 6ff802a0a5f0a3ddd82b25f860238fbd ../multiple.source.order $ hg showsort --rev 'all()' diff -r af0458d91d10 -r ee18173c54a2 tests/test-stablesort-criss-cross.t --- a/tests/test-stablesort-criss-cross.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-stablesort-criss-cross.t Sat Oct 31 18:37:12 2020 +0800 @@ -21,16 +21,6 @@ > done; > } - $ cat << EOF >> random_rev.py - > import random - > import sys - > - > loop = int(sys.argv[1]) - > var = int(sys.argv[2]) - > for x in range(loop): - > print(x + random.randint(0, var)) - > EOF - Check criss cross merge ======================= @@ -820,14 +810,14 @@ updating to branch default 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd crisscross_random - $ for x in `python ../random_rev.py 50 44`; do + $ for x in `"$PYTHON" "$TESTDIR/testlib/random-revs.py" 50 44`; do > # using python to benefit from the random seed > hg pull -r $x --quiet > done; $ hg pull --quiet $ hg showsort --rev 'all()' > ../crisscross.random.order - $ python "$RUNTESTDIR/md5sum.py" ../crisscross.*.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" ../crisscross.*.order 0ace2b2a63ec70b3b63b661aaee69878 ../crisscross.random.order 0ace2b2a63ec70b3b63b661aaee69878 ../crisscross.source.order $ diff -u ../crisscross.*.order diff -r af0458d91d10 -r ee18173c54a2 tests/test-stablesort.t --- a/tests/test-stablesort.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-stablesort.t Sat Oct 31 18:37:12 2020 +0800 @@ -24,16 +24,6 @@ > done; > } - $ cat << EOF >> random_rev.py - > import random - > import sys - > - > loop = int(sys.argv[1]) - > var = int(sys.argv[2]) - > for x in range(loop): - > print(x + random.randint(0, var)) - > EOF - Basic tests =========== (no criss cross merge) @@ -459,7 +449,7 @@ check the log output are different - $ python "$RUNTESTDIR/md5sum.py" *.log + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.log 55919ebc9c02f28070cf3255b1690f8c A.log c6244b76a60d0707767dc71780e544f3 B.log 4d8b08b8c50ecbdd2460a62e5852d84d C.log @@ -481,7 +471,7 @@ C D - $ python "$RUNTESTDIR/md5sum.py" *.all.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.all.order 25e89e555b56ed9e7b51827d58073b77 A.all.order 25e89e555b56ed9e7b51827d58073b77 B.all.order 25e89e555b56ed9e7b51827d58073b77 C.all.order @@ -493,7 +483,7 @@ > hg -R repo_$x showsort --rev 'b4594d867745' > ${x}.b4594d867745.order; > done - $ python "$RUNTESTDIR/md5sum.py" *.b4594d867745.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.b4594d867745.order 5c40900a22008f24eab8dfe2f30ad79f A.b4594d867745.order 5c40900a22008f24eab8dfe2f30ad79f B.b4594d867745.order 5c40900a22008f24eab8dfe2f30ad79f C.b4594d867745.order @@ -507,17 +497,17 @@ > hg -R repo_$x showsorthead --rev '1d8d22637c2d' --limit 4 > ${x}.1d8d22637c2d.orderhead-4; > done - $ python "$RUNTESTDIR/md5sum.py" *.1d8d22637c2d.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.1d8d22637c2d.order 77dc20a6f86db9103df8edaae9ad2754 A.1d8d22637c2d.order 77dc20a6f86db9103df8edaae9ad2754 B.1d8d22637c2d.order 77dc20a6f86db9103df8edaae9ad2754 C.1d8d22637c2d.order 77dc20a6f86db9103df8edaae9ad2754 D.1d8d22637c2d.order - $ python "$RUNTESTDIR/md5sum.py" *.1d8d22637c2d.orderhead + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.1d8d22637c2d.orderhead 77dc20a6f86db9103df8edaae9ad2754 A.1d8d22637c2d.orderhead 77dc20a6f86db9103df8edaae9ad2754 B.1d8d22637c2d.orderhead 77dc20a6f86db9103df8edaae9ad2754 C.1d8d22637c2d.orderhead 77dc20a6f86db9103df8edaae9ad2754 D.1d8d22637c2d.orderhead - $ python "$RUNTESTDIR/md5sum.py" *.1d8d22637c2d.orderhead-4 + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.1d8d22637c2d.orderhead-4 ea12ffc0007e1b4b911d09dd478881f3 A.1d8d22637c2d.orderhead-4 ea12ffc0007e1b4b911d09dd478881f3 B.1d8d22637c2d.orderhead-4 ea12ffc0007e1b4b911d09dd478881f3 C.1d8d22637c2d.orderhead-4 @@ -531,12 +521,12 @@ > hg -R repo_$x showsorthead --rev 'e7d9710d9fc6+43227190fef8' --limit 6 > ${x}.non-heads.orderhead-6; > done - $ python "$RUNTESTDIR/md5sum.py" *.non-heads.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 A.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 B.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 C.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 D.non-heads.order - $ python "$RUNTESTDIR/md5sum.py" *.non-heads.orderhead + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.non-heads.orderhead 1e5ce05b507a058c5dac3d7de9ae8feb A.non-heads.orderhead 4b07febabfee9528aedcea156a7d7071 B.non-heads.orderhead 1e5ce05b507a058c5dac3d7de9ae8feb C.non-heads.orderhead @@ -613,7 +603,7 @@ > hg -R repo_$x showsort --rev '43227190fef8' > ${x}.non-head-B.orderhead; > done - $ python "$RUNTESTDIR/md5sum.py" *.non-heads.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 A.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 B.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 C.non-heads.order @@ -621,11 +611,11 @@ 94e0ea8cdade135dabde4ec5e9954329 E.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 F.non-heads.order 94e0ea8cdade135dabde4ec5e9954329 G.non-heads.order - $ python "$RUNTESTDIR/md5sum.py" *.non-head-A.orderhead + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.non-head-A.orderhead 1e5ce05b507a058c5dac3d7de9ae8feb E.non-head-A.orderhead 1e5ce05b507a058c5dac3d7de9ae8feb F.non-head-A.orderhead 1e5ce05b507a058c5dac3d7de9ae8feb G.non-head-A.orderhead - $ python "$RUNTESTDIR/md5sum.py" *.non-head-B.orderhead + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" *.non-head-B.orderhead 4b07febabfee9528aedcea156a7d7071 E.non-head-B.orderhead 4b07febabfee9528aedcea156a7d7071 F.non-head-B.orderhead 4b07febabfee9528aedcea156a7d7071 G.non-head-B.orderhead @@ -822,7 +812,7 @@ updating to branch default 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd recursion_random - $ for x in `python ../random_rev.py 15 5`; do + $ for x in `"$PYTHON" "$TESTDIR/testlib/random-revs.py" 15 5`; do > # using python to benefit from the random seed > hg pull -r $x --quiet > done; @@ -830,13 +820,13 @@ $ hg showsort --rev 'all()' > ../multiple.random.order $ hg showsorthead --rev '160a7a0adbf4' > ../160a7a0adbf4.random.orderhead $ hg showsorthead --rev '4bbfc6078919' > ../4bbfc6078919.random.orderhead - $ python "$RUNTESTDIR/md5sum.py" ../multiple.*.order + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" ../multiple.*.order 19b28a58af0311b99159f60944a57213 ../multiple.random.order 19b28a58af0311b99159f60944a57213 ../multiple.source.order - $ python "$RUNTESTDIR/md5sum.py" ../160a7a0adbf4.*.orderhead + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" ../160a7a0adbf4.*.orderhead 905b0bab9155f65ed2e220382b94e9b9 ../160a7a0adbf4.random.orderhead 905b0bab9155f65ed2e220382b94e9b9 ../160a7a0adbf4.source.orderhead - $ python "$RUNTESTDIR/md5sum.py" ../4bbfc6078919.*.orderhead + $ "$PYTHON" "$RUNTESTDIR/md5sum.py" ../4bbfc6078919.*.orderhead 3732305a333d59ec50b91db0f5ab696e ../4bbfc6078919.random.orderhead 3732305a333d59ec50b91db0f5ab696e ../4bbfc6078919.source.orderhead $ hg showsort --rev 'all()' diff -r af0458d91d10 -r ee18173c54a2 tests/test-topic-dest.t --- a/tests/test-topic-dest.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-topic-dest.t Sat Oct 31 18:37:12 2020 +0800 @@ -42,8 +42,10 @@ | o 0 () c_alpha - $ hg log -r 'ngtip(.)' - 3 () c_delta + $ hg log -G -r 'ngtip(.)' + o 3 () c_delta + | + ~ $ hg log -r 'default' 3 () c_delta diff -r af0458d91d10 -r ee18173c54a2 tests/test-topic-merge.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-topic-merge.t Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,175 @@ +========================================================== +Testing the ability to control merge behavior around topic +========================================================== + +Especially, we want to test mode allowing the creation of merge that will +eventually become "oedipus" merge. + + $ . "$TESTDIR/testlib/topic_setup.sh" + $ . "$TESTDIR/testlib/common.sh" + + + +Setup a test repository +======================= + + $ hg init test-repo + $ cd test-repo + $ mkcommit root + $ mkcommit default-1 + $ mkcommit default-2 + $ hg up 'desc("default-2")' + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg topic test-topic + marked working directory as topic: test-topic + $ mkcommit topic-1 + active topic 'test-topic' grew its first changeset + (see 'hg help topics' for more information) + $ mkcommit topic-2 + $ hg up null + 0 files updated, 0 files merged, 5 files removed, 0 files unresolved + $ hg log -G + o changeset: 4:c3ec1ef2bf00 + | tag: tip + | topic: test-topic + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: topic-2 + | + o changeset: 3:3300cececc85 + | topic: test-topic + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: topic-1 + | + o changeset: 2:b05d997f9ab0 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: default-2 + | + o changeset: 1:ccab697ce421 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: default-1 + | + o changeset: 0:1e4be0697311 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: root + + +Test that the merge is rejected by default +========================================== + +from the topic + + $ hg up test-topic + switching to topic test-topic + 5 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge default + abort: merging with a working directory ancestor has no effect + [255] + +from the bare branch + + $ hg up default + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg merge test-topic + abort: nothing to merge + (use 'hg update' or check 'hg heads') + [255] + +Test that the merge is rejected if set to reject +================================================ + +Actually, this also work with any unvalid value, but: + +- the default value might change in the future, +- this make sure we read the config right. + +Same result when setting the config to be strict + + $ cat >> .hg/hgrc << EOF + > [experimental] + > topic.linear-merge = reject + > EOF + +from the topic + + $ hg up test-topic + switching to topic test-topic + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge default + abort: merging with a working directory ancestor has no effect + [255] + +from the bare branch + + $ hg up default + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg merge test-topic + abort: nothing to merge + (use 'hg update' or check 'hg heads') + [255] + +Test that the merge is accepted if configured to allow them +=========================================================== + + $ cat >> .hg/hgrc << EOF + > [experimental] + > topic.linear-merge = allow-from-bare-branch + > EOF + +from the topic, this is rejected since the resulting merge would be in the topic itself + + $ hg up test-topic + switching to topic test-topic + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge default + abort: merging with a working directory ancestor has no effect + [255] + +from the bare branch this is allowed since the resulting merge will be in the branch + + $ hg up default + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg merge test-topic --traceback + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m "How dreadful the knowledge of the truth can be when there's no help in truth." + $ hg log -G + @ changeset: 5:42ca2e8cb810 + |\ tag: tip + | | parent: 2:b05d997f9ab0 + | | parent: 4:c3ec1ef2bf00 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: How dreadful the knowledge of the truth can be when there's no help in truth. + | | + | o changeset: 4:c3ec1ef2bf00 + | | topic: test-topic + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: topic-2 + | | + | o changeset: 3:3300cececc85 + |/ topic: test-topic + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: topic-1 + | + o changeset: 2:b05d997f9ab0 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: default-2 + | + o changeset: 1:ccab697ce421 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: default-1 + | + o changeset: 0:1e4be0697311 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: root + diff -r af0458d91d10 -r ee18173c54a2 tests/test-topic-push-concurrent-on.t --- a/tests/test-topic-push-concurrent-on.t Sun Sep 06 05:38:24 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,432 +0,0 @@ -# same as test-topic-push but with the concurrent push feature on - - $ . "$TESTDIR/testlib/topic_setup.sh" - - $ cat << EOF >> $HGRCPATH - > [ui] - > logtemplate = {rev} {branch} {get(namespaces, "topics")} {phase} {desc|firstline}\n - > ssh = "$PYTHON" "$RUNTESTDIR/dummyssh" - > [server] - > concurrent-push-mode=check-related - > EOF - - $ hg init main - $ hg init draft - $ cat << EOF >> draft/.hg/hgrc - > [phases] - > publish=False - > EOF - $ hg clone main client - updating to branch default - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cat << EOF >> client/.hg/hgrc - > [paths] - > draft=../draft - > EOF - - -Testing core behavior to make sure we did not break anything -============================================================ - -Pushing a first changeset - - $ cd client - $ echo aaa > aaa - $ hg add aaa - $ hg commit -m 'CA' - $ hg outgoing -G - comparing with $TESTTMP/main (glob) - searching for changes - @ 0 default draft CA - - $ hg push - pushing to $TESTTMP/main (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files - -Pushing two heads - - $ echo aaa > bbb - $ hg add bbb - $ hg commit -m 'CB' - $ echo aaa > ccc - $ hg up 'desc(CA)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg add ccc - $ hg commit -m 'CC' - created new head - (consider using topic for lightweight branches. See 'hg help topic') - $ hg outgoing -G - comparing with $TESTTMP/main (glob) - searching for changes - @ 2 default draft CC - - o 1 default draft CB - - $ hg push - pushing to $TESTTMP/main (glob) - searching for changes - abort: push creates new remote head 9fe81b7f425d! - (merge or see 'hg help push' for details about pushing new heads) - [255] - $ hg outgoing -r 'desc(CB)' -G - comparing with $TESTTMP/main (glob) - searching for changes - o 1 default draft CB - - $ hg push -r 'desc(CB)' - pushing to $TESTTMP/main (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files - -Pushing a new branch - - $ hg branch mountain - marked working directory as branch mountain - (branches are permanent and global, did you want a bookmark?) - $ hg commit --amend - $ hg outgoing -G - comparing with $TESTTMP/main (glob) - searching for changes - @ 3 mountain draft CC - - $ hg push - pushing to $TESTTMP/main (glob) - searching for changes - abort: push creates new remote branches: mountain! - (use 'hg push --new-branch' to create new remote branches) - [255] - $ hg push --new-branch - pushing to $TESTTMP/main (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files (+1 heads) - 1 new obsolescence markers - -Including on non-publishing - - $ hg push --new-branch draft - pushing to $TESTTMP/draft (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 3 changesets with 3 changes to 3 files (+1 heads) - 1 new obsolescence markers - -Testing topic behavior -====================== - -Local peer tests ----------------- - - $ hg up -r 'desc(CA)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg topic babar - marked working directory as topic: babar - $ echo aaa > ddd - $ hg add ddd - $ hg commit -m 'CD' - active topic 'babar' grew its first changeset - (see 'hg help topics' for more information) - $ hg log -G # keep track of phase because I saw some strange bug during developement - @ 4 default babar draft CD - | - | o 3 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Pushing a new topic to a non publishing server should not be seen as a new head - - $ hg push draft - pushing to $TESTTMP/draft (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files (+1 heads) - $ hg log -G - @ 4 default babar draft CD - | - | o 3 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Pushing a new topic to a publishing server should be seen as a new head - - $ hg push - pushing to $TESTTMP/main (glob) - searching for changes - abort: push creates new remote head 67f579af159d! - (merge or see 'hg help push' for details about pushing new heads) - [255] - $ hg log -G - @ 4 default babar draft CD - | - | o 3 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -wireprotocol tests ------------------- - - $ hg up -r 'desc(CA)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg topic celeste - marked working directory as topic: celeste - $ echo aaa > eee - $ hg add eee - $ hg commit -m 'CE' - active topic 'celeste' grew its first changeset - (see 'hg help topics' for more information) - $ hg log -G # keep track of phase because I saw some strange bug during developement - @ 5 default celeste draft CE - | - | o 4 default babar draft CD - |/ - | o 3 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Pushing a new topic to a non publishing server without topic -> new head - - $ cat << EOF >> ../draft/.hg/hgrc - > [extensions] - > topic=! - > EOF - $ hg push ssh://user@dummy/draft - pushing to ssh://user@dummy/draft - searching for changes - abort: push creates new remote head 84eaf32db6c3! - (merge or see 'hg help push' for details about pushing new heads) - [255] - $ hg log -G - @ 5 default celeste draft CE - | - | o 4 default babar draft CD - |/ - | o 3 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Pushing a new topic to a non publishing server should not be seen as a new head - - $ printf "topic=" >> ../draft/.hg/hgrc - $ hg config extensions.topic >> ../draft/.hg/hgrc - $ hg push ssh://user@dummy/draft - pushing to ssh://user@dummy/draft - searching for changes - remote: adding changesets - remote: adding manifests - remote: adding file changes - remote: added 1 changesets with 1 changes to 1 files (+1 heads) - $ hg log -G - @ 5 default celeste draft CE - | - | o 4 default babar draft CD - |/ - | o 3 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Pushing a new topic to a publishing server should be seen as a new head - - $ hg push ssh://user@dummy/main - pushing to ssh://user@dummy/main - searching for changes - abort: push creates new remote head 67f579af159d! - (merge or see 'hg help push' for details about pushing new heads) - [255] - $ hg log -G - @ 5 default celeste draft CE - | - | o 4 default babar draft CD - |/ - | o 3 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Check that we reject multiple head on the same topic ----------------------------------------------------- - - $ hg up 'desc(CB)' - 1 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg topic babar - marked working directory as topic: babar - $ echo aaa > fff - $ hg add fff - $ hg commit -m 'CF' - $ hg log -G - @ 6 default babar draft CF - | - | o 5 default celeste draft CE - | | - | | o 4 default babar draft CD - | |/ - | | o 3 mountain public CC - | |/ - o | 1 default public CB - |/ - o 0 default public CA - - - $ hg push draft - pushing to $TESTTMP/draft (glob) - searching for changes - abort: push creates new remote head f0bc62a661be on branch 'default:babar'! - (merge or see 'hg help push' for details about pushing new heads) - [255] - -Multiple head on a branch merged in a topic changesets ------------------------------------------------------------------------- - - - $ hg up 'desc(CA)' - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ echo aaa > ggg - $ hg add ggg - $ hg commit -m 'CG' - created new head - (consider using topic for lightweight branches. See 'hg help topic') - $ hg up 'desc(CF)' - switching to topic babar - 2 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg merge 'desc(CG)' - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - (branch merge, don't forget to commit) - $ hg commit -m 'CM' - $ hg log -G - @ 8 default babar draft CM - |\ - | o 7 default draft CG - | | - o | 6 default babar draft CF - | | - | | o 5 default celeste draft CE - | |/ - | | o 4 default babar draft CD - | |/ - | | o 3 mountain public CC - | |/ - o | 1 default public CB - |/ - o 0 default public CA - - -Reject when pushing to draft - - $ hg push draft -r . - pushing to $TESTTMP/draft (glob) - searching for changes - abort: push creates new remote head 4937c4cad39e! - (merge or see 'hg help push' for details about pushing new heads) - [255] - - -Reject when pushing to publishing - - $ hg push -r . - pushing to $TESTTMP/main (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 3 changesets with 2 changes to 2 files - - $ cd .. - -Test phase move -================================== - -setup, two repo knowns about two small topic branch - - $ hg init repoA - $ hg clone repoA repoB - updating to branch default - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cat << EOF >> repoA/.hg/hgrc - > [phases] - > publish=False - > EOF - $ cat << EOF >> repoB/.hg/hgrc - > [phases] - > publish=False - > EOF - $ cd repoA - $ echo aaa > base - $ hg add base - $ hg commit -m 'CBASE' - $ echo aaa > aaa - $ hg add aaa - $ hg topic topicA - marked working directory as topic: topicA - $ hg commit -m 'CA' - active topic 'topicA' grew its first changeset - (see 'hg help topics' for more information) - $ hg up 'desc(CBASE)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ echo aaa > bbb - $ hg add bbb - $ hg topic topicB - marked working directory as topic: topicB - $ hg commit -m 'CB' - active topic 'topicB' grew its first changeset - (see 'hg help topics' for more information) - $ cd .. - $ hg push -R repoA repoB - pushing to repoB - searching for changes - adding changesets - adding manifests - adding file changes - added 3 changesets with 3 changes to 3 files (+1 heads) - $ hg log -G -R repoA - @ 2 default topicB draft CB - | - | o 1 default topicA draft CA - |/ - o 0 default draft CBASE - - -We turn different topic to public on each side, - - $ hg -R repoA phase --public topicA - $ hg -R repoB phase --public topicB - -Pushing should complain because it create to heads on default - - $ hg push -R repoA repoB - pushing to repoB - searching for changes - no changes found - abort: push create a new head on branch "default" - [255] diff -r af0458d91d10 -r ee18173c54a2 tests/test-topic-push.t --- a/tests/test-topic-push.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-topic-push.t Sat Oct 31 18:37:12 2020 +0800 @@ -1,3 +1,5 @@ +#testcases concurrent-strict concurrent-check-related + $ . "$TESTDIR/testlib/topic_setup.sh" $ cat << EOF >> $HGRCPATH @@ -6,18 +8,32 @@ > ssh = "$PYTHON" "$RUNTESTDIR/dummyssh" > EOF +#if concurrent-strict + $ cat << EOF >> $HGRCPATH + > [server] + > concurrent-push-mode = strict + > EOF +#endif + +#if concurrent-check-related + $ cat << EOF >> $HGRCPATH + > [server] + > concurrent-push-mode = check-related + > EOF +#endif + $ hg init main $ hg init draft $ cat << EOF >> draft/.hg/hgrc > [phases] - > publish=False + > publish = no > EOF $ hg clone main client updating to branch default 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cat << EOF >> client/.hg/hgrc > [paths] - > draft=../draft + > draft = ../draft > EOF @@ -92,7 +108,7 @@ searching for changes @ 3 mountain draft CC - $ hg push + $ hg push pushing to $TESTTMP/main (glob) searching for changes abort: push creates new remote branches: mountain! @@ -279,7 +295,7 @@ $ cat << EOF >> ../draft/.hg/hgrc > [extensions] - > topic=! + > topic = ! > EOF $ hg push ssh://user@dummy/draft pushing to ssh://user@dummy/draft @@ -301,8 +317,7 @@ Pushing a new topic to a non publishing server should not be seen as a new head - $ printf "topic=" >> ../draft/.hg/hgrc - $ hg config extensions.topic >> ../draft/.hg/hgrc + $ echo 'topic =' >> ../draft/.hg/hgrc $ hg push ssh://user@dummy/draft pushing to ssh://user@dummy/draft searching for changes @@ -342,8 +357,8 @@ o 0 default public CA -Check that we reject multiple head on the same topic ----------------------------------------------------- +Check that we reject multiple heads on the same topic +----------------------------------------------------- $ hg up 'desc(CB)' 1 files updated, 0 files merged, 1 files removed, 0 files unresolved @@ -373,9 +388,8 @@ (merge or see 'hg help push' for details about pushing new heads) [255] -Multiple head on a branch merged in a topic changesets ------------------------------------------------------------------------- - +Multiple heads on a branch merged into a topic branch +----------------------------------------------------- $ hg up 'desc(CA)' 0 files updated, 0 files merged, 2 files removed, 0 files unresolved @@ -418,7 +432,6 @@ (merge or see 'hg help push' for details about pushing new heads) [255] - Reject when pushing to publishing $ hg push -r . @@ -432,9 +445,9 @@ $ cd .. Test phase move -================================== +=============== -setup, two repo knowns about two small topic branch +setup, two repos have two small topic branches $ hg init repoA $ hg clone repoA repoB @@ -442,11 +455,11 @@ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cat << EOF >> repoA/.hg/hgrc > [phases] - > publish=False + > publish = no > EOF $ cat << EOF >> repoB/.hg/hgrc > [phases] - > publish=False + > publish = no > EOF $ cd repoA $ echo aaa > base @@ -484,16 +497,16 @@ o 0 default draft CBASE -We turn different topic to public on each side, +We turn a different topic to public on each side, $ hg -R repoA phase --public topicA $ hg -R repoB phase --public topicB -Pushing should complain because it create to heads on default +Pushing should complain because it would create two heads on default $ hg push -R repoA repoB pushing to repoB searching for changes no changes found - abort: push create a new head on branch "default" + abort: push creates new heads on branch 'default': bbd9d6199b88 [255] diff -r af0458d91d10 -r ee18173c54a2 tests/test-topic-shell-prompt.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-topic-shell-prompt.t Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,29 @@ + $ . $TESTDIR/testlib/topic_setup.sh + +Code logically equivalent to the following is used in Zsh to show the branch +and topic (if set) in the prompt. If the format of the files is changed in a +way that it breaks the test, a mail should be sent to zsh-workers@zsh.org. + + $ get_branch_like_zsh() { + > branchfile=".hg/branch" + > topicfile=".hg/topic" + > if [ -r "${branchfile}" ] ; then + > r_branch=$(cat "${branchfile}") + > fi + > if [ -f "${topicfile}" ] && [ -r "${topicfile}" ] && [ -s "${topicfile}" ] ; then + > IFS= read -r REPLY < ${topicfile} + > r_branch=${r_branch}:${REPLY} + > fi + > echo $r_branch + > } + + $ hg init + $ hg branch branch -q + $ get_branch_like_zsh + branch + $ hg topic topic -q + $ get_branch_like_zsh + branch:topic + $ hg topic --clear -q + $ get_branch_like_zsh + branch diff -r af0458d91d10 -r ee18173c54a2 tests/test-topic-stack.t --- a/tests/test-topic-stack.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-topic-stack.t Sat Oct 31 18:37:12 2020 +0800 @@ -104,7 +104,7 @@ s2(e629654d7050): c_d s1(8522f9e3fee9): c_c s0(ea705abc4f51)^ c_b (base) - $ hg stack -Tjson | python -m json.tool + $ hg stack -Tjson | "$PYTHON" -m json.tool [ { "desc": "c_f", @@ -157,7 +157,7 @@ "symbol": "^" } ] - $ hg stack -v -Tjson | python -m json.tool + $ hg stack -v -Tjson | "$PYTHON" -m json.tool [ { "desc": "c_f", @@ -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 af0458d91d10 -r ee18173c54a2 tests/test-topic-tutorial.t --- a/tests/test-topic-tutorial.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-topic-tutorial.t Sat Oct 31 18:37:12 2020 +0800 @@ -332,6 +332,7 @@ penwidth=2.0]; } #endif + And updating back to the topic reactivates it: $ hg update food @@ -1516,6 +1517,7 @@ penwidth=2.0]; } #endif + Multi-headed stack ------------------ diff -r af0458d91d10 -r ee18173c54a2 tests/test-topic.t --- a/tests/test-topic.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-topic.t Sat Oct 31 18:37:12 2020 +0800 @@ -134,6 +134,36 @@ [experimental] topic.server-gate-topic-changesets = yes + Explicitly merging in the target branch + ======================================= + + By default, Mercurial will not let your merge a topic into its target branch + if that topic is already based on the head of that branch. In other word, + Mercurial will not let your create a merge that will eventually have two + parents in the same branches, one parent being the ancestors of the other + parent. This behavior can be lifted using the following config: + + [experimental] + topic.linear-merge = allow-from-bare-branch + + When this option is set to 'allow-from-bare-branch', it is possible to merge a + topic branch from a bare branch (commit an active topic (eg: public one)) + regardless of the topology. The result would typically looks like that: + + @ summary: resulting merge commit + |\ branch: my-branch + | | + | o summary: some more change in a topic, the merge "target" + | | branch: my-branch + | | topic: my-topic + | | + | o summary: some change in a topic + |/ branch: my-branch + | topic: my-topic + | + o summary: previous head of the branch, the merge "source" + | branch: my-branch + list of commands: Change organization: @@ -200,8 +230,13 @@ Test topics interaction with evolution: - $ hg topics --config experimental.evolution= - $ hg topics --config experimental.evolution= --rev . bob + $ hg topics --config experimental.evolution= \ + > --config experimental.evolution.createmarkers=0 \ + > --config experimental.evolution.exchange=0 + $ hg topics --config experimental.evolution= \ + > --config experimental.evolution.createmarkers=0 \ + > --config experimental.evolution.exchange=0 \ + > --rev . bob abort: must have obsolete enabled to change topics [255] @@ -923,6 +958,10 @@ ^ 3 s1: 0 + $ tlog 'tip#s' + 0: + 4: + $ tlog 'tip#stack[0]' $ tlog 'tip#stack[1]' 0: @@ -941,6 +980,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]' @@ -991,6 +1035,7 @@ ### target: default (branch) (stack is empty) s0^ 4 (base current) + $ tlog 'wdir()#s' $ tlog 'wdir()#s[0]' 4: diff -r af0458d91d10 -r ee18173c54a2 tests/test-unstability-resolution-result.t --- a/tests/test-unstability-resolution-result.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-unstability-resolution-result.t Sat Oct 31 18:37:12 2020 +0800 @@ -66,10 +66,9 @@ Test evolve of orphan that run into conflict - $ ls -A - .hg - a - b + $ hg status -A + C a + C b $ hg pdiff a diff -r 07f494440405 a --- a/a Thu Jan 01 00:00:00 1970 +0000 diff -r af0458d91d10 -r ee18173c54a2 tests/test-wireproto.t --- a/tests/test-wireproto.t Sun Sep 06 05:38:24 2020 +0800 +++ b/tests/test-wireproto.t Sat Oct 31 18:37:12 2020 +0800 @@ -194,8 +194,9 @@ $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log --config experimental.evolution.obsdiscovery=no $ cat hg.pid >> $DAEMON_PIDS - $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshashrange_v1 batch branchmap bundle2=HG20%0Abookmarks%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Aobsmarkers%3DV0%2CV1%0Aphases%3Dheads%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps%0Arev-branch-cache%0Astream%3Dv2 changegroupsubset compression=*zlib getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-eol) (glob) + $ hg debugcapabilities http://localhost:$HGPORT | grep _evoext + _evoext_getbundle_obscommon + _evoext_obshashrange_v1 Check we cannot use pushkey for marker exchange anymore diff -r af0458d91d10 -r ee18173c54a2 tests/testlib/check-compat-strings.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/testlib/check-compat-strings.py Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,62 @@ +#!/usr/bin/env python +""" +This script finds compatibility-related comments with a node hash specified +in all files in a given directory (. by default) and looks up the hash in a +repo (~/hg by default) to determine if each of the comments is correct and, +if not, it suggests the correct release. This can prevent accidentally +removing a piece of code that was misattributed to a different (earlier) +release of core hg. + +Usage: $0 WDIR HGREPO where WDIR is usually evolve/hgext3rd/ and HGREPO is +the place with core Mercurial repo (not just checkout). Said repo has to be +sufficiently up-to-date, otherwise this script may not work correctly. +""" + +from __future__ import print_function + +import argparse +import os +import re +from subprocess import check_output + +def grepall(workdir, linere): + for root, dirs, files in os.walk(workdir): + for fname in files: + if not fname.endswith('.py'): + continue + path = os.path.join(root, fname) + with open(path, 'r') as src: + for lineno, line in enumerate(src, 1): + for groups in linere.findall(line): + yield path, lineno, line, groups + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument('workdir', nargs='?', default='.') + ap.add_argument('hgdir', nargs='?', default=os.path.expanduser('~/hg')) + + opts = ap.parse_args() + + linere = re.compile(r'hg <= ([0-9.]+) \(([0-9a-f+]+)\)') + basecmd = ['hg', '--cwd', opts.hgdir, 'log', '-T', '{tags}'] + hgenv = {'HGPLAIN': '1', 'HGENCODING': 'UTF-8'} + relcache = {} + + for path, lineno, line, match in grepall(opts.workdir, linere): + expected, revset = match + + if revset not in relcache: + tagrevset = 'max(tag("re:^[0-9]\\.[0-9]$") - (%s)::)' % revset + cmd = basecmd + ['-r', tagrevset] + relcache[revset] = check_output(cmd, env=hgenv).decode('UTF-8') + + lastrel = relcache[revset] + + if lastrel != expected: + print('%s:%d:%s' % (path, lineno, line.rstrip('\r\n'))) + print('\\ actual last major release without %s is %s' + % (revset, lastrel)) + print() + +if __name__ == '__main__': + main() diff -r af0458d91d10 -r ee18173c54a2 tests/testlib/check-compat-strings.sh --- a/tests/testlib/check-compat-strings.sh Sun Sep 06 05:38:24 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -unset GREP_OPTIONS - -# This script finds compatibility-related comments with a node hash specified -# in all files in a given directory (. by default) and looks up the hash in a -# repo (~/hg by default) to determine if each of the comments is correct and, -# if not, it suggests the correct release. This can prevent accidentally -# removing a piece of code that was misattributed to a different (earlier) -# release of core hg. - -# Usage: $0 WDIR HGREPO where WDIR is usually evolve/hgext3rd/ and HGREPO is -# the place with core Mercurial repo (not just checkout). Said repo has to be -# sufficiently up-to-date, otherwise this script may not work correctly. - -workdir=${1:-'.'} -hgdir=${2:-~/hg} -grep -Ern 'hg <= [0-9.]+ \([0-9a-f+]+\)' "$workdir" | while read -r line; do - bashre='hg <= ([0-9.]+) \(([0-9a-f+]+)\)' - if [[ $line =~ $bashre ]]; then - expected=${BASH_REMATCH[1]} - revset=${BASH_REMATCH[2]} - tagrevset="max(tag('re:^[0-9]\\.[0-9]$') - ($revset)::)" - lastrel=$(HGPLAIN=1 hg --cwd "$hgdir" log -r "$tagrevset" -T '{tags}') - if [[ "$lastrel" != "$expected" ]]; then - echo "$line" - echo "actual last major release without $revset is $lastrel" - echo - fi - fi -done diff -r af0458d91d10 -r ee18173c54a2 tests/testlib/check-min-versions.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/testlib/check-min-versions.py Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,101 @@ +#!/usr/bin/env python +""" +This script takes `minimumhgversion` and `testedwith` values from the first +file (e.g. hgext3rd/evolve/metadata.py) and mercurial package versions from the +second file (e.g. debian/control) and compares them using a set of rules to +find any issues. + +Rules: + + - if `minimumhgversion` is a feature release, the first version from + `testedwith` should belong to that feature release + + - if `minimumhgversion` is a bugfix release, the first version from + `testedwith` should be the same + + - mercurial package versions (from both Depends and Build-Depends sections) + should match `minimumhgversion` + +Usage: $0 MFILE CFILE where MFILE contains extension metadata and CFILE is a +debian/control file. +""" + +from __future__ import print_function + +import argparse +import os +import re + +def grepall(workdir, linere): + for root, dirs, files in os.walk(workdir): + for fname in files: + if not fname.endswith('.py'): + continue + path = os.path.join(root, fname) + with open(path, 'r') as src: + for line in src: + for groups in linere.findall(line): + yield path, groups + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument('mfile', help='.py file with `testedwith`') + ap.add_argument('cfile', help='debian/control file') + + opts = ap.parse_args() + + mre = re.compile(r"^minimumhgversion = b'([0-9.]+)'") + mtre = re.compile(r"^testedwith = b'([0-9.]+) ") + minversion = '' + mintestedversion = '' + + with open(opts.mfile, 'r') as src: + for line in src: + if not minversion: + groups = mre.findall(line) + if groups: + minversion = groups[0] + if not mintestedversion: + groups = mtre.findall(line) + if groups: + mintestedversion = groups[0] + + if not minversion: + print('could not find `minimumhgversion` variable in %s' % opts.mfile) + + if not mintestedversion: + print('could not find `testedwith` variable in %s' % opts.mfile) + + if minversion.count('.') > 1: + # `minversion` is a bugfix release + if minversion != mintestedversion: + print('`minimumhgversion` is a bugfix release, the first version ' + 'in `testedwith` should be the same: %s and %s' + % (minversion, mintestedversion)) + + else: + # matching X.Y to determine the "feature release" version + frelre = re.compile(r"([0-9]+).([0-9]+)") + + if frelre.findall(minversion) != frelre.findall(mintestedversion): + print('the first version in `testedwith` does not belong to the ' + 'same feature release as `minimumhgversion`: %s and %s' + % (mintestedversion, minversion)) + + cre = re.compile(r"^ mercurial \(>= ([0-9.]+)\)") + depversion = '' + + with open(opts.cfile, 'r') as src: + for line in src: + groups = cre.findall(line) + if groups: + depversion = groups[0] + if minversion != depversion: + print('versions differ: %s from `minimumhgversion`, %s ' + 'from dependencies' % (minversion, depversion)) + + if not depversion: + print('could not find dependency on mercurial in %s' % opts.cfile) + +if __name__ == '__main__': + main() diff -r af0458d91d10 -r ee18173c54a2 tests/testlib/content-divergence-util.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/testlib/content-divergence-util.sh Sat Oct 31 18:37:12 2020 +0800 @@ -0,0 +1,36 @@ +#!/bin/sh +# setup config and various utility to test content-divergence resolution + +. $TESTDIR/testlib/common.sh + +cat >> $HGRCPATH <> $HGRCPATH << EOF [experimental] -evolution=createmarkers,exchange +evolution.createmarkers=true +evolution.exchange=true [extensions] rebase=