Mercurial > hg
changeset 46030:2cf61e66c6d0
merge with stable
author | Augie Fackler <augie@google.com> |
---|---|
date | Thu, 03 Dec 2020 14:15:39 -0500 |
parents | 8b0a3ff5ed12 (diff) dadbd01f9393 (current diff) |
children | c701f616d852 |
files | hgext/rebase.py mercurial/debugcommands.py mercurial/extensions.py mercurial/patch.py mercurial/ui.py mercurial/utils/procutil.py rust/hgcli/pyoxidizer.bzl tests/test-rebase-inmemory.t |
diffstat | 635 files changed, 12246 insertions(+), 7217 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Thu Dec 03 13:36:24 2020 -0500 +++ b/.hgignore Thu Dec 03 14:15:39 2020 -0500 @@ -49,6 +49,7 @@ .DS_Store tags cscope.* +.vscode/* .idea/* .asv/* .pytype/*
--- a/Makefile Thu Dec 03 13:36:24 2020 -0500 +++ b/Makefile Thu Dec 03 14:15:39 2020 -0500 @@ -5,7 +5,18 @@ # % make PREFIX=/opt/ install export PREFIX=/usr/local -PYTHON?=python + +# Default to Python 3. +# +# Windows ships Python 3 as `python.exe`, which may not be on PATH. py.exe is. +ifeq ($(OS),Windows_NT) +PYTHON?=py -3 +else +PYTHON?=python3 +endif + +PYOXIDIZER?=pyoxidizer + $(eval HGROOT := $(shell pwd)) HGPYTHONS ?= $(HGROOT)/build/pythons PURE= @@ -181,27 +192,21 @@ # Packaging targets packaging_targets := \ - centos5 \ - centos6 \ centos7 \ centos8 \ deb \ - docker-centos5 \ - docker-centos6 \ docker-centos7 \ docker-centos8 \ docker-debian-bullseye \ docker-debian-buster \ docker-debian-stretch \ docker-fedora \ - docker-ubuntu-trusty \ - docker-ubuntu-trusty-ppa \ docker-ubuntu-xenial \ docker-ubuntu-xenial-ppa \ - docker-ubuntu-artful \ - docker-ubuntu-artful-ppa \ docker-ubuntu-bionic \ docker-ubuntu-bionic-ppa \ + docker-ubuntu-focal \ + docker-ubuntu-focal-ppa \ fedora \ linux-wheels \ linux-wheels-x86_64 \ @@ -250,9 +255,12 @@ --resources contrib/packaging/macosx/ \ "$${OUTPUTDIR:-dist/}"/Mercurial-"$${HGVER}"-macosx"$${OSXVER}".pkg +pyoxidizer: + $(PYOXIDIZER) build --path ./rust/hgcli --release + .PHONY: help all local build doc cleanbutpackages clean install install-bin \ install-doc install-home install-home-bin install-home-doc \ dist dist-notests check tests rust-tests check-code format-c \ - update-pot \ + update-pot pyoxidizer \ $(packaging_targets) \ osx
--- a/contrib/automation/hgautomation/aws.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/automation/hgautomation/aws.py Thu Dec 03 14:15:39 2020 -0500 @@ -152,7 +152,11 @@ IAM_INSTANCE_PROFILES = { - 'ephemeral-ec2-1': {'roles': ['ephemeral-ec2-role-1',],} + 'ephemeral-ec2-1': { + 'roles': [ + 'ephemeral-ec2-role-1', + ], + } } @@ -469,10 +473,22 @@ images = ec2resource.images.filter( Filters=[ - {'Name': 'owner-id', 'Values': [owner_id],}, - {'Name': 'state', 'Values': ['available'],}, - {'Name': 'image-type', 'Values': ['machine'],}, - {'Name': 'name', 'Values': [name],}, + { + 'Name': 'owner-id', + 'Values': [owner_id], + }, + { + 'Name': 'state', + 'Values': ['available'], + }, + { + 'Name': 'image-type', + 'Values': ['machine'], + }, + { + 'Name': 'name', + 'Values': [name], + }, ] ) @@ -519,10 +535,13 @@ print('adding security group %s' % actual) group_res = ec2resource.create_security_group( - Description=group['description'], GroupName=actual, + Description=group['description'], + GroupName=actual, ) - group_res.authorize_ingress(IpPermissions=group['ingress'],) + group_res.authorize_ingress( + IpPermissions=group['ingress'], + ) security_groups[name] = group_res @@ -614,7 +633,10 @@ while True: res = ssmclient.describe_instance_information( Filters=[ - {'Key': 'InstanceIds', 'Values': [i.id for i in instances],}, + { + 'Key': 'InstanceIds', + 'Values': [i.id for i in instances], + }, ], ) @@ -636,7 +658,9 @@ InstanceIds=[i.id for i in instances], DocumentName=document_name, Parameters=parameters, - CloudWatchOutputConfig={'CloudWatchOutputEnabled': True,}, + CloudWatchOutputConfig={ + 'CloudWatchOutputEnabled': True, + }, ) command_id = res['Command']['CommandId'] @@ -645,7 +669,8 @@ while True: try: res = ssmclient.get_command_invocation( - CommandId=command_id, InstanceId=instance.id, + CommandId=command_id, + InstanceId=instance.id, ) except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == 'InvocationDoesNotExist': @@ -799,19 +824,32 @@ instance.stop() ec2client.get_waiter('instance_stopped').wait( - InstanceIds=[instance.id], WaiterConfig={'Delay': 5,} + InstanceIds=[instance.id], + WaiterConfig={ + 'Delay': 5, + }, ) print('%s is stopped' % instance.id) - image = instance.create_image(Name=name, Description=description,) + image = instance.create_image( + Name=name, + Description=description, + ) image.create_tags( - Tags=[{'Key': 'HGIMAGEFINGERPRINT', 'Value': fingerprint,},] + Tags=[ + { + 'Key': 'HGIMAGEFINGERPRINT', + 'Value': fingerprint, + }, + ] ) print('waiting for image %s' % image.id) - ec2client.get_waiter('image_available').wait(ImageIds=[image.id],) + ec2client.get_waiter('image_available').wait( + ImageIds=[image.id], + ) print('image %s available as %s' % (image.id, image.name)) @@ -837,7 +875,9 @@ ssh_username = 'admin' elif distro == 'debian10': image = find_image( - ec2resource, DEBIAN_ACCOUNT_ID_2, 'debian-10-amd64-20190909-10', + ec2resource, + DEBIAN_ACCOUNT_ID_2, + 'debian-10-amd64-20190909-10', ) ssh_username = 'admin' elif distro == 'ubuntu18.04': @@ -1066,7 +1106,9 @@ def ensure_windows_dev_ami( - c: AWSConnection, prefix='hg-', base_image_name=WINDOWS_BASE_IMAGE_NAME, + c: AWSConnection, + prefix='hg-', + base_image_name=WINDOWS_BASE_IMAGE_NAME, ): """Ensure Windows Development AMI is available and up-to-date. @@ -1190,7 +1232,9 @@ ssmclient, [instance], 'AWS-RunPowerShellScript', - {'commands': WINDOWS_BOOTSTRAP_POWERSHELL.split('\n'),}, + { + 'commands': WINDOWS_BOOTSTRAP_POWERSHELL.split('\n'), + }, ) # Reboot so all updates are fully applied. @@ -1202,7 +1246,10 @@ print('rebooting instance %s' % instance.id) instance.stop() ec2client.get_waiter('instance_stopped').wait( - InstanceIds=[instance.id], WaiterConfig={'Delay': 5,} + InstanceIds=[instance.id], + WaiterConfig={ + 'Delay': 5, + }, ) instance.start()
--- a/contrib/automation/hgautomation/cli.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/automation/hgautomation/cli.py Thu Dec 03 14:15:39 2020 -0500 @@ -282,16 +282,20 @@ help='Path for local state files', ) parser.add_argument( - '--aws-region', help='AWS region to use', default='us-west-2', + '--aws-region', + help='AWS region to use', + default='us-west-2', ) subparsers = parser.add_subparsers() sp = subparsers.add_parser( - 'bootstrap-linux-dev', help='Bootstrap Linux development environments', + 'bootstrap-linux-dev', + help='Bootstrap Linux development environments', ) sp.add_argument( - '--distros', help='Comma delimited list of distros to bootstrap', + '--distros', + help='Comma delimited list of distros to bootstrap', ) sp.add_argument( '--parallel', @@ -312,13 +316,17 @@ sp.set_defaults(func=bootstrap_windows_dev) sp = subparsers.add_parser( - 'build-all-windows-packages', help='Build all Windows packages', + 'build-all-windows-packages', + help='Build all Windows packages', ) sp.add_argument( - '--revision', help='Mercurial revision to build', default='.', + '--revision', + help='Mercurial revision to build', + default='.', ) sp.add_argument( - '--version', help='Mercurial version string to use', + '--version', + help='Mercurial version string to use', ) sp.add_argument( '--base-image-name', @@ -328,7 +336,8 @@ sp.set_defaults(func=build_all_windows_packages) sp = subparsers.add_parser( - 'build-inno', help='Build Inno Setup installer(s)', + 'build-inno', + help='Build Inno Setup installer(s)', ) sp.add_argument( '--python-version', @@ -346,10 +355,13 @@ default=['x64'], ) sp.add_argument( - '--revision', help='Mercurial revision to build', default='.', + '--revision', + help='Mercurial revision to build', + default='.', ) sp.add_argument( - '--version', help='Mercurial version string to use in installer', + '--version', + help='Mercurial version string to use in installer', ) sp.add_argument( '--base-image-name', @@ -359,7 +371,8 @@ sp.set_defaults(func=build_inno) sp = subparsers.add_parser( - 'build-windows-wheel', help='Build Windows wheel(s)', + 'build-windows-wheel', + help='Build Windows wheel(s)', ) sp.add_argument( '--python-version', @@ -376,7 +389,9 @@ default=['x64'], ) sp.add_argument( - '--revision', help='Mercurial revision to build', default='.', + '--revision', + help='Mercurial revision to build', + default='.', ) sp.add_argument( '--base-image-name', @@ -402,10 +417,13 @@ default=['x64'], ) sp.add_argument( - '--revision', help='Mercurial revision to build', default='.', + '--revision', + help='Mercurial revision to build', + default='.', ) sp.add_argument( - '--version', help='Mercurial version string to use in installer', + '--version', + help='Mercurial version string to use in installer', ) sp.add_argument( '--base-image-name', @@ -421,11 +439,15 @@ sp.set_defaults(func=terminate_ec2_instances) sp = subparsers.add_parser( - 'purge-ec2-resources', help='Purge all EC2 resources managed by us', + 'purge-ec2-resources', + help='Purge all EC2 resources managed by us', ) sp.set_defaults(func=purge_ec2_resources) - sp = subparsers.add_parser('run-tests-linux', help='Run tests on Linux',) + sp = subparsers.add_parser( + 'run-tests-linux', + help='Run tests on Linux', + ) sp.add_argument( '--distro', help='Linux distribution to run tests on', @@ -468,10 +490,13 @@ sp.set_defaults(func=run_tests_linux) sp = subparsers.add_parser( - 'run-tests-windows', help='Run tests on Windows', + 'run-tests-windows', + help='Run tests on Windows', ) sp.add_argument( - '--instance-type', help='EC2 instance type to use', default='t3.medium', + '--instance-type', + help='EC2 instance type to use', + default='t3.medium', ) sp.add_argument( '--python-version', @@ -486,7 +511,8 @@ default='x64', ) sp.add_argument( - '--test-flags', help='Extra command line flags to pass to run-tests.py', + '--test-flags', + help='Extra command line flags to pass to run-tests.py', ) sp.add_argument( '--base-image-name', @@ -514,10 +540,12 @@ help='Skip uploading to www.mercurial-scm.org', ) sp.add_argument( - '--ssh-username', help='SSH username for mercurial-scm.org', + '--ssh-username', + help='SSH username for mercurial-scm.org', ) sp.add_argument( - 'version', help='Mercurial version string to locate local packages', + 'version', + help='Mercurial version string to locate local packages', ) sp.set_defaults(func=publish_windows_artifacts)
--- a/contrib/automation/hgautomation/windows.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/automation/hgautomation/windows.py Thu Dec 03 14:15:39 2020 -0500 @@ -362,7 +362,8 @@ raise Exception("unhandled arch: %s" % arch) ps = BUILD_INNO_PYTHON3.format( - pyoxidizer_target=target_triple, version=version, + pyoxidizer_target=target_triple, + version=version, ) else: extra_args = [] @@ -427,7 +428,8 @@ raise Exception("unhandled arch: %s" % arch) ps = BUILD_WIX_PYTHON3.format( - pyoxidizer_target=target_triple, version=version, + pyoxidizer_target=target_triple, + version=version, ) else: extra_args = [] @@ -460,7 +462,10 @@ python_path = 'python%s-%s' % (python_version.replace('.', ''), arch) - ps = RUN_TESTS.format(python_path=python_path, test_flags=test_flags or '',) + ps = RUN_TESTS.format( + python_path=python_path, + test_flags=test_flags or '', + ) run_powershell(winrm_client, ps)
--- a/contrib/byteify-strings.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/byteify-strings.py Thu Dec 03 14:15:39 2020 -0500 @@ -213,15 +213,19 @@ fn = t.string # *attr() builtins don't accept byte strings to 2nd argument. - if fn in ( - 'getattr', - 'setattr', - 'hasattr', - 'safehasattr', - 'wrapfunction', - 'wrapclass', - 'addattr', - ) and (opts['allow-attr-methods'] or not _isop(i - 1, '.')): + if ( + fn + in ( + 'getattr', + 'setattr', + 'hasattr', + 'safehasattr', + 'wrapfunction', + 'wrapclass', + 'addattr', + ) + and (opts['allow-attr-methods'] or not _isop(i - 1, '.')) + ): arg1idx = _findargnofcall(1) if arg1idx is not None: _ensuresysstr(arg1idx)
--- a/contrib/check-code.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/check-code.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # check-code - a style and portability checker for Mercurial # @@ -620,13 +620,17 @@ ] inutilpats = [ - [(r'\bui\.', "don't use ui in util"),], + [ + (r'\bui\.', "don't use ui in util"), + ], # warnings [], ] inrevlogpats = [ - [(r'\brepo\.', "don't use repo in revlog"),], + [ + (r'\brepo\.', "don't use repo in revlog"), + ], # warnings [], ]
--- a/contrib/check-commit Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/check-commit Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2014 Matt Mackall <mpm@selenic.com> #
--- a/contrib/check-config.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/check-config.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # check-config - a config flag documentation checker for Mercurial #
--- a/contrib/check-py3-compat.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/check-py3-compat.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # check-py3-compat - check Python 3 compatibility of Mercurial files #
--- a/contrib/debugcmdserver.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/debugcmdserver.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Dumps output generated by Mercurial's command server in a formatted style to a # given file or stderr if '-' is specified. Output is also written in its raw
--- a/contrib/dumprevlog Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/dumprevlog Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Dump revlogs as raw data stream # $ find .hg/store/ -name "*.i" | xargs dumprevlog > repo.dump
--- a/contrib/heptapod-ci.yml Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/heptapod-ci.yml Thu Dec 03 14:15:39 2020 -0500 @@ -1,9 +1,13 @@ -image: octobus/ci-mercurial-core +stages: + - tests + - phabricator + +image: registry.heptapod.net/mercurial/ci-images/mercurial-core # The runner made a clone as root. # We make a new clone owned by user used to run the step. before_script: - - hg clone . /tmp/mercurial-ci/ --noupdate + - hg clone . /tmp/mercurial-ci/ --noupdate --config phases.publish=no - hg -R /tmp/mercurial-ci/ update `hg log --rev '.' --template '{node}'` - cd /tmp/mercurial-ci/rust/rhg - cargo build @@ -15,6 +19,7 @@ TEST_HGMODULEPOLICY: "allow" .runtests_template: &runtests + stage: tests script: - echo "python used, $PYTHON" - echo "$RUNTEST_ARGS" @@ -32,15 +37,22 @@ PYTHON: python3 rust-cargo-test-py2: &rust_cargo_test + stage: tests script: - echo "python used, $PYTHON" - make rust-tests rust-cargo-test-py3: + stage: tests <<: *rust_cargo_test variables: PYTHON: python3 +phabricator-refresh: + stage: phabricator + script: + - ./contrib/phab-refresh-stack.sh + rust-cargo-test-py3-dirstate-tree: <<: *rust_cargo_test variables:
--- a/contrib/hg-ssh Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/hg-ssh Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2005-2007 by Intevation GmbH <intevation@intevation.de> #
--- a/contrib/hgperf Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/hgperf Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # hgperf - measure performance of Mercurial commands #
--- a/contrib/hgweb.fcgi Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/hgweb.fcgi Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # An example FastCGI script for use with flup, edit as necessary
--- a/contrib/import-checker.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/import-checker.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from __future__ import absolute_import, print_function
--- a/contrib/packaging/Makefile Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/Makefile Thu Dec 03 14:15:39 2020 -0500 @@ -9,19 +9,18 @@ xenial \ bionic \ cosmic \ - disco + focal FEDORA_RELEASE := 31 CENTOS_RELEASES := \ - 5 \ - 6 \ 7 \ 8 # Build a Python for these CentOS releases. -CENTOS_WITH_PYTHON_RELEASES := 5 6 -CENTOS_WITH_NONVERSIONED_PYTHON := 5 6 7 +CENTOS_WITH_PYTHON_RELEASES := +CENTOS_WITH_NONVERSIONED_PYTHON := +CENTOS_WITH_36_DOCUTILS := 7 help: @echo 'Packaging Make Targets' @@ -112,13 +111,13 @@ .PHONY: centos$(1) centos$(1): mkdir -p $$(HGROOT)/packages/centos$(1) - ./buildrpm $$(if $$(filter $(1),$$(CENTOS_WITH_PYTHON_RELEASES)),--withpython,$$(if $$(filter $(1),$$(CENTOS_WITH_NONVERSIONED_PYTHON)),--python python,)) + ./buildrpm $$(if $$(filter $(1),$$(CENTOS_WITH_PYTHON_RELEASES)),--withpython,$$(if $$(filter $(1),$$(CENTOS_WITH_NONVERSIONED_PYTHON)),--python python,))$$(if $$(filter $(1),$$(CENTOS_WITH_36_DOCUTILS)), --docutilspackage python36-docutils,) cp $$(HGROOT)/contrib/packaging/rpmbuild/RPMS/*/* $$(HGROOT)/packages/centos$(1) cp $$(HGROOT)/contrib/packaging/rpmbuild/SRPMS/* $$(HGROOT)/packages/centos$(1) .PHONY: docker-centos$(1) docker-centos$(1): - ./dockerrpm centos$(1) $$(if $$(filter $(1),$$(CENTOS_WITH_PYTHON_RELEASES)),--withpython,$$(if $$(filter $(1),$$(CENTOS_WITH_NONVERSIONED_PYTHON)),--python python,)) + ./dockerrpm centos$(1) $$(if $$(filter $(1),$$(CENTOS_WITH_PYTHON_RELEASES)),--withpython,$$(if $$(filter $(1),$$(CENTOS_WITH_NONVERSIONED_PYTHON)),--python python,))$$(if $$(filter $(1),$$(CENTOS_WITH_36_DOCUTILS)), --docutilspackage python36-docutils,) endef
--- a/contrib/packaging/buildrpm Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/buildrpm Thu Dec 03 14:15:39 2020 -0500 @@ -7,6 +7,7 @@ BUILD=1 RPMBUILDDIR="$PWD/rpmbuild" PYTHONEXE=python3 +DOCUTILSPACKAGE=python3-docutils while [ "$1" ]; do case "$1" in @@ -25,6 +26,11 @@ PYTHONMD5=f1a2ace631068444831d01485466ece0 PYTHONEXE=python ;; + --docutilspackage) + shift + DOCUTILSPACKAGE="$1" + shift + ;; --rpmbuilddir ) shift RPMBUILDDIR="$1" @@ -50,7 +56,7 @@ exit 1 fi -gethgversion +gethgversion $PYTHONEXE if [ -z "$type" ] ; then release=1 @@ -70,7 +76,7 @@ fi mkdir -p $RPMBUILDDIR/{SOURCES,BUILD,SRPMS,RPMS} -$HG archive -t tgz $RPMBUILDDIR/SOURCES/mercurial-$version-$release.tar.gz +$PYTHONEXE $HG archive -t tgz $RPMBUILDDIR/SOURCES/mercurial-$version-$release.tar.gz if [ "$PYTHONVER" ]; then ( mkdir -p build @@ -106,7 +112,7 @@ if echo $version | grep '+' > /dev/null 2>&1; then latesttag="`echo $version | sed -e 's/+.*//'`" - $HG log -r .:"$latesttag" -fM \ + $PYTHONEXE $HG log -r .:"$latesttag" -fM \ --template '{date|hgdate}\t{author}\t{desc|firstline}\n' | python -c ' import sys, time @@ -130,9 +136,9 @@ else - $HG log \ + $PYTHONEXE $HG log \ --template '{date|hgdate}\t{author}\t{desc|firstline}\n' \ - .hgtags | python -c ' + .hgtags | $PYTHONEXE -c ' import sys, time def datestr(date, format): @@ -149,6 +155,9 @@ sed -i \ -e "s/^%define withpython.*$/%define withpython $RPMPYTHONVER/" \ $rpmspec +sed -i \ + -e "s/^%global pythondocutils.*$/%global pythondocutils $DOCUTILSPACKAGE/" \ + $rpmspec if [ "$BUILD" ]; then rpmbuild --define "_topdir $RPMBUILDDIR" -ba $rpmspec --clean
--- a/contrib/packaging/docker/centos5 Thu Dec 03 13:36:24 2020 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -FROM centos:centos5 - -RUN groupadd -g %GID% build && \ - useradd -u %UID% -g %GID% -s /bin/bash -d /build -m build - -RUN \ - sed -i 's/^mirrorlist/#mirrorlist/' /etc/yum.repos.d/*.repo && \ - sed -i 's/^#\(baseurl=\)http:\/\/mirror.centos.org\/centos/\1http:\/\/vault.centos.org/' /etc/yum.repos.d/*.repo && \ - sed -i 's/\$releasever/5.11/' /etc/yum.repos.d/*.repo - -RUN yum install -y \ - gcc \ - gettext \ - make \ - python-devel \ - python-docutils \ - rpm-build \ - tar - -# For creating repo meta data -RUN yum install -y \ - bzip2-devel \ - createrepo \ - ncurses-devel \ - openssl-devel \ - readline-devel \ - zlib-devel
--- a/contrib/packaging/docker/centos6 Thu Dec 03 13:36:24 2020 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -FROM centos:centos6 - -RUN groupadd -g %GID% build && \ - useradd -u %UID% -g %GID% -s /bin/bash -d /build -m build - -RUN yum install -y \ - gcc \ - gettext \ - make \ - python-devel \ - python-docutils \ - rpm-build \ - tar - -# For creating repo meta data -RUN yum install -y createrepo - -# For python -RUN yum install -y \ - bzip2-devel \ - ncurses-devel \ - openssl-devel \ - readline-devel \ - zlib-devel
--- a/contrib/packaging/docker/centos7 Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/docker/centos7 Thu Dec 03 14:15:39 2020 -0500 @@ -3,14 +3,18 @@ RUN groupadd -g %GID% build && \ useradd -u %UID% -g %GID% -s /bin/bash -d /build -m build +RUN yum install -y epel-release RUN yum install -y \ gcc \ gettext \ make \ - python-devel \ - python-docutils \ + python3-devel \ + python36-docutils \ rpm-build \ tar # For creating repo meta data RUN yum install -y createrepo + +# For rust extensions +RUN yum install -y cargo
--- a/contrib/packaging/docker/centos8 Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/docker/centos8 Thu Dec 03 14:15:39 2020 -0500 @@ -13,3 +13,6 @@ # For creating repo meta data RUN yum install -y createrepo + +# For rust extensions +RUN yum install -y cargo
--- a/contrib/packaging/docker/ubuntu.template Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/docker/ubuntu.template Thu Dec 03 14:15:39 2020 -0500 @@ -3,6 +3,10 @@ RUN groupadd -g 1000 build && \ useradd -u 1000 -g 1000 -s /bin/bash -d /build -m build +ARG DEBIAN_FRONTEND=noninteractive + +ENV TZ=%TZ% + RUN apt-get update && apt-get install -y \ build-essential \ debhelper \
--- a/contrib/packaging/dockerdeb Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/dockerdeb Thu Dec 03 14:15:39 2020 -0500 @@ -12,10 +12,12 @@ OUTPUTDIR=${OUTPUTDIR:=$ROOTDIR/packages/$PLATFORM} CONTAINER=hg-docker-$PLATFORM +TZ=`ls -la /etc/localtime | cut -d/ -f7-9` DOCKER=$($BUILDDIR/hg-docker docker-path) $BUILDDIR/hg-docker build \ + --build-arg TZ=$TZ \ --build-arg CODENAME=$CODENAME \ $BUILDDIR/docker/$DISTID.template \ $CONTAINER @@ -25,7 +27,11 @@ # container and hope it's writable. Whee. dn=$(basename $ROOTDIR) -DBUILDUSER=build +if [[ -z "${HG_DOCKER_OWN_USER:-}" ]]; then + DBUILDUSER=build +else + DBUILDUSER="$(id -u):$(id -g)" +fi if [ $(uname) = "Darwin" ] ; then $DOCKER run -u $DBUILDUSER --rm -v $PWD/..:/mnt $CONTAINER \
--- a/contrib/packaging/hgpackaging/cli.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/hgpackaging/cli.py Thu Dec 03 14:15:39 2020 -0500 @@ -44,7 +44,11 @@ ) else: inno.build_with_py2exe( - SOURCE_DIR, build_dir, pathlib.Path(python), iscc, version=version, + SOURCE_DIR, + build_dir, + pathlib.Path(python), + iscc, + version=version, )
--- a/contrib/packaging/hgpackaging/inno.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/hgpackaging/inno.py Thu Dec 03 14:15:39 2020 -0500 @@ -198,7 +198,11 @@ except jinja2.TemplateSyntaxError as e: raise Exception( 'template syntax error at %s:%d: %s' - % (e.name, e.lineno, e.message,) + % ( + e.name, + e.lineno, + e.message, + ) ) content = template.render(package_files=package_files)
--- a/contrib/packaging/hgpackaging/pyoxidizer.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/hgpackaging/pyoxidizer.py Thu Dec 03 14:15:39 2020 -0500 @@ -127,6 +127,7 @@ # Write out a default editor.rc file to configure notepad as the # default editor. + os.makedirs(out_dir / "defaultrc", exist_ok=True) with (out_dir / "defaultrc" / "editor.rc").open( "w", encoding="utf-8" ) as fh:
--- a/contrib/packaging/hgpackaging/wix.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/hgpackaging/wix.py Thu Dec 03 14:15:39 2020 -0500 @@ -517,7 +517,10 @@ args.append(str(build_dir / ('%s.wixobj' % source[:-4]))) args.extend( - [str(build_dir / 'stage.wixobj'), str(build_dir / 'mercurial.wixobj'),] + [ + str(build_dir / 'stage.wixobj'), + str(build_dir / 'mercurial.wixobj'), + ] ) subprocess.run(args, cwd=str(source_dir), check=True)
--- a/contrib/packaging/mercurial.spec Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/mercurial.spec Thu Dec 03 14:15:39 2020 -0500 @@ -3,6 +3,7 @@ %define withpython %{nil} %global pythonexe python3 +%global pythondocutils python3-docutils %if "%{?withpython}" @@ -39,7 +40,7 @@ %if "%{?withpython}" BuildRequires: readline-devel, openssl-devel, ncurses-devel, zlib-devel, bzip2-devel %else -BuildRequires: %{pythonexe} >= %{pythonver}, %{pythonexe}-devel, %{pythonexe}-docutils >= 0.5 +BuildRequires: %{pythonexe} >= %{pythonver}, %{pythonexe}-devel, %{pythondocutils} Requires: %{pythonexe} >= %{pythonver} %endif # The hgk extension uses the wish tcl interpreter, but we don't enforce it @@ -109,14 +110,14 @@ LD_LIBRARY_PATH=$PYPATH $PYPATH/python setup.py install --root="$RPM_BUILD_ROOT" cd - -PATH=$PYPATH:$PATH LD_LIBRARY_PATH=$PYPATH make install PYTHON=%{pythonexe} DESTDIR=$RPM_BUILD_ROOT PREFIX=%{hgpyprefix} MANDIR=%{_mandir} +PATH=$PYPATH:$PATH LD_LIBRARY_PATH=$PYPATH make install PYTHON=%{pythonexe} DESTDIR=$RPM_BUILD_ROOT PREFIX=%{hgpyprefix} MANDIR=%{_mandir} PURE="--rust" mkdir -p $RPM_BUILD_ROOT%{_bindir} ( cd $RPM_BUILD_ROOT%{_bindir}/ && ln -s ../..%{hgpyprefix}/bin/hg . ) ( cd $RPM_BUILD_ROOT%{_bindir}/ && ln -s ../..%{hgpyprefix}/bin/python2.? %{pythonhg} ) %else -make install PYTHON=%{pythonexe} DESTDIR=$RPM_BUILD_ROOT PREFIX=%{_prefix} MANDIR=%{_mandir} +make install PYTHON=%{pythonexe} DESTDIR=$RPM_BUILD_ROOT PREFIX=%{_prefix} MANDIR=%{_mandir} PURE="--rust" %endif
--- a/contrib/packaging/packagelib.sh Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/packagelib.sh Thu Dec 03 14:15:39 2020 -0500 @@ -8,16 +8,21 @@ # # node: the node|short hg was built from, or empty if built from a tag gethgversion() { + if [ -z "${1+x}" ]; then + python="python" + else + python="$1" + fi export HGRCPATH= export HGPLAIN= - make cleanbutpackages - make local PURE=--pure + make cleanbutpackages PYTHON=$python + make local PURE=--pure PYTHON=$python HG="$PWD/hg" - "$HG" version > /dev/null || { echo 'abort: hg version failed!'; exit 1 ; } + $python "$HG" version > /dev/null || { echo 'abort: hg version failed!'; exit 1 ; } - hgversion=`LANGUAGE=C "$HG" version | sed -ne 's/.*(version \(.*\))$/\1/p'` + hgversion=`LANGUAGE=C $python "$HG" version | sed -ne 's/.*(version \(.*\))$/\1/p'` if echo $hgversion | grep + > /dev/null 2>&1 ; then tmp=`echo $hgversion | cut -d+ -f 2`
--- a/contrib/packaging/requirements-windows-py3.txt Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/requirements-windows-py3.txt Thu Dec 03 14:15:39 2020 -0500 @@ -4,10 +4,50 @@ # # pip-compile --generate-hashes --output-file=contrib/packaging/requirements-windows-py3.txt contrib/packaging/requirements-windows.txt.in # +cached-property==1.5.2 \ + --hash=sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130 \ + --hash=sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0 \ + # via pygit2 certifi==2020.6.20 \ --hash=sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3 \ --hash=sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41 \ # via dulwich +cffi==1.14.4 \ + --hash=sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e \ + --hash=sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d \ + --hash=sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a \ + --hash=sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec \ + --hash=sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362 \ + --hash=sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668 \ + --hash=sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c \ + --hash=sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b \ + --hash=sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06 \ + --hash=sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698 \ + --hash=sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2 \ + --hash=sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c \ + --hash=sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7 \ + --hash=sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009 \ + --hash=sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03 \ + --hash=sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b \ + --hash=sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909 \ + --hash=sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53 \ + --hash=sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35 \ + --hash=sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26 \ + --hash=sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b \ + --hash=sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb \ + --hash=sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293 \ + --hash=sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd \ + --hash=sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d \ + --hash=sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3 \ + --hash=sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d \ + --hash=sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca \ + --hash=sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d \ + --hash=sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775 \ + --hash=sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375 \ + --hash=sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b \ + --hash=sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b \ + --hash=sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f \ + # via pygit2 docutils==0.16 \ --hash=sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af \ --hash=sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc \ @@ -35,6 +75,29 @@ --hash=sha256:4e34ea2fdec90c1c43d6610b5a5fafa1b9097db1802948e90caf5763974b8f8d \ --hash=sha256:9aeadd006a852b78f4b4ef7c7556c2774d2432bbef8ee538a3e9089ac8b11466 \ # via -r contrib/packaging/requirements-windows.txt.in +pycparser==2.20 \ + --hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 \ + --hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705 \ + # via cffi +pygit2==1.4.0 ; python_version >= "3" \ + --hash=sha256:0d298098e286eeda000e49ca7e1b41f87300e10dd8b9d06b32b008bd61f50b83 \ + --hash=sha256:0ee135eb2cd8b07ce1374f3596cc5c3213472d6389bad6a4c5d87d8e267e93e9 \ + --hash=sha256:32eb863d6651d4890ced318505ea8dc229bd9637deaf29c898de1ab574d727a0 \ + --hash=sha256:37d6d7d6d7804c42a0fe23425c72e38093488525092fc5e51a05684e63503ce7 \ + --hash=sha256:41204b6f3406d9f53147710f3cc485d77181ba67f57c34d36b7c86de1c14a18c \ + --hash=sha256:818c91b582109d90580c5da74af783738838353f15eb12eeb734d80a974b05a3 \ + --hash=sha256:8306a302487dac67df7af6a064bb37e8a8eb4138958f9560ff49ff162e185dab \ + --hash=sha256:9c2f2d9ef59513007b66f6534b000792b614de3faf60313a0a68f6b8571aea85 \ + --hash=sha256:9c8d5881eb709e2e2e13000b507a131bd5fb91a879581030088d0ddffbcd19af \ + --hash=sha256:b422e417739def0a136a6355723dfe8a5ffc83db5098076f28a14f1d139779c1 \ + --hash=sha256:cbeb38ab1df9b5d8896548a11e63aae8a064763ab5f1eabe4475e6b8a78ee1c8 \ + --hash=sha256:cf00481ddf053e549a6edd0216bdc267b292d261eae02a67bb3737de920cbf88 \ + --hash=sha256:d0d889144e9487d926fecea947c3f39ce5f477e521d7d467d2e66907e4cd657d \ + --hash=sha256:ddb7a1f6d38063e8724abfa1cfdfb0f9b25014b8bca0546274b7a84b873a3888 \ + --hash=sha256:e9037a7d810750fe23c9f5641ef14a0af2525ff03e14752cd4f73e1870ecfcb0 \ + --hash=sha256:ec5c0365a9bdfcac1609d20868507b28685ec5ea7cc3a2c903c9b62ef2e0bbc0 \ + --hash=sha256:fdd8ba30cda277290e000322f505132f590cf89bd7d31829b45a3cb57447ec32 \ + # via -r contrib/packaging/requirements-windows.txt.in pygments==2.7.1 \ --hash=sha256:307543fe65c0947b126e83dd5a61bd8acbd84abec11f43caebaf5534cbc17998 \ --hash=sha256:926c3f319eda178d1bd90851e4317e6d8cdb5e292a3386aac9bd75eca29cf9c7 \
--- a/contrib/packaging/requirements-windows.txt.in Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/packaging/requirements-windows.txt.in Thu Dec 03 14:15:39 2020 -0500 @@ -3,6 +3,7 @@ dulwich < 0.20 ; python_version <= '2.7' dulwich ; python_version >= '3' keyring +pygit2 ; python_version >= '3' pygments # Need to list explicitly so dependency gets pulled in when # not running on Windows.
--- a/contrib/perf-utils/perf-revlog-write-plot.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/perf-utils/perf-revlog-write-plot.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2018 Paul Morelle <Paul.Morelle@octobus.net> #
--- a/contrib/perf.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/perf.py Thu Dec 03 14:15:39 2020 -0500 @@ -291,7 +291,9 @@ experimental=True, ) configitem( - b'perf', b'pre-run', default=mercurial.configitems.dynamicdefault, + b'perf', + b'pre-run', + default=mercurial.configitems.dynamicdefault, ) configitem( b'perf', @@ -310,19 +312,29 @@ # compatibility fix for a11fd395e83f # hg version: 5.2 configitem( - b'perf', b'presleep', default=mercurial.configitems.dynamicdefault, + b'perf', + b'presleep', + default=mercurial.configitems.dynamicdefault, ) configitem( - b'perf', b'stub', default=mercurial.configitems.dynamicdefault, + b'perf', + b'stub', + default=mercurial.configitems.dynamicdefault, ) configitem( - b'perf', b'parentscount', default=mercurial.configitems.dynamicdefault, + b'perf', + b'parentscount', + default=mercurial.configitems.dynamicdefault, ) configitem( - b'perf', b'all-timing', default=mercurial.configitems.dynamicdefault, + b'perf', + b'all-timing', + default=mercurial.configitems.dynamicdefault, ) configitem( - b'perf', b'pre-run', default=mercurial.configitems.dynamicdefault, + b'perf', + b'pre-run', + default=mercurial.configitems.dynamicdefault, ) configitem( b'perf', @@ -330,7 +342,9 @@ default=mercurial.configitems.dynamicdefault, ) configitem( - b'perf', b'run-limits', default=mercurial.configitems.dynamicdefault, + b'perf', + b'run-limits', + default=mercurial.configitems.dynamicdefault, ) @@ -385,8 +399,7 @@ from mercurial import node class defaultformatter(object): - """Minimized composition of baseformatter and plainformatter - """ + """Minimized composition of baseformatter and plainformatter""" def __init__(self, ui, topic, opts): self._ui = ui @@ -658,8 +671,7 @@ def getsvfs(repo): - """Return appropriate object to access files under .hg/store - """ + """Return appropriate object to access files under .hg/store""" # for "historical portability": # repo.svfs has been available since 2.3 (or 7034365089bf) svfs = getattr(repo, 'svfs', None) @@ -670,8 +682,7 @@ def getvfs(repo): - """Return appropriate object to access files under .hg - """ + """Return appropriate object to access files under .hg""" # for "historical portability": # repo.vfs has been available since 2.3 (or 7034365089bf) vfs = getattr(repo, 'vfs', None) @@ -682,8 +693,7 @@ def repocleartagscachefunc(repo): - """Return the function to clear tags cache according to repo internal API - """ + """Return the function to clear tags cache according to repo internal API""" if util.safehasattr(repo, b'_tagscache'): # since 2.0 (or 9dca7653b525) # in this case, setattr(repo, '_tagscache', None) or so isn't # correct way to clear tags cache, because existing code paths @@ -847,7 +857,9 @@ @command( b'perftags', formatteropts - + [(b'', b'clear-revlogs', False, b'refresh changelog and manifest'),], + + [ + (b'', b'clear-revlogs', False, b'refresh changelog and manifest'), + ], ) def perftags(ui, repo, **opts): opts = _byteskwargs(opts) @@ -900,8 +912,7 @@ @command(b'perfdiscovery', formatteropts, b'PATH') def perfdiscovery(ui, repo, path, **opts): - """benchmark discovery between local repo and the peer at given path - """ + """benchmark discovery between local repo and the peer at given path""" repos = [repo, None] timer, fm = gettimer(ui, opts) path = ui.expandpath(path) @@ -919,7 +930,9 @@ @command( b'perfbookmarks', formatteropts - + [(b'', b'clear-revlogs', False, b'refresh changelog and manifest'),], + + [ + (b'', b'clear-revlogs', False, b'refresh changelog and manifest'), + ], ) def perfbookmarks(ui, repo, **opts): """benchmark parsing bookmarks from disk to memory""" @@ -1184,8 +1197,7 @@ @command(b'perfdirstatedirs', formatteropts) def perfdirstatedirs(ui, repo, **opts): - """benchmap a 'dirstate.hasdir' call from an empty `dirs` cache - """ + """benchmap a 'dirstate.hasdir' call from an empty `dirs` cache""" opts = _byteskwargs(opts) timer, fm = gettimer(ui, opts) repo.dirstate.hasdir(b"a") @@ -1245,8 +1257,7 @@ @command(b'perfdirstatewrite', formatteropts) def perfdirstatewrite(ui, repo, **opts): - """benchmap the time it take to write a dirstate on disk - """ + """benchmap the time it take to write a dirstate on disk""" opts = _byteskwargs(opts) timer, fm = gettimer(ui, opts) ds = repo.dirstate @@ -1359,7 +1370,9 @@ @command( b'perfphases', - [(b'', b'full', False, b'include file reading time too'),], + [ + (b'', b'full', False, b'include file reading time too'), + ], b"", ) def perfphases(ui, repo, **opts): @@ -1839,7 +1852,10 @@ @command( b'perftemplating', - [(b'r', b'rev', [], b'revisions to run the template on'),] + formatteropts, + [ + (b'r', b'rev', [], b'revisions to run the template on'), + ] + + formatteropts, ) def perftemplating(ui, repo, testedtemplate=None, **opts): """test the rendering time of a given template""" @@ -2193,10 +2209,18 @@ } if dostats: alldata['nbrevs'].append( - (data['nbrevs'], base.hex(), parent.hex(),) + ( + data['nbrevs'], + base.hex(), + parent.hex(), + ) ) alldata['nbmissingfiles'].append( - (data['nbmissingfiles'], base.hex(), parent.hex(),) + ( + data['nbmissingfiles'], + base.hex(), + parent.hex(), + ) ) if dotiming: begin = util.timer() @@ -2207,10 +2231,18 @@ data['nbrenamedfiles'] = len(renames) if dostats: alldata['time'].append( - (data['time'], base.hex(), parent.hex(),) + ( + data['time'], + base.hex(), + parent.hex(), + ) ) alldata['nbrenames'].append( - (data['nbrenamedfiles'], base.hex(), parent.hex(),) + ( + data['nbrenamedfiles'], + base.hex(), + parent.hex(), + ) ) fm.startitem() fm.data(**data) @@ -3321,7 +3353,9 @@ @command( b'perfvolatilesets', - [(b'', b'clear-obsstore', False, b'drop obsstore between each call.'),] + [ + (b'', b'clear-obsstore', False, b'drop obsstore between each call.'), + ] + formatteropts, ) def perfvolatilesets(ui, repo, *names, **opts): @@ -3807,8 +3841,7 @@ ], ) def perfwrite(ui, repo, **opts): - """microbenchmark ui.write (and others) - """ + """microbenchmark ui.write (and others)""" opts = _byteskwargs(opts) write = getattr(ui, _sysstr(opts[b'write_method']))
--- a/contrib/phab-clean.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/phab-clean.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # A small script to automatically reject idle Diffs #
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/phab-refresh-stack.sh Thu Dec 03 14:15:39 2020 -0500 @@ -0,0 +1,34 @@ +#!/bin/bash +set -eu + +revision_in_stack=`hg log --rev '.#stack and ::.' -T '\nONE-REV\n' | grep 'ONE-REV' | wc -l` +revision_on_phab=`hg log --rev '.#stack and ::. and desc("re:\nDifferential Revision: [^\n]+D\d+$")' -T '\nONE-REV\n' | grep 'ONE-REV' | wc -l` + +if [[ $revision_in_stack -eq 0 ]]; then + echo "stack is empty" >&2 + exit 0 +fi + +if [[ $revision_on_phab -eq 0 ]]; then + echo "no tracked diff in this stack" >&2 + exit 0 +fi + +if [[ $revision_on_phab -lt $revision_in_stack ]]; then + echo "not all stack changesets (${revision_in_stack}) have matching Phabricator Diff (${revision_on_phab})" >&2 + exit 2 +fi + +if [[ "$PHABRICATOR_TOKEN" == "" ]]; then + echo 'missing $PHABRICATOR_TOKEN variable' >&2 + exit 2 +fi + +hg \ +--config extensions.phabricator= \ +--config phabricator.url=https://phab.mercurial-scm.org/ \ +--config phabricator.callsign=HG \ +--config auth.phabricator.schemes=https \ +--config auth.phabricator.prefix=phab.mercurial-scm.org \ +--config auth.phabricator.phabtoken=$PHABRICATOR_TOKEN \ +phabsend --rev '.#stack and ::.'
--- a/contrib/python-hook-examples.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/python-hook-examples.py Thu Dec 03 14:15:39 2020 -0500 @@ -9,12 +9,12 @@ def diffstat(ui, repo, **kwargs): - '''Example usage: + """Example usage: [hooks] commit.diffstat = python:/path/to/this/file.py:diffstat changegroup.diffstat = python:/path/to/this/file.py:diffstat - ''' + """ if kwargs.get('parent2'): return node = kwargs['node']
--- a/contrib/python-zstandard/make_cffi.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/python-zstandard/make_cffi.py Thu Dec 03 14:15:39 2020 -0500 @@ -53,7 +53,10 @@ # Headers whose preprocessed output will be fed into cdef(). HEADERS = [ os.path.join(HERE, "zstd", *p) - for p in (("zstd.h",), ("dictBuilder", "zdict.h"),) + for p in ( + ("zstd.h",), + ("dictBuilder", "zdict.h"), + ) ] INCLUDE_DIRS = [ @@ -80,12 +83,20 @@ if compiler.compiler_type == "unix": args = list(compiler.executables["compiler"]) args.extend( - ["-E", "-DZSTD_STATIC_LINKING_ONLY", "-DZDICT_STATIC_LINKING_ONLY",] + [ + "-E", + "-DZSTD_STATIC_LINKING_ONLY", + "-DZDICT_STATIC_LINKING_ONLY", + ] ) elif compiler.compiler_type == "msvc": args = [compiler.cc] args.extend( - ["/EP", "/DZSTD_STATIC_LINKING_ONLY", "/DZDICT_STATIC_LINKING_ONLY",] + [ + "/EP", + "/DZSTD_STATIC_LINKING_ONLY", + "/DZDICT_STATIC_LINKING_ONLY", + ] ) else: raise Exception("unsupported compiler type: %s" % compiler.compiler_type)
--- a/contrib/python3-ratchet.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/python3-ratchet.py Thu Dec 03 14:15:39 2020 -0500 @@ -26,7 +26,9 @@ _hgenv = dict(os.environ) _hgenv.update( - {'HGPLAIN': '1',} + { + 'HGPLAIN': '1', + } ) _HG_FIRST_CHANGE = '9117c6561b0bd7792fa13b50d28239d51b78e51f'
--- a/contrib/revsetbenchmarks.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/revsetbenchmarks.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Measure the performance of a list of revsets against multiple revisions # defined by parameter. Checkout one by one and run perfrevset with every
--- a/contrib/simplemerge Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/simplemerge Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from __future__ import absolute_import import getopt
--- a/contrib/synthrepo.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/synthrepo.py Thu Dec 03 14:15:39 2020 -0500 @@ -122,7 +122,7 @@ optionalrepo=True, ) def analyze(ui, repo, *revs, **opts): - '''create a simple model of a repository to use for later synthesis + """create a simple model of a repository to use for later synthesis This command examines every changeset in the given range (or all of history if none are specified) and creates a simple statistical @@ -133,7 +133,7 @@ :hg:`synthesize` to create or augment a repository with synthetic commits that have a structure that is statistically similar to the analyzed repository. - ''' + """ root = repo.root if not root.endswith(os.path.sep): root += os.path.sep @@ -281,7 +281,7 @@ _('hg synthesize [OPTION].. DESCFILE'), ) def synthesize(ui, repo, descpath, **opts): - '''synthesize commits based on a model of an existing repository + """synthesize commits based on a model of an existing repository The model must have been generated by :hg:`analyze`. Commits will be generated randomly according to the probabilities described in @@ -293,7 +293,7 @@ names, words will be chosen randomly from a dictionary that is presumed to contain one word per line. Use --dict to specify the path to an alternate dictionary to use. - ''' + """ try: fp = hg.openpath(ui, descpath) except Exception as err: @@ -542,12 +542,12 @@ replacements = {'': ''} def rename(dirpath): - '''Recursively rename the directory and all path prefixes. + """Recursively rename the directory and all path prefixes. The mapping from path to renamed path is stored for all path prefixes as in dynamic programming, ensuring linear runtime and consistent renaming regardless of iteration order through the model. - ''' + """ if dirpath in replacements: return replacements[dirpath] head, _ = os.path.split(dirpath)
--- a/contrib/testparseutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/testparseutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -81,8 +81,7 @@ class embeddedmatcher(object): # pytype: disable=ignored-metaclass - """Base class to detect embedded code fragments in *.t test script - """ + """Base class to detect embedded code fragments in *.t test script""" __metaclass__ = abc.ABCMeta @@ -103,8 +102,7 @@ @abc.abstractmethod def isinside(self, ctx, line): - """Examine whether line is inside embedded code, if not yet endsat - """ + """Examine whether line is inside embedded code, if not yet endsat""" @abc.abstractmethod def ignores(self, ctx):
--- a/contrib/undumprevlog Thu Dec 03 13:36:24 2020 -0500 +++ b/contrib/undumprevlog Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Undump a dump from dumprevlog # $ hg init # $ undumprevlog < repo.dump
--- a/doc/check-seclevel.py Thu Dec 03 13:36:24 2020 -0500 +++ b/doc/check-seclevel.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # checkseclevel - checking section title levels in each online help document
--- a/doc/docchecker Thu Dec 03 13:36:24 2020 -0500 +++ b/doc/docchecker Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # docchecker - look for problematic markup #
--- a/doc/gendoc.py Thu Dec 03 13:36:24 2020 -0500 +++ b/doc/gendoc.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """usage: %s DOC ... where DOC is the name of a document
--- a/doc/hgmanpage.py Thu Dec 03 13:36:24 2020 -0500 +++ b/doc/hgmanpage.py Thu Dec 03 14:15:39 2020 -0500 @@ -822,7 +822,10 @@ # man 7 man argues to use ".IP" instead of ".TP" self.body.append( '.IP %s %d\n' - % (next(self._list_char[-1]), self._list_char[-1].get_width(),) + % ( + next(self._list_char[-1]), + self._list_char[-1].get_width(), + ) ) def depart_list_item(self, node):
--- a/doc/runrst Thu Dec 03 13:36:24 2020 -0500 +++ b/doc/runrst Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # runrst - register custom roles and run correct writer #
--- a/hg Thu Dec 03 13:36:24 2020 -0500 +++ b/hg Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # mercurial - scalable distributed SCM #
--- a/hgext/absorb.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/absorb.py Thu Dec 03 14:15:39 2020 -0500 @@ -511,7 +511,7 @@ # run editor editedtext = self.ui.edit(editortext, b'', action=b'absorb') if not editedtext: - raise error.Abort(_(b'empty editor text')) + raise error.InputError(_(b'empty editor text')) # parse edited result contents = [b''] * len(self.fctxs) leftpadpos = 4 @@ -520,7 +520,7 @@ if l.startswith(b'HG:'): continue if l[colonpos - 1 : colonpos + 2] != b' : ': - raise error.Abort(_(b'malformed line: %s') % l) + raise error.InputError(_(b'malformed line: %s') % l) linecontent = l[colonpos + 2 :] for i, ch in enumerate( pycompat.bytestr(l[leftpadpos : colonpos - 1]) @@ -1018,7 +1018,7 @@ limit = ui.configint(b'absorb', b'max-stack-size') headctx = repo[b'.'] if len(headctx.parents()) > 1: - raise error.Abort(_(b'cannot absorb into a merge')) + raise error.InputError(_(b'cannot absorb into a merge')) stack = getdraftstack(headctx, limit) if limit and len(stack) >= limit: ui.warn( @@ -1029,7 +1029,7 @@ % limit ) if not stack: - raise error.Abort(_(b'no mutable changeset to change')) + raise error.InputError(_(b'no mutable changeset to change')) if targetctx is None: # default to working copy targetctx = repo[None] if pats is None: @@ -1076,7 +1076,7 @@ b"apply changes (y/N)? $$ &Yes $$ &No", default=1 ) ): - raise error.Abort(_(b'absorb cancelled\n')) + raise error.CanceledError(_(b'absorb cancelled\n')) state.apply() if state.commit():
--- a/hgext/acl.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/acl.py Thu Dec 03 14:15:39 2020 -0500 @@ -239,25 +239,44 @@ # deprecated config: acl.config configitem( - b'acl', b'config', default=None, + b'acl', + b'config', + default=None, ) configitem( - b'acl.groups', b'.*', default=None, generic=True, + b'acl.groups', + b'.*', + default=None, + generic=True, ) configitem( - b'acl.deny.branches', b'.*', default=None, generic=True, + b'acl.deny.branches', + b'.*', + default=None, + generic=True, ) configitem( - b'acl.allow.branches', b'.*', default=None, generic=True, + b'acl.allow.branches', + b'.*', + default=None, + generic=True, ) configitem( - b'acl.deny', b'.*', default=None, generic=True, + b'acl.deny', + b'.*', + default=None, + generic=True, ) configitem( - b'acl.allow', b'.*', default=None, generic=True, + b'acl.allow', + b'.*', + default=None, + generic=True, ) configitem( - b'acl', b'sources', default=lambda: [b'serve'], + b'acl', + b'sources', + default=lambda: [b'serve'], )
--- a/hgext/automv.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/automv.py Thu Dec 03 14:15:39 2020 -0500 @@ -42,7 +42,9 @@ configitem = registrar.configitem(configtable) configitem( - b'automv', b'similarity', default=95, + b'automv', + b'similarity', + default=95, )
--- a/hgext/blackbox.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/blackbox.py Thu Dec 03 14:15:39 2020 -0500 @@ -72,19 +72,29 @@ configitem = registrar.configitem(configtable) configitem( - b'blackbox', b'dirty', default=False, + b'blackbox', + b'dirty', + default=False, ) configitem( - b'blackbox', b'maxsize', default=b'1 MB', + b'blackbox', + b'maxsize', + default=b'1 MB', ) configitem( - b'blackbox', b'logsource', default=False, + b'blackbox', + b'logsource', + default=False, ) configitem( - b'blackbox', b'maxfiles', default=7, + b'blackbox', + b'maxfiles', + default=7, ) configitem( - b'blackbox', b'track', default=lambda: [b'*'], + b'blackbox', + b'track', + default=lambda: [b'*'], ) configitem( b'blackbox', @@ -92,7 +102,9 @@ default=lambda: [b'chgserver', b'cmdserver', b'extension'], ) configitem( - b'blackbox', b'date-format', default=b'%Y/%m/%d %H:%M:%S', + b'blackbox', + b'date-format', + default=b'%Y/%m/%d %H:%M:%S', ) _lastlogger = loggingutil.proxylogger() @@ -189,14 +201,15 @@ @command( b'blackbox', - [(b'l', b'limit', 10, _(b'the number of events to show')),], + [ + (b'l', b'limit', 10, _(b'the number of events to show')), + ], _(b'hg blackbox [OPTION]...'), helpcategory=command.CATEGORY_MAINTENANCE, helpbasic=True, ) def blackbox(ui, repo, *revs, **opts): - '''view the recent repository events - ''' + """view the recent repository events""" if not repo.vfs.exists(b'blackbox.log'): return
--- a/hgext/bugzilla.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/bugzilla.py Thu Dec 03 14:15:39 2020 -0500 @@ -325,22 +325,34 @@ configitem = registrar.configitem(configtable) configitem( - b'bugzilla', b'apikey', default=b'', + b'bugzilla', + b'apikey', + default=b'', ) configitem( - b'bugzilla', b'bzdir', default=b'/var/www/html/bugzilla', + b'bugzilla', + b'bzdir', + default=b'/var/www/html/bugzilla', ) configitem( - b'bugzilla', b'bzemail', default=None, + b'bugzilla', + b'bzemail', + default=None, ) configitem( - b'bugzilla', b'bzurl', default=b'http://localhost/bugzilla/', + b'bugzilla', + b'bzurl', + default=b'http://localhost/bugzilla/', ) configitem( - b'bugzilla', b'bzuser', default=None, + b'bugzilla', + b'bzuser', + default=None, ) configitem( - b'bugzilla', b'db', default=b'bugs', + b'bugzilla', + b'db', + default=b'bugs', ) configitem( b'bugzilla', @@ -353,19 +365,29 @@ ), ) configitem( - b'bugzilla', b'fixresolution', default=b'FIXED', + b'bugzilla', + b'fixresolution', + default=b'FIXED', ) configitem( - b'bugzilla', b'fixstatus', default=b'RESOLVED', + b'bugzilla', + b'fixstatus', + default=b'RESOLVED', ) configitem( - b'bugzilla', b'host', default=b'localhost', + b'bugzilla', + b'host', + default=b'localhost', ) configitem( - b'bugzilla', b'notify', default=configitem.dynamicdefault, + b'bugzilla', + b'notify', + default=configitem.dynamicdefault, ) configitem( - b'bugzilla', b'password', default=None, + b'bugzilla', + b'password', + default=None, ) configitem( b'bugzilla', @@ -377,25 +399,39 @@ ), ) configitem( - b'bugzilla', b'strip', default=0, + b'bugzilla', + b'strip', + default=0, ) configitem( - b'bugzilla', b'style', default=None, + b'bugzilla', + b'style', + default=None, ) configitem( - b'bugzilla', b'template', default=None, + b'bugzilla', + b'template', + default=None, ) configitem( - b'bugzilla', b'timeout', default=5, + b'bugzilla', + b'timeout', + default=5, ) configitem( - b'bugzilla', b'user', default=b'bugs', + b'bugzilla', + b'user', + default=b'bugs', ) configitem( - b'bugzilla', b'usermap', default=None, + b'bugzilla', + b'usermap', + default=None, ) configitem( - b'bugzilla', b'version', default=None, + b'bugzilla', + b'version', + default=None, ) @@ -430,29 +466,29 @@ '''remove bug IDs where node occurs in comment text from bugs.''' def updatebug(self, bugid, newstate, text, committer): - '''update the specified bug. Add comment text and set new states. + """update the specified bug. Add comment text and set new states. If possible add the comment as being from the committer of the changeset. Otherwise use the default Bugzilla user. - ''' + """ def notify(self, bugs, committer): - '''Force sending of Bugzilla notification emails. + """Force sending of Bugzilla notification emails. Only required if the access method does not trigger notification emails automatically. - ''' + """ # Bugzilla via direct access to MySQL database. class bzmysql(bzaccess): - '''Support for direct MySQL access to Bugzilla. + """Support for direct MySQL access to Bugzilla. The earliest Bugzilla version this is tested with is version 2.16. If your Bugzilla is version 3.4 or above, you are strongly recommended to use the XMLRPC access method instead. - ''' + """ @staticmethod def sql_buglist(ids): @@ -581,9 +617,9 @@ return userid def get_bugzilla_user(self, committer): - '''See if committer is a registered bugzilla user. Return + """See if committer is a registered bugzilla user. Return bugzilla username and userid if so. If not, return default - bugzilla username and userid.''' + bugzilla username and userid.""" user = self.map_committer(committer) try: userid = self.get_user_id(user) @@ -604,10 +640,10 @@ return (user, userid) def updatebug(self, bugid, newstate, text, committer): - '''update bug state with comment text. + """update bug state with comment text. Try adding comment as committer of changeset, otherwise as - default bugzilla user.''' + default bugzilla user.""" if len(newstate) > 0: self.ui.warn(_(b"Bugzilla/MySQL cannot update bug state\n")) @@ -869,7 +905,7 @@ return b"@%s = %s" % (fieldname, pycompat.bytestr(value)) def send_bug_modify_email(self, bugid, commands, comment, committer): - '''send modification message to Bugzilla bug via email. + """send modification message to Bugzilla bug via email. The message format is documented in the Bugzilla email_in.pl specification. commands is a list of command lines, comment is the @@ -878,7 +914,7 @@ To stop users from crafting commit comments with Bugzilla commands, specify the bug ID via the message body, rather than the subject line, and leave a blank line after it. - ''' + """ user = self.map_committer(committer) matches = self.bzproxy.User.get( {b'match': [user], b'token': self.bztoken} @@ -1016,11 +1052,11 @@ del bugs[bugid] def updatebug(self, bugid, newstate, text, committer): - '''update the specified bug. Add comment text and set new states. + """update the specified bug. Add comment text and set new states. If possible add the comment as being from the committer of the changeset. Otherwise use the default Bugzilla user. - ''' + """ bugmod = {} if b'hours' in newstate: bugmod[b'work_time'] = newstate[b'hours'] @@ -1050,11 +1086,11 @@ self.ui.debug(b'added comment to bug %s\n' % bugid) def notify(self, bugs, committer): - '''Force sending of Bugzilla notification emails. + """Force sending of Bugzilla notification emails. Only required if the access method does not trigger notification emails automatically. - ''' + """ pass @@ -1092,12 +1128,12 @@ self.split_re = re.compile(br'\D+') def find_bugs(self, ctx): - '''return bugs dictionary created from commit comment. + """return bugs dictionary created from commit comment. Extract bug info from changeset comments. Filter out any that are not known to Bugzilla, and any that already have a reference to the given changeset in their comments. - ''' + """ start = 0 bugs = {} bugmatch = self.bug_re.search(ctx.description(), start) @@ -1152,8 +1188,8 @@ '''update bugzilla bug with reference to changeset.''' def webroot(root): - '''strip leading prefix of repo root and turn into - url-safe path.''' + """strip leading prefix of repo root and turn into + url-safe path.""" count = int(self.ui.config(b'bugzilla', b'strip')) root = util.pconvert(root) while count > 0: @@ -1195,9 +1231,9 @@ def hook(ui, repo, hooktype, node=None, **kwargs): - '''add comment to bugzilla for each changeset that refers to a + """add comment to bugzilla for each changeset that refers to a bugzilla bug id. only add a comment once per bug, so same change - seen multiple times does not fill bug with duplicate data.''' + seen multiple times does not fill bug with duplicate data.""" if node is None: raise error.Abort( _(b'hook type %s does not pass a changeset id') % hooktype
--- a/hgext/churn.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/churn.py Thu Dec 03 14:15:39 2020 -0500 @@ -156,7 +156,7 @@ inferrepo=True, ) def churn(ui, repo, *pats, **opts): - '''histogram of changes to the repository + """histogram of changes to the repository This command will display a histogram representing the number of changed lines or revisions, grouped according to the given @@ -193,7 +193,7 @@ Such a file may be specified with the --aliases option, otherwise a .hgchurn file will be looked for in the working directory root. Aliases will be split from the rightmost "=". - ''' + """ def pad(s, l): return s + b" " * (l - encoding.colwidth(s))
--- a/hgext/clonebundles.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/clonebundles.py Thu Dec 03 14:15:39 2020 -0500 @@ -205,6 +205,7 @@ from __future__ import absolute_import from mercurial import ( + bundlecaches, extensions, wireprotov1server, ) @@ -218,7 +219,7 @@ # Only advertise if a manifest exists. This does add some I/O to requests. # But this should be cheaper than a wasted network round trip due to # missing file. - if repo.vfs.exists(b'clonebundles.manifest'): + if repo.vfs.exists(bundlecaches.CB_MANIFEST_FILE): caps.append(b'clonebundles') return caps
--- a/hgext/convert/__init__.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/convert/__init__.py Thu Dec 03 14:15:39 2020 -0500 @@ -536,7 +536,7 @@ norepo=True, ) def debugcvsps(ui, *args, **opts): - '''create changeset information from CVS + """create changeset information from CVS This command is intended as a debugging tool for the CVS to Mercurial converter, and can be used as a direct replacement for @@ -545,7 +545,7 @@ Hg debugcvsps reads the CVS rlog for current directory (or any named directory) in the CVS repository, and converts the log to a series of changesets based on matching commit log entries and - dates.''' + dates.""" return cvsps.debugcvsps(ui, *args, **opts)
--- a/hgext/convert/bzr.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/convert/bzr.py Thu Dec 03 14:15:39 2020 -0500 @@ -21,7 +21,11 @@ # these do not work with demandimport, blacklist demandimport.IGNORES.update( - [b'bzrlib.transactions', b'bzrlib.urlutils', b'ElementPath',] + [ + b'bzrlib.transactions', + b'bzrlib.urlutils', + b'ElementPath', + ] ) try:
--- a/hgext/convert/common.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/convert/common.py Thu Dec 03 14:15:39 2020 -0500 @@ -172,8 +172,8 @@ self.encoding = b'utf-8' def checkhexformat(self, revstr, mapname=b'splicemap'): - """ fails if revstr is not a 40 byte hex. mercurial and git both uses - such format for their revision numbering + """fails if revstr is not a 40 byte hex. mercurial and git both uses + such format for their revision numbering """ if not re.match(br'[0-9a-fA-F]{40,40}$', revstr): raise error.Abort( @@ -283,8 +283,7 @@ return False def hasnativeclose(self): - """Return true if this source has ability to close branch. - """ + """Return true if this source has ability to close branch.""" return False def lookuprev(self, rev): @@ -303,8 +302,8 @@ def checkrevformat(self, revstr, mapname=b'splicemap'): """revstr is a string that describes a revision in the given - source control system. Return true if revstr has correct - format. + source control system. Return true if revstr has correct + format. """ return True
--- a/hgext/convert/convcmd.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/convert/convcmd.py Thu Dec 03 14:15:39 2020 -0500 @@ -96,7 +96,7 @@ def mapbranch(branch, branchmap): - ''' + """ >>> bmap = {b'default': b'branch1'} >>> for i in [b'', None]: ... mapbranch(i, bmap) @@ -115,7 +115,7 @@ 'branch4' 'branch4' 'branch5' - ''' + """ # If branch is None or empty, this commit is coming from the source # repository's default branch and destined for the default branch in the # destination repository. For such commits, using a literal "default" @@ -228,14 +228,14 @@ self.branchmap = mapfile(ui, opts.get(b'branchmap')) def parsesplicemap(self, path): - """ check and validate the splicemap format and - return a child/parents dictionary. - Format checking has two parts. - 1. generic format which is same across all source types - 2. specific format checking which may be different for - different source type. This logic is implemented in - checkrevformat function in source files like - hg.py, subversion.py etc. + """check and validate the splicemap format and + return a child/parents dictionary. + Format checking has two parts. + 1. generic format which is same across all source types + 2. specific format checking which may be different for + different source type. This logic is implemented in + checkrevformat function in source files like + hg.py, subversion.py etc. """ if not path: @@ -275,8 +275,8 @@ return m def walktree(self, heads): - '''Return a mapping that identifies the uncommitted parents of every - uncommitted changeset.''' + """Return a mapping that identifies the uncommitted parents of every + uncommitted changeset.""" visit = list(heads) known = set() parents = {} @@ -332,8 +332,8 @@ parents[c] = pc def toposort(self, parents, sortmode): - '''Return an ordering such that every uncommitted changeset is - preceded by all its uncommitted ancestors.''' + """Return an ordering such that every uncommitted changeset is + preceded by all its uncommitted ancestors.""" def mapchildren(parents): """Return a (children, roots) tuple where 'children' maps parent
--- a/hgext/convert/cvsps.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/convert/cvsps.py Thu Dec 03 14:15:39 2020 -0500 @@ -29,25 +29,25 @@ class logentry(object): - '''Class logentry has the following attributes: - .author - author name as CVS knows it - .branch - name of branch this revision is on - .branches - revision tuple of branches starting at this revision - .comment - commit message - .commitid - CVS commitid or None - .date - the commit date as a (time, tz) tuple - .dead - true if file revision is dead - .file - Name of file - .lines - a tuple (+lines, -lines) or None - .parent - Previous revision of this entry - .rcs - name of file as returned from CVS - .revision - revision number as tuple - .tags - list of tags on the file - .synthetic - is this a synthetic "file ... added on ..." revision? - .mergepoint - the branch that has been merged from (if present in - rlog output) or None - .branchpoints - the branches that start at the current entry or empty - ''' + """Class logentry has the following attributes: + .author - author name as CVS knows it + .branch - name of branch this revision is on + .branches - revision tuple of branches starting at this revision + .comment - commit message + .commitid - CVS commitid or None + .date - the commit date as a (time, tz) tuple + .dead - true if file revision is dead + .file - Name of file + .lines - a tuple (+lines, -lines) or None + .parent - Previous revision of this entry + .rcs - name of file as returned from CVS + .revision - revision number as tuple + .tags - list of tags on the file + .synthetic - is this a synthetic "file ... added on ..." revision? + .mergepoint - the branch that has been merged from (if present in + rlog output) or None + .branchpoints - the branches that start at the current entry or empty + """ def __init__(self, **entries): self.synthetic = False @@ -580,20 +580,20 @@ class changeset(object): - '''Class changeset has the following attributes: - .id - integer identifying this changeset (list index) - .author - author name as CVS knows it - .branch - name of branch this changeset is on, or None - .comment - commit message - .commitid - CVS commitid or None - .date - the commit date as a (time,tz) tuple - .entries - list of logentry objects in this changeset - .parents - list of one or two parent changesets - .tags - list of tags on this changeset - .synthetic - from synthetic revision "file ... added on branch ..." - .mergepoint- the branch that has been merged from or None - .branchpoints- the branches that start at the current entry or empty - ''' + """Class changeset has the following attributes: + .id - integer identifying this changeset (list index) + .author - author name as CVS knows it + .branch - name of branch this changeset is on, or None + .comment - commit message + .commitid - CVS commitid or None + .date - the commit date as a (time,tz) tuple + .entries - list of logentry objects in this changeset + .parents - list of one or two parent changesets + .tags - list of tags on this changeset + .synthetic - from synthetic revision "file ... added on branch ..." + .mergepoint- the branch that has been merged from or None + .branchpoints- the branches that start at the current entry or empty + """ def __init__(self, **entries): self.id = None @@ -945,10 +945,10 @@ def debugcvsps(ui, *args, **opts): - '''Read CVS rlog for current directory or named path in + """Read CVS rlog for current directory or named path in repository, and convert the log to changesets based on matching commit log entries and dates. - ''' + """ opts = pycompat.byteskwargs(opts) if opts[b"new_cache"]: cache = b"write"
--- a/hgext/convert/filemap.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/convert/filemap.py Thu Dec 03 14:15:39 2020 -0500 @@ -19,14 +19,14 @@ def rpairs(path): - '''Yield tuples with path split at '/', starting with the full path. + """Yield tuples with path split at '/', starting with the full path. No leading, trailing or double '/', please. >>> for x in rpairs(b'foo/bar/baz'): print(x) ('foo/bar/baz', '') ('foo/bar', 'baz') ('foo', 'bar/baz') ('.', 'foo/bar/baz') - ''' + """ i = len(path) while i != -1: yield path[:i], path[i + 1 :] @@ -35,17 +35,17 @@ def normalize(path): - ''' We use posixpath.normpath to support cross-platform path format. - However, it doesn't handle None input. So we wrap it up. ''' + """We use posixpath.normpath to support cross-platform path format. + However, it doesn't handle None input. So we wrap it up.""" if path is None: return None return posixpath.normpath(path) class filemapper(object): - '''Map and filter filenames when importing. + """Map and filter filenames when importing. A name can be mapped to itself, a new name, or None (omit from new - repository).''' + repository).""" def __init__(self, ui, path=None): self.ui = ui
--- a/hgext/convert/hg.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/convert/hg.py Thu Dec 03 14:15:39 2020 -0500 @@ -398,7 +398,7 @@ ctx = self.repo[node] if ctx.phase() < phases.draft: phases.registernew( - self.repo, tr, phases.draft, [ctx.node()] + self.repo, tr, phases.draft, [ctx.rev()] ) text = b"(octopus merge fixup)\n"
--- a/hgext/eol.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/eol.py Thu Dec 03 14:15:39 2020 -0500 @@ -118,13 +118,19 @@ configitem = registrar.configitem(configtable) configitem( - b'eol', b'fix-trailing-newline', default=False, + b'eol', + b'fix-trailing-newline', + default=False, ) configitem( - b'eol', b'native', default=pycompat.oslinesep, + b'eol', + b'native', + default=pycompat.oslinesep, ) configitem( - b'eol', b'only-consistent', default=True, + b'eol', + b'only-consistent', + default=True, ) # Matches a lone LF, i.e., one that is not part of CRLF. @@ -274,13 +280,13 @@ return eolfile(ui, repo.root, data) except (IOError, LookupError): pass - except errormod.ParseError as inst: + except errormod.ConfigError as inst: ui.warn( _( b"warning: ignoring .hgeol file due to parse error " b"at %s: %s\n" ) - % (inst.args[1], inst.args[0]) + % (inst.location, inst.message) ) return None
--- a/hgext/extdiff.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/extdiff.py Thu Dec 03 14:15:39 2020 -0500 @@ -118,19 +118,29 @@ configitem = registrar.configitem(configtable) configitem( - b'extdiff', br'opts\..*', default=b'', generic=True, + b'extdiff', + br'opts\..*', + default=b'', + generic=True, ) configitem( - b'extdiff', br'gui\..*', generic=True, + b'extdiff', + br'gui\..*', + generic=True, ) configitem( - b'diff-tools', br'.*\.diffargs$', default=None, generic=True, + b'diff-tools', + br'.*\.diffargs$', + default=None, + generic=True, ) configitem( - b'diff-tools', br'.*\.gui$', generic=True, + b'diff-tools', + br'.*\.gui$', + generic=True, ) # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for @@ -141,9 +151,9 @@ def snapshot(ui, repo, files, node, tmproot, listsubrepos): - '''snapshot files as of some revision + """snapshot files as of some revision if not using snapshot, -I/-X does not work and recursive diff - in tools like kdiff3 and meld displays too many files.''' + in tools like kdiff3 and meld displays too many files.""" dirname = os.path.basename(repo.root) if dirname == b"": dirname = b"root" @@ -230,9 +240,9 @@ def _systembackground(cmd, environ=None, cwd=None): - ''' like 'procutil.system', but returns the Popen object directly - so we don't have to wait on it. - ''' + """like 'procutil.system', but returns the Popen object directly + so we don't have to wait on it. + """ env = procutil.shellenviron(environ) proc = subprocess.Popen( procutil.tonativestr(cmd), @@ -530,13 +540,13 @@ def dodiff(ui, repo, cmdline, pats, opts, guitool=False): - '''Do the actual diff: + """Do the actual diff: - copy to a temp structure if diffing 2 internal revisions - copy to a temp structure if diffing working revision with another one and more than 1 file is changed - just invoke the diff for a single file in the working dir - ''' + """ cmdutil.check_at_most_one_arg(opts, b'rev', b'change') revs = opts.get(b'rev') @@ -628,14 +638,16 @@ @command( b'extdiff', - [(b'p', b'program', b'', _(b'comparison program to run'), _(b'CMD')),] + [ + (b'p', b'program', b'', _(b'comparison program to run'), _(b'CMD')), + ] + extdiffopts, _(b'hg extdiff [OPT]... [FILE]...'), helpcategory=command.CATEGORY_FILE_CONTENTS, inferrepo=True, ) def extdiff(ui, repo, *pats, **opts): - '''use external program to diff repository (or selected files) + """use external program to diff repository (or selected files) Show differences between revisions for the specified files, using an external program. The default program used is diff, with @@ -664,7 +676,7 @@ The --confirm option will prompt the user before each invocation of the external program. It is ignored if --per-file isn't specified. - ''' + """ opts = pycompat.byteskwargs(opts) program = opts.get(b'program') option = opts.get(b'option')
--- a/hgext/factotum.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/factotum.py Thu Dec 03 14:15:39 2020 -0500 @@ -70,13 +70,19 @@ configitem = registrar.configitem(configtable) configitem( - b'factotum', b'executable', default=b'/bin/auth/factotum', + b'factotum', + b'executable', + default=b'/bin/auth/factotum', ) configitem( - b'factotum', b'mountpoint', default=b'/mnt/factotum', + b'factotum', + b'mountpoint', + default=b'/mnt/factotum', ) configitem( - b'factotum', b'service', default=b'hg', + b'factotum', + b'service', + default=b'hg', )
--- a/hgext/fetch.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/fetch.py Thu Dec 03 14:15:39 2020 -0500 @@ -54,7 +54,7 @@ helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT, ) def fetch(ui, repo, source=b'default', **opts): - '''pull changes from a remote repository, merge new changes if needed. + """pull changes from a remote repository, merge new changes if needed. This finds all changes from the repository at the specified path or URL and adds them to the local repository. @@ -71,7 +71,7 @@ See :hg:`help dates` for a list of formats valid for -d/--date. Returns 0 on success. - ''' + """ opts = pycompat.byteskwargs(opts) date = opts.get(b'date')
--- a/hgext/fix.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/fix.py Thu Dec 03 14:15:39 2020 -0500 @@ -372,7 +372,7 @@ def getworkqueue(ui, repo, pats, opts, revstofix, basectxs): - """"Constructs the list of files to be fixed at specific revisions + """Constructs the list of files to be fixed at specific revisions It is up to the caller how to consume the work items, and the only dependence between them is that replacement revisions must be committed in @@ -417,7 +417,7 @@ revs = repo.revs(b'(not public() and not obsolete()) or wdir()') elif opts[b'source']: source_revs = scmutil.revrange(repo, opts[b'source']) - revs = set(repo.revs(b'%ld::', source_revs)) + revs = set(repo.revs(b'(%ld::) - obsolete()', source_revs)) if wdirrev in source_revs: # `wdir()::` is currently empty, so manually add wdir revs.add(wdirrev) @@ -427,8 +427,8 @@ revs = set(scmutil.revrange(repo, opts[b'rev'])) if opts.get(b'working_dir'): revs.add(wdirrev) - for rev in revs: - checkfixablectx(ui, repo, repo[rev]) + for rev in revs: + checkfixablectx(ui, repo, repo[rev]) # Allow fixing only wdir() even if there's an unfinished operation if not (len(revs) == 1 and wdirrev in revs): cmdutil.checkunfinished(repo) @@ -439,7 +439,7 @@ raise error.Abort(b'unresolved conflicts', hint=b"use 'hg resolve'") if not revs: raise error.Abort( - b'no changesets specified', hint=b'use --rev or --working-dir' + b'no changesets specified', hint=b'use --source or --working-dir' ) return revs
--- a/hgext/fsmonitor/__init__.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/fsmonitor/__init__.py Thu Dec 03 14:15:39 2020 -0500 @@ -154,25 +154,40 @@ configitem = registrar.configitem(configtable) configitem( - b'fsmonitor', b'mode', default=b'on', + b'fsmonitor', + b'mode', + default=b'on', ) configitem( - b'fsmonitor', b'walk_on_invalidate', default=False, + b'fsmonitor', + b'walk_on_invalidate', + default=False, ) configitem( - b'fsmonitor', b'timeout', default=b'2', + b'fsmonitor', + b'timeout', + default=b'2', ) configitem( - b'fsmonitor', b'blacklistusers', default=list, + b'fsmonitor', + b'blacklistusers', + default=list, +) +configitem( + b'fsmonitor', + b'watchman_exe', + default=b'watchman', ) configitem( - b'fsmonitor', b'watchman_exe', default=b'watchman', + b'fsmonitor', + b'verbose', + default=True, + experimental=True, ) configitem( - b'fsmonitor', b'verbose', default=True, experimental=True, -) -configitem( - b'experimental', b'fsmonitor.transaction_notify', default=False, + b'experimental', + b'fsmonitor.transaction_notify', + default=False, ) # This extension is incompatible with the following blacklisted extensions @@ -271,11 +286,11 @@ def overridewalk(orig, self, match, subrepos, unknown, ignored, full=True): - '''Replacement for dirstate.walk, hooking into Watchman. + """Replacement for dirstate.walk, hooking into Watchman. Whenever full is False, ignored is False, and the Watchman client is available, use Watchman combined with saved state to possibly return only a - subset of files.''' + subset of files.""" def bail(reason): self._ui.debug(b'fsmonitor: fallback to core status, %s\n' % reason) @@ -731,8 +746,8 @@ def wrapsymlink(orig, source, link_name): - ''' if we create a dangling symlink, also touch the parent dir - to encourage fsevents notifications to work more correctly ''' + """if we create a dangling symlink, also touch the parent dir + to encourage fsevents notifications to work more correctly""" try: return orig(source, link_name) finally: @@ -743,13 +758,13 @@ class state_update(object): - ''' This context manager is responsible for dispatching the state-enter - and state-leave signals to the watchman service. The enter and leave - methods can be invoked manually (for scenarios where context manager - semantics are not possible). If parameters oldnode and newnode are None, - they will be populated based on current working copy in enter and - leave, respectively. Similarly, if the distance is none, it will be - calculated based on the oldnode and newnode in the leave method.''' + """This context manager is responsible for dispatching the state-enter + and state-leave signals to the watchman service. The enter and leave + methods can be invoked manually (for scenarios where context manager + semantics are not possible). If parameters oldnode and newnode are None, + they will be populated based on current working copy in enter and + leave, respectively. Similarly, if the distance is none, it will be + calculated based on the oldnode and newnode in the leave method.""" def __init__( self,
--- a/hgext/fsmonitor/pywatchman/__init__.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/fsmonitor/pywatchman/__init__.py Thu Dec 03 14:15:39 2020 -0500 @@ -282,11 +282,11 @@ class SocketTimeout(WatchmanError): """A specialized exception raised for socket timeouts during communication to/from watchman. - This makes it easier to implement non-blocking loops as callers can easily distinguish - between a routine timeout and an actual error condition. + This makes it easier to implement non-blocking loops as callers can easily distinguish + between a routine timeout and an actual error condition. - Note that catching WatchmanError will also catch this as it is a super-class, so backwards - compatibility in exception handling is preserved. + Note that catching WatchmanError will also catch this as it is a super-class, so backwards + compatibility in exception handling is preserved. """ @@ -323,7 +323,7 @@ pass def readLine(self): - """ read a line + """read a line Maintains its own buffer, callers of the transport should not mix calls to readBytes and readLine. """ @@ -409,7 +409,7 @@ def _get_overlapped_result_ex_impl(pipe, olap, nbytes, millis, alertable): - """ Windows 7 and earlier does not support GetOverlappedResultEx. The + """Windows 7 and earlier does not support GetOverlappedResultEx. The alternative is to use GetOverlappedResult and wait for read or write operation to complete. This is done be using CreateEvent and WaitForSingleObjectEx. CreateEvent, WaitForSingleObjectEx @@ -510,9 +510,9 @@ self.timeout = int(value * 1000) def readBytes(self, size): - """ A read can block for an unbounded amount of time, even if the - kernel reports that the pipe handle is signalled, so we need to - always perform our reads asynchronously + """A read can block for an unbounded amount of time, even if the + kernel reports that the pipe handle is signalled, so we need to + always perform our reads asynchronously """ # try to satisfy the read from any buffered data @@ -627,7 +627,7 @@ class CLIProcessTransport(Transport): - """ open a pipe to the cli to talk to the service + """open a pipe to the cli to talk to the service This intended to be used only in the test harness! The CLI is an oddball because we only support JSON input @@ -739,8 +739,8 @@ class ImmutableBserCodec(BserCodec): - """ use the BSER encoding, decoding values using the newer - immutable object support """ + """use the BSER encoding, decoding values using the newer + immutable object support""" def _loads(self, response): return bser.loads( @@ -817,8 +817,8 @@ class ImmutableBser2Codec(Bser2WithFallbackCodec, ImmutableBserCodec): - """ use the BSER encoding, decoding values using the newer - immutable object support """ + """use the BSER encoding, decoding values using the newer + immutable object support""" pass @@ -1050,7 +1050,7 @@ self.sendConn = None def receive(self): - """ receive the next PDU from the watchman service + """receive the next PDU from the watchman service If the client has activated subscriptions or logs then this PDU may be a unilateral PDU sent by the service to @@ -1098,7 +1098,7 @@ return False def getLog(self, remove=True): - """ Retrieve buffered log data + """Retrieve buffered log data If remove is true the data will be removed from the buffer. Otherwise it will be left in the buffer @@ -1109,7 +1109,7 @@ return res def getSubscription(self, name, remove=True, root=None): - """ Retrieve the data associated with a named subscription + """Retrieve the data associated with a named subscription If remove is True (the default), the subscription data is removed from the buffer. Otherwise the data is returned but left in @@ -1144,7 +1144,7 @@ return sub def query(self, *args): - """ Send a query to the watchman service and return the response + """Send a query to the watchman service and return the response This call will block until the response is returned. If any unilateral responses are sent by the service in between
--- a/hgext/fsmonitor/pywatchman/capabilities.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/fsmonitor/pywatchman/capabilities.py Thu Dec 03 14:15:39 2020 -0500 @@ -55,8 +55,8 @@ def synthesize(vers, opts): - """ Synthesize a capability enabled version response - This is a very limited emulation for relatively recent feature sets + """Synthesize a capability enabled version response + This is a very limited emulation for relatively recent feature sets """ parsed_version = parse_version(vers["version"]) vers["capabilities"] = {}
--- a/hgext/git/__init__.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/git/__init__.py Thu Dec 03 14:15:39 2020 -0500 @@ -29,13 +29,24 @@ index, ) +# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for +# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should +# be specifying the version(s) of Mercurial they are tested with, or +# leave the attribute unspecified. +testedwith = b'ships-with-hg-core' + configtable = {} configitem = registrar.configitem(configtable) # git.log-index-cache-miss: internal knob for testing configitem( - b"git", b"log-index-cache-miss", default=False, + b"git", + b"log-index-cache-miss", + default=False, ) +getversion = gitutil.pygit2_version + + # TODO: extract an interface for this in core class gitstore(object): # store.basicstore): def __init__(self, path, vfstype): @@ -224,8 +235,7 @@ return bname def applychanges(self, repo, tr, changes): - """Apply a list of changes to bookmarks - """ + """Apply a list of changes to bookmarks""" # TODO: this should respect transactions, but that's going to # require enlarging the gitbmstore to know how to do in-memory # temporary writes and read those back prior to transaction
--- a/hgext/git/gitlog.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/git/gitlog.py Thu Dec 03 14:15:39 2020 -0500 @@ -148,6 +148,12 @@ ) return (int(r[0]) for r in t) + def tiprev(self): + t = self._db.execute( + 'SELECT rev FROM changelog ' 'ORDER BY REV DESC ' 'LIMIT 1' + ) + return next(t) + def _partialmatch(self, id): if nodemod.wdirhex.startswith(id): raise error.WdirUnsupported
--- a/hgext/git/gitutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/git/gitutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -20,6 +20,19 @@ return pygit2_module +def pygit2_version(): + mod = get_pygit2() + v = "N/A" + + if mod: + try: + v = mod.__version__ + except AttributeError: + pass + + return b"(pygit2 %s)" % v.encode("utf-8") + + def togitnode(n): """Wrapper to convert a Mercurial binary node to a unicode hexlified node.
--- a/hgext/git/manifest.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/git/manifest.py Thu Dec 03 14:15:39 2020 -0500 @@ -127,7 +127,7 @@ return dir in self._dirs def diff(self, other, match=lambda x: True, clean=False): - '''Finds changes between the current manifest and m2. + """Finds changes between the current manifest and m2. The result is returned as a dict with filename as key and values of the form ((n1,fl1),(n2,fl2)), where n1/n2 is the @@ -135,7 +135,7 @@ in the current/other manifest. Where the file does not exist, the nodeid will be None and the flags will be the empty string. - ''' + """ result = {} def _iterativediff(t1, t2, subdir):
--- a/hgext/githelp.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/githelp.py Thu Dec 03 14:15:39 2020 -0500 @@ -59,10 +59,10 @@ helpbasic=True, ) def githelp(ui, repo, *args, **kwargs): - '''suggests the Mercurial equivalent of the given git command + """suggests the Mercurial equivalent of the given git command Usage: hg githelp -- <git command> - ''' + """ if len(args) == 0 or (len(args) == 1 and args[0] == b'git'): raise error.Abort(
--- a/hgext/gpg.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/gpg.py Thu Dec 03 14:15:39 2020 -0500 @@ -37,13 +37,20 @@ configitem = registrar.configitem(configtable) configitem( - b'gpg', b'cmd', default=b'gpg', + b'gpg', + b'cmd', + default=b'gpg', ) configitem( - b'gpg', b'key', default=None, + b'gpg', + b'key', + default=None, ) configitem( - b'gpg', b'.*', default=None, generic=True, + b'gpg', + b'.*', + default=None, + generic=True, ) # Custom help category @@ -78,7 +85,11 @@ fp.close() gpgcmd = ( b"%s --logger-fd 1 --status-fd 1 --verify \"%s\" \"%s\"" - % (self.path, sigfile, datafile,) + % ( + self.path, + sigfile, + datafile, + ) ) ret = procutil.filter(b"", gpgcmd) finally:
--- a/hgext/hgk.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/hgk.py Thu Dec 03 14:15:39 2020 -0500 @@ -65,7 +65,9 @@ configitem = registrar.configitem(configtable) configitem( - b'hgk', b'path', default=b'hgk', + b'hgk', + b'path', + default=b'hgk', )
--- a/hgext/histedit.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/histedit.py Thu Dec 03 14:15:39 2020 -0500 @@ -247,22 +247,34 @@ configtable = {} configitem = registrar.configitem(configtable) configitem( - b'experimental', b'histedit.autoverb', default=False, + b'experimental', + b'histedit.autoverb', + default=False, ) configitem( - b'histedit', b'defaultrev', default=None, + b'histedit', + b'defaultrev', + default=None, ) configitem( - b'histedit', b'dropmissing', default=False, + b'histedit', + b'dropmissing', + default=False, ) configitem( - b'histedit', b'linelen', default=80, + b'histedit', + b'linelen', + default=80, ) configitem( - b'histedit', b'singletransaction', default=False, + b'histedit', + b'singletransaction', + default=False, ) configitem( - b'ui', b'interface.histedit', default=None, + b'ui', + b'interface.histedit', + default=None, ) configitem(b'histedit', b'summary-template', default=b'{rev} {desc|firstline}') @@ -280,7 +292,7 @@ def geteditcomment(ui, first, last): - """ construct the editor comment + """construct the editor comment The comment includes:: - an intro - sorted primary commands @@ -477,8 +489,7 @@ @classmethod def fromrule(cls, state, rule): - """Parses the given rule, returning an instance of the histeditaction. - """ + """Parses the given rule, returning an instance of the histeditaction.""" ruleid = rule.strip().split(b' ', 1)[0] # ruleid can be anything from rev numbers, hashes, "bookmarks" etc # Check for validation of rule ids and get the rulehash @@ -525,13 +536,16 @@ """ ctx = self.repo[self.node] ui = self.repo.ui - summary = ( - cmdutil.rendertemplate( + # We don't want color codes in the commit message template, so + # disable the label() template function while we render it. + with ui.configoverride( + {(b'templatealias', b'label(l,x)'): b"x"}, b'histedit' + ): + summary = cmdutil.rendertemplate( ctx, ui.config(b'histedit', b'summary-template') ) - or b'' - ) - summary = summary.splitlines()[0] + # Handle the fact that `''.splitlines() => []` + summary = summary.splitlines()[0] if summary else b'' line = b'%s %s %s' % (self.verb, ctx, summary) # trim to 75 columns by default so it's not stupidly wide in my editor # (the 5 more are left for verb) @@ -541,7 +555,7 @@ def tostate(self): """Print an action in format used by histedit state files - (the first line is a verb, the remainder is the second) + (the first line is a verb, the remainder is the second) """ return b"%s\n%s" % (self.verb, node.hex(self.node)) @@ -1152,11 +1166,8 @@ @util.propertycache def desc(self): - summary = ( - cmdutil.rendertemplate( - self.ctx, self.ui.config(b'histedit', b'summary-template') - ) - or b'' + summary = cmdutil.rendertemplate( + self.ctx, self.ui.config(b'histedit', b'summary-template') ) if summary: return summary @@ -1178,8 +1189,8 @@ # ============ EVENTS =============== def movecursor(state, oldpos, newpos): - '''Change the rule/changeset that the cursor is pointing to, regardless of - current mode (you can switch between patches from the view patch window).''' + """Change the rule/changeset that the cursor is pointing to, regardless of + current mode (you can switch between patches from the view patch window).""" state[b'pos'] = newpos mode, _ = state[b'mode'] @@ -1256,8 +1267,8 @@ def changeview(state, delta, unit): - '''Change the region of whatever is being viewed (a patch or the list of - changesets). 'delta' is an amount (+/- 1) and 'unit' is 'page' or 'line'.''' + """Change the region of whatever is being viewed (a patch or the list of + changesets). 'delta' is an amount (+/- 1) and 'unit' is 'page' or 'line'.""" mode, _ = state[b'mode'] if mode != MODE_PATCH: return @@ -1582,8 +1593,12 @@ b'mode': (MODE_INIT, MODE_INIT), b'page_height': None, b'modes': { - MODE_RULES: {b'line_offset': 0,}, - MODE_PATCH: {b'line_offset': 0,}, + MODE_RULES: { + b'line_offset': 0, + }, + MODE_PATCH: { + b'line_offset': 0, + }, }, b'repo': repo, }
--- a/hgext/hooklib/changeset_obsoleted.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/hooklib/changeset_obsoleted.py Thu Dec 03 14:15:39 2020 -0500 @@ -40,10 +40,14 @@ configitem = registrar.configitem(configtable) configitem( - b'notify_obsoleted', b'domain', default=None, + b'notify_obsoleted', + b'domain', + default=None, ) configitem( - b'notify_obsoleted', b'messageidseed', default=None, + b'notify_obsoleted', + b'messageidseed', + default=None, ) configitem( b'notify_obsoleted',
--- a/hgext/hooklib/changeset_published.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/hooklib/changeset_published.py Thu Dec 03 14:15:39 2020 -0500 @@ -39,10 +39,14 @@ configitem = registrar.configitem(configtable) configitem( - b'notify_published', b'domain', default=None, + b'notify_published', + b'domain', + default=None, ) configitem( - b'notify_published', b'messageidseed', default=None, + b'notify_published', + b'messageidseed', + default=None, ) configitem( b'notify_published',
--- a/hgext/infinitepush/__init__.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/infinitepush/__init__.py Thu Dec 03 14:15:39 2020 -0500 @@ -154,37 +154,59 @@ configitem = registrar.configitem(configtable) configitem( - b'infinitepush', b'server', default=False, + b'infinitepush', + b'server', + default=False, ) configitem( - b'infinitepush', b'storetype', default=b'', + b'infinitepush', + b'storetype', + default=b'', ) configitem( - b'infinitepush', b'indextype', default=b'', + b'infinitepush', + b'indextype', + default=b'', ) configitem( - b'infinitepush', b'indexpath', default=b'', + b'infinitepush', + b'indexpath', + default=b'', ) configitem( - b'infinitepush', b'storeallparts', default=False, + b'infinitepush', + b'storeallparts', + default=False, ) configitem( - b'infinitepush', b'reponame', default=b'', + b'infinitepush', + b'reponame', + default=b'', ) configitem( - b'scratchbranch', b'storepath', default=b'', + b'scratchbranch', + b'storepath', + default=b'', ) configitem( - b'infinitepush', b'branchpattern', default=b'', + b'infinitepush', + b'branchpattern', + default=b'', ) configitem( - b'infinitepush', b'pushtobundlestore', default=False, + b'infinitepush', + b'pushtobundlestore', + default=False, ) configitem( - b'experimental', b'server-bundlestore-bookmark', default=b'', + b'experimental', + b'server-bundlestore-bookmark', + default=b'', ) configitem( - b'experimental', b'infinitepush-scratchpush', default=False, + b'experimental', + b'infinitepush-scratchpush', + default=False, ) experimental = b'experimental' @@ -249,13 +271,13 @@ def _tryhoist(ui, remotebookmark): - '''returns a bookmarks with hoisted part removed + """returns a bookmarks with hoisted part removed Remotenames extension has a 'hoist' config that allows to use remote bookmarks without specifying remote path. For example, 'hg update master' works as well as 'hg update remote/master'. We want to allow the same in infinitepush. - ''' + """ if common.isremotebooksenabled(ui): hoist = ui.config(b'remotenames', b'hoistedpeer') + b'/' @@ -427,11 +449,11 @@ def _includefilelogstobundle(bundlecaps, bundlerepo, bundlerevs, ui): - '''Tells remotefilelog to include all changed files to the changegroup + """Tells remotefilelog to include all changed files to the changegroup By default remotefilelog doesn't include file content to the changegroup. But we need to include it if we are fetching from bundlestore. - ''' + """ changedfiles = set() cl = bundlerepo.changelog for r in bundlerevs: @@ -457,11 +479,11 @@ def _rebundle(bundlerepo, bundleroots, unknownhead): - ''' + """ Bundle may include more revision then user requested. For example, if user asks for revision but bundle also consists its descendants. This function will filter out all revision that user is not requested. - ''' + """ parts = [] version = b'02' @@ -499,10 +521,10 @@ def _generateoutputparts(head, bundlerepo, bundleroots, bundlefile): - '''generates bundle that will be send to the user + """generates bundle that will be send to the user returns tuple with raw bundle string and bundle type - ''' + """ parts = [] if not _needsrebundling(head, bundlerepo): with util.posixfile(bundlefile, b"rb") as f: @@ -1022,7 +1044,12 @@ ) rpart.addparam(b'return', b'1', mandatory=False) - op.records.add(part.type, {b'return': 1,}) + op.records.add( + part.type, + { + b'return': 1, + }, + ) if bundlepart: bundler.addpart(bundlepart) @@ -1112,7 +1139,12 @@ bundle2._processpart(op, part) if handleallparts: - op.records.add(part.type, {b'return': 1,}) + op.records.add( + part.type, + { + b'return': 1, + }, + ) if bundlepart: bundler.addpart(bundlepart) @@ -1284,11 +1316,11 @@ def bundle2pushkey(orig, op, part): - '''Wrapper of bundle2.handlepushkey() + """Wrapper of bundle2.handlepushkey() The only goal is to skip calling the original function if flag is set. It's set if infinitepush push is happening. - ''' + """ if op.records[scratchbranchparttype + b'_skippushkey']: if op.reply is not None: rpart = op.reply.newpart(b'reply:pushkey') @@ -1300,11 +1332,11 @@ def bundle2handlephases(orig, op, part): - '''Wrapper of bundle2.handlephases() + """Wrapper of bundle2.handlephases() The only goal is to skip calling the original function if flag is set. It's set if infinitepush push is happening. - ''' + """ if op.records[scratchbranchparttype + b'_skipphaseheads']: return @@ -1313,11 +1345,11 @@ def _asyncsavemetadata(root, nodes): - '''starts a separate process that fills metadata for the nodes + """starts a separate process that fills metadata for the nodes This function creates a separate process and doesn't wait for it's completion. This was done to avoid slowing down pushes - ''' + """ maxnodes = 50 if len(nodes) > maxnodes:
--- a/hgext/infinitepush/bundleparts.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/infinitepush/bundleparts.py Thu Dec 03 14:15:39 2020 -0500 @@ -90,11 +90,11 @@ def _handlelfs(repo, missing): - '''Special case if lfs is enabled + """Special case if lfs is enabled If lfs is enabled then we need to call prepush hook to make sure large files are uploaded to lfs - ''' + """ try: lfsmod = extensions.find(b'lfs') lfsmod.wrapper.uploadblobsfromrevs(repo, missing)
--- a/hgext/infinitepush/indexapi.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/infinitepush/indexapi.py Thu Dec 03 14:15:39 2020 -0500 @@ -47,8 +47,7 @@ raise NotImplementedError() def deletebookmarks(self, patterns): - """Accepts list of bookmarks and deletes them. - """ + """Accepts list of bookmarks and deletes them.""" raise NotImplementedError() def getbundle(self, node):
--- a/hgext/infinitepush/sqlindexapi.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/infinitepush/sqlindexapi.py Thu Dec 03 14:15:39 2020 -0500 @@ -28,9 +28,9 @@ class sqlindexapi(indexapi.indexapi): - ''' + """ Sql backend for infinitepush index. See schema.sql - ''' + """ def __init__( self,
--- a/hgext/keyword.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/keyword.py Thu Dec 03 14:15:39 2020 -0500 @@ -158,13 +158,14 @@ configitem = registrar.configitem(configtable) configitem( - b'keywordset', b'svn', default=False, + b'keywordset', + b'svn', + default=False, ) # date like in cvs' $Date @templatefilter(b'utcdate', intype=templateutil.date) def utcdate(date): - '''Date. Returns a UTC-date in this format: "2009/08/18 11:00:13". - ''' + """Date. Returns a UTC-date in this format: "2009/08/18 11:00:13".""" dateformat = b'%Y/%m/%d %H:%M:%S' return dateutil.datestr((date[0], 0), dateformat) @@ -172,18 +173,18 @@ # date like in svn's $Date @templatefilter(b'svnisodate', intype=templateutil.date) def svnisodate(date): - '''Date. Returns a date in this format: "2009-08-18 13:00:13 + """Date. Returns a date in this format: "2009-08-18 13:00:13 +0200 (Tue, 18 Aug 2009)". - ''' + """ return dateutil.datestr(date, b'%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)') # date like in svn's $Id @templatefilter(b'svnutcdate', intype=templateutil.date) def svnutcdate(date): - '''Date. Returns a UTC-date in this format: "2009-08-18 + """Date. Returns a UTC-date in this format: "2009-08-18 11:00:13Z". - ''' + """ dateformat = b'%Y-%m-%d %H:%M:%SZ' return dateutil.datestr((date[0], 0), dateformat) @@ -221,25 +222,25 @@ def _shrinktext(text, subfunc): - '''Helper for keyword expansion removal in text. - Depending on subfunc also returns number of substitutions.''' + """Helper for keyword expansion removal in text. + Depending on subfunc also returns number of substitutions.""" return subfunc(br'$\1$', text) def _preselect(wstatus, changed): - '''Retrieves modified and added files from a working directory state + """Retrieves modified and added files from a working directory state and returns the subset of each contained in given changed files - retrieved from a change context.''' + retrieved from a change context.""" modified = [f for f in wstatus.modified if f in changed] added = [f for f in wstatus.added if f in changed] return modified, added class kwtemplater(object): - ''' + """ Sets up keyword templates, corresponding keyword regex, and provides keyword substitution functions. - ''' + """ def __init__(self, ui, repo, inc, exc): self.ui = ui @@ -304,8 +305,8 @@ return data def iskwfile(self, cand, ctx): - '''Returns subset of candidates which are configured for keyword - expansion but are not symbolic links.''' + """Returns subset of candidates which are configured for keyword + expansion but are not symbolic links.""" return [f for f in cand if self.match(f) and b'l' not in ctx.flags(f)] def overwrite(self, ctx, candidates, lookup, expand, rekw=False): @@ -374,18 +375,18 @@ return lines def wread(self, fname, data): - '''If in restricted mode returns data read from wdir with - keyword substitutions removed.''' + """If in restricted mode returns data read from wdir with + keyword substitutions removed.""" if self.restrict: return self.shrink(fname, data) return data class kwfilelog(filelog.filelog): - ''' + """ Subclass of filelog to hook into its read, add, cmp methods. Keywords are "stored" unexpanded, and processed on reading. - ''' + """ def __init__(self, opener, kwt, path): super(kwfilelog, self).__init__(opener, path) @@ -411,8 +412,8 @@ def _status(ui, repo, wctx, kwt, *pats, **opts): - '''Bails out if [keyword] configuration is not active. - Returns status of working directory.''' + """Bails out if [keyword] configuration is not active. + Returns status of working directory.""" if kwt: opts = pycompat.byteskwargs(opts) return repo.status( @@ -448,7 +449,7 @@ optionalrepo=True, ) def demo(ui, repo, *args, **opts): - '''print [keywordmaps] configuration and an expansion example + """print [keywordmaps] configuration and an expansion example Show current, custom, or default keyword template maps and their expansions. @@ -459,7 +460,7 @@ Use -d/--default to disable current configuration. See :hg:`help templates` for information on templates and filters. - ''' + """ def demoitems(section, items): ui.write(b'[%s]\n' % section) @@ -547,12 +548,12 @@ inferrepo=True, ) def expand(ui, repo, *pats, **opts): - '''expand keywords in the working directory + """expand keywords in the working directory Run after (re)enabling keyword expansion. kwexpand refuses to run if given files contain local changes. - ''' + """ # 3rd argument sets expansion to True _kwfwrite(ui, repo, True, *pats, **opts) @@ -569,7 +570,7 @@ inferrepo=True, ) def files(ui, repo, *pats, **opts): - '''show files configured for keyword expansion + """show files configured for keyword expansion List which files in the working directory are matched by the [keyword] configuration patterns. @@ -588,7 +589,7 @@ k = keyword expansion candidate (not tracked) I = ignored i = ignored (not tracked) - ''' + """ kwt = getattr(repo, '_keywordkwt', None) wctx = repo[None] status = _status(ui, repo, wctx, kwt, *pats, **opts) @@ -634,12 +635,12 @@ inferrepo=True, ) def shrink(ui, repo, *pats, **opts): - '''revert expanded keywords in the working directory + """revert expanded keywords in the working directory Must be run before changing/disabling active keywords. kwshrink refuses to run if given files contain local changes. - ''' + """ # 3rd argument sets expansion to False _kwfwrite(ui, repo, False, *pats, **opts) @@ -648,8 +649,8 @@ def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None): - '''Monkeypatch/wrap patch.patchfile.__init__ to avoid - rejects or conflicts due to expanded keywords in working dir.''' + """Monkeypatch/wrap patch.patchfile.__init__ to avoid + rejects or conflicts due to expanded keywords in working dir.""" orig(self, ui, gp, backend, store, eolmode) kwt = getattr(getattr(backend, 'repo', None), '_keywordkwt', None) if kwt: @@ -702,7 +703,7 @@ def kw_copy(orig, ui, repo, pats, opts, rename=False): - '''Wraps cmdutil.copy so that copy/rename destinations do not + """Wraps cmdutil.copy so that copy/rename destinations do not contain expanded keywords. Note that the source of a regular file destination may also be a symlink: @@ -710,7 +711,7 @@ cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords) For the latter we have to follow the symlink to find out whether its target is configured for expansion and we therefore must unexpand the - keywords in the destination.''' + keywords in the destination.""" kwt = getattr(repo, '_keywordkwt', None) if kwt is None: return orig(ui, repo, pats, opts, rename) @@ -722,9 +723,9 @@ cwd = repo.getcwd() def haskwsource(dest): - '''Returns true if dest is a regular file and configured for + """Returns true if dest is a regular file and configured for expansion or a symlink which points to a file configured for - expansion. ''' + expansion.""" source = repo.dirstate.copied(dest) if b'l' in wctx.flags(source): source = pathutil.canonpath( @@ -785,12 +786,12 @@ def uisetup(ui): - ''' Monkeypatches dispatch._parse to retrieve user command. + """Monkeypatches dispatch._parse to retrieve user command. Overrides file method to return kwfilelog instead of filelog if file matches user configuration. Wraps commit to overwrite configured files with updated keyword substitutions. - Monkeypatches patch and webcommands.''' + Monkeypatches patch and webcommands.""" def kwdispatch_parse(orig, ui, args): '''Monkeypatch dispatch._parse to obtain running hg command.'''
--- a/hgext/largefiles/__init__.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/largefiles/__init__.py Thu Dec 03 14:15:39 2020 -0500 @@ -136,13 +136,19 @@ eh.merge(proto.eh) eh.configitem( - b'largefiles', b'minsize', default=eh.configitem.dynamicdefault, + b'largefiles', + b'minsize', + default=eh.configitem.dynamicdefault, ) eh.configitem( - b'largefiles', b'patterns', default=list, + b'largefiles', + b'patterns', + default=list, ) eh.configitem( - b'largefiles', b'usercache', default=None, + b'largefiles', + b'usercache', + default=None, ) cmdtable = eh.cmdtable
--- a/hgext/largefiles/basestore.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/largefiles/basestore.py Thu Dec 03 14:15:39 2020 -0500 @@ -17,8 +17,8 @@ class StoreError(Exception): - '''Raised when there is a problem getting files from or putting - files to a central store.''' + """Raised when there is a problem getting files from or putting + files to a central store.""" def __init__(self, filename, hash, url, detail): self.filename = filename @@ -49,19 +49,19 @@ raise NotImplementedError(b'abstract method') def exists(self, hashes): - '''Check to see if the store contains the given hashes. Given an - iterable of hashes it returns a mapping from hash to bool.''' + """Check to see if the store contains the given hashes. Given an + iterable of hashes it returns a mapping from hash to bool.""" raise NotImplementedError(b'abstract method') def get(self, files): - '''Get the specified largefiles from the store and write to local + """Get the specified largefiles from the store and write to local files under repo.root. files is a list of (filename, hash) tuples. Return (success, missing), lists of files successfully downloaded and those not found in the store. success is a list of (filename, hash) tuples; missing is a list of filenames that we could not get. (The detailed error message will already have been presented to the user, so missing is just supplied as a - summary.)''' + summary.)""" success = [] missing = [] ui = self.ui @@ -123,9 +123,9 @@ return True def verify(self, revs, contents=False): - '''Verify the existence (and, optionally, contents) of every big + """Verify the existence (and, optionally, contents) of every big file revision referenced by every changeset in revs. - Return 0 if all is well, non-zero on any errors.''' + Return 0 if all is well, non-zero on any errors.""" self.ui.status( _(b'searching %d changesets for largefiles\n') % len(revs) @@ -163,17 +163,17 @@ return int(failed) def _getfile(self, tmpfile, filename, hash): - '''Fetch one revision of one file from the store and write it + """Fetch one revision of one file from the store and write it to tmpfile. Compute the hash of the file on-the-fly as it downloads and return the hash. Close tmpfile. Raise StoreError if unable to download the file (e.g. it does not - exist in the store).''' + exist in the store).""" raise NotImplementedError(b'abstract method') def _verifyfiles(self, contents, filestocheck): - '''Perform the actual verification of files in the store. + """Perform the actual verification of files in the store. 'contents' controls verification of content hash. 'filestocheck' is list of files to check. Returns _true_ if any problems are found! - ''' + """ raise NotImplementedError(b'abstract method')
--- a/hgext/largefiles/lfcommands.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/largefiles/lfcommands.py Thu Dec 03 14:15:39 2020 -0500 @@ -66,7 +66,7 @@ inferrepo=True, ) def lfconvert(ui, src, dest, *pats, **opts): - '''convert a normal repository to a largefiles repository + """convert a normal repository to a largefiles repository Convert repository SOURCE to a new repository DEST, identical to SOURCE except that certain files will be converted as largefiles: @@ -82,7 +82,7 @@ repository. Use --to-normal to convert largefiles back to normal files; after - this, the DEST repository can be used without largefiles at all.''' + this, the DEST repository can be used without largefiles at all.""" opts = pycompat.byteskwargs(opts) if opts[b'to_normal']: @@ -393,8 +393,8 @@ def _islfile(file, ctx, matcher, size): - '''Return true if file should be considered a largefile, i.e. - matcher matches it or it is larger than size.''' + """Return true if file should be considered a largefile, i.e. + matcher matches it or it is larger than size.""" # never store special .hg* files as largefiles if file == b'.hgtags' or file == b'.hgignore' or file == b'.hgsigs': return False @@ -440,11 +440,11 @@ def verifylfiles(ui, repo, all=False, contents=False): - '''Verify that every largefile revision in the current changeset + """Verify that every largefile revision in the current changeset exists in the central store. With --contents, also verify that the contents of each local largefile file revision are correct (SHA-1 hash matches the revision ID). With --all, check every changeset in - this repository.''' + this repository.""" if all: revs = repo.revs(b'all()') else: @@ -455,12 +455,12 @@ def cachelfiles(ui, repo, node, filelist=None): - '''cachelfiles ensures that all largefiles needed by the specified revision + """cachelfiles ensures that all largefiles needed by the specified revision are present in the repository's largefile cache. returns a tuple (cached, missing). cached is the list of files downloaded by this operation; missing is the list of files that were needed but could - not be found.''' + not be found.""" lfiles = lfutil.listlfiles(repo, node) if filelist: lfiles = set(lfiles) & set(filelist) @@ -502,11 +502,11 @@ def updatelfiles( ui, repo, filelist=None, printmessage=None, normallookup=False ): - '''Update largefiles according to standins in the working directory + """Update largefiles according to standins in the working directory If ``printmessage`` is other than ``None``, it means "print (or ignore, for false) message forcibly". - ''' + """ statuswriter = lfutil.getstatuswriter(ui, repo, printmessage) with repo.wlock(): lfdirstate = lfutil.openlfdirstate(ui, repo)
--- a/hgext/largefiles/lfutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/largefiles/lfutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -80,10 +80,10 @@ def usercachepath(ui, hash): - '''Return the correct location in the "global" largefiles cache for a file + """Return the correct location in the "global" largefiles cache for a file with the given hash. This cache is used for sharing of largefiles across repositories - both - to preserve download bandwidth and storage space.''' + to preserve download bandwidth and storage space.""" return os.path.join(_usercachedir(ui), hash) @@ -143,9 +143,9 @@ def findfile(repo, hash): - '''Return store path of the largefile with the specified hash. + """Return store path of the largefile with the specified hash. As a side effect, the file might be linked from user cache. - Return None if the file can't be found locally.''' + Return None if the file can't be found locally.""" path, exists = findstorepath(repo, hash) if exists: repo.ui.note(_(b'found %s in store\n') % hash) @@ -191,10 +191,10 @@ def openlfdirstate(ui, repo, create=True): - ''' + """ Return a dirstate object that tracks largefiles: i.e. its root is the repo root, but it is saved in .hg/largefiles/dirstate. - ''' + """ vfs = repo.vfs lfstoredir = longname opener = vfsmod.vfs(vfs.join(lfstoredir)) @@ -245,8 +245,8 @@ def listlfiles(repo, rev=None, matcher=None): - '''return a list of largefiles in the working copy or the - specified changeset''' + """return a list of largefiles in the working copy or the + specified changeset""" if matcher is None: matcher = getstandinmatcher(repo) @@ -265,18 +265,18 @@ def storepath(repo, hash, forcelocal=False): - '''Return the correct location in the repository largefiles store for a - file with the given hash.''' + """Return the correct location in the repository largefiles store for a + file with the given hash.""" if not forcelocal and repo.shared(): return repo.vfs.reljoin(repo.sharedpath, longname, hash) return repo.vfs.join(longname, hash) def findstorepath(repo, hash): - '''Search through the local store path(s) to find the file for the given + """Search through the local store path(s) to find the file for the given hash. If the file is not found, its path in the primary store is returned. The return value is a tuple of (path, exists(path)). - ''' + """ # For shared repos, the primary store is in the share source. But for # backward compatibility, force a lookup in the local store if it wasn't # found in the share source. @@ -291,11 +291,11 @@ def copyfromcache(repo, hash, filename): - '''Copy the specified largefile from the repo or system cache to + """Copy the specified largefile from the repo or system cache to filename in the repository. Return true on success or false if the file was not found in either cache (which should not happened: this is meant to be called only after ensuring that the needed - largefile exists in the cache).''' + largefile exists in the cache).""" wvfs = repo.wvfs path = findfile(repo, hash) if path is None: @@ -354,8 +354,8 @@ def linktousercache(repo, hash): - '''Link / copy the largefile with the specified hash from the store - to the cache.''' + """Link / copy the largefile with the specified hash from the store + to the cache.""" path = usercachepath(repo.ui, hash) link(storepath(repo, hash), path) @@ -380,9 +380,9 @@ def composestandinmatcher(repo, rmatcher): - '''Return a matcher that accepts standins corresponding to the + """Return a matcher that accepts standins corresponding to the files accepted by rmatcher. Pass the list of files in the matcher - as the paths specified by the user.''' + as the paths specified by the user.""" smatcher = getstandinmatcher(repo, rmatcher) isstandin = smatcher.matchfn @@ -395,8 +395,8 @@ def standin(filename): - '''Return the repo-relative path to the standin for the specified big - file.''' + """Return the repo-relative path to the standin for the specified big + file.""" # Notes: # 1) Some callers want an absolute path, but for instance addlargefiles # needs it repo-relative so it can be passed to repo[None].add(). So @@ -408,8 +408,8 @@ def isstandin(filename): - '''Return true if filename is a big file standin. filename must be - in Mercurial's internal form (slash-separated).''' + """Return true if filename is a big file standin. filename must be + in Mercurial's internal form (slash-separated).""" return filename.startswith(shortnameslash) @@ -439,9 +439,9 @@ def readasstandin(fctx): - '''read hex hash from given filectx of standin file + """read hex hash from given filectx of standin file - This encapsulates how "standin" data is stored into storage layer.''' + This encapsulates how "standin" data is stored into storage layer.""" return fctx.data().strip() @@ -451,8 +451,8 @@ def copyandhash(instream, outfile): - '''Read bytes from instream (iterable) and write them to outfile, - computing the SHA-1 hash of the data along the way. Return the hash.''' + """Read bytes from instream (iterable) and write them to outfile, + computing the SHA-1 hash of the data along the way. Return the hash.""" hasher = hashutil.sha1(b'') for data in instream: hasher.update(data) @@ -635,11 +635,11 @@ def updatestandinsbymatch(repo, match): - '''Update standins in the working directory according to specified match + """Update standins in the working directory according to specified match This returns (possibly modified) ``match`` object to be used for subsequent commit process. - ''' + """ ui = repo.ui @@ -741,7 +741,7 @@ class automatedcommithook(object): - '''Stateful hook to update standins at the 1st commit of resuming + """Stateful hook to update standins at the 1st commit of resuming For efficiency, updating standins in the working directory should be avoided while automated committing (like rebase, transplant and @@ -750,7 +750,7 @@ But the 1st commit of resuming automated committing (e.g. ``rebase --continue``) should update them, because largefiles may be modified manually. - ''' + """ def __init__(self, resuming): self.resuming = resuming @@ -764,14 +764,14 @@ def getstatuswriter(ui, repo, forcibly=None): - '''Return the function to write largefiles specific status out + """Return the function to write largefiles specific status out If ``forcibly`` is ``None``, this returns the last element of ``repo._lfstatuswriters`` as "default" writer function. Otherwise, this returns the function to always write out (or ignore if ``not forcibly``) status. - ''' + """ if forcibly is None and util.safehasattr(repo, b'_largefilesenabled'): return repo._lfstatuswriters[-1] else:
--- a/hgext/largefiles/localstore.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/largefiles/localstore.py Thu Dec 03 14:15:39 2020 -0500 @@ -20,9 +20,9 @@ class localstore(basestore.basestore): - '''localstore first attempts to grab files out of the store in the remote + """localstore first attempts to grab files out of the store in the remote Mercurial repository. Failing that, it attempts to grab the files from - the user cache.''' + the user cache.""" def __init__(self, ui, repo, remote): self.remote = remote.local()
--- a/hgext/largefiles/overrides.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/largefiles/overrides.py Thu Dec 03 14:15:39 2020 -0500 @@ -58,8 +58,8 @@ def composelargefilematcher(match, manifest): - '''create a matcher that matches only the largefiles in the original - matcher''' + """create a matcher that matches only the largefiles in the original + matcher""" m = copy.copy(match) lfile = lambda f: lfutil.standin(f) in manifest m._files = [lf for lf in m._files if lfile(lf)] @@ -586,11 +586,17 @@ mresult.addfile(lfile, b'k', None, b'replaces standin') if branchmerge: mresult.addfile( - standin, b'k', None, b'replaced by non-standin', + standin, + b'k', + None, + b'replaced by non-standin', ) else: mresult.addfile( - standin, b'r', None, b'replaced by non-standin', + standin, + b'r', + None, + b'replaced by non-standin', ) elif lm in (b'g', b'dc') and sm != b'r': if lm == b'dc': @@ -610,7 +616,10 @@ if branchmerge: # largefile can be restored from standin safely mresult.addfile( - lfile, b'k', None, b'replaced by standin', + lfile, + b'k', + None, + b'replaced by standin', ) mresult.addfile(standin, b'k', None, b'replaces standin') else: @@ -628,7 +637,10 @@ else: # pick remote normal file mresult.addfile(lfile, b'g', largs, b'replaces standin') mresult.addfile( - standin, b'r', None, b'replaced by non-standin', + standin, + b'r', + None, + b'replaced by non-standin', ) return mresult
--- a/hgext/largefiles/proto.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/largefiles/proto.py Thu Dec 03 14:15:39 2020 -0500 @@ -39,8 +39,8 @@ def putlfile(repo, proto, sha): - '''Server command for putting a largefile into a repository's local store - and into the user cache.''' + """Server command for putting a largefile into a repository's local store + and into the user cache.""" with proto.mayberedirectstdio() as output: path = lfutil.storepath(repo, sha) util.makedirs(os.path.dirname(path)) @@ -69,8 +69,8 @@ def getlfile(repo, proto, sha): - '''Server command for retrieving a largefile from the repository-local - cache or user cache.''' + """Server command for retrieving a largefile from the repository-local + cache or user cache.""" filename = lfutil.findfile(repo, sha) if not filename: raise error.Abort( @@ -93,12 +93,12 @@ def statlfile(repo, proto, sha): - '''Server command for checking if a largefile is present - returns '2\n' if + """Server command for checking if a largefile is present - returns '2\n' if the largefile is missing, '0\n' if it seems to be in good condition. The value 1 is reserved for mismatched checksum, but that is too expensive to be verified on every stat and must be caught be running 'hg verify' - server side.''' + server side.""" filename = lfutil.findfile(repo, sha) if not filename: return wireprototypes.bytesresponse(b'2\n') @@ -194,8 +194,8 @@ def heads(orig, repo, proto): - '''Wrap server command - largefile capable clients will know to call - lheads instead''' + """Wrap server command - largefile capable clients will know to call + lheads instead""" if lfutil.islfilesrepo(repo): return wireprototypes.ooberror(LARGEFILES_REQUIRED_MSG)
--- a/hgext/largefiles/remotestore.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/largefiles/remotestore.py Thu Dec 03 14:15:39 2020 -0500 @@ -146,8 +146,8 @@ raise NotImplementedError(b'abstract method') def _stat(self, hashes): - '''Get information about availability of files specified by + """Get information about availability of files specified by hashes in the remote store. Return dictionary mapping hashes to return code where 0 means that file is available, other - values if not.''' + values if not.""" raise NotImplementedError(b'abstract method')
--- a/hgext/largefiles/reposetup.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/largefiles/reposetup.py Thu Dec 03 14:15:39 2020 -0500 @@ -360,7 +360,7 @@ # TODO: _subdirlfs should be moved into "lfutil.py", because # it is referred only from "lfutil.updatestandinsbymatch" def _subdirlfs(self, files, lfiles): - ''' + """ Adjust matched file list If we pass a directory to commit whose only committable files are largefiles, the core commit code aborts before finding @@ -370,7 +370,7 @@ we explicitly add the largefiles to the match list and remove the directory. In other cases, we leave the match list unmodified. - ''' + """ actualfiles = [] dirs = [] regulars = []
--- a/hgext/largefiles/wirestore.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/largefiles/wirestore.py Thu Dec 03 14:15:39 2020 -0500 @@ -30,13 +30,23 @@ return self.remote.getlfile(hash) def _stat(self, hashes): - '''For each hash, return 0 if it is available, other values if not. + """For each hash, return 0 if it is available, other values if not. It is usually 2 if the largefile is missing, but might be 1 the server - has a corrupted copy.''' + has a corrupted copy.""" with self.remote.commandexecutor() as e: fs = [] for hash in hashes: - fs.append((hash, e.callcommand(b'statlfile', {b'sha': hash,}))) + fs.append( + ( + hash, + e.callcommand( + b'statlfile', + { + b'sha': hash, + }, + ), + ) + ) return {hash: f.result() for hash, f in fs}
--- a/hgext/lfs/__init__.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/lfs/__init__.py Thu Dec 03 14:15:39 2020 -0500 @@ -127,10 +127,10 @@ from mercurial.i18n import _ from mercurial import ( + bundlecaches, config, context, error, - exchange, extensions, exthelper, filelog, @@ -172,33 +172,51 @@ templatekeyword = eh.templatekeyword eh.configitem( - b'experimental', b'lfs.serve', default=True, + b'experimental', + b'lfs.serve', + default=True, ) eh.configitem( - b'experimental', b'lfs.user-agent', default=None, + b'experimental', + b'lfs.user-agent', + default=None, ) eh.configitem( - b'experimental', b'lfs.disableusercache', default=False, + b'experimental', + b'lfs.disableusercache', + default=False, ) eh.configitem( - b'experimental', b'lfs.worker-enable', default=True, + b'experimental', + b'lfs.worker-enable', + default=True, ) eh.configitem( - b'lfs', b'url', default=None, + b'lfs', + b'url', + default=None, ) eh.configitem( - b'lfs', b'usercache', default=None, + b'lfs', + b'usercache', + default=None, ) # Deprecated eh.configitem( - b'lfs', b'threshold', default=None, + b'lfs', + b'threshold', + default=None, ) eh.configitem( - b'lfs', b'track', default=b'none()', + b'lfs', + b'track', + default=b'none()', ) eh.configitem( - b'lfs', b'retry', default=5, + b'lfs', + b'retry', + default=5, ) lfsprocessor = ( @@ -351,7 +369,7 @@ # Make bundle choose changegroup3 instead of changegroup2. This affects # "hg bundle" command. Note: it does not cover all bundle formats like # "packed1". Using "packed1" with lfs will likely cause trouble. - exchange._bundlespeccontentopts[b"v2"][b"cg.version"] = b"03" + bundlecaches._bundlespeccontentopts[b"v2"][b"cg.version"] = b"03" @eh.filesetpredicate(b'lfs()')
--- a/hgext/lfs/blobstore.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/lfs/blobstore.py Thu Dec 03 14:15:39 2020 -0500 @@ -96,8 +96,7 @@ class lfsuploadfile(httpconnectionmod.httpsendfile): - """a file-like object that supports keepalive. - """ + """a file-like object that supports keepalive.""" def __init__(self, ui, filename): super(lfsuploadfile, self).__init__(ui, filename, b'rb') @@ -258,9 +257,9 @@ def _urlerrorreason(urlerror): - '''Create a friendly message for the given URLError to be used in an + """Create a friendly message for the given URLError to be used in an LfsRemoteError message. - ''' + """ inst = urlerror if isinstance(urlerror.reason, Exception): @@ -338,7 +337,10 @@ ] requestdata = pycompat.bytesurl( json.dumps( - {'objects': objects, 'operation': pycompat.strurl(action),} + { + 'objects': objects, + 'operation': pycompat.strurl(action), + } ) ) url = b'%s/objects/batch' % self.baseurl
--- a/hgext/lfs/wrapper.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/lfs/wrapper.py Thu Dec 03 14:15:39 2020 -0500 @@ -381,10 +381,10 @@ def uploadblobsfromrevs(repo, revs): - '''upload lfs blobs introduced by revs + """upload lfs blobs introduced by revs Note: also used by other extensions e. g. infinitepush. avoid renaming. - ''' + """ if _canskipupload(repo): return pointers = extractpointers(repo, revs)
--- a/hgext/mq.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/mq.py Thu Dec 03 14:15:39 2020 -0500 @@ -100,6 +100,7 @@ revsetlang, scmutil, smartset, + strip, subrepoutil, util, vfs as vfsmod, @@ -124,21 +125,29 @@ configitem = registrar.configitem(configtable) configitem( - b'mq', b'git', default=b'auto', + b'mq', + b'git', + default=b'auto', ) configitem( - b'mq', b'keepchanges', default=False, + b'mq', + b'keepchanges', + default=False, ) configitem( - b'mq', b'plain', default=False, + b'mq', + b'plain', + default=False, ) configitem( - b'mq', b'secret', default=False, + b'mq', + b'secret', + default=False, ) # force load strip extension formerly included in mq and import some utility try: - stripext = extensions.find(b'strip') + extensions.find(b'strip') except KeyError: # note: load is lazy so we could avoid the try-except, # but I (marmoute) prefer this explicit code. @@ -149,14 +158,14 @@ def log(self, event, msgfmt, *msgargs, **opts): pass - stripext = extensions.load(dummyui(), b'strip', b'') - -strip = stripext.strip + extensions.load(dummyui(), b'strip', b'') + +strip = strip.strip def checksubstate(repo, baserev=None): - '''return list of subrepos at a different revision than substate. - Abort if any subrepos have uncommitted changes.''' + """return list of subrepos at a different revision than substate. + Abort if any subrepos have uncommitted changes.""" inclsubs = [] wctx = repo[None] if baserev: @@ -448,9 +457,9 @@ __str__ = encoding.strmethod(__bytes__) def _delmsg(self): - '''Remove existing message, keeping the rest of the comments fields. + """Remove existing message, keeping the rest of the comments fields. If comments contains 'subject: ', message will prepend - the field and a blank line.''' + the field and a blank line.""" if self.message: subj = b'subject: ' + self.message[0].lower() for i in pycompat.xrange(len(self.comments)): @@ -948,8 +957,8 @@ return (0, head) def patch(self, repo, patchfile): - '''Apply patchfile to the working directory. - patchfile: name of patch file''' + """Apply patchfile to the working directory. + patchfile: name of patch file""" files = set() try: fuzz = patchmod.patch( @@ -1362,7 +1371,7 @@ def new(self, repo, patchfn, *pats, **opts): """options: - msg: a string or a no-argument function returning a string + msg: a string or a no-argument function returning a string """ opts = pycompat.byteskwargs(opts) msg = opts.get(b'msg') @@ -1717,7 +1726,10 @@ except: # re-raises self.ui.warn(_(b'cleaning up working directory...\n')) cmdutil.revert( - self.ui, repo, repo[b'.'], no_backup=True, + self.ui, + repo, + repo[b'.'], + no_backup=True, ) # only remove unknown files that we know we touched or # created while patching @@ -2822,7 +2834,7 @@ norepo=True, ) def clone(ui, source, dest=None, **opts): - '''clone main and patch repository at same time + """clone main and patch repository at same time If source is local, destination will have no patches applied. If source is remote, this command can not check if patches are @@ -2837,7 +2849,7 @@ would be created by :hg:`init --mq`. Return 0 on success. - ''' + """ opts = pycompat.byteskwargs(opts) def patchdir(repo): @@ -2936,7 +2948,10 @@ @command( b"qseries", - [(b'm', b'missing', None, _(b'print patches not in series')),] + seriesopts, + [ + (b'm', b'missing', None, _(b'print patches not in series')), + ] + + seriesopts, _(b'hg qseries [-ms]'), helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) @@ -3281,9 +3296,9 @@ helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def goto(ui, repo, patch, **opts): - '''push or pop patches until named patch is at top of stack - - Returns 0 on success.''' + """push or pop patches until named patch is at top of stack + + Returns 0 on success.""" opts = pycompat.byteskwargs(opts) opts = fixkeepchangesopts(ui, opts) q = repo.mq @@ -3320,7 +3335,7 @@ helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def guard(ui, repo, *args, **opts): - '''set or print guards for a patch + """set or print guards for a patch Guards control whether a patch can be pushed. A patch with no guards is always pushed. A patch with a positive guard ("+foo") is @@ -3340,7 +3355,7 @@ hg qguard other.patch -- +2.6.17 -stable Returns 0 on success. - ''' + """ def status(idx): guards = q.seriesguards[idx] or [b'unguarded'] @@ -3711,7 +3726,7 @@ helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def select(ui, repo, *args, **opts): - '''set or print guarded patches to push + """set or print guarded patches to push Use the :hg:`qguard` command to set or print guards on patch, then use qselect to tell mq which guards to use. A patch will be pushed if @@ -3743,7 +3758,7 @@ Use -s/--series to print a list of all guards in the series file (no other arguments needed). Use -v for more information. - Returns 0 on success.''' + Returns 0 on success.""" q = repo.mq opts = pycompat.byteskwargs(opts) @@ -3887,7 +3902,7 @@ helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def qqueue(ui, repo, name=None, **opts): - '''manage multiple patch queues + """manage multiple patch queues Supports switching between different patch queues, as well as creating new patch queues and deleting existing ones. @@ -3906,7 +3921,7 @@ active queue. Returns 0 on success. - ''' + """ q = repo.mq _defaultqueue = b'patches' _allqueues = b'patches.queues' @@ -4249,8 +4264,7 @@ @revsetpredicate(b'mq()') def revsetmq(repo, subset, x): - """Changesets managed by MQ. - """ + """Changesets managed by MQ.""" revsetlang.getargs(x, 0, 0, _(b"mq takes no arguments")) applied = {repo[r.node].rev() for r in repo.mq.applied} return smartset.baseset([r for r in subset if r in applied])
--- a/hgext/narrow/narrowbundle2.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/narrow/narrowbundle2.py Thu Dec 03 14:15:39 2020 -0500 @@ -78,7 +78,14 @@ def generateellipsesbundle2( - bundler, repo, include, exclude, version, common, heads, depth, + bundler, + repo, + include, + exclude, + version, + common, + heads, + depth, ): match = narrowspec.match(repo.root, include=include, exclude=exclude) if depth is not None: @@ -113,7 +120,13 @@ def generate_ellipses_bundle2_for_widening( - bundler, repo, oldmatch, newmatch, version, common, known, + bundler, + repo, + oldmatch, + newmatch, + version, + common, + known, ): common = set(common or [nullid]) # Steps:
--- a/hgext/narrow/narrowwirepeer.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/narrow/narrowwirepeer.py Thu Dec 03 14:15:39 2020 -0500 @@ -120,7 +120,13 @@ ) else: narrowbundle2.generate_ellipses_bundle2_for_widening( - bundler, repo, oldmatch, newmatch, cgversion, common, known, + bundler, + repo, + oldmatch, + newmatch, + cgversion, + common, + known, ) except error.Abort as exc: bundler = bundle2.bundle20(repo.ui)
--- a/hgext/notify.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/notify.py Thu Dec 03 14:15:39 2020 -0500 @@ -190,64 +190,104 @@ configitem = registrar.configitem(configtable) configitem( - b'notify', b'changegroup', default=None, + b'notify', + b'changegroup', + default=None, ) configitem( - b'notify', b'config', default=None, + b'notify', + b'config', + default=None, ) configitem( - b'notify', b'diffstat', default=True, + b'notify', + b'diffstat', + default=True, ) configitem( - b'notify', b'domain', default=None, + b'notify', + b'domain', + default=None, ) configitem( - b'notify', b'messageidseed', default=None, + b'notify', + b'messageidseed', + default=None, ) configitem( - b'notify', b'fromauthor', default=None, + b'notify', + b'fromauthor', + default=None, ) configitem( - b'notify', b'incoming', default=None, + b'notify', + b'incoming', + default=None, ) configitem( - b'notify', b'maxdiff', default=300, + b'notify', + b'maxdiff', + default=300, ) configitem( - b'notify', b'maxdiffstat', default=-1, + b'notify', + b'maxdiffstat', + default=-1, ) configitem( - b'notify', b'maxsubject', default=67, + b'notify', + b'maxsubject', + default=67, ) configitem( - b'notify', b'mbox', default=None, + b'notify', + b'mbox', + default=None, ) configitem( - b'notify', b'merge', default=True, + b'notify', + b'merge', + default=True, ) configitem( - b'notify', b'outgoing', default=None, + b'notify', + b'outgoing', + default=None, ) configitem( - b'notify', b'reply-to-predecessor', default=False, + b'notify', + b'reply-to-predecessor', + default=False, ) configitem( - b'notify', b'sources', default=b'serve', + b'notify', + b'sources', + default=b'serve', ) configitem( - b'notify', b'showfunc', default=None, + b'notify', + b'showfunc', + default=None, ) configitem( - b'notify', b'strip', default=0, + b'notify', + b'strip', + default=0, ) configitem( - b'notify', b'style', default=None, + b'notify', + b'style', + default=None, ) configitem( - b'notify', b'template', default=None, + b'notify', + b'template', + default=None, ) configitem( - b'notify', b'test', default=True, + b'notify', + b'test', + default=True, ) # template for single changeset can include email headers. @@ -539,10 +579,10 @@ def hook(ui, repo, hooktype, node=None, source=None, **kwargs): - '''send email notifications to interested subscribers. + """send email notifications to interested subscribers. if used as changegroup hook, send one email for all changesets in - changegroup. else send one email per changeset.''' + changegroup. else send one email per changeset.""" n = notifier(ui, repo, hooktype) ctx = repo.unfiltered()[node]
--- a/hgext/pager.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/pager.py Thu Dec 03 14:15:39 2020 -0500 @@ -41,7 +41,9 @@ configitem = registrar.configitem(configtable) configitem( - b'pager', b'attend', default=lambda: attended, + b'pager', + b'attend', + default=lambda: attended, )
--- a/hgext/patchbomb.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/patchbomb.py Thu Dec 03 14:15:39 2020 -0500 @@ -110,34 +110,54 @@ configitem = registrar.configitem(configtable) configitem( - b'patchbomb', b'bundletype', default=None, + b'patchbomb', + b'bundletype', + default=None, ) configitem( - b'patchbomb', b'bcc', default=None, + b'patchbomb', + b'bcc', + default=None, ) configitem( - b'patchbomb', b'cc', default=None, + b'patchbomb', + b'cc', + default=None, ) configitem( - b'patchbomb', b'confirm', default=False, + b'patchbomb', + b'confirm', + default=False, ) configitem( - b'patchbomb', b'flagtemplate', default=None, + b'patchbomb', + b'flagtemplate', + default=None, ) configitem( - b'patchbomb', b'from', default=None, + b'patchbomb', + b'from', + default=None, ) configitem( - b'patchbomb', b'intro', default=b'auto', + b'patchbomb', + b'intro', + default=b'auto', ) configitem( - b'patchbomb', b'publicurl', default=None, + b'patchbomb', + b'publicurl', + default=None, ) configitem( - b'patchbomb', b'reply-to', default=None, + b'patchbomb', + b'reply-to', + default=None, ) configitem( - b'patchbomb', b'to', default=None, + b'patchbomb', + b'to', + default=None, ) # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for @@ -148,8 +168,7 @@ def _addpullheader(seq, ctx): - """Add a header pointing to a public URL where the changeset is available - """ + """Add a header pointing to a public URL where the changeset is available""" repo = ctx.repo() # experimental config: patchbomb.publicurl # waiting for some logic that check that the changeset are available on the @@ -656,7 +675,7 @@ helpcategory=command.CATEGORY_IMPORT_EXPORT, ) def email(ui, repo, *revs, **opts): - '''send changesets by email + """send changesets by email By default, diffs are sent in the format generated by :hg:`export`, one per message. The series starts with a "[PATCH 0 @@ -739,7 +758,7 @@ Before using this command, you will need to enable email in your hgrc. See the [email] section in hgrc(5) for details. - ''' + """ opts = pycompat.byteskwargs(opts) _charsets = mail._charsets(ui)
--- a/hgext/phabricator.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/phabricator.py Thu Dec 03 14:15:39 2020 -0500 @@ -35,6 +35,20 @@ # the internal library. curlcmd = curl --connect-timeout 2 --retry 3 --silent + # retry failed command N time (default 0). Useful when using the extension + # over flakly connection. + # + # We wait `retry.interval` between each retry, in seconds. + # (default 1 second). + retry = 3 + retry.interval = 10 + + # the retry option can combine well with the http.timeout one. + # + # For example to give up on http request after 20 seconds: + [http] + timeout=20 + [auth] example.schemes = https example.prefix = phab.example.com @@ -53,6 +67,7 @@ import mimetypes import operator import re +import time from mercurial.node import bin, nullid, short from mercurial.i18n import _ @@ -108,42 +123,68 @@ # developer config: phabricator.batchsize eh.configitem( - b'phabricator', b'batchsize', default=12, + b'phabricator', + b'batchsize', + default=12, ) eh.configitem( - b'phabricator', b'callsign', default=None, + b'phabricator', + b'callsign', + default=None, ) eh.configitem( - b'phabricator', b'curlcmd', default=None, + b'phabricator', + b'curlcmd', + default=None, ) # developer config: phabricator.debug eh.configitem( - b'phabricator', b'debug', default=False, + b'phabricator', + b'debug', + default=False, ) # developer config: phabricator.repophid eh.configitem( - b'phabricator', b'repophid', default=None, + b'phabricator', + b'repophid', + default=None, ) eh.configitem( - b'phabricator', b'url', default=None, + b'phabricator', + b'retry', + default=0, +) +eh.configitem( + b'phabricator', + b'retry.interval', + default=1, ) eh.configitem( - b'phabsend', b'confirm', default=False, + b'phabricator', + b'url', + default=None, ) eh.configitem( - b'phabimport', b'secret', default=False, + b'phabsend', + b'confirm', + default=False, ) eh.configitem( - b'phabimport', b'obsolete', default=False, + b'phabimport', + b'secret', + default=False, +) +eh.configitem( + b'phabimport', + b'obsolete', + default=False, ) colortable = { b'phabricator.action.created': b'green', b'phabricator.action.skipped': b'magenta', b'phabricator.action.updated': b'magenta', - b'phabricator.desc': b'', b'phabricator.drev': b'bold', - b'phabricator.node': b'', b'phabricator.status.abandoned': b'magenta dim', b'phabricator.status.accepted': b'green bold', b'phabricator.status.closed': b'green', @@ -168,8 +209,7 @@ @eh.wrapfunction(localrepo, "loadhgrc") def _loadhgrc(orig, ui, wdirvfs, hgvfs, requirements, *args, **opts): - """Load ``.arcconfig`` content into a ui instance on repository open. - """ + """Load ``.arcconfig`` content into a ui instance on repository open.""" result = False arcconfig = {} @@ -385,8 +425,25 @@ else: urlopener = urlmod.opener(ui, authinfo) request = util.urlreq.request(pycompat.strurl(url), data=data) - with contextlib.closing(urlopener.open(request)) as rsp: - body = rsp.read() + max_try = ui.configint(b'phabricator', b'retry') + 1 + timeout = ui.configwith(float, b'http', b'timeout') + for try_count in range(max_try): + try: + with contextlib.closing( + urlopener.open(request, timeout=timeout) + ) as rsp: + body = rsp.read() + break + except util.urlerr.urlerror as err: + if try_count == max_try - 1: + raise + ui.debug( + b'Conduit Request failed (try %d/%d): %r\n' + % (try_count + 1, max_try, err) + ) + # failing request might come from overloaded server + retry_interval = ui.configint(b'phabricator', b'retry.interval') + time.sleep(retry_interval) ui.debug(b'Conduit Response: %s\n' % body) parsed = pycompat.rapply( lambda x: encoding.unitolocal(x) @@ -635,8 +692,7 @@ @attr.s class phabhunk(dict): - """Represents a Differential hunk, which is owned by a Differential change - """ + """Represents a Differential hunk, which is owned by a Differential change""" oldOffset = attr.ib(default=0) # camelcase-required oldLength = attr.ib(default=0) # camelcase-required @@ -1220,9 +1276,8 @@ b'phabricator.action.%s' % action, ) drevdesc = ui.label(b'D%d' % newrevid, b'phabricator.drev') - nodedesc = ui.label(bytes(ctx), b'phabricator.node') - desc = ui.label(ctx.description().split(b'\n')[0], b'phabricator.desc') - ui.write(_(b'%s - %s - %s: %s\n') % (drevdesc, actiondesc, nodedesc, desc)) + summary = cmdutil.format_changeset_summary(ui, ctx, b'phabsend') + ui.write(_(b'%s - %s - %s\n') % (drevdesc, actiondesc, summary)) def _amend_diff_properties(unfi, drevid, newnodes, diff): @@ -1515,7 +1570,9 @@ mapping.get(old.p2().node(), (old.p2(),))[0], ] newdesc = rewriteutil.update_hash_refs( - repo, newdesc, mapping, + repo, + newdesc, + mapping, ) new = context.metadataonlyctx( repo, @@ -1642,7 +1699,6 @@ ui = repo.ui for rev in revs: ctx = repo[rev] - desc = ctx.description().splitlines()[0] oldnode, olddiff, drevid = oldmap.get(ctx.node(), (None, None, None)) if drevid: drevdesc = ui.label(b'D%d' % drevid, b'phabricator.drev') @@ -1650,11 +1706,10 @@ drevdesc = ui.label(_(b'NEW'), b'phabricator.drev') ui.write( - _(b'%s - %s: %s\n') + _(b'%s - %s\n') % ( drevdesc, - ui.label(bytes(ctx), b'phabricator.node'), - ui.label(desc, b'phabricator.desc'), + cmdutil.format_changeset_summary(ui, ctx, b'phabsend'), ) ) @@ -2232,7 +2287,10 @@ m = _differentialrevisiondescre.search(ctx.description()) if m: return templateutil.hybriddict( - {b'url': m.group('url'), b'id': b"D%s" % m.group('id'),} + { + b'url': m.group('url'), + b'id': b"D%s" % m.group('id'), + } ) else: tags = ctx.repo().nodetags(ctx.node()) @@ -2243,14 +2301,18 @@ url += b'/' url += t - return templateutil.hybriddict({b'url': url, b'id': t,}) + return templateutil.hybriddict( + { + b'url': url, + b'id': t, + } + ) return None @eh.templatekeyword(b'phabstatus', requires={b'ctx', b'repo', b'ui'}) def template_status(context, mapping): - """:phabstatus: String. Status of Phabricator differential. - """ + """:phabstatus: String. Status of Phabricator differential.""" ctx = context.resource(mapping, b'ctx') repo = context.resource(mapping, b'repo') ui = context.resource(mapping, b'ui') @@ -2264,7 +2326,10 @@ for drev in drevs: if int(drev[b'id']) == drevid: return templateutil.hybriddict( - {b'url': drev[b'uri'], b'status': drev[b'statusName'],} + { + b'url': drev[b'uri'], + b'status': drev[b'statusName'], + } ) return None
--- a/hgext/purge.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/purge.py Thu Dec 03 14:15:39 2020 -0500 @@ -67,7 +67,7 @@ helpcategory=command.CATEGORY_WORKING_DIRECTORY, ) def purge(ui, repo, *dirs, **opts): - '''removes files not tracked by Mercurial + """removes files not tracked by Mercurial Delete files not known to Mercurial. This is useful to test local and uncommitted changes in an otherwise-clean source tree. @@ -95,7 +95,7 @@ you forgot to add to the repository. If you only want to print the list of files that this program would delete, use the --print option. - ''' + """ opts = pycompat.byteskwargs(opts) cmdutil.check_at_most_one_arg(opts, b'all', b'ignored')
--- a/hgext/rebase.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/rebase.py Thu Dec 03 14:15:39 2020 -0500 @@ -146,20 +146,9 @@ def _ctxdesc(ctx): """short description for a context""" - desc = b'%d:%s "%s"' % ( - ctx.rev(), - ctx, - ctx.description().split(b'\n', 1)[0], + return cmdutil.format_changeset_summary( + ctx.repo().ui, ctx, command=b'rebase' ) - repo = ctx.repo() - names = [] - for nsname, ns in pycompat.iteritems(repo.names): - if nsname == b'branches': - continue - names.extend(ns.names(repo, ctx.node())) - if names: - desc += b' (%s)' % b' '.join(names) - return desc class rebaseruntime(object): @@ -518,14 +507,29 @@ ui.note(_(b'rebase merging completed\n')) def _concludenode(self, rev, editor, commitmsg=None): - '''Commit the wd changes with parents p1 and p2. + """Commit the wd changes with parents p1 and p2. Reuse commit info from rev but also store useful information in extra. - Return node of committed revision.''' + Return node of committed revision.""" repo = self.repo ctx = repo[rev] if commitmsg is None: commitmsg = ctx.description() + + # Skip replacement if collapsing, as that degenerates to p1 for all + # nodes. + if not self.collapsef: + cl = repo.changelog + commitmsg = rewriteutil.update_hash_refs( + repo, + commitmsg, + { + cl.node(oldrev): [cl.node(newrev)] + for oldrev, newrev in self.state.items() + if newrev != revtodo + }, + ) + date = self.date if date is None: date = ctx.date() @@ -1136,7 +1140,11 @@ overrides = {(b'rebase', b'singletransaction'): True} with ui.configoverride(overrides, b'rebase'): _origrebase( - ui, repo, action, opts, rbsrt, + ui, + repo, + action, + opts, + rbsrt, ) except error.ConflictResolutionRequired: ui.status(_(b'hit a merge conflict\n')) @@ -1448,8 +1456,8 @@ def commitmemorynode(repo, wctx, editor, extra, user, date, commitmsg): - '''Commit the memory changes with parents p1 and p2. - Return node of committed revision.''' + """Commit the memory changes with parents p1 and p2. + Return node of committed revision.""" # By convention, ``extra['branch']`` (set by extrafn) clobbers # ``branch`` (used when passing ``--keepbranches``). branch = None @@ -1476,8 +1484,8 @@ def commitnode(repo, editor, extra, user, date, commitmsg): - '''Commit the wd changes with parents p1 and p2. - Return node of committed revision.''' + """Commit the wd changes with parents p1 and p2. + Return node of committed revision.""" dsguard = util.nullcontextmanager() if not repo.ui.configbool(b'rebase', b'singletransaction'): dsguard = dirstateguard.dirstateguard(repo, b'rebase') @@ -1966,11 +1974,11 @@ def buildstate(repo, destmap, collapse): - '''Define which revisions are going to be rebased and where + """Define which revisions are going to be rebased and where repo: repo destmap: {srcrev: destrev} - ''' + """ rebaseset = destmap.keys() originalwd = repo[b'.'].rev()
--- a/hgext/record.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/record.py Thu Dec 03 14:15:39 2020 -0500 @@ -39,7 +39,7 @@ helpcategory=command.CATEGORY_COMMITTING, ) def record(ui, repo, *pats, **opts): - '''interactively select changes to commit + """interactively select changes to commit If a list of files is omitted, all changes reported by :hg:`status` will be candidates for recording. @@ -65,7 +65,7 @@ ? - display help - This command is not available when committing a merge.''' + This command is not available when committing a merge.""" if not ui.interactive(): raise error.Abort( @@ -106,11 +106,11 @@ inferrepo=True, ) def qrecord(ui, repo, patch, *pats, **opts): - '''interactively record a new patch + """interactively record a new patch See :hg:`help qnew` & :hg:`help record` for more information and usage. - ''' + """ return _qrecord(b'qnew', ui, repo, patch, *pats, **opts)
--- a/hgext/remotefilelog/__init__.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/remotefilelog/__init__.py Thu Dec 03 14:15:39 2020 -0500 @@ -758,10 +758,10 @@ rcache = {} def getrenamed(fn, rev): - '''looks up all renames for a file (up to endrev) the first + """looks up all renames for a file (up to endrev) the first time the file is given. It indexes on the changerev and only parses the manifest if linkrev != changerev. - Returns rename info for fn at changerev rev.''' + Returns rename info for fn at changerev rev.""" if rev in rcache.setdefault(fn, {}): return rcache[fn][rev] @@ -822,8 +822,7 @@ @command(b'gc', [], _(b'hg gc [REPO...]'), norepo=True) def gc(ui, *args, **opts): - '''garbage collect the client and server filelog caches - ''' + """garbage collect the client and server filelog caches""" cachepaths = set() # get the system client cache @@ -1105,7 +1104,9 @@ @command( b'debugremotefilelog', - [(b'd', b'decompress', None, _(b'decompress the filelog first')),], + [ + (b'd', b'decompress', None, _(b'decompress the filelog first')), + ], _(b'hg debugremotefilelog <path>'), norepo=True, ) @@ -1115,7 +1116,9 @@ @command( b'verifyremotefilelog', - [(b'd', b'decompress', None, _(b'decompress the filelogs first')),], + [ + (b'd', b'decompress', None, _(b'decompress the filelogs first')), + ], _(b'hg verifyremotefilelogs <directory>'), norepo=True, )
--- a/hgext/remotefilelog/basestore.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/remotefilelog/basestore.py Thu Dec 03 14:15:39 2020 -0500 @@ -103,7 +103,7 @@ def _cleanupdirectory(self, rootdir): """Removes the empty directories and unnecessary files within the root directory recursively. Note that this method does not remove the root - directory itself. """ + directory itself.""" oldfiles = set() otherfiles = set()
--- a/hgext/remotefilelog/contentstore.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/remotefilelog/contentstore.py Thu Dec 03 14:15:39 2020 -0500 @@ -17,8 +17,7 @@ class ChainIndicies(object): - """A static class for easy reference to the delta chain indicies. - """ + """A static class for easy reference to the delta chain indicies.""" # The filename of this revision delta NAME = 0 @@ -73,8 +72,7 @@ @basestore.baseunionstore.retriable def getdelta(self, name, node): - """Return the single delta entry for the given name/node pair. - """ + """Return the single delta entry for the given name/node pair.""" for store in self.stores: try: return store.getdelta(name, node)
--- a/hgext/remotefilelog/fileserverclient.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/remotefilelog/fileserverclient.py Thu Dec 03 14:15:39 2020 -0500 @@ -302,8 +302,7 @@ class fileserverclient(object): - """A client for requesting files from the remote file server. - """ + """A client for requesting files from the remote file server.""" def __init__(self, repo): ui = repo.ui @@ -568,8 +567,7 @@ def prefetch( self, fileids, force=False, fetchdata=True, fetchhistory=False ): - """downloads the given file versions to the cache - """ + """downloads the given file versions to the cache""" repo = self.repo idstocheck = [] for file, id in fileids:
--- a/hgext/remotefilelog/remotefilectx.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/remotefilelog/remotefilectx.py Thu Dec 03 14:15:39 2020 -0500 @@ -63,8 +63,8 @@ return self.linkrev() def filectx(self, fileid, changeid=None): - '''opens an arbitrary revision of the file without - opening a new filelog''' + """opens an arbitrary revision of the file without + opening a new filelog""" return remotefilectx( self._repo, self._path,
--- a/hgext/remotefilelog/remotefilelogserver.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/remotefilelog/remotefilelogserver.py Thu Dec 03 14:15:39 2020 -0500 @@ -40,8 +40,7 @@ def setupserver(ui, repo): - """Sets up a normal Mercurial repo so it can serve files to shallow repos. - """ + """Sets up a normal Mercurial repo so it can serve files to shallow repos.""" onetimesetup(ui) # don't send files to shallow clients during pulls @@ -79,8 +78,7 @@ def onetimesetup(ui): - """Configures the wireprotocol for both clients and servers. - """ + """Configures the wireprotocol for both clients and servers.""" global onetime if onetime: return @@ -281,8 +279,7 @@ def getflogheads(repo, proto, path): - """A server api for requesting a filelog's heads - """ + """A server api for requesting a filelog's heads""" flog = repo.file(path) heads = flog.heads() return b'\n'.join((hex(head) for head in heads if head != nullid)) @@ -309,8 +306,7 @@ def getfiles(repo, proto): - """A server api for requesting particular versions of particular files. - """ + """A server api for requesting particular versions of particular files.""" if shallowutil.isenabled(repo): raise error.Abort(_(b'cannot fetch remote files from shallow repo')) if not isinstance(proto, _sshv1server):
--- a/hgext/remotefilelog/repack.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/remotefilelog/repack.py Thu Dec 03 14:15:39 2020 -0500 @@ -54,8 +54,7 @@ def fullrepack(repo, options=None): - """If ``packsonly`` is True, stores creating only loose objects are skipped. - """ + """If ``packsonly`` is True, stores creating only loose objects are skipped.""" if util.safehasattr(repo, 'shareddatastores'): datasource = contentstore.unioncontentstore(*repo.shareddatastores) historysource = metadatastore.unionmetadatastore( @@ -874,8 +873,7 @@ class repackentry(object): - """Simple class representing a single revision entry in the repackledger. - """ + """Simple class representing a single revision entry in the repackledger.""" __slots__ = ( 'filename',
--- a/hgext/remotefilelog/shallowrepo.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/remotefilelog/shallowrepo.py Thu Dec 03 14:15:39 2020 -0500 @@ -161,11 +161,11 @@ return path def maybesparsematch(self, *revs, **kwargs): - ''' + """ A wrapper that allows the remotefilelog to invoke sparsematch() if this is a sparse repository, or returns None if this is not a sparse repository. - ''' + """ if revs: ret = sparse.matcher(repo, revs=revs) else: @@ -217,8 +217,7 @@ def backgroundprefetch( self, revs, base=None, repack=False, pats=None, opts=None ): - """Runs prefetch in background with optional repack - """ + """Runs prefetch in background with optional repack""" cmd = [procutil.hgexecutable(), b'-R', repo.origroot, b'prefetch'] if repack: cmd.append(b'--repack')
--- a/hgext/remotenames.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/remotenames.py Thu Dec 03 14:15:39 2020 -0500 @@ -66,13 +66,19 @@ revsetpredicate = registrar.revsetpredicate() configitem( - b'remotenames', b'bookmarks', default=True, + b'remotenames', + b'bookmarks', + default=True, ) configitem( - b'remotenames', b'branches', default=True, + b'remotenames', + b'branches', + default=True, ) configitem( - b'remotenames', b'hoistedpeer', default=b'default', + b'remotenames', + b'hoistedpeer', + default=b'default', )
--- a/hgext/schemes.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/schemes.py Thu Dec 03 14:15:39 2020 -0500 @@ -142,8 +142,7 @@ @command(b'debugexpandscheme', norepo=True) def expandscheme(ui, url, **opts): - """given a repo path, provide the scheme-expanded path - """ + """given a repo path, provide the scheme-expanded path""" repo = hg._peerlookup(url) if isinstance(repo, ShortRepository): url = repo.resolve(url)
--- a/hgext/share.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/share.py Thu Dec 03 14:15:39 2020 -0500 @@ -44,6 +44,26 @@ that was cloned before. The default naming mode is "identity". + +.. container:: verbose + + Sharing requirements and configs of source repository with shares + ----------------------------------------------------------------- + + By default creating a shared repository only enables sharing a common + history and does not share requirements and configs between them. This + may lead to problems in some cases, for example when you upgrade the + storage format from one repository but does not set related configs + in the shares. + + Setting `format.exp-share-safe = True` enables sharing configs and + requirements. This only applies to shares which are done after enabling + the config option. + + For enabling this in existing shares, enable the config option and reshare. + + For resharing existing shares, make sure your working directory is clean + and there are no untracked files, delete that share and create a new share. ''' from __future__ import absolute_import @@ -75,7 +95,12 @@ [ (b'U', b'noupdate', None, _(b'do not create a working directory')), (b'B', b'bookmarks', None, _(b'also share bookmarks')), - (b'', b'relative', None, _(b'point to source using a relative path'),), + ( + b'', + b'relative', + None, + _(b'point to source using a relative path'), + ), ], _(b'[-U] [-B] SOURCE [DEST]'), helpcategory=command.CATEGORY_REPO_CREATION,
--- a/hgext/split.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/split.py Thu Dec 03 14:15:39 2020 -0500 @@ -72,7 +72,7 @@ with repo.wlock(), repo.lock(), repo.transaction(b'split') as tr: revs = scmutil.revrange(repo, revlist or [b'.']) if len(revs) > 1: - raise error.Abort(_(b'cannot split multiple revisions')) + raise error.InputError(_(b'cannot split multiple revisions')) rev = revs.first() ctx = repo[rev] @@ -82,7 +82,7 @@ ui.status(_(b'nothing to split\n')) return 1 if ctx.node() is None: - raise error.Abort(_(b'cannot split working directory')) + raise error.InputError(_(b'cannot split working directory')) if opts.get(b'rebase'): # Skip obsoleted descendants and their descendants so the rebase @@ -98,7 +98,7 @@ rewriteutil.precheck(repo, [rev] + torebase, b'split') if len(ctx.parents()) > 1: - raise error.Abort(_(b'cannot split a merge changeset')) + raise error.InputError(_(b'cannot split a merge changeset')) cmdutil.bailifchanged(repo) @@ -142,9 +142,14 @@ header = _( b'HG: Splitting %s. So far it has been split into:\n' ) % short(ctx.node()) - for c in committed: - firstline = c.description().split(b'\n', 1)[0] - header += _(b'HG: - %s: %s\n') % (short(c.node()), firstline) + # We don't want color codes in the commit message template, so + # disable the label() template function while we render it. + with ui.configoverride( + {(b'templatealias', b'label(l,x)'): b"x"}, b'split' + ): + for c in committed: + summary = cmdutil.format_changeset_summary(ui, c, b'split') + header += _(b'HG: - %s\n') % summary header += _( b'HG: Write commit message for the next split changeset.\n' ) @@ -165,7 +170,7 @@ committed.append(newctx) if not committed: - raise error.Abort(_(b'cannot split an empty revision')) + raise error.InputError(_(b'cannot split an empty revision')) scmutil.cleanupnodes( repo,
--- a/hgext/sqlitestore.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/sqlitestore.py Thu Dec 03 14:15:39 2020 -0500 @@ -674,9 +674,10 @@ linkmapper, transaction, addrevisioncb=None, + duplicaterevisioncb=None, maybemissingparents=False, ): - nodes = [] + empty = True for node, p1, p2, linknode, deltabase, delta, wireflags in deltas: storeflags = 0 @@ -715,8 +716,6 @@ linkrev = linkmapper(linknode) - nodes.append(node) - if node in self._revisions: # Possibly reset parents to make them proper. entry = self._revisions[node] @@ -741,6 +740,9 @@ (self._nodetorev[p1], entry.flags, entry.rid), ) + if duplicaterevisioncb: + duplicaterevisioncb(self, node) + empty = False continue if deltabase == nullid: @@ -763,8 +765,9 @@ if addrevisioncb: addrevisioncb(self, node) + empty = False - return nodes + return not empty def censorrevision(self, tr, censornode, tombstone=b''): tombstone = storageutil.packmeta({b'censored': tombstone}, b'')
--- a/hgext/strip.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/strip.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,287 +1,22 @@ -"""strip changesets and their descendants from history +"""strip changesets and their descendants from history (DEPRECATED) + +The functionality of this extension has been included in core Mercurial +since version 5.7. Please use :hg:`debugstrip ...` instead. This extension allows you to strip changesets and all their descendants from the repository. See the command help for details. """ from __future__ import absolute_import -from mercurial.i18n import _ -from mercurial.pycompat import getattr -from mercurial import ( - bookmarks as bookmarksmod, - cmdutil, - error, - hg, - lock as lockmod, - mergestate as mergestatemod, - node as nodemod, - pycompat, - registrar, - repair, - scmutil, - util, -) +from mercurial import commands -nullid = nodemod.nullid -release = lockmod.release - -cmdtable = {} -command = registrar.command(cmdtable) # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or # leave the attribute unspecified. testedwith = b'ships-with-hg-core' - -def checklocalchanges(repo, force=False): - s = repo.status() - if not force: - cmdutil.checkunfinished(repo) - cmdutil.bailifchanged(repo) - else: - cmdutil.checkunfinished(repo, skipmerge=True) - return s - - -def _findupdatetarget(repo, nodes): - unode, p2 = repo.changelog.parents(nodes[0]) - currentbranch = repo[None].branch() - - if ( - util.safehasattr(repo, b'mq') - and p2 != nullid - and p2 in [x.node for x in repo.mq.applied] - ): - unode = p2 - elif currentbranch != repo[unode].branch(): - pwdir = b'parents(wdir())' - revset = b'max(((parents(%ln::%r) + %r) - %ln::%r) and branch(%s))' - branchtarget = repo.revs( - revset, nodes, pwdir, pwdir, nodes, pwdir, currentbranch - ) - if branchtarget: - cl = repo.changelog - unode = cl.node(branchtarget.first()) - - return unode - - -def strip( - ui, - repo, - revs, - update=True, - backup=True, - force=None, - bookmarks=None, - soft=False, -): - with repo.wlock(), repo.lock(): - - if update: - checklocalchanges(repo, force=force) - urev = _findupdatetarget(repo, revs) - hg.clean(repo, urev) - repo.dirstate.write(repo.currenttransaction()) - - if soft: - repair.softstrip(ui, repo, revs, backup) - else: - repair.strip(ui, repo, revs, backup) - - repomarks = repo._bookmarks - if bookmarks: - with repo.transaction(b'strip') as tr: - if repo._activebookmark in bookmarks: - bookmarksmod.deactivate(repo) - repomarks.applychanges(repo, tr, [(b, None) for b in bookmarks]) - for bookmark in sorted(bookmarks): - ui.write(_(b"bookmark '%s' deleted\n") % bookmark) - - -@command( - b"strip", - [ - ( - b'r', - b'rev', - [], - _( - b'strip specified revision (optional, ' - b'can specify revisions without this ' - b'option)' - ), - _(b'REV'), - ), - ( - b'f', - b'force', - None, - _( - b'force removal of changesets, discard ' - b'uncommitted changes (no backup)' - ), - ), - (b'', b'no-backup', None, _(b'do not save backup bundle')), - (b'', b'nobackup', None, _(b'do not save backup bundle (DEPRECATED)'),), - (b'n', b'', None, _(b'ignored (DEPRECATED)')), - ( - b'k', - b'keep', - None, - _(b"do not modify working directory during strip"), - ), - ( - b'B', - b'bookmark', - [], - _(b"remove revs only reachable from given bookmark"), - _(b'BOOKMARK'), - ), - ( - b'', - b'soft', - None, - _(b"simply drop changesets from visible history (EXPERIMENTAL)"), - ), - ], - _(b'hg strip [-k] [-f] [-B bookmark] [-r] REV...'), - helpcategory=command.CATEGORY_MAINTENANCE, -) -def stripcmd(ui, repo, *revs, **opts): - """strip changesets and all their descendants from the repository - - The strip command removes the specified changesets and all their - descendants. If the working directory has uncommitted changes, the - operation is aborted unless the --force flag is supplied, in which - case changes will be discarded. - - If a parent of the working directory is stripped, then the working - directory will automatically be updated to the most recent - available ancestor of the stripped parent after the operation - completes. - - Any stripped changesets are stored in ``.hg/strip-backup`` as a - bundle (see :hg:`help bundle` and :hg:`help unbundle`). They can - be restored by running :hg:`unbundle .hg/strip-backup/BUNDLE`, - where BUNDLE is the bundle file created by the strip. Note that - the local revision numbers will in general be different after the - restore. - - Use the --no-backup option to discard the backup bundle once the - operation completes. - - Strip is not a history-rewriting operation and can be used on - changesets in the public phase. But if the stripped changesets have - been pushed to a remote repository you will likely pull them again. - - Return 0 on success. - """ - opts = pycompat.byteskwargs(opts) - backup = True - if opts.get(b'no_backup') or opts.get(b'nobackup'): - backup = False - - cl = repo.changelog - revs = list(revs) + opts.get(b'rev') - revs = set(scmutil.revrange(repo, revs)) - - with repo.wlock(): - bookmarks = set(opts.get(b'bookmark')) - if bookmarks: - repomarks = repo._bookmarks - if not bookmarks.issubset(repomarks): - raise error.Abort( - _(b"bookmark '%s' not found") - % b','.join(sorted(bookmarks - set(repomarks.keys()))) - ) - - # If the requested bookmark is not the only one pointing to a - # a revision we have to only delete the bookmark and not strip - # anything. revsets cannot detect that case. - nodetobookmarks = {} - for mark, node in pycompat.iteritems(repomarks): - nodetobookmarks.setdefault(node, []).append(mark) - for marks in nodetobookmarks.values(): - if bookmarks.issuperset(marks): - rsrevs = scmutil.bookmarkrevs(repo, marks[0]) - revs.update(set(rsrevs)) - if not revs: - with repo.lock(), repo.transaction(b'bookmark') as tr: - bmchanges = [(b, None) for b in bookmarks] - repomarks.applychanges(repo, tr, bmchanges) - for bookmark in sorted(bookmarks): - ui.write(_(b"bookmark '%s' deleted\n") % bookmark) - - if not revs: - raise error.Abort(_(b'empty revision set')) - - descendants = set(cl.descendants(revs)) - strippedrevs = revs.union(descendants) - roots = revs.difference(descendants) - - # if one of the wdir parent is stripped we'll need - # to update away to an earlier revision - update = any( - p != nullid and cl.rev(p) in strippedrevs - for p in repo.dirstate.parents() - ) - - rootnodes = {cl.node(r) for r in roots} - - q = getattr(repo, 'mq', None) - if q is not None and q.applied: - # refresh queue state if we're about to strip - # applied patches - if cl.rev(repo.lookup(b'qtip')) in strippedrevs: - q.applieddirty = True - start = 0 - end = len(q.applied) - for i, statusentry in enumerate(q.applied): - if statusentry.node in rootnodes: - # if one of the stripped roots is an applied - # patch, only part of the queue is stripped - start = i - break - del q.applied[start:end] - q.savedirty() - - revs = sorted(rootnodes) - if update and opts.get(b'keep'): - urev = _findupdatetarget(repo, revs) - uctx = repo[urev] - - # only reset the dirstate for files that would actually change - # between the working context and uctx - descendantrevs = repo.revs(b"only(., %d)", uctx.rev()) - changedfiles = [] - for rev in descendantrevs: - # blindly reset the files, regardless of what actually changed - changedfiles.extend(repo[rev].files()) - - # reset files that only changed in the dirstate too - dirstate = repo.dirstate - dirchanges = [f for f in dirstate if dirstate[f] != b'n'] - changedfiles.extend(dirchanges) - - repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles) - repo.dirstate.write(repo.currenttransaction()) - - # clear resolve state - mergestatemod.mergestate.clean(repo) - - update = False - - strip( - ui, - repo, - revs, - backup=backup, - update=update, - force=opts.get(b'force'), - bookmarks=bookmarks, - soft=opts[b'soft'], - ) - - return 0 +# This is a bit ugly, but a uisetup function that defines strip as an +# alias for debugstrip would override any user alias for strip, +# including aliases like "strip = strip --no-backup". +commands.command.rename(old=b'debugstrip', new=b'debugstrip|strip')
--- a/hgext/transplant.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/transplant.py Thu Dec 03 14:15:39 2020 -0500 @@ -62,10 +62,14 @@ configitem = registrar.configitem(configtable) configitem( - b'transplant', b'filter', default=None, + b'transplant', + b'filter', + default=None, ) configitem( - b'transplant', b'log', default=None, + b'transplant', + b'log', + default=None, ) @@ -140,8 +144,8 @@ self.getcommiteditor = getcommiteditor def applied(self, repo, node, parent): - '''returns True if a node is already an ancestor of parent - or is parent or has already been transplanted''' + """returns True if a node is already an ancestor of parent + or is parent or has already been transplanted""" if hasnode(repo, parent): parentrev = repo.changelog.rev(parent) if hasnode(repo, node): @@ -682,7 +686,7 @@ helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, ) def transplant(ui, repo, *revs, **opts): - '''transplant changesets from another branch + """transplant changesets from another branch Selected changesets will be applied on top of the current working directory with the log of the original changeset. The changesets @@ -731,7 +735,7 @@ If a changeset application fails, you can fix the merge by hand and then resume where you left off by calling :hg:`transplant --continue/-c`. - ''' + """ with repo.wlock(): return _dotransplant(ui, repo, *revs, **opts) @@ -743,9 +747,9 @@ yield node def transplantwalk(repo, dest, heads, match=util.always): - '''Yield all nodes that are ancestors of a head but not ancestors + """Yield all nodes that are ancestors of a head but not ancestors of dest. - If no heads are specified, the heads of repo will be used.''' + If no heads are specified, the heads of repo will be used.""" if not heads: heads = repo.heads() ancestors = [] @@ -804,10 +808,10 @@ raise error.Abort(_(b'no revision checked out')) if opts.get(b'continue'): if not tp.canresume(): - raise error.Abort(_(b'no transplant to continue')) + raise error.StateError(_(b'no transplant to continue')) elif opts.get(b'stop'): if not tp.canresume(): - raise error.Abort(_(b'no interrupted transplant found')) + raise error.StateError(_(b'no interrupted transplant found')) return tp.stop(ui, repo) else: cmdutil.checkunfinished(repo) @@ -886,8 +890,7 @@ @revsetpredicate(b'transplanted([set])') def revsettransplanted(repo, subset, x): - """Transplanted changesets in set, or all transplanted changesets. - """ + """Transplanted changesets in set, or all transplanted changesets.""" if x: s = revset.getset(repo, subset, x) else:
--- a/hgext/uncommit.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/uncommit.py Thu Dec 03 14:15:39 2020 -0500 @@ -43,10 +43,14 @@ configitem = registrar.configitem(configtable) configitem( - b'experimental', b'uncommitondirtywdir', default=False, + b'experimental', + b'uncommitondirtywdir', + default=False, ) configitem( - b'experimental', b'uncommit.keep', default=False, + b'experimental', + b'uncommit.keep', + default=False, ) # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
--- a/hgext/win32mbcs.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/win32mbcs.py Thu Dec 03 14:15:39 2020 -0500 @@ -70,7 +70,9 @@ # Encoding.encoding may be updated by --encoding option. # Use a lambda do delay the resolution. configitem( - b'win32mbcs', b'encoding', default=lambda: encoding.encoding, + b'win32mbcs', + b'encoding', + default=lambda: encoding.encoding, ) _encoding = None # see extsetup
--- a/hgext/win32text.py Thu Dec 03 13:36:24 2020 -0500 +++ b/hgext/win32text.py Thu Dec 03 14:15:39 2020 -0500 @@ -62,7 +62,9 @@ configitem = registrar.configitem(configtable) configitem( - b'win32text', b'warn', default=True, + b'win32text', + b'warn', + default=True, ) # regexp for single LF without CR preceding.
--- a/hgweb.cgi Thu Dec 03 13:36:24 2020 -0500 +++ b/hgweb.cgi Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # An example hgweb CGI script, edit as necessary # See also https://mercurial-scm.org/wiki/PublishingRepositories
--- a/i18n/check-translation.py Thu Dec 03 13:36:24 2020 -0500 +++ b/i18n/check-translation.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # check-translation.py - check Mercurial specific translation problems from __future__ import absolute_import @@ -33,8 +33,7 @@ def match(checker, pe): - """Examine whether POEntry "pe" is target of specified checker or not - """ + """Examine whether POEntry "pe" is target of specified checker or not""" if not checker.match(pe.msgid): return # examine suppression by translator comment
--- a/i18n/hggettext Thu Dec 03 13:36:24 2020 -0500 +++ b/i18n/hggettext Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # hggettext - carefully extract docstrings for Mercurial #
--- a/i18n/posplit Thu Dec 03 13:36:24 2020 -0500 +++ b/i18n/posplit Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # posplit - split messages in paragraphs on .po/.pot files #
--- a/mercurial/ancestor.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/ancestor.py Thu Dec 03 14:15:39 2020 -0500 @@ -148,11 +148,11 @@ class incrementalmissingancestors(object): - '''persistent state used to calculate missing ancestors incrementally + """persistent state used to calculate missing ancestors incrementally Although similar in spirit to lazyancestors below, this is a separate class because trying to support contains and missingancestors operations with the - same internal data structures adds needless complexity.''' + same internal data structures adds needless complexity.""" def __init__(self, pfunc, bases): self.bases = set(bases) @@ -198,12 +198,12 @@ break def missingancestors(self, revs): - '''return all the ancestors of revs that are not ancestors of self.bases + """return all the ancestors of revs that are not ancestors of self.bases This may include elements from revs. Equivalent to the revset (::revs - ::self.bases). Revs are returned in - revision number order, which is a topological order.''' + revision number order, which is a topological order.""" revsvisit = set(revs) basesvisit = self.bases pfunc = self.pfunc
--- a/mercurial/archival.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/archival.py Thu Dec 03 14:15:39 2020 -0500 @@ -37,8 +37,8 @@ def tidyprefix(dest, kind, prefix): - '''choose prefix to use for names in archive. make sure prefix is - safe for consumers.''' + """choose prefix to use for names in archive. make sure prefix is + safe for consumers.""" if prefix: prefix = util.normpath(prefix) @@ -132,8 +132,8 @@ class tarit(object): - '''write archive to tar file or stream. can write uncompressed, - or compress with gzip or bzip2.''' + """write archive to tar file or stream. can write uncompressed, + or compress with gzip or bzip2.""" if pycompat.ispy3: GzipFileWithTime = gzip.GzipFile # camelcase-required @@ -185,8 +185,10 @@ mtime=mtime, ) self.fileobj = gzfileobj - return tarfile.TarFile.taropen( # pytype: disable=attribute-error - name, pycompat.sysstr(mode), gzfileobj + return ( + tarfile.TarFile.taropen( # pytype: disable=attribute-error + name, pycompat.sysstr(mode), gzfileobj + ) ) else: try: @@ -224,8 +226,8 @@ class zipit(object): - '''write archive to zip file or stream. can write uncompressed, - or compressed with deflate.''' + """write archive to zip file or stream. can write uncompressed, + or compressed with deflate.""" def __init__(self, dest, mtime, compress=True): if isinstance(dest, bytes): @@ -316,7 +318,7 @@ mtime=None, subrepos=False, ): - '''create archive of repo as it was at node. + """create archive of repo as it was at node. dest can be name of directory, name of archive file, or file object to write archive to. @@ -333,7 +335,7 @@ mtime is the modified time, in seconds, or None to use the changeset time. subrepos tells whether to include subrepos. - ''' + """ if kind == b'txz' and not pycompat.ispy3: raise error.Abort(_(b'xz compression is only available in Python 3'))
--- a/mercurial/bookmarks.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/bookmarks.py Thu Dec 03 14:15:39 2020 -0500 @@ -189,8 +189,7 @@ return self._nodemap.get(node, []) def applychanges(self, repo, tr, changes): - """Apply a list of changes to bookmarks - """ + """Apply a list of changes to bookmarks""" bmchanges = tr.changes.get(b'bookmarks') for name, node in changes: old = self._refmap.get(name) @@ -422,8 +421,8 @@ def calculateupdate(ui, repo): - '''Return a tuple (activemark, movemarkfrom) indicating the active bookmark - and where to move the active bookmark from, if needed.''' + """Return a tuple (activemark, movemarkfrom) indicating the active bookmark + and where to move the active bookmark from, if needed.""" checkout, movemarkfrom = None, None activemark = repo._activebookmark if isactivewdirparent(repo): @@ -509,7 +508,7 @@ def comparebookmarks(repo, srcmarks, dstmarks, targets=None): - '''Compare bookmarks between srcmarks and dstmarks + """Compare bookmarks between srcmarks and dstmarks This returns tuple "(addsrc, adddst, advsrc, advdst, diverge, differ, invalid)", each are list of bookmarks below: @@ -532,7 +531,7 @@ If "targets" is specified, only bookmarks listed in it are examined. - ''' + """ if targets: bset = set(targets) @@ -585,14 +584,14 @@ def _diverge(ui, b, path, localmarks, remotenode): - '''Return appropriate diverged bookmark for specified ``path`` + """Return appropriate diverged bookmark for specified ``path`` This returns None, if it is failed to assign any divergent bookmark name. This reuses already existing one with "@number" suffix, if it refers ``remotenode``. - ''' + """ if b == b'@': b = b'' # try to use an @pathalias suffix @@ -762,13 +761,17 @@ def incoming(ui, repo, peer): - '''Show bookmarks incoming from other to repo - ''' + """Show bookmarks incoming from other to repo""" ui.status(_(b"searching for changed bookmarks\n")) with peer.commandexecutor() as e: remotemarks = unhexlifybookmarks( - e.callcommand(b'listkeys', {b'namespace': b'bookmarks',}).result() + e.callcommand( + b'listkeys', + { + b'namespace': b'bookmarks', + }, + ).result() ) r = comparebookmarks(repo, remotemarks, repo._bookmarks) @@ -813,8 +816,7 @@ def outgoing(ui, repo, other): - '''Show bookmarks outgoing from repo to other - ''' + """Show bookmarks outgoing from repo to other""" ui.status(_(b"searching for changed bookmarks\n")) remotemarks = unhexlifybookmarks(other.listkeys(b'bookmarks')) @@ -863,13 +865,18 @@ def summary(repo, peer): - '''Compare bookmarks between repo and other for "hg summary" output + """Compare bookmarks between repo and other for "hg summary" output This returns "(# of incoming, # of outgoing)" tuple. - ''' + """ with peer.commandexecutor() as e: remotemarks = unhexlifybookmarks( - e.callcommand(b'listkeys', {b'namespace': b'bookmarks',}).result() + e.callcommand( + b'listkeys', + { + b'namespace': b'bookmarks', + }, + ).result() ) r = comparebookmarks(repo, remotemarks, repo._bookmarks) @@ -901,7 +908,7 @@ """ mark = mark.strip() if not mark: - raise error.Abort( + raise error.InputError( _(b"bookmark names cannot consist entirely of whitespace") ) scmutil.checknewlabel(repo, mark, b'bookmark') @@ -917,7 +924,7 @@ changes = [] for mark in names: if mark not in marks: - raise error.Abort(_(b"bookmark '%s' does not exist") % mark) + raise error.InputError(_(b"bookmark '%s' does not exist") % mark) if mark == repo._activebookmark: deactivate(repo) changes.append((mark, None)) @@ -937,7 +944,7 @@ marks = repo._bookmarks mark = checkformat(repo, new) if old not in marks: - raise error.Abort(_(b"bookmark '%s' does not exist") % old) + raise error.InputError(_(b"bookmark '%s' does not exist") % old) changes = [] for bm in marks.checkconflict(mark, force): changes.append((bm, None)) @@ -1041,7 +1048,7 @@ bmarks = {} for bmark in names or marks: if bmark not in marks: - raise error.Abort(_(b"bookmark '%s' does not exist") % bmark) + raise error.InputError(_(b"bookmark '%s' does not exist") % bmark) active = repo._activebookmark if bmark == active: prefix, label = b'*', activebookmarklabel
--- a/mercurial/branchmap.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/branchmap.py Thu Dec 03 14:15:39 2020 -0500 @@ -41,7 +41,17 @@ ) assert any( - (Any, Callable, Dict, Iterable, List, Optional, Set, Tuple, Union,) + ( + Any, + Callable, + Dict, + Iterable, + List, + Optional, + Set, + Tuple, + Union, + ) ) subsettable = repoviewutil.subsettable @@ -139,8 +149,7 @@ def _unknownnode(node): - """ raises ValueError when branchcache found a node which does not exists - """ + """raises ValueError when branchcache found a node which does not exists""" raise ValueError('node %s does not exist' % pycompat.sysstr(hex(node))) @@ -183,9 +192,9 @@ hasnode=None, ): # type: (Union[Dict[bytes, List[bytes]], Iterable[Tuple[bytes, List[bytes]]]], bytes, int, Optional[bytes], Optional[Set[bytes]], Optional[Callable[[bytes], bool]]) -> None - """ hasnode is a function which can be used to verify whether changelog + """hasnode is a function which can be used to verify whether changelog has a given node or not. If it's not provided, we assume that every node - we have exists in changelog """ + we have exists in changelog""" self.tipnode = tipnode self.tiprev = tiprev self.filteredhash = filteredhash @@ -304,7 +313,7 @@ return bcache def load(self, repo, lineiter): - """ fully loads the branchcache by reading from the file using the line + """fully loads the branchcache by reading from the file using the line iterator passed""" for line in lineiter: line = line.rstrip(b'\n') @@ -340,8 +349,8 @@ return False def _branchtip(self, heads): - '''Return tuple with last open head in heads and false, - otherwise return last closed head and true.''' + """Return tuple with last open head in heads and false, + otherwise return last closed head and true.""" tip = heads[-1] closed = True for h in reversed(heads): @@ -352,9 +361,9 @@ return tip, closed def branchtip(self, branch): - '''Return the tipmost open head on branch head, otherwise return the + """Return the tipmost open head on branch head, otherwise return the tipmost closed head on branch. - Raise KeyError for unknown branch.''' + Raise KeyError for unknown branch.""" return self._branchtip(self[branch])[0] def iteropen(self, nodes):
--- a/mercurial/bundle2.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/bundle2.py Thu Dec 03 14:15:39 2020 -0500 @@ -489,7 +489,12 @@ def _processchangegroup(op, cg, tr, source, url, **kwargs): ret = cg.apply(op.repo, tr, source, url, **kwargs) - op.records.add(b'changegroup', {b'return': ret,}) + op.records.add( + b'changegroup', + { + b'return': ret, + }, + ) return ret @@ -1647,8 +1652,7 @@ def obsmarkersversion(caps): - """extract the list of supported obsmarkers versions from a bundle2caps dict - """ + """extract the list of supported obsmarkers versions from a bundle2caps dict""" obscaps = caps.get(b'obsmarkers', ()) return [int(c[1:]) for c in obscaps if c.startswith(b'V')]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/bundlecaches.py Thu Dec 03 14:15:39 2020 -0500 @@ -0,0 +1,424 @@ +# bundlecaches.py - utility to deal with pre-computed bundle for servers +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +from .i18n import _ + +from .thirdparty import attr + +from . import ( + error, + sslutil, + util, +) +from .utils import stringutil + +urlreq = util.urlreq + +CB_MANIFEST_FILE = b'clonebundles.manifest' + + +@attr.s +class bundlespec(object): + compression = attr.ib() + wirecompression = attr.ib() + version = attr.ib() + wireversion = attr.ib() + params = attr.ib() + contentopts = attr.ib() + + +# Maps bundle version human names to changegroup versions. +_bundlespeccgversions = { + b'v1': b'01', + b'v2': b'02', + b'packed1': b's1', + b'bundle2': b'02', # legacy +} + +# Maps bundle version with content opts to choose which part to bundle +_bundlespeccontentopts = { + b'v1': { + b'changegroup': True, + b'cg.version': b'01', + b'obsolescence': False, + b'phases': False, + b'tagsfnodescache': False, + b'revbranchcache': False, + }, + b'v2': { + b'changegroup': True, + b'cg.version': b'02', + b'obsolescence': False, + b'phases': False, + b'tagsfnodescache': True, + b'revbranchcache': True, + }, + b'packed1': {b'cg.version': b's1'}, +} +_bundlespeccontentopts[b'bundle2'] = _bundlespeccontentopts[b'v2'] + +_bundlespecvariants = { + b"streamv2": { + b"changegroup": False, + b"streamv2": True, + b"tagsfnodescache": False, + b"revbranchcache": False, + } +} + +# Compression engines allowed in version 1. THIS SHOULD NEVER CHANGE. +_bundlespecv1compengines = {b'gzip', b'bzip2', b'none'} + + +def parsebundlespec(repo, spec, strict=True): + """Parse a bundle string specification into parts. + + Bundle specifications denote a well-defined bundle/exchange format. + The content of a given specification should not change over time in + order to ensure that bundles produced by a newer version of Mercurial are + readable from an older version. + + The string currently has the form: + + <compression>-<type>[;<parameter0>[;<parameter1>]] + + Where <compression> is one of the supported compression formats + and <type> is (currently) a version string. A ";" can follow the type and + all text afterwards is interpreted as URI encoded, ";" delimited key=value + pairs. + + If ``strict`` is True (the default) <compression> is required. Otherwise, + it is optional. + + Returns a bundlespec object of (compression, version, parameters). + Compression will be ``None`` if not in strict mode and a compression isn't + defined. + + An ``InvalidBundleSpecification`` is raised when the specification is + not syntactically well formed. + + An ``UnsupportedBundleSpecification`` is raised when the compression or + bundle type/version is not recognized. + + Note: this function will likely eventually return a more complex data + structure, including bundle2 part information. + """ + + def parseparams(s): + if b';' not in s: + return s, {} + + params = {} + version, paramstr = s.split(b';', 1) + + for p in paramstr.split(b';'): + if b'=' not in p: + raise error.InvalidBundleSpecification( + _( + b'invalid bundle specification: ' + b'missing "=" in parameter: %s' + ) + % p + ) + + key, value = p.split(b'=', 1) + key = urlreq.unquote(key) + value = urlreq.unquote(value) + params[key] = value + + return version, params + + if strict and b'-' not in spec: + raise error.InvalidBundleSpecification( + _( + b'invalid bundle specification; ' + b'must be prefixed with compression: %s' + ) + % spec + ) + + if b'-' in spec: + compression, version = spec.split(b'-', 1) + + if compression not in util.compengines.supportedbundlenames: + raise error.UnsupportedBundleSpecification( + _(b'%s compression is not supported') % compression + ) + + version, params = parseparams(version) + + if version not in _bundlespeccgversions: + raise error.UnsupportedBundleSpecification( + _(b'%s is not a recognized bundle version') % version + ) + else: + # Value could be just the compression or just the version, in which + # case some defaults are assumed (but only when not in strict mode). + assert not strict + + spec, params = parseparams(spec) + + if spec in util.compengines.supportedbundlenames: + compression = spec + version = b'v1' + # Generaldelta repos require v2. + if b'generaldelta' in repo.requirements: + version = b'v2' + # Modern compression engines require v2. + if compression not in _bundlespecv1compengines: + version = b'v2' + elif spec in _bundlespeccgversions: + if spec == b'packed1': + compression = b'none' + else: + compression = b'bzip2' + version = spec + else: + raise error.UnsupportedBundleSpecification( + _(b'%s is not a recognized bundle specification') % spec + ) + + # Bundle version 1 only supports a known set of compression engines. + if version == b'v1' and compression not in _bundlespecv1compengines: + raise error.UnsupportedBundleSpecification( + _(b'compression engine %s is not supported on v1 bundles') + % compression + ) + + # The specification for packed1 can optionally declare the data formats + # required to apply it. If we see this metadata, compare against what the + # repo supports and error if the bundle isn't compatible. + if version == b'packed1' and b'requirements' in params: + requirements = set(params[b'requirements'].split(b',')) + missingreqs = requirements - repo.supportedformats + if missingreqs: + raise error.UnsupportedBundleSpecification( + _(b'missing support for repository features: %s') + % b', '.join(sorted(missingreqs)) + ) + + # Compute contentopts based on the version + contentopts = _bundlespeccontentopts.get(version, {}).copy() + + # Process the variants + if b"stream" in params and params[b"stream"] == b"v2": + variant = _bundlespecvariants[b"streamv2"] + contentopts.update(variant) + + engine = util.compengines.forbundlename(compression) + compression, wirecompression = engine.bundletype() + wireversion = _bundlespeccgversions[version] + + return bundlespec( + compression, wirecompression, version, wireversion, params, contentopts + ) + + +def parseclonebundlesmanifest(repo, s): + """Parses the raw text of a clone bundles manifest. + + Returns a list of dicts. The dicts have a ``URL`` key corresponding + to the URL and other keys are the attributes for the entry. + """ + m = [] + for line in s.splitlines(): + fields = line.split() + if not fields: + continue + attrs = {b'URL': fields[0]} + for rawattr in fields[1:]: + key, value = rawattr.split(b'=', 1) + key = util.urlreq.unquote(key) + value = util.urlreq.unquote(value) + attrs[key] = value + + # Parse BUNDLESPEC into components. This makes client-side + # preferences easier to specify since you can prefer a single + # component of the BUNDLESPEC. + if key == b'BUNDLESPEC': + try: + bundlespec = parsebundlespec(repo, value) + attrs[b'COMPRESSION'] = bundlespec.compression + attrs[b'VERSION'] = bundlespec.version + except error.InvalidBundleSpecification: + pass + except error.UnsupportedBundleSpecification: + pass + + m.append(attrs) + + return m + + +def isstreamclonespec(bundlespec): + # Stream clone v1 + if bundlespec.wirecompression == b'UN' and bundlespec.wireversion == b's1': + return True + + # Stream clone v2 + if ( + bundlespec.wirecompression == b'UN' + and bundlespec.wireversion == b'02' + and bundlespec.contentopts.get(b'streamv2') + ): + return True + + return False + + +def filterclonebundleentries(repo, entries, streamclonerequested=False): + """Remove incompatible clone bundle manifest entries. + + Accepts a list of entries parsed with ``parseclonebundlesmanifest`` + and returns a new list consisting of only the entries that this client + should be able to apply. + + There is no guarantee we'll be able to apply all returned entries because + the metadata we use to filter on may be missing or wrong. + """ + newentries = [] + for entry in entries: + spec = entry.get(b'BUNDLESPEC') + if spec: + try: + bundlespec = parsebundlespec(repo, spec, strict=True) + + # If a stream clone was requested, filter out non-streamclone + # entries. + if streamclonerequested and not isstreamclonespec(bundlespec): + repo.ui.debug( + b'filtering %s because not a stream clone\n' + % entry[b'URL'] + ) + continue + + except error.InvalidBundleSpecification as e: + repo.ui.debug(stringutil.forcebytestr(e) + b'\n') + continue + except error.UnsupportedBundleSpecification as e: + repo.ui.debug( + b'filtering %s because unsupported bundle ' + b'spec: %s\n' % (entry[b'URL'], stringutil.forcebytestr(e)) + ) + continue + # If we don't have a spec and requested a stream clone, we don't know + # what the entry is so don't attempt to apply it. + elif streamclonerequested: + repo.ui.debug( + b'filtering %s because cannot determine if a stream ' + b'clone bundle\n' % entry[b'URL'] + ) + continue + + if b'REQUIRESNI' in entry and not sslutil.hassni: + repo.ui.debug( + b'filtering %s because SNI not supported\n' % entry[b'URL'] + ) + continue + + if b'REQUIREDRAM' in entry: + try: + requiredram = util.sizetoint(entry[b'REQUIREDRAM']) + except error.ParseError: + repo.ui.debug( + b'filtering %s due to a bad REQUIREDRAM attribute\n' + % entry[b'URL'] + ) + continue + actualram = repo.ui.estimatememory() + if actualram is not None and actualram * 0.66 < requiredram: + repo.ui.debug( + b'filtering %s as it needs more than 2/3 of system memory\n' + % entry[b'URL'] + ) + continue + + newentries.append(entry) + + return newentries + + +class clonebundleentry(object): + """Represents an item in a clone bundles manifest. + + This rich class is needed to support sorting since sorted() in Python 3 + doesn't support ``cmp`` and our comparison is complex enough that ``key=`` + won't work. + """ + + def __init__(self, value, prefers): + self.value = value + self.prefers = prefers + + def _cmp(self, other): + for prefkey, prefvalue in self.prefers: + avalue = self.value.get(prefkey) + bvalue = other.value.get(prefkey) + + # Special case for b missing attribute and a matches exactly. + if avalue is not None and bvalue is None and avalue == prefvalue: + return -1 + + # Special case for a missing attribute and b matches exactly. + if bvalue is not None and avalue is None and bvalue == prefvalue: + return 1 + + # We can't compare unless attribute present on both. + if avalue is None or bvalue is None: + continue + + # Same values should fall back to next attribute. + if avalue == bvalue: + continue + + # Exact matches come first. + if avalue == prefvalue: + return -1 + if bvalue == prefvalue: + return 1 + + # Fall back to next attribute. + continue + + # If we got here we couldn't sort by attributes and prefers. Fall + # back to index order. + return 0 + + def __lt__(self, other): + return self._cmp(other) < 0 + + def __gt__(self, other): + return self._cmp(other) > 0 + + def __eq__(self, other): + return self._cmp(other) == 0 + + def __le__(self, other): + return self._cmp(other) <= 0 + + def __ge__(self, other): + return self._cmp(other) >= 0 + + def __ne__(self, other): + return self._cmp(other) != 0 + + +def sortclonebundleentries(ui, entries): + prefers = ui.configlist(b'ui', b'clonebundleprefers') + if not prefers: + return list(entries) + + def _split(p): + if b'=' not in p: + hint = _(b"each comma separated item should be key=value pairs") + raise error.Abort( + _(b"invalid ui.clonebundleprefers item: %s") % p, hint=hint + ) + return p.split(b'=', 1) + + prefers = [_split(p) for p in prefers] + + items = sorted(clonebundleentry(v, prefers) for v in entries) + return [i.value for i in items]
--- a/mercurial/bundlerepo.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/bundlerepo.py Thu Dec 03 14:15:39 2020 -0500 @@ -63,11 +63,14 @@ size = len(delta) start = cgunpacker.tell() - size - link = linkmapper(cs) if self.index.has_node(node): # this can happen if two branches make the same change self.bundlerevs.add(self.index.rev(node)) continue + if cs == node: + linkrev = nullrev + else: + linkrev = linkmapper(cs) for p in (p1, p2): if not self.index.has_node(p): @@ -87,7 +90,7 @@ size, -1, baserev, - link, + linkrev, self.rev(p1), self.rev(p2), node, @@ -325,8 +328,7 @@ self._cgunpacker = changegroup.getunbundler(version, cgstream, b'UN') def _writetempbundle(self, readfn, suffix, header=b''): - """Write a temporary file to disk - """ + """Write a temporary file to disk""" fdtemp, temp = self.vfs.mkstemp(prefix=b"hg-bundle-", suffix=suffix) self.tempfile = temp @@ -527,7 +529,7 @@ def getremotechanges( ui, repo, peer, onlyheads=None, bundlename=None, force=False ): - '''obtains a bundle of changes incoming from peer + """obtains a bundle of changes incoming from peer "onlyheads" restricts the returned changes to those reachable from the specified heads. @@ -545,7 +547,7 @@ "cleanupfn" must be called without arguments when you're done processing the changes; it closes both the original "peer" and the one returned here. - ''' + """ tmp = discovery.findcommonincoming(repo, peer, heads=onlyheads, force=force) common, incoming, rheads = tmp if not incoming: @@ -608,7 +610,10 @@ with peer.commandexecutor() as e: cg = e.callcommand( b'changegroup', - {b'nodes': incoming, b'source': b'incoming',}, + { + b'nodes': incoming, + b'source': b'incoming', + }, ).result() rheads = None @@ -652,7 +657,10 @@ with peer.commandexecutor() as e: remotephases = e.callcommand( - b'listkeys', {b'namespace': b'phases',} + b'listkeys', + { + b'namespace': b'phases', + }, ).result() pullop = exchange.pulloperation(bundlerepo, peer, heads=reponodes)
--- a/mercurial/cext/revlog.c Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/cext/revlog.c Thu Dec 03 14:15:39 2020 -0500 @@ -81,11 +81,11 @@ /* Type-specific fields go here. */ PyObject *data; /* raw bytes of index */ Py_buffer buf; /* buffer of data */ - PyObject **cache; /* cached tuples */ const char **offsets; /* populated on demand */ - Py_ssize_t raw_length; /* original number of elements */ - Py_ssize_t length; /* current number of elements */ - PyObject *added; /* populated on demand */ + Py_ssize_t length; /* current on-disk number of elements */ + unsigned new_length; /* number of added elements */ + unsigned added_length; /* space reserved for added elements */ + char *added; /* populated on demand */ PyObject *headrevs; /* cache, invalidated on changes */ PyObject *filteredrevs; /* filtered revs set */ nodetree nt; /* base-16 trie */ @@ -98,9 +98,7 @@ static Py_ssize_t index_length(const indexObject *self) { - if (self->added == NULL) - return self->length; - return self->length + PyList_GET_SIZE(self->added); + return self->length + self->new_length; } static PyObject *nullentry = NULL; @@ -156,11 +154,14 @@ */ static const char *index_deref(indexObject *self, Py_ssize_t pos) { + if (pos >= self->length) + return self->added + (pos - self->length) * v1_hdrsize; + if (self->inlined && pos > 0) { if (self->offsets == NULL) { Py_ssize_t ret; - self->offsets = PyMem_Malloc(self->raw_length * - sizeof(*self->offsets)); + self->offsets = + PyMem_Malloc(self->length * sizeof(*self->offsets)); if (self->offsets == NULL) return (const char *)PyErr_NoMemory(); ret = inline_scan(self, self->offsets); @@ -183,23 +184,11 @@ static inline int index_get_parents(indexObject *self, Py_ssize_t rev, int *ps, int maxrev) { - if (rev >= self->length) { - long tmp; - PyObject *tuple = - PyList_GET_ITEM(self->added, rev - self->length); - if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 5), &tmp)) { - return -1; - } - ps[0] = (int)tmp; - if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 6), &tmp)) { - return -1; - } - ps[1] = (int)tmp; - } else { - const char *data = index_deref(self, rev); - ps[0] = getbe32(data + 24); - ps[1] = getbe32(data + 28); - } + const char *data = index_deref(self, rev); + + ps[0] = getbe32(data + 24); + ps[1] = getbe32(data + 28); + /* If index file is corrupted, ps[] may point to invalid revisions. So * there is a risk of buffer overflow to trust them unconditionally. */ if (ps[0] < -1 || ps[0] > maxrev || ps[1] < -1 || ps[1] > maxrev) { @@ -238,74 +227,41 @@ static inline int64_t index_get_start(indexObject *self, Py_ssize_t rev) { + const char *data; uint64_t offset; - if (rev == nullrev) { + + if (rev == nullrev) return 0; - } - if (rev >= self->length) { - PyObject *tuple; - PyObject *pylong; - PY_LONG_LONG tmp; - tuple = PyList_GET_ITEM(self->added, rev - self->length); - pylong = PyTuple_GET_ITEM(tuple, 0); - tmp = PyLong_AsLongLong(pylong); - if (tmp == -1 && PyErr_Occurred()) { - return -1; - } - if (tmp < 0) { - PyErr_Format(PyExc_OverflowError, - "revlog entry size out of bound (%lld)", - (long long)tmp); - return -1; - } - offset = (uint64_t)tmp; + + data = index_deref(self, rev); + offset = getbe32(data + 4); + if (rev == 0) { + /* mask out version number for the first entry */ + offset &= 0xFFFF; } else { - const char *data = index_deref(self, rev); - offset = getbe32(data + 4); - if (rev == 0) { - /* mask out version number for the first entry */ - offset &= 0xFFFF; - } else { - uint32_t offset_high = getbe32(data); - offset |= ((uint64_t)offset_high) << 32; - } + uint32_t offset_high = getbe32(data); + offset |= ((uint64_t)offset_high) << 32; } return (int64_t)(offset >> 16); } static inline int index_get_length(indexObject *self, Py_ssize_t rev) { - if (rev == nullrev) { + const char *data; + int tmp; + + if (rev == nullrev) return 0; + + data = index_deref(self, rev); + + tmp = (int)getbe32(data + 8); + if (tmp < 0) { + PyErr_Format(PyExc_OverflowError, + "revlog entry size out of bound (%d)", tmp); + return -1; } - if (rev >= self->length) { - PyObject *tuple; - PyObject *pylong; - long ret; - tuple = PyList_GET_ITEM(self->added, rev - self->length); - pylong = PyTuple_GET_ITEM(tuple, 1); - ret = PyInt_AsLong(pylong); - if (ret == -1 && PyErr_Occurred()) { - return -1; - } - if (ret < 0 || ret > (long)INT_MAX) { - PyErr_Format(PyExc_OverflowError, - "revlog entry size out of bound (%ld)", - ret); - return -1; - } - return (int)ret; - } else { - const char *data = index_deref(self, rev); - int tmp = (int)getbe32(data + 8); - if (tmp < 0) { - PyErr_Format(PyExc_OverflowError, - "revlog entry size out of bound (%d)", - tmp); - return -1; - } - return tmp; - } + return tmp; } /* @@ -327,7 +283,6 @@ const char *c_node_id; const char *data; Py_ssize_t length = index_length(self); - PyObject *entry; if (pos == nullrev) { Py_INCREF(nullentry); @@ -339,30 +294,16 @@ return NULL; } - if (pos >= self->length) { - PyObject *obj; - obj = PyList_GET_ITEM(self->added, pos - self->length); - Py_INCREF(obj); - return obj; - } - - if (self->cache) { - if (self->cache[pos]) { - Py_INCREF(self->cache[pos]); - return self->cache[pos]; - } - } else { - self->cache = calloc(self->raw_length, sizeof(PyObject *)); - if (self->cache == NULL) - return PyErr_NoMemory(); - } - data = index_deref(self, pos); if (data == NULL) return NULL; offset_flags = getbe32(data + 4); - if (pos == 0) /* mask out version number for the first entry */ + /* + * The first entry on-disk needs the version number masked out, + * but this doesn't apply if entries are added to an empty index. + */ + if (self->length && pos == 0) offset_flags &= 0xFFFF; else { uint32_t offset_high = getbe32(data); @@ -377,18 +318,9 @@ parent_2 = getbe32(data + 28); c_node_id = data + 32; - entry = Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len, - base_rev, link_rev, parent_1, parent_2, c_node_id, - (Py_ssize_t)20); - - if (entry) { - PyObject_GC_UnTrack(entry); - Py_INCREF(entry); - } - - self->cache[pos] = entry; - - return entry; + return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len, + base_rev, link_rev, parent_1, parent_2, c_node_id, + (Py_ssize_t)20); } /* @@ -405,13 +337,6 @@ if (pos >= length) return NULL; - if (pos >= self->length) { - PyObject *tuple, *str; - tuple = PyList_GET_ITEM(self->added, pos - self->length); - str = PyTuple_GetItem(tuple, 7); - return str ? PyBytes_AS_STRING(str) : NULL; - } - data = index_deref(self, pos); return data ? data + 32 : NULL; } @@ -445,30 +370,48 @@ static PyObject *index_append(indexObject *self, PyObject *obj) { - char *node; - Py_ssize_t len; + unsigned long offset_flags; + int rev, comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2; + Py_ssize_t c_node_id_len; + const char *c_node_id; + char *data; - if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 8) { + if (!PyArg_ParseTuple(obj, tuple_format, &offset_flags, &comp_len, + &uncomp_len, &base_rev, &link_rev, &parent_1, + &parent_2, &c_node_id, &c_node_id_len)) { PyErr_SetString(PyExc_TypeError, "8-tuple required"); return NULL; } + if (c_node_id_len != 20 && c_node_id_len != 32) { + PyErr_SetString(PyExc_TypeError, "invalid node"); + return NULL; + } - if (node_check(PyTuple_GET_ITEM(obj, 7), &node) == -1) - return NULL; - - len = index_length(self); - - if (self->added == NULL) { - self->added = PyList_New(0); - if (self->added == NULL) - return NULL; + if (self->new_length == self->added_length) { + size_t new_added_length = + self->added_length ? self->added_length * 2 : 4096; + void *new_added = + PyMem_Realloc(self->added, new_added_length * v1_hdrsize); + if (!new_added) + return PyErr_NoMemory(); + self->added = new_added; + self->added_length = new_added_length; } - - if (PyList_Append(self->added, obj) == -1) - return NULL; + rev = self->length + self->new_length; + data = self->added + v1_hdrsize * self->new_length++; + putbe32(offset_flags >> 32, data); + putbe32(offset_flags & 0xffffffffU, data + 4); + putbe32(comp_len, data + 8); + putbe32(uncomp_len, data + 12); + putbe32(base_rev, data + 16); + putbe32(link_rev, data + 20); + putbe32(parent_1, data + 24); + putbe32(parent_2, data + 28); + memcpy(data + 32, c_node_id, c_node_id_len); + memset(data + 32 + c_node_id_len, 0, 32 - c_node_id_len); if (self->ntinitialized) - nt_insert(&self->nt, node, (int)len); + nt_insert(&self->nt, c_node_id, rev); Py_CLEAR(self->headrevs); Py_RETURN_NONE; @@ -495,20 +438,8 @@ Py_CLEAR(t); \ } while (0) - if (self->added) { - Py_ssize_t len = PyList_GET_SIZE(self->added); - s = PyBytes_FromString("index entries added"); - t = PyInt_FromSsize_t(len); - if (!s || !t) - goto bail; - if (PyDict_SetItem(obj, s, t) == -1) - goto bail; - Py_CLEAR(s); - Py_CLEAR(t); - } - - if (self->raw_length != self->length) - istat(raw_length, "revs on disk"); + if (self->added_length) + istat(new_length, "index entries added"); istat(length, "revs in memory"); istat(ntlookups, "node trie lookups"); istat(ntmisses, "node trie misses"); @@ -1020,22 +951,11 @@ const char *data; int result; - if (rev >= self->length) { - PyObject *tuple = - PyList_GET_ITEM(self->added, rev - self->length); - long ret; - if (!pylong_to_long(PyTuple_GET_ITEM(tuple, 3), &ret)) { - return -2; - } - result = (int)ret; - } else { - data = index_deref(self, rev); - if (data == NULL) { - return -2; - } + data = index_deref(self, rev); + if (data == NULL) + return -2; + result = getbe32(data + 16); - result = getbe32(data + 16); - } if (result > rev) { PyErr_Format( PyExc_ValueError, @@ -1876,7 +1796,7 @@ static int index_init_nt(indexObject *self) { if (!self->ntinitialized) { - if (nt_init(&self->nt, self, (int)self->raw_length) == -1) { + if (nt_init(&self->nt, self, (int)self->length) == -1) { nt_dealloc(&self->nt); return -1; } @@ -2501,17 +2421,17 @@ */ static void index_invalidate_added(indexObject *self, Py_ssize_t start) { - Py_ssize_t i, len = PyList_GET_SIZE(self->added); - - for (i = start; i < len; i++) { - PyObject *tuple = PyList_GET_ITEM(self->added, i); - PyObject *node = PyTuple_GET_ITEM(tuple, 7); + Py_ssize_t i, len; - nt_delete_node(&self->nt, PyBytes_AS_STRING(node)); - } + len = self->length + self->new_length; + i = start - self->length; + if (i < 0) + return; - if (start == 0) - Py_CLEAR(self->added); + for (i = start; i < len; i++) + nt_delete_node(&self->nt, index_deref(self, i) + 32); + + self->new_length = start - self->length; } /* @@ -2569,34 +2489,25 @@ nt_delete_node(&self->nt, node); } - if (self->added) - index_invalidate_added(self, 0); + if (self->new_length) + index_invalidate_added(self, self->length); if (self->ntrev > start) self->ntrev = (int)start; - } else if (self->added) { - Py_CLEAR(self->added); + } else if (self->new_length) { + self->new_length = 0; } self->length = start; - if (start < self->raw_length) { - if (self->cache) { - Py_ssize_t i; - for (i = start; i < self->raw_length; i++) - Py_CLEAR(self->cache[i]); - } - self->raw_length = start; - } goto done; } if (self->ntinitialized) { - index_invalidate_added(self, start - self->length); + index_invalidate_added(self, start); if (self->ntrev > start) self->ntrev = (int)start; + } else { + self->new_length = start - self->length; } - if (self->added) - ret = PyList_SetSlice(self->added, start - self->length, - PyList_GET_SIZE(self->added), NULL); done: Py_CLEAR(self->headrevs); return ret; @@ -2675,9 +2586,9 @@ /* Initialize before argument-checking to avoid index_dealloc() crash. */ - self->raw_length = 0; self->added = NULL; - self->cache = NULL; + self->new_length = 0; + self->added_length = 0; self->data = NULL; memset(&self->buf, 0, sizeof(self->buf)); self->headrevs = NULL; @@ -2709,15 +2620,13 @@ Py_ssize_t len = inline_scan(self, NULL); if (len == -1) goto bail; - self->raw_length = len; self->length = len; } else { if (size % v1_hdrsize) { PyErr_SetString(PyExc_ValueError, "corrupt index file"); goto bail; } - self->raw_length = size / v1_hdrsize; - self->length = self->raw_length; + self->length = size / v1_hdrsize; } return 0; @@ -2733,14 +2642,6 @@ static void _index_clearcaches(indexObject *self) { - if (self->cache) { - Py_ssize_t i; - - for (i = 0; i < self->raw_length; i++) - Py_CLEAR(self->cache[i]); - free(self->cache); - self->cache = NULL; - } if (self->offsets) { PyMem_Free((void *)self->offsets); self->offsets = NULL; @@ -2769,7 +2670,7 @@ memset(&self->buf, 0, sizeof(self->buf)); } Py_XDECREF(self->data); - Py_XDECREF(self->added); + PyMem_Free(self->added); PyObject_Del(self); }
--- a/mercurial/changegroup.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/changegroup.py Thu Dec 03 14:15:39 2020 -0500 @@ -316,20 +316,29 @@ self.callback = progress.increment efilesset = set() + cgnodes = [] + + def ondupchangelog(cl, node): + if cl.rev(node) < clstart: + cgnodes.append(node) def onchangelog(cl, node): efilesset.update(cl.readfiles(node)) self.changelogheader() deltas = self.deltaiter() - cgnodes = cl.addgroup(deltas, csmap, trp, addrevisioncb=onchangelog) - efiles = len(efilesset) - - if not cgnodes: + if not cl.addgroup( + deltas, + csmap, + trp, + addrevisioncb=onchangelog, + duplicaterevisioncb=ondupchangelog, + ): repo.ui.develwarn( b'applied empty changelog from changegroup', config=b'warn-empty-changegroup', ) + efiles = len(efilesset) clend = len(cl) changesets = clend - clstart progress.complete() @@ -356,7 +365,7 @@ for cset in pycompat.xrange(clstart, clend): mfnode = cl.changelogrevision(cset).manifest mfest = ml[mfnode].readdelta() - # store file cgnodes we must see + # store file nodes we must see for f, n in pycompat.iteritems(mfest): needfiles.setdefault(f, set()).add(n) @@ -414,7 +423,7 @@ **pycompat.strkwargs(hookargs) ) - added = [cl.node(r) for r in pycompat.xrange(clstart, clend)] + added = pycompat.xrange(clstart, clend) phaseall = None if srctype in (b'push', b'serve'): # Old servers can not push the boundary themselves. @@ -436,7 +445,8 @@ if added: phases.registernew(repo, tr, targetphase, added) if phaseall is not None: - phases.advanceboundary(repo, tr, phaseall, cgnodes) + phases.advanceboundary(repo, tr, phaseall, cgnodes, revs=added) + cgnodes = [] if changesets > 0: @@ -449,9 +459,9 @@ repo.hook(b"changegroup", **pycompat.strkwargs(hookargs)) - for n in added: + for rev in added: args = hookargs.copy() - args[b'node'] = hex(n) + args[b'node'] = hex(cl.node(rev)) del args[b'node_last'] repo.hook(b"incoming", **pycompat.strkwargs(args))
--- a/mercurial/changelog.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/changelog.py Thu Dec 03 14:15:39 2020 -0500 @@ -91,8 +91,8 @@ class appender(object): - '''the changelog index must be updated last on disk, so we use this class - to delay writes to it''' + """the changelog index must be updated last on disk, so we use this class + to delay writes to it""" def __init__(self, vfs, name, mode, buf): self.data = buf
--- a/mercurial/chgserver.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/chgserver.py Thu Dec 03 14:15:39 2020 -0500 @@ -409,14 +409,23 @@ # be unbuffered no matter if it is a tty or not. if fn == b'ferr': newfp = fp + elif pycompat.ispy3: + # On Python 3, the standard library doesn't offer line-buffered + # binary streams, so wrap/unwrap it. + if fp.isatty(): + newfp = procutil.make_line_buffered(fp) + else: + newfp = procutil.unwrap_line_buffered(fp) else: - # make it line buffered explicitly because the default is - # decided on first write(), where fout could be a pager. + # Python 2 uses the I/O streams provided by the C library, so + # make it line-buffered explicitly. Otherwise the default would + # be decided on first write(), where fout could be a pager. if fp.isatty(): bufsize = 1 # line buffered else: bufsize = -1 # system default newfp = os.fdopen(fp.fileno(), mode, bufsize) + if newfp is not fp: setattr(ui, fn, newfp) setattr(self, cn, newfp) @@ -440,13 +449,16 @@ ui = self.ui for (ch, fp, fd), (cn, fn, mode) in zip(self._oldios, _iochannels): newfp = getattr(ui, fn) - # close newfp while it's associated with client; otherwise it - # would be closed when newfp is deleted - if newfp is not fp: + # On Python 2, newfp and fp may be separate file objects associated + # with the same fd, so we must close newfp while it's associated + # with the client. Otherwise the new associated fd would be closed + # when newfp gets deleted. On Python 3, newfp is just a wrapper + # around fp even if newfp is not fp, so deleting newfp is safe. + if not (pycompat.ispy3 or newfp is fp): newfp.close() # restore original fd: fp is open again try: - if newfp is fp and 'w' in mode: + if (pycompat.ispy3 or newfp is fp) and 'w' in mode: # Discard buffered data which couldn't be flushed because # of EPIPE. The data should belong to the current session # and should never persist. @@ -491,20 +503,22 @@ list, the client can continue with this server after completing all the instructions. """ - from . import dispatch # avoid cycle - args = self._readlist() + errorraised = False try: self.ui, lui = _loadnewui(self.ui, args, self.cdebug) - except error.ParseError as inst: - dispatch._formatparse(self.ui.warn, inst) - self.ui.flush() - self.cresult.write(b'exit 255') - return - except error.Abort as inst: - self.ui.error(_(b"abort: %s\n") % inst.message) + except error.RepoError as inst: + # RepoError can be raised while trying to read shared source + # configuration + self.ui.error(_(b"abort: %s\n") % stringutil.forcebytestr(inst)) if inst.hint: self.ui.error(_(b"(%s)\n") % inst.hint) + errorraised = True + except error.Abort as inst: + self.ui.error(inst.format()) + errorraised = True + + if errorraised: self.ui.flush() self.cresult.write(b'exit 255') return
--- a/mercurial/cmdutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/cmdutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -279,7 +279,7 @@ for x in args: if opts.get(x): if previous: - raise error.Abort( + raise error.InputError( _(b'cannot specify both --%s and --%s') % (to_display(previous), to_display(x)) ) @@ -332,9 +332,9 @@ return if len(note) > 255: - raise error.Abort(_(b"cannot store a note of more than 255 bytes")) + raise error.InputError(_(b"cannot store a note of more than 255 bytes")) if b'\n' in note: - raise error.Abort(_(b"note cannot contain a newline")) + raise error.InputError(_(b"note cannot contain a newline")) def ishunk(x): @@ -399,7 +399,7 @@ def recordfilter(ui, originalhunks, match, operation=None): - """ Prompts the user to filter the originalhunks and return a list of + """Prompts the user to filter the originalhunks and return a list of selected hunks. *operation* is used for to build ui messages to indicate the user what kind of filtering they are doing: reverting, committing, shelving, etc. @@ -426,7 +426,7 @@ msg = _(b'running non-interactively, use %s instead') % cmdsuggest else: msg = _(b'running non-interactively') - raise error.Abort(msg) + raise error.InputError(msg) # make sure username is set before going interactive if not opts.get(b'user'): @@ -451,7 +451,7 @@ wctx = repo[None] merge = len(wctx.parents()) > 1 if merge: - raise error.Abort( + raise error.InputError( _( b'cannot partially commit a merge ' b'(use "hg commit" instead)' @@ -459,7 +459,7 @@ ) def fail(f, msg): - raise error.Abort(b'%s: %s' % (f, msg)) + raise error.InputError(b'%s: %s' % (f, msg)) force = opts.get(b'force') if not force: @@ -510,7 +510,7 @@ try: chunks, newopts = filterfn(ui, originalchunks, match) except error.PatchError as err: - raise error.Abort(_(b'error parsing patch: %s') % err) + raise error.InputError(_(b'error parsing patch: %s') % err) opts.update(newopts) # We need to keep a backup of files that have been newly added and @@ -600,7 +600,7 @@ ui.debug(fp.getvalue()) patch.internalpatch(ui, repo, fp, 1, eolmode=None) except error.PatchError as err: - raise error.Abort(pycompat.bytestr(err)) + raise error.InputError(pycompat.bytestr(err)) del fp # 4. We prepared working directory according to filtered @@ -762,7 +762,7 @@ # checking the argument validity for s in pycompat.bytestr(terseargs): if s not in allst: - raise error.Abort(_(b"'%s' not recognized") % s) + raise error.InputError(_(b"'%s' not recognized") % s) # creating a dirnode object for the root of the repo rootobj = dirnode(b'') @@ -968,10 +968,10 @@ bailifchanged(repo) revs = scmutil.revrange(repo, revs) if not revs: - raise error.Abort(b"empty revision set") + raise error.InputError(b"empty revision set") roots = repo.revs(b'roots(%ld)', revs) if len(roots) > 1: - raise error.Abort( + raise error.InputError( _(b"cannot change branch of non-linear revisions") ) rewriteutil.precheck(repo, revs, b'change branch of') @@ -983,16 +983,20 @@ and label not in rpb and label in repo.branchmap() ): - raise error.Abort(_(b"a branch of the same name already exists")) + raise error.InputError( + _(b"a branch of the same name already exists") + ) if repo.revs(b'obsolete() and %ld', revs): - raise error.Abort( + raise error.InputError( _(b"cannot change branch of a obsolete changeset") ) # make sure only topological heads if repo.revs(b'heads(%ld) - head()', revs): - raise error.Abort(_(b"cannot change branch in middle of a stack")) + raise error.InputError( + _(b"cannot change branch in middle of a stack") + ) replacements = {} # avoid import cycle mercurial.cmdutil -> mercurial.context -> @@ -1074,7 +1078,7 @@ def bailifchanged(repo, merge=True, hint=None): - """ enforce the precondition that working directory must be clean. + """enforce the precondition that working directory must be clean. 'merge' can be set to false if a pending uncommitted merge should be ignored (such as when 'update --check' runs). @@ -1083,10 +1087,10 @@ """ if merge and repo.dirstate.p2() != nullid: - raise error.Abort(_(b'outstanding uncommitted merge'), hint=hint) + raise error.StateError(_(b'outstanding uncommitted merge'), hint=hint) st = repo.status() if st.modified or st.added or st.removed or st.deleted: - raise error.Abort(_(b'uncommitted changes'), hint=hint) + raise error.StateError(_(b'uncommitted changes'), hint=hint) ctx = repo[None] for s in sorted(ctx.substate): ctx.sub(s).bailifchanged(hint=hint) @@ -1210,6 +1214,30 @@ return t.renderdefault(mapping) +def format_changeset_summary(ui, ctx, command=None, default_spec=None): + """Format a changeset summary (one line).""" + spec = None + if command: + spec = ui.config( + b'command-templates', b'oneline-summary.%s' % command, None + ) + if not spec: + spec = ui.config(b'command-templates', b'oneline-summary') + if not spec: + spec = default_spec + if not spec: + spec = ( + b'{separate(" ", ' + b'label("oneline-summary.changeset", "{rev}:{node|short}")' + b', ' + b'join(filter(namespaces % "{ifeq(namespace, "branches", "", join(names % "{label("oneline-summary.{namespace}", name)}", " "))}"), " ")' + b')} ' + b'"{label("oneline-summary.desc", desc|firstline)}"' + ) + text = rendertemplate(ctx, spec) + return text.split(b'\n')[0] + + def _buildfntemplate(pat, total=None, seqno=None, revwidth=None, pathname=None): r"""Convert old-style filename format string to template string @@ -1349,7 +1377,7 @@ b'without a repository' ) if msg: - raise error.Abort(msg) + raise error.InputError(msg) r = None if repo: @@ -1357,7 +1385,7 @@ r = repo.unfiltered().changelog elif dir: if not scmutil.istreemanifest(repo): - raise error.Abort( + raise error.InputError( _( b"--dir can only be used on repos with " b"treemanifest enabled" @@ -1383,16 +1411,18 @@ elif util.safehasattr(r, b'_revlog'): r = r._revlog # pytype: disable=attribute-error elif r is not None: - raise error.Abort(_(b'%r does not appear to be a revlog') % r) + raise error.InputError( + _(b'%r does not appear to be a revlog') % r + ) if not r: if not returnrevlog: - raise error.Abort(_(b'cannot give path to non-revlog')) + raise error.InputError(_(b'cannot give path to non-revlog')) if not file_: raise error.CommandError(cmd, _(b'invalid arguments')) if not os.path.isfile(file_): - raise error.Abort(_(b"revlog '%s' not found") % file_) + raise error.InputError(_(b"revlog '%s' not found") % file_) r = revlog.revlog( vfsmod.vfs(encoding.getcwd(), audit=False), file_[:-2] + b".i" ) @@ -1429,10 +1459,12 @@ if not forget and not after: # TODO: Remove this restriction and make it also create the copy # targets (and remove the rename source if rename==True). - raise error.Abort(_(b'--at-rev requires --after')) + raise error.InputError(_(b'--at-rev requires --after')) ctx = scmutil.revsingle(repo, rev) if len(ctx.parents()) > 1: - raise error.Abort(_(b'cannot mark/unmark copy in merge commit')) + raise error.InputError( + _(b'cannot mark/unmark copy in merge commit') + ) else: ctx = repo[None] @@ -1445,7 +1477,7 @@ new_ctx = ctx else: if len(ctx.parents()) > 1: - raise error.Abort(_(b'cannot unmark copy in merge commit')) + raise error.InputError(_(b'cannot unmark copy in merge commit')) # avoid cycle context -> subrepo -> cmdutil from . import context @@ -1488,9 +1520,9 @@ pats = scmutil.expandpats(pats) if not pats: - raise error.Abort(_(b'no source or destination specified')) + raise error.InputError(_(b'no source or destination specified')) if len(pats) == 1: - raise error.Abort(_(b'no destination specified')) + raise error.InputError(_(b'no destination specified')) dest = pats.pop() def walkpat(pat): @@ -1530,12 +1562,12 @@ rewriteutil.precheck(repo, [ctx.rev()], b'uncopy') absdest = pathutil.canonpath(repo.root, cwd, dest) if ctx.hasdir(absdest): - raise error.Abort( + raise error.InputError( _(b'%s: --at-rev does not support a directory as destination') % uipathfn(absdest) ) if absdest not in ctx: - raise error.Abort( + raise error.InputError( _(b'%s: copy destination does not exist in %s') % (uipathfn(absdest), ctx) ) @@ -1552,12 +1584,12 @@ copylist.append(abs) if not copylist: - raise error.Abort(_(b'no files to copy')) + raise error.InputError(_(b'no files to copy')) # TODO: Add support for `hg cp --at-rev . foo bar dir` and # `hg cp --at-rev . dir1 dir2`, preferably unifying the code with the # existing functions below. if len(copylist) != 1: - raise error.Abort(_(b'--at-rev requires a single source')) + raise error.InputError(_(b'--at-rev requires a single source')) new_ctx = context.overlayworkingctx(repo) new_ctx.setbase(ctx.p1()) @@ -1785,14 +1817,16 @@ destdirexists = os.path.isdir(dest) and not os.path.islink(dest) if not destdirexists: if len(pats) > 1 or matchmod.patkind(pats[0]): - raise error.Abort( + raise error.InputError( _( b'with multiple sources, destination must be an ' b'existing directory' ) ) if util.endswithsep(dest): - raise error.Abort(_(b'destination %s is not a directory') % dest) + raise error.InputError( + _(b'destination %s is not a directory') % dest + ) tfn = targetpathfn if after: @@ -1804,7 +1838,7 @@ continue copylist.append((tfn(pat, dest, srcs), srcs)) if not copylist: - raise error.Abort(_(b'no files to copy')) + raise error.InputError(_(b'no files to copy')) errors = 0 for targetpath, srcs in copylist: @@ -1895,7 +1929,7 @@ parents.append(repo[nullid]) if opts.get(b'exact'): if not nodeid or not p1: - raise error.Abort(_(b'not a Mercurial patch')) + raise error.InputError(_(b'not a Mercurial patch')) p1 = repo[p1] p2 = repo[p2 or nullid] elif p2: @@ -2150,7 +2184,7 @@ opts=None, match=None, ): - '''export changesets as hg patches + """export changesets as hg patches Args: repo: The repository from which we're exporting revisions. @@ -2171,7 +2205,7 @@ fntemplate specified: Each rev is written to a unique file named using the given template. Otherwise: All revs will be written to basefm. - ''' + """ _prefetchchangedfiles(repo, revs, match) if not fntemplate: @@ -2231,7 +2265,7 @@ try: rev = mrevs.max() except ValueError: - raise error.Abort(_(b"revision matching date not found")) + raise error.InputError(_(b"revision matching date not found")) ui.status( _(b"found revision %d from %s\n") @@ -2314,7 +2348,9 @@ ui, repo, match, prefix, uipathfn, explicitonly, dryrun, interactive ): if dryrun and interactive: - raise error.Abort(_(b"cannot specify both --dry-run and --interactive")) + raise error.InputError( + _(b"cannot specify both --dry-run and --interactive") + ) bad = [] badfn = lambda x, y: bad.append(x) or match.bad(x, y) wctx = repo[None] @@ -3026,9 +3062,9 @@ if finishdesc: text = finishdesc(text) if not text.strip(): - raise error.Abort(_(b"empty commit message")) + raise error.InputError(_(b"empty commit message")) if unchangedmessagedetection and editortext == templatetext: - raise error.Abort(_(b"commit message unchanged")) + raise error.InputError(_(b"commit message unchanged")) return text @@ -3089,13 +3125,18 @@ return b"\n".join(edittext) -def commitstatus(repo, node, branch, bheads=None, opts=None): +def commitstatus(repo, node, branch, bheads=None, tip=None, opts=None): if opts is None: opts = {} ctx = repo[node] parents = ctx.parents() - if ( + if tip is not None and repo.changelog.tip() == tip: + # avoid reporting something like "committed new head" when + # recommitting old changesets, and issue a helpful warning + # for most instances + repo.ui.warn(_("warning: commit already existed in the repository!\n")) + elif ( not opts.get(b'amend') and bheads and node not in bheads @@ -3435,7 +3476,8 @@ repo, [f for sublist in oplist for f in sublist] ) prefetch( - repo, [(ctx.rev(), matchfiles)], + repo, + [(ctx.rev(), matchfiles)], ) match = scmutil.match(repo[None], pats) _performrevert( @@ -3683,10 +3725,10 @@ def checkunfinished(repo, commit=False, skipmerge=False): - '''Look for an unfinished multistep operation, like graft, and abort + """Look for an unfinished multistep operation, like graft, and abort if found. It's probably good to check this right before bailifchanged(). - ''' + """ # Check for non-clearable states first, so things like rebase will take # precedence over update. for state in statemod._unfinishedstates: @@ -3697,7 +3739,7 @@ ): continue if state.isunfinished(repo): - raise error.Abort(state.msg(), hint=state.hint()) + raise error.StateError(state.msg(), hint=state.hint()) for s in statemod._unfinishedstates: if ( @@ -3708,18 +3750,18 @@ ): continue if s.isunfinished(repo): - raise error.Abort(s.msg(), hint=s.hint()) + raise error.StateError(s.msg(), hint=s.hint()) def clearunfinished(repo): - '''Check for unfinished operations (as above), and clear the ones + """Check for unfinished operations (as above), and clear the ones that are clearable. - ''' + """ for state in statemod._unfinishedstates: if state._reportonly: continue if not state._clearable and state.isunfinished(repo): - raise error.Abort(state.msg(), hint=state.hint()) + raise error.StateError(state.msg(), hint=state.hint()) for s in statemod._unfinishedstates: if s._opname == b'merge' or state._reportonly: @@ -3729,8 +3771,8 @@ def getunfinishedstate(repo): - ''' Checks for unfinished operations and returns statecheck object - for it''' + """Checks for unfinished operations and returns statecheck object + for it""" for state in statemod._unfinishedstates: if state.isunfinished(repo): return state @@ -3738,7 +3780,7 @@ def howtocontinue(repo): - '''Check for an unfinished operation and return the command to finish + """Check for an unfinished operation and return the command to finish it. statemod._unfinishedstates list is checked for an unfinished operation @@ -3747,7 +3789,7 @@ Returns a (msg, warning) tuple. 'msg' is a string and 'warning' is a boolean. - ''' + """ contmsg = _(b"continue: %s") for state in statemod._unfinishedstates: if not state._continueflag: @@ -3760,13 +3802,13 @@ def checkafterresolved(repo): - '''Inform the user about the next action after completing hg resolve + """Inform the user about the next action after completing hg resolve If there's a an unfinished operation that supports continue flag, howtocontinue will yield repo.ui.warn as the reporter. Otherwise, it will yield repo.ui.note. - ''' + """ msg, warning = howtocontinue(repo) if msg is not None: if warning: @@ -3776,26 +3818,26 @@ def wrongtooltocontinue(repo, task): - '''Raise an abort suggesting how to properly continue if there is an + """Raise an abort suggesting how to properly continue if there is an active task. Uses howtocontinue() to find the active task. If there's no task (repo.ui.note for 'hg commit'), it does not offer a hint. - ''' + """ after = howtocontinue(repo) hint = None if after[1]: hint = after[0] - raise error.Abort(_(b'no %s in progress') % task, hint=hint) + raise error.StateError(_(b'no %s in progress') % task, hint=hint) def abortgraft(ui, repo, graftstate): """abort the interrupted graft and rollbacks to the state before interrupted graft""" if not graftstate.exists(): - raise error.Abort(_(b"no interrupted graft to abort")) + raise error.StateError(_(b"no interrupted graft to abort")) statedata = readgraftstate(repo, graftstate) newnodes = statedata.get(b'newnodes') if newnodes is None:
--- a/mercurial/commands.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/commands.py Thu Dec 03 14:15:39 2020 -0500 @@ -26,6 +26,7 @@ archival, bookmarks, bundle2, + bundlecaches, changegroup, cmdutil, copies, @@ -186,9 +187,9 @@ dryrun = opts.get('dry_run') abortstate = cmdutil.getunfinishedstate(repo) if not abortstate: - raise error.Abort(_(b'no operation in progress')) + raise error.StateError(_(b'no operation in progress')) if not abortstate.abortfunc: - raise error.Abort( + raise error.InputError( ( _(b"%s in progress but does not support 'hg abort'") % (abortstate._opname) @@ -417,7 +418,9 @@ """ opts = pycompat.byteskwargs(opts) if not pats: - raise error.Abort(_(b'at least one filename or pattern is required')) + raise error.InputError( + _(b'at least one filename or pattern is required') + ) if opts.get(b'follow'): # --follow is deprecated and now just an alias for -f/--file @@ -438,7 +441,7 @@ and (not opts.get(b'changeset')) and (not opts.get(b'number')) ): - raise error.Abort(_(b'at least one of -n/-c is required for -l')) + raise error.InputError(_(b'at least one of -n/-c is required for -l')) rev = opts.get(b'rev') if rev: @@ -602,7 +605,7 @@ helpcategory=command.CATEGORY_IMPORT_EXPORT, ) def archive(ui, repo, dest, **opts): - '''create an unversioned archive of a repository revision + """create an unversioned archive of a repository revision By default, the revision used is the parent of the working directory; use -r/--rev to specify a different revision. @@ -641,7 +644,7 @@ removed. Returns 0 on success. - ''' + """ opts = pycompat.byteskwargs(opts) rev = opts.get(b'rev') @@ -649,18 +652,20 @@ repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn') ctx = scmutil.revsingle(repo, rev) if not ctx: - raise error.Abort(_(b'no working directory: please specify a revision')) + raise error.InputError( + _(b'no working directory: please specify a revision') + ) node = ctx.node() dest = cmdutil.makefilename(ctx, dest) if os.path.realpath(dest) == repo.root: - raise error.Abort(_(b'repository root cannot be destination')) + raise error.InputError(_(b'repository root cannot be destination')) kind = opts.get(b'type') or archival.guesskind(dest) or b'files' prefix = opts.get(b'prefix') if dest == b'-': if kind == b'files': - raise error.Abort(_(b'cannot archive plain files to stdout')) + raise error.InputError(_(b'cannot archive plain files to stdout')) dest = cmdutil.makefileobj(ctx, dest) if not prefix: prefix = os.path.basename(repo.root) + b'-%h' @@ -713,7 +718,7 @@ helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, ) def backout(ui, repo, node=None, rev=None, **opts): - '''reverse effect of earlier changeset + """reverse effect of earlier changeset Prepare a new changeset with the effect of REV undone in the current working directory. If no conflicts were encountered, @@ -763,7 +768,7 @@ Returns 0 on success, 1 if nothing to backout or there are unresolved files. - ''' + """ with repo.wlock(), repo.lock(): return _dobackout(ui, repo, node, rev, **opts) @@ -773,13 +778,13 @@ opts = pycompat.byteskwargs(opts) if rev and node: - raise error.Abort(_(b"please specify just one revision")) + raise error.InputError(_(b"please specify just one revision")) if not rev: rev = node if not rev: - raise error.Abort(_(b"please specify a revision to backout")) + raise error.InputError(_(b"please specify a revision to backout")) date = opts.get(b'date') if date: @@ -792,23 +797,27 @@ op1, op2 = repo.dirstate.parents() if not repo.changelog.isancestor(node, op1): - raise error.Abort(_(b'cannot backout change that is not an ancestor')) + raise error.InputError( + _(b'cannot backout change that is not an ancestor') + ) p1, p2 = repo.changelog.parents(node) if p1 == nullid: - raise error.Abort(_(b'cannot backout a change with no parents')) + raise error.InputError(_(b'cannot backout a change with no parents')) if p2 != nullid: if not opts.get(b'parent'): - raise error.Abort(_(b'cannot backout a merge changeset')) + raise error.InputError(_(b'cannot backout a merge changeset')) p = repo.lookup(opts[b'parent']) if p not in (p1, p2): - raise error.Abort( + raise error.InputError( _(b'%s is not a parent of %s') % (short(p), short(node)) ) parent = p else: if opts.get(b'parent'): - raise error.Abort(_(b'cannot use --parent on non-merge changeset')) + raise error.InputError( + _(b'cannot use --parent on non-merge changeset') + ) parent = p1 # the backout should appear on the same branch @@ -850,11 +859,14 @@ message, opts.get(b'user'), opts.get(b'date'), match, editor=e ) + # save to detect changes + tip = repo.changelog.tip() + newnode = cmdutil.commit(ui, repo, commitfunc, [], opts) if not newnode: ui.status(_(b"nothing changed\n")) return 1 - cmdutil.commitstatus(repo, newnode, branch, bheads) + cmdutil.commitstatus(repo, newnode, branch, bheads, tip) def nice(node): return b'%d:%s' % (repo.changelog.rev(node), short(node)) @@ -895,8 +907,8 @@ def bisect( ui, repo, - rev=None, - extra=None, + positional_1=None, + positional_2=None, command=None, reset=None, good=None, @@ -986,18 +998,22 @@ Returns 0 on success. """ + rev = [] # backward compatibility - if rev in b"good bad reset init".split(): + if positional_1 in (b"good", b"bad", b"reset", b"init"): ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n")) - cmd, rev, extra = rev, extra, None + cmd = positional_1 + rev.append(positional_2) if cmd == b"good": good = True elif cmd == b"bad": bad = True else: reset = True - elif extra: - raise error.Abort(_(b'incompatible arguments')) + elif positional_2: + raise error.InputError(_(b'incompatible arguments')) + elif positional_1 is not None: + rev.append(positional_1) incompatibles = { b'--bad': bad, @@ -1011,7 +1027,7 @@ enabled = [x for x in incompatibles if incompatibles[x]] if len(enabled) > 1: - raise error.Abort( + raise error.InputError( _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2]) ) @@ -1021,12 +1037,13 @@ state = hbisect.load_state(repo) + if rev: + nodes = [repo[i].node() for i in scmutil.revrange(repo, rev)] + else: + nodes = [repo.lookup(b'.')] + # update state if good or bad or skip: - if rev: - nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])] - else: - nodes = [repo.lookup(b'.')] if good: state[b'good'] += nodes elif bad: @@ -1053,7 +1070,7 @@ try: node = state[b'current'][0] except LookupError: - raise error.Abort( + raise error.StateError( _( b'current bisect revision is unknown - ' b'start a new bisect to fix' @@ -1062,9 +1079,11 @@ else: node, p2 = repo.dirstate.parents() if p2 != nullid: - raise error.Abort(_(b'current bisect revision is a merge')) + raise error.StateError(_(b'current bisect revision is a merge')) if rev: - node = repo[scmutil.revsingle(repo, rev, node)].node() + if not nodes: + raise error.Abort(_(b'empty revision set')) + node = repo[nodes.last()].node() with hbisect.restore_state(repo, state, node): while changesets: # update state @@ -1115,7 +1134,7 @@ state[b'current'] = [extendnode.node()] hbisect.save_state(repo, state) return mayupdate(repo, extendnode.node()) - raise error.Abort(_(b"nothing to extend")) + raise error.StateError(_(b"nothing to extend")) if changesets == 0: hbisect.printresult(ui, repo, state, displayer, nodes, good) @@ -1154,7 +1173,7 @@ helpcategory=command.CATEGORY_CHANGE_ORGANIZATION, ) def bookmark(ui, repo, *names, **opts): - '''create a new bookmark or list existing bookmarks + """create a new bookmark or list existing bookmarks Bookmarks are labels on changesets to help track lines of development. Bookmarks are unversioned and can be moved, renamed and deleted. @@ -1212,7 +1231,7 @@ - print only the active bookmark name:: hg book -ql . - ''' + """ opts = pycompat.byteskwargs(opts) force = opts.get(b'force') rev = opts.get(b'rev') @@ -1232,7 +1251,7 @@ opts, b'inactive', [b'delete', b'list'] ) if not names and action in {b'add', b'delete'}: - raise error.Abort(_(b"bookmark name required")) + raise error.InputError(_(b"bookmark name required")) if action in {b'add', b'delete', b'rename', b'inactive'}: with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr: @@ -1241,9 +1260,11 @@ bookmarks.delete(repo, tr, names) elif action == b'rename': if not names: - raise error.Abort(_(b"new bookmark name required")) + raise error.InputError(_(b"new bookmark name required")) elif len(names) > 1: - raise error.Abort(_(b"only one new bookmark name allowed")) + raise error.InputError( + _(b"only one new bookmark name allowed") + ) oldname = repo._bookmarks.expandname(opts[b'rename']) bookmarks.rename(repo, tr, oldname, names[0], force, inactive) elif action == b'add': @@ -1319,7 +1340,9 @@ if not opts.get(b'clean') and not label: if revs: - raise error.Abort(_(b"no branch name specified for the revisions")) + raise error.InputError( + _(b"no branch name specified for the revisions") + ) ui.write(b"%s\n" % repo.dirstate.branch()) return @@ -1336,7 +1359,7 @@ if not opts.get(b'force') and label in repo.branchmap(): if label not in [p.branch() for p in repo[None].parents()]: - raise error.Abort( + raise error.InputError( _(b'a branch of the same name already exists'), # i18n: "it" refers to an existing branch hint=_(b"use 'hg update' to switch to it"), @@ -1538,13 +1561,15 @@ revstrings = opts[b'rev'] revs = scmutil.revrange(repo, revstrings) if revstrings and not revs: - raise error.Abort(_(b'no commits to bundle')) + raise error.InputError(_(b'no commits to bundle')) bundletype = opts.get(b'type', b'bzip2').lower() try: - bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False) + bundlespec = bundlecaches.parsebundlespec( + repo, bundletype, strict=False + ) except error.UnsupportedBundleSpecification as e: - raise error.Abort( + raise error.InputError( pycompat.bytestr(e), hint=_(b"see 'hg help bundlespec' for supported values for --type"), ) @@ -1552,14 +1577,14 @@ # Packed bundles are a pseudo bundle format for now. if cgversion == b's1': - raise error.Abort( + raise error.InputError( _(b'packed bundles cannot be produced by "hg bundle"'), hint=_(b"use 'hg debugcreatestreamclonebundle'"), ) if opts.get(b'all'): if dest: - raise error.Abort( + raise error.InputError( _(b"--all is incompatible with specifying a destination") ) if opts.get(b'base'): @@ -1574,7 +1599,7 @@ if base: if dest: - raise error.Abort( + raise error.InputError( _(b"--base is incompatible with specifying a destination") ) common = [repo[rev].node() for rev in base] @@ -2013,8 +2038,7 @@ opts = pycompat.byteskwargs(opts) if opts.get(b'subrepos'): - if opts.get(b'amend'): - raise error.Abort(_(b'cannot amend with --subrepos')) + cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'amend']) # Let --subrepos on the command line override config setting. ui.setconfig(b'ui', b'commitsubrepos', True, b'commit') @@ -2022,17 +2046,20 @@ branch = repo[None].branch() bheads = repo.branchheads(branch) + tip = repo.changelog.tip() extra = {} if opts.get(b'close_branch') or opts.get(b'force_close_branch'): extra[b'close'] = b'1' if repo[b'.'].closesbranch(): - raise error.Abort( + raise error.InputError( _(b'current revision is already a branch closing head') ) elif not bheads: - raise error.Abort(_(b'branch "%s" has no heads to close') % branch) + raise error.InputError( + _(b'branch "%s" has no heads to close') % branch + ) elif ( branch == repo[b'.'].branch() and repo[b'.'].node() not in bheads @@ -2042,17 +2069,19 @@ b'use --force-close-branch to close branch from a non-head' b' changeset' ) - raise error.Abort(_(b'can only close branch heads'), hint=hint) + raise error.InputError(_(b'can only close branch heads'), hint=hint) elif opts.get(b'amend'): if ( repo[b'.'].p1().branch() != branch and repo[b'.'].p2().branch() != branch ): - raise error.Abort(_(b'can only close branch heads')) + raise error.InputError(_(b'can only close branch heads')) if opts.get(b'amend'): if ui.configbool(b'ui', b'commitsubrepos'): - raise error.Abort(_(b'cannot amend with ui.commitsubrepos enabled')) + raise error.InputError( + _(b'cannot amend with ui.commitsubrepos enabled') + ) old = repo[b'.'] rewriteutil.precheck(repo, [old.rev()], b'amend') @@ -2111,7 +2140,7 @@ ui.status(_(b"nothing changed\n")) return 1 - cmdutil.commitstatus(repo, node, branch, bheads, opts) + cmdutil.commitstatus(repo, node, branch, bheads, tip, opts) if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'): status( @@ -2138,6 +2167,7 @@ None, _(b'edit shared source repository config (EXPERIMENTAL)'), ), + (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')), (b'g', b'global', None, _(b'edit global config')), ] + formatteropts, @@ -2168,6 +2198,9 @@ .. container:: verbose + --non-shared flag is used to edit `.hg/hgrc-not-shared` config file. + This file is not shared across shares when in share-safe mode. + Template: The following keywords are supported. See also :hg:`help templates`. @@ -2185,28 +2218,32 @@ """ opts = pycompat.byteskwargs(opts) - editopts = (b'edit', b'local', b'global', b'shared') + editopts = (b'edit', b'local', b'global', b'shared', b'non_shared') if any(opts.get(o) for o in editopts): cmdutil.check_at_most_one_arg(opts, *editopts[1:]) if opts.get(b'local'): if not repo: - raise error.Abort(_(b"can't use --local outside a repository")) + raise error.InputError( + _(b"can't use --local outside a repository") + ) paths = [repo.vfs.join(b'hgrc')] elif opts.get(b'global'): paths = rcutil.systemrcpath() elif opts.get(b'shared'): if not repo.shared(): - raise error.Abort( + raise error.InputError( _(b"repository is not shared; can't use --shared") ) - if requirements.SHARESAFE_REQUIREMENT not in repo.requirements: - raise error.Abort( - _( - b"share safe feature not unabled; " - b"unable to edit shared source repository config" - ) + if requirements.SHARESAFE_REQUIREMENT not in repo.requirements: + raise error.InputError( + _( + b"share safe feature not enabled; " + b"unable to edit shared source repository config" ) + ) paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')] + elif opts.get(b'non_shared'): + paths = [repo.vfs.join(b'hgrc-not-shared')] else: paths = rcutil.userrcpath() @@ -2229,7 +2266,7 @@ editor = ui.geteditor() ui.system( b"%s \"%s\"" % (editor, f), - onerr=error.Abort, + onerr=error.InputError, errprefix=_(b"edit failed"), blockedtag=b'config_edit', ) @@ -2305,9 +2342,9 @@ dryrun = opts.get('dry_run') contstate = cmdutil.getunfinishedstate(repo) if not contstate: - raise error.Abort(_(b'no operation in progress')) + raise error.StateError(_(b'no operation in progress')) if not contstate.continuefunc: - raise error.Abort( + raise error.StateError( ( _(b"%s in progress but does not support 'hg continue'") % (contstate._opname) @@ -2341,7 +2378,7 @@ ] + walkopts + dryrunopts, - _(b'[OPTION]... SOURCE... DEST'), + _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'), helpcategory=command.CATEGORY_FILE_CONTENTS, ) def copy(ui, repo, *pats, **opts): @@ -2637,7 +2674,7 @@ if bookmark: if bookmark not in repo._bookmarks: - raise error.Abort(_(b"bookmark '%s' not found") % bookmark) + raise error.InputError(_(b"bookmark '%s' not found") % bookmark) revs = scmutil.bookmarkrevs(repo, bookmark) else: @@ -2648,7 +2685,7 @@ revs = scmutil.revrange(repo, changesets) if not revs: - raise error.Abort(_(b"export requires at least one changeset")) + raise error.InputError(_(b"export requires at least one changeset")) if len(revs) > 1: ui.note(_(b'exporting patches:\n')) else: @@ -2774,7 +2811,9 @@ @command( b'forget', - [(b'i', b'interactive', None, _(b'use interactive mode')),] + [ + (b'i', b'interactive', None, _(b'use interactive mode')), + ] + walkopts + dryrunopts, _(b'[OPTION]... FILE...'), @@ -2813,7 +2852,7 @@ opts = pycompat.byteskwargs(opts) if not pats: - raise error.Abort(_(b'no files specified')) + raise error.InputError(_(b'no files specified')) m = scmutil.match(repo[None], pats, opts) dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive') @@ -2874,7 +2913,7 @@ helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, ) def graft(ui, repo, *revs, **opts): - '''copy changes from other branches onto the current branch + """copy changes from other branches onto the current branch This command uses Mercurial's merge logic to copy individual changes from other branches without merging branches in the @@ -2967,7 +3006,7 @@ See :hg:`help revisions` for more about specifying revisions. Returns 0 on successful completion, 1 if there are unresolved files. - ''' + """ with repo.wlock(): return _dograft(ui, repo, *revs, **opts) @@ -3040,7 +3079,7 @@ elif opts.get(b'continue'): cont = True if revs: - raise error.Abort(_(b"can't specify --continue and revisions")) + raise error.InputError(_(b"can't specify --continue and revisions")) # read in unfinished revisions if graftstate.exists(): statedata = cmdutil.readgraftstate(repo, graftstate) @@ -3060,7 +3099,7 @@ cmdutil.wrongtooltocontinue(repo, _(b'graft')) else: if not revs: - raise error.Abort(_(b'no revisions specified')) + raise error.InputError(_(b'no revisions specified')) cmdutil.checkunfinished(repo) cmdutil.bailifchanged(repo) revs = scmutil.revrange(repo, revs) @@ -3078,7 +3117,7 @@ if not revs: return -1 if basectx is not None and len(revs) != 1: - raise error.Abort(_(b'only one revision allowed with --base ')) + raise error.InputError(_(b'only one revision allowed with --base ')) # Don't check in the --continue case, in effect retaining --force across # --continues. That's because without --force, any revisions we decided to @@ -3240,7 +3279,7 @@ def _stopgraft(ui, repo, graftstate): """stop the interrupted graft""" if not graftstate.exists(): - raise error.Abort(_(b"no interrupted graft found")) + raise error.StateError(_(b"no interrupted graft found")) pctx = repo[b'.'] mergemod.clean_update(pctx) graftstate.delete() @@ -3753,7 +3792,7 @@ opts = pycompat.byteskwargs(opts) if not repo and not source: - raise error.Abort( + raise error.InputError( _(b"there is no Mercurial repository here (.hg not found)") ) @@ -3772,7 +3811,7 @@ if not repo: if num or branch or tags: - raise error.Abort( + raise error.InputError( _(b"can't query remote revision number, branch, or tags") ) if not rev and revs: @@ -4044,7 +4083,7 @@ cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix']) opts = pycompat.byteskwargs(opts) if not patch1: - raise error.Abort(_(b'need at least one patch to import')) + raise error.InputError(_(b'need at least one patch to import')) patches = (patch1,) + patches @@ -4057,11 +4096,11 @@ try: sim = float(opts.get(b'similarity') or 0) except ValueError: - raise error.Abort(_(b'similarity must be a number')) + raise error.InputError(_(b'similarity must be a number')) if sim < 0 or sim > 100: - raise error.Abort(_(b'similarity must be between 0 and 100')) + raise error.InputError(_(b'similarity must be between 0 and 100')) if sim and not update: - raise error.Abort(_(b'cannot use --similarity with --bypass')) + raise error.InputError(_(b'cannot use --similarity with --bypass')) base = opts[b"base"] msgs = [] @@ -4118,7 +4157,7 @@ break if not haspatch: - raise error.Abort(_(b'%s: no diffs found') % patchurl) + raise error.InputError(_(b'%s: no diffs found') % patchurl) if msgs: repo.savecommitmessage(b'\n* * *\n'.join(msgs)) @@ -4426,6 +4465,13 @@ _(b'BRANCH'), ), ( + b'B', + b'bookmark', + [], + _(b"show changesets within the given bookmark"), + _(b'BOOKMARK'), + ), + ( b'P', b'prune', [], @@ -4564,7 +4610,7 @@ See :hg:`help templates` for more about pre-packaged styles and specifying custom templates. The default template used by the log - command can be customized via the ``ui.logtemplate`` configuration + command can be customized via the ``command-templates.log`` configuration setting. Returns 0 on success. @@ -4574,23 +4620,28 @@ linerange = opts.get(b'line_range') if linerange and not opts.get(b'follow'): - raise error.Abort(_(b'--line-range requires --follow')) + raise error.InputError(_(b'--line-range requires --follow')) if linerange and pats: # TODO: take pats as patterns with no line-range filter - raise error.Abort( + raise error.InputError( _(b'FILE arguments are not compatible with --line-range option') ) repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn') - revs, differ = logcmdutil.getrevs( - repo, logcmdutil.parseopts(ui, pats, opts) - ) + walk_opts = logcmdutil.parseopts(ui, pats, opts) + revs, differ = logcmdutil.getrevs(repo, walk_opts) if linerange: # TODO: should follow file history from logcmdutil._initialrevs(), # then filter the result by logcmdutil._makerevset() and --limit revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts) + if opts.get(b'bookmark'): + cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark') + bookmarks = opts.get(b'bookmark') + bookmark = bookmarks[0] + revs, differ = logcmdutil.get_bookmark_revs(repo, bookmark, walk_opts) + getcopies = None if opts.get(b'copies'): endrev = None @@ -4640,7 +4691,7 @@ if opts.get(b'all'): if rev or node: - raise error.Abort(_(b"can't specify a revision with --all")) + raise error.InputError(_(b"can't specify a revision with --all")) res = set() for rev in repo: @@ -4655,7 +4706,7 @@ return if rev and node: - raise error.Abort(_(b"please specify just one revision")) + raise error.InputError(_(b"please specify just one revision")) if not node: node = rev @@ -4737,16 +4788,16 @@ if abort: state = cmdutil.getunfinishedstate(repo) if state and state._opname != b'merge': - raise error.Abort( + raise error.StateError( _(b'cannot abort merge with %s in progress') % (state._opname), hint=state.hint(), ) if node: - raise error.Abort(_(b"cannot specify a node with --abort")) + raise error.InputError(_(b"cannot specify a node with --abort")) return hg.abortmerge(repo.ui, repo) if opts.get(b'rev') and node: - raise error.Abort(_(b"please specify just one revision")) + raise error.InputError(_(b"please specify just one revision")) if not node: node = opts.get(b'rev') @@ -4754,7 +4805,7 @@ ctx = scmutil.revsingle(repo, node) else: if ui.configbool(b'commands', b'merge.require-rev'): - raise error.Abort( + raise error.InputError( _( b'configuration requires specifying revision to merge ' b'with' @@ -4763,7 +4814,9 @@ ctx = repo[destutil.destmerge(repo)] if ctx.node() is None: - raise error.Abort(_(b'merging with the working copy has no effect')) + raise error.InputError( + _(b'merging with the working copy has no effect') + ) if opts.get(b'preview'): # find nodes that are ancestors of p2 but not of p1 @@ -4871,7 +4924,7 @@ # style URLs, so don't overwrite dest. path = ui.paths.getpath(dest, default=(b'default-push', b'default')) if not path: - raise error.Abort( + raise error.ConfigError( _(b'default repository not configured!'), hint=_(b"see 'hg help config.paths'"), ) @@ -4956,7 +5009,7 @@ if file_: m = scmutil.match(ctx, (file_,), opts) if m.anypats() or len(m.files()) != 1: - raise error.Abort(_(b'can only specify an explicit filename')) + raise error.InputError(_(b'can only specify an explicit filename')) file_ = m.files()[0] filenodes = [] for cp in ctx.parents(): @@ -4967,7 +5020,7 @@ except error.LookupError: pass if not filenodes: - raise error.Abort(_(b"'%s' not found in manifest!") % file_) + raise error.InputError(_(b"'%s' not found in manifest") % file_) p = [] for fn in filenodes: fctx = repo.filectx(file_, fileid=fn) @@ -5109,7 +5162,7 @@ for idx, name in enumerate(phases.cmdphasenames): if opts[name]: if targetphase is not None: - raise error.Abort(_(b'only one phase can be specified')) + raise error.InputError(_(b'only one phase can be specified')) targetphase = idx # look for specified revision @@ -5132,7 +5185,7 @@ with repo.lock(), repo.transaction(b"phase") as tr: # set phase if not revs: - raise error.Abort(_(b'empty revision set')) + raise error.InputError(_(b'empty revision set')) nodes = [repo[r].node() for r in revs] # moving revision from public to draft may hide them # We have to check result on an unfiltered repository @@ -5217,7 +5270,12 @@ None, _(b'run even when remote repository is unrelated'), ), - (b'', b'confirm', None, _(b'confirm pull before applying changes'),), + ( + b'', + b'confirm', + None, + _(b'confirm pull before applying changes'), + ), ( b'r', b'rev', @@ -5275,10 +5333,11 @@ ): msg = _(b'update destination required by configuration') hint = _(b'use hg pull followed by hg update DEST') - raise error.Abort(msg, hint=hint) + raise error.InputError(msg, hint=hint) source, branches = hg.parseurl(ui.expandpath(source), opts.get(b'branch')) ui.status(_(b'pulling from %s\n') % util.hidepassword(source)) + ui.flush() other = hg.peer(repo, opts, source) try: revs, checkout = hg.addbranchrevs( @@ -5314,7 +5373,9 @@ for b in opts.get(b'bookmark', []): b = repo._bookmarks.expandname(b) if b not in remotebookmarks: - raise error.Abort(_(b'remote bookmark %s not found!') % b) + raise error.InputError( + _(b'remote bookmark %s not found!') % b + ) nodes.append(remotebookmarks[b]) for i, rev in enumerate(revs): node = fnodes[i].result() @@ -5383,6 +5444,7 @@ _(b'REV'), ), (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')), + (b'', b'all-bookmarks', None, _(b"push all bookmarks (EXPERIMENTAL)")), ( b'b', b'branch', @@ -5439,7 +5501,8 @@ If -B/--bookmark is used, the specified bookmarked revision, its ancestors, and the bookmark will be pushed to the remote repository. Specifying ``.`` is equivalent to specifying the active - bookmark's name. + bookmark's name. Use the --all-bookmarks option for pushing all + current bookmarks. Please see :hg:`help urls` for important details about ``ssh://`` URLs. If DESTINATION is omitted, a default path will be used. @@ -5467,6 +5530,15 @@ """ opts = pycompat.byteskwargs(opts) + + if opts.get(b'all_bookmarks'): + cmdutil.check_incompatible_arguments( + opts, + b'all_bookmarks', + [b'bookmark', b'rev'], + ) + opts[b'bookmark'] = list(repo._bookmarks) + if opts.get(b'bookmark'): ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push') for b in opts[b'bookmark']: @@ -5481,7 +5553,7 @@ path = ui.paths.getpath(dest, default=(b'default-push', b'default')) if not path: - raise error.Abort( + raise error.ConfigError( _(b'default repository not configured!'), hint=_(b"see 'hg help config.paths'"), ) @@ -5494,7 +5566,7 @@ if revs: revs = [repo[r].node() for r in scmutil.revrange(repo, revs)] if not revs: - raise error.Abort( + raise error.InputError( _(b"specified revisions evaluate to an empty set"), hint=_(b"use different revision arguments"), ) @@ -5505,11 +5577,11 @@ revs = scmutil.revrange(repo, [expr]) revs = [repo[rev].node() for rev in revs] if not revs: - raise error.Abort( + raise error.InputError( _(b'default push revset for path evaluates to an empty set') ) elif ui.configbool(b'commands', b'push.require-revs'): - raise error.Abort( + raise error.InputError( _(b'no revisions specified to push'), hint=_(b'did you mean "hg push -r ."?'), ) @@ -5553,7 +5625,9 @@ @command( b'recover', - [(b'', b'verify', False, b"run `hg verify` after successful recover"),], + [ + (b'', b'verify', False, b"run `hg verify` after successful recover"), + ], helpcategory=command.CATEGORY_MAINTENANCE, ) def recover(ui, repo, **opts): @@ -5638,7 +5712,7 @@ after, force = opts.get(b'after'), opts.get(b'force') dryrun = opts.get(b'dry_run') if not pats and not after: - raise error.Abort(_(b'no files specified')) + raise error.InputError(_(b'no files specified')) m = scmutil.match(repo[None], pats, opts) subrepos = opts.get(b'subrepos') @@ -5768,16 +5842,16 @@ actioncount = len(list(filter(None, [show, mark, unmark, remerge]))) if actioncount > 1: - raise error.Abort(_(b"too many actions specified")) + raise error.InputError(_(b"too many actions specified")) elif actioncount == 0 and ui.configbool( b'commands', b'resolve.explicit-re-merge' ): hint = _(b'use --mark, --unmark, --list or --re-merge') - raise error.Abort(_(b'no action specified'), hint=hint) + raise error.InputError(_(b'no action specified'), hint=hint) if pats and all: - raise error.Abort(_(b"can't specify --all and patterns")) + raise error.InputError(_(b"can't specify --all and patterns")) if not (all or pats or show or mark or unmark): - raise error.Abort( + raise error.InputError( _(b'no files or directories specified'), hint=b'use --all to re-merge all unresolved files', ) @@ -5787,7 +5861,7 @@ if ui.promptchoice( _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No') ): - raise error.Abort(_(b'user quit')) + raise error.CanceledError(_(b'user quit')) if mark and not pats: if ui.promptchoice( _( @@ -5795,7 +5869,7 @@ b'$$ &Yes $$ &No' ) ): - raise error.Abort(_(b'user quit')) + raise error.CanceledError(_(b'user quit')) if unmark and not pats: if ui.promptchoice( _( @@ -5803,7 +5877,7 @@ b'$$ &Yes $$ &No' ) ): - raise error.Abort(_(b'user quit')) + raise error.CanceledError(_(b'user quit')) uipathfn = scmutil.getuipathfn(repo) @@ -5850,7 +5924,7 @@ ms = mergestatemod.mergestate.read(repo) if not (ms.active() or repo.dirstate.p2() != nullid): - raise error.Abort( + raise error.StateError( _(b'resolve command not applicable when not merging') ) @@ -5942,7 +6016,7 @@ ) ) if markcheck == b'abort' and not all and not pats: - raise error.Abort( + raise error.StateError( _(b'conflict markers detected'), hint=_(b'use --all to mark anyway'), ) @@ -6061,7 +6135,7 @@ parent, p2 = repo.dirstate.parents() if not opts.get(b'rev') and p2 != nullid: # revert after merge is a trap for new users (issue2915) - raise error.Abort( + raise error.InputError( _(b'uncommitted merge with no revision specified'), hint=_(b"use 'hg update' or see 'hg help revert'"), ) @@ -6084,7 +6158,7 @@ b"uncommitted merge, use --all to discard all changes," b" or 'hg update -C .' to abort the merge" ) - raise error.Abort(msg, hint=hint) + raise error.InputError(msg, hint=hint) dirty = any(repo.status()) node = ctx.node() if node != parent: @@ -6108,7 +6182,7 @@ hint = _(b"uncommitted changes, use --all to discard all changes") else: hint = _(b"use --all to revert all files") - raise error.Abort(msg, hint=hint) + raise error.InputError(msg, hint=hint) return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts)) @@ -6318,7 +6392,7 @@ cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver']) opts = pycompat.byteskwargs(opts) if opts[b"print_url"] and ui.verbose: - raise error.Abort(_(b"cannot use --print-url with --verbose")) + raise error.InputError(_(b"cannot use --print-url with --verbose")) if opts[b"stdio"]: if repo is None: @@ -6327,6 +6401,7 @@ ) s = wireprotoserver.sshserver(ui, repo) s.serve_forever() + return service = server.createservice(ui, repo, opts) return server.runservice(opts, initfn=service.init, runfn=service.run) @@ -6392,7 +6467,7 @@ helpcategory=command.CATEGORY_WORKING_DIRECTORY, ) def shelve(ui, repo, *pats, **opts): - '''save and set aside changes from the working directory + """save and set aside changes from the working directory Shelving takes files that "hg status" reports as not clean, saves the modifications to a bundle (a shelved change), and reverts the @@ -6423,7 +6498,7 @@ To delete specific shelved changes, use ``--delete``. To delete all shelved changes, use ``--cleanup``. - ''' + """ opts = pycompat.byteskwargs(opts) allowables = [ (b'addremove', {b'create'}), # 'create' is pseudo action @@ -6444,7 +6519,7 @@ if opts.get(opt): for i, allowable in allowables: if opts[i] and opt not in allowable: - raise error.Abort( + raise error.InputError( _( b"options '--%s' and '--%s' may not be " b"used together" @@ -6455,7 +6530,9 @@ if checkopt(b'cleanup'): if pats: - raise error.Abort(_(b"cannot specify names when using '--cleanup'")) + raise error.InputError( + _(b"cannot specify names when using '--cleanup'") + ) return shelvemod.cleanupcmd(ui, repo) elif checkopt(b'delete'): return shelvemod.deletecmd(ui, repo, pats) @@ -6621,7 +6698,7 @@ if revs and terse: msg = _(b'cannot use --terse with --rev') - raise error.Abort(msg) + raise error.InputError(msg) elif change: repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn') ctx2 = scmutil.revsingle(repo, change, None) @@ -7092,11 +7169,11 @@ rev_ = b"." names = [t.strip() for t in (name1,) + names] if len(names) != len(set(names)): - raise error.Abort(_(b'tag names must be unique')) + raise error.InputError(_(b'tag names must be unique')) for n in names: scmutil.checknewlabel(repo, n, b'tag') if not n: - raise error.Abort( + raise error.InputError( _(b'tag names cannot consist entirely of whitespace') ) if opts.get(b'rev'): @@ -7112,16 +7189,20 @@ if repo.tagtype(n) == b'global': alltags = tagsmod.findglobaltags(ui, repo) if alltags[n][0] == nullid: - raise error.Abort(_(b"tag '%s' is already removed") % n) + raise error.InputError( + _(b"tag '%s' is already removed") % n + ) if not repo.tagtype(n): - raise error.Abort(_(b"tag '%s' does not exist") % n) + raise error.InputError(_(b"tag '%s' does not exist") % n) if repo.tagtype(n) != expectedtype: if expectedtype == b'global': - raise error.Abort( + raise error.InputError( _(b"tag '%s' is not a global tag") % n ) else: - raise error.Abort(_(b"tag '%s' is not a local tag") % n) + raise error.InputError( + _(b"tag '%s' is not a local tag") % n + ) rev_ = b'null' if not message: # we don't translate commit messages @@ -7129,16 +7210,16 @@ elif not opts.get(b'force'): for n in names: if n in repo.tags(): - raise error.Abort( + raise error.InputError( _(b"tag '%s' already exists (use -f to force)") % n ) if not opts.get(b'local'): p1, p2 = repo.dirstate.parents() if p2 != nullid: - raise error.Abort(_(b'uncommitted merge')) + raise error.StateError(_(b'uncommitted merge')) bheads = repo.branchheads() if not opts.get(b'force') and bheads and p1 not in bheads: - raise error.Abort( + raise error.InputError( _( b'working directory is not at a branch head ' b'(use -f to force)' @@ -7170,7 +7251,7 @@ not opts.get(b'remove') and scmutil.revsingle(repo, rev_).rev() == nullrev ): - raise error.Abort(_(b"cannot tag null revision")) + raise error.InputError(_(b"cannot tag null revision")) tagsmod.tag( repo, @@ -7302,7 +7383,7 @@ f = hg.openpath(ui, fname) gen = exchange.readbundle(ui, f, fname) if isinstance(gen, streamclone.streamcloneapplier): - raise error.Abort( + raise error.InputError( _( b'packed bundles cannot be applied with ' b'"hg unbundle"' @@ -7497,11 +7578,11 @@ check = opts.get('check') merge = opts.get('merge') if rev and node: - raise error.Abort(_(b"please specify just one revision")) + raise error.InputError(_(b"please specify just one revision")) if ui.configbool(b'commands', b'update.requiredest'): if not node and not rev and not date: - raise error.Abort( + raise error.InputError( _(b'you must specify a destination'), hint=_(b'for example: hg update ".::"'), ) @@ -7510,7 +7591,7 @@ rev = node if date and rev is not None: - raise error.Abort(_(b"you can't specify a revision and a date")) + raise error.InputError(_(b"you can't specify a revision and a date")) updatecheck = None if check: @@ -7645,8 +7726,7 @@ def loadcmdtable(ui, name, cmdtable): - """Load command functions from specified cmdtable - """ + """Load command functions from specified cmdtable""" overrides = [cmd for cmd in cmdtable if cmd in table] if overrides: ui.warn(
--- a/mercurial/commandserver.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/commandserver.py Thu Dec 03 14:15:39 2020 -0500 @@ -316,8 +316,8 @@ return -1 def runcommand(self): - """ reads a list of \0 terminated arguments, executes - and writes the return code to the result channel """ + """reads a list of \0 terminated arguments, executes + and writes the return code to the result channel""" from . import dispatch # avoid cycle args = self._readlist()
--- a/mercurial/commit.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/commit.py Thu Dec 03 14:15:39 2020 -0500 @@ -98,7 +98,11 @@ ) xp1, xp2 = p1.hex(), p2 and p2.hex() or b'' repo.hook( - b'pretxncommit', throw=True, node=hex(n), parent1=xp1, parent2=xp2, + b'pretxncommit', + throw=True, + node=hex(n), + parent1=xp1, + parent2=xp2, ) # set the new commit is proper phase targetphase = subrepoutil.newcommitphase(repo.ui, ctx) @@ -112,7 +116,7 @@ # be compliant anyway # # if minimal phase was 0 we don't need to retract anything - phases.registernew(repo, tr, targetphase, [n]) + phases.registernew(repo, tr, targetphase, [repo[n].rev()]) return n @@ -154,10 +158,10 @@ def _get_salvaged(repo, ms, ctx): - """ returns a list of salvaged files + """returns a list of salvaged files returns empty list if config option which process salvaged files are - not enabled """ + not enabled""" salvaged = [] copy_sd = repo.filecopiesmode == b'changeset-sidedata' if copy_sd and len(ctx.parents()) > 1: @@ -238,7 +242,14 @@ def _filecommit( - repo, fctx, manifest1, manifest2, linkrev, tr, includecopymeta, ms, + repo, + fctx, + manifest1, + manifest2, + linkrev, + tr, + includecopymeta, + ms, ): """ commit an individual file as part of a larger transaction
--- a/mercurial/config.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/config.py Thu Dec 03 14:15:39 2020 -0500 @@ -165,7 +165,7 @@ include(expanded, remap=remap, sections=sections) except IOError as inst: if inst.errno != errno.ENOENT: - raise error.ParseError( + raise error.ConfigError( _(b"cannot include %s (%s)") % (expanded, encoding.strtolocal(inst.strerror)), b"%s:%d" % (src, line), @@ -200,14 +200,19 @@ self._unset.append((section, name)) continue - raise error.ParseError(l.rstrip(), (b"%s:%d" % (src, line))) + message = l.rstrip() + if l.startswith(b' '): + message = b"unexpected leading whitespace: %s" % message + raise error.ConfigError(message, (b"%s:%d" % (src, line))) def read(self, path, fp=None, sections=None, remap=None): if not fp: fp = util.posixfile(path, b'rb') - assert getattr(fp, 'mode', 'rb') == 'rb', ( - b'config files must be opened in binary mode, got fp=%r mode=%r' - % (fp, fp.mode,) + assert ( + getattr(fp, 'mode', 'rb') == 'rb' + ), b'config files must be opened in binary mode, got fp=%r mode=%r' % ( + fp, + fp.mode, ) dir = os.path.dirname(path)
--- a/mercurial/configitems.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/configitems.py Thu Dec 03 14:15:39 2020 -0500 @@ -133,78 +133,127 @@ def _registerdiffopts(section, configprefix=b''): coreconfigitem( - section, configprefix + b'nodates', default=False, + section, + configprefix + b'nodates', + default=False, ) coreconfigitem( - section, configprefix + b'showfunc', default=False, + section, + configprefix + b'showfunc', + default=False, ) coreconfigitem( - section, configprefix + b'unified', default=None, + section, + configprefix + b'unified', + default=None, ) coreconfigitem( - section, configprefix + b'git', default=False, + section, + configprefix + b'git', + default=False, ) coreconfigitem( - section, configprefix + b'ignorews', default=False, + section, + configprefix + b'ignorews', + default=False, ) coreconfigitem( - section, configprefix + b'ignorewsamount', default=False, + section, + configprefix + b'ignorewsamount', + default=False, ) coreconfigitem( - section, configprefix + b'ignoreblanklines', default=False, + section, + configprefix + b'ignoreblanklines', + default=False, ) coreconfigitem( - section, configprefix + b'ignorewseol', default=False, + section, + configprefix + b'ignorewseol', + default=False, ) coreconfigitem( - section, configprefix + b'nobinary', default=False, + section, + configprefix + b'nobinary', + default=False, ) coreconfigitem( - section, configprefix + b'noprefix', default=False, + section, + configprefix + b'noprefix', + default=False, ) coreconfigitem( - section, configprefix + b'word-diff', default=False, + section, + configprefix + b'word-diff', + default=False, ) coreconfigitem( - b'alias', b'.*', default=dynamicdefault, generic=True, -) -coreconfigitem( - b'auth', b'cookiefile', default=None, + b'alias', + b'.*', + default=dynamicdefault, + generic=True, +) +coreconfigitem( + b'auth', + b'cookiefile', + default=None, ) _registerdiffopts(section=b'annotate') # bookmarks.pushing: internal hack for discovery coreconfigitem( - b'bookmarks', b'pushing', default=list, + b'bookmarks', + b'pushing', + default=list, ) # bundle.mainreporoot: internal hack for bundlerepo coreconfigitem( - b'bundle', b'mainreporoot', default=b'', -) -coreconfigitem( - b'censor', b'policy', default=b'abort', experimental=True, -) -coreconfigitem( - b'chgserver', b'idletimeout', default=3600, -) -coreconfigitem( - b'chgserver', b'skiphash', default=False, -) -coreconfigitem( - b'cmdserver', b'log', default=None, -) -coreconfigitem( - b'cmdserver', b'max-log-files', default=7, -) -coreconfigitem( - b'cmdserver', b'max-log-size', default=b'1 MB', -) -coreconfigitem( - b'cmdserver', b'max-repo-cache', default=0, experimental=True, -) -coreconfigitem( - b'cmdserver', b'message-encodings', default=list, + b'bundle', + b'mainreporoot', + default=b'', +) +coreconfigitem( + b'censor', + b'policy', + default=b'abort', + experimental=True, +) +coreconfigitem( + b'chgserver', + b'idletimeout', + default=3600, +) +coreconfigitem( + b'chgserver', + b'skiphash', + default=False, +) +coreconfigitem( + b'cmdserver', + b'log', + default=None, +) +coreconfigitem( + b'cmdserver', + b'max-log-files', + default=7, +) +coreconfigitem( + b'cmdserver', + b'max-log-size', + default=b'1 MB', +) +coreconfigitem( + b'cmdserver', + b'max-repo-cache', + default=0, + experimental=True, +) +coreconfigitem( + b'cmdserver', + b'message-encodings', + default=list, ) coreconfigitem( b'cmdserver', @@ -212,340 +261,610 @@ default=lambda: [b'chgserver', b'cmdserver', b'repocache'], ) coreconfigitem( - b'cmdserver', b'shutdown-on-interrupt', default=True, -) -coreconfigitem( - b'color', b'.*', default=None, generic=True, -) -coreconfigitem( - b'color', b'mode', default=b'auto', -) -coreconfigitem( - b'color', b'pagermode', default=dynamicdefault, + b'cmdserver', + b'shutdown-on-interrupt', + default=True, +) +coreconfigitem( + b'color', + b'.*', + default=None, + generic=True, +) +coreconfigitem( + b'color', + b'mode', + default=b'auto', +) +coreconfigitem( + b'color', + b'pagermode', + default=dynamicdefault, +) +coreconfigitem( + b'command-templates', + b'graphnode', + default=None, + alias=[(b'ui', b'graphnodetemplate')], +) +coreconfigitem( + b'command-templates', + b'log', + default=None, + alias=[(b'ui', b'logtemplate')], +) +coreconfigitem( + b'command-templates', + b'mergemarker', + default=( + b'{node|short} ' + b'{ifeq(tags, "tip", "", ' + b'ifeq(tags, "", "", "{tags} "))}' + b'{if(bookmarks, "{bookmarks} ")}' + b'{ifeq(branch, "default", "", "{branch} ")}' + b'- {author|user}: {desc|firstline}' + ), + alias=[(b'ui', b'mergemarkertemplate')], +) +coreconfigitem( + b'command-templates', + b'pre-merge-tool-output', + default=None, + alias=[(b'ui', b'pre-merge-tool-output-template')], +) +coreconfigitem( + b'command-templates', + b'oneline-summary', + default=None, +) +coreconfigitem( + b'command-templates', + b'oneline-summary.*', + default=dynamicdefault, + generic=True, ) _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.') coreconfigitem( - b'commands', b'commit.post-status', default=False, -) -coreconfigitem( - b'commands', b'grep.all-files', default=False, experimental=True, -) -coreconfigitem( - b'commands', b'merge.require-rev', default=False, -) -coreconfigitem( - b'commands', b'push.require-revs', default=False, -) -coreconfigitem( - b'commands', b'resolve.confirm', default=False, -) -coreconfigitem( - b'commands', b'resolve.explicit-re-merge', default=False, -) -coreconfigitem( - b'commands', b'resolve.mark-check', default=b'none', + b'commands', + b'commit.post-status', + default=False, +) +coreconfigitem( + b'commands', + b'grep.all-files', + default=False, + experimental=True, +) +coreconfigitem( + b'commands', + b'merge.require-rev', + default=False, +) +coreconfigitem( + b'commands', + b'push.require-revs', + default=False, +) +coreconfigitem( + b'commands', + b'resolve.confirm', + default=False, +) +coreconfigitem( + b'commands', + b'resolve.explicit-re-merge', + default=False, +) +coreconfigitem( + b'commands', + b'resolve.mark-check', + default=b'none', ) _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.') coreconfigitem( - b'commands', b'show.aliasprefix', default=list, -) -coreconfigitem( - b'commands', b'status.relative', default=False, -) -coreconfigitem( - b'commands', b'status.skipstates', default=[], experimental=True, -) -coreconfigitem( - b'commands', b'status.terse', default=b'', -) -coreconfigitem( - b'commands', b'status.verbose', default=False, -) -coreconfigitem( - b'commands', b'update.check', default=None, -) -coreconfigitem( - b'commands', b'update.requiredest', default=False, -) -coreconfigitem( - b'committemplate', b'.*', default=None, generic=True, -) -coreconfigitem( - b'convert', b'bzr.saverev', default=True, -) -coreconfigitem( - b'convert', b'cvsps.cache', default=True, -) -coreconfigitem( - b'convert', b'cvsps.fuzz', default=60, -) -coreconfigitem( - b'convert', b'cvsps.logencoding', default=None, -) -coreconfigitem( - b'convert', b'cvsps.mergefrom', default=None, -) -coreconfigitem( - b'convert', b'cvsps.mergeto', default=None, -) -coreconfigitem( - b'convert', b'git.committeractions', default=lambda: [b'messagedifferent'], -) -coreconfigitem( - b'convert', b'git.extrakeys', default=list, -) -coreconfigitem( - b'convert', b'git.findcopiesharder', default=False, -) -coreconfigitem( - b'convert', b'git.remoteprefix', default=b'remote', -) -coreconfigitem( - b'convert', b'git.renamelimit', default=400, -) -coreconfigitem( - b'convert', b'git.saverev', default=True, -) -coreconfigitem( - b'convert', b'git.similarity', default=50, -) -coreconfigitem( - b'convert', b'git.skipsubmodules', default=False, -) -coreconfigitem( - b'convert', b'hg.clonebranches', default=False, -) -coreconfigitem( - b'convert', b'hg.ignoreerrors', default=False, -) -coreconfigitem( - b'convert', b'hg.preserve-hash', default=False, -) -coreconfigitem( - b'convert', b'hg.revs', default=None, -) -coreconfigitem( - b'convert', b'hg.saverev', default=False, -) -coreconfigitem( - b'convert', b'hg.sourcename', default=None, -) -coreconfigitem( - b'convert', b'hg.startrev', default=None, -) -coreconfigitem( - b'convert', b'hg.tagsbranch', default=b'default', -) -coreconfigitem( - b'convert', b'hg.usebranchnames', default=True, -) -coreconfigitem( - b'convert', b'ignoreancestorcheck', default=False, experimental=True, -) -coreconfigitem( - b'convert', b'localtimezone', default=False, -) -coreconfigitem( - b'convert', b'p4.encoding', default=dynamicdefault, -) -coreconfigitem( - b'convert', b'p4.startrev', default=0, -) -coreconfigitem( - b'convert', b'skiptags', default=False, -) -coreconfigitem( - b'convert', b'svn.debugsvnlog', default=True, -) -coreconfigitem( - b'convert', b'svn.trunk', default=None, -) -coreconfigitem( - b'convert', b'svn.tags', default=None, -) -coreconfigitem( - b'convert', b'svn.branches', default=None, -) -coreconfigitem( - b'convert', b'svn.startrev', default=0, -) -coreconfigitem( - b'debug', b'dirstate.delaywrite', default=0, -) -coreconfigitem( - b'defaults', b'.*', default=None, generic=True, -) -coreconfigitem( - b'devel', b'all-warnings', default=False, -) -coreconfigitem( - b'devel', b'bundle2.debug', default=False, -) -coreconfigitem( - b'devel', b'bundle.delta', default=b'', -) -coreconfigitem( - b'devel', b'cache-vfs', default=None, -) -coreconfigitem( - b'devel', b'check-locks', default=False, -) -coreconfigitem( - b'devel', b'check-relroot', default=False, -) -coreconfigitem( - b'devel', b'default-date', default=None, -) -coreconfigitem( - b'devel', b'deprec-warn', default=False, -) -coreconfigitem( - b'devel', b'disableloaddefaultcerts', default=False, -) -coreconfigitem( - b'devel', b'warn-empty-changegroup', default=False, -) -coreconfigitem( - b'devel', b'legacy.exchange', default=list, -) -coreconfigitem( - b'devel', b'persistent-nodemap', default=False, -) -coreconfigitem( - b'devel', b'servercafile', default=b'', -) -coreconfigitem( - b'devel', b'serverexactprotocol', default=b'', -) -coreconfigitem( - b'devel', b'serverrequirecert', default=False, -) -coreconfigitem( - b'devel', b'strip-obsmarkers', default=True, -) -coreconfigitem( - b'devel', b'warn-config', default=None, -) -coreconfigitem( - b'devel', b'warn-config-default', default=None, -) -coreconfigitem( - b'devel', b'user.obsmarker', default=None, -) -coreconfigitem( - b'devel', b'warn-config-unknown', default=None, -) -coreconfigitem( - b'devel', b'debug.copies', default=False, -) -coreconfigitem( - b'devel', b'debug.extensions', default=False, -) -coreconfigitem( - b'devel', b'debug.repo-filters', default=False, -) -coreconfigitem( - b'devel', b'debug.peer-request', default=False, -) -coreconfigitem( - b'devel', b'discovery.randomize', default=True, + b'commands', + b'show.aliasprefix', + default=list, +) +coreconfigitem( + b'commands', + b'status.relative', + default=False, +) +coreconfigitem( + b'commands', + b'status.skipstates', + default=[], + experimental=True, +) +coreconfigitem( + b'commands', + b'status.terse', + default=b'', +) +coreconfigitem( + b'commands', + b'status.verbose', + default=False, +) +coreconfigitem( + b'commands', + b'update.check', + default=None, +) +coreconfigitem( + b'commands', + b'update.requiredest', + default=False, +) +coreconfigitem( + b'committemplate', + b'.*', + default=None, + generic=True, +) +coreconfigitem( + b'convert', + b'bzr.saverev', + default=True, +) +coreconfigitem( + b'convert', + b'cvsps.cache', + default=True, +) +coreconfigitem( + b'convert', + b'cvsps.fuzz', + default=60, +) +coreconfigitem( + b'convert', + b'cvsps.logencoding', + default=None, +) +coreconfigitem( + b'convert', + b'cvsps.mergefrom', + default=None, +) +coreconfigitem( + b'convert', + b'cvsps.mergeto', + default=None, +) +coreconfigitem( + b'convert', + b'git.committeractions', + default=lambda: [b'messagedifferent'], +) +coreconfigitem( + b'convert', + b'git.extrakeys', + default=list, +) +coreconfigitem( + b'convert', + b'git.findcopiesharder', + default=False, +) +coreconfigitem( + b'convert', + b'git.remoteprefix', + default=b'remote', +) +coreconfigitem( + b'convert', + b'git.renamelimit', + default=400, +) +coreconfigitem( + b'convert', + b'git.saverev', + default=True, +) +coreconfigitem( + b'convert', + b'git.similarity', + default=50, +) +coreconfigitem( + b'convert', + b'git.skipsubmodules', + default=False, +) +coreconfigitem( + b'convert', + b'hg.clonebranches', + default=False, +) +coreconfigitem( + b'convert', + b'hg.ignoreerrors', + default=False, +) +coreconfigitem( + b'convert', + b'hg.preserve-hash', + default=False, +) +coreconfigitem( + b'convert', + b'hg.revs', + default=None, +) +coreconfigitem( + b'convert', + b'hg.saverev', + default=False, +) +coreconfigitem( + b'convert', + b'hg.sourcename', + default=None, +) +coreconfigitem( + b'convert', + b'hg.startrev', + default=None, +) +coreconfigitem( + b'convert', + b'hg.tagsbranch', + default=b'default', +) +coreconfigitem( + b'convert', + b'hg.usebranchnames', + default=True, +) +coreconfigitem( + b'convert', + b'ignoreancestorcheck', + default=False, + experimental=True, +) +coreconfigitem( + b'convert', + b'localtimezone', + default=False, +) +coreconfigitem( + b'convert', + b'p4.encoding', + default=dynamicdefault, +) +coreconfigitem( + b'convert', + b'p4.startrev', + default=0, +) +coreconfigitem( + b'convert', + b'skiptags', + default=False, +) +coreconfigitem( + b'convert', + b'svn.debugsvnlog', + default=True, +) +coreconfigitem( + b'convert', + b'svn.trunk', + default=None, +) +coreconfigitem( + b'convert', + b'svn.tags', + default=None, +) +coreconfigitem( + b'convert', + b'svn.branches', + default=None, +) +coreconfigitem( + b'convert', + b'svn.startrev', + default=0, +) +coreconfigitem( + b'debug', + b'dirstate.delaywrite', + default=0, +) +coreconfigitem( + b'defaults', + b'.*', + default=None, + generic=True, +) +coreconfigitem( + b'devel', + b'all-warnings', + default=False, +) +coreconfigitem( + b'devel', + b'bundle2.debug', + default=False, +) +coreconfigitem( + b'devel', + b'bundle.delta', + default=b'', +) +coreconfigitem( + b'devel', + b'cache-vfs', + default=None, +) +coreconfigitem( + b'devel', + b'check-locks', + default=False, +) +coreconfigitem( + b'devel', + b'check-relroot', + default=False, +) +coreconfigitem( + b'devel', + b'default-date', + default=None, +) +coreconfigitem( + b'devel', + b'deprec-warn', + default=False, +) +coreconfigitem( + b'devel', + b'disableloaddefaultcerts', + default=False, +) +coreconfigitem( + b'devel', + b'warn-empty-changegroup', + default=False, +) +coreconfigitem( + b'devel', + b'legacy.exchange', + default=list, +) +coreconfigitem( + b'devel', + b'persistent-nodemap', + default=False, +) +coreconfigitem( + b'devel', + b'servercafile', + default=b'', +) +coreconfigitem( + b'devel', + b'serverexactprotocol', + default=b'', +) +coreconfigitem( + b'devel', + b'serverrequirecert', + default=False, +) +coreconfigitem( + b'devel', + b'strip-obsmarkers', + default=True, +) +coreconfigitem( + b'devel', + b'warn-config', + default=None, +) +coreconfigitem( + b'devel', + b'warn-config-default', + default=None, +) +coreconfigitem( + b'devel', + b'user.obsmarker', + default=None, +) +coreconfigitem( + b'devel', + b'warn-config-unknown', + default=None, +) +coreconfigitem( + b'devel', + b'debug.copies', + default=False, +) +coreconfigitem( + b'devel', + b'debug.extensions', + default=False, +) +coreconfigitem( + b'devel', + b'debug.repo-filters', + default=False, +) +coreconfigitem( + b'devel', + b'debug.peer-request', + default=False, +) +coreconfigitem( + b'devel', + b'discovery.randomize', + default=True, ) _registerdiffopts(section=b'diff') coreconfigitem( - b'email', b'bcc', default=None, -) -coreconfigitem( - b'email', b'cc', default=None, -) -coreconfigitem( - b'email', b'charsets', default=list, -) -coreconfigitem( - b'email', b'from', default=None, -) -coreconfigitem( - b'email', b'method', default=b'smtp', -) -coreconfigitem( - b'email', b'reply-to', default=None, -) -coreconfigitem( - b'email', b'to', default=None, -) -coreconfigitem( - b'experimental', b'archivemetatemplate', default=dynamicdefault, -) -coreconfigitem( - b'experimental', b'auto-publish', default=b'publish', -) -coreconfigitem( - b'experimental', b'bundle-phases', default=False, -) -coreconfigitem( - b'experimental', b'bundle2-advertise', default=True, -) -coreconfigitem( - b'experimental', b'bundle2-output-capture', default=False, -) -coreconfigitem( - b'experimental', b'bundle2.pushback', default=False, -) -coreconfigitem( - b'experimental', b'bundle2lazylocking', default=False, -) -coreconfigitem( - b'experimental', b'bundlecomplevel', default=None, -) -coreconfigitem( - b'experimental', b'bundlecomplevel.bzip2', default=None, -) -coreconfigitem( - b'experimental', b'bundlecomplevel.gzip', default=None, -) -coreconfigitem( - b'experimental', b'bundlecomplevel.none', default=None, -) -coreconfigitem( - b'experimental', b'bundlecomplevel.zstd', default=None, -) -coreconfigitem( - b'experimental', b'changegroup3', default=False, -) -coreconfigitem( - b'experimental', b'cleanup-as-archived', default=False, -) -coreconfigitem( - b'experimental', b'clientcompressionengines', default=list, -) -coreconfigitem( - b'experimental', b'copytrace', default=b'on', -) -coreconfigitem( - b'experimental', b'copytrace.movecandidateslimit', default=100, -) -coreconfigitem( - b'experimental', b'copytrace.sourcecommitlimit', default=100, -) -coreconfigitem( - b'experimental', b'copies.read-from', default=b"filelog-only", -) -coreconfigitem( - b'experimental', b'copies.write-to', default=b'filelog-only', -) -coreconfigitem( - b'experimental', b'crecordtest', default=None, -) -coreconfigitem( - b'experimental', b'directaccess', default=False, -) -coreconfigitem( - b'experimental', b'directaccess.revnums', default=False, -) -coreconfigitem( - b'experimental', b'editortmpinhg', default=False, -) -coreconfigitem( - b'experimental', b'evolution', default=list, + b'email', + b'bcc', + default=None, +) +coreconfigitem( + b'email', + b'cc', + default=None, +) +coreconfigitem( + b'email', + b'charsets', + default=list, +) +coreconfigitem( + b'email', + b'from', + default=None, +) +coreconfigitem( + b'email', + b'method', + default=b'smtp', +) +coreconfigitem( + b'email', + b'reply-to', + default=None, +) +coreconfigitem( + b'email', + b'to', + default=None, +) +coreconfigitem( + b'experimental', + b'archivemetatemplate', + default=dynamicdefault, +) +coreconfigitem( + b'experimental', + b'auto-publish', + default=b'publish', +) +coreconfigitem( + b'experimental', + b'bundle-phases', + default=False, +) +coreconfigitem( + b'experimental', + b'bundle2-advertise', + default=True, +) +coreconfigitem( + b'experimental', + b'bundle2-output-capture', + default=False, +) +coreconfigitem( + b'experimental', + b'bundle2.pushback', + default=False, +) +coreconfigitem( + b'experimental', + b'bundle2lazylocking', + default=False, +) +coreconfigitem( + b'experimental', + b'bundlecomplevel', + default=None, +) +coreconfigitem( + b'experimental', + b'bundlecomplevel.bzip2', + default=None, +) +coreconfigitem( + b'experimental', + b'bundlecomplevel.gzip', + default=None, +) +coreconfigitem( + b'experimental', + b'bundlecomplevel.none', + default=None, +) +coreconfigitem( + b'experimental', + b'bundlecomplevel.zstd', + default=None, +) +coreconfigitem( + b'experimental', + b'changegroup3', + default=False, +) +coreconfigitem( + b'experimental', + b'cleanup-as-archived', + default=False, +) +coreconfigitem( + b'experimental', + b'clientcompressionengines', + default=list, +) +coreconfigitem( + b'experimental', + b'copytrace', + default=b'on', +) +coreconfigitem( + b'experimental', + b'copytrace.movecandidateslimit', + default=100, +) +coreconfigitem( + b'experimental', + b'copytrace.sourcecommitlimit', + default=100, +) +coreconfigitem( + b'experimental', + b'copies.read-from', + default=b"filelog-only", +) +coreconfigitem( + b'experimental', + b'copies.write-to', + default=b'filelog-only', +) +coreconfigitem( + b'experimental', + b'crecordtest', + default=None, +) +coreconfigitem( + b'experimental', + b'directaccess', + default=False, +) +coreconfigitem( + b'experimental', + b'directaccess.revnums', + default=False, +) +coreconfigitem( + b'experimental', + b'editortmpinhg', + default=False, +) +coreconfigitem( + b'experimental', + b'evolution', + default=list, ) coreconfigitem( b'experimental', @@ -554,10 +873,14 @@ alias=[(b'experimental', b'allowdivergence')], ) coreconfigitem( - b'experimental', b'evolution.allowunstable', default=None, -) -coreconfigitem( - b'experimental', b'evolution.createmarkers', default=None, + b'experimental', + b'evolution.allowunstable', + default=None, +) +coreconfigitem( + b'experimental', + b'evolution.createmarkers', + default=None, ) coreconfigitem( b'experimental', @@ -566,109 +889,173 @@ alias=[(b'experimental', b'effect-flags')], ) coreconfigitem( - b'experimental', b'evolution.exchange', default=None, -) -coreconfigitem( - b'experimental', b'evolution.bundle-obsmarker', default=False, -) -coreconfigitem( - b'experimental', b'log.topo', default=False, -) -coreconfigitem( - b'experimental', b'evolution.report-instabilities', default=True, -) -coreconfigitem( - b'experimental', b'evolution.track-operation', default=True, + b'experimental', + b'evolution.exchange', + default=None, +) +coreconfigitem( + b'experimental', + b'evolution.bundle-obsmarker', + default=False, +) +coreconfigitem( + b'experimental', + b'log.topo', + default=False, +) +coreconfigitem( + b'experimental', + b'evolution.report-instabilities', + default=True, +) +coreconfigitem( + b'experimental', + b'evolution.track-operation', + default=True, ) # repo-level config to exclude a revset visibility # # The target use case is to use `share` to expose different subset of the same # repository, especially server side. See also `server.view`. coreconfigitem( - b'experimental', b'extra-filter-revs', default=None, -) -coreconfigitem( - b'experimental', b'maxdeltachainspan', default=-1, + b'experimental', + b'extra-filter-revs', + default=None, +) +coreconfigitem( + b'experimental', + b'maxdeltachainspan', + default=-1, ) # tracks files which were undeleted (merge might delete them but we explicitly # kept/undeleted them) and creates new filenodes for them coreconfigitem( - b'experimental', b'merge-track-salvaged', default=False, -) -coreconfigitem( - b'experimental', b'mergetempdirprefix', default=None, -) -coreconfigitem( - b'experimental', b'mmapindexthreshold', default=None, -) -coreconfigitem( - b'experimental', b'narrow', default=False, -) -coreconfigitem( - b'experimental', b'nonnormalparanoidcheck', default=False, -) -coreconfigitem( - b'experimental', b'exportableenviron', default=list, -) -coreconfigitem( - b'experimental', b'extendedheader.index', default=None, -) -coreconfigitem( - b'experimental', b'extendedheader.similarity', default=False, -) -coreconfigitem( - b'experimental', b'graphshorten', default=False, -) -coreconfigitem( - b'experimental', b'graphstyle.parent', default=dynamicdefault, -) -coreconfigitem( - b'experimental', b'graphstyle.missing', default=dynamicdefault, -) -coreconfigitem( - b'experimental', b'graphstyle.grandparent', default=dynamicdefault, -) -coreconfigitem( - b'experimental', b'hook-track-tags', default=False, -) -coreconfigitem( - b'experimental', b'httppeer.advertise-v2', default=False, -) -coreconfigitem( - b'experimental', b'httppeer.v2-encoder-order', default=None, -) -coreconfigitem( - b'experimental', b'httppostargs', default=False, + b'experimental', + b'merge-track-salvaged', + default=False, +) +coreconfigitem( + b'experimental', + b'mergetempdirprefix', + default=None, +) +coreconfigitem( + b'experimental', + b'mmapindexthreshold', + default=None, +) +coreconfigitem( + b'experimental', + b'narrow', + default=False, +) +coreconfigitem( + b'experimental', + b'nonnormalparanoidcheck', + default=False, +) +coreconfigitem( + b'experimental', + b'exportableenviron', + default=list, +) +coreconfigitem( + b'experimental', + b'extendedheader.index', + default=None, +) +coreconfigitem( + b'experimental', + b'extendedheader.similarity', + default=False, +) +coreconfigitem( + b'experimental', + b'graphshorten', + default=False, +) +coreconfigitem( + b'experimental', + b'graphstyle.parent', + default=dynamicdefault, +) +coreconfigitem( + b'experimental', + b'graphstyle.missing', + default=dynamicdefault, +) +coreconfigitem( + b'experimental', + b'graphstyle.grandparent', + default=dynamicdefault, +) +coreconfigitem( + b'experimental', + b'hook-track-tags', + default=False, +) +coreconfigitem( + b'experimental', + b'httppeer.advertise-v2', + default=False, +) +coreconfigitem( + b'experimental', + b'httppeer.v2-encoder-order', + default=None, +) +coreconfigitem( + b'experimental', + b'httppostargs', + default=False, ) coreconfigitem(b'experimental', b'nointerrupt', default=False) coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True) coreconfigitem( - b'experimental', b'obsmarkers-exchange-debug', default=False, -) -coreconfigitem( - b'experimental', b'remotenames', default=False, -) -coreconfigitem( - b'experimental', b'removeemptydirs', default=True, -) -coreconfigitem( - b'experimental', b'revert.interactive.select-to-keep', default=False, -) -coreconfigitem( - b'experimental', b'revisions.prefixhexnode', default=False, -) -coreconfigitem( - b'experimental', b'revlogv2', default=None, -) -coreconfigitem( - b'experimental', b'revisions.disambiguatewithin', default=None, -) -coreconfigitem( - b'experimental', b'rust.index', default=False, -) -coreconfigitem( - b'experimental', b'server.filesdata.recommended-batch-size', default=50000, + b'experimental', + b'obsmarkers-exchange-debug', + default=False, +) +coreconfigitem( + b'experimental', + b'remotenames', + default=False, +) +coreconfigitem( + b'experimental', + b'removeemptydirs', + default=True, +) +coreconfigitem( + b'experimental', + b'revert.interactive.select-to-keep', + default=False, +) +coreconfigitem( + b'experimental', + b'revisions.prefixhexnode', + default=False, +) +coreconfigitem( + b'experimental', + b'revlogv2', + default=None, +) +coreconfigitem( + b'experimental', + b'revisions.disambiguatewithin', + default=None, +) +coreconfigitem( + b'experimental', + b'rust.index', + default=False, +) +coreconfigitem( + b'experimental', + b'server.filesdata.recommended-batch-size', + default=50000, ) coreconfigitem( b'experimental', @@ -676,10 +1063,14 @@ default=100000, ) coreconfigitem( - b'experimental', b'server.stream-narrow-clones', default=False, -) -coreconfigitem( - b'experimental', b'single-head-per-branch', default=False, + b'experimental', + b'server.stream-narrow-clones', + default=False, +) +coreconfigitem( + b'experimental', + b'single-head-per-branch', + default=False, ) coreconfigitem( b'experimental', @@ -687,73 +1078,125 @@ default=False, ) coreconfigitem( - b'experimental', b'sshserver.support-v2', default=False, -) -coreconfigitem( - b'experimental', b'sparse-read', default=False, -) -coreconfigitem( - b'experimental', b'sparse-read.density-threshold', default=0.50, -) -coreconfigitem( - b'experimental', b'sparse-read.min-gap-size', default=b'65K', -) -coreconfigitem( - b'experimental', b'treemanifest', default=False, -) -coreconfigitem( - b'experimental', b'update.atomic-file', default=False, -) -coreconfigitem( - b'experimental', b'sshpeer.advertise-v2', default=False, -) -coreconfigitem( - b'experimental', b'web.apiserver', default=False, -) -coreconfigitem( - b'experimental', b'web.api.http-v2', default=False, -) -coreconfigitem( - b'experimental', b'web.api.debugreflect', default=False, -) -coreconfigitem( - b'experimental', b'worker.wdir-get-thread-safe', default=False, -) -coreconfigitem( - b'experimental', b'worker.repository-upgrade', default=False, -) -coreconfigitem( - b'experimental', b'xdiff', default=False, -) -coreconfigitem( - b'extensions', b'.*', default=None, generic=True, -) -coreconfigitem( - b'extdata', b'.*', default=None, generic=True, -) -coreconfigitem( - b'format', b'bookmarks-in-store', default=False, -) -coreconfigitem( - b'format', b'chunkcachesize', default=None, experimental=True, -) -coreconfigitem( - b'format', b'dotencode', default=True, -) -coreconfigitem( - b'format', b'generaldelta', default=False, experimental=True, -) -coreconfigitem( - b'format', b'manifestcachesize', default=None, experimental=True, -) -coreconfigitem( - b'format', b'maxchainlen', default=dynamicdefault, experimental=True, -) -coreconfigitem( - b'format', b'obsstore-version', default=None, -) -coreconfigitem( - b'format', b'sparse-revlog', default=True, + b'experimental', + b'sshserver.support-v2', + default=False, +) +coreconfigitem( + b'experimental', + b'sparse-read', + default=False, +) +coreconfigitem( + b'experimental', + b'sparse-read.density-threshold', + default=0.50, +) +coreconfigitem( + b'experimental', + b'sparse-read.min-gap-size', + default=b'65K', +) +coreconfigitem( + b'experimental', + b'treemanifest', + default=False, +) +coreconfigitem( + b'experimental', + b'update.atomic-file', + default=False, +) +coreconfigitem( + b'experimental', + b'sshpeer.advertise-v2', + default=False, +) +coreconfigitem( + b'experimental', + b'web.apiserver', + default=False, +) +coreconfigitem( + b'experimental', + b'web.api.http-v2', + default=False, +) +coreconfigitem( + b'experimental', + b'web.api.debugreflect', + default=False, +) +coreconfigitem( + b'experimental', + b'worker.wdir-get-thread-safe', + default=False, +) +coreconfigitem( + b'experimental', + b'worker.repository-upgrade', + default=False, +) +coreconfigitem( + b'experimental', + b'xdiff', + default=False, +) +coreconfigitem( + b'extensions', + b'.*', + default=None, + generic=True, +) +coreconfigitem( + b'extdata', + b'.*', + default=None, + generic=True, +) +coreconfigitem( + b'format', + b'bookmarks-in-store', + default=False, +) +coreconfigitem( + b'format', + b'chunkcachesize', + default=None, + experimental=True, +) +coreconfigitem( + b'format', + b'dotencode', + default=True, +) +coreconfigitem( + b'format', + b'generaldelta', + default=False, + experimental=True, +) +coreconfigitem( + b'format', + b'manifestcachesize', + default=None, + experimental=True, +) +coreconfigitem( + b'format', + b'maxchainlen', + default=dynamicdefault, + experimental=True, +) +coreconfigitem( + b'format', + b'obsstore-version', + default=None, +) +coreconfigitem( + b'format', + b'sparse-revlog', + default=True, ) coreconfigitem( b'format', @@ -762,13 +1205,19 @@ alias=[(b'experimental', b'format.compression')], ) coreconfigitem( - b'format', b'usefncache', default=True, -) -coreconfigitem( - b'format', b'usegeneraldelta', default=True, -) -coreconfigitem( - b'format', b'usestore', default=True, + b'format', + b'usefncache', + default=True, +) +coreconfigitem( + b'format', + b'usegeneraldelta', + default=True, +) +coreconfigitem( + b'format', + b'usestore', + default=True, ) # Right now, the only efficient implement of the nodemap logic is in Rust, so # the persistent nodemap feature needs to stay experimental as long as the Rust @@ -783,43 +1232,77 @@ experimental=True, ) coreconfigitem( - b'format', b'exp-use-side-data', default=False, experimental=True, -) -coreconfigitem( - b'format', b'exp-share-safe', default=False, experimental=True, -) -coreconfigitem( - b'format', b'internal-phase', default=False, experimental=True, -) -coreconfigitem( - b'fsmonitor', b'warn_when_unused', default=True, -) -coreconfigitem( - b'fsmonitor', b'warn_update_file_count', default=50000, -) -coreconfigitem( - b'fsmonitor', b'warn_update_file_count_rust', default=400000, -) -coreconfigitem( - b'help', br'hidden-command\..*', default=False, generic=True, -) -coreconfigitem( - b'help', br'hidden-topic\..*', default=False, generic=True, -) -coreconfigitem( - b'hooks', b'.*', default=dynamicdefault, generic=True, -) -coreconfigitem( - b'hgweb-paths', b'.*', default=list, generic=True, -) -coreconfigitem( - b'hostfingerprints', b'.*', default=list, generic=True, -) -coreconfigitem( - b'hostsecurity', b'ciphers', default=None, -) -coreconfigitem( - b'hostsecurity', b'minimumprotocol', default=dynamicdefault, + b'format', + b'exp-use-side-data', + default=False, + experimental=True, +) +coreconfigitem( + b'format', + b'exp-share-safe', + default=False, + experimental=True, +) +coreconfigitem( + b'format', + b'internal-phase', + default=False, + experimental=True, +) +coreconfigitem( + b'fsmonitor', + b'warn_when_unused', + default=True, +) +coreconfigitem( + b'fsmonitor', + b'warn_update_file_count', + default=50000, +) +coreconfigitem( + b'fsmonitor', + b'warn_update_file_count_rust', + default=400000, +) +coreconfigitem( + b'help', + br'hidden-command\..*', + default=False, + generic=True, +) +coreconfigitem( + b'help', + br'hidden-topic\..*', + default=False, + generic=True, +) +coreconfigitem( + b'hooks', + b'.*', + default=dynamicdefault, + generic=True, +) +coreconfigitem( + b'hgweb-paths', + b'.*', + default=list, + generic=True, +) +coreconfigitem( + b'hostfingerprints', + b'.*', + default=list, + generic=True, +) +coreconfigitem( + b'hostsecurity', + b'ciphers', + default=None, +) +coreconfigitem( + b'hostsecurity', + b'minimumprotocol', + default=dynamicdefault, ) coreconfigitem( b'hostsecurity', @@ -828,73 +1311,122 @@ generic=True, ) coreconfigitem( - b'hostsecurity', b'.*:ciphers$', default=dynamicdefault, generic=True, -) -coreconfigitem( - b'hostsecurity', b'.*:fingerprints$', default=list, generic=True, -) -coreconfigitem( - b'hostsecurity', b'.*:verifycertsfile$', default=None, generic=True, + b'hostsecurity', + b'.*:ciphers$', + default=dynamicdefault, + generic=True, +) +coreconfigitem( + b'hostsecurity', + b'.*:fingerprints$', + default=list, + generic=True, +) +coreconfigitem( + b'hostsecurity', + b'.*:verifycertsfile$', + default=None, + generic=True, ) coreconfigitem( - b'http_proxy', b'always', default=False, -) -coreconfigitem( - b'http_proxy', b'host', default=None, -) -coreconfigitem( - b'http_proxy', b'no', default=list, -) -coreconfigitem( - b'http_proxy', b'passwd', default=None, -) -coreconfigitem( - b'http_proxy', b'user', default=None, + b'http_proxy', + b'always', + default=False, +) +coreconfigitem( + b'http_proxy', + b'host', + default=None, +) +coreconfigitem( + b'http_proxy', + b'no', + default=list, +) +coreconfigitem( + b'http_proxy', + b'passwd', + default=None, +) +coreconfigitem( + b'http_proxy', + b'user', + default=None, ) coreconfigitem( - b'http', b'timeout', default=None, + b'http', + b'timeout', + default=None, ) coreconfigitem( - b'logtoprocess', b'commandexception', default=None, -) -coreconfigitem( - b'logtoprocess', b'commandfinish', default=None, -) -coreconfigitem( - b'logtoprocess', b'command', default=None, -) -coreconfigitem( - b'logtoprocess', b'develwarn', default=None, -) -coreconfigitem( - b'logtoprocess', b'uiblocked', default=None, -) -coreconfigitem( - b'merge', b'checkunknown', default=b'abort', -) -coreconfigitem( - b'merge', b'checkignored', default=b'abort', -) -coreconfigitem( - b'experimental', b'merge.checkpathconflicts', default=False, -) -coreconfigitem( - b'merge', b'followcopies', default=True, -) -coreconfigitem( - b'merge', b'on-failure', default=b'continue', -) -coreconfigitem( - b'merge', b'preferancestor', default=lambda: [b'*'], experimental=True, -) -coreconfigitem( - b'merge', b'strict-capability-check', default=False, -) -coreconfigitem( - b'merge-tools', b'.*', default=None, generic=True, + b'logtoprocess', + b'commandexception', + default=None, +) +coreconfigitem( + b'logtoprocess', + b'commandfinish', + default=None, +) +coreconfigitem( + b'logtoprocess', + b'command', + default=None, +) +coreconfigitem( + b'logtoprocess', + b'develwarn', + default=None, +) +coreconfigitem( + b'logtoprocess', + b'uiblocked', + default=None, +) +coreconfigitem( + b'merge', + b'checkunknown', + default=b'abort', +) +coreconfigitem( + b'merge', + b'checkignored', + default=b'abort', +) +coreconfigitem( + b'experimental', + b'merge.checkpathconflicts', + default=False, +) +coreconfigitem( + b'merge', + b'followcopies', + default=True, +) +coreconfigitem( + b'merge', + b'on-failure', + default=b'continue', +) +coreconfigitem( + b'merge', + b'preferancestor', + default=lambda: [b'*'], + experimental=True, +) +coreconfigitem( + b'merge', + b'strict-capability-check', + default=False, +) +coreconfigitem( + b'merge-tools', + b'.*', + default=None, + generic=True, ) coreconfigitem( b'merge-tools', @@ -904,10 +1436,18 @@ priority=-1, ) coreconfigitem( - b'merge-tools', br'.*\.binary$', default=False, generic=True, priority=-1, -) -coreconfigitem( - b'merge-tools', br'.*\.check$', default=list, generic=True, priority=-1, + b'merge-tools', + br'.*\.binary$', + default=False, + generic=True, + priority=-1, +) +coreconfigitem( + b'merge-tools', + br'.*\.check$', + default=list, + generic=True, + priority=-1, ) coreconfigitem( b'merge-tools', @@ -924,10 +1464,18 @@ priority=-1, ) coreconfigitem( - b'merge-tools', br'.*\.fixeol$', default=False, generic=True, priority=-1, -) -coreconfigitem( - b'merge-tools', br'.*\.gui$', default=False, generic=True, priority=-1, + b'merge-tools', + br'.*\.fixeol$', + default=False, + generic=True, + priority=-1, +) +coreconfigitem( + b'merge-tools', + br'.*\.gui$', + default=False, + generic=True, + priority=-1, ) coreconfigitem( b'merge-tools', @@ -939,12 +1487,16 @@ coreconfigitem( b'merge-tools', br'.*\.mergemarkertemplate$', - default=dynamicdefault, # take from ui.mergemarkertemplate + default=dynamicdefault, # take from command-templates.mergemarker generic=True, priority=-1, ) coreconfigitem( - b'merge-tools', br'.*\.priority$', default=0, generic=True, priority=-1, + b'merge-tools', + br'.*\.priority$', + default=0, + generic=True, + priority=-1, ) coreconfigitem( b'merge-tools', @@ -954,100 +1506,168 @@ priority=-1, ) coreconfigitem( - b'merge-tools', br'.*\.symlink$', default=False, generic=True, priority=-1, -) -coreconfigitem( - b'pager', b'attend-.*', default=dynamicdefault, generic=True, -) -coreconfigitem( - b'pager', b'ignore', default=list, -) -coreconfigitem( - b'pager', b'pager', default=dynamicdefault, -) -coreconfigitem( - b'patch', b'eol', default=b'strict', -) -coreconfigitem( - b'patch', b'fuzz', default=2, -) -coreconfigitem( - b'paths', b'default', default=None, -) -coreconfigitem( - b'paths', b'default-push', default=None, -) -coreconfigitem( - b'paths', b'.*', default=None, generic=True, -) -coreconfigitem( - b'phases', b'checksubrepos', default=b'follow', -) -coreconfigitem( - b'phases', b'new-commit', default=b'draft', -) -coreconfigitem( - b'phases', b'publish', default=True, -) -coreconfigitem( - b'profiling', b'enabled', default=False, -) -coreconfigitem( - b'profiling', b'format', default=b'text', -) -coreconfigitem( - b'profiling', b'freq', default=1000, -) -coreconfigitem( - b'profiling', b'limit', default=30, -) -coreconfigitem( - b'profiling', b'nested', default=0, -) -coreconfigitem( - b'profiling', b'output', default=None, -) -coreconfigitem( - b'profiling', b'showmax', default=0.999, -) -coreconfigitem( - b'profiling', b'showmin', default=dynamicdefault, -) -coreconfigitem( - b'profiling', b'showtime', default=True, -) -coreconfigitem( - b'profiling', b'sort', default=b'inlinetime', -) -coreconfigitem( - b'profiling', b'statformat', default=b'hotpath', -) -coreconfigitem( - b'profiling', b'time-track', default=dynamicdefault, -) -coreconfigitem( - b'profiling', b'type', default=b'stat', -) -coreconfigitem( - b'progress', b'assume-tty', default=False, -) -coreconfigitem( - b'progress', b'changedelay', default=1, -) -coreconfigitem( - b'progress', b'clear-complete', default=True, -) -coreconfigitem( - b'progress', b'debug', default=False, -) -coreconfigitem( - b'progress', b'delay', default=3, -) -coreconfigitem( - b'progress', b'disable', default=False, -) -coreconfigitem( - b'progress', b'estimateinterval', default=60.0, + b'merge-tools', + br'.*\.symlink$', + default=False, + generic=True, + priority=-1, +) +coreconfigitem( + b'pager', + b'attend-.*', + default=dynamicdefault, + generic=True, +) +coreconfigitem( + b'pager', + b'ignore', + default=list, +) +coreconfigitem( + b'pager', + b'pager', + default=dynamicdefault, +) +coreconfigitem( + b'patch', + b'eol', + default=b'strict', +) +coreconfigitem( + b'patch', + b'fuzz', + default=2, +) +coreconfigitem( + b'paths', + b'default', + default=None, +) +coreconfigitem( + b'paths', + b'default-push', + default=None, +) +coreconfigitem( + b'paths', + b'.*', + default=None, + generic=True, +) +coreconfigitem( + b'phases', + b'checksubrepos', + default=b'follow', +) +coreconfigitem( + b'phases', + b'new-commit', + default=b'draft', +) +coreconfigitem( + b'phases', + b'publish', + default=True, +) +coreconfigitem( + b'profiling', + b'enabled', + default=False, +) +coreconfigitem( + b'profiling', + b'format', + default=b'text', +) +coreconfigitem( + b'profiling', + b'freq', + default=1000, +) +coreconfigitem( + b'profiling', + b'limit', + default=30, +) +coreconfigitem( + b'profiling', + b'nested', + default=0, +) +coreconfigitem( + b'profiling', + b'output', + default=None, +) +coreconfigitem( + b'profiling', + b'showmax', + default=0.999, +) +coreconfigitem( + b'profiling', + b'showmin', + default=dynamicdefault, +) +coreconfigitem( + b'profiling', + b'showtime', + default=True, +) +coreconfigitem( + b'profiling', + b'sort', + default=b'inlinetime', +) +coreconfigitem( + b'profiling', + b'statformat', + default=b'hotpath', +) +coreconfigitem( + b'profiling', + b'time-track', + default=dynamicdefault, +) +coreconfigitem( + b'profiling', + b'type', + default=b'stat', +) +coreconfigitem( + b'progress', + b'assume-tty', + default=False, +) +coreconfigitem( + b'progress', + b'changedelay', + default=1, +) +coreconfigitem( + b'progress', + b'clear-complete', + default=True, +) +coreconfigitem( + b'progress', + b'debug', + default=False, +) +coreconfigitem( + b'progress', + b'delay', + default=3, +) +coreconfigitem( + b'progress', + b'disable', + default=False, +) +coreconfigitem( + b'progress', + b'estimateinterval', + default=60.0, ) coreconfigitem( b'progress', @@ -1055,16 +1675,24 @@ default=lambda: [b'topic', b'bar', b'number', b'estimate'], ) coreconfigitem( - b'progress', b'refresh', default=0.1, -) -coreconfigitem( - b'progress', b'width', default=dynamicdefault, -) -coreconfigitem( - b'pull', b'confirm', default=False, -) -coreconfigitem( - b'push', b'pushvars.server', default=False, + b'progress', + b'refresh', + default=0.1, +) +coreconfigitem( + b'progress', + b'width', + default=dynamicdefault, +) +coreconfigitem( + b'pull', + b'confirm', + default=False, +) +coreconfigitem( + b'push', + b'pushvars.server', + default=False, ) coreconfigitem( b'rewrite', @@ -1073,13 +1701,21 @@ alias=[(b'ui', b'history-editing-backup')], ) coreconfigitem( - b'rewrite', b'update-timestamp', default=False, -) -coreconfigitem( - b'rewrite', b'empty-successor', default=b'skip', experimental=True, -) -coreconfigitem( - b'storage', b'new-repo-backend', default=b'revlogv1', experimental=True, + b'rewrite', + b'update-timestamp', + default=False, +) +coreconfigitem( + b'rewrite', + b'empty-successor', + default=b'skip', + experimental=True, +) +coreconfigitem( + b'storage', + b'new-repo-backend', + default=b'revlogv1', + experimental=True, ) coreconfigitem( b'storage', @@ -1096,37 +1732,59 @@ b'storage', b'revlog.nodemap.mode', default=b'compat', experimental=True ) coreconfigitem( - b'storage', b'revlog.reuse-external-delta', default=True, -) -coreconfigitem( - b'storage', b'revlog.reuse-external-delta-parent', default=None, -) -coreconfigitem( - b'storage', b'revlog.zlib.level', default=None, -) -coreconfigitem( - b'storage', b'revlog.zstd.level', default=None, -) -coreconfigitem( - b'server', b'bookmarks-pushkey-compat', default=True, -) -coreconfigitem( - b'server', b'bundle1', default=True, -) -coreconfigitem( - b'server', b'bundle1gd', default=None, -) -coreconfigitem( - b'server', b'bundle1.pull', default=None, -) -coreconfigitem( - b'server', b'bundle1gd.pull', default=None, -) -coreconfigitem( - b'server', b'bundle1.push', default=None, -) -coreconfigitem( - b'server', b'bundle1gd.push', default=None, + b'storage', + b'revlog.reuse-external-delta', + default=True, +) +coreconfigitem( + b'storage', + b'revlog.reuse-external-delta-parent', + default=None, +) +coreconfigitem( + b'storage', + b'revlog.zlib.level', + default=None, +) +coreconfigitem( + b'storage', + b'revlog.zstd.level', + default=None, +) +coreconfigitem( + b'server', + b'bookmarks-pushkey-compat', + default=True, +) +coreconfigitem( + b'server', + b'bundle1', + default=True, +) +coreconfigitem( + b'server', + b'bundle1gd', + default=None, +) +coreconfigitem( + b'server', + b'bundle1.pull', + default=None, +) +coreconfigitem( + b'server', + b'bundle1gd.pull', + default=None, +) +coreconfigitem( + b'server', + b'bundle1.push', + default=None, +) +coreconfigitem( + b'server', + b'bundle1gd.push', + default=None, ) coreconfigitem( b'server', @@ -1135,73 +1793,120 @@ alias=[(b'experimental', b'bundle2.stream')], ) coreconfigitem( - b'server', b'compressionengines', default=list, -) -coreconfigitem( - b'server', b'concurrent-push-mode', default=b'check-related', -) -coreconfigitem( - b'server', b'disablefullbundle', default=False, -) -coreconfigitem( - b'server', b'maxhttpheaderlen', default=1024, -) -coreconfigitem( - b'server', b'pullbundle', default=False, -) -coreconfigitem( - b'server', b'preferuncompressed', default=False, -) -coreconfigitem( - b'server', b'streamunbundle', default=False, -) -coreconfigitem( - b'server', b'uncompressed', default=True, -) -coreconfigitem( - b'server', b'uncompressedallowsecret', default=False, -) -coreconfigitem( - b'server', b'view', default=b'served', -) -coreconfigitem( - b'server', b'validate', default=False, -) -coreconfigitem( - b'server', b'zliblevel', default=-1, -) -coreconfigitem( - b'server', b'zstdlevel', default=3, -) -coreconfigitem( - b'share', b'pool', default=None, -) -coreconfigitem( - b'share', b'poolnaming', default=b'identity', -) -coreconfigitem( - b'shelve', b'maxbackups', default=10, -) -coreconfigitem( - b'smtp', b'host', default=None, -) -coreconfigitem( - b'smtp', b'local_hostname', default=None, -) -coreconfigitem( - b'smtp', b'password', default=None, -) -coreconfigitem( - b'smtp', b'port', default=dynamicdefault, -) -coreconfigitem( - b'smtp', b'tls', default=b'none', -) -coreconfigitem( - b'smtp', b'username', default=None, -) -coreconfigitem( - b'sparse', b'missingwarning', default=True, experimental=True, + b'server', + b'compressionengines', + default=list, +) +coreconfigitem( + b'server', + b'concurrent-push-mode', + default=b'check-related', +) +coreconfigitem( + b'server', + b'disablefullbundle', + default=False, +) +coreconfigitem( + b'server', + b'maxhttpheaderlen', + default=1024, +) +coreconfigitem( + b'server', + b'pullbundle', + default=False, +) +coreconfigitem( + b'server', + b'preferuncompressed', + default=False, +) +coreconfigitem( + b'server', + b'streamunbundle', + default=False, +) +coreconfigitem( + b'server', + b'uncompressed', + default=True, +) +coreconfigitem( + b'server', + b'uncompressedallowsecret', + default=False, +) +coreconfigitem( + b'server', + b'view', + default=b'served', +) +coreconfigitem( + b'server', + b'validate', + default=False, +) +coreconfigitem( + b'server', + b'zliblevel', + default=-1, +) +coreconfigitem( + b'server', + b'zstdlevel', + default=3, +) +coreconfigitem( + b'share', + b'pool', + default=None, +) +coreconfigitem( + b'share', + b'poolnaming', + default=b'identity', +) +coreconfigitem( + b'shelve', + b'maxbackups', + default=10, +) +coreconfigitem( + b'smtp', + b'host', + default=None, +) +coreconfigitem( + b'smtp', + b'local_hostname', + default=None, +) +coreconfigitem( + b'smtp', + b'password', + default=None, +) +coreconfigitem( + b'smtp', + b'port', + default=dynamicdefault, +) +coreconfigitem( + b'smtp', + b'tls', + default=b'none', +) +coreconfigitem( + b'smtp', + b'username', + default=None, +) +coreconfigitem( + b'sparse', + b'missingwarning', + default=True, + experimental=True, ) coreconfigitem( b'subrepos', @@ -1209,385 +1914,612 @@ default=dynamicdefault, # to make backporting simpler ) coreconfigitem( - b'subrepos', b'hg:allowed', default=dynamicdefault, -) -coreconfigitem( - b'subrepos', b'git:allowed', default=dynamicdefault, -) -coreconfigitem( - b'subrepos', b'svn:allowed', default=dynamicdefault, -) -coreconfigitem( - b'templates', b'.*', default=None, generic=True, -) -coreconfigitem( - b'templateconfig', b'.*', default=dynamicdefault, generic=True, -) -coreconfigitem( - b'trusted', b'groups', default=list, -) -coreconfigitem( - b'trusted', b'users', default=list, -) -coreconfigitem( - b'ui', b'_usedassubrepo', default=False, -) -coreconfigitem( - b'ui', b'allowemptycommit', default=False, -) -coreconfigitem( - b'ui', b'archivemeta', default=True, -) -coreconfigitem( - b'ui', b'askusername', default=False, -) -coreconfigitem( - b'ui', b'available-memory', default=None, + b'subrepos', + b'hg:allowed', + default=dynamicdefault, +) +coreconfigitem( + b'subrepos', + b'git:allowed', + default=dynamicdefault, +) +coreconfigitem( + b'subrepos', + b'svn:allowed', + default=dynamicdefault, +) +coreconfigitem( + b'templates', + b'.*', + default=None, + generic=True, +) +coreconfigitem( + b'templateconfig', + b'.*', + default=dynamicdefault, + generic=True, +) +coreconfigitem( + b'trusted', + b'groups', + default=list, +) +coreconfigitem( + b'trusted', + b'users', + default=list, +) +coreconfigitem( + b'ui', + b'_usedassubrepo', + default=False, +) +coreconfigitem( + b'ui', + b'allowemptycommit', + default=False, +) +coreconfigitem( + b'ui', + b'archivemeta', + default=True, +) +coreconfigitem( + b'ui', + b'askusername', + default=False, +) +coreconfigitem( + b'ui', + b'available-memory', + default=None, ) coreconfigitem( - b'ui', b'clonebundlefallback', default=False, -) -coreconfigitem( - b'ui', b'clonebundleprefers', default=list, -) -coreconfigitem( - b'ui', b'clonebundles', default=True, -) -coreconfigitem( - b'ui', b'color', default=b'auto', -) -coreconfigitem( - b'ui', b'commitsubrepos', default=False, -) -coreconfigitem( - b'ui', b'debug', default=False, -) -coreconfigitem( - b'ui', b'debugger', default=None, -) -coreconfigitem( - b'ui', b'editor', default=dynamicdefault, -) -coreconfigitem( - b'ui', b'fallbackencoding', default=None, -) -coreconfigitem( - b'ui', b'forcecwd', default=None, -) -coreconfigitem( - b'ui', b'forcemerge', default=None, -) -coreconfigitem( - b'ui', b'formatdebug', default=False, -) -coreconfigitem( - b'ui', b'formatjson', default=False, -) -coreconfigitem( - b'ui', b'formatted', default=None, -) -coreconfigitem( - b'ui', b'graphnodetemplate', default=None, -) -coreconfigitem( - b'ui', b'interactive', default=None, -) -coreconfigitem( - b'ui', b'interface', default=None, -) -coreconfigitem( - b'ui', b'interface.chunkselector', default=None, -) -coreconfigitem( - b'ui', b'large-file-limit', default=10000000, -) -coreconfigitem( - b'ui', b'logblockedtimes', default=False, -) -coreconfigitem( - b'ui', b'logtemplate', default=None, -) -coreconfigitem( - b'ui', b'merge', default=None, -) -coreconfigitem( - b'ui', b'mergemarkers', default=b'basic', + b'ui', + b'clonebundlefallback', + default=False, +) +coreconfigitem( + b'ui', + b'clonebundleprefers', + default=list, +) +coreconfigitem( + b'ui', + b'clonebundles', + default=True, +) +coreconfigitem( + b'ui', + b'color', + default=b'auto', +) +coreconfigitem( + b'ui', + b'commitsubrepos', + default=False, +) +coreconfigitem( + b'ui', + b'debug', + default=False, +) +coreconfigitem( + b'ui', + b'debugger', + default=None, +) +coreconfigitem( + b'ui', + b'editor', + default=dynamicdefault, +) +coreconfigitem( + b'ui', + b'detailed-exit-code', + default=False, + experimental=True, +) +coreconfigitem( + b'ui', + b'fallbackencoding', + default=None, +) +coreconfigitem( + b'ui', + b'forcecwd', + default=None, +) +coreconfigitem( + b'ui', + b'forcemerge', + default=None, +) +coreconfigitem( + b'ui', + b'formatdebug', + default=False, +) +coreconfigitem( + b'ui', + b'formatjson', + default=False, +) +coreconfigitem( + b'ui', + b'formatted', + default=None, +) +coreconfigitem( + b'ui', + b'interactive', + default=None, +) +coreconfigitem( + b'ui', + b'interface', + default=None, +) +coreconfigitem( + b'ui', + b'interface.chunkselector', + default=None, +) +coreconfigitem( + b'ui', + b'large-file-limit', + default=10000000, +) +coreconfigitem( + b'ui', + b'logblockedtimes', + default=False, +) +coreconfigitem( + b'ui', + b'merge', + default=None, +) +coreconfigitem( + b'ui', + b'mergemarkers', + default=b'basic', +) +coreconfigitem( + b'ui', + b'message-output', + default=b'stdio', +) +coreconfigitem( + b'ui', + b'nontty', + default=False, +) +coreconfigitem( + b'ui', + b'origbackuppath', + default=None, +) +coreconfigitem( + b'ui', + b'paginate', + default=True, +) +coreconfigitem( + b'ui', + b'patch', + default=None, +) +coreconfigitem( + b'ui', + b'portablefilenames', + default=b'warn', +) +coreconfigitem( + b'ui', + b'promptecho', + default=False, +) +coreconfigitem( + b'ui', + b'quiet', + default=False, +) +coreconfigitem( + b'ui', + b'quietbookmarkmove', + default=False, +) +coreconfigitem( + b'ui', + b'relative-paths', + default=b'legacy', +) +coreconfigitem( + b'ui', + b'remotecmd', + default=b'hg', +) +coreconfigitem( + b'ui', + b'report_untrusted', + default=True, +) +coreconfigitem( + b'ui', + b'rollback', + default=True, +) +coreconfigitem( + b'ui', + b'signal-safe-lock', + default=True, +) +coreconfigitem( + b'ui', + b'slash', + default=False, +) +coreconfigitem( + b'ui', + b'ssh', + default=b'ssh', +) +coreconfigitem( + b'ui', + b'ssherrorhint', + default=None, +) +coreconfigitem( + b'ui', + b'statuscopies', + default=False, +) +coreconfigitem( + b'ui', + b'strict', + default=False, +) +coreconfigitem( + b'ui', + b'style', + default=b'', +) +coreconfigitem( + b'ui', + b'supportcontact', + default=None, +) +coreconfigitem( + b'ui', + b'textwidth', + default=78, +) +coreconfigitem( + b'ui', + b'timeout', + default=b'600', ) coreconfigitem( b'ui', - b'mergemarkertemplate', - default=( - b'{node|short} ' - b'{ifeq(tags, "tip", "", ' - b'ifeq(tags, "", "", "{tags} "))}' - b'{if(bookmarks, "{bookmarks} ")}' - b'{ifeq(branch, "default", "", "{branch} ")}' - b'- {author|user}: {desc|firstline}' - ), -) -coreconfigitem( - b'ui', b'message-output', default=b'stdio', -) -coreconfigitem( - b'ui', b'nontty', default=False, -) -coreconfigitem( - b'ui', b'origbackuppath', default=None, -) -coreconfigitem( - b'ui', b'paginate', default=True, -) -coreconfigitem( - b'ui', b'patch', default=None, -) -coreconfigitem( - b'ui', b'pre-merge-tool-output-template', default=None, -) -coreconfigitem( - b'ui', b'portablefilenames', default=b'warn', -) -coreconfigitem( - b'ui', b'promptecho', default=False, -) -coreconfigitem( - b'ui', b'quiet', default=False, -) -coreconfigitem( - b'ui', b'quietbookmarkmove', default=False, -) -coreconfigitem( - b'ui', b'relative-paths', default=b'legacy', -) -coreconfigitem( - b'ui', b'remotecmd', default=b'hg', -) -coreconfigitem( - b'ui', b'report_untrusted', default=True, -) -coreconfigitem( - b'ui', b'rollback', default=True, -) -coreconfigitem( - b'ui', b'signal-safe-lock', default=True, -) -coreconfigitem( - b'ui', b'slash', default=False, -) -coreconfigitem( - b'ui', b'ssh', default=b'ssh', -) -coreconfigitem( - b'ui', b'ssherrorhint', default=None, -) -coreconfigitem( - b'ui', b'statuscopies', default=False, -) -coreconfigitem( - b'ui', b'strict', default=False, -) -coreconfigitem( - b'ui', b'style', default=b'', -) -coreconfigitem( - b'ui', b'supportcontact', default=None, -) -coreconfigitem( - b'ui', b'textwidth', default=78, -) -coreconfigitem( - b'ui', b'timeout', default=b'600', -) -coreconfigitem( - b'ui', b'timeout.warn', default=0, -) -coreconfigitem( - b'ui', b'timestamp-output', default=False, -) -coreconfigitem( - b'ui', b'traceback', default=False, -) -coreconfigitem( - b'ui', b'tweakdefaults', default=False, + b'timeout.warn', + default=0, +) +coreconfigitem( + b'ui', + b'timestamp-output', + default=False, +) +coreconfigitem( + b'ui', + b'traceback', + default=False, +) +coreconfigitem( + b'ui', + b'tweakdefaults', + default=False, ) coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')]) coreconfigitem( - b'ui', b'verbose', default=False, -) -coreconfigitem( - b'verify', b'skipflags', default=None, -) -coreconfigitem( - b'web', b'allowbz2', default=False, -) -coreconfigitem( - b'web', b'allowgz', default=False, -) -coreconfigitem( - b'web', b'allow-pull', alias=[(b'web', b'allowpull')], default=True, -) -coreconfigitem( - b'web', b'allow-push', alias=[(b'web', b'allow_push')], default=list, -) -coreconfigitem( - b'web', b'allowzip', default=False, -) -coreconfigitem( - b'web', b'archivesubrepos', default=False, -) -coreconfigitem( - b'web', b'cache', default=True, -) -coreconfigitem( - b'web', b'comparisoncontext', default=5, -) -coreconfigitem( - b'web', b'contact', default=None, -) -coreconfigitem( - b'web', b'deny_push', default=list, -) -coreconfigitem( - b'web', b'guessmime', default=False, -) -coreconfigitem( - b'web', b'hidden', default=False, -) -coreconfigitem( - b'web', b'labels', default=list, -) -coreconfigitem( - b'web', b'logoimg', default=b'hglogo.png', -) -coreconfigitem( - b'web', b'logourl', default=b'https://mercurial-scm.org/', -) -coreconfigitem( - b'web', b'accesslog', default=b'-', -) -coreconfigitem( - b'web', b'address', default=b'', -) -coreconfigitem( - b'web', b'allow-archive', alias=[(b'web', b'allow_archive')], default=list, -) -coreconfigitem( - b'web', b'allow_read', default=list, -) -coreconfigitem( - b'web', b'baseurl', default=None, -) -coreconfigitem( - b'web', b'cacerts', default=None, -) -coreconfigitem( - b'web', b'certificate', default=None, -) -coreconfigitem( - b'web', b'collapse', default=False, -) -coreconfigitem( - b'web', b'csp', default=None, -) -coreconfigitem( - b'web', b'deny_read', default=list, -) -coreconfigitem( - b'web', b'descend', default=True, -) -coreconfigitem( - b'web', b'description', default=b"", -) -coreconfigitem( - b'web', b'encoding', default=lambda: encoding.encoding, -) -coreconfigitem( - b'web', b'errorlog', default=b'-', -) -coreconfigitem( - b'web', b'ipv6', default=False, -) -coreconfigitem( - b'web', b'maxchanges', default=10, -) -coreconfigitem( - b'web', b'maxfiles', default=10, -) -coreconfigitem( - b'web', b'maxshortchanges', default=60, -) -coreconfigitem( - b'web', b'motd', default=b'', -) -coreconfigitem( - b'web', b'name', default=dynamicdefault, -) -coreconfigitem( - b'web', b'port', default=8000, -) -coreconfigitem( - b'web', b'prefix', default=b'', -) -coreconfigitem( - b'web', b'push_ssl', default=True, -) -coreconfigitem( - b'web', b'refreshinterval', default=20, -) -coreconfigitem( - b'web', b'server-header', default=None, -) -coreconfigitem( - b'web', b'static', default=None, -) -coreconfigitem( - b'web', b'staticurl', default=None, -) -coreconfigitem( - b'web', b'stripes', default=1, -) -coreconfigitem( - b'web', b'style', default=b'paper', -) -coreconfigitem( - b'web', b'templates', default=None, -) -coreconfigitem( - b'web', b'view', default=b'served', experimental=True, -) -coreconfigitem( - b'worker', b'backgroundclose', default=dynamicdefault, + b'ui', + b'verbose', + default=False, +) +coreconfigitem( + b'verify', + b'skipflags', + default=None, +) +coreconfigitem( + b'web', + b'allowbz2', + default=False, +) +coreconfigitem( + b'web', + b'allowgz', + default=False, +) +coreconfigitem( + b'web', + b'allow-pull', + alias=[(b'web', b'allowpull')], + default=True, +) +coreconfigitem( + b'web', + b'allow-push', + alias=[(b'web', b'allow_push')], + default=list, +) +coreconfigitem( + b'web', + b'allowzip', + default=False, +) +coreconfigitem( + b'web', + b'archivesubrepos', + default=False, +) +coreconfigitem( + b'web', + b'cache', + default=True, +) +coreconfigitem( + b'web', + b'comparisoncontext', + default=5, +) +coreconfigitem( + b'web', + b'contact', + default=None, +) +coreconfigitem( + b'web', + b'deny_push', + default=list, +) +coreconfigitem( + b'web', + b'guessmime', + default=False, +) +coreconfigitem( + b'web', + b'hidden', + default=False, +) +coreconfigitem( + b'web', + b'labels', + default=list, +) +coreconfigitem( + b'web', + b'logoimg', + default=b'hglogo.png', +) +coreconfigitem( + b'web', + b'logourl', + default=b'https://mercurial-scm.org/', +) +coreconfigitem( + b'web', + b'accesslog', + default=b'-', +) +coreconfigitem( + b'web', + b'address', + default=b'', +) +coreconfigitem( + b'web', + b'allow-archive', + alias=[(b'web', b'allow_archive')], + default=list, +) +coreconfigitem( + b'web', + b'allow_read', + default=list, +) +coreconfigitem( + b'web', + b'baseurl', + default=None, +) +coreconfigitem( + b'web', + b'cacerts', + default=None, +) +coreconfigitem( + b'web', + b'certificate', + default=None, +) +coreconfigitem( + b'web', + b'collapse', + default=False, +) +coreconfigitem( + b'web', + b'csp', + default=None, +) +coreconfigitem( + b'web', + b'deny_read', + default=list, +) +coreconfigitem( + b'web', + b'descend', + default=True, +) +coreconfigitem( + b'web', + b'description', + default=b"", +) +coreconfigitem( + b'web', + b'encoding', + default=lambda: encoding.encoding, +) +coreconfigitem( + b'web', + b'errorlog', + default=b'-', +) +coreconfigitem( + b'web', + b'ipv6', + default=False, +) +coreconfigitem( + b'web', + b'maxchanges', + default=10, +) +coreconfigitem( + b'web', + b'maxfiles', + default=10, +) +coreconfigitem( + b'web', + b'maxshortchanges', + default=60, +) +coreconfigitem( + b'web', + b'motd', + default=b'', +) +coreconfigitem( + b'web', + b'name', + default=dynamicdefault, +) +coreconfigitem( + b'web', + b'port', + default=8000, +) +coreconfigitem( + b'web', + b'prefix', + default=b'', +) +coreconfigitem( + b'web', + b'push_ssl', + default=True, +) +coreconfigitem( + b'web', + b'refreshinterval', + default=20, +) +coreconfigitem( + b'web', + b'server-header', + default=None, +) +coreconfigitem( + b'web', + b'static', + default=None, +) +coreconfigitem( + b'web', + b'staticurl', + default=None, +) +coreconfigitem( + b'web', + b'stripes', + default=1, +) +coreconfigitem( + b'web', + b'style', + default=b'paper', +) +coreconfigitem( + b'web', + b'templates', + default=None, +) +coreconfigitem( + b'web', + b'view', + default=b'served', + experimental=True, +) +coreconfigitem( + b'worker', + b'backgroundclose', + default=dynamicdefault, ) # Windows defaults to a limit of 512 open files. A buffer of 128 # should give us enough headway. coreconfigitem( - b'worker', b'backgroundclosemaxqueue', default=384, -) -coreconfigitem( - b'worker', b'backgroundcloseminfilecount', default=2048, -) -coreconfigitem( - b'worker', b'backgroundclosethreadcount', default=4, -) -coreconfigitem( - b'worker', b'enabled', default=True, -) -coreconfigitem( - b'worker', b'numcpus', default=None, + b'worker', + b'backgroundclosemaxqueue', + default=384, +) +coreconfigitem( + b'worker', + b'backgroundcloseminfilecount', + default=2048, +) +coreconfigitem( + b'worker', + b'backgroundclosethreadcount', + default=4, +) +coreconfigitem( + b'worker', + b'enabled', + default=True, +) +coreconfigitem( + b'worker', + b'numcpus', + default=None, ) # Rebase related configuration moved to core because other extension are doing # strange things. For example, shelve import the extensions to reuse some bit # without formally loading it. coreconfigitem( - b'commands', b'rebase.requiredest', default=False, -) -coreconfigitem( - b'experimental', b'rebaseskipobsolete', default=True, -) -coreconfigitem( - b'rebase', b'singletransaction', default=False, -) -coreconfigitem( - b'rebase', b'experimental.inmemory', default=False, -) + b'commands', + b'rebase.requiredest', + default=False, +) +coreconfigitem( + b'experimental', + b'rebaseskipobsolete', + default=True, +) +coreconfigitem( + b'rebase', + b'singletransaction', + default=False, +) +coreconfigitem( + b'rebase', + b'experimental.inmemory', + default=False, +)
--- a/mercurial/context.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/context.py Thu Dec 03 14:15:39 2020 -0500 @@ -316,9 +316,9 @@ return subrepo.nullsubrepo(self, path, pctx) def workingsub(self, path): - '''return a subrepo for the stored revision, or wdir if this is a wdir + """return a subrepo for the stored revision, or wdir if this is a wdir context. - ''' + """ return subrepo.subrepo(self, path, allowwdir=True) def match( @@ -398,7 +398,17 @@ If other is None, compare this node with working directory. - returns (modified, added, removed, deleted, unknown, ignored, clean) + ctx1.status(ctx2) returns the status of change from ctx1 to ctx2 + + Returns a mercurial.scmutils.status object. + + Data can be accessed using either tuple notation: + + (modified, added, removed, deleted, unknown, ignored, clean) + + or direct attribute access: + + s.modified, s.added, ... """ ctx1 = self @@ -1044,8 +1054,7 @@ return lkr def isintroducedafter(self, changelogrev): - """True if a filectx has been introduced after a given floor revision - """ + """True if a filectx has been introduced after a given floor revision""" if self.linkrev() >= changelogrev: return True introrev = self._introrev(stoprev=changelogrev) @@ -1222,7 +1231,7 @@ class filectx(basefilectx): """A filecontext object makes access to data related to a particular - filerevision convenient.""" + filerevision convenient.""" def __init__( self, @@ -1234,15 +1243,16 @@ changectx=None, ): """changeid must be a revision number, if specified. - fileid can be a file revision or node.""" + fileid can be a file revision or node.""" self._repo = repo self._path = path assert ( changeid is not None or fileid is not None or changectx is not None - ), ( - b"bad args: changeid=%r, fileid=%r, changectx=%r" - % (changeid, fileid, changectx,) + ), b"bad args: changeid=%r, fileid=%r, changectx=%r" % ( + changeid, + fileid, + changectx, ) if filelog is not None: @@ -1279,8 +1289,8 @@ return self._repo.unfiltered()[self._changeid] def filectx(self, fileid, changeid=None): - '''opens an arbitrary revision of the file without - opening a new filelog''' + """opens an arbitrary revision of the file without + opening a new filelog""" return filectx( self._repo, self._path, @@ -2091,7 +2101,7 @@ class workingfilectx(committablefilectx): """A workingfilectx object makes access to data related to a particular - file in the working directory convenient.""" + file in the working directory convenient.""" def __init__(self, repo, path, filelog=None, workingctx=None): super(workingfilectx, self).__init__(repo, path, filelog, workingctx) @@ -2692,8 +2702,7 @@ @propertycache def _changedset(self): - """Return the set of files changed in this context - """ + """Return the set of files changed in this context""" changed = set(self._status.modified) changed.update(self._status.added) changed.update(self._status.removed) @@ -2867,8 +2876,7 @@ @propertycache def _status(self): - """Calculate exact status from ``files`` specified at construction - """ + """Calculate exact status from ``files`` specified at construction""" man1 = self.p1().manifest() p2 = self._parents[1] # "1 < len(self._parents)" can't be used for checking
--- a/mercurial/copies.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/copies.py Thu Dec 03 14:15:39 2020 -0500 @@ -17,6 +17,7 @@ match as matchmod, node, pathutil, + policy, pycompat, util, ) @@ -26,6 +27,8 @@ from .revlogutils import flagutil +rustmod = policy.importrust("copy_tracing") + def _filter(src, dst, t): """filters out invalid copies after chaining""" @@ -230,6 +233,24 @@ return revinfo +def cached_is_ancestor(is_ancestor): + """return a cached version of is_ancestor""" + cache = {} + + def _is_ancestor(anc, desc): + if anc > desc: + return False + elif anc == desc: + return True + key = (anc, desc) + ret = cache.get(key) + if ret is None: + ret = cache[key] = is_ancestor(anc, desc) + return ret + + return _is_ancestor + + def _changesetforwardcopies(a, b, match): if a.rev() in (node.nullrev, b.rev()): return {} @@ -238,7 +259,7 @@ children = {} cl = repo.changelog - isancestor = cl.isancestorrev # XXX we should had chaching to this. + isancestor = cl.isancestorrev missingrevs = cl.findmissingrevs(common=[a.rev()], heads=[b.rev()]) mrset = set(missingrevs) roots = set() @@ -292,8 +313,17 @@ It returns the aggregated copies information for `targetrev`. """ + + alwaysmatch = match.always() + + if rustmod is not None and alwaysmatch: + return rustmod.combine_changeset_copies( + list(revs), children, targetrev, revinfo, isancestor + ) + + isancestor = cached_is_ancestor(isancestor) + all_copies = {} - alwaysmatch = match.always() for r in revs: copies = all_copies.pop(r, None) if copies is None: @@ -324,7 +354,9 @@ source = prev[1] newcopies[dest] = (c, source) assert newcopies is not copies - if changes is not None: + if changes is not None and changes.removed: + if newcopies is copies: + newcopies = copies.copy() for f in changes.removed: if f in newcopies: if newcopies is copies: @@ -336,6 +368,9 @@ othercopies = all_copies.get(c) if othercopies is None: all_copies[c] = newcopies + elif newcopies is othercopies: + # nothing to merge: + pass else: # we are the second parent to work on c, we need to merge our # work with the other. @@ -345,14 +380,11 @@ # changeset based copies. It was made without regards with # potential filelog related behavior. if parent == 1: - _merge_copies_dict( - othercopies, newcopies, isancestor, changes - ) + minor, major = othercopies, newcopies else: - _merge_copies_dict( - newcopies, othercopies, isancestor, changes - ) - all_copies[c] = newcopies + minor, major = newcopies, othercopies + copies = _merge_copies_dict(minor, major, isancestor, changes) + all_copies[c] = copies final_copies = {} for dest, (tt, source) in all_copies[targetrev].items(): @@ -371,6 +403,8 @@ - `ismerged(path)`: callable return True if `path` have been merged in the current revision, + + return the resulting dict (in practice, the "minor" object, updated) """ for dest, value in major.items(): other = minor.get(dest) @@ -400,7 +434,11 @@ elif changes is not None and dest in changes.merged: minor[dest] = value elif not isancestor(new_tt, other_tt): - minor[dest] = value + if value[1] is not None: + minor[dest] = value + elif isancestor(other_tt, new_tt): + minor[dest] = value + return minor def _revinfo_getter_extra(repo): @@ -681,7 +719,7 @@ def _isfullcopytraceable(repo, c1, base): - """ Checks that if base, source and destination are all no-public branches, + """Checks that if base, source and destination are all no-public branches, if yes let's use the full copytrace algorithm for increased capabilities since it will be fast enough. @@ -749,14 +787,16 @@ self.movewithdir = {} if movewithdir is None else movewithdir def __repr__(self): - return ( - '<branch_copies\n copy=%r\n renamedelete=%r\n dirmove=%r\n movewithdir=%r\n>' - % (self.copy, self.renamedelete, self.dirmove, self.movewithdir,) + return '<branch_copies\n copy=%r\n renamedelete=%r\n dirmove=%r\n movewithdir=%r\n>' % ( + self.copy, + self.renamedelete, + self.dirmove, + self.movewithdir, ) def _fullcopytracing(repo, c1, c2, base): - """ The full copytracing algorithm which finds all the new files that were + """The full copytracing algorithm which finds all the new files that were added from merge base up to the top commit and for each file it checks if this file was copied from another file. @@ -890,7 +930,6 @@ addedfiles: added files on the other side (compared to ctx) """ # generate a directory move map - d = ctx.dirs() invalid = set() dirmove = {} @@ -901,7 +940,7 @@ if dsrc in invalid: # already seen to be uninteresting continue - elif dsrc in d and ddst in d: + elif ctx.hasdir(dsrc) and ctx.hasdir(ddst): # directory wasn't entirely moved locally invalid.add(dsrc) elif dsrc in dirmove and dirmove[dsrc] != ddst: @@ -914,7 +953,7 @@ for i in invalid: if i in dirmove: del dirmove[i] - del d, invalid + del invalid if not dirmove: return {}, {} @@ -946,7 +985,7 @@ def _heuristicscopytracing(repo, c1, c2, base): - """ Fast copytracing using filename heuristics + """Fast copytracing using filename heuristics Assumes that moves or renames are of following two types:
--- a/mercurial/crecord.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/crecord.py Thu Dec 03 14:15:39 2020 -0500 @@ -1000,7 +1000,7 @@ def toggleallbetween(self): """toggle applied on or off for all items in range [lastapplied, - current]. """ + current].""" if ( not self.lastapplieditem or self.currentselecteditem == self.lastapplieditem @@ -1894,7 +1894,7 @@ elif keypressed in ["H", "KEY_SLEFT"]: self.leftarrowshiftevent() elif keypressed in ["q"]: - raise error.Abort(_(b'user quit')) + raise error.CanceledError(_(b'user quit')) elif keypressed in ['a']: self.flipselections() elif keypressed in ["c"]:
--- a/mercurial/dagop.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/dagop.py Thu Dec 03 14:15:39 2020 -0500 @@ -682,7 +682,7 @@ def _annotatepair(parents, childfctx, child, skipchild, diffopts): - r''' + r""" Given parent and child fctxes and annotate data for parents, for all lines in either parent that match the child, annotate the child with the parent's data. @@ -691,7 +691,7 @@ annotate data as well such that child is never blamed for any lines. See test-annotate.py for unit tests. - ''' + """ pblocks = [ (parent, mdiff.allblocks(parent.text, child.text, opts=diffopts)) for parent in parents
--- a/mercurial/dagparser.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/dagparser.py Thu Dec 03 14:15:39 2020 -0500 @@ -425,7 +425,7 @@ usedots=False, maxlinewidth=70, ): - '''generates lines of a textual representation for a dag event stream + """generates lines of a textual representation for a dag event stream events should generate what parsedag() does, so: @@ -501,7 +501,7 @@ >>> dagtext(parsedag(b'+1 :f +1 :p2 *f */p2')) '+1 :f +1 :p2 *f */p2' - ''' + """ return b"\n".join( dagtextlines( dag,
--- a/mercurial/debugcommands.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/debugcommands.py Thu Dec 03 14:15:39 2020 -0500 @@ -78,6 +78,7 @@ sshpeer, sslutil, streamclone, + strip, tags as tagsmod, templater, treediscovery, @@ -105,7 +106,9 @@ release = lockmod.release -command = registrar.command() +table = {} +table.update(strip.command._table) +command = registrar.command(table) @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True) @@ -1059,11 +1062,14 @@ @command( - b'debugdownload', [(b'o', b'output', b'', _(b'path')),], optionalrepo=True + b'debugdownload', + [ + (b'o', b'output', b'', _(b'path')), + ], + optionalrepo=True, ) def debugdownload(ui, repo, url, output=None, **opts): - """download a resource using Mercurial logic and config - """ + """download a resource using Mercurial logic and config""" fh = urlmod.open(ui, url, output) dest = ui @@ -1507,10 +1513,10 @@ @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True) def debuginstall(ui, **opts): - '''test Mercurial installation + """test Mercurial installation Returns 0 on success. - ''' + """ opts = pycompat.byteskwargs(opts) problems = 0 @@ -2170,8 +2176,7 @@ ], ) def debugnodemap(ui, repo, **opts): - """write and inspect on disk nodemap - """ + """write and inspect on disk nodemap""" if opts['dump_new']: unfi = repo.unfiltered() cl = unfi.changelog @@ -2250,7 +2255,7 @@ raise TypeError() return n except TypeError: - raise error.Abort( + raise error.InputError( b'changeset references must be full hexadecimal ' b'node identifiers' ) @@ -2261,7 +2266,7 @@ try: indices.append(int(v)) except ValueError: - raise error.Abort( + raise error.InputError( _(b'invalid index value: %r') % v, hint=_(b'use integers for indices'), ) @@ -2279,7 +2284,9 @@ if precursor is not None: if opts[b'rev']: - raise error.Abort(b'cannot select revision when creating marker') + raise error.InputError( + b'cannot select revision when creating marker' + ) metadata = {} metadata[b'user'] = encoding.fromlocal(opts[b'user'] or ui.username()) succs = tuple(parsenodeid(succ) for succ in successors) @@ -2397,13 +2404,13 @@ _(b'FILESPEC...'), ) def debugpathcomplete(ui, repo, *specs, **opts): - '''complete part or all of a tracked path + """complete part or all of a tracked path This command supports shells that offer path name completion. It currently completes only files already known to the dirstate. Completion extends only to the next path segment unless - --full is specified, in which case entire paths are used.''' + --full is specified, in which case entire paths are used.""" def complete(path, acceptable): dirstate = repo.dirstate @@ -2582,13 +2589,13 @@ @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True) def debugpushkey(ui, repopath, namespace, *keyinfo, **opts): - '''access the pushkey key/value protocol + """access the pushkey key/value protocol With two args, list the keys in the given namespace. With five args, set a key to new if it currently is set to old. Reports success or failure. - ''' + """ target = hg.peer(ui, {}, repopath) if keyinfo: @@ -3427,7 +3434,7 @@ @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True) def debugssl(ui, repo, source=None, **opts): - '''test a secure connection to a server + """test a secure connection to a server This builds the certificate chain for the server on Windows, installing the missing intermediates and trusted root via Windows Update if necessary. It @@ -3438,7 +3445,7 @@ If the update succeeds, retry the original operation. Otherwise, the cause of the SSL error is likely another issue. - ''' + """ if not pycompat.iswindows: raise error.Abort( _(b'certificate chain building is only possible on Windows') @@ -3780,7 +3787,9 @@ @command( b'debuguigetpass', - [(b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),], + [ + (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')), + ], _(b'[-p TEXT]'), norepo=True, ) @@ -3796,7 +3805,9 @@ @command( b'debuguiprompt', - [(b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),], + [ + (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')), + ], _(b'[-p TEXT]'), norepo=True, ) @@ -3827,6 +3838,7 @@ (b'', b'backup', True, _(b'keep the old repository content around')), (b'', b'changelog', None, _(b'select the changelog for upgrade')), (b'', b'manifest', None, _(b'select the manifest for upgrade')), + (b'', b'filelogs', None, _(b'select all filelogs for upgrade')), ], ) def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts): @@ -3855,6 +3867,8 @@ * `--no-manifest`: optimize all revlog but the manifest * `--changelog`: optimize the changelog only * `--no-changelog --no-manifest`: optimize filelogs only + * `--filelogs`: optimize the filelogs only + * `--no-changelog --no-manifest --no-filelogs`: skip all filelog optimisation """ return upgrade.upgraderepo( ui, repo, run=run, optimize=optimize, backup=backup, **opts @@ -4309,7 +4323,10 @@ { 'loggingfh': ui, 'loggingname': b's', - 'loggingopts': {'logdata': True, 'logdataapis': False,}, + 'loggingopts': { + 'logdata': True, + 'logdataapis': False, + }, } )
--- a/mercurial/destutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/destutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -405,7 +405,7 @@ elif default: revs = scmutil.revrange(repo, [default]) else: - raise error.Abort( + raise error.ConfigError( _(b"config option histedit.defaultrev can't be empty") )
--- a/mercurial/diffutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/diffutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -43,14 +43,14 @@ formatchanging=False, configprefix=b'', ): - '''return diffopts with only opted-in features parsed + """return diffopts with only opted-in features parsed Features: - git: git-style diffs - whitespace: whitespace options like ignoreblanklines and ignorews - formatchanging: options that will likely break or cause correctness issues with most diff parsers - ''' + """ def get(key, name=None, getter=ui.configbool, forceplain=None): if opts:
--- a/mercurial/dirstate.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/dirstate.py Thu Dec 03 14:15:39 2020 -0500 @@ -74,12 +74,12 @@ @interfaceutil.implementer(intdirstate.idirstate) class dirstate(object): def __init__(self, opener, ui, root, validate, sparsematchfn): - '''Create a new dirstate object. + """Create a new dirstate object. opener is an open()-like callable that can be used to open the dirstate file; root is the root of the directory tracked by the dirstate. - ''' + """ self._opener = opener self._validate = validate self._root = root @@ -112,12 +112,12 @@ @contextlib.contextmanager def parentchange(self): - '''Context manager for handling dirstate parents. + """Context manager for handling dirstate parents. If an exception occurs in the scope of the context manager, the incoherent dirstate won't be written when wlock is released. - ''' + """ self._parentwriters += 1 yield # Typically we want the "undo" step of a context manager in a @@ -128,9 +128,9 @@ self._parentwriters -= 1 def pendingparentchange(self): - '''Returns true if the dirstate is in the middle of a set of changes + """Returns true if the dirstate is in the middle of a set of changes that modify the dirstate parent. - ''' + """ return self._parentwriters > 0 @propertycache @@ -247,12 +247,12 @@ return encoding.getcwd() def getcwd(self): - '''Return the path from which a canonical path is calculated. + """Return the path from which a canonical path is calculated. This path should be used to resolve file patterns or to convert canonical paths back to file paths for display. It shouldn't be used to get real file paths. Use vfs functions instead. - ''' + """ cwd = self._cwd if cwd == self._root: return b'' @@ -275,7 +275,7 @@ return path def __getitem__(self, key): - '''Return the current state of key (a filename) in the dirstate. + """Return the current state of key (a filename) in the dirstate. States are: n normal @@ -283,7 +283,7 @@ r marked for removal a marked for addition ? not tracked - ''' + """ return self._map.get(key, (b"?",))[0] def __contains__(self, key): @@ -370,11 +370,11 @@ raise def invalidate(self): - '''Causes the next access to reread the dirstate. + """Causes the next access to reread the dirstate. This is different from localrepo.invalidatedirstate() because it always rereads the dirstate. Use localrepo.invalidatedirstate() if you want to - check whether the dirstate has changed before rereading it.''' + check whether the dirstate has changed before rereading it.""" for a in ("_map", "_branch", "_ignore"): if a in self.__dict__: @@ -426,7 +426,7 @@ self._map.addfile(f, oldstate, state, mode, size, mtime) def normal(self, f, parentfiledata=None): - '''Mark a file normal and clean. + """Mark a file normal and clean. parentfiledata: (mode, size, mtime) of the clean file @@ -434,7 +434,7 @@ size), as or close as possible from the point where we determined the file was clean, to limit the risk of the file having been changed by an external process between the - moment where the file was determined to be clean and now.''' + moment where the file was determined to be clean and now.""" if parentfiledata: (mode, size, mtime) = parentfiledata else: @@ -581,7 +581,7 @@ return folded def normalize(self, path, isknown=False, ignoremissing=False): - ''' + """ normalize the case of a pathname when on a casefolding filesystem isknown specifies whether the filename came from walking the @@ -596,7 +596,7 @@ - version of name already stored in the dirstate - version of name stored on disk - version provided via command arguments - ''' + """ if self._checkcase: return self._normalize(path, isknown, ignoremissing) @@ -643,11 +643,11 @@ self._dirty = True def identity(self): - '''Return identity of dirstate itself to detect changing in storage + """Return identity of dirstate itself to detect changing in storage If identity of previous dirstate is equal to this, writing changes based on the former dirstate out can keep consistency. - ''' + """ return self._map.identity def write(self, tr): @@ -769,14 +769,14 @@ return (None, -1, b"") def _walkexplicit(self, match, subrepos): - '''Get stat data about the files explicitly specified by match. + """Get stat data about the files explicitly specified by match. Return a triple (results, dirsfound, dirsnotfound). - results is a mapping from filename to stat result. It also contains listings mapping subrepos and .hg to None. - dirsfound is a list of files found to be directories. - dirsnotfound is a list of files that the dirstate thinks are - directories and that were not found.''' + directories and that were not found.""" def badtype(mode): kind = _(b'unknown') @@ -904,7 +904,7 @@ return results, dirsfound, dirsnotfound def walk(self, match, subrepos, unknown, ignored, full=True): - ''' + """ Walk recursively through the directory tree, finding all files matched by match. @@ -913,7 +913,7 @@ Return a dict mapping filename to stat-like object (either mercurial.osutil.stat instance or return value of os.stat()). - ''' + """ # full is a flag that extensions that hook into walk can use -- this # implementation doesn't use it at all. This satisfies the contract # because we only guarantee a "maybe". @@ -1168,7 +1168,7 @@ return (lookup, status) def status(self, match, subrepos, ignored, clean, unknown): - '''Determine the status of the working copy relative to the + """Determine the status of the working copy relative to the dirstate and return a pair of (unsure, status), where status is of type scmutil.status and: @@ -1182,7 +1182,7 @@ status.clean: files that have definitely not been modified since the dirstate was written - ''' + """ listignored, listclean, listunknown = ignored, clean, unknown lookup, modified, added, unknown, ignored = [], [], [], [], [] removed, deleted, clean = [], [], [] @@ -1305,9 +1305,9 @@ return (lookup, status) def matches(self, match): - ''' + """ return files in the dirstate (in whatever state) filtered by match - ''' + """ dmap = self._map if rustmod is not None: dmap = self._map._rustmap
--- a/mercurial/dirstateguard.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/dirstateguard.py Thu Dec 03 14:15:39 2020 -0500 @@ -17,7 +17,7 @@ class dirstateguard(util.transactional): - '''Restore dirstate at unexpected failure. + """Restore dirstate at unexpected failure. At the construction, this class does: @@ -28,7 +28,7 @@ is invoked before ``close()``. This just removes the backup file at ``close()`` before ``release()``. - ''' + """ def __init__(self, repo, name): self._repo = repo
--- a/mercurial/discovery.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/discovery.py Thu Dec 03 14:15:39 2020 -0500 @@ -75,7 +75,7 @@ class outgoing(object): - '''Represents the result of a findcommonoutgoing() call. + """Represents the result of a findcommonoutgoing() call. Members: @@ -94,7 +94,7 @@ remotely. Some members are computed on demand from the heads, unless provided upfront - by discovery.''' + by discovery.""" def __init__( self, repo, commonheads=None, ancestorsof=None, missingroots=None @@ -157,7 +157,7 @@ def findcommonoutgoing( repo, other, onlyheads=None, force=False, commoninc=None, portable=False ): - '''Return an outgoing instance to identify the nodes present in repo but + """Return an outgoing instance to identify the nodes present in repo but not in other. If onlyheads is given, only nodes ancestral to nodes in onlyheads @@ -168,7 +168,7 @@ findcommonincoming(repo, other, force) to avoid recomputing it here. If portable is given, compute more conservative common and ancestorsof, - to make bundles created from the instance more portable.''' + to make bundles created from the instance more portable.""" # declare an empty outgoing object to be filled later og = outgoing(repo, None, None) @@ -332,7 +332,10 @@ with remote.commandexecutor() as e: remotebookmarks = e.callcommand( - b'listkeys', {b'namespace': b'bookmarks',} + b'listkeys', + { + b'namespace': b'bookmarks', + }, ).result() bookmarkedheads = set() @@ -399,12 +402,12 @@ closedbranches.add(tag) closedbranches = closedbranches & set(newbranches) if closedbranches: - errmsg = _(b"push creates new remote branches: %s (%d closed)!") % ( + errmsg = _(b"push creates new remote branches: %s (%d closed)") % ( branchnames, len(closedbranches), ) else: - errmsg = _(b"push creates new remote branches: %s!") % branchnames + errmsg = _(b"push creates new remote branches: %s") % branchnames hint = _(b"use 'hg push --new-branch' to create new remote branches") raise error.Abort(errmsg, hint=hint) @@ -469,15 +472,18 @@ if errormsg is None: if branch not in (b'default', None): errormsg = _( - b"push creates new remote head %s on branch '%s'!" - ) % (short(dhs[0]), branch,) + b"push creates new remote head %s on branch '%s'" + ) % ( + short(dhs[0]), + branch, + ) elif repo[dhs[0]].bookmarks(): errormsg = _( b"push creates new remote head %s " - b"with bookmark '%s'!" + b"with bookmark '%s'" ) % (short(dhs[0]), repo[dhs[0]].bookmarks()[0]) else: - errormsg = _(b"push creates new remote head %s!") % short( + errormsg = _(b"push creates new remote head %s") % short( dhs[0] ) if unsyncedheads:
--- a/mercurial/dispatch.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/dispatch.py Thu Dec 03 14:15:39 2020 -0500 @@ -7,7 +7,6 @@ from __future__ import absolute_import, print_function -import difflib import errno import getopt import io @@ -36,13 +35,16 @@ help, hg, hook, + localrepo, profiling, pycompat, rcutil, registrar, + requirements as requirementsmod, scmutil, ui as uimod, util, + vfs, ) from .utils import ( @@ -223,40 +225,6 @@ pass -def _getsimilar(symbols, value): - sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio() - # The cutoff for similarity here is pretty arbitrary. It should - # probably be investigated and tweaked. - return [s for s in symbols if sim(s) > 0.6] - - -def _reportsimilar(write, similar): - if len(similar) == 1: - write(_(b"(did you mean %s?)\n") % similar[0]) - elif similar: - ss = b", ".join(sorted(similar)) - write(_(b"(did you mean one of %s?)\n") % ss) - - -def _formatparse(write, inst): - similar = [] - if isinstance(inst, error.UnknownIdentifier): - # make sure to check fileset first, as revset can invoke fileset - similar = _getsimilar(inst.symbols, inst.function) - if len(inst.args) > 1: - write( - _(b"hg: parse error at %s: %s\n") - % (pycompat.bytestr(inst.args[1]), inst.args[0]) - ) - if inst.args[0].startswith(b' '): - write(_(b"unexpected leading whitespace\n")) - else: - write(_(b"hg: parse error: %s\n") % inst.args[0]) - _reportsimilar(write, similar) - if inst.hint: - write(_(b"(%s)\n") % inst.hint) - - def _formatargs(args): return b' '.join(procutil.shellquote(a) for a in args) @@ -288,12 +256,7 @@ if req.fmsg: req.ui.fmsg = req.fmsg except error.Abort as inst: - ferr.write(_(b"abort: %s\n") % inst.message) - if inst.hint: - ferr.write(_(b"(%s)\n") % inst.hint) - return -1 - except error.ParseError as inst: - _formatparse(ferr.write, inst) + ferr.write(inst.format()) return -1 msg = _formatargs(req.args) @@ -500,9 +463,6 @@ else: ui.warn(_(b"hg: %s\n") % inst.message) ui.warn(_(b"(use 'hg help -v' for a list of global options)\n")) - except error.ParseError as inst: - _formatparse(ui.warn, inst) - return -1 except error.UnknownCommand as inst: nocmdmsg = _(b"hg: unknown command '%s'\n") % inst.command try: @@ -516,10 +476,10 @@ except (error.UnknownCommand, error.Abort): suggested = False if inst.all_commands: - sim = _getsimilar(inst.all_commands, inst.command) + sim = error.getsimilar(inst.all_commands, inst.command) if sim: ui.warn(nocmdmsg) - _reportsimilar(ui.warn, sim) + ui.warn(b"(%s)\n" % error.similarity_hint(sim)) suggested = True if not suggested: ui.warn(nocmdmsg) @@ -550,7 +510,7 @@ nums.append(num) if num < len(givenargs): return givenargs[num] - raise error.Abort(_(b'too few arguments for command alias')) + raise error.InputError(_(b'too few arguments for command alias')) cmd = re.sub(br'\$(\d+|\$)', replacer, cmd) givenargs = [x for i, x in enumerate(givenargs) if i not in nums] @@ -559,10 +519,10 @@ def aliasinterpolate(name, args, cmd): - '''interpolate args into cmd for shell aliases + """interpolate args into cmd for shell aliases This also handles $0, $@ and "$@". - ''' + """ # util.interpolate can't deal with "$@" (with quotes) because it's only # built to match prefix + patterns. replacemap = {b'$%d' % (i + 1): arg for i, arg in enumerate(args)} @@ -670,12 +630,18 @@ except error.UnknownCommand: self.badalias = _( b"alias '%s' resolves to unknown command '%s'" - ) % (self.name, cmd,) + ) % ( + self.name, + cmd, + ) self.unknowncmd = True except error.AmbiguousCommand: self.badalias = _( b"alias '%s' resolves to ambiguous command '%s'" - ) % (self.name, cmd,) + ) % ( + self.name, + cmd, + ) def _populatehelp(self, ui, name, cmd, fn, defaulthelp=None): # confine strings to be passed to i18n.gettext() @@ -734,7 +700,7 @@ hint = _(b"'%s' is provided by '%s' extension") % (cmd, ext) except error.UnknownCommand: pass - raise error.Abort(self.badalias, hint=hint) + raise error.ConfigError(self.badalias, hint=hint) if self.shadows: ui.debug( b"alias '%s' shadows command '%s'\n" % (self.name, self.cmdname) @@ -941,6 +907,30 @@ return ret +def _readsharedsourceconfig(ui, path): + """if the current repository is shared one, this tries to read + .hg/hgrc of shared source if we are in share-safe mode + + Config read is loaded into the ui object passed + + This should be called before reading .hg/hgrc or the main repo + as that overrides config set in shared source""" + try: + with open(os.path.join(path, b".hg", b"requires"), "rb") as fp: + requirements = set(fp.read().splitlines()) + if not ( + requirementsmod.SHARESAFE_REQUIREMENT in requirements + and requirementsmod.SHARED_REQUIREMENT in requirements + ): + return + hgvfs = vfs.vfs(os.path.join(path, b".hg")) + sharedvfs = localrepo._getsharedvfs(hgvfs, requirements) + root = sharedvfs.base + ui.readconfig(sharedvfs.join(b"hgrc"), root) + except IOError: + pass + + def _getlocal(ui, rpath, wd=None): """Return (path, local ui object) for the given target path. @@ -961,13 +951,17 @@ else: lui = ui.copy() if rcutil.use_repo_hgrc(): + _readsharedsourceconfig(lui, path) lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path) + lui.readconfig(os.path.join(path, b".hg", b"hgrc-not-shared"), path) if rpath: path = lui.expandpath(rpath) lui = ui.copy() if rcutil.use_repo_hgrc(): + _readsharedsourceconfig(lui, path) lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path) + lui.readconfig(os.path.join(path, b".hg", b"hgrc-not-shared"), path) return path, lui @@ -1071,18 +1065,20 @@ req.canonical_command = cmd if options[b"config"] != req.earlyoptions[b"config"]: - raise error.Abort(_(b"option --config may not be abbreviated!")) + raise error.InputError(_(b"option --config may not be abbreviated")) if options[b"cwd"] != req.earlyoptions[b"cwd"]: - raise error.Abort(_(b"option --cwd may not be abbreviated!")) + raise error.InputError(_(b"option --cwd may not be abbreviated")) if options[b"repository"] != req.earlyoptions[b"repository"]: - raise error.Abort( + raise error.InputError( _( b"option -R has to be separated from other options (e.g. not " - b"-qR) and --repository may only be abbreviated as --repo!" + b"-qR) and --repository may only be abbreviated as --repo" ) ) if options[b"debugger"] != req.earlyoptions[b"debugger"]: - raise error.Abort(_(b"option --debugger may not be abbreviated!")) + raise error.InputError( + _(b"option --debugger may not be abbreviated") + ) # don't validate --profile/--traceback, which can be enabled from now if options[b"encoding"]: @@ -1187,7 +1183,7 @@ intents=func.intents, ) if not repo.local(): - raise error.Abort( + raise error.InputError( _(b"repository '%s' is not local") % path ) repo.ui.setconfig( @@ -1208,7 +1204,7 @@ req.earlyoptions[b'repository'] = guess return _dispatch(req) if not path: - raise error.RepoError( + raise error.InputError( _( b"no repository found in" b" '%s' (.hg not found)" @@ -1257,7 +1253,7 @@ # of date) will be clueful enough to notice the implausible # version number and try updating. ct = util.versiontuple(n=2) - worst = None, ct, b'' + worst = None, ct, b'', b'' if ui.config(b'ui', b'supportcontact') is None: for name, mod in extensions.extensions(): # 'testedwith' should be bytes, but not all extensions are ported @@ -1265,10 +1261,11 @@ testedwith = stringutil.forcebytestr( getattr(mod, 'testedwith', b'') ) + version = extensions.moduleversion(mod) report = getattr(mod, 'buglink', _(b'the extension author.')) if not testedwith.strip(): # We found an untested extension. It's likely the culprit. - worst = name, b'unknown', report + worst = name, b'unknown', report, version break # Never blame on extensions bundled with Mercurial. @@ -1282,20 +1279,21 @@ lower = [t for t in tested if t < ct] nearest = max(lower or tested) if worst[0] is None or nearest < worst[1]: - worst = name, nearest, report + worst = name, nearest, report, version if worst[0] is not None: - name, testedwith, report = worst + name, testedwith, report, version = worst if not isinstance(testedwith, (bytes, str)): testedwith = b'.'.join( [stringutil.forcebytestr(c) for c in testedwith] ) + extver = version or _(b"(version N/A)") warning = _( b'** Unknown exception encountered with ' - b'possibly-broken third-party extension %s\n' + b'possibly-broken third-party extension "%s" %s\n' b'** which supports versions %s of Mercurial.\n' - b'** Please disable %s and try your action again.\n' + b'** Please disable "%s" and try your action again.\n' b'** If that fixes the bug please report it to %s\n' - ) % (name, testedwith, name, stringutil.forcebytestr(report)) + ) % (name, extver, testedwith, name, stringutil.forcebytestr(report)) else: bugtracker = ui.config(b'ui', b'supportcontact') if bugtracker is None: @@ -1309,12 +1307,22 @@ + b'\n' ) sysversion = pycompat.sysbytes(sys.version).replace(b'\n', b'') + + def ext_with_ver(x): + ext = x[0] + ver = extensions.moduleversion(x[1]) + if ver: + ext += b' ' + ver + return ext + warning += ( (_(b"** Python %s\n") % sysversion) + (_(b"** Mercurial Distributed SCM (version %s)\n") % util.version()) + ( _(b"** Extensions loaded: %s\n") - % b", ".join([x[0] for x in extensions.extensions()]) + % b", ".join( + [ext_with_ver(x) for x in sorted(extensions.extensions())] + ) ) ) return warning
--- a/mercurial/encoding.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/encoding.py Thu Dec 03 14:15:39 2020 -0500 @@ -113,8 +113,8 @@ class localstr(bytes): - '''This class allows strings that are unmodified to be - round-tripped to the local encoding and back''' + """This class allows strings that are unmodified to be + round-tripped to the local encoding and back""" def __new__(cls, u, l): s = bytes.__new__(cls, l) @@ -329,8 +329,8 @@ def getcols(s, start, c): # type: (bytes, int, int) -> bytes - '''Use colwidth to find a c-column substring of s starting at byte - index start''' + """Use colwidth to find a c-column substring of s starting at byte + index start""" for x in pycompat.xrange(start + c, len(s)): t = s[start:x] if colwidth(t) == c: @@ -487,7 +487,7 @@ class normcasespecs(object): - '''what a platform's normcase does to ASCII strings + """what a platform's normcase does to ASCII strings This is specified per platform, and should be consistent with what normcase on that platform actually does. @@ -496,7 +496,7 @@ upper: normcase uppercases ASCII strings other: the fallback function should always be called - This should be kept in sync with normcase_spec in util.h.''' + This should be kept in sync with normcase_spec in util.h.""" lower = -1 upper = 1 @@ -505,7 +505,7 @@ def jsonescape(s, paranoid=False): # type: (Any, Any) -> Any - '''returns a string suitable for JSON + """returns a string suitable for JSON JSON is problematic for us because it doesn't support non-Unicode bytes. To deal with this, we take the following approach: @@ -547,7 +547,7 @@ 'non-BMP: \\\\ud834\\\\udd1e' >>> jsonescape(b'<foo@example.org>', paranoid=True) '\\\\u003cfoo@example.org\\\\u003e' - ''' + """ u8chars = toutf8b(s) try: @@ -569,11 +569,11 @@ def getutf8char(s, pos): # type: (bytes, int) -> bytes - '''get the next full utf-8 character in the given string, starting at pos + """get the next full utf-8 character in the given string, starting at pos Raises a UnicodeError if the given location does not start a valid utf-8 character. - ''' + """ # find how many bytes to attempt decoding from first nibble l = _utf8len[ord(s[pos : pos + 1]) >> 4] @@ -588,7 +588,7 @@ def toutf8b(s): # type: (bytes) -> bytes - '''convert a local, possibly-binary string into UTF-8b + """convert a local, possibly-binary string into UTF-8b This is intended as a generic method to preserve data when working with schemes like JSON and XML that have no provision for @@ -616,7 +616,7 @@ arbitrary bytes into an internal Unicode format that can be re-encoded back into the original. Here we are exposing the internal surrogate encoding as a UTF-8 string.) - ''' + """ if isinstance(s, localstr): # assume that the original UTF-8 sequence would never contain @@ -657,7 +657,7 @@ def fromutf8b(s): # type: (bytes) -> bytes - '''Given a UTF-8b string, return a local, possibly-binary string. + """Given a UTF-8b string, return a local, possibly-binary string. return the original binary string. This is a round-trip process for strings like filenames, but metadata @@ -677,7 +677,7 @@ True >>> roundtrip(b"\\xf1\\x80\\x80\\x80\\x80") True - ''' + """ if isasciistr(s): return s
--- a/mercurial/error.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/error.py Thu Dec 03 14:15:39 2020 -0500 @@ -13,6 +13,8 @@ from __future__ import absolute_import +import difflib + # Do not import anything but pycompat here, please from . import pycompat @@ -48,7 +50,7 @@ class RevlogError(StorageError): - __bytes__ = _tobytes + pass class SidedataHashError(RevlogError): @@ -130,6 +132,17 @@ __bytes__ = _tobytes +class WorkerError(Exception): + """Exception raised when a worker process dies.""" + + def __init__(self, status_code): + self.status_code = status_code + # Pass status code to superclass just so it becomes part of __bytes__ + super(WorkerError, self).__init__(status_code) + + __bytes__ = _tobytes + + class InterventionRequired(Hint, Exception): """Exception raised when a command requires human intervention.""" @@ -173,6 +186,43 @@ # may raise another exception. return pycompat.sysstr(self.__bytes__()) + def format(self): + from .i18n import _ + + message = _(b"abort: %s\n") % self.message + if self.hint: + message += _(b"(%s)\n") % self.hint + return message + + +class InputError(Abort): + """Indicates that the user made an error in their input. + + Examples: Invalid command, invalid flags, invalid revision. + """ + + +class StateError(Abort): + """Indicates that the operation might work if retried in a different state. + + Examples: Unresolved merge conflicts, unfinished operations. + """ + + +class CanceledError(Abort): + """Indicates that the user canceled the operation. + + Examples: Close commit editor with error status, quit chistedit. + """ + + +class SecurityError(Abort): + """Indicates that some aspect of security failed. + + Examples: Bad server credentials, expired local credentials for network + filesystem, mismatched GPG signature, DoS protection. + """ + class HookLoadError(Abort): """raised when loading a hook fails, aborting an operation @@ -189,6 +239,24 @@ class ConfigError(Abort): """Exception raised when parsing config files""" + def __init__(self, message, location=None, hint=None): + super(ConfigError, self).__init__(message, hint=hint) + self.location = location + + def format(self): + from .i18n import _ + + if self.location is not None: + message = _(b"config error at %s: %s\n") % ( + pycompat.bytestr(self.location), + self.message, + ) + else: + message = _(b"config error: %s\n") % self.message + if self.hint: + message += _(b"(%s)\n") % self.hint + return message + class UpdateAbort(Abort): """Raised when an update is aborted for destination issue""" @@ -221,25 +289,63 @@ __bytes__ = _tobytes -class ParseError(Hint, Exception): +class ParseError(Abort): """Raised when parsing config files and {rev,file}sets (msg[, pos])""" - __bytes__ = _tobytes + def __init__(self, message, location=None, hint=None): + super(ParseError, self).__init__(message, hint=hint) + self.location = location + + def format(self): + from .i18n import _ + + if self.location is not None: + message = _(b"hg: parse error at %s: %s\n") % ( + pycompat.bytestr(self.location), + self.message, + ) + else: + message = _(b"hg: parse error: %s\n") % self.message + if self.hint: + message += _(b"(%s)\n") % self.hint + return message class PatchError(Exception): __bytes__ = _tobytes +def getsimilar(symbols, value): + sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio() + # The cutoff for similarity here is pretty arbitrary. It should + # probably be investigated and tweaked. + return [s for s in symbols if sim(s) > 0.6] + + +def similarity_hint(similar): + from .i18n import _ + + if len(similar) == 1: + return _(b"did you mean %s?") % similar[0] + elif similar: + ss = b", ".join(sorted(similar)) + return _(b"did you mean one of %s?") % ss + else: + return None + + class UnknownIdentifier(ParseError): """Exception raised when a {rev,file}set references an unknown identifier""" def __init__(self, function, symbols): from .i18n import _ - ParseError.__init__(self, _(b"unknown identifier: %s") % function) - self.function = function - self.symbols = symbols + similar = getsimilar(symbols, function) + hint = similarity_hint(similar) + + ParseError.__init__( + self, _(b"unknown identifier: %s") % function, hint=hint + ) class RepoError(Hint, Exception): @@ -288,8 +394,7 @@ class UnknownVersion(Abort): - """generic exception for aborting from an encounter with an unknown version - """ + """generic exception for aborting from an encounter with an unknown version""" def __init__(self, msg, hint=None, version=None): self.version = version
--- a/mercurial/exchange.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/exchange.py Thu Dec 03 14:15:39 2020 -0500 @@ -16,10 +16,10 @@ nullid, nullrev, ) -from .thirdparty import attr from . import ( bookmarks as bookmod, bundle2, + bundlecaches, changegroup, discovery, error, @@ -34,7 +34,6 @@ pycompat, requirements, scmutil, - sslutil, streamclone, url as urlmod, util, @@ -50,202 +49,6 @@ _NARROWACL_SECTION = b'narrowacl' -# Maps bundle version human names to changegroup versions. -_bundlespeccgversions = { - b'v1': b'01', - b'v2': b'02', - b'packed1': b's1', - b'bundle2': b'02', # legacy -} - -# Maps bundle version with content opts to choose which part to bundle -_bundlespeccontentopts = { - b'v1': { - b'changegroup': True, - b'cg.version': b'01', - b'obsolescence': False, - b'phases': False, - b'tagsfnodescache': False, - b'revbranchcache': False, - }, - b'v2': { - b'changegroup': True, - b'cg.version': b'02', - b'obsolescence': False, - b'phases': False, - b'tagsfnodescache': True, - b'revbranchcache': True, - }, - b'packed1': {b'cg.version': b's1'}, -} -_bundlespeccontentopts[b'bundle2'] = _bundlespeccontentopts[b'v2'] - -_bundlespecvariants = { - b"streamv2": { - b"changegroup": False, - b"streamv2": True, - b"tagsfnodescache": False, - b"revbranchcache": False, - } -} - -# Compression engines allowed in version 1. THIS SHOULD NEVER CHANGE. -_bundlespecv1compengines = {b'gzip', b'bzip2', b'none'} - - -@attr.s -class bundlespec(object): - compression = attr.ib() - wirecompression = attr.ib() - version = attr.ib() - wireversion = attr.ib() - params = attr.ib() - contentopts = attr.ib() - - -def parsebundlespec(repo, spec, strict=True): - """Parse a bundle string specification into parts. - - Bundle specifications denote a well-defined bundle/exchange format. - The content of a given specification should not change over time in - order to ensure that bundles produced by a newer version of Mercurial are - readable from an older version. - - The string currently has the form: - - <compression>-<type>[;<parameter0>[;<parameter1>]] - - Where <compression> is one of the supported compression formats - and <type> is (currently) a version string. A ";" can follow the type and - all text afterwards is interpreted as URI encoded, ";" delimited key=value - pairs. - - If ``strict`` is True (the default) <compression> is required. Otherwise, - it is optional. - - Returns a bundlespec object of (compression, version, parameters). - Compression will be ``None`` if not in strict mode and a compression isn't - defined. - - An ``InvalidBundleSpecification`` is raised when the specification is - not syntactically well formed. - - An ``UnsupportedBundleSpecification`` is raised when the compression or - bundle type/version is not recognized. - - Note: this function will likely eventually return a more complex data - structure, including bundle2 part information. - """ - - def parseparams(s): - if b';' not in s: - return s, {} - - params = {} - version, paramstr = s.split(b';', 1) - - for p in paramstr.split(b';'): - if b'=' not in p: - raise error.InvalidBundleSpecification( - _( - b'invalid bundle specification: ' - b'missing "=" in parameter: %s' - ) - % p - ) - - key, value = p.split(b'=', 1) - key = urlreq.unquote(key) - value = urlreq.unquote(value) - params[key] = value - - return version, params - - if strict and b'-' not in spec: - raise error.InvalidBundleSpecification( - _( - b'invalid bundle specification; ' - b'must be prefixed with compression: %s' - ) - % spec - ) - - if b'-' in spec: - compression, version = spec.split(b'-', 1) - - if compression not in util.compengines.supportedbundlenames: - raise error.UnsupportedBundleSpecification( - _(b'%s compression is not supported') % compression - ) - - version, params = parseparams(version) - - if version not in _bundlespeccgversions: - raise error.UnsupportedBundleSpecification( - _(b'%s is not a recognized bundle version') % version - ) - else: - # Value could be just the compression or just the version, in which - # case some defaults are assumed (but only when not in strict mode). - assert not strict - - spec, params = parseparams(spec) - - if spec in util.compengines.supportedbundlenames: - compression = spec - version = b'v1' - # Generaldelta repos require v2. - if b'generaldelta' in repo.requirements: - version = b'v2' - # Modern compression engines require v2. - if compression not in _bundlespecv1compengines: - version = b'v2' - elif spec in _bundlespeccgversions: - if spec == b'packed1': - compression = b'none' - else: - compression = b'bzip2' - version = spec - else: - raise error.UnsupportedBundleSpecification( - _(b'%s is not a recognized bundle specification') % spec - ) - - # Bundle version 1 only supports a known set of compression engines. - if version == b'v1' and compression not in _bundlespecv1compengines: - raise error.UnsupportedBundleSpecification( - _(b'compression engine %s is not supported on v1 bundles') - % compression - ) - - # The specification for packed1 can optionally declare the data formats - # required to apply it. If we see this metadata, compare against what the - # repo supports and error if the bundle isn't compatible. - if version == b'packed1' and b'requirements' in params: - requirements = set(params[b'requirements'].split(b',')) - missingreqs = requirements - repo.supportedformats - if missingreqs: - raise error.UnsupportedBundleSpecification( - _(b'missing support for repository features: %s') - % b', '.join(sorted(missingreqs)) - ) - - # Compute contentopts based on the version - contentopts = _bundlespeccontentopts.get(version, {}).copy() - - # Process the variants - if b"stream" in params and params[b"stream"] == b"v2": - variant = _bundlespecvariants[b"streamv2"] - contentopts.update(variant) - - engine = util.compengines.forbundlename(compression) - compression, wirecompression = engine.bundletype() - wireversion = _bundlespeccgversions[version] - - return bundlespec( - compression, wirecompression, version, wireversion, params, contentopts - ) - def readbundle(ui, fh, fname, vfs=None): header = changegroup.readexactly(fh, 4) @@ -390,7 +193,7 @@ _(b'push and publish %i changesets (yn)?$$ &Yes $$ &No') % len(published) ): - raise error.Abort(_(b'user quit')) + raise error.CanceledError(_(b'user quit')) elif behavior == b'abort': msg = _(b'push would publish %i changesets') % len(published) hint = _( @@ -552,15 +355,15 @@ bookmsgmap = { b'update': ( _(b"updating bookmark %s\n"), - _(b'updating bookmark %s failed!\n'), + _(b'updating bookmark %s failed\n'), ), b'export': ( _(b"exporting bookmark %s\n"), - _(b'exporting bookmark %s failed!\n'), + _(b'exporting bookmark %s failed\n'), ), b'delete': ( _(b"deleting remote bookmark %s\n"), - _(b'deleting remote bookmark %s failed!\n'), + _(b'deleting remote bookmark %s failed\n'), ), } @@ -575,14 +378,14 @@ publish=False, opargs=None, ): - '''Push outgoing changesets (limited by revs) from a local + """Push outgoing changesets (limited by revs) from a local repository to remote. Return an integer: - None means nothing to push - 0 means HTTP error - 1 means we pushed and remote head count is unchanged *or* we have outgoing changesets but refused to push - other values as described by addchangegroup() - ''' + """ if opargs is None: opargs = {} pushop = pushoperation( @@ -1707,8 +1510,8 @@ def add_confirm_callback(repo, pullop): - """ adds a finalize callback to transaction which can be used to show stats - to user and confirm the pull before committing transaction """ + """adds a finalize callback to transaction which can be used to show stats + to user and confirm the pull before committing transaction""" tr = pullop.trmanager.transaction() scmutil.registersummarycallback( @@ -2089,7 +1892,11 @@ elif pullop.heads is None: with pullop.remote.commandexecutor() as e: cg = e.callcommand( - b'changegroup', {b'nodes': pullop.fetch, b'source': b'pull',} + b'changegroup', + { + b'nodes': pullop.fetch, + b'source': b'pull', + }, ).result() elif not pullop.remote.capable(b'changegroupsubset'): @@ -2867,7 +2674,7 @@ # attempt. pullop.clonebundleattempted = True - entries = parseclonebundlesmanifest(repo, res) + entries = bundlecaches.parseclonebundlesmanifest(repo, res) if not entries: repo.ui.note( _( @@ -2877,7 +2684,7 @@ ) return - entries = filterclonebundleentries( + entries = bundlecaches.filterclonebundleentries( repo, entries, streamclonerequested=pullop.streamclonerequested ) @@ -2898,7 +2705,7 @@ ) return - entries = sortclonebundleentries(repo.ui, entries) + entries = bundlecaches.sortclonebundleentries(repo.ui, entries) url = entries[0][b'URL'] repo.ui.status(_(b'applying clone bundle from %s\n') % url) @@ -2923,214 +2730,6 @@ ) -def parseclonebundlesmanifest(repo, s): - """Parses the raw text of a clone bundles manifest. - - Returns a list of dicts. The dicts have a ``URL`` key corresponding - to the URL and other keys are the attributes for the entry. - """ - m = [] - for line in s.splitlines(): - fields = line.split() - if not fields: - continue - attrs = {b'URL': fields[0]} - for rawattr in fields[1:]: - key, value = rawattr.split(b'=', 1) - key = urlreq.unquote(key) - value = urlreq.unquote(value) - attrs[key] = value - - # Parse BUNDLESPEC into components. This makes client-side - # preferences easier to specify since you can prefer a single - # component of the BUNDLESPEC. - if key == b'BUNDLESPEC': - try: - bundlespec = parsebundlespec(repo, value) - attrs[b'COMPRESSION'] = bundlespec.compression - attrs[b'VERSION'] = bundlespec.version - except error.InvalidBundleSpecification: - pass - except error.UnsupportedBundleSpecification: - pass - - m.append(attrs) - - return m - - -def isstreamclonespec(bundlespec): - # Stream clone v1 - if bundlespec.wirecompression == b'UN' and bundlespec.wireversion == b's1': - return True - - # Stream clone v2 - if ( - bundlespec.wirecompression == b'UN' - and bundlespec.wireversion == b'02' - and bundlespec.contentopts.get(b'streamv2') - ): - return True - - return False - - -def filterclonebundleentries(repo, entries, streamclonerequested=False): - """Remove incompatible clone bundle manifest entries. - - Accepts a list of entries parsed with ``parseclonebundlesmanifest`` - and returns a new list consisting of only the entries that this client - should be able to apply. - - There is no guarantee we'll be able to apply all returned entries because - the metadata we use to filter on may be missing or wrong. - """ - newentries = [] - for entry in entries: - spec = entry.get(b'BUNDLESPEC') - if spec: - try: - bundlespec = parsebundlespec(repo, spec, strict=True) - - # If a stream clone was requested, filter out non-streamclone - # entries. - if streamclonerequested and not isstreamclonespec(bundlespec): - repo.ui.debug( - b'filtering %s because not a stream clone\n' - % entry[b'URL'] - ) - continue - - except error.InvalidBundleSpecification as e: - repo.ui.debug(stringutil.forcebytestr(e) + b'\n') - continue - except error.UnsupportedBundleSpecification as e: - repo.ui.debug( - b'filtering %s because unsupported bundle ' - b'spec: %s\n' % (entry[b'URL'], stringutil.forcebytestr(e)) - ) - continue - # If we don't have a spec and requested a stream clone, we don't know - # what the entry is so don't attempt to apply it. - elif streamclonerequested: - repo.ui.debug( - b'filtering %s because cannot determine if a stream ' - b'clone bundle\n' % entry[b'URL'] - ) - continue - - if b'REQUIRESNI' in entry and not sslutil.hassni: - repo.ui.debug( - b'filtering %s because SNI not supported\n' % entry[b'URL'] - ) - continue - - if b'REQUIREDRAM' in entry: - try: - requiredram = util.sizetoint(entry[b'REQUIREDRAM']) - except error.ParseError: - repo.ui.debug( - b'filtering %s due to a bad REQUIREDRAM attribute\n' - % entry[b'URL'] - ) - continue - actualram = repo.ui.estimatememory() - if actualram is not None and actualram * 0.66 < requiredram: - repo.ui.debug( - b'filtering %s as it needs more than 2/3 of system memory\n' - % entry[b'URL'] - ) - continue - - newentries.append(entry) - - return newentries - - -class clonebundleentry(object): - """Represents an item in a clone bundles manifest. - - This rich class is needed to support sorting since sorted() in Python 3 - doesn't support ``cmp`` and our comparison is complex enough that ``key=`` - won't work. - """ - - def __init__(self, value, prefers): - self.value = value - self.prefers = prefers - - def _cmp(self, other): - for prefkey, prefvalue in self.prefers: - avalue = self.value.get(prefkey) - bvalue = other.value.get(prefkey) - - # Special case for b missing attribute and a matches exactly. - if avalue is not None and bvalue is None and avalue == prefvalue: - return -1 - - # Special case for a missing attribute and b matches exactly. - if bvalue is not None and avalue is None and bvalue == prefvalue: - return 1 - - # We can't compare unless attribute present on both. - if avalue is None or bvalue is None: - continue - - # Same values should fall back to next attribute. - if avalue == bvalue: - continue - - # Exact matches come first. - if avalue == prefvalue: - return -1 - if bvalue == prefvalue: - return 1 - - # Fall back to next attribute. - continue - - # If we got here we couldn't sort by attributes and prefers. Fall - # back to index order. - return 0 - - def __lt__(self, other): - return self._cmp(other) < 0 - - def __gt__(self, other): - return self._cmp(other) > 0 - - def __eq__(self, other): - return self._cmp(other) == 0 - - def __le__(self, other): - return self._cmp(other) <= 0 - - def __ge__(self, other): - return self._cmp(other) >= 0 - - def __ne__(self, other): - return self._cmp(other) != 0 - - -def sortclonebundleentries(ui, entries): - prefers = ui.configlist(b'ui', b'clonebundleprefers') - if not prefers: - return list(entries) - - def _split(p): - if b'=' not in p: - hint = _(b"each comma separated item should be key=value pairs") - raise error.Abort( - _(b"invalid ui.clonebundleprefers item: %s") % p, hint=hint - ) - return p.split(b'=', 1) - - prefers = [_split(p) for p in prefers] - - items = sorted(clonebundleentry(v, prefers) for v in entries) - return [i.value for i in items] - - def trypullbundlefromurl(ui, repo, url): """Attempt to apply a bundle from a URL.""" with repo.lock(), repo.transaction(b'bundleurl') as tr:
--- a/mercurial/exchangev2.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/exchangev2.py Thu Dec 03 14:15:39 2020 -0500 @@ -79,7 +79,9 @@ # Ensure all new changesets are draft by default. If the repo is # publishing, the phase will be adjusted by the loop below. if csetres[b'added']: - phases.registernew(repo, tr, phases.draft, csetres[b'added']) + phases.registernew( + repo, tr, phases.draft, [repo[n].rev() for n in csetres[b'added']] + ) # And adjust the phase of all changesets accordingly. for phasenumber, phase in phases.phasenames.items(): @@ -87,7 +89,10 @@ continue phases.advanceboundary( - repo, tr, phasenumber, csetres[b'nodesbyphase'][phase], + repo, + tr, + phasenumber, + csetres[b'nodesbyphase'][phase], ) # Write bookmark updates. @@ -187,7 +192,10 @@ def _fetchrawstorefiles(repo, remote): with remote.commandexecutor() as e: objs = e.callcommand( - b'rawstorefiledata', {b'files': [b'changelog', b'manifestlog'],} + b'rawstorefiledata', + { + b'files': [b'changelog', b'manifestlog'], + }, ).result() # First object is a summary of files data that follows. @@ -343,16 +351,21 @@ ) manifestnodes = {} + added = [] def linkrev(node): repo.ui.debug(b'add changeset %s\n' % short(node)) # Linkrev for changelog is always self. return len(cl) + def ondupchangeset(cl, node): + added.append(node) + def onchangeset(cl, node): progress.increment() revision = cl.changelogrevision(node) + added.append(node) # We need to preserve the mapping of changelog revision to node # so we can set the linkrev accordingly when manifests are added. @@ -403,8 +416,12 @@ 0, ) - added = cl.addgroup( - iterrevisions(), linkrev, weakref.proxy(tr), addrevisioncb=onchangeset + cl.addgroup( + iterrevisions(), + linkrev, + weakref.proxy(tr), + addrevisioncb=onchangeset, + duplicaterevisioncb=ondupchangeset, ) progress.complete() @@ -516,12 +533,15 @@ # Chomp off header object. next(objs) - added.extend( - rootmanifest.addgroup( - iterrevisions(objs, progress), - linkrevs.__getitem__, - weakref.proxy(tr), - ) + def onchangeset(cl, node): + added.append(node) + + rootmanifest.addgroup( + iterrevisions(objs, progress), + linkrevs.__getitem__, + weakref.proxy(tr), + addrevisioncb=onchangeset, + duplicaterevisioncb=onchangeset, ) progress.complete() @@ -732,7 +752,10 @@ with remote.commandexecutor() as e: args = { b'revisions': [ - {b'type': b'changesetexplicit', b'nodes': batch,} + { + b'type': b'changesetexplicit', + b'nodes': batch, + } ], b'fields': fields, b'haveparents': haveparents,
--- a/mercurial/extensions.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/extensions.py Thu Dec 03 14:15:39 2020 -0500 @@ -457,7 +457,7 @@ def afterloaded(extension, callback): - '''Run the specified function after a named extension is loaded. + """Run the specified function after a named extension is loaded. If the named extension is already loaded, the callback will be called immediately. @@ -467,7 +467,7 @@ The callback receives the named argument ``loaded``, which is a boolean indicating whether the dependent extension actually loaded. - ''' + """ if extension in _extensions: # Report loaded as False if the extension is disabled @@ -500,12 +500,12 @@ def bind(func, *args): - '''Partial function application + """Partial function application - Returns a new function that is the partial application of args and kwargs - to func. For example, + Returns a new function that is the partial application of args and kwargs + to func. For example, - f(1, 2, bar=3) === bind(f, 1)(2, bar=3)''' + f(1, 2, bar=3) === bind(f, 1)(2, bar=3)""" assert callable(func) def closure(*a, **kw): @@ -618,7 +618,7 @@ def wrapfunction(container, funcname, wrapper): - '''Wrap the function named funcname in container + """Wrap the function named funcname in container Replace the funcname member in the given container with the specified wrapper. The container is typically a module, class, or instance. @@ -649,7 +649,7 @@ work. Since you cannot control what other extensions are loaded by your end users, you should play nicely with others by using the subclass trick. - ''' + """ assert callable(wrapper) origfn = getattr(container, funcname) @@ -668,7 +668,7 @@ def unwrapfunction(container, funcname, wrapper=None): - '''undo wrapfunction + """undo wrapfunction If wrappers is None, undo the last wrap. Otherwise removes the wrapper from the chain of wrappers. @@ -676,7 +676,7 @@ Return the removed wrapper. Raise IndexError if wrapper is None and nothing to unwrap; ValueError if wrapper is not None but is not found in the wrapper chain. - ''' + """ chain = getwrapperchain(container, funcname) origfn = chain.pop() if wrapper is None: @@ -689,13 +689,13 @@ def getwrapperchain(container, funcname): - '''get a chain of wrappers of a function + """get a chain of wrappers of a function Return a list of functions: [newest wrapper, ..., oldest wrapper, origfunc] The wrapper functions are the ones passed to wrapfunction, whose first argument is origfunc. - ''' + """ result = [] fn = getattr(container, funcname) while fn: @@ -744,11 +744,11 @@ def _moduledoc(file): - '''return the top-level python documentation for the given file + """return the top-level python documentation for the given file Loosely inspired by pydoc.source_synopsis(), but rewritten to handle triple quotes and to return the whole text instead of just - the synopsis''' + the synopsis""" result = [] line = file.readline() @@ -883,8 +883,8 @@ def disabledcmd(ui, cmd, strict=False): - '''find cmd from disabled extensions without importing. - returns (cmdname, extname, doc)''' + """find cmd from disabled extensions without importing. + returns (cmdname, extname, doc)""" paths = _disabledpaths() if not paths:
--- a/mercurial/exthelper.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/exthelper.py Thu Dec 03 14:15:39 2020 -0500 @@ -53,29 +53,29 @@ revsetpredicate = eh.revsetpredicate templatekeyword = eh.templatekeyword - @eh.command('mynewcommand', - [('r', 'rev', [], _('operate on these revisions'))], - _('-r REV...'), + @eh.command(b'mynewcommand', + [(b'r', b'rev', [], _(b'operate on these revisions'))], + _(b'-r REV...'), helpcategory=command.CATEGORY_XXX) def newcommand(ui, repo, *revs, **opts): # implementation goes here - eh.configitem('experimental', 'foo', + eh.configitem(b'experimental', b'foo', default=False, ) - @eh.filesetpredicate('lfs()') + @eh.filesetpredicate(b'lfs()') def filesetbabar(mctx, x): return mctx.predicate(...) - @eh.revsetpredicate('hidden') + @eh.revsetpredicate(b'hidden') def revsetbabar(repo, subset, x): - args = revset.getargs(x, 0, 0, 'babar accept no argument') - return [r for r in subset if 'babar' in repo[r].description()] + args = revset.getargs(x, 0, 0, b'babar accept no argument') + return [r for r in subset if b'babar' in repo[r].description()] - @eh.templatekeyword('babar') + @eh.templatekeyword(b'babar') def kwbabar(ctx): - return 'babar' + return b'babar' """ def __init__(self): @@ -160,7 +160,7 @@ The following operations belong here: - Changes depending on the status of other extensions. (if - extensions.find('mq')) + extensions.find(b'mq')) - Add a global option to all commands """ knownexts = {} @@ -203,7 +203,7 @@ @eh.uisetup def setupbabar(ui): - print 'this is uisetup!' + print('this is uisetup!') """ self._uicallables.append(call) return call @@ -215,7 +215,7 @@ @eh.uipopulate def setupfoo(ui): - print 'this is uipopulate!' + print('this is uipopulate!') """ self._uipopulatecallables.append(call) return call @@ -227,7 +227,7 @@ @eh.extsetup def setupcelestine(ui): - print 'this is extsetup!' + print('this is extsetup!') """ self._extcallables.append(call) return call @@ -239,7 +239,7 @@ @eh.reposetup def setupzephir(ui, repo): - print 'this is reposetup!' + print('this is reposetup!') """ self._repocallables.append(call) return call @@ -258,9 +258,9 @@ example:: - @eh.wrapcommand('summary') + @eh.wrapcommand(b'summary') def wrapsummary(orig, ui, repo, *args, **kwargs): - ui.note('Barry!') + ui.note(b'Barry!') return orig(ui, repo, *args, **kwargs) The `opts` argument allows specifying a list of tuples for additional @@ -298,9 +298,9 @@ example:: - @eh.function(discovery, 'checkheads') + @eh.function(discovery, b'checkheads') def wrapfunction(orig, *args, **kwargs): - ui.note('His head smashed in and his heart cut out') + ui.note(b'His head smashed in and his heart cut out') return orig(*args, **kwargs) """
--- a/mercurial/fancyopts.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/fancyopts.py Thu Dec 03 14:15:39 2020 -0500 @@ -380,7 +380,7 @@ else: def abort(s): - raise error.Abort( + raise error.InputError( _(b'invalid value %r for option %s, %s') % (pycompat.maybebytestr(val), opt, s) )
--- a/mercurial/filelog.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/filelog.py Thu Dec 03 14:15:39 2020 -0500 @@ -139,6 +139,7 @@ linkmapper, transaction, addrevisioncb=None, + duplicaterevisioncb=None, maybemissingparents=False, ): if maybemissingparents: @@ -150,7 +151,11 @@ ) return self._revlog.addgroup( - deltas, linkmapper, transaction, addrevisioncb=addrevisioncb + deltas, + linkmapper, + transaction, + addrevisioncb=addrevisioncb, + duplicaterevisioncb=duplicaterevisioncb, ) def getstrippoint(self, minlink):
--- a/mercurial/filemerge.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/filemerge.py Thu Dec 03 14:15:39 2020 -0500 @@ -643,7 +643,7 @@ def _describemerge(ui, repo, mynode, fcl, fcb, fco, env, toolpath, args): - tmpl = ui.config(b'ui', b'pre-merge-tool-output-template') + tmpl = ui.config(b'command-templates', b'pre-merge-tool-output') if not tmpl: return @@ -831,7 +831,7 @@ ca = fca.changectx() ui = repo.ui - template = ui.config(b'ui', b'mergemarkertemplate') + template = ui.config(b'command-templates', b'mergemarker') if tool is not None: template = _toolstr(ui, tool, b'mergemarkertemplate', template) template = templater.unquotestring(template) @@ -1100,7 +1100,7 @@ labeltool = None if markerstyle != b'basic': # respect 'tool's mergemarkertemplate (which defaults to - # ui.mergemarkertemplate) + # command-templates.mergemarker) labeltool = tool if internalmarkerstyle != b'basic' or markerstyle != b'basic': premergelabels = _formatlabels( @@ -1232,8 +1232,7 @@ def loadinternalmerge(ui, extname, registrarobj): - """Load internal merge tool from specified registrarobj - """ + """Load internal merge tool from specified registrarobj""" for name, func in pycompat.iteritems(registrarobj._table): fullname = b':' + name internals[fullname] = func
--- a/mercurial/fileset.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/fileset.py Thu Dec 03 14:15:39 2020 -0500 @@ -122,8 +122,7 @@ @predicate(b'modified()', callstatus=True, weight=_WEIGHT_STATUS) def modified(mctx, x): - """File that is modified according to :hg:`status`. - """ + """File that is modified according to :hg:`status`.""" # i18n: "modified" is a keyword getargs(x, 0, 0, _(b"modified takes no arguments")) s = set(mctx.status().modified) @@ -132,8 +131,7 @@ @predicate(b'added()', callstatus=True, weight=_WEIGHT_STATUS) def added(mctx, x): - """File that is added according to :hg:`status`. - """ + """File that is added according to :hg:`status`.""" # i18n: "added" is a keyword getargs(x, 0, 0, _(b"added takes no arguments")) s = set(mctx.status().added) @@ -142,8 +140,7 @@ @predicate(b'removed()', callstatus=True, weight=_WEIGHT_STATUS) def removed(mctx, x): - """File that is removed according to :hg:`status`. - """ + """File that is removed according to :hg:`status`.""" # i18n: "removed" is a keyword getargs(x, 0, 0, _(b"removed takes no arguments")) s = set(mctx.status().removed) @@ -152,8 +149,7 @@ @predicate(b'deleted()', callstatus=True, weight=_WEIGHT_STATUS) def deleted(mctx, x): - """Alias for ``missing()``. - """ + """Alias for ``missing()``.""" # i18n: "deleted" is a keyword getargs(x, 0, 0, _(b"deleted takes no arguments")) s = set(mctx.status().deleted) @@ -162,8 +158,7 @@ @predicate(b'missing()', callstatus=True, weight=_WEIGHT_STATUS) def missing(mctx, x): - """File that is missing according to :hg:`status`. - """ + """File that is missing according to :hg:`status`.""" # i18n: "missing" is a keyword getargs(x, 0, 0, _(b"missing takes no arguments")) s = set(mctx.status().deleted) @@ -190,8 +185,7 @@ @predicate(b'clean()', callstatus=True, weight=_WEIGHT_STATUS) def clean(mctx, x): - """File that is clean according to :hg:`status`. - """ + """File that is clean according to :hg:`status`.""" # i18n: "clean" is a keyword getargs(x, 0, 0, _(b"clean takes no arguments")) s = set(mctx.status().clean) @@ -208,8 +202,7 @@ @predicate(b'binary()', weight=_WEIGHT_READ_CONTENTS) def binary(mctx, x): - """File that appears to be binary (contains NUL bytes). - """ + """File that appears to be binary (contains NUL bytes).""" # i18n: "binary" is a keyword getargs(x, 0, 0, _(b"binary takes no arguments")) return mctx.fpredicate( @@ -219,8 +212,7 @@ @predicate(b'exec()') def exec_(mctx, x): - """File that is marked as executable. - """ + """File that is marked as executable.""" # i18n: "exec" is a keyword getargs(x, 0, 0, _(b"exec takes no arguments")) ctx = mctx.ctx @@ -229,8 +221,7 @@ @predicate(b'symlink()') def symlink(mctx, x): - """File that is marked as a symlink. - """ + """File that is marked as a symlink.""" # i18n: "symlink" is a keyword getargs(x, 0, 0, _(b"symlink takes no arguments")) ctx = mctx.ctx @@ -239,8 +230,7 @@ @predicate(b'resolved()', weight=_WEIGHT_STATUS) def resolved(mctx, x): - """File that is marked resolved according to :hg:`resolve -l`. - """ + """File that is marked resolved according to :hg:`resolve -l`.""" # i18n: "resolved" is a keyword getargs(x, 0, 0, _(b"resolved takes no arguments")) if mctx.ctx.rev() is not None: @@ -253,8 +243,7 @@ @predicate(b'unresolved()', weight=_WEIGHT_STATUS) def unresolved(mctx, x): - """File that is marked unresolved according to :hg:`resolve -l`. - """ + """File that is marked unresolved according to :hg:`resolve -l`.""" # i18n: "unresolved" is a keyword getargs(x, 0, 0, _(b"unresolved takes no arguments")) if mctx.ctx.rev() is not None: @@ -267,8 +256,7 @@ @predicate(b'hgignore()', weight=_WEIGHT_STATUS) def hgignore(mctx, x): - """File that matches the active .hgignore pattern. - """ + """File that matches the active .hgignore pattern.""" # i18n: "hgignore" is a keyword getargs(x, 0, 0, _(b"hgignore takes no arguments")) return mctx.ctx.repo().dirstate._ignore @@ -288,8 +276,7 @@ @predicate(b'grep(regex)', weight=_WEIGHT_READ_CONTENTS) def grep(mctx, x): - """File contains the given regular expression. - """ + """File contains the given regular expression.""" try: # i18n: "grep" is a keyword r = re.compile(getstring(x, _(b"grep requires a pattern"))) @@ -414,8 +401,7 @@ @predicate(b'copied()') def copied(mctx, x): - """File that is recorded as being copied. - """ + """File that is recorded as being copied.""" # i18n: "copied" is a keyword getargs(x, 0, 0, _(b"copied takes no arguments")) @@ -476,8 +462,7 @@ @predicate(b'subrepo([pattern])') def subrepo(mctx, x): - """Subrepositories whose paths match the given pattern. - """ + """Subrepositories whose paths match the given pattern.""" # i18n: "subrepo" is a keyword getargs(x, 0, 1, _(b"subrepo takes at most one argument")) ctx = mctx.ctx @@ -628,8 +613,7 @@ def loadpredicate(ui, extname, registrarobj): - """Load fileset predicates from specified registrarobj - """ + """Load fileset predicates from specified registrarobj""" for name, func in pycompat.iteritems(registrarobj._table): symbols[name] = func
--- a/mercurial/hbisect.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/hbisect.py Thu Dec 03 14:15:39 2020 -0500 @@ -172,13 +172,13 @@ def checkstate(state): """check we have both 'good' and 'bad' to define a range - Raise Abort exception otherwise.""" + Raise StateError exception otherwise.""" if state[b'good'] and state[b'bad']: return True if not state[b'good']: - raise error.Abort(_(b'cannot bisect (no known good revisions)')) + raise error.StateError(_(b'cannot bisect (no known good revisions)')) else: - raise error.Abort(_(b'cannot bisect (no known bad revisions)')) + raise error.StateError(_(b'cannot bisect (no known bad revisions)')) @contextlib.contextmanager
--- a/mercurial/help.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/help.py Thu Dec 03 14:15:39 2020 -0500 @@ -698,10 +698,10 @@ fullname=None, **opts ): - ''' + """ Generate the help for 'name' as unformatted restructured text. If 'name' is None, describe the commands available. - ''' + """ opts = pycompat.byteskwargs(opts)
--- a/mercurial/helptext/config.txt Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/helptext/config.txt Thu Dec 03 14:15:39 2020 -0500 @@ -54,6 +54,7 @@ On Unix, the following files are consulted: + - ``<repo>/.hg/hgrc-not-shared`` (per-repository) - ``<repo>/.hg/hgrc`` (per-repository) - ``$HOME/.hgrc`` (per-user) - ``${XDG_CONFIG_HOME:-$HOME/.config}/hg/hgrc`` (per-user) @@ -67,6 +68,7 @@ On Windows, the following files are consulted: + - ``<repo>/.hg/hgrc-not-shared`` (per-repository) - ``<repo>/.hg/hgrc`` (per-repository) - ``%USERPROFILE%\.hgrc`` (per-user) - ``%USERPROFILE%\Mercurial.ini`` (per-user) @@ -89,6 +91,7 @@ On Plan9, the following files are consulted: + - ``<repo>/.hg/hgrc-not-shared`` (per-repository) - ``<repo>/.hg/hgrc`` (per-repository) - ``$home/lib/hgrc`` (per-user) - ``<install-root>/lib/mercurial/hgrc`` (per-installation) @@ -144,6 +147,15 @@ merge tool configuration but packagers can also put other default configuration there. +.. container:: verbose + + On versions 5.7 and later, if share-safe functionality is enabled, + shares will read config file of share source too. + `<share-source/.hg/hgrc>` is read before reading `<repo/.hg/hgrc>`. + + For configs which should not be shared, `<repo/.hg/hgrc-not-shared>` + should be used. + Syntax ====== @@ -1549,11 +1561,11 @@ (default: ``basic``) ``mergemarkertemplate`` - This setting can be used to override ``mergemarkertemplate`` from the ``[ui]`` - section on a per-tool basis; this applies to the ``$label``-prefixed variables - and to the conflict markers that are generated if ``premerge`` is ``keep` or - ``keep-merge3``. See the corresponding variable in ``[ui]`` for more - information. + This setting can be used to override ``mergemarker`` from the + ``[command-templates]`` section on a per-tool basis; this applies to the + ``$label``-prefixed variables and to the conflict markers that are generated + if ``premerge`` is ``keep` or ``keep-merge3``. See the corresponding variable + in ``[ui]`` for more information. .. container:: windows @@ -2334,8 +2346,7 @@ UTF-8. (default: ISO-8859-1) ``graphnodetemplate`` - The template used to print changeset nodes in an ASCII revision graph. - (default: ``{graphnode}``) + (DEPRECATED) Use ``command-templates.graphnode`` instead. ``ignore`` A file to read per-user ignore patterns from. This file should be @@ -2363,7 +2374,7 @@ (default: 10000000) ``logtemplate`` - Template string for commands that print changesets. + (DEPRECATED) Use ``command-templates.log`` instead. ``merge`` The conflict resolution program to use during a manual merge. @@ -2371,29 +2382,14 @@ For configuring merge tools see the ``[merge-tools]`` section. ``mergemarkers`` - Sets the merge conflict marker label styling. The ``detailed`` - style uses the ``mergemarkertemplate`` setting to style the labels. + Sets the merge conflict marker label styling. The ``detailed`` style + uses the ``command-templates.mergemarker`` setting to style the labels. The ``basic`` style just uses 'local' and 'other' as the marker label. One of ``basic`` or ``detailed``. (default: ``basic``) ``mergemarkertemplate`` - The template used to print the commit description next to each conflict - marker during merge conflicts. See :hg:`help templates` for the template - format. - - Defaults to showing the hash, tags, branches, bookmarks, author, and - the first line of the commit description. - - If you use non-ASCII characters in names for tags, branches, bookmarks, - authors, and/or commit descriptions, you must pay attention to encodings of - managed files. At template expansion, non-ASCII characters use the encoding - specified by the ``--encoding`` global option, ``HGENCODING`` or other - environment variables that govern your locale. If the encoding of the merge - markers is different from the encoding of the merged files, - serious problems may occur. - - Can be overridden per-merge-tool, see the ``[merge-tools]`` section. + (DEPRECATED) Use ``command-templates.mergemarker`` instead. ``message-output`` Where to write status and error messages. (default: ``stdio``) @@ -2456,14 +2452,7 @@ On Windows, this configuration option is ignored and the command aborted. ``pre-merge-tool-output-template`` - A template that is printed before executing an external merge tool. This can - be used to print out additional context that might be useful to have during - the conflict resolution, such as the description of the various commits - involved or bookmarks/tags. - - Additional information is available in the ``local`, ``base``, and ``other`` - dicts. For example: ``{local.label}``, ``{base.name}``, or - ``{other.islink}``. + (DEPRECATED) Use ``command-template.pre-merge-tool-output`` instead. ``quiet`` Reduce the amount of output printed. @@ -2561,6 +2550,55 @@ Increase the amount of output printed. (default: False) +``command-templates`` +--------------------- + +Templates used for customizing the output of commands. + +``graphnode`` + The template used to print changeset nodes in an ASCII revision graph. + (default: ``{graphnode}``) + +``log`` + Template string for commands that print changesets. + +``mergemarker`` + The template used to print the commit description next to each conflict + marker during merge conflicts. See :hg:`help templates` for the template + format. + + Defaults to showing the hash, tags, branches, bookmarks, author, and + the first line of the commit description. + + If you use non-ASCII characters in names for tags, branches, bookmarks, + authors, and/or commit descriptions, you must pay attention to encodings of + managed files. At template expansion, non-ASCII characters use the encoding + specified by the ``--encoding`` global option, ``HGENCODING`` or other + environment variables that govern your locale. If the encoding of the merge + markers is different from the encoding of the merged files, + serious problems may occur. + + Can be overridden per-merge-tool, see the ``[merge-tools]`` section. + +``oneline-summary`` + A template used by `hg rebase` and other commands for showing a one-line + summary of a commit. If the template configured here is longer than one + line, then only the first line is used. + + The template can be overridden per command by defining a template in + `oneline-summary.<command>`, where `<command>` can be e.g. "rebase". + +``pre-merge-tool-output`` + A template that is printed before executing an external merge tool. This can + be used to print out additional context that might be useful to have during + the conflict resolution, such as the description of the various commits + involved or bookmarks/tags. + + Additional information is available in the ``local`, ``base``, and ``other`` + dicts. For example: ``{local.label}``, ``{base.name}``, or + ``{other.islink}``. + + ``web`` -------
--- a/mercurial/helptext/dates.txt Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/helptext/dates.txt Thu Dec 03 14:15:39 2020 -0500 @@ -36,4 +36,4 @@ - ``<DATE`` - at or before a given date/time - ``>DATE`` - on or after a given date/time - ``DATE to DATE`` - a date range, inclusive -- ``-DAYS`` - within a given number of days of today +- ``-DAYS`` - within a given number of days from today
--- a/mercurial/helptext/internals/extensions.txt Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/helptext/internals/extensions.txt Thu Dec 03 14:15:39 2020 -0500 @@ -24,7 +24,8 @@ To write your own extension, your python module can provide an optional dict named ``cmdtable`` with entries describing each command. A command should be -registered to the ``cmdtable`` by ``@command`` decorator. +registered to the ``cmdtable`` by ``@command`` decorator. All string-like +values must be the ``bytes`` type, and are thus prefixed with ``b``. Example using ``@command`` decorator (requires Mercurial 1.9):: @@ -39,10 +40,10 @@ from mercurial import cmdutil command = cmdutil.command(cmdtable) - @command('print-parents', - [('s', 'short', None, _('print short form')), - ('l', 'long', None, _('print long form'))], - _('[options] node')) + @command(b'print-parents', + [(b's', b'short', None, _(b'print short form')), + (b'l', b'long', None, _(b'print long form'))], + _(b'[options] node')) def printparents(ui, repo, node, **opts): ... @@ -84,7 +85,7 @@ ``repo`` passed, then ``norepo=True`` should be passed to the ``@command`` decorator:: - @command('mycommand', [], norepo=True) + @command(b'mycommand', [], norepo=True) def mycommand(ui, **opts): ... @@ -140,7 +141,7 @@ =========================== Besides the ``ui`` methods, like ``ui.write(*msg)`` or -``ui.prompt(msg, default="y")``, an extension can add help text for each +``ui.prompt(msg, default=b"y")``, an extension can add help text for each of its commands and the extension itself. The module docstring will be used as help string when ``hg help extensionname`` @@ -175,7 +176,7 @@ Be aware that ``uisetup`` in NOT the function to configure a ``ui`` instance. It's called only once per process, not per ``ui`` instance. Also, any changes -to the ``ui`` may be discarded because the ``ui`` here temporarily loaded +to the ``ui`` may be discarded because the ``ui`` here is a temporarily loaded local configuration. So, it's generally wrong to do `ui.setconfig()` in these callbacks. Notable exception is setting ``pre/post-<command>`` hooks and extending ``ui.__class__``. @@ -248,7 +249,7 @@ class echologui(ui.__class__): def log(self, service, *msg, **opts): if msg: - self.write('%s: %s\n' % (service, msg[0] % msg[1:])) + self.write(b'%s: %s\n' % (service, msg[0] % msg[1:])) super(echologui, self).log(service, *msg, **opts) ui.__class__ = echologui @@ -259,7 +260,7 @@ Some extensions must use hooks to do their work. These required hooks can be configured manually by the user by modifying the ``[hook]`` section of their hgrc, but they can also be configured automatically by calling the -``ui.setconfig('hooks', ...)`` function in one of the setup functions +``ui.setconfig(b'hooks', ...)`` function in one of the setup functions described above. The main difference between manually modifying the hooks section in the hgrc @@ -273,21 +274,21 @@ # Define hooks -- note that the actual function name it irrelevant. def preupdatehook(ui, repo, **kwargs): - ui.write("Pre-update hook triggered\n") + ui.write(b"Pre-update hook triggered\n") def updatehook(ui, repo, **kwargs): - ui.write("Update hook triggered\n") + ui.write(b"Update hook triggered\n") def uisetup(ui): # When pre-<cmd> and post-<cmd> hooks are configured by means of # the ui.setconfig() function, you must use the ui object passed # to uisetup or extsetup. - ui.setconfig("hooks", "pre-update.myextension", preupdatehook) + ui.setconfig(b"hooks", b"pre-update.myextension", preupdatehook) def reposetup(ui, repo): # Repository-specific hooks can be configured here. These include # the update hook. - ui.setconfig("hooks", "update.myextension", updatehook) + ui.setconfig(b"hooks", b"update.myextension", updatehook) Note how different hooks may need to be configured in different setup functions. In the example you can see that the ``update`` hook must be @@ -301,7 +302,7 @@ releases it's known to be compatible with. This helps us and users diagnose where problems are coming from:: - testedwith = '2.0 2.0.1 2.1 2.1.1 2.1.2' + testedwith = b'2.0 2.0.1 2.1 2.1.1 2.1.2' Do not use the ``internal`` marker in third-party extensions; we will immediately drop all bug reports mentioning your extension if we catch you @@ -311,16 +312,25 @@ should report issues with the extension. This link will be included in the error message if the extension produces errors:: - buglink = 'https://bitbucket.org/USER/REPO/issues' + buglink = b'https://bitbucket.org/USER/REPO/issues' If an extension requires a minimum version of Mercurial, it can be declared with the ``minimumhgversion`` variable:: - minimumhgversion = '4.6' + minimumhgversion = b'4.6' Older clients will print a warning that the extension requires a new version, instead of attempting to load it. +The extension itself can be assigned a version value through one of two module +attributes, and will be displayed in crash reports and :hg:`version -v`:: + + * ``__version__`` is a plain value + * ``getversion`` is a no argument ``Callable`` that returns a value + +In both cases, the value must be either a byte string, or a list or tuple of +numeric values which will be joined with ``.``. + Wrap up: what belongs where? ============================ @@ -347,7 +357,7 @@ extsetup -------- -* Changes depending on the status of other extensions. (``if extensions.find('mq')``) +* Changes depending on the status of other extensions. (``if extensions.find(b'mq')``) * Add a global option to all commands * Extend revsets
--- a/mercurial/helptext/internals/requirements.txt Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/helptext/internals/requirements.txt Thu Dec 03 14:15:39 2020 -0500 @@ -170,7 +170,7 @@ in ``.hg/``. Shares read the ``.hg/hgrc`` of the source repository. -Support for this requirement was added in Mercurial 5.6 (released -November 2020). The requirement will only be present on repositories that have +Support for this requirement was added in Mercurial 5.7 (released +February 2021). The requirement will only be present on repositories that have opted in to this format (by having ``format.exp-share-safe=true`` set when they were created).
--- a/mercurial/hg.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/hg.py Thu Dec 03 14:15:39 2020 -0500 @@ -243,7 +243,7 @@ def defaultdest(source): - '''return default destination of clone if none is given + """return default destination of clone if none is given >>> defaultdest(b'foo') 'foo' @@ -257,7 +257,7 @@ '' >>> defaultdest(b'http://example.org/foo/') 'foo' - ''' + """ path = util.url(source).path if not path: return b'' @@ -333,7 +333,7 @@ def _prependsourcehgrc(repo): - """ copies the source repo config and prepend it in current repo .hg/hgrc + """copies the source repo config and prepend it in current repo .hg/hgrc on unshare. This is only done if the share was perfomed using share safe method where we share config of source in shares""" srcvfs = vfsmod.vfs(repo.sharedpath) @@ -443,10 +443,10 @@ def copystore(ui, srcrepo, destpath): - '''copy files from store of srcrepo in destpath + """copy files from store of srcrepo in destpath returns destlock - ''' + """ destlock = None try: hardlink = None @@ -517,7 +517,12 @@ for r in rev: with srcpeer.commandexecutor() as e: remoterevs.append( - e.callcommand(b'lookup', {b'key': r,}).result() + e.callcommand( + b'lookup', + { + b'key': r, + }, + ).result() ) revs = remoterevs @@ -683,14 +688,14 @@ source = util.urllocalpath(source) if not dest: - raise error.Abort(_(b"empty destination path is not valid")) + raise error.InputError(_(b"empty destination path is not valid")) destvfs = vfsmod.vfs(dest, expandpath=True) if destvfs.lexists(): if not destvfs.isdir(): - raise error.Abort(_(b"destination '%s' already exists") % dest) + raise error.InputError(_(b"destination '%s' already exists") % dest) elif destvfs.listdir(): - raise error.Abort(_(b"destination '%s' is not empty") % dest) + raise error.InputError(_(b"destination '%s' is not empty") % dest) createopts = {} narrow = False @@ -751,7 +756,10 @@ try: with srcpeer.commandexecutor() as e: rootnode = e.callcommand( - b'lookup', {b'key': b'0',} + b'lookup', + { + b'key': b'0', + }, ).result() if rootnode != node.nullid: @@ -900,7 +908,12 @@ for rev in revs: with srcpeer.commandexecutor() as e: remoterevs.append( - e.callcommand(b'lookup', {b'key': rev,}).result() + e.callcommand( + b'lookup', + { + b'key': rev, + }, + ).result() ) revs = remoterevs @@ -974,7 +987,10 @@ if update is not True: with srcpeer.commandexecutor() as e: checkout = e.callcommand( - b'lookup', {b'key': update,} + b'lookup', + { + b'key': update, + }, ).result() uprev = None @@ -1176,7 +1192,10 @@ def merge( - ctx, force=False, remind=True, labels=None, + ctx, + force=False, + remind=True, + labels=None, ): """Branch merge with node, resolving changes. Return true if any unresolved conflicts."""
--- a/mercurial/hgweb/__init__.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/hgweb/__init__.py Thu Dec 03 14:15:39 2020 -0500 @@ -27,7 +27,7 @@ def hgweb(config, name=None, baseui=None): - '''create an hgweb wsgi object + """create an hgweb wsgi object config can be one of: - repo object (single repo view) @@ -35,7 +35,7 @@ - path to config file (multi-repo view) - dict of virtual:real pairs (multi-repo view) - list of virtual:real tuples (multi-repo view) - ''' + """ if isinstance(config, pycompat.unicode): raise error.ProgrammingError(
--- a/mercurial/hgweb/common.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/hgweb/common.py Thu Dec 03 14:15:39 2020 -0500 @@ -51,9 +51,9 @@ def checkauthz(hgweb, req, op): - '''Check permission for operation based on request data (including + """Check permission for operation based on request data (including authentication info). Return if op allowed, else raise an ErrorResponse - exception.''' + exception.""" user = req.remoteuser
--- a/mercurial/hgweb/hgweb_mod.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/hgweb/hgweb_mod.py Thu Dec 03 14:15:39 2020 -0500 @@ -86,12 +86,12 @@ def makebreadcrumb(url, prefix=b''): - '''Return a 'URL breadcrumb' list + """Return a 'URL breadcrumb' list A 'URL breadcrumb' is a list of URL-name pairs, corresponding to each of the path items on a URL. This can be used to create path navigation entries. - ''' + """ if url.endswith(b'/'): url = url[:-1] if prefix:
--- a/mercurial/hgweb/request.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/hgweb/request.py Thu Dec 03 14:15:39 2020 -0500 @@ -622,8 +622,8 @@ def wsgiapplication(app_maker): - '''For compatibility with old CGI scripts. A plain hgweb() or hgwebdir() - can and should now be used as a WSGI application.''' + """For compatibility with old CGI scripts. A plain hgweb() or hgwebdir() + can and should now be used as a WSGI application.""" application = app_maker() def run_wsgi(env, respond):
--- a/mercurial/hgweb/webutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/hgweb/webutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -491,11 +491,11 @@ def changelistentry(web, ctx): - '''Obtain a dictionary to be used for entries in a changelist. + """Obtain a dictionary to be used for entries in a changelist. This function is called when producing items for the "entries" list passed to the "shortlog" and "changelog" templates. - ''' + """ repo = web.repo rev = ctx.rev() n = scmutil.binnode(ctx)
--- a/mercurial/hook.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/hook.py Thu Dec 03 14:15:39 2020 -0500 @@ -30,14 +30,14 @@ def pythonhook(ui, repo, htype, hname, funcname, args, throw): - '''call python hook. hook is callable object, looked up as + """call python hook. hook is callable object, looked up as name in python module. if callable returns "true", hook fails, else passes. if hook raises exception, treated as hook failure. exception propagates if throw is "true". reason for "true" meaning "hook failed" is so that unmodified commands (e.g. mercurial.commands.update) can - be run as hooks without wrappers to convert return values.''' + be run as hooks without wrappers to convert return values.""" if callable(funcname): obj = funcname
--- a/mercurial/httppeer.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/httppeer.py Thu Dec 03 14:15:39 2020 -0500 @@ -766,7 +766,10 @@ % _(b', ').join(sorted(permissions)) ) - permission = {b'push': b'rw', b'pull': b'ro',}[permissions.pop()] + permission = { + b'push': b'rw', + b'pull': b'ro', + }[permissions.pop()] handler, resp = sendv2request( self._ui, @@ -942,7 +945,10 @@ # Integer priority for the service. If we could choose from multiple # services, we choose the one with the highest priority. API_PEERS = { - wireprototypes.HTTP_WIREPROTO_V2: {b'init': httpv2peer, b'priority': 50,}, + wireprototypes.HTTP_WIREPROTO_V2: { + b'init': httpv2peer, + b'priority': 50, + }, }
--- a/mercurial/interfaces/dirstate.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/interfaces/dirstate.py Thu Dec 03 14:15:39 2020 -0500 @@ -9,12 +9,12 @@ class idirstate(interfaceutil.Interface): def __init__(opener, ui, root, validate, sparsematchfn): - '''Create a new dirstate object. + """Create a new dirstate object. opener is an open()-like callable that can be used to open the dirstate file; root is the root of the directory tracked by the dirstate. - ''' + """ # TODO: all these private methods and attributes should be made # public or removed from the interface. @@ -31,17 +31,17 @@ @contextlib.contextmanager def parentchange(): - '''Context manager for handling dirstate parents. + """Context manager for handling dirstate parents. If an exception occurs in the scope of the context manager, the incoherent dirstate won't be written when wlock is released. - ''' + """ def pendingparentchange(): - '''Returns true if the dirstate is in the middle of a set of changes + """Returns true if the dirstate is in the middle of a set of changes that modify the dirstate parent. - ''' + """ def hasdir(d): pass @@ -50,18 +50,18 @@ pass def getcwd(): - '''Return the path from which a canonical path is calculated. + """Return the path from which a canonical path is calculated. This path should be used to resolve file patterns or to convert canonical paths back to file paths for display. It shouldn't be used to get real file paths. Use vfs functions instead. - ''' + """ def pathto(f, cwd=None): pass def __getitem__(key): - '''Return the current state of key (a filename) in the dirstate. + """Return the current state of key (a filename) in the dirstate. States are: n normal @@ -69,7 +69,7 @@ r marked for removal a marked for addition ? not tracked - ''' + """ def __contains__(key): """Check if bytestring `key` is known to the dirstate.""" @@ -111,11 +111,11 @@ pass def invalidate(): - '''Causes the next access to reread the dirstate. + """Causes the next access to reread the dirstate. This is different from localrepo.invalidatedirstate() because it always rereads the dirstate. Use localrepo.invalidatedirstate() if you want to - check whether the dirstate has changed before rereading it.''' + check whether the dirstate has changed before rereading it.""" def copy(source, dest): """Mark dest as a copy of source. Unmark dest if source is None.""" @@ -127,7 +127,7 @@ pass def normal(f, parentfiledata=None): - '''Mark a file normal and clean. + """Mark a file normal and clean. parentfiledata: (mode, size, mtime) of the clean file @@ -135,7 +135,7 @@ size), as or close as possible from the point where we determined the file was clean, to limit the risk of the file having been changed by an external process between the - moment where the file was determined to be clean and now.''' + moment where the file was determined to be clean and now.""" pass def normallookup(f): @@ -157,7 +157,7 @@ '''Drop a file from the dirstate''' def normalize(path, isknown=False, ignoremissing=False): - ''' + """ normalize the case of a pathname when on a casefolding filesystem isknown specifies whether the filename came from walking the @@ -172,7 +172,7 @@ - version of name already stored in the dirstate - version of name stored on disk - version provided via command arguments - ''' + """ def clear(): pass @@ -181,11 +181,11 @@ pass def identity(): - '''Return identity of dirstate it to detect changing in storage + """Return identity of dirstate it to detect changing in storage If identity of previous dirstate is equal to this, writing changes based on the former dirstate out can keep consistency. - ''' + """ def write(tr): pass @@ -201,7 +201,7 @@ """ def walk(match, subrepos, unknown, ignored, full=True): - ''' + """ Walk recursively through the directory tree, finding all files matched by match. @@ -210,10 +210,10 @@ Return a dict mapping filename to stat-like object (either mercurial.osutil.stat instance or return value of os.stat()). - ''' + """ def status(match, subrepos, ignored, clean, unknown): - '''Determine the status of the working copy relative to the + """Determine the status of the working copy relative to the dirstate and return a pair of (unsure, status), where status is of type scmutil.status and: @@ -227,12 +227,12 @@ status.clean: files that have definitely not been modified since the dirstate was written - ''' + """ def matches(match): - ''' + """ return files in the dirstate (in whatever state) filtered by match - ''' + """ def savebackup(tr, backupname): '''Save current dirstate into backup file'''
--- a/mercurial/interfaces/repository.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/interfaces/repository.py Thu Dec 03 14:15:39 2020 -0500 @@ -617,7 +617,7 @@ """ def revision(node, raw=False): - """"Obtain fulltext data for a node. + """Obtain fulltext data for a node. By default, any storage transformations are applied before the data is returned. If ``raw`` is True, non-raw storage transformations @@ -628,8 +628,7 @@ """ def rawdata(node): - """Obtain raw data for a node. - """ + """Obtain raw data for a node.""" def read(node): """Resolve file fulltext data. @@ -756,6 +755,7 @@ linkmapper, transaction, addrevisioncb=None, + duplicaterevisioncb=None, maybemissingparents=False, ): """Process a series of deltas for storage. @@ -1247,7 +1247,13 @@ See the documentation for ``ifiledata`` for more. """ - def addgroup(deltas, linkmapper, transaction, addrevisioncb=None): + def addgroup( + deltas, + linkmapper, + transaction, + addrevisioncb=None, + duplicaterevisioncb=None, + ): """Process a series of deltas for storage. See the documentation in ``ifilemutation`` for more.
--- a/mercurial/keepalive.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/keepalive.py Thu Dec 03 14:15:39 2020 -0500 @@ -112,7 +112,7 @@ """ The connection manager must be able to: * keep track of all existing - """ + """ def __init__(self): self._lock = threading.Lock() @@ -675,8 +675,7 @@ def wrapgetresponse(cls): - """Wraps getresponse in cls with a broken-pipe sane version. - """ + """Wraps getresponse in cls with a broken-pipe sane version.""" def safegetresponse(self): # In safesend() we might set the _broken_pipe_resp
--- a/mercurial/localrepo.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/localrepo.py Thu Dec 03 14:15:39 2020 -0500 @@ -31,6 +31,7 @@ bookmarks, branchmap, bundle2, + bundlecaches, changegroup, color, commit, @@ -95,8 +96,7 @@ class _basefilecache(scmutil.filecache): - """All filecache usage on repo are done for logic that should be unfiltered - """ + """All filecache usage on repo are done for logic that should be unfiltered""" def __get__(self, repo, type=None): if repo is None: @@ -299,7 +299,7 @@ return self._caps def clonebundles(self): - return self._repo.tryread(b'clonebundles.manifest') + return self._repo.tryread(bundlecaches.CB_MANIFEST_FILE) def debugwireargs(self, one, two, three=None, four=None, five=None): """Used to test argument passing over the wire""" @@ -399,8 +399,8 @@ @interfaceutil.implementer(repository.ipeerlegacycommands) class locallegacypeer(localpeer): - '''peer extension which implements legacy methods too; used for tests with - restricted capabilities''' + """peer extension which implements legacy methods too; used for tests with + restricted capabilities""" def __init__(self, repo): super(locallegacypeer, self).__init__(repo, caps=legacycaps) @@ -439,7 +439,7 @@ def _getsharedvfs(hgvfs, requirements): - """ returns the vfs object pointing to root of shared source + """returns the vfs object pointing to root of shared source repo for a shared repository hgvfs is vfs pointing at .hg/ of current repo (shared one) @@ -464,7 +464,7 @@ def _readrequires(vfs, allowmissing): - """ reads the require file present at root of this vfs + """reads the require file present at root of this vfs and return a set of requirements If allowmissing is True, we suppress ENOENT if raised""" @@ -557,7 +557,22 @@ # NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement # is present. We never write SHARESAFE_REQUIREMENT for a repo if store # is not present, refer checkrequirementscompat() for that + # + # However, if SHARESAFE_REQUIREMENT is not present, it means that the + # repository was shared the old way. We check the share source .hg/requires + # for SHARESAFE_REQUIREMENT to detect whether the current repository needs + # to be reshared if requirementsmod.SHARESAFE_REQUIREMENT in requirements: + + if ( + shared + and requirementsmod.SHARESAFE_REQUIREMENT + not in _readrequires(sharedvfs, True) + ): + raise error.Abort( + _(b"share source does not support exp-sharesafe requirement") + ) + if shared: # This is a shared repo storevfs = vfsmod.vfs(sharedvfs.join(b'store')) @@ -565,6 +580,15 @@ storevfs = vfsmod.vfs(hgvfs.join(b'store')) requirements |= _readrequires(storevfs, False) + elif shared: + sourcerequires = _readrequires(sharedvfs, False) + if requirementsmod.SHARESAFE_REQUIREMENT in sourcerequires: + ui.warn( + _( + b'warning: source repository supports share-safe functionality.' + b' Reshare to upgrade.\n' + ) + ) # The .hg/hgrc file may load extensions or contain config options # that influence repository construction. Attempt to load it and @@ -715,18 +739,28 @@ if not rcutil.use_repo_hgrc(): return False + ret = False # first load config from shared source if we has to if requirementsmod.SHARESAFE_REQUIREMENT in requirements and sharedvfs: try: ui.readconfig(sharedvfs.join(b'hgrc'), root=sharedvfs.base) + ret = True except IOError: pass try: ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base) - return True + ret = True except IOError: - return False + pass + + try: + ui.readconfig(hgvfs.join(b'hgrc-not-shared'), root=wdirvfs.base) + ret = True + except IOError: + pass + + return ret def afterhgrcload(ui, wdirvfs, hgvfs, requirements): @@ -1745,7 +1779,7 @@ return iter(self.changelog) def revs(self, expr, *args): - '''Find revisions matching a revset. + """Find revisions matching a revset. The revset is specified as a string ``expr`` that may contain %-formatting to escape certain types. See ``revsetlang.formatspec``. @@ -1756,30 +1790,30 @@ Returns a smartset.abstractsmartset, which is a list-like interface that contains integer revisions. - ''' + """ tree = revsetlang.spectree(expr, *args) return revset.makematcher(tree)(self) def set(self, expr, *args): - '''Find revisions matching a revset and emit changectx instances. + """Find revisions matching a revset and emit changectx instances. This is a convenience wrapper around ``revs()`` that iterates the result and is a generator of changectx instances. Revset aliases from the configuration are not expanded. To expand user aliases, consider calling ``scmutil.revrange()``. - ''' + """ for r in self.revs(expr, *args): yield self[r] def anyrevs(self, specs, user=False, localalias=None): - '''Find revisions matching one of the given revsets. + """Find revisions matching one of the given revsets. Revset aliases from the configuration are not expanded by default. To expand user aliases, specify ``user=True``. To provide some local definitions overriding user aliases, set ``localalias`` to ``{name: definitionstring}``. - ''' + """ if specs == [b'null']: return revset.baseset([nullrev]) if specs == [b'.']: @@ -1811,8 +1845,8 @@ @filteredpropertycache def _tagscache(self): - '''Returns a tagscache object that contains various tags related - caches.''' + """Returns a tagscache object that contains various tags related + caches.""" # This simplifies its cache management by having one decorated # function (this one) and the rest simply fetch things from it. @@ -1850,12 +1884,12 @@ return t def _findtags(self): - '''Do the hard work of finding tags. Return a pair of dicts + """Do the hard work of finding tags. Return a pair of dicts (tags, tagtypes) where tags maps tag name to node, and tagtypes maps tag name to a string like \'global\' or \'local\'. Subclasses or extensions are free to add their own tags, but should be aware that the returned dicts will be retained for the - duration of the localrepo object.''' + duration of the localrepo object.""" # XXX what tagtype should subclasses/extensions use? Currently # mq and bookmarks add tags, but do not set the tagtype at all. @@ -1886,13 +1920,13 @@ return (tags, tagtypes) def tagtype(self, tagname): - ''' + """ return the type of the given tag. result can be: 'local' : a local tag 'global' : a global tag None : tag does not exist - ''' + """ return self._tagscache.tagtypes.get(tagname) @@ -1922,8 +1956,8 @@ return self._bookmarks.names(node) def branchmap(self): - '''returns a dictionary {branch: [branchheads]} with branchheads - ordered by increasing revision number''' + """returns a dictionary {branch: [branchheads]} with branchheads + ordered by increasing revision number""" return self._branchcaches[self] @unfilteredmethod @@ -1933,13 +1967,13 @@ return self._revbranchcache def branchtip(self, branch, ignoremissing=False): - '''return the tip node for a given branch + """return the tip node for a given branch If ignoremissing is True, then this method will not raise an error. This is helpful for callers that only expect None for a missing branch (e.g. namespace). - ''' + """ try: return self.branchmap().branchtip(branch) except KeyError: @@ -2003,7 +2037,7 @@ def filectx(self, path, changeid=None, fileid=None, changectx=None): """changeid must be a changeset revision, if specified. - fileid can be a file revision or node.""" + fileid can be a file revision or node.""" return context.filectx( self, path, changeid, fileid, changectx=changectx ) @@ -2300,8 +2334,7 @@ tr.addfinalize(b'flush-fncache', self.store.write) def txnclosehook(tr2): - """To be run if transaction is successful, will schedule a hook run - """ + """To be run if transaction is successful, will schedule a hook run""" # Don't reference tr2 in hook() so we don't hold a reference. # This reduces memory consumption when there are multiple # transactions per lock. This can likely go away if issue5045 @@ -2351,8 +2384,7 @@ tr.addpostclose(b'-warm-cache', self._buildcacheupdater(tr)) def txnaborthook(tr2): - """To be run if transaction is aborted - """ + """To be run if transaction is aborted""" reporef().hook( b'txnabort', throw=False, **pycompat.strkwargs(tr2.hookargs) ) @@ -2609,14 +2641,14 @@ self._quick_access_changeid_invalidate() def invalidatedirstate(self): - '''Invalidates the dirstate, causing the next call to dirstate + """Invalidates the dirstate, causing the next call to dirstate to check if it was modified since the last time it was read, rereading it if it has. This is different to dirstate.invalidate() that it doesn't always rereads the dirstate. Use dirstate.invalidate() if you want to explicitly read the dirstate again (i.e. restoring it to a previous - known good state).''' + known good state).""" if hasunfilteredcache(self, 'dirstate'): for k in self.dirstate._filecache: try: @@ -2626,13 +2658,13 @@ delattr(self.unfiltered(), 'dirstate') def invalidate(self, clearfilecache=False): - '''Invalidates both store and non-store parts other than dirstate + """Invalidates both store and non-store parts other than dirstate If a transaction is running, invalidation of store is omitted, because discarding in-memory changes might cause inconsistency (e.g. incomplete fncache causes unintentional failure, but redundant one doesn't). - ''' + """ unfiltered = self.unfiltered() # all file caches are stored unfiltered for k in list(self._filecache.keys()): # dirstate is invalidated separately in invalidatedirstate() @@ -2662,8 +2694,8 @@ self.store.invalidatecaches() def invalidateall(self): - '''Fully invalidates both store and non-store parts, causing the - subsequent operation to reread any outside changes.''' + """Fully invalidates both store and non-store parts, causing the + subsequent operation to reread any outside changes.""" # extension should hook this to invalidate its caches self.invalidate() self.invalidatedirstate() @@ -2678,7 +2710,13 @@ ce.refresh() def _lock( - self, vfs, lockname, wait, releasefn, acquirefn, desc, + self, + vfs, + lockname, + wait, + releasefn, + acquirefn, + desc, ): timeout = 0 warntimeout = 0 @@ -2715,12 +2753,12 @@ callback(True) def lock(self, wait=True): - '''Lock the repository store (.hg/store) and return a weak reference + """Lock the repository store (.hg/store) and return a weak reference to the lock. Use this before modifying the store (e.g. committing or stripping). If you are opening a transaction, get a lock as well.) If both 'lock' and 'wlock' must be acquired, ensure you always acquires - 'wlock' first to avoid a dead-lock hazard.''' + 'wlock' first to avoid a dead-lock hazard.""" l = self._currentlock(self._lockref) if l is not None: l.lock() @@ -2738,13 +2776,13 @@ return l def wlock(self, wait=True): - '''Lock the non-store parts of the repository (everything under + """Lock the non-store parts of the repository (everything under .hg except .hg/store) and return a weak reference to the lock. Use this before modifying files in .hg. If both 'lock' and 'wlock' must be acquired, ensure you always acquires - 'wlock' first to avoid a dead-lock hazard.''' + 'wlock' first to avoid a dead-lock hazard.""" l = self._wlockref and self._wlockref() if l is not None and l.held: l.lock() @@ -2834,7 +2872,7 @@ extra = {} def fail(f, msg): - raise error.Abort(b'%s: %s' % (f, msg)) + raise error.InputError(b'%s: %s' % (f, msg)) if not match: match = matchmod.always() @@ -2952,7 +2990,7 @@ @unfilteredmethod def destroying(self): - '''Inform the repository that nodes are about to be destroyed. + """Inform the repository that nodes are about to be destroyed. Intended for use by strip and rollback, so there's a common place for anything that has to be done before destroying history. @@ -2961,7 +2999,7 @@ destroyed is imminent, the repo will be invalidated causing those changes to stay in memory (waiting for the next unlock), or vanish completely. - ''' + """ # When using the same lock to commit and strip, the phasecache is left # dirty after committing. Then when we strip, the repo is invalidated, # causing those changes to disappear. @@ -2970,10 +3008,10 @@ @unfilteredmethod def destroyed(self): - '''Inform the repository that nodes have been destroyed. + """Inform the repository that nodes have been destroyed. Intended for use by strip and rollback, so there's a common place for anything that has to be done after destroying history. - ''' + """ # When one tries to: # 1) destroy nodes thus calling this method (e.g. strip) # 2) use phasecache somewhere (e.g. commit) @@ -3056,13 +3094,13 @@ return sorted(heads, key=self.changelog.rev, reverse=True) def branchheads(self, branch=None, start=None, closed=False): - '''return a (possibly filtered) list of heads for the given branch + """return a (possibly filtered) list of heads for the given branch Heads are returned in topological order, from newest to oldest. If branch is None, use the dirstate branch. If start is not None, return only heads reachable from start. If closed is True, return heads that are marked as closed as well. - ''' + """ if branch is None: branch = self[None].branch() branches = self.branchmap() @@ -3341,10 +3379,10 @@ def checkrequirementscompat(ui, requirements): - """ Checks compatibility of repository requirements enabled and disabled. + """Checks compatibility of repository requirements enabled and disabled. Returns a set of requirements which needs to be dropped because dependend - requirements are not enabled. Also warns users about it """ + requirements are not enabled. Also warns users about it""" dropped = set()
--- a/mercurial/lock.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/lock.py Thu Dec 03 14:15:39 2020 -0500 @@ -175,14 +175,14 @@ class lock(object): - '''An advisory lock held by one process to control access to a set + """An advisory lock held by one process to control access to a set of files. Non-cooperating processes or incorrectly written scripts can ignore Mercurial's locking scheme and stomp all over the repository, so don't do that. Typically used via localrepository.lock() to lock the repository store (.hg/store/) or localrepository.wlock() to lock everything - else under .hg/.''' + else under .hg/.""" # lock is symlink on platforms that support it, file on others.
--- a/mercurial/logcmdutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/logcmdutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -417,8 +417,7 @@ ) def _exthook(self, ctx): - '''empty method used by extension as a hook point - ''' + """empty method used by extension as a hook point""" def _showpatch(self, ctx, graphwidth=0): if self._includestat: @@ -509,13 +508,13 @@ class changesettemplater(changesetprinter): - '''format changeset information. + """format changeset information. Note: there are a variety of convenience functions to build a changesettemplater for common cases. See functions such as: maketemplater, changesetdisplayer, buildcommittemplate, or other functions that use changesest_templater. - ''' + """ # Arguments before "buffered" used to be positional. Consider not # adding/removing arguments before "buffered" to not break callers. @@ -623,7 +622,7 @@ # ui settings if not tmpl and not style: # template are stronger than style - tmpl = ui.config(b'ui', b'logtemplate') + tmpl = ui.config(b'command-templates', b'log') if tmpl: return formatter.literal_templatespec(templater.unquotestring(tmpl)) else: @@ -656,7 +655,7 @@ Display format will be the first non-empty hit of: 1. option 'template' 2. option 'style' - 3. [ui] setting 'logtemplate' + 3. [command-templates] setting 'log' 4. [ui] setting 'style' If all of these values are either the unset or the empty string, regular display via changesetprinter() is done. @@ -1024,6 +1023,26 @@ return revs, differ +def get_bookmark_revs(repo, bookmark, walk_opts): + # type: (Any, bookmark, walk_opts) -> Tuple[smartset.abstractsmartset, Optional[changesetdiffer]] + """Return (revs, differ) where revs is a smartset + + differ is a changesetdiffer with pre-configured file matcher. + """ + revs, filematcher = makewalker(repo, walk_opts) + if not revs: + return revs, None + differ = changesetdiffer() + differ._makefilematcher = filematcher + + if bookmark: + if bookmark not in repo._bookmarks: + raise error.Abort(_(b"bookmark '%s' not found") % bookmark) + revs = scmutil.bookmarkrevs(repo, bookmark) + + return revs, differ + + def _parselinerangeopt(repo, opts): """Parse --line-range log option and return a list of tuples (filename, (fromline, toline)). @@ -1111,7 +1130,7 @@ def _graphnodeformatter(ui, displayer): - spec = ui.config(b'ui', b'graphnodetemplate') + spec = ui.config(b'command-templates', b'graphnode') if not spec: return templatekw.getgraphnode # fast path for "{graphnode}"
--- a/mercurial/logexchange.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/logexchange.py Thu Dec 03 14:15:39 2020 -0500 @@ -141,7 +141,10 @@ with remoterepo.commandexecutor() as e: bookmarks = e.callcommand( - b'listkeys', {b'namespace': b'bookmarks',} + b'listkeys', + { + b'namespace': b'bookmarks', + }, ).result() # on a push, we don't want to keep obsolete heads since
--- a/mercurial/mail.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/mail.py Thu Dec 03 14:15:39 2020 -0500 @@ -44,10 +44,10 @@ class STARTTLS(smtplib.SMTP): - '''Derived class to verify the peer certificate for STARTTLS. + """Derived class to verify the peer certificate for STARTTLS. This class allows to pass any keyword arguments to SSL socket creation. - ''' + """ def __init__(self, ui, host=None, **kwargs): smtplib.SMTP.__init__(self, **kwargs) @@ -76,10 +76,10 @@ class SMTPS(smtplib.SMTP): - '''Derived class to verify the peer certificate for SMTPS. + """Derived class to verify the peer certificate for SMTPS. This class allows to pass any keyword arguments to SSL socket creation. - ''' + """ def __init__(self, ui, keyfile=None, certfile=None, host=None, **kwargs): self.keyfile = keyfile @@ -221,8 +221,8 @@ def connect(ui, mbox=None): - '''make a mail connection. return a function to send mail. - call as sendmail(sender, list-of-recipients, msg).''' + """make a mail connection. return a function to send mail. + call as sendmail(sender, list-of-recipients, msg).""" if mbox: open(mbox, b'wb').close() return lambda s, r, m: _mbox(mbox, s, r, m) @@ -267,11 +267,11 @@ def mimetextpatch(s, subtype='plain', display=False): # type: (bytes, str, bool) -> email.message.Message - '''Return MIME message suitable for a patch. + """Return MIME message suitable for a patch. Charset will be detected by first trying to decode as us-ascii, then utf-8, and finally the global encodings. If all those fail, fall back to ISO-8859-1, an encoding with that allows all byte sequences. - Transfer encodings will be used if necessary.''' + Transfer encodings will be used if necessary.""" cs = [ 'us-ascii', @@ -293,9 +293,9 @@ def mimetextqp(body, subtype, charset): # type: (bytes, str, str) -> email.message.Message - '''Return MIME message. + """Return MIME message. Quoted-printable transfer encoding will be used if necessary. - ''' + """ cs = email.charset.Charset(charset) msg = email.message.Message() msg.set_type('text/' + subtype) @@ -337,11 +337,11 @@ def _encode(ui, s, charsets): # type: (Any, bytes, List[str]) -> Tuple[bytes, str] - '''Returns (converted) string, charset tuple. + """Returns (converted) string, charset tuple. Finds out best charset by cycling through sendcharsets in descending order. Tries both encoding and fallbackencoding for input. Only as last resort send as is in fake ascii. - Caveat: Do not use for mail parts containing patches!''' + Caveat: Do not use for mail parts containing patches!""" sendcharsets = charsets or _charsets(ui) if not isinstance(s, bytes): # We have unicode data, which we need to try and encode to @@ -427,9 +427,9 @@ def addrlistencode(ui, addrs, charsets=None, display=False): # type: (Any, List[bytes], List[str], bool) -> List[str] - '''Turns a list of addresses into a list of RFC-2047 compliant headers. + """Turns a list of addresses into a list of RFC-2047 compliant headers. A single element of input list may contain multiple addresses, but output - always has one address per item''' + always has one address per item""" straddrs = [] for a in addrs: assert isinstance(a, bytes), '%r unexpectedly not a bytestr' % a @@ -447,8 +447,8 @@ def mimeencode(ui, s, charsets=None, display=False): # type: (Any, bytes, List[str], bool) -> email.message.Message - '''creates mime text object, encodes it if needed, and sets - charset and transfer-encoding accordingly.''' + """creates mime text object, encodes it if needed, and sets + charset and transfer-encoding accordingly.""" cs = 'us-ascii' if not display: s, cs = _encode(ui, s, charsets)
--- a/mercurial/manifest.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/manifest.py Thu Dec 03 14:15:39 2020 -0500 @@ -528,8 +528,8 @@ return dir in self._dirs def _filesfastpath(self, match): - '''Checks whether we can correctly and quickly iterate over matcher - files instead of over manifest files.''' + """Checks whether we can correctly and quickly iterate over matcher + files instead of over manifest files.""" files = match.files() return len(files) < 100 and ( match.isexact() @@ -537,13 +537,13 @@ ) def walk(self, match): - '''Generates matching file names. + """Generates matching file names. Equivalent to manifest.matches(match).iterkeys(), but without creating an entirely new manifest. It also reports nonexistent files by marking them bad with match.bad(). - ''' + """ if match.always(): for f in iter(self): yield f @@ -591,7 +591,7 @@ return m def diff(self, m2, match=None, clean=False): - '''Finds changes between the current manifest and m2. + """Finds changes between the current manifest and m2. Args: m2: the manifest to which this manifest should be compared. @@ -604,7 +604,7 @@ in the current/other manifest. Where the file does not exist, the nodeid will be None and the flags will be the empty string. - ''' + """ if match: m1 = self._matches(match) m2 = m2._matches(match) @@ -703,14 +703,14 @@ def _msearch(m, s, lo=0, hi=None): - '''return a tuple (start, end) that says where to find s within m. + """return a tuple (start, end) that says where to find s within m. If the string is found m[start:end] are the line containing that string. If start == end the string was not found and they indicate the proper sorted insertion point. m should be a buffer, a memoryview or a byte string. - s is a byte string''' + s is a byte string""" def advance(i, c): while i < lenm and m[i : i + 1] != c: @@ -909,14 +909,14 @@ ) def dir(self): - '''The directory that this tree manifest represents, including a - trailing '/'. Empty string for the repo root directory.''' + """The directory that this tree manifest represents, including a + trailing '/'. Empty string for the repo root directory.""" return self._dir def node(self): - '''This node of this instance. nullid for unsaved instances. Should + """This node of this instance. nullid for unsaved instances. Should be updated when the instance is read or written from a revlog. - ''' + """ assert not self._dirty return self._node @@ -1157,10 +1157,10 @@ return dirslash in self._dirs or dirslash in self._lazydirs def walk(self, match): - '''Generates matching file names. + """Generates matching file names. It also reports nonexistent files by marking them bad with match.bad(). - ''' + """ if match.always(): for f in iter(self): yield f @@ -1202,8 +1202,7 @@ yield f def _matches(self, match): - '''recursively generate a new manifest filtered by the match argument. - ''' + """recursively generate a new manifest filtered by the match argument.""" if match.always(): return self.copy() return self._matches_inner(match) @@ -1253,7 +1252,7 @@ raise FastdeltaUnavailable() def diff(self, m2, match=None, clean=False): - '''Finds changes between the current manifest and m2. + """Finds changes between the current manifest and m2. Args: m2: the manifest to which this manifest should be compared. @@ -1266,7 +1265,7 @@ in the current/other manifest. Where the file does not exist, the nodeid will be None and the flags will be the empty string. - ''' + """ if match and not match.always(): m1 = self._matches(match) m2 = m2._matches(match) @@ -1546,9 +1545,9 @@ @interfaceutil.implementer(repository.imanifeststorage) class manifestrevlog(object): - '''A revlog that stores manifest texts. This is responsible for caching the + """A revlog that stores manifest texts. This is responsible for caching the full-text manifest contents. - ''' + """ def __init__( self, @@ -1832,9 +1831,20 @@ deltamode=deltamode, ) - def addgroup(self, deltas, linkmapper, transaction, addrevisioncb=None): + def addgroup( + self, + deltas, + linkmapper, + transaction, + addrevisioncb=None, + duplicaterevisioncb=None, + ): return self._revlog.addgroup( - deltas, linkmapper, transaction, addrevisioncb=addrevisioncb + deltas, + linkmapper, + transaction, + addrevisioncb=addrevisioncb, + duplicaterevisioncb=duplicaterevisioncb, ) def rawsize(self, rev): @@ -2066,12 +2076,12 @@ return self._data def readfast(self, shallow=False): - '''Calls either readdelta or read, based on which would be less work. + """Calls either readdelta or read, based on which would be less work. readdelta is called if the delta is against the p1, and therefore can be read quickly. If `shallow` is True, nothing changes since this is a flat manifest. - ''' + """ store = self._storage() r = store.rev(self._node) deltaparent = store.deltaparent(r) @@ -2080,12 +2090,12 @@ return self.read() def readdelta(self, shallow=False): - '''Returns a manifest containing just the entries that are present + """Returns a manifest containing just the entries that are present in this manifest, but not in its p1 manifest. This is efficient to read if the revlog delta is already p1. Changing the value of `shallow` has no effect on flat manifests. - ''' + """ store = self._storage() r = store.rev(self._node) d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r)) @@ -2197,7 +2207,7 @@ return self._storage().parents(self._node) def readdelta(self, shallow=False): - '''Returns a manifest containing just the entries that are present + """Returns a manifest containing just the entries that are present in this manifest, but not in its p1 manifest. This is efficient to read if the revlog delta is already p1. @@ -2206,7 +2216,7 @@ subdirectory entry will be reported as it appears in the manifest, i.e. the subdirectory will be reported among files and distinguished only by its 't' flag. - ''' + """ store = self._storage() if shallow: r = store.rev(self._node) @@ -2226,13 +2236,13 @@ return md def readfast(self, shallow=False): - '''Calls either readdelta or read, based on which would be less work. + """Calls either readdelta or read, based on which would be less work. readdelta is called if the delta is against the p1, and therefore can be read quickly. If `shallow` is True, it only returns the entries from this manifest, and not any submanifests. - ''' + """ store = self._storage() r = store.rev(self._node) deltaparent = store.deltaparent(r)
--- a/mercurial/match.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/match.py Thu Dec 03 14:15:39 2020 -0500 @@ -47,8 +47,8 @@ def _rematcher(regex): - '''compile the regexp with the best available regexp engine and return a - matcher function''' + """compile the regexp with the best available regexp engine and return a + matcher function""" m = util.re.compile(regex) try: # slightly faster, provided by facebook's re2 bindings @@ -82,8 +82,8 @@ def _expandsubinclude(kindpats, root): - '''Returns the list of subinclude matcher args and the kindpats without the - subincludes in it.''' + """Returns the list of subinclude matcher args and the kindpats without the + subincludes in it.""" relmatchers = [] other = [] @@ -107,7 +107,7 @@ def _kindpatsalwaysmatch(kindpats): - """"Checks whether the kindspats match everything, as e.g. + """Checks whether the kindspats match everything, as e.g. 'relpath:.' does. """ for kind, pat, source in kindpats: @@ -117,11 +117,21 @@ def _buildkindpatsmatcher( - matchercls, root, cwd, kindpats, ctx=None, listsubrepos=False, badfn=None, + matchercls, + root, + cwd, + kindpats, + ctx=None, + listsubrepos=False, + badfn=None, ): matchers = [] fms, kindpats = _expandsets( - cwd, kindpats, ctx=ctx, listsubrepos=listsubrepos, badfn=badfn, + cwd, + kindpats, + ctx=ctx, + listsubrepos=listsubrepos, + badfn=badfn, ) if kindpats: m = matchercls(root, kindpats, badfn=badfn) @@ -321,8 +331,8 @@ def _donormalize(patterns, default, root, cwd, auditor=None, warn=None): - '''Convert 'kind:pat' from the patterns list to tuples with kind and - normalized and rooted patterns and with listfiles expanded.''' + """Convert 'kind:pat' from the patterns list to tuples with kind and + normalized and rooted patterns and with listfiles expanded.""" kindpats = [] for kind, pat in [_patsplit(p, default) for p in patterns]: if kind in cwdrelativepatternkinds: @@ -383,8 +393,8 @@ # Callbacks related to how the matcher is used by dirstate.walk. # Subscribers to these events must monkeypatch the matcher object. def bad(self, f, msg): - '''Callback from dirstate.walk for each explicit file that can't be - found/accessed, with an error message.''' + """Callback from dirstate.walk for each explicit file that can't be + found/accessed, with an error message.""" # If an traversedir is set, it will be called when a directory discovered # by recursive traversal is visited. @@ -395,11 +405,11 @@ return [] def files(self): - '''Explicitly listed files or patterns or roots: + """Explicitly listed files or patterns or roots: if no patterns or .always(): empty list, if exact: list exact files, if not .anypats(): list all files and dirs, - else: optimal roots''' + else: optimal roots""" return self._files @propertycache @@ -414,18 +424,18 @@ return False def visitdir(self, dir): - '''Decides whether a directory should be visited based on whether it + """Decides whether a directory should be visited based on whether it has potential matches in it or one of its subdirectories. This is based on the match's primary, included, and excluded patterns. Returns the string 'all' if the given directory and all subdirectories should be visited. Otherwise returns True or False indicating whether the given directory should be visited. - ''' + """ return True def visitchildrenset(self, dir): - '''Decides whether a directory should be visited based on whether it + """Decides whether a directory should be visited based on whether it has potential matches in it or one of its subdirectories, and potentially lists which subdirectories of that directory should be visited. This is based on the match's primary, included, and excluded @@ -464,27 +474,27 @@ indicating that there are no files in this dir to investigate (or equivalently that if there are files to investigate in 'dir' that it will always return 'this'). - ''' + """ return b'this' def always(self): - '''Matcher will match everything and .files() will be empty -- - optimization might be possible.''' + """Matcher will match everything and .files() will be empty -- + optimization might be possible.""" return False def isexact(self): - '''Matcher will match exactly the list of files in .files() -- - optimization might be possible.''' + """Matcher will match exactly the list of files in .files() -- + optimization might be possible.""" return False def prefix(self): - '''Matcher will match the paths in .files() recursively -- - optimization might be possible.''' + """Matcher will match the paths in .files() recursively -- + optimization might be possible.""" return False def anypats(self): - '''None of .always(), .isexact(), and .prefix() is true -- - optimizations will be difficult.''' + """None of .always(), .isexact(), and .prefix() is true -- + optimizations will be difficult.""" return not self.always() and not self.isexact() and not self.prefix() @@ -553,6 +563,36 @@ return b'<predicatenmatcher pred=%s>' % s +def path_or_parents_in_set(path, prefix_set): + """Returns True if `path` (or any parent of `path`) is in `prefix_set`.""" + l = len(prefix_set) + if l == 0: + return False + if path in prefix_set: + return True + # If there's more than 5 paths in prefix_set, it's *probably* quicker to + # "walk up" the directory hierarchy instead, with the assumption that most + # directory hierarchies are relatively shallow and hash lookup is cheap. + if l > 5: + return any( + parentdir in prefix_set for parentdir in pathutil.finddirs(path) + ) + + # FIXME: Ideally we'd never get to this point if this is the case - we'd + # recognize ourselves as an 'always' matcher and skip this. + if b'' in prefix_set: + return True + + if pycompat.ispy3: + sl = ord(b'/') + else: + sl = '/' + + # We already checked that path isn't in prefix_set exactly, so + # `path[len(pf)] should never raise IndexError. + return any(path.startswith(pf) and path[len(pf)] == sl for pf in prefix_set) + + class patternmatcher(basematcher): r"""Matches a set of (kind, pat, source) against a 'root' directory. @@ -601,12 +641,8 @@ if self._prefix and dir in self._fileset: return b'all' return ( - dir in self._fileset - or dir in self._dirs - or any( - parentdir in self._fileset - for parentdir in pathutil.finddirs(dir) - ) + dir in self._dirs + or path_or_parents_in_set(dir, self._fileset) ) def visitchildrenset(self, dir): @@ -688,12 +724,9 @@ if self._prefix and dir in self._roots: return b'all' return ( - dir in self._roots - or dir in self._dirs + dir in self._dirs or dir in self._parents - or any( - parentdir in self._roots for parentdir in pathutil.finddirs(dir) - ) + or path_or_parents_in_set(dir, self._roots) ) @propertycache @@ -716,11 +749,8 @@ # visitdir, that's handled below. if ( b'' in self._roots - or dir in self._roots or dir in self._dirs - or any( - parentdir in self._roots for parentdir in pathutil.finddirs(dir) - ) + or path_or_parents_in_set(dir, self._roots) ): return b'this' @@ -734,7 +764,7 @@ class exactmatcher(basematcher): - r'''Matches the input files exactly. They are interpreted as paths, not + r"""Matches the input files exactly. They are interpreted as paths, not patterns (so no kind-prefixes). >>> m = exactmatcher([b'a.txt', br're:.*\.c$']) @@ -752,7 +782,7 @@ False >>> m(br're:.*\.c$') True - ''' + """ def __init__(self, files, badfn=None): super(exactmatcher, self).__init__(badfn) @@ -799,11 +829,11 @@ class differencematcher(basematcher): - '''Composes two matchers by matching if the first matches and the second + """Composes two matchers by matching if the first matches and the second does not. The second matcher's non-matching-attributes (bad, traversedir) are ignored. - ''' + """ def __init__(self, m1, m2): super(differencematcher, self).__init__() @@ -868,10 +898,10 @@ def intersectmatchers(m1, m2): - '''Composes two matchers by matching if both of them match. + """Composes two matchers by matching if both of them match. The second matcher's non-matching-attributes (bad, traversedir) are ignored. - ''' + """ if m1 is None or m2 is None: return m1 or m2 if m1.always(): @@ -1166,7 +1196,7 @@ def patkind(pattern, default=None): - r'''If pattern is 'kind:pat' with a known kind, return kind. + r"""If pattern is 'kind:pat' with a known kind, return kind. >>> patkind(br're:.*\.c$') 're' @@ -1177,7 +1207,7 @@ >>> patkind(b'main.py') >>> patkind(b'main.py', default=b're') 're' - ''' + """ return _patsplit(pattern, default)[0] @@ -1192,7 +1222,7 @@ def _globre(pat): - r'''Convert an extended glob string to a regexp string. + r"""Convert an extended glob string to a regexp string. >>> from . import pycompat >>> def bprint(s): @@ -1213,7 +1243,7 @@ (?:a|b) >>> bprint(_globre(br'.\*\?')) \.\*\? - ''' + """ i, n = 0, len(pat) res = b'' group = 0 @@ -1276,9 +1306,9 @@ def _regex(kind, pat, globsuffix): - '''Convert a (normalized) pattern of any kind into a + """Convert a (normalized) pattern of any kind into a regular expression. - globsuffix is appended to the regexp of globs.''' + globsuffix is appended to the regexp of globs.""" if not pat and kind in (b'glob', b'relpath'): return b'' if kind == b're': @@ -1312,8 +1342,8 @@ def _buildmatch(kindpats, globsuffix, root): - '''Return regexp string and a matcher function for kindpats. - globsuffix is appended to the regexp of globs.''' + """Return regexp string and a matcher function for kindpats. + globsuffix is appended to the regexp of globs.""" matchfuncs = [] subincludes, kindpats = _expandsubinclude(kindpats, root) @@ -1422,13 +1452,13 @@ def _patternrootsanddirs(kindpats): - '''Returns roots and directories corresponding to each pattern. + """Returns roots and directories corresponding to each pattern. This calculates the roots and directories exactly matching the patterns and returns a tuple of (roots, dirs) for each. It does not return other directories which may also need to be considered, like the parent directories. - ''' + """ r = [] d = [] for kind, pat, source in kindpats: @@ -1459,7 +1489,7 @@ def _rootsdirsandparents(kindpats): - '''Returns roots and exact directories from patterns. + """Returns roots and exact directories from patterns. `roots` are directories to match recursively, `dirs` should be matched non-recursively, and `parents` are the implicitly required @@ -1486,7 +1516,7 @@ ... (b'relre', b'rr', b'')]) >>> print(r[0:2], sorted(r[2])) # the set has an unstable output (['', '', ''], []) [''] - ''' + """ r, d = _patternrootsanddirs(kindpats) p = set() @@ -1503,13 +1533,13 @@ def _explicitfiles(kindpats): - '''Returns the potential explicit filenames from the patterns. + """Returns the potential explicit filenames from the patterns. >>> _explicitfiles([(b'path', b'foo/bar', b'')]) ['foo/bar'] >>> _explicitfiles([(b'rootfilesin', b'foo/bar', b'')]) [] - ''' + """ # Keep only the pattern kinds where one can specify filenames (vs only # directory names). filable = [kp for kp in kindpats if kp[0] not in (b'rootfilesin',)] @@ -1528,7 +1558,7 @@ def readpatternfile(filepath, warn, sourceinfo=False): - '''parse a pattern file, returning a list of + """parse a pattern file, returning a list of patterns. These patterns should be given to compile() to be validated and converted into a match function. @@ -1549,7 +1579,7 @@ if sourceinfo is set, returns a list of tuples: (pattern, lineno, originalline). This is useful to debug ignore patterns. - ''' + """ syntaxes = { b're': b'relre:',
--- a/mercurial/mdiff.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/mdiff.py Thu Dec 03 14:15:39 2020 -0500 @@ -39,7 +39,7 @@ # TODO: this looks like it could be an attrs, which might help pytype class diffopts(object): - '''context is the number of context lines + """context is the number of context lines text treats all files as text showfunc enables diff -p output git enables the git extended patch format @@ -50,7 +50,7 @@ ignorewsamount ignores changes in the amount of whitespace ignoreblanklines ignores changes whose lines are all blank upgrade generates git diffs to avoid data loss - ''' + """ _HAS_DYNAMIC_ATTRIBUTES = True @@ -199,7 +199,7 @@ if hunkinrange((b1, (b2 - b1)), rangeb): filteredblocks.append(block) if lba is None or uba is None or uba < lba: - raise error.Abort(_(b'line range exceeds file size')) + raise error.InputError(_(b'line range exceeds file size')) return filteredblocks, (lba, uba)
--- a/mercurial/merge.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/merge.py Thu Dec 03 14:15:39 2020 -0500 @@ -217,7 +217,10 @@ if config == b'warn': warnconflicts.add(f) mresult.addfile( - f, mergestatemod.ACTION_GET, (fl2, True), b'remote created', + f, + mergestatemod.ACTION_GET, + (fl2, True), + b'remote created', ) for f in sorted(abortconflicts): @@ -281,7 +284,10 @@ for f in wctx.removed(): if f not in mctx: mresult.addfile( - f, mergestatemod.ACTION_FORGET, None, b"forget removed", + f, + mergestatemod.ACTION_FORGET, + None, + b"forget removed", ) @@ -544,10 +550,10 @@ class mergeresult(object): - ''''An object representing result of merging manifests. + """An object representing result of merging manifests. It has information about what actions need to be performed on dirstate - mapping of divergent renames and other such cases. ''' + mapping of divergent renames and other such cases.""" def __init__(self): """ @@ -572,7 +578,7 @@ self._renamedelete = renamedelete def addfile(self, filename, action, data, message): - """ adds a new file to the mergeresult object + """adds a new file to the mergeresult object filename: file which we are adding action: one of mergestatemod.ACTION_* @@ -589,15 +595,15 @@ self._actionmapping[action][filename] = (data, message) def getfile(self, filename, default_return=None): - """ returns (action, args, msg) about this file + """returns (action, args, msg) about this file - returns default_return if the file is not present """ + returns default_return if the file is not present""" if filename in self._filemapping: return self._filemapping[filename] return default_return def files(self, actions=None): - """ returns files on which provided action needs to perfromed + """returns files on which provided action needs to perfromed If actions is None, all files are returned """ @@ -613,14 +619,14 @@ yield f def removefile(self, filename): - """ removes a file from the mergeresult object as the file might - not merging anymore """ + """removes a file from the mergeresult object as the file might + not merging anymore""" action, data, message = self._filemapping[filename] del self._filemapping[filename] del self._actionmapping[action][filename] def getactions(self, actions, sort=False): - """ get list of files which are marked with these actions + """get list of files which are marked with these actions if sort is true, files for each action is sorted and then added Returns a list of tuple of form (filename, data, message) @@ -637,10 +643,10 @@ yield f, args, msg def len(self, actions=None): - """ returns number of files which needs actions + """returns number of files which needs actions if actions is passed, total of number of files in that action - only is returned """ + only is returned""" if actions is None: return len(self._filemapping) @@ -656,8 +662,8 @@ yield key, val def addcommitinfo(self, filename, key, value): - """ adds key-value information about filename which will be required - while committing this merge """ + """adds key-value information about filename which will be required + while committing this merge""" self._commitinfo[filename][key] = value @property @@ -674,8 +680,8 @@ @property def actionsdict(self): - """ returns a dictionary of actions to be perfomed with action as key - and a list of files and related arguments as values """ + """returns a dictionary of actions to be perfomed with action as key + and a list of files and related arguments as values""" res = collections.defaultdict(list) for a, d in pycompat.iteritems(self._actionmapping): for f, (args, msg) in pycompat.iteritems(d): @@ -689,8 +695,8 @@ self._actionmapping[act][f] = data, msg def hasconflicts(self): - """ tells whether this merge resulted in some actions which can - result in conflicts or not """ + """tells whether this merge resulted in some actions which can + result in conflicts or not""" for a in self._actionmapping.keys(): if ( a @@ -817,13 +823,32 @@ args = (f, f, None, False, pa.node()) msg = b'both created' mresult.addfile(f, mergestatemod.ACTION_MERGE, args, msg) + elif f in branch_copies1.copy: + fa = branch_copies1.copy[f] + mresult.addfile( + f, + mergestatemod.ACTION_MERGE, + (f, fa, fa, False, pa.node()), + b'local replaced from %s' % fa, + ) + elif f in branch_copies2.copy: + fa = branch_copies2.copy[f] + mresult.addfile( + f, + mergestatemod.ACTION_MERGE, + (fa, f, fa, False, pa.node()), + b'other replaced from %s' % fa, + ) else: a = ma[f] fla = ma.flags(f) nol = b'l' not in fl1 + fl2 + fla if n2 == a and fl2 == fla: mresult.addfile( - f, mergestatemod.ACTION_KEEP, (), b'remote unchanged', + f, + mergestatemod.ACTION_KEEP, + (), + b'remote unchanged', ) elif n1 == a and fl1 == fla: # local unchanged - use remote if n1 == n2: # optimization: keep local content @@ -920,11 +945,17 @@ # This file was locally added. We should forget it instead of # deleting it. mresult.addfile( - f, mergestatemod.ACTION_FORGET, None, b'remote deleted', + f, + mergestatemod.ACTION_FORGET, + None, + b'remote deleted', ) else: mresult.addfile( - f, mergestatemod.ACTION_REMOVE, None, b'other deleted', + f, + mergestatemod.ACTION_REMOVE, + None, + b'other deleted', ) if branchmerge: # the file must be absent after merging, @@ -1070,7 +1101,7 @@ def _resolvetrivial(repo, wctx, mctx, ancestor, mresult): """Resolves false conflicts where the nodeid changed but the content - remained the same.""" + remained the same.""" # We force a copy of actions.items() because we're going to mutate # actions as we resolve trivial conflicts. for f in list(mresult.files((mergestatemod.ACTION_CHANGED_DELETED,))): @@ -1407,7 +1438,13 @@ prefetch = scmutil.prefetchfiles matchfiles = scmutil.matchfiles prefetch( - repo, [(ctx.rev(), matchfiles(repo, files),)], + repo, + [ + ( + ctx.rev(), + matchfiles(repo, files), + ) + ], ) @@ -1428,7 +1465,13 @@ def applyupdates( - repo, mresult, wctx, mctx, overwrite, wantfiledata, labels=None, + repo, + mresult, + wctx, + mctx, + overwrite, + wantfiledata, + labels=None, ): """apply the merge action list to the working directory @@ -1718,7 +1761,8 @@ if dirstate.rustmod is not None: # When using rust status, fsmonitor becomes necessary at higher sizes fsmonitorthreshold = repo.ui.configint( - b'fsmonitor', b'warn_update_file_count_rust', + b'fsmonitor', + b'warn_update_file_count_rust', ) try: @@ -1896,7 +1940,7 @@ hint=_(b"use 'hg update' or check 'hg heads'"), ) if not force and (wc.files() or wc.deleted()): - raise error.Abort( + raise error.StateError( _(b"uncommitted changes"), hint=_(b"use 'hg status' to list changes"), ) @@ -1985,7 +2029,10 @@ 0, ): mresult.addfile( - f, mergestatemod.ACTION_REMOVE, None, b'prompt delete', + f, + mergestatemod.ACTION_REMOVE, + None, + b'prompt delete', ) elif f in p1: mresult.addfile( @@ -1996,7 +2043,10 @@ ) else: mresult.addfile( - f, mergestatemod.ACTION_ADD, None, b'prompt keep', + f, + mergestatemod.ACTION_ADD, + None, + b'prompt keep', ) elif m == mergestatemod.ACTION_DELETED_CHANGED: f1, f2, fa, move, anc = args @@ -2073,7 +2123,13 @@ wantfiledata = updatedirstate and not branchmerge stats, getfiledata = applyupdates( - repo, mresult, wc, p2, overwrite, wantfiledata, labels=labels, + repo, + mresult, + wc, + p2, + overwrite, + wantfiledata, + labels=labels, ) if updatedirstate:
--- a/mercurial/mergestate.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/mergestate.py Thu Dec 03 14:15:39 2020 -0500 @@ -132,7 +132,7 @@ class _mergestate_base(object): - '''track 3-way merge state of individual files + """track 3-way merge state of individual files The merge state is stored on disk when needed. Two files are used: one with an old format (version 1), and one with a new format (version 2). Version 2 @@ -164,7 +164,7 @@ The resolve command transitions between 'u' and 'r' for conflicts and 'pu' and 'pr' for path conflicts. - ''' + """ def __init__(self, repo): """Initialize the merge state. @@ -275,8 +275,8 @@ self._dirty = True def addcommitinfo(self, path, data): - """ stores information which is required at commit - into _stateextras """ + """stores information which is required at commit + into _stateextras""" self._stateextras[path].update(data) self._dirty = True
--- a/mercurial/mergeutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/mergeutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -14,6 +14,6 @@ def checkunresolved(ms): if list(ms.unresolved()): - raise error.Abort( + raise error.StateError( _(b"unresolved merge conflicts (see 'hg help resolve')") )
--- a/mercurial/metadata.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/metadata.py Thu Dec 03 14:15:39 2020 -0500 @@ -254,8 +254,7 @@ def _process_root(ctx): - """compute the appropriate changed files for a changeset with no parents - """ + """compute the appropriate changed files for a changeset with no parents""" # Simple, there was nothing before it, so everything is added. md = ChangingFiles() manifest = ctx.manifest() @@ -265,8 +264,7 @@ def _process_linear(parent_ctx, children_ctx, parent=1): - """compute the appropriate changed files for a changeset with a single parent - """ + """compute the appropriate changed files for a changeset with a single parent""" md = ChangingFiles() parent_manifest = parent_ctx.manifest() children_manifest = children_ctx.manifest() @@ -515,8 +513,7 @@ def computechangesetfilesadded(ctx): - """return the list of files added in a changeset - """ + """return the list of files added in a changeset""" added = [] for f in ctx.files(): if not any(f in p for p in ctx.parents()): @@ -580,8 +577,7 @@ def computechangesetfilesremoved(ctx): - """return the list of files removed in a changeset - """ + """return the list of files removed in a changeset""" removed = [] for f in ctx.files(): if f not in ctx: @@ -593,8 +589,7 @@ def computechangesetfilesmerged(ctx): - """return the list of files merged in a changeset - """ + """return the list of files merged in a changeset""" merged = [] if len(ctx.parents()) < 2: return merged
--- a/mercurial/minirst.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/minirst.py Thu Dec 03 14:15:39 2020 -0500 @@ -52,7 +52,7 @@ def replace(text, substs): - ''' + """ Apply a list of (find, replace) pairs to a text. >>> replace(b"foo bar", [(b'f', b'F'), (b'b', b'B')]) @@ -63,7 +63,7 @@ >>> encoding.encoding = b'shiftjis' >>> replace(b'\\x81\\\\', [(b'\\\\', b'/')]) '\\x81\\\\' - ''' + """ # some character encodings (cp932 for Japanese, at least) use # ASCII characters other than control/alphabet/digit as a part of @@ -322,10 +322,10 @@ def findtables(blocks): - '''Find simple tables + """Find simple tables - Only simple one-line table elements are supported - ''' + Only simple one-line table elements are supported + """ for block in blocks: # Searching for a block that looks like this: @@ -432,7 +432,11 @@ while i < len(blocks): if blocks[i][b'type'] == blocks[i - 1][b'type'] and blocks[i][ b'type' - ] in (b'bullet', b'option', b'field',): + ] in ( + b'bullet', + b'option', + b'field', + ): i += 1 elif not blocks[i - 1][b'lines']: # no lines in previous block, do not separate
--- a/mercurial/narrowspec.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/narrowspec.py Thu Dec 03 14:15:39 2020 -0500 @@ -226,7 +226,7 @@ def restrictpatterns(req_includes, req_excludes, repo_includes, repo_excludes): - r""" Restricts the patterns according to repo settings, + r"""Restricts the patterns according to repo settings, results in a logical AND operation :param req_includes: requested includes
--- a/mercurial/obsolete.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/obsolete.py Thu Dec 03 14:15:39 2020 -0500 @@ -998,8 +998,7 @@ @cachefor(b'contentdivergent') def _computecontentdivergentset(repo): - """the set of rev that compete to be the final successors of some revision. - """ + """the set of rev that compete to be the final successors of some revision.""" divergent = set() obsstore = repo.obsstore newermap = {}
--- a/mercurial/obsutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/obsutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -381,7 +381,7 @@ def metanotblacklisted(metaitem): - """ Check that the key of a meta item (extrakey, extravalue) does not + """Check that the key of a meta item (extrakey, extravalue) does not match at least one of the blacklist pattern """ metakey = metaitem[0] @@ -439,7 +439,7 @@ def geteffectflag(source, successors): - """ From an obs-marker relation, compute what changed between the + """From an obs-marker relation, compute what changed between the predecessor and the successor. """ effects = 0 @@ -816,7 +816,7 @@ def _getobsfate(successorssets): - """ Compute a changeset obsolescence fate based on its successorssets. + """Compute a changeset obsolescence fate based on its successorssets. Successors can be the tipmost ones or the immediate ones. This function return values are not meant to be shown directly to users, it is meant to be used by internal functions only. @@ -843,7 +843,7 @@ def obsfateverb(successorset, markers): - """ Return the verb summarizing the successorset and potentially using + """Return the verb summarizing the successorset and potentially using information from the markers """ if not successorset: @@ -856,14 +856,12 @@ def markersdates(markers): - """returns the list of dates for a list of markers - """ + """returns the list of dates for a list of markers""" return [m[4] for m in markers] def markersusers(markers): - """ Returns a sorted list of markers users without duplicates - """ + """Returns a sorted list of markers users without duplicates""" markersmeta = [dict(m[3]) for m in markers] users = { encoding.tolocal(meta[b'user']) @@ -875,8 +873,7 @@ def markersoperations(markers): - """ Returns a sorted list of markers operations without duplicates - """ + """Returns a sorted list of markers operations without duplicates""" markersmeta = [dict(m[3]) for m in markers] operations = { meta.get(b'operation') for meta in markersmeta if meta.get(b'operation') @@ -886,7 +883,7 @@ def obsfateprinter(ui, repo, successors, markers, formatctx): - """ Build a obsfate string for a single successorset using all obsfate + """Build a obsfate string for a single successorset using all obsfate related function defined in obsutil """ quiet = ui.quiet @@ -950,8 +947,7 @@ def _getfilteredreason(repo, changeid, ctx): - """return a human-friendly string on why a obsolete changeset is hidden - """ + """return a human-friendly string on why a obsolete changeset is hidden""" successors = successorssets(repo, ctx.node()) fate = _getobsfate(successors)
--- a/mercurial/parser.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/parser.py Thu Dec 03 14:15:39 2020 -0500 @@ -406,12 +406,11 @@ def parseerrordetail(inst): - """Compose error message from specified ParseError object - """ - if len(inst.args) > 1: - return _(b'at %d: %s') % (inst.args[1], inst.args[0]) + """Compose error message from specified ParseError object""" + if inst.location is not None: + return _(b'at %d: %s') % (inst.location, inst.message) else: - return inst.args[0] + return inst.message class alias(object):
--- a/mercurial/patch.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/patch.py Thu Dec 03 14:15:39 2020 -0500 @@ -200,7 +200,7 @@ @contextlib.contextmanager def extract(ui, fileobj): - '''extract patch from data read from fileobj. + """extract patch from data read from fileobj. patch can be a normal patch or contained in an email message. @@ -214,7 +214,7 @@ - p1, - p2. Any item can be missing from the dictionary. If filename is missing, - fileobj did not contain a patch. Caller must unlink filename when done.''' + fileobj did not contain a patch. Caller must unlink filename when done.""" fd, tmpname = pycompat.mkstemp(prefix=b'hg-patch-') tmpfp = os.fdopen(fd, 'wb') @@ -905,8 +905,7 @@ class header(object): - """patch header - """ + """patch header""" diffgit_re = re.compile(b'diff --git a/(.*) b/(.*)$') diff_re = re.compile(b'diff -r .* (.*)$') @@ -1272,7 +1271,7 @@ elif r == 6: # all ret = skipall = True elif r == 7: # quit - raise error.Abort(_(b'user quit')) + raise error.CanceledError(_(b'user quit')) return ret, skipfile, skipall, newpatches seen = set() @@ -1854,7 +1853,7 @@ def pathtransform(path, strip, prefix): - '''turn a path from a patch into a path suitable for the repository + """turn a path from a patch into a path suitable for the repository prefix, if not empty, is expected to be normalized with a / at the end. @@ -1873,7 +1872,7 @@ >>> pathtransform(b'a/b/c', 3, b'') Traceback (most recent call last): PatchError: unable to strip away 1 of 3 dirs from a/b/c - ''' + """ pathlen = len(path) i = 0 if strip == 0: @@ -2503,7 +2502,7 @@ copysourcematch=None, hunksfilterfn=None, ): - '''yields diff of changes to files between two nodes, or node and + """yields diff of changes to files between two nodes, or node and working directory. if node1 is None, use first dirstate parent instead. @@ -2531,7 +2530,7 @@ hunksfilterfn, if not None, should be a function taking a filectx and hunks generator that may yield filtered hunks. - ''' + """ if not node1 and not node2: node1 = repo.dirstate.p1() @@ -2886,10 +2885,10 @@ def _filepairs(modified, added, removed, copy, opts): - '''generates tuples (f1, f2, copyop), where f1 is the name of the file + """generates tuples (f1, f2, copyop), where f1 is the name of the file before and f2 is the the name after. For added files, f1 will be None, and for removed files, f2 will be None. copyop may be set to None, 'copy' - or 'rename' (the latter two only if opts.git is set).''' + or 'rename' (the latter two only if opts.git is set).""" gone = set() copyto = {v: k for k, v in copy.items()} @@ -2948,13 +2947,13 @@ losedatafn, pathfn, ): - '''given input data, generate a diff and yield it in blocks + """given input data, generate a diff and yield it in blocks If generating a diff would lose data like flags or binary data and losedatafn is not None, it will be called. pathfn is applied to every path in the diff output. - ''' + """ if opts.noprefix: aprefix = bprefix = b'' @@ -3079,7 +3078,7 @@ def diffcontent(data1, data2, header, binary, opts): - """ diffs two versions of a file. + """diffs two versions of a file. data1 and data2 are tuples containg: @@ -3241,9 +3240,9 @@ def diffstatui(*args, **kw): - '''like diffstat(), but yields 2-tuples of (output, label) for + """like diffstat(), but yields 2-tuples of (output, label) for ui.write() - ''' + """ for line in diffstat(*args, **kw).splitlines(): if line and line[-1] in b'+-':
--- a/mercurial/pathutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/pathutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -24,7 +24,7 @@ class pathauditor(object): - '''ensure that a filesystem path contains no banned components. + """ensure that a filesystem path contains no banned components. the following properties of a path are checked: - ends with a directory separator @@ -44,7 +44,7 @@ If 'cached' is set to True, audited paths and sub-directories are cached. Be careful to not keep the cache of unmanaged directories for long because audited paths may be replaced with symlinks. - ''' + """ def __init__(self, root, callback=None, realfs=True, cached=False): self.audited = set() @@ -59,8 +59,8 @@ self.normcase = lambda x: x def __call__(self, path, mode=None): - '''Check the relative path. - path may contain a pattern (e.g. foodir/**.txt)''' + """Check the relative path. + path may contain a pattern (e.g. foodir/**.txt)""" path = util.localpath(path) normpath = self.normcase(path) @@ -164,7 +164,7 @@ def canonpath(root, cwd, myname, auditor=None): - '''return the canonical path of myname, given cwd and root + """return the canonical path of myname, given cwd and root >>> def check(root, cwd, myname): ... a = pathauditor(root, realfs=False) @@ -204,7 +204,7 @@ 'filename' >>> unixonly(b'/repo', b'/repo/subdir', b'filename', b'subdir/filename') 'subdir/filename' - ''' + """ if util.endswithsep(root): rootsep = root else: @@ -266,7 +266,7 @@ def normasprefix(path): - '''normalize the specified path as path prefix + """normalize the specified path as path prefix Returned value can be used safely for "p.startswith(prefix)", "p[len(prefix):]", and so on. @@ -280,7 +280,7 @@ '/foo/bar/' >>> normasprefix(b'/').replace(pycompat.ossep, b'/') '/' - ''' + """ d, p = os.path.splitdrive(path) if len(p) != len(pycompat.ossep): return path + pycompat.ossep @@ -300,9 +300,9 @@ '''a multiset of directory names from a set of file paths''' def __init__(self, map, skip=None): - ''' + """ a dict map indicates a dirstate while a list indicates a manifest - ''' + """ self._dirs = {} addpath = self.addpath if isinstance(map, dict) and skip is not None:
--- a/mercurial/phases.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/phases.py Thu Dec 03 14:15:39 2020 -0500 @@ -510,21 +510,20 @@ tr.addfilegenerator(b'phase', (b'phaseroots',), self._write) tr.hookargs[b'phases_moved'] = b'1' - def registernew(self, repo, tr, targetphase, nodes): + def registernew(self, repo, tr, targetphase, revs): repo = repo.unfiltered() - self._retractboundary(repo, tr, targetphase, nodes) + self._retractboundary(repo, tr, targetphase, [], revs=revs) if tr is not None and b'phases' in tr.changes: phasetracking = tr.changes[b'phases'] - torev = repo.changelog.rev phase = self.phase - revs = [torev(node) for node in nodes] - revs.sort() - for rev in revs: + for rev in sorted(revs): revphase = phase(repo, rev) _trackphasechange(phasetracking, rev, None, revphase) repo.invalidatevolatilesets() - def advanceboundary(self, repo, tr, targetphase, nodes, dryrun=None): + def advanceboundary( + self, repo, tr, targetphase, nodes, revs=None, dryrun=None + ): """Set all 'nodes' to phase 'targetphase' Nodes with a phase lower than 'targetphase' are not affected. @@ -535,26 +534,27 @@ """ # Be careful to preserve shallow-copied values: do not update # phaseroots values, replace them. + if revs is None: + revs = [] if tr is None: phasetracking = None else: phasetracking = tr.changes.get(b'phases') repo = repo.unfiltered() + revs = [repo[n].rev() for n in nodes] + [r for r in revs] changes = set() # set of revisions to be changed delroots = [] # set of root deleted by this path for phase in (phase for phase in allphases if phase > targetphase): # filter nodes that are not in a compatible phase already - nodes = [ - n for n in nodes if self.phase(repo, repo[n].rev()) >= phase - ] - if not nodes: + revs = [rev for rev in revs if self.phase(repo, rev) >= phase] + if not revs: break # no roots to move anymore olds = self.phaseroots[phase] - affected = repo.revs(b'%ln::%ln', olds, nodes) + affected = repo.revs(b'%ln::%ld', olds, revs) changes.update(affected) if dryrun: continue @@ -611,9 +611,11 @@ _trackphasechange(phasetracking, r, phase, targetphase) repo.invalidatevolatilesets() - def _retractboundary(self, repo, tr, targetphase, nodes): + def _retractboundary(self, repo, tr, targetphase, nodes, revs=None): # Be careful to preserve shallow-copied values: do not update # phaseroots values, replace them. + if revs is None: + revs = [] if targetphase in (archived, internal) and not supportinternal(repo): name = phasenames[targetphase] msg = b'this repository does not support the %s phase' % name @@ -624,7 +626,7 @@ tonode = repo.changelog.node currentroots = {torev(node) for node in self.phaseroots[targetphase]} finalroots = oldroots = set(currentroots) - newroots = [torev(node) for node in nodes] + newroots = [torev(node) for node in nodes] + [r for r in revs] newroots = [ rev for rev in newroots if self.phase(repo, rev) < targetphase ] @@ -679,7 +681,7 @@ self.invalidate() -def advanceboundary(repo, tr, targetphase, nodes, dryrun=None): +def advanceboundary(repo, tr, targetphase, nodes, revs=None, dryrun=None): """Add nodes to a phase changing other nodes phases if necessary. This function move boundary *forward* this means that all nodes @@ -691,9 +693,11 @@ Returns a set of revs whose phase is changed or should be changed """ + if revs is None: + revs = [] phcache = repo._phasecache.copy() changes = phcache.advanceboundary( - repo, tr, targetphase, nodes, dryrun=dryrun + repo, tr, targetphase, nodes, revs=revs, dryrun=dryrun ) if not dryrun: repo._phasecache.replace(phcache) @@ -713,14 +717,14 @@ repo._phasecache.replace(phcache) -def registernew(repo, tr, targetphase, nodes): +def registernew(repo, tr, targetphase, revs): """register a new revision and its phase Code adding revisions to the repository should use this function to set new changeset in their target phase (or higher). """ phcache = repo._phasecache.copy() - phcache.registernew(repo, tr, targetphase, nodes) + phcache.registernew(repo, tr, targetphase, revs) repo._phasecache.replace(phcache)
--- a/mercurial/posix.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/posix.py Thu Dec 03 14:15:39 2020 -0500 @@ -76,7 +76,7 @@ def split(p): - '''Same as posixpath.split, but faster + """Same as posixpath.split, but faster >>> import posixpath >>> for f in [b'/absolute/path/to/file', @@ -88,7 +88,7 @@ ... b'///multiple_leading_separators_at_root', ... b'']: ... assert split(f) == posixpath.split(f), f - ''' + """ ht = p.rsplit(b'/', 1) if len(ht) == 1: return b'', p @@ -183,9 +183,9 @@ def copymode(src, dst, mode=None, enforcewritable=False): - '''Copy the file mode from the file at path src to dst. + """Copy the file mode from the file at path src to dst. If src doesn't exist, we're using mode instead. If mode is None, we're - using umask.''' + using umask.""" try: st_mode = os.lstat(src).st_mode & 0o777 except OSError as inst: @@ -359,24 +359,24 @@ def checkosfilename(path): - '''Check that the base-relative path is a valid filename on this platform. - Returns None if the path is ok, or a UI string describing the problem.''' + """Check that the base-relative path is a valid filename on this platform. + Returns None if the path is ok, or a UI string describing the problem.""" return None # on posix platforms, every path is ok def getfsmountpoint(dirpath): - '''Get the filesystem mount point from a directory (best-effort) + """Get the filesystem mount point from a directory (best-effort) Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. - ''' + """ return getattr(osutil, 'getfsmountpoint', lambda x: None)(dirpath) def getfstype(dirpath): - '''Get the filesystem type name from a directory (best-effort) + """Get the filesystem type name from a directory (best-effort) Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. - ''' + """ return getattr(osutil, 'getfstype', lambda x: None)(dirpath) @@ -419,7 +419,7 @@ if pycompat.isdarwin: def normcase(path): - ''' + """ Normalize a filename for OS X-compatible comparison: - escape-encode invalid characters - decompose to NFD @@ -434,7 +434,7 @@ 'e\\xcc\\x81' >>> normcase(b'\\xb8\\xca\\xc3\\xca\\xbe\\xc8.JPG') # issue3918 '%b8%ca%c3\\xca\\xbe%c8.jpg' - ''' + """ try: return encoding.asciilower(path) # exception for non-ASCII @@ -475,7 +475,12 @@ # default mount points cygwinmountpoints = sorted( - [b"/usr/bin", b"/usr/lib", b"/cygdrive",], reverse=True + [ + b"/usr/bin", + b"/usr/lib", + b"/cygdrive", + ], + reverse=True, ) # use upper-ing as normcase as same as NTFS workaround @@ -553,10 +558,10 @@ def findexe(command): - '''Find executable for command searching like which does. + """Find executable for command searching like which does. If command is a basename then PATH is searched for command. PATH isn't searched if command is an absolute or relative path. - If command isn't found None is returned.''' + If command isn't found None is returned.""" if pycompat.sysplatform == b'OpenVMS': return command @@ -587,8 +592,8 @@ def statfiles(files): - '''Stat each file in files. Yield each stat, or None if a file does not - exist or has a type we don't care about.''' + """Stat each file in files. Yield each stat, or None if a file does not + exist or has a type we don't care about.""" lstat = os.lstat getkind = stat.S_IFMT for nf in files:
--- a/mercurial/progress.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/progress.py Thu Dec 03 14:15:39 2020 -0500 @@ -251,7 +251,7 @@ return False def _calibrateestimate(self, topic, now, pos): - '''Adjust starttimes and startvals for topic so ETA works better + """Adjust starttimes and startvals for topic so ETA works better If progress is non-linear (ex. get much slower in the last minute), it's more friendly to only use a recent time span for ETA and speed @@ -260,7 +260,7 @@ [======================================> ] ^^^^^^^ estimateinterval, only use this for estimation - ''' + """ interval = self.estimateinterval if interval <= 0: return
--- a/mercurial/pure/bdiff.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/pure/bdiff.py Thu Dec 03 14:15:39 2020 -0500 @@ -51,7 +51,10 @@ shift += 1 r.append((a1, b1, l1 + shift)) prev = a2 + shift, b2 + shift, l2 - shift - r.append(prev) + + if prev is not None: + r.append(prev) + return r
--- a/mercurial/pure/charencode.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/pure/charencode.py Thu Dec 03 14:15:39 2020 -0500 @@ -21,17 +21,17 @@ def asciilower(s): - '''convert a string to lowercase if ASCII + """convert a string to lowercase if ASCII - Raises UnicodeDecodeError if non-ASCII characters are found.''' + Raises UnicodeDecodeError if non-ASCII characters are found.""" s.decode('ascii') return s.lower() def asciiupper(s): - '''convert a string to uppercase if ASCII + """convert a string to uppercase if ASCII - Raises UnicodeDecodeError if non-ASCII characters are found.''' + Raises UnicodeDecodeError if non-ASCII characters are found.""" s.decode('ascii') return s.upper()
--- a/mercurial/pure/mpatch.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/pure/mpatch.py Thu Dec 03 14:15:39 2020 -0500 @@ -15,8 +15,7 @@ class mpatchError(Exception): - """error raised when a delta cannot be decoded - """ + """error raised when a delta cannot be decoded""" # This attempts to apply a series of patches in time proportional to
--- a/mercurial/pure/osutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/pure/osutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -39,7 +39,7 @@ def listdir(path, stat=False, skip=None): - '''listdir(path, stat=False) -> list_of_tuples + """listdir(path, stat=False) -> list_of_tuples Return a sorted list containing information about the entries in the directory. @@ -51,7 +51,7 @@ Otherwise, each element is a 2-tuple: (name, type) - ''' + """ result = [] prefix = path if not prefix.endswith(pycompat.ossep): @@ -222,7 +222,7 @@ ) class posixfile(object): - '''a file object aiming for POSIX-like semantics + """a file object aiming for POSIX-like semantics CPython's open() returns a file that was opened *without* setting the _FILE_SHARE_DELETE flag, which causes rename and unlink to abort. @@ -231,7 +231,7 @@ renamed and deleted while they are held open. Note that if a file opened with posixfile is unlinked, the file remains but cannot be opened again or be recreated under the same name, - until all reading processes have closed the file.''' + until all reading processes have closed the file.""" def __init__(self, name, mode=b'r', bufsize=-1): if b'b' in mode: @@ -290,10 +290,11 @@ return getattr(self._file, name) def __setattr__(self, name, value): - '''mimics the read-only attributes of Python file objects + """mimics the read-only attributes of Python file objects by raising 'TypeError: readonly attribute' if someone tries: f = posixfile('foo.txt') - f.name = 'bla' ''' + f.name = 'bla' + """ return self._file.__setattr__(name, value) def __enter__(self):
--- a/mercurial/pure/parsers.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/pure/parsers.py Thu Dec 03 14:15:39 2020 -0500 @@ -94,7 +94,8 @@ def append(self, tup): if '_nodemap' in vars(self): self._nodemap[tup[7]] = len(self) - self._extra.append(tup) + data = _pack(indexformatng, *tup) + self._extra.append(data) def _check_index(self, i): if not isinstance(i, int): @@ -107,14 +108,13 @@ return nullitem self._check_index(i) if i >= self._lgt: - return self._extra[i - self._lgt] - index = self._calculate_index(i) - r = struct.unpack(indexformatng, self._data[index : index + indexsize]) - if i == 0: - e = list(r) - type = gettype(e[0]) - e[0] = offset_type(0, type) - return tuple(e) + data = self._extra[i - self._lgt] + else: + index = self._calculate_index(i) + data = self._data[index : index + indexsize] + r = _unpack(indexformatng, data) + if self._lgt and i == 0: + r = (offset_type(0, gettype(r[0])),) + r[1:] return r @@ -234,8 +234,7 @@ def parse_index_devel_nodemap(data, inline): - """like parse_index2, but alway return a PersistentNodeMapIndexObject - """ + """like parse_index2, but alway return a PersistentNodeMapIndexObject""" return PersistentNodeMapIndexObject(data), None
--- a/mercurial/rcutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/rcutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -39,13 +39,13 @@ def envrcitems(env=None): - '''Return [(section, name, value, source)] config items. + """Return [(section, name, value, source)] config items. The config items are extracted from environment variables specified by env, used to override systemrc, but not userrc. If env is not provided, encoding.environ will be used. - ''' + """ if env is None: env = encoding.environ checklist = [ @@ -73,7 +73,7 @@ def rccomponents(): - '''return an ordered [(type, obj)] about where to load configs. + """return an ordered [(type, obj)] about where to load configs. respect $HGRCPATH. if $HGRCPATH is empty, only .hg/hgrc of current repo is used. if $HGRCPATH is not set, the platform default will be used. @@ -84,7 +84,7 @@ obj is a string, and is the config file path. if type is 'items', obj is a list of (section, name, value, source) that should fill the config directly. If type is 'resource', obj is a tuple of (package name, resource name). - ''' + """ envrc = (b'items', envrcitems()) if b'HGRCPATH' in encoding.environ: @@ -108,9 +108,9 @@ def defaultpagerenv(): - '''return a dict of default environment variables and their values, + """return a dict of default environment variables and their values, intended to be set before starting a pager. - ''' + """ return {b'LESS': b'FRX', b'LV': b'-c'}
--- a/mercurial/registrar.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/registrar.py Thu Dec 03 14:15:39 2020 -0500 @@ -37,7 +37,7 @@ keyword = registrar.keyword() - @keyword('bar') + @keyword(b'bar') def barfunc(*args, **kwargs): '''Explanation of bar keyword .... ''' @@ -95,8 +95,7 @@ self._table.update(registrarbase._table) def _parsefuncdecl(self, decl): - """Parse function declaration and return the name of function in it - """ + """Parse function declaration and return the name of function in it""" i = decl.find(b'(') if i >= 0: return decl[:i] @@ -121,8 +120,7 @@ return self._docformat % (decl, doc) def _extrasetup(self, name, func): - """Execute extra setup for registered function, if needed - """ + """Execute extra setup for registered function, if needed""" class command(_funcregistrarbase): @@ -234,6 +232,12 @@ self._table[name] = func, list(options) return func + def rename(self, old, new): + """rename a command. Used to add aliases, debugstrip -> + debugstrip|strip + """ + self._table[new] = self._table.pop(old) + INTENT_READONLY = b'readonly' @@ -245,7 +249,7 @@ revsetpredicate = registrar.revsetpredicate() - @revsetpredicate('mypredicate(arg1, arg2[, arg3])') + @revsetpredicate(b'mypredicate(arg1, arg2[, arg3])') def mypredicatefunc(repo, subset, x): '''Explanation of this revset predicate .... ''' @@ -295,7 +299,7 @@ filesetpredicate = registrar.filesetpredicate() - @filesetpredicate('mypredicate()') + @filesetpredicate(b'mypredicate()') def mypredicatefunc(mctx, x): '''Explanation of this fileset predicate .... ''' @@ -339,8 +343,7 @@ class _templateregistrarbase(_funcregistrarbase): - """Base of decorator to register functions as template specific one - """ + """Base of decorator to register functions as template specific one""" _docformat = b":%s: %s" @@ -353,7 +356,7 @@ templatekeyword = registrar.templatekeyword() # new API (since Mercurial 4.6) - @templatekeyword('mykeyword', requires={'repo', 'ctx'}) + @templatekeyword(b'mykeyword', requires={b'repo', b'ctx'}) def mykeywordfunc(context, mapping): '''Explanation of this template keyword .... ''' @@ -385,7 +388,7 @@ templatefilter = registrar.templatefilter() - @templatefilter('myfilter', intype=bytes) + @templatefilter(b'myfilter', intype=bytes) def myfilterfunc(text): '''Explanation of this template filter .... ''' @@ -417,8 +420,8 @@ templatefunc = registrar.templatefunc() - @templatefunc('myfunc(arg1, arg2[, arg3])', argspec='arg1 arg2 arg3', - requires={'ctx'}) + @templatefunc(b'myfunc(arg1, arg2[, arg3])', argspec=b'arg1 arg2 arg3', + requires={b'ctx'}) def myfuncfunc(context, mapping, args): '''Explanation of this template function .... ''' @@ -457,7 +460,7 @@ internalmerge = registrar.internalmerge() - @internalmerge('mymerge', internalmerge.mergeonly, + @internalmerge(b'mymerge', internalmerge.mergeonly, onfailure=None, precheck=None, binary=False, symlink=False): def mymergefunc(repo, mynode, orig, fcd, fco, fca,
--- a/mercurial/repair.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/repair.py Thu Dec 03 14:15:39 2020 -0500 @@ -209,7 +209,8 @@ # transaction and makes assumptions that file storage is # using append-only files. We'll need some kind of storage # API to handle stripping for us. - offset = len(tr._entries) + oldfiles = set(tr._offsetmap.keys()) + oldfiles.update(tr._newfiles) tr.startgroup() cl.strip(striprev, tr) @@ -219,8 +220,11 @@ repo.file(fn).strip(striprev, tr) tr.endgroup() - for i in pycompat.xrange(offset, len(tr._entries)): - file, troffset, ignore = tr._entries[i] + entries = tr.readjournal() + + for file, troffset in entries: + if file in oldfiles: + continue with repo.svfs(file, b'a', checkambig=True) as fp: fp.truncate(troffset) if troffset == 0:
--- a/mercurial/repoview.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/repoview.py Thu Dec 03 14:15:39 2020 -0500 @@ -48,8 +48,7 @@ def pinnedrevs(repo): - """revisions blocking hidden changesets from being filtered - """ + """revisions blocking hidden changesets from being filtered""" cl = repo.changelog pinned = set()
--- a/mercurial/revlog.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/revlog.py Thu Dec 03 14:15:39 2020 -0500 @@ -668,7 +668,7 @@ if not self._chunkcache: self._chunkclear() # revnum -> (chain-length, sum-delta-length) - self._chaininfocache = {} + self._chaininfocache = util.lrucachedict(500) # revlog header -> revlog compressor self._decompressors = {} @@ -1491,8 +1491,8 @@ def lookup(self, id): """locate a node based on: - - revision number or str(revision number) - - nodeid or subset of hex nodeid + - revision number or str(revision number) + - nodeid or subset of hex nodeid """ n = self._match(id) if n is not None: @@ -1771,8 +1771,7 @@ return rev - 1 def issnapshot(self, rev): - """tells whether rev is a snapshot - """ + """tells whether rev is a snapshot""" if not self._sparserevlog: return self.deltaparent(rev) == nullrev elif util.safehasattr(self.index, b'issnapshot'): @@ -1819,7 +1818,7 @@ elif operation == b'read': return flagutil.processflagsread(self, text, flags) else: # write operation - return flagutil.processflagswrite(self, text, flags) + return flagutil.processflagswrite(self, text, flags, None) def revision(self, nodeorrev, _df=None, raw=False): """return an uncompressed revision of a given node or revision @@ -2000,21 +1999,13 @@ ): return - trinfo = tr.find(self.indexfile) - if trinfo is None: + troffset = tr.findoffset(self.indexfile) + if troffset is None: raise error.RevlogError( _(b"%s not found in the transaction") % self.indexfile ) - - trindex = trinfo[2] - if trindex is not None: - dataoff = self.start(trindex) - else: - # revlog was stripped at start of transaction, use all leftover data - trindex = len(self) - 1 - dataoff = self.end(tiprev) - - tr.add(self.datafile, dataoff) + trindex = 0 + tr.add(self.datafile, 0) if fp: fp.flush() @@ -2026,6 +2017,8 @@ with self._indexfp(b'r') as ifh, self._datafp(b'w') as dfh: for r in self: dfh.write(self._getsegmentforrevs(r, r, df=ifh)[1]) + if troffset <= self.start(r): + trindex = r with self._indexfp(b'w') as fp: self.version &= ~FLAG_INLINE_DATA @@ -2043,8 +2036,7 @@ self._chunkclear() def _nodeduplicatecallback(self, transaction, node): - """called when trying to add a node already stored. - """ + """called when trying to add a node already stored.""" def addrevision( self, @@ -2361,14 +2353,21 @@ ifh.write(entry) else: offset += curr * self._io.size - transaction.add(self.indexfile, offset, curr) + transaction.add(self.indexfile, offset) ifh.write(entry) ifh.write(data[0]) ifh.write(data[1]) self._enforceinlinesize(transaction, ifh) nodemaputil.setup_persistent_nodemap(transaction, self) - def addgroup(self, deltas, linkmapper, transaction, addrevisioncb=None): + def addgroup( + self, + deltas, + linkmapper, + transaction, + addrevisioncb=None, + duplicaterevisioncb=None, + ): """ add a delta group @@ -2383,8 +2382,6 @@ if self._writinghandles: raise error.ProgrammingError(b'cannot nest addgroup() calls') - nodes = [] - r = len(self) end = 0 if r: @@ -2392,10 +2389,10 @@ ifh = self._indexfp(b"a+") isize = r * self._io.size if self._inline: - transaction.add(self.indexfile, end + isize, r) + transaction.add(self.indexfile, end + isize) dfh = None else: - transaction.add(self.indexfile, isize, r) + transaction.add(self.indexfile, isize) transaction.add(self.datafile, end) dfh = self._datafp(b"a+") @@ -2405,6 +2402,7 @@ ifh.flush() self._writinghandles = (ifh, dfh) + empty = True try: deltacomputer = deltautil.deltacomputer(self) @@ -2414,11 +2412,12 @@ link = linkmapper(linknode) flags = flags or REVIDX_DEFAULT_FLAGS - nodes.append(node) - if self.index.has_node(node): + # this can happen if two branches make the same change self._nodeduplicatecallback(transaction, node) - # this can happen if two branches make the same change + if duplicaterevisioncb: + duplicaterevisioncb(self, node) + empty = False continue for p in (p1, p2): @@ -2472,6 +2471,7 @@ if addrevisioncb: addrevisioncb(self, node) + empty = False if not dfh and not self._inline: # addrevision switched from inline to conventional @@ -2486,8 +2486,7 @@ if dfh: dfh.close() ifh.close() - - return nodes + return not empty def iscensored(self, rev): """Check if a file revision is censored.""" @@ -2550,7 +2549,7 @@ # then reset internal state in memory to forget those revisions self._revisioncache = None - self._chaininfocache = {} + self._chaininfocache = util.lrucachedict(500) self._chunkclear() del self.index[rev:-1]
--- a/mercurial/revlogutils/nodemap.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/revlogutils/nodemap.py Thu Dec 03 14:15:39 2020 -0500 @@ -86,8 +86,7 @@ class _NoTransaction(object): - """transaction like object to update the nodemap outside a transaction - """ + """transaction like object to update the nodemap outside a transaction""" def __init__(self): self._postclose = {} @@ -129,8 +128,7 @@ def _persist_nodemap(tr, revlog, pending=False): - """Write nodemap data on disk for a given revlog - """ + """Write nodemap data on disk for a given revlog""" if getattr(revlog, 'filteredrevs', ()): raise error.ProgrammingError( "cannot persist nodemap of a filtered changelog" @@ -400,15 +398,13 @@ def persistent_data(index): - """return the persistent binary form for a nodemap for a given index - """ + """return the persistent binary form for a nodemap for a given index""" trie = _build_trie(index) return _persist_trie(trie) def update_persistent_data(index, root, max_idx, last_rev): - """return the incremental update for persistent nodemap from a given index - """ + """return the incremental update for persistent nodemap from a given index""" changed_block, trie = _update_trie(index, root, last_rev) return ( changed_block * S_BLOCK.size,
--- a/mercurial/revset.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/revset.py Thu Dec 03 14:15:39 2020 -0500 @@ -529,8 +529,7 @@ @predicate(b'author(string)', safe=True, weight=10) def author(repo, subset, x): - """Alias for ``user(string)``. - """ + """Alias for ``user(string)``.""" # i18n: "author" is a keyword n = getstring(x, _(b"author requires a string")) kind, pattern, matcher = _substringmatcher(n, casesensitive=False) @@ -737,8 +736,7 @@ @predicate(b'children(set)', safe=True) def children(repo, subset, x): - """Child changesets of changesets in set. - """ + """Child changesets of changesets in set.""" s = getset(repo, fullreposet(repo), x) cs = _children(repo, subset, s) return subset & cs @@ -746,8 +744,7 @@ @predicate(b'closed()', safe=True, weight=10) def closed(repo, subset, x): - """Changeset is closed. - """ + """Changeset is closed.""" # i18n: "closed" is a keyword getargs(x, 0, 0, _(b"closed takes no arguments")) return subset.filter( @@ -771,8 +768,7 @@ @predicate(b'commonancestors(set)', safe=True) def commonancestors(repo, subset, x): - """Changesets that are ancestors of every changeset in set. - """ + """Changesets that are ancestors of every changeset in set.""" startrevs = getset(repo, fullreposet(repo), x, order=anyorder) if not startrevs: return baseset() @@ -868,8 +864,7 @@ @predicate(b'date(interval)', safe=True, weight=10) def date(repo, subset, x): - """Changesets within the interval, see :hg:`help dates`. - """ + """Changesets within the interval, see :hg:`help dates`.""" # i18n: "date" is a keyword ds = getstring(x, _(b"date requires a string")) dm = dateutil.matchdate(ds) @@ -1108,8 +1103,7 @@ @predicate(b'extinct()', safe=True) def extinct(repo, subset, x): - """Obsolete changesets with obsolete descendants only. (EXPERIMENTAL) - """ + """Obsolete changesets with obsolete descendants only. (EXPERIMENTAL)""" # i18n: "extinct" is a keyword getargs(x, 0, 0, _(b"extinct takes no arguments")) extincts = obsmod.getrevs(repo, b'extinct') @@ -1216,8 +1210,7 @@ @predicate(b'first(set, [n])', safe=True, takeorder=True, weight=0) def first(repo, subset, x, order): - """An alias for limit(). - """ + """An alias for limit().""" return limit(repo, subset, x, order) @@ -1341,8 +1334,7 @@ @predicate(b'all()', safe=True) def getall(repo, subset, x): - """All changesets, the same as ``0:tip``. - """ + """All changesets, the same as ``0:tip``.""" # i18n: "all" is a keyword getargs(x, 0, 0, _(b"all takes no arguments")) return subset & spanset(repo) # drop "null" if any @@ -1480,8 +1472,7 @@ @predicate(b'head()', safe=True) def head(repo, subset, x): - """Changeset is a named branch head. - """ + """Changeset is a named branch head.""" # i18n: "head" is a keyword getargs(x, 0, 0, _(b"head takes no arguments")) hs = set() @@ -1493,8 +1484,7 @@ @predicate(b'heads(set)', safe=True, takeorder=True) def heads(repo, subset, x, order): - """Members of set with no children in set. - """ + """Members of set with no children in set.""" # argument set should never define order if order == defineorder: order = followorder @@ -1515,8 +1505,7 @@ @predicate(b'hidden()', safe=True) def hidden(repo, subset, x): - """Hidden changesets. - """ + """Hidden changesets.""" # i18n: "hidden" is a keyword getargs(x, 0, 0, _(b"hidden takes no arguments")) hiddenrevs = repoview.filterrevs(repo, b'visible') @@ -1546,8 +1535,7 @@ @predicate(b'limit(set[, n[, offset]])', safe=True, takeorder=True, weight=0) def limit(repo, subset, x, order): - """First n members of set, defaulting to 1, starting from offset. - """ + """First n members of set, defaulting to 1, starting from offset.""" args = getargsdict(x, b'limit', b'set n offset') if b'set' not in args: # i18n: "limit" is a keyword @@ -1571,8 +1559,7 @@ @predicate(b'last(set, [n])', safe=True, takeorder=True) def last(repo, subset, x, order): - """Last n members of set, defaulting to 1. - """ + """Last n members of set, defaulting to 1.""" # i18n: "last" is a keyword l = getargs(x, 1, 2, _(b"last requires one or two arguments")) lim = 1 @@ -1592,8 +1579,7 @@ @predicate(b'max(set)', safe=True) def maxrev(repo, subset, x): - """Changeset with highest revision number in set. - """ + """Changeset with highest revision number in set.""" os = getset(repo, fullreposet(repo), x) try: m = os.max() @@ -1608,8 +1594,7 @@ @predicate(b'merge()', safe=True) def merge(repo, subset, x): - """Changeset is a merge changeset. - """ + """Changeset is a merge changeset.""" # i18n: "merge" is a keyword getargs(x, 0, 0, _(b"merge takes no arguments")) cl = repo.changelog @@ -1626,8 +1611,7 @@ @predicate(b'branchpoint()', safe=True) def branchpoint(repo, subset, x): - """Changesets with more than one child. - """ + """Changesets with more than one child.""" # i18n: "branchpoint" is a keyword getargs(x, 0, 0, _(b"branchpoint takes no arguments")) cl = repo.changelog @@ -1648,8 +1632,7 @@ @predicate(b'min(set)', safe=True) def minrev(repo, subset, x): - """Changeset with lowest revision number in set. - """ + """Changeset with lowest revision number in set.""" os = getset(repo, fullreposet(repo), x) try: m = os.min() @@ -1715,8 +1698,7 @@ @predicate(b'id(string)', safe=True) def node_(repo, subset, x): - """Revision non-ambiguously specified by the given hex string prefix. - """ + """Revision non-ambiguously specified by the given hex string prefix.""" # i18n: "id" is a keyword l = getargs(x, 1, 1, _(b"id requires one argument")) # i18n: "id" is a keyword @@ -1747,8 +1729,7 @@ @predicate(b'none()', safe=True) def none(repo, subset, x): - """No changesets. - """ + """No changesets.""" # i18n: "none" is a keyword getargs(x, 0, 0, _(b"none takes no arguments")) return baseset() @@ -1869,8 +1850,7 @@ @predicate(b'p1([set])', safe=True) def p1(repo, subset, x): - """First parent of changesets in set, or the working directory. - """ + """First parent of changesets in set, or the working directory.""" if x is None: p = repo[x].p1().rev() if p >= 0: @@ -1892,8 +1872,7 @@ @predicate(b'p2([set])', safe=True) def p2(repo, subset, x): - """Second parent of changesets in set, or the working directory. - """ + """Second parent of changesets in set, or the working directory.""" if x is None: ps = repo[x].parents() try: @@ -2305,8 +2284,7 @@ @predicate(b'reverse(set)', safe=True, takeorder=True, weight=0) def reverse(repo, subset, x, order): - """Reverse order of set. - """ + """Reverse order of set.""" l = getset(repo, subset, x, order) if order == defineorder: l.reverse() @@ -2315,8 +2293,7 @@ @predicate(b'roots(set)', safe=True) def roots(repo, subset, x): - """Changesets in set with no parent changeset in set. - """ + """Changesets in set with no parent changeset in set.""" s = getset(repo, fullreposet(repo), x) parents = repo.changelog.parentrevs @@ -2556,8 +2533,7 @@ @predicate(b'orphan()', safe=True) def orphan(repo, subset, x): - """Non-obsolete changesets with obsolete ancestors. (EXPERIMENTAL) - """ + """Non-obsolete changesets with obsolete ancestors. (EXPERIMENTAL)""" # i18n: "orphan" is a keyword getargs(x, 0, 0, _(b"orphan takes no arguments")) orphan = obsmod.getrevs(repo, b'orphan') @@ -2566,8 +2542,7 @@ @predicate(b'unstable()', safe=True) def unstable(repo, subset, x): - """Changesets with instabilities. (EXPERIMENTAL) - """ + """Changesets with instabilities. (EXPERIMENTAL)""" # i18n: "unstable" is a keyword getargs(x, 0, 0, b'unstable takes no arguments') _unstable = set() @@ -2781,8 +2756,7 @@ def loadpredicate(ui, extname, registrarobj): - """Load revset predicates from specified registrarobj - """ + """Load revset predicates from specified registrarobj""" for name, func in pycompat.iteritems(registrarobj._table): symbols[name] = func if func._safe:
--- a/mercurial/revsetlang.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/revsetlang.py Thu Dec 03 14:15:39 2020 -0500 @@ -83,7 +83,7 @@ def tokenize(program, lookup=None, syminitletters=None, symletters=None): - ''' + """ Parse a revset statement into a stream of tokens ``syminitletters`` is the set of valid characters for the initial @@ -102,7 +102,7 @@ >>> list(tokenize(b"@::")) [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)] - ''' + """ if not isinstance(program, bytes): raise error.ProgrammingError( b'revset statement must be bytes, got %r' % program @@ -558,14 +558,22 @@ >>> _parsewith(b'foo($1)', syminitletters=_aliassyminitletters) ('func', ('symbol', 'foo'), ('symbol', '$1')) - >>> _parsewith(b'$1') - Traceback (most recent call last): - ... - ParseError: ("syntax error in revset '$1'", 0) - >>> _parsewith(b'foo bar') - Traceback (most recent call last): - ... - ParseError: ('invalid token', 4) + >>> from . import error + >>> from . import pycompat + >>> try: + ... _parsewith(b'$1') + ... except error.ParseError as e: + ... pycompat.sysstr(e.message) + ... e.location + "syntax error in revset '$1'" + 0 + >>> try: + ... _parsewith(b'foo bar') + ... except error.ParseError as e: + ... pycompat.sysstr(e.message) + ... e.location + 'invalid token' + 4 """ if lookup and spec.startswith(b'revset(') and spec.endswith(b')'): lookup = None @@ -613,8 +621,7 @@ def foldconcat(tree): - """Fold elements to be concatenated by `##` - """ + """Fold elements to be concatenated by `##`""" if not isinstance(tree, tuple) or tree[0] in ( b'string', b'symbol', @@ -642,8 +649,8 @@ try: return _parsewith(spec, lookup=lookup) except error.ParseError as inst: - if len(inst.args) > 1: # has location - loc = inst.args[1] + if inst.location is not None: + loc = inst.location # Remove newlines -- spaces are equivalent whitespace. spec = spec.replace(b'\n', b' ') # We want the caret to point to the place in the template that @@ -734,7 +741,7 @@ def formatspec(expr, *args): - ''' + """ This is a convenience function for using revsets internally, and escapes arguments appropriately. Aliases are intentionally ignored so that intended expression behavior isn't accidentally subverted. @@ -769,7 +776,7 @@ "sort((:), 'desc', 'user')" >>> formatspec(b'%ls', [b'a', b"'"]) "_list('a\\\\x00\\\\'')" - ''' + """ parsed = _parseargs(expr, args) ret = [] for t, arg in parsed:
--- a/mercurial/rewriteutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/rewriteutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -33,20 +33,20 @@ if node.nullrev in revs: msg = _(b"cannot %s null changeset") % action hint = _(b"no changeset checked out") - raise error.Abort(msg, hint=hint) + raise error.InputError(msg, hint=hint) if len(repo[None].parents()) > 1: - raise error.Abort(_(b"cannot %s while merging") % action) + raise error.StateError(_(b"cannot %s while merging") % action) publicrevs = repo.revs(b'%ld and public()', revs) if publicrevs: msg = _(b"cannot %s public changesets") % action hint = _(b"see 'hg help phases' for details") - raise error.Abort(msg, hint=hint) + raise error.InputError(msg, hint=hint) newunstable = disallowednewunstable(repo, revs) if newunstable: - raise error.Abort(_(b"cannot %s changeset with children") % action) + raise error.InputError(_(b"cannot %s changeset with children") % action) def disallowednewunstable(repo, revs):
--- a/mercurial/scmposix.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/scmposix.py Thu Dec 03 14:15:39 2020 -0500 @@ -27,7 +27,7 @@ rcs.extend( [ os.path.join(rcdir, f) - for f, kind in util.listdir(rcdir) + for f, kind in sorted(util.listdir(rcdir)) if f.endswith(b".rc") ] )
--- a/mercurial/scmutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/scmutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -66,11 +66,11 @@ @attr.s(slots=True, repr=False) class status(object): - '''Struct with a list of files per status. + """Struct with a list of files per status. The 'deleted', 'unknown' and 'ignored' properties are only relevant to the working copy. - ''' + """ modified = attr.ib(default=attr.Factory(list)) added = attr.ib(default=attr.Factory(list)) @@ -123,9 +123,9 @@ def nochangesfound(ui, repo, excluded=None): - '''Report no changes for push/pull, excluded is None or a list of + """Report no changes for push/pull, excluded is None or a list of nodes excluded from the push/pull. - ''' + """ secretlist = [] if excluded: for n in excluded: @@ -148,6 +148,8 @@ return func() if no exception happens. otherwise do some error handling and return an exit code accordingly. does not handle all exceptions. """ + coarse_exit_code = -1 + detailed_exit_code = -1 try: try: return func() @@ -157,6 +159,7 @@ # Global exception handling, alphabetically # Mercurial-specific first, followed by built-in and library exceptions except error.LockHeld as inst: + detailed_exit_code = 20 if inst.errno == errno.ETIMEDOUT: reason = _(b'timed out waiting for lock held by %r') % ( pycompat.bytestr(inst.locker) @@ -170,6 +173,7 @@ if not inst.locker: ui.error(_(b"(lock might be very busy)\n")) except error.LockUnavailable as inst: + detailed_exit_code = 20 ui.error( _(b"abort: could not lock %s: %s\n") % ( @@ -178,6 +182,7 @@ ) ) except error.OutOfBandError as inst: + detailed_exit_code = 100 if inst.args: msg = _(b"abort: remote error:\n") else: @@ -188,7 +193,7 @@ if inst.hint: ui.error(b'(%s)\n' % inst.hint) except error.RepoError as inst: - ui.error(_(b"abort: %s!\n") % inst) + ui.error(_(b"abort: %s\n") % inst) if inst.hint: ui.error(_(b"(%s)\n") % inst.hint) except error.ResponseError as inst: @@ -203,43 +208,57 @@ else: ui.error(b"\n%r\n" % pycompat.bytestr(stringutil.ellipsis(msg))) except error.CensoredNodeError as inst: - ui.error(_(b"abort: file censored %s!\n") % inst) + ui.error(_(b"abort: file censored %s\n") % inst) except error.StorageError as inst: - ui.error(_(b"abort: %s!\n") % inst) + ui.error(_(b"abort: %s\n") % inst) if inst.hint: ui.error(_(b"(%s)\n") % inst.hint) except error.InterventionRequired as inst: ui.error(b"%s\n" % inst) if inst.hint: ui.error(_(b"(%s)\n") % inst.hint) - return 1 + detailed_exit_code = 240 + coarse_exit_code = 1 except error.WdirUnsupported: ui.error(_(b"abort: working directory revision cannot be specified\n")) except error.Abort as inst: - ui.error(_(b"abort: %s\n") % inst.message) - if inst.hint: - ui.error(_(b"(%s)\n") % inst.hint) + if isinstance(inst, (error.InputError, error.ParseError)): + detailed_exit_code = 10 + elif isinstance(inst, error.StateError): + detailed_exit_code = 20 + elif isinstance(inst, error.ConfigError): + detailed_exit_code = 30 + elif isinstance(inst, error.SecurityError): + detailed_exit_code = 150 + elif isinstance(inst, error.CanceledError): + detailed_exit_code = 250 + ui.error(inst.format()) + except error.WorkerError as inst: + # Don't print a message -- the worker already should have + return inst.status_code except ImportError as inst: - ui.error(_(b"abort: %s!\n") % stringutil.forcebytestr(inst)) + ui.error(_(b"abort: %s\n") % stringutil.forcebytestr(inst)) m = stringutil.forcebytestr(inst).split()[-1] if m in b"mpatch bdiff".split(): ui.error(_(b"(did you forget to compile extensions?)\n")) elif m in b"zlib".split(): ui.error(_(b"(is your Python install correct?)\n")) + except util.urlerr.httperror as inst: + detailed_exit_code = 100 + ui.error(_(b"abort: %s\n") % stringutil.forcebytestr(inst)) + except util.urlerr.urlerror as inst: + detailed_exit_code = 100 + try: # usually it is in the form (errno, strerror) + reason = inst.reason.args[1] + except (AttributeError, IndexError): + # it might be anything, for example a string + reason = inst.reason + if isinstance(reason, pycompat.unicode): + # SSLError of Python 2.7.9 contains a unicode + reason = encoding.unitolocal(reason) + ui.error(_(b"abort: error: %s\n") % stringutil.forcebytestr(reason)) except (IOError, OSError) as inst: - if util.safehasattr(inst, b"code"): # HTTPError - ui.error(_(b"abort: %s\n") % stringutil.forcebytestr(inst)) - elif util.safehasattr(inst, b"reason"): # URLError or SSLError - try: # usually it is in the form (errno, strerror) - reason = inst.reason.args[1] - except (AttributeError, IndexError): - # it might be anything, for example a string - reason = inst.reason - if isinstance(reason, pycompat.unicode): - # SSLError of Python 2.7.9 contains a unicode - reason = encoding.unitolocal(reason) - ui.error(_(b"abort: error: %s\n") % stringutil.forcebytestr(reason)) - elif ( + if ( util.safehasattr(inst, b"args") and inst.args and inst.args[0] == errno.EPIPE @@ -263,34 +282,40 @@ except SystemExit as inst: # Commands shouldn't sys.exit directly, but give a return code. # Just in case catch this and and pass exit code to caller. - return inst.code + detailed_exit_code = 254 + coarse_exit_code = inst.code - return -1 + if ui.configbool(b'ui', b'detailed-exit-code'): + return detailed_exit_code + else: + return coarse_exit_code def checknewlabel(repo, lbl, kind): # Do not use the "kind" parameter in ui output. # It makes strings difficult to translate. if lbl in [b'tip', b'.', b'null']: - raise error.Abort(_(b"the name '%s' is reserved") % lbl) + raise error.InputError(_(b"the name '%s' is reserved") % lbl) for c in (b':', b'\0', b'\n', b'\r'): if c in lbl: - raise error.Abort( + raise error.InputError( _(b"%r cannot be used in a name") % pycompat.bytestr(c) ) try: int(lbl) - raise error.Abort(_(b"cannot use an integer as a name")) + raise error.InputError(_(b"cannot use an integer as a name")) except ValueError: pass if lbl.strip() != lbl: - raise error.Abort(_(b"leading or trailing whitespace in name %r") % lbl) + raise error.InputError( + _(b"leading or trailing whitespace in name %r") % lbl + ) def checkfilename(f): '''Check that the filename f is an acceptable filename for a tracked file''' if b'\r' in f or b'\n' in f: - raise error.Abort( + raise error.InputError( _(b"'\\n' and '\\r' disallowed in filenames: %r") % pycompat.bytestr(f) ) @@ -305,13 +330,13 @@ if msg: msg = b"%s: %s" % (msg, procutil.shellquote(f)) if abort: - raise error.Abort(msg) + raise error.InputError(msg) ui.warn(_(b"warning: %s\n") % msg) def checkportabilityalert(ui): - '''check if the user's config requests nothing, a warning, or abort for - non-portable filenames''' + """check if the user's config requests nothing, a warning, or abort for + non-portable filenames""" val = ui.config(b'ui', b'portablefilenames') lval = val.lower() bval = stringutil.parsebool(val) @@ -377,8 +402,8 @@ def walkrepos(path, followsym=False, seen_dirs=None, recurse=False): - '''yield every hg repository under path, always recursively. - The recurse flag will only control recursion into repo working dirs''' + """yield every hg repository under path, always recursively. + The recurse flag will only control recursion into repo working dirs""" def errhandler(err): if err.filename == path: @@ -768,7 +793,7 @@ def walkchangerevs(repo, revs, makefilematcher, prepare): - '''Iterate over files and the revs in a "windowed" way. + """Iterate over files and the revs in a "windowed" way. Callers most commonly need to iterate backwards over the history in which they are interested. Doing so has awful (quadratic-looking) @@ -780,7 +805,7 @@ This function returns an iterator yielding contexts. Before yielding each context, the iterator will first call the prepare - function on each context in the window in forward order.''' + function on each context in the window in forward order.""" if not revs: return [] @@ -872,17 +897,17 @@ def anypats(pats, opts): - '''Checks if any patterns, including --include and --exclude were given. + """Checks if any patterns, including --include and --exclude were given. Some commands (e.g. addremove) use this condition for deciding whether to print absolute or relative paths. - ''' + """ return bool(pats or opts.get(b'include') or opts.get(b'exclude')) def expandpats(pats): - '''Expand bare globs when running on windows. - On posix we assume it already has already been done by sh.''' + """Expand bare globs when running on windows. + On posix we assume it already has already been done by sh.""" if not util.expandglobs: return list(pats) ret = [] @@ -903,9 +928,9 @@ def matchandpats( ctx, pats=(), opts=None, globbed=False, default=b'relpath', badfn=None ): - '''Return a matcher and the patterns that were used. + """Return a matcher and the patterns that were used. The matcher will warn about bad matches, unless an alternate badfn callback - is provided.''' + is provided.""" if opts is None: opts = {} if not globbed and default == b'relpath': @@ -976,7 +1001,7 @@ def backuppath(ui, repo, filepath): - '''customize where working copy backup files (.orig files) are created + """customize where working copy backup files (.orig files) are created Fetch user defined path from config file: [ui] origbackuppath = <path> Fall back to default (filepath with .orig suffix) if not specified @@ -984,7 +1009,7 @@ filepath is repo-relative Returns an absolute path - ''' + """ origvfs = getorigvfs(ui, repo) if origvfs is None: return repo.wjoin(filepath + b".orig") @@ -1275,8 +1300,8 @@ def marktouched(repo, files, similarity=0.0): - '''Assert that files have somehow been operated upon. files are relative to - the repo root.''' + """Assert that files have somehow been operated upon. files are relative to + the repo root.""" m = matchfiles(repo, files, badfn=lambda x, y: rejected.append(x)) rejected = [] @@ -1310,11 +1335,11 @@ def _interestingfiles(repo, matcher): - '''Walk dirstate with matcher, looking for files that addremove would care + """Walk dirstate with matcher, looking for files that addremove would care about. This is different from dirstate.status because it doesn't care about - whether files are modified or clean.''' + whether files are modified or clean.""" added, unknown, deleted, removed, forgotten = [], [], [], [], [] audit_path = pathutil.pathauditor(repo.root, cached=True) @@ -1369,8 +1394,8 @@ def _markchanges(repo, unknown, deleted, renames): - '''Marks the files in unknown as added, the files in deleted as removed, - and the files in renames as copied.''' + """Marks the files in unknown as added, the files in deleted as removed, + and the files in renames as copied.""" wctx = repo[None] with repo.wlock(): wctx.forget(deleted) @@ -1399,10 +1424,10 @@ endrev = len(repo) def getrenamed(fn, rev): - '''looks up all renames for a file (up to endrev) the first + """looks up all renames for a file (up to endrev) the first time the file is given. It indexes on the changerev and only parses the manifest if linkrev != changerev. - Returns rename info for fn at changerev rev.''' + Returns rename info for fn at changerev rev.""" if fn not in rcache: rcache[fn] = {} fl = repo.file(fn) @@ -1523,7 +1548,7 @@ def filterrequirements(requirements): - """ filters the requirements into two sets: + """filters the requirements into two sets: wcreq: requirements which should be written in .hg/requires storereq: which should be written in .hg/store/requires @@ -1555,6 +1580,9 @@ writerequires(repo.vfs, wcreq) if storereq is not None: writerequires(repo.svfs, storereq) + elif repo.ui.configbool(b'format', b'usestore'): + # only remove store requires if we are using store + repo.svfs.tryunlink(b'requires') def writerequires(opener, requirements): @@ -1843,8 +1871,7 @@ def gdinitconfig(ui): - """helper function to know if a repo should be created as general delta - """ + """helper function to know if a repo should be created as general delta""" # experimental config: format.generaldelta return ui.configbool(b'format', b'generaldelta') or ui.configbool( b'format', b'usegeneraldelta' @@ -1852,8 +1879,7 @@ def gddeltaconfig(ui): - """helper function to know if incoming delta should be optimised - """ + """helper function to know if incoming delta should be optimised""" # experimental config: format.generaldelta return ui.configbool(b'format', b'generaldelta')
--- a/mercurial/scmwindows.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/scmwindows.py Thu Dec 03 14:15:39 2020 -0500 @@ -31,7 +31,7 @@ def _processdir(progrcd): if os.path.isdir(progrcd): - for f, kind in util.listdir(progrcd): + for f, kind in sorted(util.listdir(progrcd)): if f.endswith(b'.rc'): rcpath.append(os.path.join(progrcd, f))
--- a/mercurial/setdiscovery.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/setdiscovery.py Thu Dec 03 14:15:39 2020 -0500 @@ -292,9 +292,9 @@ ancestorsof=None, samplegrowth=1.05, ): - '''Return a tuple (common, anyincoming, remoteheads) used to identify + """Return a tuple (common, anyincoming, remoteheads) used to identify missing nodes from or in remote. - ''' + """ start = util.timer() roundtrips = 0 @@ -371,7 +371,10 @@ with remote.commandexecutor() as e: fheads = e.callcommand(b'heads', {}) fknown = e.callcommand( - b'known', {b'nodes': [clnode(r) for r in sample],} + b'known', + { + b'nodes': [clnode(r) for r in sample], + }, ) srvheadhashes, yesno = fheads.result(), fknown.result() @@ -449,7 +452,10 @@ with remote.commandexecutor() as e: yesno = e.callcommand( - b'known', {b'nodes': [clnode(r) for r in sample],} + b'known', + { + b'nodes': [clnode(r) for r in sample], + }, ).result() full = True
--- a/mercurial/shelve.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/shelve.py Thu Dec 03 14:15:39 2020 -0500 @@ -350,8 +350,7 @@ def _aborttransaction(repo, tr): - '''Abort current transaction for shelve/unshelve, but keep dirstate - ''' + """Abort current transaction for shelve/unshelve, but keep dirstate""" dirstatebackupname = b'dirstate.shelve' repo.dirstate.savebackup(tr, dirstatebackupname) tr.abort() @@ -564,6 +563,10 @@ scmutil.movedirstate(repo, parent, match) else: hg.update(repo, parent.node()) + ms = mergestatemod.mergestate.read(repo) + if not ms.unresolvedcount(): + ms.reset() + if origbranch != repo[b'.'].branch() and not _isbareshelve(pats, opts): repo.dirstate.setbranch(origbranch)
--- a/mercurial/similar.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/similar.py Thu Dec 03 14:15:39 2020 -0500 @@ -15,11 +15,11 @@ def _findexactmatches(repo, added, removed): - '''find renamed files that have no changes + """find renamed files that have no changes Takes a list of new filectxs and a list of removed filectxs, and yields (before, after) tuples of exact matches. - ''' + """ # Build table of removed files: {hash(fctx.data()): [fctx, ...]}. # We use hash() to discard fctx.data() from memory. hashes = {} @@ -77,11 +77,11 @@ def _findsimilarmatches(repo, added, removed, threshold): - '''find potentially renamed files based on similar file content + """find potentially renamed files based on similar file content Takes a list of new filectxs and a list of removed filectxs, and yields (before, after, score) tuples of partial matches. - ''' + """ copies = {} progress = repo.ui.makeprogress( _(b'searching for similar files'), unit=_(b'files'), total=len(removed)
--- a/mercurial/simplemerge.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/simplemerge.py Thu Dec 03 14:15:39 2020 -0500 @@ -57,8 +57,7 @@ def compare_range(a, astart, aend, b, bstart, bend): - """Compare a[astart:aend] == b[bstart:bend], without slicing. - """ + """Compare a[astart:aend] == b[bstart:bend], without slicing.""" if (aend - astart) != (bend - bstart): return False for ia, ib in zip( @@ -102,8 +101,7 @@ localorother=None, minimize=False, ): - """Return merge in cvs-like form. - """ + """Return merge in cvs-like form.""" self.conflicts = False newline = b'\n' if len(self.a) > 0:
--- a/mercurial/sshpeer.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/sshpeer.py Thu Dec 03 14:15:39 2020 -0500 @@ -121,8 +121,7 @@ return self._call(b'readline') def _call(self, methname, data=None): - """call <methname> on "main", forward output of "side" while blocking - """ + """call <methname> on "main", forward output of "side" while blocking""" # data can be '' or 0 if (data is not None and not data) or self._main.closed: _forwardoutput(self._ui, self._side)
--- a/mercurial/sslutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/sslutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -227,8 +227,7 @@ def commonssloptions(minimumprotocol): - """Return SSLContext options common to servers and clients. - """ + """Return SSLContext options common to servers and clients.""" if minimumprotocol not in configprotocols: raise ValueError(b'protocol value not supported: %s' % minimumprotocol) @@ -470,7 +469,7 @@ # closed # - see http://bugs.python.org/issue13721 if not sslsocket.cipher(): - raise error.Abort(_(b'ssl connection failed')) + raise error.SecurityError(_(b'ssl connection failed')) sslsocket._hgstate = { b'caloaded': caloaded, @@ -617,11 +616,11 @@ def _verifycert(cert, hostname): - '''Verify that cert (in socket.getpeercert() format) matches hostname. + """Verify that cert (in socket.getpeercert() format) matches hostname. CRLs is not handled. Returns error message if any problems are found and None on success. - ''' + """ if not cert: return _(b'no certificate received') @@ -736,10 +735,10 @@ peercert = sock.getpeercert(True) peercert2 = sock.getpeercert() except AttributeError: - raise error.Abort(_(b'%s ssl connection error') % host) + raise error.SecurityError(_(b'%s ssl connection error') % host) if not peercert: - raise error.Abort( + raise error.SecurityError( _(b'%s certificate error: no certificate received') % host ) @@ -801,7 +800,7 @@ else: section = b'hostsecurity' nice = b'%s:%s' % (hash, fmtfingerprint(peerfingerprints[hash])) - raise error.Abort( + raise error.SecurityError( _(b'certificate for %s has unexpected fingerprint %s') % (host, nice), hint=_(b'check %s configuration') % section, @@ -810,7 +809,7 @@ # Security is enabled but no CAs are loaded. We can't establish trust # for the cert so abort. if not sock._hgstate[b'caloaded']: - raise error.Abort( + raise error.SecurityError( _( b'unable to verify security of %s (no loaded CA certificates); ' b'refusing to connect' @@ -826,7 +825,7 @@ msg = _verifycert(peercert2, shost) if msg: - raise error.Abort( + raise error.SecurityError( _(b'%s certificate error: %s') % (host, msg), hint=_( b'set hostsecurity.%s:certfingerprints=%s '
--- a/mercurial/state.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/state.py Thu Dec 03 14:15:39 2020 -0500 @@ -55,7 +55,7 @@ """ def __init__(self, repo, fname): - """ repo is the repo object + """repo is the repo object fname is the file name in which data should be stored in .hg directory """ self._repo = repo @@ -105,11 +105,11 @@ class _statecheck(object): """a utility class that deals with multistep operations like graft, - histedit, bisect, update etc and check whether such commands - are in an unfinished conditition or not and return appropriate message - and hint. - It also has the ability to register and determine the states of any new - multistep operation or multistep command extension. + histedit, bisect, update etc and check whether such commands + are in an unfinished conditition or not and return appropriate message + and hint. + It also has the ability to register and determine the states of any new + multistep operation or multistep command extension. """ def __init__( @@ -173,7 +173,11 @@ return _( b"use 'hg %s --continue', 'hg %s --abort', " b"or 'hg %s --stop'" - ) % (self._opname, self._opname, self._opname,) + ) % ( + self._opname, + self._opname, + self._opname, + ) return self._cmdhint
--- a/mercurial/statprof.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/statprof.py Thu Dec 03 14:15:39 2020 -0500 @@ -411,11 +411,11 @@ def reset(frequency=None): - '''Clear out the state of the profiler. Do not call while the + """Clear out the state of the profiler. Do not call while the profiler is running. The optional frequency argument specifies the number of samples to - collect per second.''' + collect per second.""" assert state.profile_level == 0, b"Can't reset() while statprof is running" CodeSite.cache.clear() state.reset(frequency) @@ -525,8 +525,8 @@ def display_by_line(data, fp): - '''Print the profiler data with each sample line represented - as one row in a table. Sorted by self-time per line.''' + """Print the profiler data with each sample line represented + as one row in a table. Sorted by self-time per line.""" stats = SiteStats.buildstats(data.samples) stats.sort(reverse=True, key=lambda x: x.selfseconds()) @@ -554,9 +554,9 @@ def display_by_method(data, fp): - '''Print the profiler data with each sample function represented + """Print the profiler data with each sample function represented as one row in a table. Important lines within that function are - output as nested rows. Sorted by self-time per line.''' + output as nested rows. Sorted by self-time per line.""" fp.write( b'%5.5s %10.10s %7.7s %-8.8s\n' % (b'% ', b'cumulative', b'self', b'') @@ -732,6 +732,9 @@ i += 1 if i < len(stack): child.add(stack[i:], time) + else: + # Normally this is done by the .add() calls + child.count += time root = HotNode(None) lasttime = data.samples[0].time @@ -749,12 +752,8 @@ ] if site: indent = depth * 2 - 1 - filename = b'' - function = b'' - if len(node.children) > 0: - childsite = list(pycompat.itervalues(node.children))[0].site - filename = (childsite.filename() + b':').ljust(15) - function = childsite.function + filename = (site.filename() + b':').ljust(15) + function = site.function # lots of string formatting listpattern = ( @@ -769,10 +768,18 @@ filename, function, ) - codepattern = b'%' + (b'%d' % (55 - len(liststring))) + b's %d: %s' + # 4 to account for the word 'line' + spacing_len = max(4, 55 - len(liststring)) + prefix = b'' + if spacing_len == 4: + prefix = b', ' + + codepattern = b'%s%s %d: %s%s' codestring = codepattern % ( - b'line', + prefix, + b'line'.rjust(spacing_len), site.lineno, + b''.ljust(max(0, 4 - len(str(site.lineno)))), site.getsource(30), ) @@ -835,9 +842,9 @@ def simplifypath(path): - '''Attempt to make the path to a Python module easier to read by + """Attempt to make the path to a Python module easier to read by removing whatever part of the Python search path it was found - on.''' + on.""" if path in _pathcache: return _pathcache[path]
--- a/mercurial/store.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/store.py Thu Dec 03 14:15:39 2020 -0500 @@ -52,7 +52,7 @@ # This avoids a collision between a file named foo and a dir named # foo.i or foo.d def _encodedir(path): - ''' + """ >>> _encodedir(b'data/foo.i') 'data/foo.i' >>> _encodedir(b'data/foo.i/bla.i') @@ -61,7 +61,7 @@ 'data/foo.i.hg.hg/bla.i' >>> _encodedir(b'data/foo.i\\ndata/foo.i/bla.i\\ndata/foo.i.hg/bla.i\\n') 'data/foo.i\\ndata/foo.i.hg/bla.i\\ndata/foo.i.hg.hg/bla.i\\n' - ''' + """ return ( path.replace(b".hg/", b".hg.hg/") .replace(b".i/", b".i.hg/") @@ -73,14 +73,14 @@ def decodedir(path): - ''' + """ >>> decodedir(b'data/foo.i') 'data/foo.i' >>> decodedir(b'data/foo.i.hg/bla.i') 'data/foo.i/bla.i' >>> decodedir(b'data/foo.i.hg.hg/bla.i') 'data/foo.i.hg/bla.i' - ''' + """ if b".hg/" not in path: return path return ( @@ -91,14 +91,14 @@ def _reserved(): - ''' characters that are problematic for filesystems + """characters that are problematic for filesystems * ascii escapes (0..31) * ascii hi (126..255) * windows specials these characters will be escaped by encodefunctions - ''' + """ winreserved = [ord(x) for x in u'\\:*?"<>|'] for x in range(32): yield x @@ -109,7 +109,7 @@ def _buildencodefun(): - ''' + """ >>> enc, dec = _buildencodefun() >>> enc(b'nothing/special.txt') @@ -131,7 +131,7 @@ 'the~07quick~adshot' >>> dec(b'the~07quick~adshot') 'the\\x07quick\\xadshot' - ''' + """ e = b'_' xchr = pycompat.bytechr asciistr = list(map(xchr, range(127))) @@ -172,23 +172,23 @@ def encodefilename(s): - ''' + """ >>> encodefilename(b'foo.i/bar.d/bla.hg/hi:world?/HELLO') 'foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o' - ''' + """ return _encodefname(encodedir(s)) def decodefilename(s): - ''' + """ >>> decodefilename(b'foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o') 'foo.i/bar.d/bla.hg/hi:world?/HELLO' - ''' + """ return decodedir(_decodefname(s)) def _buildlowerencodefun(): - ''' + """ >>> f = _buildlowerencodefun() >>> f(b'nothing/special.txt') 'nothing/special.txt' @@ -198,7 +198,7 @@ 'hello~3aworld~3f' >>> f(b'the\\x07quick\\xADshot') 'the~07quick~adshot' - ''' + """ xchr = pycompat.bytechr cmap = {xchr(x): xchr(x) for x in pycompat.xrange(127)} for x in _reserved(): @@ -220,7 +220,7 @@ def _auxencode(path, dotencode): - ''' + """ Encodes filenames containing names reserved by Windows or which end in period or space. Does not touch other single reserved characters c. Specifically, c in '\\:*?"<>|' or ord(c) <= 31 are *not* encoded here. @@ -240,7 +240,7 @@ ['foo.~20'] >>> _auxencode([b' .foo'], True) ['~20.foo'] - ''' + """ for i, n in enumerate(path): if not n: continue @@ -305,7 +305,7 @@ def _hybridencode(path, dotencode): - '''encodes path with a length limit + """encodes path with a length limit Encodes all paths that begin with 'data/', according to the following. @@ -334,7 +334,7 @@ The string 'data/' at the beginning is replaced with 'dh/', if the hashed encoding was used. - ''' + """ path = encodedir(path) ef = _encodefname(path).split(b'/') res = b'/'.join(_auxencode(ef, dotencode)) @@ -444,11 +444,11 @@ return reversed(self._walk(b'', False)) def walk(self, matcher=None): - '''yields (unencoded, encoded, size) + """yields (unencoded, encoded, size) if a matcher is passed, storage files of only those tracked paths are passed with matches the matcher - ''' + """ # yield data files first for x in self.datafiles(matcher): yield x @@ -517,10 +517,10 @@ self.addls = set() def ensureloaded(self, warn=None): - '''read the fncache file if not already read. + """read the fncache file if not already read. If the file on disk is corrupted, raise. If warn is provided, - warn and keep going instead.''' + warn and keep going instead.""" if self.entries is None: self._load(warn)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/strip.py Thu Dec 03 14:15:39 2020 -0500 @@ -0,0 +1,282 @@ +from __future__ import absolute_import + +from .i18n import _ +from .pycompat import getattr +from . import ( + bookmarks as bookmarksmod, + cmdutil, + error, + hg, + lock as lockmod, + mergestate as mergestatemod, + node as nodemod, + pycompat, + registrar, + repair, + scmutil, + util, +) + +nullid = nodemod.nullid +release = lockmod.release + +cmdtable = {} +command = registrar.command(cmdtable) + + +def checklocalchanges(repo, force=False): + s = repo.status() + if not force: + cmdutil.checkunfinished(repo) + cmdutil.bailifchanged(repo) + else: + cmdutil.checkunfinished(repo, skipmerge=True) + return s + + +def _findupdatetarget(repo, nodes): + unode, p2 = repo.changelog.parents(nodes[0]) + currentbranch = repo[None].branch() + + if ( + util.safehasattr(repo, b'mq') + and p2 != nullid + and p2 in [x.node for x in repo.mq.applied] + ): + unode = p2 + elif currentbranch != repo[unode].branch(): + pwdir = b'parents(wdir())' + revset = b'max(((parents(%ln::%r) + %r) - %ln::%r) and branch(%s))' + branchtarget = repo.revs( + revset, nodes, pwdir, pwdir, nodes, pwdir, currentbranch + ) + if branchtarget: + cl = repo.changelog + unode = cl.node(branchtarget.first()) + + return unode + + +def strip( + ui, + repo, + revs, + update=True, + backup=True, + force=None, + bookmarks=None, + soft=False, +): + with repo.wlock(), repo.lock(): + + if update: + checklocalchanges(repo, force=force) + urev = _findupdatetarget(repo, revs) + hg.clean(repo, urev) + repo.dirstate.write(repo.currenttransaction()) + + if soft: + repair.softstrip(ui, repo, revs, backup) + else: + repair.strip(ui, repo, revs, backup) + + repomarks = repo._bookmarks + if bookmarks: + with repo.transaction(b'strip') as tr: + if repo._activebookmark in bookmarks: + bookmarksmod.deactivate(repo) + repomarks.applychanges(repo, tr, [(b, None) for b in bookmarks]) + for bookmark in sorted(bookmarks): + ui.write(_(b"bookmark '%s' deleted\n") % bookmark) + + +@command( + b"debugstrip", + [ + ( + b'r', + b'rev', + [], + _( + b'strip specified revision (optional, ' + b'can specify revisions without this ' + b'option)' + ), + _(b'REV'), + ), + ( + b'f', + b'force', + None, + _( + b'force removal of changesets, discard ' + b'uncommitted changes (no backup)' + ), + ), + (b'', b'no-backup', None, _(b'do not save backup bundle')), + ( + b'', + b'nobackup', + None, + _(b'do not save backup bundle (DEPRECATED)'), + ), + (b'n', b'', None, _(b'ignored (DEPRECATED)')), + ( + b'k', + b'keep', + None, + _(b"do not modify working directory during strip"), + ), + ( + b'B', + b'bookmark', + [], + _(b"remove revs only reachable from given bookmark"), + _(b'BOOKMARK'), + ), + ( + b'', + b'soft', + None, + _(b"simply drop changesets from visible history (EXPERIMENTAL)"), + ), + ], + _(b'hg debugstrip [-k] [-f] [-B bookmark] [-r] REV...'), + helpcategory=command.CATEGORY_MAINTENANCE, +) +def debugstrip(ui, repo, *revs, **opts): + """strip changesets and all their descendants from the repository + + The strip command removes the specified changesets and all their + descendants. If the working directory has uncommitted changes, the + operation is aborted unless the --force flag is supplied, in which + case changes will be discarded. + + If a parent of the working directory is stripped, then the working + directory will automatically be updated to the most recent + available ancestor of the stripped parent after the operation + completes. + + Any stripped changesets are stored in ``.hg/strip-backup`` as a + bundle (see :hg:`help bundle` and :hg:`help unbundle`). They can + be restored by running :hg:`unbundle .hg/strip-backup/BUNDLE`, + where BUNDLE is the bundle file created by the strip. Note that + the local revision numbers will in general be different after the + restore. + + Use the --no-backup option to discard the backup bundle once the + operation completes. + + Strip is not a history-rewriting operation and can be used on + changesets in the public phase. But if the stripped changesets have + been pushed to a remote repository you will likely pull them again. + + Return 0 on success. + """ + opts = pycompat.byteskwargs(opts) + backup = True + if opts.get(b'no_backup') or opts.get(b'nobackup'): + backup = False + + cl = repo.changelog + revs = list(revs) + opts.get(b'rev') + revs = set(scmutil.revrange(repo, revs)) + + with repo.wlock(): + bookmarks = set(opts.get(b'bookmark')) + if bookmarks: + repomarks = repo._bookmarks + if not bookmarks.issubset(repomarks): + raise error.Abort( + _(b"bookmark '%s' not found") + % b','.join(sorted(bookmarks - set(repomarks.keys()))) + ) + + # If the requested bookmark is not the only one pointing to a + # a revision we have to only delete the bookmark and not strip + # anything. revsets cannot detect that case. + nodetobookmarks = {} + for mark, node in pycompat.iteritems(repomarks): + nodetobookmarks.setdefault(node, []).append(mark) + for marks in nodetobookmarks.values(): + if bookmarks.issuperset(marks): + rsrevs = scmutil.bookmarkrevs(repo, marks[0]) + revs.update(set(rsrevs)) + if not revs: + with repo.lock(), repo.transaction(b'bookmark') as tr: + bmchanges = [(b, None) for b in bookmarks] + repomarks.applychanges(repo, tr, bmchanges) + for bookmark in sorted(bookmarks): + ui.write(_(b"bookmark '%s' deleted\n") % bookmark) + + if not revs: + raise error.Abort(_(b'empty revision set')) + + descendants = set(cl.descendants(revs)) + strippedrevs = revs.union(descendants) + roots = revs.difference(descendants) + + # if one of the wdir parent is stripped we'll need + # to update away to an earlier revision + update = any( + p != nullid and cl.rev(p) in strippedrevs + for p in repo.dirstate.parents() + ) + + rootnodes = {cl.node(r) for r in roots} + + q = getattr(repo, 'mq', None) + if q is not None and q.applied: + # refresh queue state if we're about to strip + # applied patches + if cl.rev(repo.lookup(b'qtip')) in strippedrevs: + q.applieddirty = True + start = 0 + end = len(q.applied) + for i, statusentry in enumerate(q.applied): + if statusentry.node in rootnodes: + # if one of the stripped roots is an applied + # patch, only part of the queue is stripped + start = i + break + del q.applied[start:end] + q.savedirty() + + revs = sorted(rootnodes) + if update and opts.get(b'keep'): + urev = _findupdatetarget(repo, revs) + uctx = repo[urev] + + # only reset the dirstate for files that would actually change + # between the working context and uctx + descendantrevs = repo.revs(b"only(., %d)", uctx.rev()) + changedfiles = [] + for rev in descendantrevs: + # blindly reset the files, regardless of what actually changed + changedfiles.extend(repo[rev].files()) + + # reset files that only changed in the dirstate too + dirstate = repo.dirstate + dirchanges = [f for f in dirstate if dirstate[f] != b'n'] + changedfiles.extend(dirchanges) + + repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles) + repo.dirstate.write(repo.currenttransaction()) + + # clear resolve state + mergestatemod.mergestate.clean(repo) + + update = False + + strip( + ui, + repo, + revs, + backup=backup, + update=update, + force=opts.get(b'force'), + bookmarks=bookmarks, + soft=opts[b'soft'], + ) + + return 0
--- a/mercurial/subrepo.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/subrepo.py Thu Dec 03 14:15:39 2020 -0500 @@ -49,9 +49,9 @@ def _expandedabspath(path): - ''' + """ get a path or url and if it is a path expand it and return an absolute path - ''' + """ expandedpath = util.urllocalpath(util.expandpath(path)) u = util.url(expandedpath) if not u.scheme: @@ -268,8 +268,7 @@ ) def bailifchanged(self, ignoreupdate=False, hint=None): - """raise Abort if subrepository is ``dirty()`` - """ + """raise Abort if subrepository is ``dirty()``""" dirtyreason = self.dirtyreason(ignoreupdate=ignoreupdate, missing=True) if dirtyreason: raise error.Abort(dirtyreason, hint=hint) @@ -291,8 +290,7 @@ raise NotImplementedError def phase(self, state): - """returns phase of specified state in the subrepository. - """ + """returns phase of specified state in the subrepository.""" return phases.public def remove(self): @@ -384,10 +382,10 @@ return total def walk(self, match): - ''' + """ walk recursively through the directory tree, finding all files matched by the match function - ''' + """ def forget(self, match, prefix, uipathfn, dryrun, interactive): return ([], []) @@ -423,9 +421,9 @@ return revid def unshare(self): - ''' + """ convert this repository from shared to normal storage. - ''' + """ def verify(self, onpush=False): """verify the revision of this repository that is held in `_state` is @@ -437,14 +435,12 @@ @propertycache def wvfs(self): - """return vfs to access the working directory of this subrepository - """ + """return vfs to access the working directory of this subrepository""" return vfsmod.vfs(self._ctx.repo().wvfs.join(self._path)) @propertycache def _relpath(self): - """return path to this subrepository as seen from outermost repository - """ + """return path to this subrepository as seen from outermost repository""" return self.wvfs.reljoin(reporelpath(self._ctx.repo()), self._path) @@ -503,10 +499,10 @@ return clean def _calcstorehash(self, remotepath): - '''calculate a unique "store hash" + """calculate a unique "store hash" This method is used to to detect when there are changes that may - require a push to a given remote path.''' + require a push to a given remote path.""" # sort the files that will be hashed in increasing (likely) file size filelist = (b'bookmarks', b'store/phaseroots', b'store/00changelog.i') yield b'# %s\n' % _expandedabspath(remotepath) @@ -525,11 +521,11 @@ return self._cachestorehashvfs.tryreadlines(cachefile, b'r') def _cachestorehash(self, remotepath): - '''cache the current store hash + """cache the current store hash Each remote repo requires its own store hash cache, because a subrepo store may be "clean" versus a given remote repo, but not versus another - ''' + """ cachefile = _getstorehashcachename(remotepath) with self._repo.lock(): storehash = list(self._calcstorehash(remotepath)) @@ -537,8 +533,7 @@ vfs.writelines(cachefile, storehash, mode=b'wb', notindexed=True) def _getctx(self): - '''fetch the context for this subrepo revision, possibly a workingctx - ''' + """fetch the context for this subrepo revision, possibly a workingctx""" if self._ctx.rev() is None: return self._repo[None] # workingctx if parent is workingctx else: @@ -1048,14 +1043,12 @@ @propertycache def wvfs(self): - """return own wvfs for efficiency and consistency - """ + """return own wvfs for efficiency and consistency""" return self._repo.wvfs @propertycache def _relpath(self): - """return path to this subrepository as seen from outermost repository - """ + """return path to this subrepository as seen from outermost repository""" # Keep consistent dir separators by avoiding vfs.join(self._path) return reporelpath(self._repo) @@ -1170,12 +1163,16 @@ externals.append(path) elif item == 'missing': missing.append(path) - if item not in ( - '', - 'normal', - 'unversioned', - 'external', - ) or props not in ('', 'none', 'normal'): + if ( + item + not in ( + '', + 'normal', + 'unversioned', + 'external', + ) + or props not in ('', 'none', 'normal') + ): changes.append(path) for path in changes: for ext in externals: @@ -1384,7 +1381,7 @@ @staticmethod def _checkversion(out): - '''ensure git version is new enough + """ensure git version is new enough >>> _checkversion = gitsubrepo._checkversion >>> _checkversion(b'git version 1.6.0') @@ -1405,7 +1402,7 @@ 'unknown' >>> _checkversion(b'no') 'unknown' - ''' + """ version = gitsubrepo._gitversion(out) # git 1.4.0 can't work at all, but 1.5.X can in at least some cases, # despite the docstring comment. For now, error on 1.4.0, warn on @@ -1516,9 +1513,9 @@ self._gitcommand([b'update-index', b'-q', b'--refresh']) def _gitbranchmap(self): - '''returns 2 things: + """returns 2 things: a map from git branch to revision - a map from revision to branches''' + a map from revision to branches""" branch2rev = {} rev2branch = {}
--- a/mercurial/tagmerge.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/tagmerge.py Thu Dec 03 14:15:39 2020 -0500 @@ -87,12 +87,12 @@ def readtagsformerge(ui, repo, lines, fn=b'', keeplinenums=False): - '''read the .hgtags file into a structure that is suitable for merging + """read the .hgtags file into a structure that is suitable for merging Depending on the keeplinenums flag, clear the line numbers associated with each tag. This is done because only the line numbers of the first parent are useful for merging. - ''' + """ filetags = tagsmod._readtaghist( ui, repo, lines, fn=fn, recode=None, calcnodelines=True )[1] @@ -104,7 +104,7 @@ def grouptagnodesbyline(tagnodes): - ''' + """ Group nearby nodes (i.e. those that must be written next to each other) The input is a list of [node, position] pairs, corresponding to a given tag @@ -118,7 +118,7 @@ position is None). The result is a list of [position, [consecutive node list]] - ''' + """ firstlinenum = None for hexnode, linenum in tagnodes: firstlinenum = linenum @@ -139,14 +139,14 @@ def writemergedtags(fcd, mergedtags): - ''' + """ write the merged tags while trying to minimize the diff to the first parent This function uses the ordering info stored on the merged tags dict to generate an .hgtags file which is correct (in the sense that its contents correspond to the result of the tag merge) while also being as close as possible to the first parent's .hgtags file. - ''' + """ # group the node-tag pairs that must be written next to each other for tname, taglist in list(mergedtags.items()): mergedtags[tname] = grouptagnodesbyline(taglist) @@ -175,12 +175,12 @@ def singletagmerge(p1nodes, p2nodes): - ''' + """ merge the nodes corresponding to a single tag Note that the inputs are lists of node-linenum pairs (i.e. not just lists of nodes) - ''' + """ if not p2nodes: return p1nodes if not p1nodes: @@ -221,10 +221,10 @@ def merge(repo, fcd, fco, fca): - ''' + """ Merge the tags of two revisions, taking into account the base tags Try to minimize the diff between the merged tags and the first parent tags - ''' + """ ui = repo.ui # read the p1, p2 and base tags # only keep the line numbers for the p1 tags
--- a/mercurial/tags.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/tags.py Thu Dec 03 14:15:39 2020 -0500 @@ -177,12 +177,12 @@ def findglobaltags(ui, repo): - '''Find global tags in a repo: return a tagsmap + """Find global tags in a repo: return a tagsmap tagsmap: tag name to (node, hist) 2-tuples. The tags cache is read and updated as a side-effect of calling. - ''' + """ (heads, tagfnode, valid, cachetags, shouldwrite) = _readtagcache(ui, repo) if cachetags is not None: assert not shouldwrite @@ -267,7 +267,7 @@ def _readtaghist(ui, repo, lines, fn, recode=None, calcnodelines=False): - '''Read tag definitions from a file (or any source of lines). + """Read tag definitions from a file (or any source of lines). This function returns two sortdicts with similar information: @@ -283,7 +283,7 @@ When calcnodelines is False the hextaglines dict is not calculated (an empty dict is returned). This is done to improve this function's performance in cases where the line numbers are not needed. - ''' + """ bintaghist = util.sortdict() hextaglines = util.sortdict() @@ -325,14 +325,14 @@ def _readtags(ui, repo, lines, fn, recode=None, calcnodelines=False): - '''Read tag definitions from a file (or any source of lines). + """Read tag definitions from a file (or any source of lines). Returns a mapping from tag name to (node, hist). "node" is the node id from the last line read for that name. "hist" is the list of node ids previously associated with it (in file order). All node ids are binary, not hex. - ''' + """ filetags, nodelines = _readtaghist( ui, repo, lines, fn, recode=recode, calcnodelines=calcnodelines ) @@ -390,7 +390,7 @@ def _readtagcache(ui, repo): - '''Read the tag cache. + """Read the tag cache. Returns a tuple (heads, fnodes, validinfo, cachetags, shouldwrite). @@ -406,7 +406,7 @@ If the cache is not up to date, the caller is responsible for reading tag info from each returned head. (See findglobaltags().) - ''' + """ try: cachefile = repo.cachevfs(_filename(repo), b'r') # force reading the file for static-http @@ -549,7 +549,7 @@ def tag(repo, names, node, message, local, user, date, editor=False): - '''tag a revision with one or more symbolic names. + """tag a revision with one or more symbolic names. names is a list of strings or, when adding a single tag, names may be a string. @@ -567,7 +567,7 @@ user: name of user to use if committing - date: date tuple to use if committing''' + date: date tuple to use if committing""" if not local: m = matchmod.exact([b'.hgtags']) @@ -759,7 +759,7 @@ properprefix = node[0:4] # Validate and return existing entry. - if record != _fnodesmissingrec: + if record != _fnodesmissingrec and len(record) == _fnodesrecsize: fileprefix = record[0:4] if fileprefix == properprefix:
--- a/mercurial/templatefilters.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/templatefilters.py Thu Dec 03 14:15:39 2020 -0500 @@ -548,8 +548,7 @@ def loadfilter(ui, extname, registrarobj): - """Load template filter from specified registrarobj - """ + """Load template filter from specified registrarobj""" for name, func in pycompat.iteritems(registrarobj._table): filters[name] = func
--- a/mercurial/templatefuncs.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/templatefuncs.py Thu Dec 03 14:15:39 2020 -0500 @@ -912,8 +912,7 @@ def loadfunction(ui, extname, registrarobj): - """Load template function from specified registrarobj - """ + """Load template function from specified registrarobj""" for name, func in pycompat.iteritems(registrarobj._table): funcs[name] = func
--- a/mercurial/templatekw.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/templatekw.py Thu Dec 03 14:15:39 2020 -0500 @@ -634,6 +634,19 @@ return b'' +@templatekeyword(b'onelinesummary', requires={b'ui', b'ctx'}) +def showonelinesummary(context, mapping): + """String. A one-line summary for the ctx (not including trailing newline). + The default template be overridden in command-templates.oneline-summary.""" + # Avoid cycle: + # mercurial.cmdutil -> mercurial.templatekw -> mercurial.cmdutil + from . import cmdutil + + ui = context.resource(mapping, b'ui') + ctx = context.resource(mapping, b'ctx') + return cmdutil.format_changeset_summary(ui, ctx) + + @templatekeyword(b'path', requires={b'fctx'}) def showpath(context, mapping): """String. Repository-absolute path of the current file. (EXPERIMENTAL)""" @@ -981,8 +994,7 @@ def loadkeyword(ui, extname, registrarobj): - """Load template keyword from specified registrarobj - """ + """Load template keyword from specified registrarobj""" for name, func in pycompat.iteritems(registrarobj._table): keywords[name] = func
--- a/mercurial/templater.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/templater.py Thu Dec 03 14:15:39 2020 -0500 @@ -312,9 +312,9 @@ def _addparseerrorhint(inst, tmpl): - if len(inst.args) <= 1: - return # no location - loc = inst.args[1] + if inst.location is None: + return + loc = inst.location # Offset the caret location by the number of newlines before the # location of the error, since we will replace one-char newlines # with the two-char literal r'\n'. @@ -376,14 +376,22 @@ ('string', 'foo') >>> parseexpr(b'foo(bar)') ('func', ('symbol', 'foo'), ('symbol', 'bar')) - >>> parseexpr(b'foo(') - Traceback (most recent call last): - ... - ParseError: ('not a prefix: end', 4) - >>> parseexpr(b'"foo" "bar"') - Traceback (most recent call last): - ... - ParseError: ('invalid token', 7) + >>> from . import error + >>> from . import pycompat + >>> try: + ... parseexpr(b'foo(') + ... except error.ParseError as e: + ... pycompat.sysstr(e.message) + ... e.location + 'not a prefix: end' + 4 + >>> try: + ... parseexpr(b'"foo" "bar"') + ... except error.ParseError as e: + ... pycompat.sysstr(e.message) + ... e.location + 'invalid token' + 7 """ try: return _parseexpr(expr) @@ -655,7 +663,7 @@ class engine(object): - '''template expansion engine. + """template expansion engine. template expansion works like this. a map file contains key=value pairs. if value is quoted, it is treated as string. otherwise, it @@ -672,7 +680,7 @@ {key%format}. filter uses function to transform value. syntax is - {key|filter1|filter2|...}.''' + {key|filter1|filter2|...}.""" def __init__(self, loader, filters=None, defaults=None, resources=None): self._loader = loader @@ -773,9 +781,9 @@ return False def process(self, t, mapping): - '''Perform expansion. t is name of map element to expand. + """Perform expansion. t is name of map element to expand. mapping contains added elements for use during expansion. Is a - generator.''' + generator.""" func, data = self._load(t) return self._expand(func, data, mapping) @@ -849,7 +857,11 @@ if subresource: data = subresource.read() conf.parse( - abs, data, sections=sections, remap=remap, include=include, + abs, + data, + sections=sections, + remap=remap, + include=include, ) data = fp.read() @@ -1086,12 +1098,12 @@ def open_template(name, templatepath=None): - '''returns a file-like object for the given template, and its full path + """returns a file-like object for the given template, and its full path If the name is a relative path and we're in a frozen binary, the template will be read from the mercurial.templates package instead. The returned path will then be the relative path. - ''' + """ # Does the name point directly to a map file? if os.path.isfile(name) or os.path.isabs(name): return name, open(name, mode='rb')
--- a/mercurial/testing/storage.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/testing/storage.py Thu Dec 03 14:15:39 2020 -0500 @@ -1021,7 +1021,12 @@ def testcensored(self): f = self._makefilefn() - stored1 = storageutil.packmeta({b'censored': b'tombstone',}, b'') + stored1 = storageutil.packmeta( + { + b'censored': b'tombstone', + }, + b'', + ) with self._maketransactionfn() as tr: node0 = f.add(b'foo', None, tr, 0, nullid, nullid) @@ -1050,7 +1055,12 @@ f = self._makefilefn() - stored1 = storageutil.packmeta({b'censored': b'tombstone',}, b'') + stored1 = storageutil.packmeta( + { + b'censored': b'tombstone', + }, + b'', + ) with self._maketransactionfn() as tr: node0 = f.add(b'foo', None, tr, 0, nullid, nullid) @@ -1117,7 +1127,22 @@ return 0 with self._maketransactionfn() as tr: - nodes = f.addgroup([], None, tr, addrevisioncb=cb) + nodes = [] + + def onchangeset(cl, node): + nodes.append(node) + cb(cl, node) + + def ondupchangeset(cl, node): + nodes.append(node) + + f.addgroup( + [], + None, + tr, + addrevisioncb=onchangeset, + duplicaterevisioncb=ondupchangeset, + ) self.assertEqual(nodes, []) self.assertEqual(callbackargs, []) @@ -1136,7 +1161,22 @@ ] with self._maketransactionfn() as tr: - nodes = f.addgroup(deltas, linkmapper, tr, addrevisioncb=cb) + nodes = [] + + def onchangeset(cl, node): + nodes.append(node) + cb(cl, node) + + def ondupchangeset(cl, node): + nodes.append(node) + + f.addgroup( + deltas, + linkmapper, + tr, + addrevisioncb=onchangeset, + duplicaterevisioncb=ondupchangeset, + ) self.assertEqual( nodes, @@ -1175,7 +1215,19 @@ deltas.append((nodes[i], nullid, nullid, nullid, nullid, delta, 0)) with self._maketransactionfn() as tr: - self.assertEqual(f.addgroup(deltas, lambda x: 0, tr), nodes) + newnodes = [] + + def onchangeset(cl, node): + newnodes.append(node) + + f.addgroup( + deltas, + lambda x: 0, + tr, + addrevisioncb=onchangeset, + duplicaterevisioncb=onchangeset, + ) + self.assertEqual(newnodes, nodes) self.assertEqual(len(f), len(deltas)) self.assertEqual(list(f.revs()), [0, 1, 2]) @@ -1190,7 +1242,12 @@ # Attempt to apply a delta made against a censored revision. f = self._makefilefn() - stored1 = storageutil.packmeta({b'censored': b'tombstone',}, b'') + stored1 = storageutil.packmeta( + { + b'censored': b'tombstone', + }, + b'', + ) with self._maketransactionfn() as tr: node0 = f.add(b'foo\n' * 30, None, tr, 0, nullid, nullid)
--- a/mercurial/transaction.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/transaction.py Thu Dec 03 14:15:39 2020 -0500 @@ -56,7 +56,7 @@ unlink=True, checkambigfiles=None, ): - for f, o, _ignore in entries: + for f, o in entries: if o or not unlink: checkambig = checkambigfiles and (f, b'') in checkambigfiles try: @@ -158,8 +158,8 @@ vfsmap[b''] = opener # set default value self._vfsmap = vfsmap self._after = after - self._entries = [] - self._map = {} + self._offsetmap = {} + self._newfiles = set() self._journal = journalname self._undoname = undoname self._queue = [] @@ -180,7 +180,7 @@ # a dict of arguments to be passed to hooks self.hookargs = {} - self._file = opener.open(self._journal, b"w") + self._file = opener.open(self._journal, b"w+") # a list of ('location', 'path', 'backuppath', cache) entries. # - if 'backuppath' is empty, no file existed at backup time @@ -243,26 +243,36 @@ This is used by strip to delay vision of strip offset. The transaction sees either none or all of the strip actions to be done.""" q = self._queue.pop() - for f, o, data in q: - self._addentry(f, o, data) + for f, o in q: + self._addentry(f, o) @active - def add(self, file, offset, data=None): + def add(self, file, offset): """record the state of an append-only file before update""" - if file in self._map or file in self._backupmap: + if ( + file in self._newfiles + or file in self._offsetmap + or file in self._backupmap + ): return if self._queue: - self._queue[-1].append((file, offset, data)) + self._queue[-1].append((file, offset)) return - self._addentry(file, offset, data) + self._addentry(file, offset) - def _addentry(self, file, offset, data): + def _addentry(self, file, offset): """add a append-only entry to memory and on-disk state""" - if file in self._map or file in self._backupmap: + if ( + file in self._newfiles + or file in self._offsetmap + or file in self._backupmap + ): return - self._entries.append((file, offset, data)) - self._map[file] = len(self._entries) - 1 + if offset: + self._offsetmap[file] = offset + else: + self._newfiles.add(file) # add enough data to the journal to do the truncate self._file.write(b"%s\0%d\n" % (file, offset)) self._file.flush() @@ -282,7 +292,11 @@ msg = b'cannot use transaction.addbackup inside "group"' raise error.ProgrammingError(msg) - if file in self._map or file in self._backupmap: + if ( + file in self._newfiles + or file in self._offsetmap + or file in self._backupmap + ): return vfs = self._vfsmap[location] dirname, filename = vfs.split(file) @@ -395,24 +409,39 @@ return any @active - def find(self, file): - if file in self._map: - return self._entries[self._map[file]] - if file in self._backupmap: - return self._backupentries[self._backupmap[file]] - return None + def findoffset(self, file): + if file in self._newfiles: + return 0 + return self._offsetmap.get(file) + + @active + def readjournal(self): + self._file.seek(0) + entries = [] + for l in self._file: + file, troffset = l.split(b'\0') + entries.append((file, int(troffset))) + return entries @active - def replace(self, file, offset, data=None): - ''' + def replace(self, file, offset): + """ replace can only replace already committed entries that are not pending in the queue - ''' - - if file not in self._map: + """ + if file in self._newfiles: + if not offset: + return + self._newfiles.remove(file) + self._offsetmap[file] = offset + elif file in self._offsetmap: + if not offset: + del self._offsetmap[file] + self._newfiles.add(file) + else: + self._offsetmap[file] = offset + else: raise KeyError(file) - index = self._map[file] - self._entries[index] = (file, offset, data) self._file.write(b"%s\0%d\n" % (file, offset)) self._file.flush() @@ -447,9 +476,9 @@ @active def writepending(self): - '''write pending file to temporary version + """write pending file to temporary version - This is used to allow hooks to view a transaction before commit''' + This is used to allow hooks to view a transaction before commit""" categories = sorted(self._pendingcallback) for cat in categories: # remove callback since the data will have been flushed @@ -460,8 +489,7 @@ @active def hasfinalize(self, category): - """check is a callback already exist for a category - """ + """check is a callback already exist for a category""" return category in self._finalizecallback @active @@ -504,11 +532,11 @@ @active def addvalidator(self, category, callback): - """ adds a callback to be called when validating the transaction. + """adds a callback to be called when validating the transaction. The transaction will be given as the first argument to the callback. - callback should raise exception if to abort transaction """ + callback should raise exception if to abort transaction""" self._validatecallback[category] = callback @active @@ -552,7 +580,8 @@ self._report( b"couldn't remove %s: %s\n" % (vfs.join(b), inst) ) - self._entries = [] + self._offsetmap = {} + self._newfiles = set() self._writeundo() if self._after: self._after() @@ -594,9 +623,9 @@ @active def abort(self): - '''abort the transaction (generally called on error, or when the + """abort the transaction (generally called on error, or when the transaction is not explicitly committed before going out of - scope)''' + scope)""" self._abort() def _writeundo(self): @@ -629,13 +658,14 @@ undobackupfile.close() def _abort(self): + entries = self.readjournal() self._count = 0 self._usages = 0 self._file.close() self._backupsfile.close() try: - if not self._entries and not self._backupentries: + if not entries and not self._backupentries: if self._backupjournal: self._opener.unlink(self._backupjournal) if self._journal: @@ -654,7 +684,7 @@ self._report, self._opener, self._vfsmap, - self._entries, + entries, self._backupentries, False, checkambigfiles=self._checkambigfiles, @@ -696,7 +726,7 @@ for l in lines: try: f, o = l.split(b'\0') - entries.append((f, int(o), None)) + entries.append((f, int(o))) except ValueError: report( _(b"couldn't read journal entry %r!\n") % pycompat.bytestr(l)
--- a/mercurial/treediscovery.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/treediscovery.py Thu Dec 03 14:15:39 2020 -0500 @@ -117,7 +117,10 @@ for p in pycompat.xrange(0, len(r), 10): with remote.commandexecutor() as e: branches = e.callcommand( - b'branches', {b'nodes': r[p : p + 10],} + b'branches', + { + b'nodes': r[p : p + 10], + }, ).result() for b in branches:
--- a/mercurial/txnutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/txnutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -13,20 +13,20 @@ def mayhavepending(root): - '''return whether 'root' may have pending changes, which are + """return whether 'root' may have pending changes, which are visible to this process. - ''' + """ return root == encoding.environ.get(b'HG_PENDING') def trypending(root, vfs, filename, **kwargs): - '''Open file to be read according to HG_PENDING environment variable + """Open file to be read according to HG_PENDING environment variable This opens '.pending' of specified 'filename' only when HG_PENDING is equal to 'root'. This returns '(fp, is_pending_opened)' tuple. - ''' + """ if mayhavepending(root): try: return (vfs(b'%s.pending' % filename, **kwargs), True)
--- a/mercurial/ui.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/ui.py Thu Dec 03 14:15:39 2020 -0500 @@ -60,6 +60,8 @@ # The config knobs that will be altered (if unset) by ui.tweakdefaults. tweakrc = b""" [ui] +# Gives detailed exit codes for input/user errors, config errors, etc. +detailed-exit-code = True # The rollback command is dangerous. As a rule, don't use it. rollback = False # Make `hg status` report copy information @@ -464,10 +466,12 @@ try: cfg.read(filename, fp, sections=sections, remap=remap) - except error.ParseError as inst: + except error.ConfigError as inst: if trusted: raise - self.warn(_(b'ignored: %s\n') % stringutil.forcebytestr(inst)) + self.warn( + _(b'ignored %s: %s\n') % (inst.location, inst.message) + ) self._applyconfig(cfg, trusted, root) @@ -507,6 +511,8 @@ del cfg[b'defaults'][k] for k, v in cfg.items(b'commands'): del cfg[b'commands'][k] + for k, v in cfg.items(b'command-templates'): + del cfg[b'command-templates'][k] # Don't remove aliases from the configuration if in the exceptionlist if self.plain(b'alias'): for k, v in cfg.items(b'alias'): @@ -919,7 +925,7 @@ yield section, name, value def plain(self, feature=None): - '''is plain mode active? + """is plain mode active? Plain mode means that all configuration variables which affect the behavior and output of Mercurial should be @@ -933,7 +939,7 @@ - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT - False if feature is disabled by default and not included in HGPLAIN - True otherwise - ''' + """ if ( b'HGPLAIN' not in encoding.environ and b'HGPLAINEXCEPT' not in encoding.environ @@ -1106,7 +1112,7 @@ return self._colormode != b'win32' def write(self, *args, **opts): - '''write args to output + """write args to output By default, this method simply writes to the buffer or stdout. Color mode can be set on the UI class to have the output decorated @@ -1127,7 +1133,7 @@ When labeling output for a specific command, a label of "cmdname.type" is recommended. For example, status issues a label of "status.modified" for modified files. - ''' + """ dest = self._fout # inlined _write() for speed @@ -1447,9 +1453,9 @@ return _reqexithandlers def atexit(self, func, *args, **kwargs): - '''register a function to run after dispatching a request + """register a function to run after dispatching a request - Handlers do not stay registered across request boundaries.''' + Handlers do not stay registered across request boundaries.""" self._exithandlers.append((func, args, kwargs)) return func @@ -1478,8 +1484,14 @@ alldefaults = frozenset([b"text", b"curses"]) featureinterfaces = { - b"chunkselector": [b"text", b"curses",], - b"histedit": [b"text", b"curses",], + b"chunkselector": [ + b"text", + b"curses", + ], + b"histedit": [ + b"text", + b"curses", + ], } # Feature-specific interface @@ -1526,7 +1538,7 @@ return choseninterface def interactive(self): - '''is interactive input allowed? + """is interactive input allowed? An interactive session is a session where input can be reasonably read from `sys.stdin'. If this function returns false, any attempt to read @@ -1538,7 +1550,7 @@ to a terminal device. This function refers to input only; for output, see `ui.formatted()'. - ''' + """ i = self.configbool(b"ui", b"interactive") if i is None: # some environments replace stdin without implementing isatty @@ -1548,8 +1560,7 @@ return i def termwidth(self): - '''how wide is the terminal in columns? - ''' + """how wide is the terminal in columns?""" if b'COLUMNS' in encoding.environ: try: return int(encoding.environ[b'COLUMNS']) @@ -1558,7 +1569,7 @@ return scmutil.termsize(self)[0] def formatted(self): - '''should formatted output be used? + """should formatted output be used? It is often desirable to format the output to suite the output medium. Examples of this are truncating long lines or colorizing messages. @@ -1573,7 +1584,7 @@ This function refers to output only; for input, see `ui.interactive()'. This function always returns false when in plain mode, see `ui.plain()'. - ''' + """ if self.plain(): return False @@ -1740,40 +1751,40 @@ raise error.ResponseExpected() def status(self, *msg, **opts): - '''write status message to output (if ui.quiet is False) + """write status message to output (if ui.quiet is False) This adds an output label of "ui.status". - ''' + """ if not self.quiet: self._writemsg(self._fmsgout, type=b'status', *msg, **opts) def warn(self, *msg, **opts): - '''write warning message to output (stderr) + """write warning message to output (stderr) This adds an output label of "ui.warning". - ''' + """ self._writemsg(self._fmsgerr, type=b'warning', *msg, **opts) def error(self, *msg, **opts): - '''write error message to output (stderr) + """write error message to output (stderr) This adds an output label of "ui.error". - ''' + """ self._writemsg(self._fmsgerr, type=b'error', *msg, **opts) def note(self, *msg, **opts): - '''write note to output (if ui.verbose is True) + """write note to output (if ui.verbose is True) This adds an output label of "ui.note". - ''' + """ if self.verbose: self._writemsg(self._fmsgout, type=b'note', *msg, **opts) def debug(self, *msg, **opts): - '''write debug message to output (if ui.debugflag is True) + """write debug message to output (if ui.debugflag is True) This adds an output label of "ui.debug". - ''' + """ if self.debugflag: self._writemsg(self._fmsgout, type=b'debug', *msg, **opts) self.log(b'debug', b'%s', b''.join(msg)) @@ -1848,7 +1859,7 @@ self.system( b"%s \"%s\"" % (editor, name), environ=environ, - onerr=error.Abort, + onerr=error.CanceledError, errprefix=_(b"edit failed"), blockedtag=b'editor', ) @@ -1869,12 +1880,12 @@ errprefix=None, blockedtag=None, ): - '''execute shell command with appropriate output stream. command + """execute shell command with appropriate output stream. command output will be redirected if fout is not stdout. if command fails and onerr is None, return status, else raise onerr object as exception. - ''' + """ if blockedtag is None: # Long cmds tend to be because of an absolute path on cmd. Keep # the tail end instead @@ -1901,9 +1912,9 @@ return procutil.system(cmd, environ=environ, cwd=cwd, out=out) def traceback(self, exc=None, force=False): - '''print exception traceback if traceback printing enabled or forced. + """print exception traceback if traceback printing enabled or forced. only to call in exception handler. returns true if traceback - printed.''' + printed.""" if self.tracebackflag or force: if exc is None: exc = sys.exc_info() @@ -2005,7 +2016,7 @@ self._loggers[name] = logger def log(self, event, msgfmt, *msgargs, **opts): - '''hook for logging facility extensions + """hook for logging facility extensions event should be a readily-identifiable subsystem, which will allow filtering. @@ -2014,7 +2025,7 @@ *msgargs are %-formatted into it. **opts currently has no defined meanings. - ''' + """ if not self._loggers: return activeloggers = [ @@ -2034,7 +2045,7 @@ self._loggers = registeredloggers def label(self, msg, label): - '''style msg based on supplied label + """style msg based on supplied label If some color mode is enabled, this will add the necessary control characters to apply such color. In addition, 'debug' color mode adds @@ -2042,7 +2053,7 @@ ui.write(s, 'label') is equivalent to ui.write(ui.label(s, 'label')). - ''' + """ if self._colormode is not None: return color.colorlabel(self, msg, label) return msg
--- a/mercurial/unionrepo.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/unionrepo.py Thu Dec 03 14:15:39 2020 -0500 @@ -71,11 +71,11 @@ p1node = self.revlog2.node(p1rev) p2node = self.revlog2.node(p2rev) - # TODO: it's probably wrong to set compressed length to None, but + # TODO: it's probably wrong to set compressed length to -1, but # I have no idea if csize is valid in the base revlog context. e = ( flags, - None, + -1, rsize, base, link, @@ -129,6 +129,7 @@ linkmapper, transaction, addrevisioncb=None, + duplicaterevisioncb=None, maybemissingparents=False, ): raise NotImplementedError
--- a/mercurial/upgrade.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/upgrade.py Thu Dec 03 14:15:39 2020 -0500 @@ -80,6 +80,7 @@ requirements.SIDEDATA_REQUIREMENT, requirements.COPIESSDC_REQUIREMENT, requirements.NODEMAP_REQUIREMENT, + requirements.SHARESAFE_REQUIREMENT, } for name in compression.compengines: engine = compression.compengines[name] @@ -137,6 +138,7 @@ requirements.SIDEDATA_REQUIREMENT, requirements.COPIESSDC_REQUIREMENT, requirements.NODEMAP_REQUIREMENT, + requirements.SHARESAFE_REQUIREMENT, } for name in compression.compengines: engine = compression.compengines[name] @@ -151,8 +153,8 @@ return set() -deficiency = b'deficiency' -optimisation = b'optimization' +DEFICIENCY = b'deficiency' +OPTIMISATION = b'optimization' class improvement(object): @@ -165,14 +167,14 @@ will be mapped to an action later in the upgrade process. type - Either ``deficiency`` or ``optimisation``. A deficiency is an obvious + Either ``DEFICIENCY`` or ``OPTIMISATION``. A deficiency is an obvious problem. An optimization is an action (sometimes optional) that can be taken to further improve the state of the repository. description Message intended for humans explaining the improvement in more detail, - including the implications of it. For ``deficiency`` types, should be - worded in the present tense. For ``optimisation`` types, should be + including the implications of it. For ``DEFICIENCY`` types, should be + worded in the present tense. For ``OPTIMISATION`` types, should be worded in the future tense. upgrademessage @@ -210,7 +212,7 @@ class formatvariant(improvement): """an improvement subclass dedicated to repository format""" - type = deficiency + type = DEFICIENCY ### The following attributes should be defined for each class: # machine-readable string uniquely identifying this improvement. it will be @@ -218,7 +220,7 @@ name = None # message intended for humans explaining the improvement in more detail, - # including the implications of it ``deficiency`` types, should be worded + # including the implications of it ``DEFICIENCY`` types, should be worded # in the present tense. description = None @@ -337,6 +339,26 @@ @registerformatvariant +class sharedsafe(requirementformatvariant): + name = b'exp-sharesafe' + _requirement = requirements.SHARESAFE_REQUIREMENT + + default = False + + description = _( + b'old shared repositories do not share source repository ' + b'requirements and config. This leads to various problems ' + b'when the source repository format is upgraded or some new ' + b'extensions are enabled.' + ) + + upgrademessage = _( + b'Upgrades a repository to share-safe format so that future ' + b'shares of this repository share its requirements and configs.' + ) + + +@registerformatvariant class sparserevlog(requirementformatvariant): name = b'sparserevlog' @@ -541,96 +563,102 @@ b'redeltafulladd': b're-delta-fulladd', } +ALL_OPTIMISATIONS = [] + + +def register_optimization(obj): + ALL_OPTIMISATIONS.append(obj) + return obj + + +register_optimization( + improvement( + name=b're-delta-parent', + type=OPTIMISATION, + description=_( + b'deltas within internal storage will be recalculated to ' + b'choose an optimal base revision where this was not ' + b'already done; the size of the repository may shrink and ' + b'various operations may become faster; the first time ' + b'this optimization is performed could slow down upgrade ' + b'execution considerably; subsequent invocations should ' + b'not run noticeably slower' + ), + upgrademessage=_( + b'deltas within internal storage will choose a new ' + b'base revision if needed' + ), + ) +) + +register_optimization( + improvement( + name=b're-delta-multibase', + type=OPTIMISATION, + description=_( + b'deltas within internal storage will be recalculated ' + b'against multiple base revision and the smallest ' + b'difference will be used; the size of the repository may ' + b'shrink significantly when there are many merges; this ' + b'optimization will slow down execution in proportion to ' + b'the number of merges in the repository and the amount ' + b'of files in the repository; this slow down should not ' + b'be significant unless there are tens of thousands of ' + b'files and thousands of merges' + ), + upgrademessage=_( + b'deltas within internal storage will choose an ' + b'optimal delta by computing deltas against multiple ' + b'parents; may slow down execution time ' + b'significantly' + ), + ) +) + +register_optimization( + improvement( + name=b're-delta-all', + type=OPTIMISATION, + description=_( + b'deltas within internal storage will always be ' + b'recalculated without reusing prior deltas; this will ' + b'likely make execution run several times slower; this ' + b'optimization is typically not needed' + ), + upgrademessage=_( + b'deltas within internal storage will be fully ' + b'recomputed; this will likely drastically slow down ' + b'execution time' + ), + ) +) + +register_optimization( + improvement( + name=b're-delta-fulladd', + type=OPTIMISATION, + description=_( + b'every revision will be re-added as if it was new ' + b'content. It will go through the full storage ' + b'mechanism giving extensions a chance to process it ' + b'(eg. lfs). This is similar to "re-delta-all" but even ' + b'slower since more logic is involved.' + ), + upgrademessage=_( + b'each revision will be added as new content to the ' + b'internal storage; this will likely drastically slow ' + b'down execution time, but some extensions might need ' + b'it' + ), + ) +) + def findoptimizations(repo): """Determine optimisation that could be used during upgrade""" # These are unconditionally added. There is logic later that figures out # which ones to apply. - optimizations = [] - - optimizations.append( - improvement( - name=b're-delta-parent', - type=optimisation, - description=_( - b'deltas within internal storage will be recalculated to ' - b'choose an optimal base revision where this was not ' - b'already done; the size of the repository may shrink and ' - b'various operations may become faster; the first time ' - b'this optimization is performed could slow down upgrade ' - b'execution considerably; subsequent invocations should ' - b'not run noticeably slower' - ), - upgrademessage=_( - b'deltas within internal storage will choose a new ' - b'base revision if needed' - ), - ) - ) - - optimizations.append( - improvement( - name=b're-delta-multibase', - type=optimisation, - description=_( - b'deltas within internal storage will be recalculated ' - b'against multiple base revision and the smallest ' - b'difference will be used; the size of the repository may ' - b'shrink significantly when there are many merges; this ' - b'optimization will slow down execution in proportion to ' - b'the number of merges in the repository and the amount ' - b'of files in the repository; this slow down should not ' - b'be significant unless there are tens of thousands of ' - b'files and thousands of merges' - ), - upgrademessage=_( - b'deltas within internal storage will choose an ' - b'optimal delta by computing deltas against multiple ' - b'parents; may slow down execution time ' - b'significantly' - ), - ) - ) - - optimizations.append( - improvement( - name=b're-delta-all', - type=optimisation, - description=_( - b'deltas within internal storage will always be ' - b'recalculated without reusing prior deltas; this will ' - b'likely make execution run several times slower; this ' - b'optimization is typically not needed' - ), - upgrademessage=_( - b'deltas within internal storage will be fully ' - b'recomputed; this will likely drastically slow down ' - b'execution time' - ), - ) - ) - - optimizations.append( - improvement( - name=b're-delta-fulladd', - type=optimisation, - description=_( - b'every revision will be re-added as if it was new ' - b'content. It will go through the full storage ' - b'mechanism giving extensions a chance to process it ' - b'(eg. lfs). This is similar to "re-delta-all" but even ' - b'slower since more logic is involved.' - ), - upgrademessage=_( - b'each revision will be added as new content to the ' - b'internal storage; this will likely drastically slow ' - b'down execution time, but some extensions might need ' - b'it' - ), - ) - ) - - return optimizations + return list(ALL_OPTIMISATIONS) def determineactions(repo, deficiencies, sourcereqs, destreqs): @@ -716,10 +744,10 @@ UPGRADE_CHANGELOG = object() UPGRADE_MANIFEST = object() -UPGRADE_FILELOG = object() +UPGRADE_FILELOGS = object() UPGRADE_ALL_REVLOGS = frozenset( - [UPGRADE_CHANGELOG, UPGRADE_MANIFEST, UPGRADE_FILELOG] + [UPGRADE_CHANGELOG, UPGRADE_MANIFEST, UPGRADE_FILELOGS] ) @@ -753,7 +781,7 @@ return UPGRADE_CHANGELOG in revlogfilter elif entry.endswith(b'00manifest.i'): return UPGRADE_MANIFEST in revlogfilter - return UPGRADE_FILELOG in revlogfilter + return UPGRADE_FILELOGS in revlogfilter def _clonerevlogs( @@ -1146,6 +1174,7 @@ backup=True, manifest=None, changelog=None, + filelogs=None, ): """Upgrade a repository in place.""" if optimize is None: @@ -1154,25 +1183,23 @@ repo = repo.unfiltered() revlogs = set(UPGRADE_ALL_REVLOGS) - specentries = ((b'c', changelog), (b'm', manifest)) + specentries = ( + (UPGRADE_CHANGELOG, changelog), + (UPGRADE_MANIFEST, manifest), + (UPGRADE_FILELOGS, filelogs), + ) specified = [(y, x) for (y, x) in specentries if x is not None] if specified: # we have some limitation on revlogs to be recloned if any(x for y, x in specified): revlogs = set() - for r, enabled in specified: + for upgrade, enabled in specified: if enabled: - if r == b'c': - revlogs.add(UPGRADE_CHANGELOG) - elif r == b'm': - revlogs.add(UPGRADE_MANIFEST) + revlogs.add(upgrade) else: # none are enabled - for r, __ in specified: - if r == b'c': - revlogs.discard(UPGRADE_CHANGELOG) - elif r == b'm': - revlogs.discard(UPGRADE_MANIFEST) + for upgrade, __ in specified: + revlogs.discard(upgrade) # Ensure the repository can be upgraded. missingreqs = requiredsourcerequirements(repo) - repo.requirements @@ -1298,7 +1325,7 @@ ui.write(b'\n') def printoptimisations(): - optimisations = [a for a in actions if a.type == optimisation] + optimisations = [a for a in actions if a.type == OPTIMISATION] optimisations.sort(key=lambda a: a.name) if optimisations: ui.write(_(b'optimisations: ')) @@ -1434,3 +1461,21 @@ b'repository is verified\n' ) ) + + if sharedsafe.name in addedreqs: + ui.warn( + _( + b'repository upgraded to share safe mode, existing' + b' shares will still work in old non-safe mode. ' + b'Re-share existing shares to use them in safe mode' + b' New shares will be created in safe mode.\n' + ) + ) + if sharedsafe.name in removedreqs: + ui.warn( + _( + b'repository downgraded to not use share safe mode, ' + b'existing shares will not work and needs to' + b' be reshared.\n' + ) + )
--- a/mercurial/url.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/url.py Thu Dec 03 14:15:39 2020 -0500 @@ -35,13 +35,13 @@ def escape(s, quote=None): - '''Replace special characters "&", "<" and ">" to HTML-safe sequences. + """Replace special characters "&", "<" and ">" to HTML-safe sequences. If the optional flag quote is true, the quotation mark character (") is also translated. This is the same as cgi.escape in Python, but always operates on bytes, whereas cgi.escape in Python 3 only works on unicodes. - ''' + """ s = s.replace(b"&", b"&") s = s.replace(b"<", b"<") s = s.replace(b">", b">") @@ -586,7 +586,7 @@ loggingopts=None, sendaccept=True, ): - ''' + """ construct an opener suitable for urllib2 authinfo will be added to the password manager @@ -600,7 +600,7 @@ ``sendaccept`` allows controlling whether the ``Accept`` request header is sent. The header is sent by default. - ''' + """ timeout = ui.configwith(float, b'http', b'timeout') handlers = []
--- a/mercurial/urllibcompat.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/urllibcompat.py Thu Dec 03 14:15:39 2020 -0500 @@ -83,10 +83,22 @@ ) import urllib.response - urlreq._registeraliases(urllib.response, (b"addclosehook", b"addinfourl",)) + urlreq._registeraliases( + urllib.response, + ( + b"addclosehook", + b"addinfourl", + ), + ) import urllib.error - urlerr._registeraliases(urllib.error, (b"HTTPError", b"URLError",)) + urlerr._registeraliases( + urllib.error, + ( + b"HTTPError", + b"URLError", + ), + ) import http.server httpserver._registeraliases( @@ -179,12 +191,28 @@ b"urlopen", ), ) - urlreq._registeraliases(urlparse, (b"urlparse", b"urlunparse",)) + urlreq._registeraliases( + urlparse, + ( + b"urlparse", + b"urlunparse", + ), + ) urlreq._registeralias(urlparse, b"parse_qs", b"parseqs") urlreq._registeralias(urlparse, b"parse_qsl", b"parseqsl") - urlerr._registeraliases(urllib2, (b"HTTPError", b"URLError",)) + urlerr._registeraliases( + urllib2, + ( + b"HTTPError", + b"URLError", + ), + ) httpserver._registeraliases( - BaseHTTPServer, (b"HTTPServer", b"BaseHTTPRequestHandler",) + BaseHTTPServer, + ( + b"HTTPServer", + b"BaseHTTPRequestHandler", + ), ) httpserver._registeraliases( SimpleHTTPServer, (b"SimpleHTTPRequestHandler",)
--- a/mercurial/util.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/util.py Thu Dec 03 14:15:39 2020 -0500 @@ -1264,7 +1264,7 @@ class sortdict(collections.OrderedDict): - '''a simple sorted dictionary + """a simple sorted dictionary >>> d1 = sortdict([(b'a', 0), (b'b', 1)]) >>> d2 = d1.copy() @@ -1276,7 +1276,7 @@ >>> d1.insert(1, b'a.5', 0.5) >>> d1 sortdict([('a', 0), ('a.5', 0.5), ('b', 1)]) - ''' + """ def __setitem__(self, key, value): if key in self: @@ -1761,8 +1761,8 @@ def increasingchunks(source, min=1024, max=65536): - '''return no less than min bytes per chunk while data remains, - doubling min after each chunk until it reaches max''' + """return no less than min bytes per chunk while data remains, + doubling min after each chunk until it reaches max""" def log2(x): if not x: @@ -1833,7 +1833,7 @@ def pathto(root, n1, n2): - '''return the relative path from one place to another. + """return the relative path from one place to another. root should use os.sep to separate directories n1 should use os.sep to separate directories n2 should use "/" to separate directories @@ -1842,7 +1842,7 @@ If n1 is a relative path, it's assumed it's relative to root. n2 should always be relative to root. - ''' + """ if not n1: return localpath(n2) if os.path.isabs(n1): @@ -1892,7 +1892,7 @@ def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False): - '''copy a file, preserving mode and optionally other stat info like + """copy a file, preserving mode and optionally other stat info like atime/mtime checkambig argument is used with filestat, and is useful only if @@ -1900,7 +1900,7 @@ repo.wlock). copystat and checkambig should be exclusive. - ''' + """ assert not (copystat and checkambig) oldstat = None if os.path.lexists(dest): @@ -2017,7 +2017,7 @@ def checkwinfilename(path): - r'''Check that the base-relative path is a valid filename on Windows. + r"""Check that the base-relative path is a valid filename on Windows. Returns None if the path is ok, or a UI string describing the problem. >>> checkwinfilename(b"just/a/normal/path") @@ -2039,7 +2039,7 @@ "filename ends with '\\', which is invalid on Windows" >>> checkwinfilename(b"foo\\/bar") "directory name ends with '\\', which is invalid on Windows" - ''' + """ if path.endswith(b'\\'): return _(b"filename ends with '\\', which is invalid on Windows") if b'\\/' in path: @@ -2175,11 +2175,11 @@ _re2 = False def compile(self, pat, flags=0): - '''Compile a regular expression, using re2 if possible + """Compile a regular expression, using re2 if possible For best performance, use only re2-compatible regexp features. The only flags from the re module that are re2-compatible are - IGNORECASE and MULTILINE.''' + IGNORECASE and MULTILINE.""" if _re2 is None: self._checkre2() if _re2 and (flags & ~(remod.IGNORECASE | remod.MULTILINE)) == 0: @@ -2195,11 +2195,11 @@ @propertycache def escape(self): - '''Return the version of escape corresponding to self.compile. + """Return the version of escape corresponding to self.compile. This is imperfect because whether re2 or re is used for a particular function depends on the flags, etc, but it's the best we can do. - ''' + """ global _re2 if _re2 is None: self._checkre2() @@ -2215,7 +2215,7 @@ def fspath(name, root): - '''Get name in the case stored in the filesystem + """Get name in the case stored in the filesystem The name should be relative to root, and be normcase-ed for efficiency. @@ -2223,7 +2223,7 @@ called, for case-sensitive filesystems (simply because it's expensive). The root should be normcase-ed, too. - ''' + """ def _makefspathcacheentry(dir): return {normcase(n): n for n in os.listdir(dir)} @@ -2301,11 +2301,11 @@ def splitpath(path): - '''Split path by os.sep. + """Split path by os.sep. Note that this function does not use os.altsep because this is an alternative of simple "xxx.split(os.sep)". It is recommended to use os.path.normpath() before using this - function if need.''' + function if need.""" return path.split(pycompat.ossep) @@ -2459,7 +2459,7 @@ class atomictempfile(object): - '''writable file object that atomically updates a file + """writable file object that atomically updates a file All writes will go to a temporary copy of the original file. Call close() when you are done writing, and atomictempfile will rename @@ -2470,7 +2470,7 @@ checkambig argument of constructor is used with filestat, and is useful only if target file is guarded by any lock (e.g. repo.lock or repo.wlock). - ''' + """ def __init__(self, name, mode=b'w+b', createmode=None, checkambig=False): self.__name = name # permanent name @@ -3365,7 +3365,7 @@ def timed(func): - '''Report the execution time of a function call to stderr. + """Report the execution time of a function call to stderr. During development, use as a decorator when you need to measure the cost of a function, e.g. as follows: @@ -3373,7 +3373,7 @@ @util.timed def foo(a, b, c): pass - ''' + """ def wrapper(*args, **kwargs): with timedcm(pycompat.bytestr(func.__name__)) as time_stats: @@ -3404,7 +3404,7 @@ def sizetoint(s): - '''Convert a space specifier to a byte count. + """Convert a space specifier to a byte count. >>> sizetoint(b'30') 30 @@ -3412,7 +3412,7 @@ 2252 >>> sizetoint(b'6M') 6291456 - ''' + """ t = s.strip().lower() try: for k, u in _sizeunits: @@ -3424,9 +3424,9 @@ class hooks(object): - '''A collection of hook functions that can be used to extend a + """A collection of hook functions that can be used to extend a function's behavior. Hooks are called in lexicographic order, - based on the names of their sources.''' + based on the names of their sources.""" def __init__(self): self._hooks = [] @@ -3443,7 +3443,7 @@ def getstackframes(skip=0, line=b' %-*s in %s\n', fileline=b'%s:%d', depth=0): - '''Yields lines for a nicely formatted stacktrace. + """Yields lines for a nicely formatted stacktrace. Skips the 'skip' last entries, then return the last 'depth' entries. Each file+linenumber is formatted according to fileline. Each line is formatted according to line. @@ -3453,7 +3453,7 @@ function Not be used in production code but very convenient while developing. - ''' + """ entries = [ (fileline % (pycompat.sysbytes(fn), ln), pycompat.sysbytes(func)) for fn, ln, func, _text in traceback.extract_stack()[: -skip - 1] @@ -3475,12 +3475,12 @@ depth=0, prefix=b'', ): - '''Writes a message to f (stderr) with a nicely formatted stacktrace. + """Writes a message to f (stderr) with a nicely formatted stacktrace. Skips the 'skip' entries closest to the call, then show 'depth' entries. By default it will flush stdout first. It can be used everywhere and intentionally does not require an ui object. Not be used in production code but very convenient while developing. - ''' + """ if otherf: otherf.flush() f.write(b'%s%s at:\n' % (prefix, msg.rstrip()))
--- a/mercurial/utils/cborutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/utils/cborutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -641,19 +641,28 @@ elif special == SPECIAL_START_ARRAY: self._collectionstack.append( - {b'remaining': value, b'v': [],} + { + b'remaining': value, + b'v': [], + } ) self._state = self._STATE_WANT_ARRAY_VALUE elif special == SPECIAL_START_MAP: self._collectionstack.append( - {b'remaining': value, b'v': {},} + { + b'remaining': value, + b'v': {}, + } ) self._state = self._STATE_WANT_MAP_KEY elif special == SPECIAL_START_SET: self._collectionstack.append( - {b'remaining': value, b'v': set(),} + { + b'remaining': value, + b'v': set(), + } ) self._state = self._STATE_WANT_SET_VALUE @@ -684,7 +693,10 @@ lastc[b'remaining'] -= 1 self._collectionstack.append( - {b'remaining': value, b'v': newvalue,} + { + b'remaining': value, + b'v': newvalue, + } ) # self._state doesn't need changed. @@ -711,7 +723,10 @@ lastc[b'remaining'] -= 1 self._collectionstack.append( - {b'remaining': value, b'v': newvalue,} + { + b'remaining': value, + b'v': newvalue, + } ) self._state = self._STATE_WANT_SET_VALUE @@ -775,7 +790,10 @@ lastc[b'remaining'] -= 1 self._collectionstack.append( - {b'remaining': value, b'v': newvalue,} + { + b'remaining': value, + b'v': newvalue, + } ) self._state = self._STATE_WANT_ARRAY_VALUE @@ -789,7 +807,10 @@ lastc[b'remaining'] -= 1 self._collectionstack.append( - {b'remaining': value, b'v': newvalue,} + { + b'remaining': value, + b'v': newvalue, + } ) self._state = self._STATE_WANT_MAP_KEY @@ -803,7 +824,10 @@ lastc[b'remaining'] -= 1 self._collectionstack.append( - {b'remaining': value, b'v': newvalue,} + { + b'remaining': value, + b'v': newvalue, + } ) self._state = self._STATE_WANT_SET_VALUE
--- a/mercurial/utils/compression.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/utils/compression.py Thu Dec 03 14:15:39 2020 -0500 @@ -29,7 +29,8 @@ CLIENTROLE = b'client' compewireprotosupport = collections.namedtuple( - 'compenginewireprotosupport', ('name', 'serverpriority', 'clientpriority'), + 'compenginewireprotosupport', + ('name', 'serverpriority', 'clientpriority'), )
--- a/mercurial/utils/dateutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/utils/dateutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -53,12 +53,17 @@ b'%I:%M%p', ) -extendeddateformats = defaultdateformats + (b"%Y", b"%Y-%m", b"%b", b"%b %Y",) +extendeddateformats = defaultdateformats + ( + b"%Y", + b"%Y-%m", + b"%b", + b"%b %Y", +) def makedate(timestamp=None): - '''Return a unix timestamp (or the current time) as a (unixtime, - offset) tuple based off the local timezone.''' + """Return a unix timestamp (or the current time) as a (unixtime, + offset) tuple based off the local timezone.""" if timestamp is None: timestamp = time.time() if timestamp < 0: @@ -115,7 +120,7 @@ def parsetimezone(s): """find a trailing timezone, if any, in string, and return a - (offset, remainder) pair""" + (offset, remainder) pair""" s = pycompat.bytestr(s) if s.endswith(b"GMT") or s.endswith(b"UTC"):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/utils/memorytop.py Thu Dec 03 14:15:39 2020 -0500 @@ -0,0 +1,44 @@ +# memorytop requires Python 3.4 +# +# Usage: set PYTHONTRACEMALLOC=n in the environment of the hg invocation, +# where n>= is the number of frames to show in the backtrace. Put calls to +# memorytop in strategic places to show the current memory use by allocation +# site. + +import gc +import tracemalloc + + +def memorytop(limit=10): + gc.collect() + snapshot = tracemalloc.take_snapshot() + + snapshot = snapshot.filter_traces( + ( + tracemalloc.Filter(False, "<frozen importlib._bootstrap>"), + tracemalloc.Filter(False, "<frozen importlib._bootstrap_external>"), + tracemalloc.Filter(False, "<unknown>"), + ) + ) + stats = snapshot.statistics('traceback') + + total = sum(stat.size for stat in stats) + print("\nTotal allocated size: %.1f KiB\n" % (total / 1024)) + print("Lines with the biggest net allocations") + for index, stat in enumerate(stats[:limit], 1): + print( + "#%d: %d objects using %.1f KiB" + % (index, stat.count, stat.size / 1024) + ) + for line in stat.traceback.format(most_recent_first=True): + print(' ', line) + + other = stats[limit:] + if other: + size = sum(stat.size for stat in other) + count = sum(stat.count for stat in other) + print( + "%s other: %d objects using %.1f KiB" + % (len(other), count, size / 1024) + ) + print()
--- a/mercurial/utils/procutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/utils/procutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -80,6 +80,13 @@ return LineBufferedWrapper(stream) +def unwrap_line_buffered(stream): + if isinstance(stream, LineBufferedWrapper): + assert not isinstance(stream.orig, LineBufferedWrapper) + return stream.orig + return stream + + class WriteAllWrapper(object): def __init__(self, orig): self.orig = orig @@ -285,10 +292,10 @@ def tempfilter(s, cmd): - '''filter string S through a pair of temporary files with CMD. + """filter string S through a pair of temporary files with CMD. CMD is used as a template to create the real command to be run, with the strings INFILE and OUTFILE replaced by the real names of - the temporary files generated.''' + the temporary files generated.""" inname, outname = None, None try: infd, inname = pycompat.mkstemp(prefix=b'hg-filter-in-') @@ -458,17 +465,16 @@ def tonativeenv(env): - '''convert the environment from bytes to strings suitable for Popen(), etc. - ''' + """convert the environment from bytes to strings suitable for Popen(), etc.""" return pycompat.rapply(tonativestr, env) def system(cmd, environ=None, cwd=None, out=None): - '''enhanced shell command execution. + """enhanced shell command execution. run with environment maybe modified, maybe in different dir. if out is specified, it is assumed to be a file-like object that has a - write() method. stdout and stderr will be redirected to out.''' + write() method. stdout and stderr will be redirected to out.""" try: stdout.flush() except Exception: @@ -635,21 +641,35 @@ stderr=None, ensurestart=True, record_wait=None, + stdin_bytes=None, ): '''Spawn a command without waiting for it to finish.''' # we can't use close_fds *and* redirect stdin. I'm not sure that we # need to because the detached process has no console connection. - p = subprocess.Popen( - pycompat.rapply(tonativestr, script), - shell=shell, - env=tonativeenv(env), - close_fds=True, - creationflags=_creationflags, - stdout=stdout, - stderr=stderr, - ) - if record_wait is not None: - record_wait(p.wait) + + try: + stdin = None + if stdin_bytes is not None: + stdin = pycompat.unnamedtempfile() + stdin.write(stdin_bytes) + stdin.flush() + stdin.seek(0) + + p = subprocess.Popen( + pycompat.rapply(tonativestr, script), + shell=shell, + env=tonativeenv(env), + close_fds=True, + creationflags=_creationflags, + stdin=stdin, + stdout=stdout, + stderr=stderr, + ) + if record_wait is not None: + record_wait(p.wait) + finally: + if stdin is not None: + stdin.close() else: @@ -662,15 +682,16 @@ stderr=None, ensurestart=True, record_wait=None, + stdin_bytes=None, ): - '''Spawn a command without waiting for it to finish. + """Spawn a command without waiting for it to finish. When `record_wait` is not None, the spawned process will not be fully detached and the `record_wait` argument will be called with a the `Subprocess.wait` function for the spawned process. This is mostly useful for developers that need to make sure the spawned process - finished before a certain point. (eg: writing test)''' + finished before a certain point. (eg: writing test)""" if pycompat.isdarwin: # avoid crash in CoreFoundation in case another thread # calls gui() while we're calling fork(). @@ -722,15 +743,21 @@ if record_wait is None: # Start a new session os.setsid() + # connect stdin to devnull to make sure the subprocess can't + # muck up that stream for mercurial. + if stdin_bytes is None: + stdin = open(os.devnull, b'r') + else: + stdin = pycompat.unnamedtempfile() + stdin.write(stdin_bytes) + stdin.flush() + stdin.seek(0) - stdin = open(os.devnull, b'r') if stdout is None: stdout = open(os.devnull, b'w') if stderr is None: stderr = open(os.devnull, b'w') - # connect stdin to devnull to make sure the subprocess can't - # muck up that stream for mercurial. p = subprocess.Popen( cmd, shell=shell, @@ -754,5 +781,6 @@ finally: # mission accomplished, this child needs to exit and not # continue the hg process here. + stdin.close() if record_wait is None: os._exit(returncode)
--- a/mercurial/utils/stringutil.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/utils/stringutil.py Thu Dec 03 14:15:39 2020 -0500 @@ -494,15 +494,15 @@ @attr.s(hash=True) class mailmapping(object): - '''Represents a username/email key or value in - a mailmap file''' + """Represents a username/email key or value in + a mailmap file""" email = attr.ib() name = attr.ib(default=None) def _ismailmaplineinvalid(names, emails): - '''Returns True if the parsed names and emails + """Returns True if the parsed names and emails in a mailmap entry are invalid. >>> # No names or emails fails @@ -522,7 +522,7 @@ >>> emails = [b'proper@email.com', b'commit@email.com'] >>> _ismailmaplineinvalid(names, emails) False - ''' + """ return not emails or not names and len(emails) < 2 @@ -597,11 +597,13 @@ continue mailmapkey = mailmapping( - email=emails[-1], name=names[-1] if len(names) == 2 else None, + email=emails[-1], + name=names[-1] if len(names) == 2 else None, ) mailmap[mailmapkey] = mailmapping( - email=emails[0], name=names[0] if names else None, + email=emails[0], + name=names[0] if names else None, ) return mailmap @@ -659,7 +661,7 @@ def isauthorwellformed(author): - '''Return True if the author field is well formed + """Return True if the author field is well formed (ie "Contributor Name <contrib@email.dom>") >>> isauthorwellformed(b'Good Author <good@author.com>') @@ -676,7 +678,7 @@ False >>> isauthorwellformed(b'Bad Author <author>') False - ''' + """ return _correctauthorformat.match(author) is not None
--- a/mercurial/vfs.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/vfs.py Thu Dec 03 14:15:39 2020 -0500 @@ -83,12 +83,12 @@ @util.propertycache def open(self): - '''Open ``path`` file, which is relative to vfs root. + """Open ``path`` file, which is relative to vfs root. Newly created directories are marked as "not to be indexed by the content indexing service", if ``notindexed`` is specified for "write" mode access. - ''' + """ return self.__call__ def read(self, path): @@ -142,9 +142,9 @@ return os.path.islink(self.join(path)) def isfileorlink(self, path=None): - '''return whether path is a regular file or a symlink + """return whether path is a regular file or a symlink - Unlike isfile, this doesn't follow symlinks.''' + Unlike isfile, this doesn't follow symlinks.""" try: st = self.lstat(path) except OSError: @@ -228,8 +228,7 @@ return util.readlink(self.join(path)) def removedirs(self, path=None): - """Remove a leaf directory and all empty intermediate ones - """ + """Remove a leaf directory and all empty intermediate ones""" return util.removedirs(self.join(path)) def rmdir(self, path=None): @@ -332,7 +331,7 @@ class vfs(abstractvfs): - '''Operate files relative to a base directory + """Operate files relative to a base directory This class is used to hide the details of COW semantics and remote file access from higher level code. @@ -340,7 +339,7 @@ 'cacheaudited' should be enabled only if (a) vfs object is short-lived, or (b) the base directory is managed by hg and considered sort-of append-only. See pathutil.pathauditor() for details. - ''' + """ def __init__( self, @@ -397,7 +396,7 @@ auditpath=True, makeparentdirs=True, ): - '''Open ``path`` file, which is relative to vfs root. + """Open ``path`` file, which is relative to vfs root. By default, parent directories are created as needed. Newly created directories are marked as "not to be indexed by the content indexing @@ -426,7 +425,7 @@ truncation), if it is owned by another. Therefore, use combination of append mode and checkambig=True only in limited cases (see also issue5418 and issue5584 for detail). - ''' + """ if auditpath: self._auditpath(path, mode) f = self.join(path)
--- a/mercurial/win32.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/win32.py Thu Dec 03 14:15:39 2020 -0500 @@ -385,13 +385,13 @@ def checkcertificatechain(cert, build=True): - '''Tests the given certificate to see if there is a complete chain to a - trusted root certificate. As a side effect, missing certificates are - downloaded and installed unless ``build=False``. True is returned if a - chain to a trusted root exists (even if built on the fly), otherwise - False. NB: A chain to a trusted root does NOT imply that the certificate - is valid. - ''' + """Tests the given certificate to see if there is a complete chain to a + trusted root certificate. As a side effect, missing certificates are + downloaded and installed unless ``build=False``. True is returned if a + chain to a trusted root exists (even if built on the fly), otherwise + False. NB: A chain to a trusted root does NOT imply that the certificate + is valid. + """ chainctxptr = ctypes.POINTER(CERT_CHAIN_CONTEXT) @@ -488,8 +488,8 @@ def testpid(pid): - '''return True if pid is still running or unable to - determine, False otherwise''' + """return True if pid is still running or unable to + determine, False otherwise""" h = _kernel32.OpenProcess(_PROCESS_QUERY_INFORMATION, False, pid) if h: try: @@ -576,10 +576,10 @@ def setsignalhandler(): - '''Register a termination handler for console events including + """Register a termination handler for console events including CTRL+C. python signal handlers do not work well with socket operations. - ''' + """ def handler(event): _kernel32.ExitProcess(1) @@ -627,8 +627,8 @@ def enablevtmode(): - '''Enable virtual terminal mode for the associated console. Return True if - enabled, else False.''' + """Enable virtual terminal mode for the associated console. Return True if + enabled, else False.""" ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4
--- a/mercurial/windows.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/windows.py Thu Dec 03 14:15:39 2020 -0500 @@ -195,13 +195,13 @@ class winstdout(object): - '''Some files on Windows misbehave. + """Some files on Windows misbehave. When writing to a broken pipe, EINVAL instead of EPIPE may be raised. When writing too many bytes to a console at the same, a "Not enough space" error may happen. Python 3 already works around that. - ''' + """ def __init__(self, fp): self.fp = fp @@ -497,11 +497,11 @@ def findexe(command): - '''Find executable for command searching like cmd.exe does. + """Find executable for command searching like cmd.exe does. If command is a basename then PATH is searched for command. PATH isn't searched if command is an absolute or relative path. An extension from PATHEXT is found and added if not present. - If command isn't found None is returned.''' + If command isn't found None is returned.""" pathext = encoding.environ.get(b'PATHEXT', b'.COM;.EXE;.BAT;.CMD') pathexts = [ext for ext in pathext.lower().split(pycompat.ospathsep)] if os.path.splitext(command)[1].lower() in pathexts: @@ -529,10 +529,10 @@ def statfiles(files): - '''Stat each file in files. Yield each stat, or None if a file + """Stat each file in files. Yield each stat, or None if a file does not exist or has a type we don't care about. - Cluster and cache stat per directory to minimize number of OS stat calls.''' + Cluster and cache stat per directory to minimize number of OS stat calls.""" dircache = {} # dirname -> filename -> status | None if file does not exist getkind = stat.S_IFMT for nf in files: @@ -630,14 +630,14 @@ def lookupreg(key, valname=None, scope=None): - ''' Look up a key/value name in the Windows registry. + """Look up a key/value name in the Windows registry. valname: value name. If unspecified, the default value for the key is used. scope: optionally specify scope for registry lookup, this can be a sequence of scopes to look up in order. Default (CURRENT_USER, LOCAL_MACHINE). - ''' + """ if scope is None: scope = (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE) elif not isinstance(scope, (list, tuple)):
--- a/mercurial/wireprotoframing.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/wireprotoframing.py Thu Dec 03 14:15:39 2020 -0500 @@ -456,7 +456,10 @@ def createalternatelocationresponseframe(stream, requestid, location): data = { b'status': b'redirect', - b'location': {b'url': location.url, b'mediatype': location.mediatype,}, + b'location': { + b'url': location.url, + b'mediatype': location.mediatype, + }, } for a in ( @@ -490,7 +493,12 @@ def createcommanderrorresponse(stream, requestid, message, args=None): # TODO should this be using a list of {'msg': ..., 'args': {}} so atom # formatting works consistently? - m = {b'status': b'error', b'error': {b'message': message,}} + m = { + b'status': b'error', + b'error': { + b'message': message, + }, + } if args: m[b'error'][b'args'] = args @@ -510,7 +518,12 @@ assert len(msg) <= DEFAULT_MAX_FRAME_SIZE payload = b''.join( - cborutil.streamencode({b'type': errtype, b'message': [{b'msg': msg}],}) + cborutil.streamencode( + { + b'type': errtype, + b'message': [{b'msg': msg}], + } + ) ) yield stream.makeframe( @@ -1292,14 +1305,18 @@ for frame in gen: yield frame - return b'sendframes', {b'framegen': makegen(),} + return b'sendframes', { + b'framegen': makegen(), + } def _handlesendframes(self, framegen): if self._deferoutput: self._bufferedframegens.append(framegen) return b'noop', {} else: - return b'sendframes', {b'framegen': framegen,} + return b'sendframes', { + b'framegen': framegen, + } def onservererror(self, stream, requestid, msg): ensureserverstream(stream) @@ -1351,7 +1368,9 @@ return s def _makeerrorresult(self, msg): - return b'error', {b'message': msg,} + return b'error', { + b'message': msg, + } def _makeruncommandresult(self, requestid): entry = self._receivingcommands[requestid] @@ -1397,7 +1416,9 @@ ) def _makewantframeresult(self): - return b'wantframe', {b'state': self._state,} + return b'wantframe', { + b'state': self._state, + } def _validatecommandrequestframe(self, frame): new = frame.flags & FLAG_COMMAND_REQUEST_NEW @@ -1802,7 +1823,9 @@ return ( request, b'sendframes', - {b'framegen': self._makecommandframes(request),}, + { + b'framegen': self._makecommandframes(request), + }, ) def flushcommands(self): @@ -1835,7 +1858,9 @@ for frame in self._makecommandframes(request): yield frame - return b'sendframes', {b'framegen': makeframes(),} + return b'sendframes', { + b'framegen': makeframes(), + } def _makecommandframes(self, request): """Emit frames to issue a command request. @@ -1851,7 +1876,9 @@ payload = b''.join( cborutil.streamencode( - {b'contentencodings': self._clientcontentencoders,} + { + b'contentencodings': self._clientcontentencoders, + } ) )
--- a/mercurial/wireprotoserver.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/wireprotoserver.py Thu Dec 03 14:15:39 2020 -0500 @@ -8,7 +8,6 @@ import contextlib import struct -import sys import threading from .i18n import _ @@ -851,7 +850,6 @@ def serve_forever(self): self.serveuntil(threading.Event()) self._ui.restorefinout(self._fin, self._fout) - sys.exit(0) def serveuntil(self, ev): """Serve until a threading.Event is set."""
--- a/mercurial/wireprototypes.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/wireprototypes.py Thu Dec 03 14:15:39 2020 -0500 @@ -33,14 +33,23 @@ # All available wire protocol transports. TRANSPORTS = { - SSHV1: {b'transport': b'ssh', b'version': 1,}, + SSHV1: { + b'transport': b'ssh', + b'version': 1, + }, SSHV2: { b'transport': b'ssh', # TODO mark as version 2 once all commands are implemented. b'version': 1, }, - b'http-v1': {b'transport': b'http', b'version': 1,}, - HTTP_WIREPROTO_V2: {b'transport': b'http', b'version': 2,}, + b'http-v1': { + b'transport': b'http', + b'version': 1, + }, + HTTP_WIREPROTO_V2: { + b'transport': b'http', + b'version': 2, + }, }
--- a/mercurial/wireprotov1peer.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/wireprotov1peer.py Thu Dec 03 14:15:39 2020 -0500 @@ -36,7 +36,7 @@ def batchable(f): - '''annotation for batchable methods + """annotation for batchable methods Such methods must implement a coroutine as follows: @@ -56,7 +56,7 @@ method, but adds the original method as an attribute called "batchable", which is used by remotebatch to split the call into separate encoding and decoding phases. - ''' + """ def plain(*args, **opts): batchable = f(*args, **opts) @@ -474,7 +474,7 @@ return changegroupmod.cg1unpacker(f, b'UN') def unbundle(self, bundle, heads, url): - '''Send cg (a readable file-like object representing the + """Send cg (a readable file-like object representing the changegroup to push, typically a chunkbuffer object) to the remote server as a bundle. @@ -485,7 +485,7 @@ `url` is the url the client thinks it's pushing to, which is visible to hooks. - ''' + """ if heads != [b'force'] and self.capable(b'unbundlehash'): heads = wireprototypes.encodelist( @@ -655,6 +655,5 @@ raise NotImplementedError() def _abort(self, exception): - """clearly abort the wire protocol connection and raise the exception - """ + """clearly abort the wire protocol connection and raise the exception""" raise NotImplementedError()
--- a/mercurial/wireprotov1server.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/wireprotov1server.py Thu Dec 03 14:15:39 2020 -0500 @@ -19,6 +19,7 @@ from . import ( bundle2, + bundlecaches, changegroup as changegroupmod, discovery, encoding, @@ -272,7 +273,7 @@ data center given the client's IP address. """ return wireprototypes.bytesresponse( - repo.vfs.tryread(b'clonebundles.manifest') + repo.vfs.tryread(bundlecaches.CB_MANIFEST_FILE) ) @@ -387,8 +388,8 @@ manifest = repo.vfs.tryread(b'pullbundles.manifest') if not manifest: return None - res = exchange.parseclonebundlesmanifest(repo, manifest) - res = exchange.filterclonebundleentries(repo, res) + res = bundlecaches.parseclonebundlesmanifest(repo, manifest) + res = bundlecaches.filterclonebundleentries(repo, res) if not res: return None cl = repo.unfiltered().changelog @@ -601,10 +602,10 @@ @wireprotocommand(b'stream_out', permission=b'pull') def stream(repo, proto): - '''If the server supports streaming clone, it advertises the "stream" + """If the server supports streaming clone, it advertises the "stream" capability with a value representing the version and flags of the repo it is serving. Client checks to see if it understands the format. - ''' + """ return wireprototypes.streamreslegacy(streamclone.generatev1wireproto(repo)) @@ -684,9 +685,7 @@ # We did not change it to minimise code change. # This need to be moved to something proper. # Feel free to do it. - procutil.stderr.write(b"abort: %s\n" % exc.message) - if exc.hint is not None: - procutil.stderr.write(b"(%s)\n" % exc.hint) + procutil.stderr.write(exc.format()) procutil.stderr.flush() return wireprototypes.pushres( 0, output.getvalue() if output else b''
--- a/mercurial/wireprotov2server.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/wireprotov2server.py Thu Dec 03 14:15:39 2020 -0500 @@ -982,7 +982,10 @@ b'revisions': { b'type': b'list', b'example': [ - {b'type': b'changesetexplicit', b'nodes': [b'abcdef...'],} + { + b'type': b'changesetexplicit', + b'nodes': [b'abcdef...'], + } ], }, b'fields': { @@ -1166,14 +1169,20 @@ b'default': lambda: False, b'example': True, }, - b'nodes': {b'type': b'list', b'example': [b'0123456...'],}, + b'nodes': { + b'type': b'list', + b'example': [b'0123456...'], + }, b'fields': { b'type': b'set', b'default': set, b'example': {b'parents', b'revision'}, b'validvalues': {b'parents', b'revision', b'linknode'}, }, - b'path': {b'type': b'bytes', b'example': b'foo.txt',}, + b'path': { + b'type': b'bytes', + b'example': b'foo.txt', + }, }, permission=b'pull', # TODO censoring a file revision won't invalidate the cache. @@ -1262,7 +1271,10 @@ b'revisions': { b'type': b'list', b'example': [ - {b'type': b'changesetexplicit', b'nodes': [b'abcdef...'],} + { + b'type': b'changesetexplicit', + b'nodes': [b'abcdef...'], + } ], }, }, @@ -1375,7 +1387,12 @@ @wireprotocommand( b'listkeys', - args={b'namespace': {b'type': b'bytes', b'example': b'ns',},}, + args={ + b'namespace': { + b'type': b'bytes', + b'example': b'ns', + }, + }, permission=b'pull', ) def listkeysv2(repo, proto, namespace): @@ -1390,7 +1407,12 @@ @wireprotocommand( b'lookup', - args={b'key': {b'type': b'bytes', b'example': b'foo',},}, + args={ + b'key': { + b'type': b'bytes', + b'example': b'foo', + }, + }, permission=b'pull', ) def lookupv2(repo, proto, key): @@ -1415,7 +1437,10 @@ @wireprotocommand( b'manifestdata', args={ - b'nodes': {b'type': b'list', b'example': [b'0123456...'],}, + b'nodes': { + b'type': b'list', + b'example': [b'0123456...'], + }, b'haveparents': { b'type': b'bool', b'default': lambda: False, @@ -1427,7 +1452,10 @@ b'example': {b'parents', b'revision'}, b'validvalues': {b'parents', b'revision'}, }, - b'tree': {b'type': b'bytes', b'example': b'',}, + b'tree': { + b'type': b'bytes', + b'example': b'', + }, }, permission=b'pull', cachekeyfn=makecommandcachekeyfn(b'manifestdata', 1, allargs=True), @@ -1485,10 +1513,22 @@ @wireprotocommand( b'pushkey', args={ - b'namespace': {b'type': b'bytes', b'example': b'ns',}, - b'key': {b'type': b'bytes', b'example': b'key',}, - b'old': {b'type': b'bytes', b'example': b'old',}, - b'new': {b'type': b'bytes', b'example': b'new',}, + b'namespace': { + b'type': b'bytes', + b'example': b'ns', + }, + b'key': { + b'type': b'bytes', + b'example': b'key', + }, + b'old': { + b'type': b'bytes', + b'example': b'old', + }, + b'new': { + b'type': b'bytes', + b'example': b'new', + }, }, permission=b'push', )
--- a/mercurial/worker.py Thu Dec 03 13:36:24 2020 -0500 +++ b/mercurial/worker.py Thu Dec 03 14:15:39 2020 -0500 @@ -116,8 +116,8 @@ def worthwhile(ui, costperop, nops, threadsafe=True): - '''try to determine whether the benefit of multiple processes can - outweigh the cost of starting them''' + """try to determine whether the benefit of multiple processes can + outweigh the cost of starting them""" if not threadsafe and _DISALLOW_THREAD_UNSAFE: return False @@ -131,7 +131,7 @@ def worker( ui, costperarg, func, staticargs, args, hasretval=False, threadsafe=True ): - '''run a function, possibly in parallel in multiple worker + """run a function, possibly in parallel in multiple worker processes. returns a progress iterator @@ -153,7 +153,7 @@ threadsafe - whether work items are thread safe and can be executed using a thread-based worker. Should be disabled for CPU heavy tasks that don't release the GIL. - ''' + """ enabled = ui.configbool(b'worker', b'enabled') if enabled and worthwhile(ui, costperarg, len(args), threadsafe=threadsafe): return _platformworker(ui, func, staticargs, args, hasretval) @@ -300,16 +300,16 @@ if status: if status < 0: os.kill(os.getpid(), -status) - sys.exit(status) + raise error.WorkerError(status) if hasretval: yield True, retval def _posixexitstatus(code): - '''convert a posix exit status into the same form returned by + """convert a posix exit status into the same form returned by os.spawnv - returns None if the process was stopped instead of exiting''' + returns None if the process was stopped instead of exiting""" if os.WIFEXITED(code): return os.WEXITSTATUS(code) elif os.WIFSIGNALED(code): @@ -423,7 +423,7 @@ def partition(lst, nslices): - '''partition a list into N slices of roughly equal size + """partition a list into N slices of roughly equal size The current strategy takes every Nth element from the input. If we ever write workers that need to preserve grouping in input @@ -450,6 +450,6 @@ What we should really be doing is have workers read filenames from a ordered queue. This preserves locality and also keeps any worker from getting more than one file out of balance. - ''' + """ for i in range(nslices): yield lst[i::nslices]
--- a/relnotes/5.6 Thu Dec 03 13:36:24 2020 -0500 +++ b/relnotes/5.6 Thu Dec 03 14:15:39 2020 -0500 @@ -8,6 +8,9 @@ * New revset predicate `diffcontains(pattern)` for filtering revisions in the same way as `hg grep --diff pattern`. + * The memory footprint per changeset and per file during pull/unbundle + operations has been significantly reduced. + == New Experimental Features == @@ -27,3 +30,15 @@ the higher-level functions available in the same module cover your use cases. + * `phases.registernew` now takes a set of revisions instead of a list + of nodes. `phases.advanceboundary` takes an optional set of revisions + in addition to the list of nodes. The corresponeding members of the + `phasecache` class follow this change. + + * The `addgroup` member of `revlog` classes no longer keeps a list of + all found nodes. It now returns True iff a node was found in the group. + An optional callback for duplicated nodes can be used by callers to keep + track of all nodes themselve. + + * The `_chaininfocache` of `revlog` classes has been changed from a dict + to a LRU cache.
--- a/relnotes/next Thu Dec 03 13:36:24 2020 -0500 +++ b/relnotes/next Thu Dec 03 14:15:39 2020 -0500 @@ -1,6 +1,27 @@ == New Features == + * There is a new config section for templates used by hg commands. It + is called `[command-templates]`. Some existing config options have + been deprecated in favor of config options in the new + section. These are: `ui.logtemplate` to `command-templates.log`, + `ui.graphnodetemplate` to `command-templates.graphnode`, + `ui.mergemarkertemplate` to `command-templates.mergemarker`, + `ui.pre-merge-tool-output-template` to + `command-templates.pre-merge-tool-output`. + * There is a new set of config options for the template used for the + one-line commit summary displayed by various commands, such as `hg + rebase`. The main one is `command-templates.oneline-summary`. That + can be overridden per command with + `command-templates.oneline-summary.<command>`, where `<command>` + can be e.g. `rebase`. As part of this effort, the default format + from `hg rebase` was reorganized a bit. + + * `hg strip`, from the strip extension, is now a core command, `hg + debugstrip`. The extension remains for compatibility. + + * The memory footprint per changeset during pull/unbundle + operations has been further reduced. == New Experimental Features ==
--- a/rust/Cargo.lock Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/Cargo.lock Thu Dec 03 14:15:39 2020 -0500 @@ -42,6 +42,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "byteorder" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -202,6 +210,26 @@ ] [[package]] +name = "format-bytes" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "format-bytes-macros 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "format-bytes-macros" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.19 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -248,6 +276,7 @@ "crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "im-rc 15.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -286,6 +315,19 @@ ] [[package]] +name = "im-rc" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitmaps 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sized-chunks 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "itertools" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -432,6 +474,11 @@ ] [[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "proc-macro2" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -558,6 +605,14 @@ ] [[package]] +name = "rand_xoshiro" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "rayon" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -623,6 +678,7 @@ dependencies = [ "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "format-bytes 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "hg-core 0.1.0", "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "micro-timer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -659,6 +715,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "sized-chunks" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitmaps 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -729,6 +794,11 @@ ] [[package]] +name = "typenum" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "unicode-width" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -749,6 +819,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -820,6 +895,7 @@ "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum bitmaps 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" "checksum cc 1.0.60 (registry+https://github.com/rust-lang/crates.io-index)" = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" @@ -837,6 +913,8 @@ "checksum either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" "checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" "checksum flate2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "766d0e77a2c1502169d4a93ff3b8c15a71fd946cd0126309752104e5f3c46d94" +"checksum format-bytes 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1a7374eb574cd29ae45878554298091c554c3286a17b3afa440a3e2710ae0790" +"checksum format-bytes-macros 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4edcc04201cea17a0e6b937adebd46b93fba09924c7e6ed8c515a35ce8432cbc" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum getrandom 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" @@ -844,6 +922,7 @@ "checksum hermit-abi 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151" "checksum hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +"checksum im-rc 15.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f" "checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" "checksum jobserver 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" @@ -863,6 +942,7 @@ "checksum pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" "checksum ppv-lite86 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" +"checksum proc-macro-hack 0.5.19 (registry+https://github.com/rust-lang/crates.io-index)" = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" "checksum proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "36e28516df94f3dd551a587da5357459d9b36d945a7c37c3557928c1c2ff2a2c" "checksum python27-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67cb041de8615111bf224dd75667af5f25c6e032118251426fed7f1b70ce4c8c" "checksum python3-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90af11779515a1e530af60782d273b59ac79d33b0e253c071a728563957c76d4" @@ -878,6 +958,7 @@ "checksum rand_distr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2" "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +"checksum rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" "checksum rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd016f0c045ad38b5251be2c9c0ab806917f82da4d36b2a327e5166adad9270" "checksum rayon-core 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" @@ -889,6 +970,7 @@ "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" "checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +"checksum sized-chunks 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1ec31ceca5644fa6d444cc77548b88b67f46db6f7c71683b0f9336e671830d2f" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" @@ -897,10 +979,12 @@ "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" "checksum time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" "checksum twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" +"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" "checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" "checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" "checksum vcpkg 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" "checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" "checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" "checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
--- a/rust/hg-core/Cargo.toml Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-core/Cargo.toml Thu Dec 03 14:15:39 2020 -0500 @@ -11,6 +11,7 @@ [dependencies] byteorder = "1.3.4" hex = "0.4.2" +im-rc = "15.0.*" lazy_static = "1.4.0" memchr = "2.3.3" rand = "0.7.3"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/hg-core/src/copy_tracing.rs Thu Dec 03 14:15:39 2020 -0500 @@ -0,0 +1,415 @@ +use crate::utils::hg_path::HgPath; +use crate::utils::hg_path::HgPathBuf; +use crate::Revision; + +use im_rc::ordmap::DiffItem; +use im_rc::ordmap::OrdMap; + +use std::collections::HashMap; +use std::collections::HashSet; + +pub type PathCopies = HashMap<HgPathBuf, HgPathBuf>; + +#[derive(Clone, Debug, PartialEq)] +struct TimeStampedPathCopy { + /// revision at which the copy information was added + rev: Revision, + /// the copy source, (Set to None in case of deletion of the associated + /// key) + path: Option<HgPathBuf>, +} + +/// maps CopyDestination to Copy Source (+ a "timestamp" for the operation) +type TimeStampedPathCopies = OrdMap<HgPathBuf, TimeStampedPathCopy>; + +/// hold parent 1, parent 2 and relevant files actions. +pub type RevInfo = (Revision, Revision, ChangedFiles); + +/// represent the files affected by a changesets +/// +/// This hold a subset of mercurial.metadata.ChangingFiles as we do not need +/// all the data categories tracked by it. +pub struct ChangedFiles { + removed: HashSet<HgPathBuf>, + merged: HashSet<HgPathBuf>, + salvaged: HashSet<HgPathBuf>, + copied_from_p1: PathCopies, + copied_from_p2: PathCopies, +} + +/// Represent active changes that affect the copy tracing. +enum Action<'a> { + /// The parent ? children edge is removing a file + /// + /// (actually, this could be the edge from the other parent, but it does + /// not matters) + Removed(&'a HgPath), + /// The parent ? children edge introduce copy information between (dest, + /// source) + Copied(&'a HgPath, &'a HgPath), +} + +/// This express the possible "special" case we can get in a merge +/// +/// See mercurial/metadata.py for details on these values. +#[derive(PartialEq)] +enum MergeCase { + /// Merged: file had history on both side that needed to be merged + Merged, + /// Salvaged: file was candidate for deletion, but survived the merge + Salvaged, + /// Normal: Not one of the two cases above + Normal, +} + +impl ChangedFiles { + pub fn new( + removed: HashSet<HgPathBuf>, + merged: HashSet<HgPathBuf>, + salvaged: HashSet<HgPathBuf>, + copied_from_p1: PathCopies, + copied_from_p2: PathCopies, + ) -> Self { + ChangedFiles { + removed, + merged, + salvaged, + copied_from_p1, + copied_from_p2, + } + } + + pub fn new_empty() -> Self { + ChangedFiles { + removed: HashSet::new(), + merged: HashSet::new(), + salvaged: HashSet::new(), + copied_from_p1: PathCopies::new(), + copied_from_p2: PathCopies::new(), + } + } + + /// Return an iterator over all the `Action` in this instance. + fn iter_actions(&self, parent: usize) -> impl Iterator<Item = Action> { + let copies_iter = match parent { + 1 => self.copied_from_p1.iter(), + 2 => self.copied_from_p2.iter(), + _ => unreachable!(), + }; + let remove_iter = self.removed.iter(); + let copies_iter = copies_iter.map(|(x, y)| Action::Copied(x, y)); + let remove_iter = remove_iter.map(|x| Action::Removed(x)); + copies_iter.chain(remove_iter) + } + + /// return the MergeCase value associated with a filename + fn get_merge_case(&self, path: &HgPath) -> MergeCase { + if self.salvaged.contains(path) { + return MergeCase::Salvaged; + } else if self.merged.contains(path) { + return MergeCase::Merged; + } else { + return MergeCase::Normal; + } + } +} + +/// A struct responsible for answering "is X ancestors of Y" quickly +/// +/// The structure will delegate ancestors call to a callback, and cache the +/// result. +#[derive(Debug)] +struct AncestorOracle<'a, A: Fn(Revision, Revision) -> bool> { + inner: &'a A, + pairs: HashMap<(Revision, Revision), bool>, +} + +impl<'a, A: Fn(Revision, Revision) -> bool> AncestorOracle<'a, A> { + fn new(func: &'a A) -> Self { + Self { + inner: func, + pairs: HashMap::default(), + } + } + + /// returns `true` if `anc` is an ancestors of `desc`, `false` otherwise + fn is_ancestor(&mut self, anc: Revision, desc: Revision) -> bool { + if anc > desc { + false + } else if anc == desc { + true + } else { + if let Some(b) = self.pairs.get(&(anc, desc)) { + *b + } else { + let b = (self.inner)(anc, desc); + self.pairs.insert((anc, desc), b); + b + } + } + } +} + +/// Same as mercurial.copies._combine_changeset_copies, but in Rust. +/// +/// Arguments are: +/// +/// revs: all revisions to be considered +/// children: a {parent ? [childrens]} mapping +/// target_rev: the final revision we are combining copies to +/// rev_info(rev): callback to get revision information: +/// * first parent +/// * second parent +/// * ChangedFiles +/// isancestors(low_rev, high_rev): callback to check if a revision is an +/// ancestor of another +pub fn combine_changeset_copies<A: Fn(Revision, Revision) -> bool>( + revs: Vec<Revision>, + children: HashMap<Revision, Vec<Revision>>, + target_rev: Revision, + rev_info: &impl Fn(Revision) -> RevInfo, + is_ancestor: &A, +) -> PathCopies { + let mut all_copies = HashMap::new(); + let mut oracle = AncestorOracle::new(is_ancestor); + + for rev in revs { + // Retrieve data computed in a previous iteration + let copies = all_copies.remove(&rev); + let copies = match copies { + Some(c) => c, + None => TimeStampedPathCopies::default(), // root of the walked set + }; + + let current_children = match children.get(&rev) { + Some(c) => c, + None => panic!("inconsistent `revs` and `children`"), + }; + + for child in current_children { + // We will chain the copies information accumulated for `rev` with + // the individual copies information for each of its children. + // Creating a new PathCopies for each `rev` ? `children` vertex. + let (p1, p2, changes) = rev_info(*child); + + let parent = if rev == p1 { + 1 + } else { + assert_eq!(rev, p2); + 2 + }; + let mut new_copies = copies.clone(); + + for action in changes.iter_actions(parent) { + match action { + Action::Copied(dest, source) => { + let entry; + if let Some(v) = copies.get(source) { + entry = match &v.path { + Some(path) => Some((*(path)).to_owned()), + None => Some(source.to_owned()), + } + } else { + entry = Some(source.to_owned()); + } + // Each new entry is introduced by the children, we + // record this information as we will need it to take + // the right decision when merging conflicting copy + // information. See merge_copies_dict for details. + let ttpc = TimeStampedPathCopy { + rev: *child, + path: entry, + }; + new_copies.insert(dest.to_owned(), ttpc); + } + Action::Removed(f) => { + // We must drop copy information for removed file. + // + // We need to explicitly record them as dropped to + // propagate this information when merging two + // TimeStampedPathCopies object. + if new_copies.contains_key(f.as_ref()) { + let ttpc = TimeStampedPathCopy { + rev: *child, + path: None, + }; + new_copies.insert(f.to_owned(), ttpc); + } + } + } + } + + // Merge has two parents needs to combines their copy information. + // + // If the vertex from the other parent was already processed, we + // will have a value for the child ready to be used. We need to + // grab it and combine it with the one we already + // computed. If not we can simply store the newly + // computed data. The processing happening at + // the time of the second parent will take care of combining the + // two TimeStampedPathCopies instance. + match all_copies.remove(child) { + None => { + all_copies.insert(child, new_copies); + } + Some(other_copies) => { + let (minor, major) = match parent { + 1 => (other_copies, new_copies), + 2 => (new_copies, other_copies), + _ => unreachable!(), + }; + let merged_copies = + merge_copies_dict(minor, major, &changes, &mut oracle); + all_copies.insert(child, merged_copies); + } + }; + } + } + + // Drop internal information (like the timestamp) and return the final + // mapping. + let tt_result = all_copies + .remove(&target_rev) + .expect("target revision was not processed"); + let mut result = PathCopies::default(); + for (dest, tt_source) in tt_result { + if let Some(path) = tt_source.path { + result.insert(dest, path); + } + } + result +} + +/// merge two copies-mapping together, minor and major +/// +/// In case of conflict, value from "major" will be picked, unless in some +/// cases. See inline documentation for details. +#[allow(clippy::if_same_then_else)] +fn merge_copies_dict<A: Fn(Revision, Revision) -> bool>( + minor: TimeStampedPathCopies, + major: TimeStampedPathCopies, + changes: &ChangedFiles, + oracle: &mut AncestorOracle<A>, +) -> TimeStampedPathCopies { + if minor.is_empty() { + return major; + } else if major.is_empty() { + return minor; + } + let mut override_minor = Vec::new(); + let mut override_major = Vec::new(); + + let mut to_major = |k: &HgPathBuf, v: &TimeStampedPathCopy| { + override_major.push((k.clone(), v.clone())) + }; + let mut to_minor = |k: &HgPathBuf, v: &TimeStampedPathCopy| { + override_minor.push((k.clone(), v.clone())) + }; + + // The diff function leverage detection of the identical subpart if minor + // and major has some common ancestors. This make it very fast is most + // case. + // + // In case where the two map are vastly different in size, the current + // approach is still slowish because the iteration will iterate over + // all the "exclusive" content of the larger on. This situation can be + // frequent when the subgraph of revision we are processing has a lot + // of roots. Each roots adding they own fully new map to the mix (and + // likely a small map, if the path from the root to the "main path" is + // small. + // + // We could do better by detecting such situation and processing them + // differently. + for d in minor.diff(&major) { + match d { + DiffItem::Add(k, v) => to_minor(k, v), + DiffItem::Remove(k, v) => to_major(k, v), + DiffItem::Update { old, new } => { + let (dest, src_major) = new; + let (_, src_minor) = old; + let mut pick_minor = || (to_major(dest, src_minor)); + let mut pick_major = || (to_minor(dest, src_major)); + if src_major.path == src_minor.path { + // we have the same value, but from other source; + if src_major.rev == src_minor.rev { + // If the two entry are identical, no need to do + // anything (but diff should not have yield them) + unreachable!(); + } else if oracle.is_ancestor(src_major.rev, src_minor.rev) + { + pick_minor(); + } else { + pick_major(); + } + } else if src_major.rev == src_minor.rev { + // We cannot get copy information for both p1 and p2 in the + // same rev. So this is the same value. + unreachable!(); + } else { + let action = changes.get_merge_case(&dest); + if src_major.path.is_none() + && action == MergeCase::Salvaged + { + // If the file is "deleted" in the major side but was + // salvaged by the merge, we keep the minor side alive + pick_minor(); + } else if src_minor.path.is_none() + && action == MergeCase::Salvaged + { + // If the file is "deleted" in the minor side but was + // salvaged by the merge, unconditionnaly preserve the + // major side. + pick_major(); + } else if action == MergeCase::Merged { + // If the file was actively merged, copy information + // from each side might conflict. The major side will + // win such conflict. + pick_major(); + } else if oracle.is_ancestor(src_major.rev, src_minor.rev) + { + // If the minor side is strictly newer than the major + // side, it should be kept. + pick_minor(); + } else if src_major.path.is_some() { + // without any special case, the "major" value win + // other the "minor" one. + pick_major(); + } else if oracle.is_ancestor(src_minor.rev, src_major.rev) + { + // the "major" rev is a direct ancestors of "minor", + // any different value should + // overwrite + pick_major(); + } else { + // major version is None (so the file was deleted on + // that branch) and that branch is independant (neither + // minor nor major is an ancestors of the other one.) + // We preserve the new + // information about the new file. + pick_minor(); + } + } + } + }; + } + + let updates; + let mut result; + if override_major.is_empty() { + result = major + } else if override_minor.is_empty() { + result = minor + } else { + if override_minor.len() < override_major.len() { + updates = override_minor; + result = minor; + } else { + updates = override_major; + result = major; + } + for (k, v) in updates { + result.insert(k, v); + } + } + result +}
--- a/rust/hg-core/src/dirstate/dirstate_tree/node.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-core/src/dirstate/dirstate_tree/node.rs Thu Dec 03 14:15:39 2020 -0500 @@ -60,43 +60,46 @@ // Are we're modifying the current file ? Is the the end of the path ? let is_current_file = tail.is_empty() && head.is_empty(); - if let NodeKind::File(file) = &mut self.kind { - if is_current_file { - let new = Self { - kind: NodeKind::File(File { - entry: new_entry, - ..file.clone() - }), - }; - return InsertResult { - did_insert: false, - old_entry: Some(std::mem::replace(self, new)), - }; - } else { - match file.entry.state { - // Only replace the current file with a directory if it's - // marked as `Removed` - EntryState::Removed => { - self.kind = NodeKind::Directory(Directory { - was_file: Some(Box::from(file.clone())), - children: Default::default(), - }) - } - _ => { - return Node::insert_in_file( - file, new_entry, head, tail, - ) - } + // Potentially Replace the current file with a directory if it's marked + // as `Removed` + if !is_current_file { + if let NodeKind::File(file) = &mut self.kind { + if file.entry.state == EntryState::Removed { + self.kind = NodeKind::Directory(Directory { + was_file: Some(Box::from(file.clone())), + children: Default::default(), + }) } } } - match &mut self.kind { NodeKind::Directory(directory) => { Node::insert_in_directory(directory, new_entry, head, tail) } - NodeKind::File(_) => { - unreachable!("The file case has already been handled") + NodeKind::File(file) => { + if is_current_file { + let new = Self { + kind: NodeKind::File(File { + entry: new_entry, + ..file.clone() + }), + }; + InsertResult { + did_insert: false, + old_entry: Some(std::mem::replace(self, new)), + } + } else { + match file.entry.state { + EntryState::Removed => { + unreachable!("Removed file turning into a directory was dealt with earlier") + } + _ => { + Node::insert_in_file( + file, new_entry, head, tail, + ) + } + } + } } } }
--- a/rust/hg-core/src/dirstate/status.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-core/src/dirstate/status.rs Thu Dec 03 14:15:39 2020 -0500 @@ -109,6 +109,10 @@ /// A path with its computed ``Dispatch`` information type DispatchedPath<'a> = (HgPathCow<'a>, Dispatch); +/// The conversion from `HgPath` to a real fs path failed. +/// `22` is the error code for "Invalid argument" +const INVALID_PATH_DISPATCH: Dispatch = Dispatch::Bad(BadMatch::OsError(22)); + /// Dates and times that are outside the 31-bit signed range are compared /// modulo 2^31. This should prevent hg from behaving badly with very large /// files or corrupt dates while still having a high probability of detecting @@ -217,6 +221,12 @@ } } +fn dispatch_os_error(e: &std::io::Error) -> Dispatch { + Dispatch::Bad(BadMatch::OsError( + e.raw_os_error().expect("expected real OS error"), + )) +} + lazy_static! { static ref DEFAULT_WORK: HashSet<&'static HgPath> = { let mut h = HashSet::new(); @@ -372,13 +382,18 @@ .file_set() .unwrap_or(&DEFAULT_WORK) .par_iter() - .map(|&filename| -> Option<IoResult<_>> { + .flat_map(|&filename| -> Option<_> { // TODO normalization let normalized = filename; let buf = match hg_path_to_path_buf(normalized) { Ok(x) => x, - Err(e) => return Some(Err(e.into())), + Err(_) => { + return Some(( + Cow::Borrowed(normalized), + INVALID_PATH_DISPATCH, + )) + } }; let target = self.root_dir.join(buf); let st = target.symlink_metadata(); @@ -389,7 +404,7 @@ return if file_type.is_file() || file_type.is_symlink() { if let Some(entry) = in_dmap { - return Some(Ok(( + return Some(( Cow::Borrowed(normalized), dispatch_found( &normalized, @@ -398,26 +413,26 @@ &self.dmap.copy_map, self.options, ), - ))); + )); } - Some(Ok(( + Some(( Cow::Borrowed(normalized), Dispatch::Unknown, - ))) + )) } else if file_type.is_dir() { if self.options.collect_traversed_dirs { traversed_sender .send(normalized.to_owned()) .expect("receiver should outlive sender"); } - Some(Ok(( + Some(( Cow::Borrowed(normalized), Dispatch::Directory { was_file: in_dmap.is_some(), }, - ))) + )) } else { - Some(Ok(( + Some(( Cow::Borrowed(normalized), Dispatch::Bad(BadMatch::BadType( // TODO do more than unknown @@ -428,22 +443,20 @@ // users. BadType::Unknown, )), - ))) + )) }; } Err(_) => { if let Some(entry) = in_dmap { - return Some(Ok(( + return Some(( Cow::Borrowed(normalized), dispatch_missing(entry.state), - ))); + )); } } }; None }) - .flatten() - .filter_map(Result::ok) .partition(|(_, dispatch)| match dispatch { Dispatch::Directory { .. } => true, _ => false, @@ -462,7 +475,7 @@ old_results: &FastHashMap<HgPathCow<'a>, Dispatch>, results: &mut Vec<DispatchedPath<'a>>, traversed_sender: crossbeam::Sender<HgPathBuf>, - ) -> IoResult<()> { + ) { // The traversal is done in parallel, so use a channel to gather // entries. `crossbeam::Sender` is `Sync`, while `mpsc::Sender` // is not. @@ -474,25 +487,17 @@ path, &old_results, traversed_sender, - )?; + ); // Disconnect the channel so the receiver stops waiting drop(files_transmitter); - // TODO don't collect. Find a way of replicating the behavior of - // `itertools::process_results`, but for `rayon::ParallelIterator` - let new_results: IoResult<Vec<(Cow<HgPath>, Dispatch)>> = - files_receiver - .into_iter() - .map(|item| { - let (f, d) = item?; - Ok((Cow::Owned(f), d)) - }) - .collect(); + let new_results = files_receiver + .into_iter() + .par_bridge() + .map(|(f, d)| (Cow::Owned(f), d)); - results.par_extend(new_results?); - - Ok(()) + results.par_extend(new_results); } /// Dispatch a single entry (file, folder, symlink...) found during @@ -501,7 +506,7 @@ fn handle_traversed_entry<'b>( &'a self, scope: &rayon::Scope<'b>, - files_sender: &'b crossbeam::Sender<IoResult<(HgPathBuf, Dispatch)>>, + files_sender: &'b crossbeam::Sender<(HgPathBuf, Dispatch)>, old_results: &'a FastHashMap<Cow<HgPath>, Dispatch>, filename: HgPathBuf, dir_entry: DirEntry, @@ -534,7 +539,7 @@ { let metadata = dir_entry.metadata()?; files_sender - .send(Ok(( + .send(( filename.to_owned(), dispatch_found( &filename, @@ -543,7 +548,7 @@ &self.dmap.copy_map, self.options, ), - ))) + )) .unwrap(); } } else if (self.matcher.matches_everything() @@ -556,17 +561,17 @@ { if self.options.list_ignored { files_sender - .send(Ok((filename.to_owned(), Dispatch::Ignored))) + .send((filename.to_owned(), Dispatch::Ignored)) .unwrap(); } } else if self.options.list_unknown { files_sender - .send(Ok((filename.to_owned(), Dispatch::Unknown))) + .send((filename.to_owned(), Dispatch::Unknown)) .unwrap(); } } else if self.is_ignored(&filename) && self.options.list_ignored { files_sender - .send(Ok((filename.to_owned(), Dispatch::Ignored))) + .send((filename.to_owned(), Dispatch::Ignored)) .unwrap(); } } else if let Some(entry) = entry_option { @@ -575,10 +580,7 @@ || self.matcher.matches(&filename) { files_sender - .send(Ok(( - filename.to_owned(), - dispatch_missing(entry.state), - ))) + .send((filename.to_owned(), dispatch_missing(entry.state))) .unwrap(); } } @@ -590,7 +592,7 @@ fn handle_traversed_dir<'b>( &'a self, scope: &rayon::Scope<'b>, - files_sender: &'b crossbeam::Sender<IoResult<(HgPathBuf, Dispatch)>>, + files_sender: &'b crossbeam::Sender<(HgPathBuf, Dispatch)>, old_results: &'a FastHashMap<Cow<HgPath>, Dispatch>, entry_option: Option<&'a DirstateEntry>, directory: HgPathBuf, @@ -606,10 +608,10 @@ || self.matcher.matches(&directory) { files_sender - .send(Ok(( + .send(( directory.to_owned(), dispatch_missing(entry.state), - ))) + )) .unwrap(); } } @@ -621,7 +623,6 @@ &old_results, traversed_sender, ) - .unwrap_or_else(|e| files_sender.send(Err(e)).unwrap()) } }); } @@ -630,11 +631,11 @@ /// entries in a separate thread. fn traverse_dir( &self, - files_sender: &crossbeam::Sender<IoResult<(HgPathBuf, Dispatch)>>, + files_sender: &crossbeam::Sender<(HgPathBuf, Dispatch)>, directory: impl AsRef<HgPath>, old_results: &FastHashMap<Cow<HgPath>, Dispatch>, traversed_sender: crossbeam::Sender<HgPathBuf>, - ) -> IoResult<()> { + ) { let directory = directory.as_ref(); if self.options.collect_traversed_dirs { @@ -644,38 +645,33 @@ } let visit_entries = match self.matcher.visit_children_set(directory) { - VisitChildrenSet::Empty => return Ok(()), + VisitChildrenSet::Empty => return, VisitChildrenSet::This | VisitChildrenSet::Recursive => None, VisitChildrenSet::Set(set) => Some(set), }; - let buf = hg_path_to_path_buf(directory)?; + let buf = match hg_path_to_path_buf(directory) { + Ok(b) => b, + Err(_) => { + files_sender + .send((directory.to_owned(), INVALID_PATH_DISPATCH)) + .expect("receiver should outlive sender"); + return; + } + }; let dir_path = self.root_dir.join(buf); let skip_dot_hg = !directory.as_bytes().is_empty(); let entries = match list_directory(dir_path, skip_dot_hg) { Err(e) => { - return match e.kind() { - ErrorKind::NotFound | ErrorKind::PermissionDenied => { - files_sender - .send(Ok(( - directory.to_owned(), - Dispatch::Bad(BadMatch::OsError( - // Unwrapping here is OK because the error - // always is a - // real os error - e.raw_os_error().unwrap(), - )), - ))) - .expect("receiver should outlive sender"); - Ok(()) - } - _ => Err(e), - }; + files_sender + .send((directory.to_owned(), dispatch_os_error(&e))) + .expect("receiver should outlive sender"); + return; } Ok(entries) => entries, }; - rayon::scope(|scope| -> IoResult<()> { + rayon::scope(|scope| { for (filename, dir_entry) in entries { if let Some(ref set) = visit_entries { if !set.contains(filename.deref()) { @@ -690,17 +686,26 @@ }; if !old_results.contains_key(filename.deref()) { - self.handle_traversed_entry( + match self.handle_traversed_entry( scope, files_sender, old_results, filename, dir_entry, traversed_sender.clone(), - )?; + ) { + Err(e) => { + files_sender + .send(( + directory.to_owned(), + dispatch_os_error(&e), + )) + .expect("receiver should outlive sender"); + } + Ok(_) => {} + } } } - Ok(()) }) } @@ -716,14 +721,23 @@ .fs_iter(self.root_dir.clone()) .par_bridge() .filter(|(path, _)| self.matcher.matches(path)) - .flat_map(move |(filename, shortcut)| { + .map(move |(filename, shortcut)| { let entry = match shortcut { StatusShortcut::Entry(e) => e, StatusShortcut::Dispatch(d) => { - return Ok((Cow::Owned(filename), d)) + return (Cow::Owned(filename), d) } }; - let filename_as_path = hg_path_to_path_buf(&filename)?; + let filename_as_path = match hg_path_to_path_buf(&filename) + { + Ok(f) => f, + Err(_) => { + return ( + Cow::Owned(filename), + INVALID_PATH_DISPATCH, + ) + } + }; let meta = self .root_dir .join(filename_as_path) @@ -734,10 +748,10 @@ if !(m.file_type().is_file() || m.file_type().is_symlink()) => { - Ok(( + ( Cow::Owned(filename), dispatch_missing(entry.state), - )) + ) } Ok(m) => { let dispatch = dispatch_found( @@ -747,7 +761,7 @@ &self.dmap.copy_map, self.options, ); - Ok((Cow::Owned(filename), dispatch)) + (Cow::Owned(filename), dispatch) } Err(e) if e.kind() == ErrorKind::NotFound @@ -758,12 +772,14 @@ // It happens if the dirstate contains `foo/bar` // and foo is not a // directory - Ok(( + ( Cow::Owned(filename), dispatch_missing(entry.state), - )) + ) } - Err(e) => Err(e), + Err(e) => { + (Cow::Owned(filename), dispatch_os_error(&e)) + } } }), ); @@ -776,10 +792,18 @@ #[cfg(not(feature = "dirstate-tree"))] #[timed] pub fn extend_from_dmap(&self, results: &mut Vec<DispatchedPath<'a>>) { - results.par_extend(self.dmap.par_iter().flat_map( + results.par_extend(self.dmap.par_iter().map( move |(filename, entry)| { let filename: &HgPath = filename; - let filename_as_path = hg_path_to_path_buf(filename)?; + let filename_as_path = match hg_path_to_path_buf(filename) { + Ok(f) => f, + Err(_) => { + return ( + Cow::Borrowed(filename), + INVALID_PATH_DISPATCH, + ) + } + }; let meta = self.root_dir.join(filename_as_path).symlink_metadata(); match meta { @@ -787,12 +811,12 @@ if !(m.file_type().is_file() || m.file_type().is_symlink()) => { - Ok(( + ( Cow::Borrowed(filename), dispatch_missing(entry.state), - )) + ) } - Ok(m) => Ok(( + Ok(m) => ( Cow::Borrowed(filename), dispatch_found( filename, @@ -801,7 +825,7 @@ &self.dmap.copy_map, self.options, ), - )), + ), Err(e) if e.kind() == ErrorKind::NotFound || e.raw_os_error() == Some(20) => @@ -811,12 +835,12 @@ // It happens if the dirstate contains `foo/bar` // and foo is not a // directory - Ok(( + ( Cow::Borrowed(filename), dispatch_missing(entry.state), - )) + ) } - Err(e) => Err(e), + Err(e) => (Cow::Borrowed(filename), dispatch_os_error(&e)), } }, )); @@ -830,10 +854,7 @@ /// `extend` in timings #[cfg(not(feature = "dirstate-tree"))] #[timed] - pub fn handle_unknowns( - &self, - results: &mut Vec<DispatchedPath<'a>>, - ) -> IoResult<()> { + pub fn handle_unknowns(&self, results: &mut Vec<DispatchedPath<'a>>) { let to_visit: Vec<(&HgPath, &DirstateEntry)> = if results.is_empty() && self.matcher.matches_everything() { self.dmap.iter().map(|(f, e)| (f.deref(), e)).collect() @@ -857,21 +878,23 @@ let path_auditor = PathAuditor::new(&self.root_dir); - // TODO don't collect. Find a way of replicating the behavior of - // `itertools::process_results`, but for `rayon::ParallelIterator` - let new_results: IoResult<Vec<_>> = to_visit - .into_par_iter() - .filter_map(|(filename, entry)| -> Option<IoResult<_>> { + let new_results = to_visit.into_par_iter().filter_map( + |(filename, entry)| -> Option<_> { // Report ignored items in the dmap as long as they are not // under a symlink directory. if path_auditor.check(filename) { // TODO normalize for case-insensitive filesystems let buf = match hg_path_to_path_buf(filename) { Ok(x) => x, - Err(e) => return Some(Err(e.into())), + Err(_) => { + return Some(( + Cow::Owned(filename.to_owned()), + INVALID_PATH_DISPATCH, + )); + } }; - Some(Ok(( - Cow::Borrowed(filename), + Some(( + Cow::Owned(filename.to_owned()), match self.root_dir.join(&buf).symlink_metadata() { // File was just ignored, no links, and exists Ok(meta) => { @@ -887,21 +910,19 @@ // File doesn't exist Err(_) => dispatch_missing(entry.state), }, - ))) + )) } else { // It's either missing or under a symlink directory which // we, in this case, report as missing. - Some(Ok(( - Cow::Borrowed(filename), + Some(( + Cow::Owned(filename.to_owned()), dispatch_missing(entry.state), - ))) + )) } - }) - .collect(); + }, + ); - results.par_extend(new_results?); - - Ok(()) + results.par_extend(new_results); } }
--- a/rust/hg-core/src/lib.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-core/src/lib.rs Thu Dec 03 14:15:39 2020 -0500 @@ -8,6 +8,7 @@ pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors}; mod dirstate; pub mod discovery; +pub mod requirements; pub mod testing; // unconditionally built, for use from integration tests pub use dirstate::{ dirs_multiset::{DirsMultiset, DirsMultisetIter}, @@ -19,6 +20,7 @@ CopyMap, CopyMapIter, DirstateEntry, DirstateParents, EntryState, StateMap, StateMapIter, }; +pub mod copy_tracing; mod filepatterns; pub mod matchers; pub mod revlog;
--- a/rust/hg-core/src/operations/cat.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-core/src/operations/cat.rs Thu Dec 03 14:15:39 2020 -0500 @@ -6,7 +6,7 @@ // GNU General Public License version 2 or any later version. use std::convert::From; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use crate::revlog::changelog::Changelog; use crate::revlog::manifest::{Manifest, ManifestEntry}; @@ -14,7 +14,10 @@ use crate::revlog::revlog::Revlog; use crate::revlog::revlog::RevlogError; use crate::revlog::Revision; -use crate::utils::hg_path::HgPathBuf; +use crate::utils::files::get_path_from_bytes; +use crate::utils::hg_path::{HgPath, HgPathBuf}; + +const METADATA_DELIMITER: [u8; 2] = [b'\x01', b'\n']; /// Kind of error encountered by `CatRev` #[derive(Debug)] @@ -119,20 +122,29 @@ { for cat_file in self.files.iter() { if cat_file.as_bytes() == manifest_file.as_bytes() { - let encoded_bytes = - path_encode(manifest_file.as_bytes()); - let revlog_index_string = format!( - ".hg/store/data/{}.i", - String::from_utf8_lossy(&encoded_bytes), - ); - let revlog_index_path = - self.root.join(&revlog_index_string); - let file_log = Revlog::open(&revlog_index_path)?; + let index_path = + store_path(self.root, manifest_file, b".i"); + let data_path = + store_path(self.root, manifest_file, b".d"); + + let file_log = + Revlog::open(&index_path, Some(&data_path))?; let file_node = hex::decode(&node_bytes) .map_err(|_| CatRevErrorKind::CorruptedRevlog)?; let file_rev = file_log.get_node_rev(&file_node)?; let data = file_log.get_rev_data(file_rev)?; - bytes.extend(data); + if data.starts_with(&METADATA_DELIMITER) { + let end_delimiter_position = data + [METADATA_DELIMITER.len()..] + .windows(METADATA_DELIMITER.len()) + .position(|bytes| bytes == METADATA_DELIMITER); + if let Some(position) = end_delimiter_position { + let offset = METADATA_DELIMITER.len() * 2; + bytes.extend(data[position + offset..].iter()); + } + } else { + bytes.extend(data); + } } } } @@ -143,3 +155,15 @@ } } } + +fn store_path(root: &Path, hg_path: &HgPath, suffix: &[u8]) -> PathBuf { + let encoded_bytes = + path_encode(&[b"data/", hg_path.as_bytes(), suffix].concat()); + [ + root, + &Path::new(".hg/store/"), + get_path_from_bytes(&encoded_bytes), + ] + .iter() + .collect() +}
--- a/rust/hg-core/src/operations/debugdata.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-core/src/operations/debugdata.rs Thu Dec 03 14:15:39 2020 -0500 @@ -92,18 +92,22 @@ } pub fn run(&mut self) -> Result<Vec<u8>, DebugDataError> { - let rev = self - .rev - .parse::<Revision>() - .or(Err(DebugDataErrorKind::InvalidRevision))?; - let root = find_root::FindRoot::new().run()?; let index_file = match self.kind { DebugDataKind::Changelog => root.join(".hg/store/00changelog.i"), DebugDataKind::Manifest => root.join(".hg/store/00manifest.i"), }; - let revlog = Revlog::open(&index_file)?; - let data = revlog.get_rev_data(rev)?; + let revlog = Revlog::open(&index_file, None)?; + + let data = match self.rev.parse::<Revision>() { + Ok(rev) => revlog.get_rev_data(rev)?, + _ => { + let node = hex::decode(&self.rev) + .map_err(|_| DebugDataErrorKind::InvalidRevision)?; + let rev = revlog.get_node_rev(&node)?; + revlog.get_rev_data(rev)? + } + }; Ok(data) }
--- a/rust/hg-core/src/operations/dirstate_status.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-core/src/operations/dirstate_status.rs Thu Dec 03 14:15:39 2020 -0500 @@ -56,7 +56,7 @@ .expect("old results should exist"), &mut results, traversed_sender.clone(), - )?; + ); } } _ => { @@ -104,7 +104,7 @@ &old_results, &mut results, traversed_sender.clone(), - )?; + ); } } _ => { @@ -116,7 +116,7 @@ if !self.matcher.is_exact() { if self.options.list_unknown { - self.handle_unknowns(&mut results)?; + self.handle_unknowns(&mut results); } else { // TODO this is incorrect, see issue6335 // This requires a fix in both Python and Rust that can happen
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/hg-core/src/requirements.rs Thu Dec 03 14:15:39 2020 -0500 @@ -0,0 +1,72 @@ +use std::io; +use std::path::Path; + +#[derive(Debug)] +pub enum RequirementsError { + // TODO: include a path? + Io(io::Error), + /// The `requires` file is corrupted + Corrupted, + /// The repository requires a feature that we don't support + Unsupported { + feature: String, + }, +} + +fn parse(bytes: &[u8]) -> Result<Vec<String>, ()> { + // The Python code reading this file uses `str.splitlines` + // which looks for a number of line separators (even including a couple of + // non-ASCII ones), but Python code writing it always uses `\n`. + let lines = bytes.split(|&byte| byte == b'\n'); + + lines + .filter(|line| !line.is_empty()) + .map(|line| { + // Python uses Unicode `str.isalnum` but feature names are all + // ASCII + if line[0].is_ascii_alphanumeric() && line.is_ascii() { + Ok(String::from_utf8(line.into()).unwrap()) + } else { + Err(()) + } + }) + .collect() +} + +pub fn load(repo_root: &Path) -> Result<Vec<String>, RequirementsError> { + match std::fs::read(repo_root.join(".hg").join("requires")) { + Ok(bytes) => parse(&bytes).map_err(|()| RequirementsError::Corrupted), + + // Treat a missing file the same as an empty file. + // From `mercurial/localrepo.py`: + // > requires file contains a newline-delimited list of + // > features/capabilities the opener (us) must have in order to use + // > the repository. This file was introduced in Mercurial 0.9.2, + // > which means very old repositories may not have one. We assume + // > a missing file translates to no requirements. + Err(error) if error.kind() == std::io::ErrorKind::NotFound => { + Ok(Vec::new()) + } + + Err(error) => Err(RequirementsError::Io(error))?, + } +} + +pub fn check(repo_root: &Path) -> Result<(), RequirementsError> { + for feature in load(repo_root)? { + if !SUPPORTED.contains(&&*feature) { + return Err(RequirementsError::Unsupported { feature }); + } + } + Ok(()) +} + +// TODO: set this to actually-supported features +const SUPPORTED: &[&str] = &[ + "dotencode", + "fncache", + "generaldelta", + "revlogv1", + "sparserevlog", + "store", +];
--- a/rust/hg-core/src/revlog/changelog.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-core/src/revlog/changelog.rs Thu Dec 03 14:15:39 2020 -0500 @@ -12,7 +12,7 @@ /// Open the `changelog` of a repository given by its root. pub fn open(root: &PathBuf) -> Result<Self, RevlogError> { let index_file = root.join(".hg/store/00changelog.i"); - let revlog = Revlog::open(&index_file)?; + let revlog = Revlog::open(&index_file, None)?; Ok(Self { revlog }) }
--- a/rust/hg-core/src/revlog/manifest.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-core/src/revlog/manifest.rs Thu Dec 03 14:15:39 2020 -0500 @@ -13,7 +13,7 @@ /// Open the `manifest` of a repository given by its root. pub fn open(root: &PathBuf) -> Result<Self, RevlogError> { let index_file = root.join(".hg/store/00manifest.i"); - let revlog = Revlog::open(&index_file)?; + let revlog = Revlog::open(&index_file, None)?; Ok(Self { revlog }) }
--- a/rust/hg-core/src/revlog/revlog.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-core/src/revlog/revlog.rs Thu Dec 03 14:15:39 2020 -0500 @@ -47,7 +47,10 @@ /// It will also open the associated data file if index and data are not /// interleaved. #[timed] - pub fn open(index_path: &Path) -> Result<Self, RevlogError> { + pub fn open( + index_path: &Path, + data_path: Option<&Path>, + ) -> Result<Self, RevlogError> { let index_mmap = mmap_open(&index_path).map_err(RevlogError::IoError)?; @@ -58,16 +61,17 @@ let index = Index::new(Box::new(index_mmap))?; - // TODO load data only when needed // + let default_data_path = index_path.with_extension("d"); + // type annotation required // won't recognize Mmap as Deref<Target = [u8]> let data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>> = if index.is_inline() { None } else { - let data_path = index_path.with_extension("d"); + let data_path = data_path.unwrap_or(&default_data_path); let data_mmap = - mmap_open(&data_path).map_err(RevlogError::IoError)?; + mmap_open(data_path).map_err(RevlogError::IoError)?; Some(Box::new(data_mmap)) };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/hg-cpython/src/copy_tracing.rs Thu Dec 03 14:15:39 2020 -0500 @@ -0,0 +1,295 @@ +use cpython::ObjectProtocol; +use cpython::PyBool; +use cpython::PyBytes; +use cpython::PyDict; +use cpython::PyList; +use cpython::PyModule; +use cpython::PyObject; +use cpython::PyResult; +use cpython::PyTuple; +use cpython::Python; + +use hg::copy_tracing::combine_changeset_copies; +use hg::copy_tracing::ChangedFiles; +use hg::copy_tracing::RevInfo; +use hg::utils::hg_path::HgPathBuf; +use hg::Revision; + +/// Combines copies information contained into revision `revs` to build a copy +/// map. +/// +/// See mercurial/copies.py for details +pub fn combine_changeset_copies_wrapper( + py: Python, + revs: PyList, + children: PyDict, + target_rev: Revision, + rev_info: PyObject, + is_ancestor: PyObject, +) -> PyResult<PyDict> { + let revs: PyResult<_> = + revs.iter(py).map(|r| Ok(r.extract(py)?)).collect(); + + // Wrap the `is_ancestor` python callback as a Rust closure + // + // No errors are expected from the Python side, and they will should only + // happens in case of programing error or severe data corruption. Such + // errors will raise panic and the rust-cpython harness will turn them into + // Python exception. + let is_ancestor_wrap = |anc: Revision, desc: Revision| -> bool { + is_ancestor + .call(py, (anc, desc), None) + .expect( + "rust-copy-tracing: python call to `is_ancestor` \ + failed", + ) + .cast_into::<PyBool>(py) + .expect( + "rust-copy-tracing: python call to `is_ancestor` \ + returned unexpected non-Bool value", + ) + .is_true() + }; + + // Wrap the `rev_info_maker` python callback as a Rust closure + // + // No errors are expected from the Python side, and they will should only + // happens in case of programing error or severe data corruption. Such + // errors will raise panic and the rust-cpython harness will turn them into + // Python exception. + let rev_info_maker = |rev: Revision| -> RevInfo { + let res: PyTuple = rev_info + .call(py, (rev,), None) + .expect("rust-copy-tracing: python call to `rev_info` failed") + .cast_into(py) + .expect( + "rust-copy_tracing: python call to `rev_info` returned \ + unexpected non-Tuple value", + ); + let p1 = res.get_item(py, 0).extract(py).expect( + "rust-copy-tracing: \ + rev_info return is invalid, first item is a not a revision", + ); + let p2 = res.get_item(py, 1).extract(py).expect( + "rust-copy-tracing: \ + rev_info return is invalid, second item is a not a revision", + ); + + let changes = res.get_item(py, 2); + + let files; + if !changes + .hasattr(py, "copied_from_p1") + .expect("rust-copy-tracing: python call to `hasattr` failed") + { + files = ChangedFiles::new_empty(); + } else { + let p1_copies: PyDict = changes + .getattr(py, "copied_from_p1") + .expect( + "rust-copy-tracing: retrieval of python attribute \ + `copied_from_p1` failed", + ) + .cast_into(py) + .expect( + "rust-copy-tracing: failed to convert `copied_from_p1` \ + to PyDict", + ); + let p1_copies: PyResult<_> = p1_copies + .items(py) + .iter() + .map(|(key, value)| { + let key = key.extract::<PyBytes>(py).expect( + "rust-copy-tracing: conversion of copy destination to\ + PyBytes failed", + ); + let key = key.data(py); + let value = value.extract::<PyBytes>(py).expect( + "rust-copy-tracing: conversion of copy source to \ + PyBytes failed", + ); + let value = value.data(py); + Ok(( + HgPathBuf::from_bytes(key), + HgPathBuf::from_bytes(value), + )) + }) + .collect(); + + let p2_copies: PyDict = changes + .getattr(py, "copied_from_p2") + .expect( + "rust-copy-tracing: retrieval of python attribute \ + `copied_from_p2` failed", + ) + .cast_into(py) + .expect( + "rust-copy-tracing: failed to convert `copied_from_p2` \ + to PyDict", + ); + let p2_copies: PyResult<_> = p2_copies + .items(py) + .iter() + .map(|(key, value)| { + let key = key.extract::<PyBytes>(py).expect( + "rust-copy-tracing: conversion of copy destination to \ + PyBytes failed"); + let key = key.data(py); + let value = value.extract::<PyBytes>(py).expect( + "rust-copy-tracing: conversion of copy source to \ + PyBytes failed", + ); + let value = value.data(py); + Ok(( + HgPathBuf::from_bytes(key), + HgPathBuf::from_bytes(value), + )) + }) + .collect(); + + let removed: PyObject = changes.getattr(py, "removed").expect( + "rust-copy-tracing: retrieval of python attribute \ + `removed` failed", + ); + let removed: PyResult<_> = removed + .iter(py) + .expect( + "rust-copy-tracing: getting a python iterator over the \ + `removed` set failed", + ) + .map(|filename| { + let filename = filename + .expect( + "rust-copy-tracing: python iteration over the \ + `removed` set failed", + ) + .extract::<PyBytes>(py) + .expect( + "rust-copy-tracing: \ + conversion of `removed` item to PyBytes failed", + ); + let filename = filename.data(py); + Ok(HgPathBuf::from_bytes(filename)) + }) + .collect(); + + let merged: PyObject = changes.getattr(py, "merged").expect( + "rust-copy-tracing: retrieval of python attribute \ + `merged` failed", + ); + let merged: PyResult<_> = merged + .iter(py) + .expect( + "rust-copy-tracing: getting a python iterator over the \ + `merged` set failed", + ) + .map(|filename| { + let filename = filename + .expect( + "rust-copy-tracing: python iteration over the \ + `merged` set failed", + ) + .extract::<PyBytes>(py) + .expect( + "rust-copy-tracing: \ + conversion of `merged` item to PyBytes failed", + ); + let filename = filename.data(py); + Ok(HgPathBuf::from_bytes(filename)) + }) + .collect(); + + let salvaged: PyObject = changes.getattr(py, "salvaged").expect( + "rust-copy-tracing: retrieval of python attribute \ + `salvaged` failed", + ); + let salvaged: PyResult<_> = salvaged + .iter(py) + .expect( + "rust-copy-tracing: getting a python iterator over the \ + `salvaged` set failed", + ) + .map(|filename| { + let filename = filename + .expect( + "rust-copy-tracing: python iteration over the \ + `salvaged` set failed", + ) + .extract::<PyBytes>(py) + .expect( + "rust-copy-tracing: \ + conversion of `salvaged` item to PyBytes failed", + ); + let filename = filename.data(py); + Ok(HgPathBuf::from_bytes(filename)) + }) + .collect(); + files = ChangedFiles::new( + removed.unwrap(), + merged.unwrap(), + salvaged.unwrap(), + p1_copies.unwrap(), + p2_copies.unwrap(), + ); + } + + (p1, p2, files) + }; + let children: PyResult<_> = children + .items(py) + .iter() + .map(|(k, v)| { + let v: &PyList = v.cast_as(py)?; + let v: PyResult<_> = + v.iter(py).map(|child| Ok(child.extract(py)?)).collect(); + Ok((k.extract(py)?, v?)) + }) + .collect(); + + let res = combine_changeset_copies( + revs?, + children?, + target_rev, + &rev_info_maker, + &is_ancestor_wrap, + ); + let out = PyDict::new(py); + for (dest, source) in res.into_iter() { + out.set_item( + py, + PyBytes::new(py, &dest.into_vec()), + PyBytes::new(py, &source.into_vec()), + )?; + } + Ok(out) +} + +/// Create the module, with `__package__` given from parent +pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> { + let dotted_name = &format!("{}.copy_tracing", package); + let m = PyModule::new(py, dotted_name)?; + + m.add(py, "__package__", package)?; + m.add(py, "__doc__", "Copy tracing - Rust implementation")?; + + m.add( + py, + "combine_changeset_copies", + py_fn!( + py, + combine_changeset_copies_wrapper( + revs: PyList, + children: PyDict, + target_rev: Revision, + rev_info: PyObject, + is_ancestor: PyObject + ) + ), + )?; + + let sys = PyModule::import(py, "sys")?; + let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?; + sys_modules.set_item(py, dotted_name, &m)?; + + Ok(m) +}
--- a/rust/hg-cpython/src/dirstate/status.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-cpython/src/dirstate/status.rs Thu Dec 03 14:15:39 2020 -0500 @@ -10,6 +10,7 @@ //! `rustext.dirstate.status`. use crate::{dirstate::DirstateMap, exceptions::FallbackError}; +use cpython::exc::OSError; use cpython::{ exc::ValueError, ObjectProtocol, PyBytes, PyErr, PyList, PyObject, PyResult, PyTuple, Python, PythonObject, ToPyObject, @@ -89,6 +90,7 @@ PyErr::new::<FallbackError, _>(py, &as_string) } + StatusError::IO(e) => PyErr::new::<OSError, _>(py, e.to_string()), e => PyErr::new::<ValueError, _>(py, e.to_string()), } }
--- a/rust/hg-cpython/src/lib.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hg-cpython/src/lib.rs Thu Dec 03 14:15:39 2020 -0500 @@ -29,6 +29,7 @@ mod conversion; #[macro_use] pub mod ref_sharing; +pub mod copy_tracing; pub mod dagops; pub mod debug; pub mod dirstate; @@ -49,6 +50,11 @@ m.add(py, "ancestor", ancestors::init_module(py, &dotted_name)?)?; m.add(py, "dagop", dagops::init_module(py, &dotted_name)?)?; m.add(py, "debug", debug::init_module(py, &dotted_name)?)?; + m.add( + py, + "copy_tracing", + copy_tracing::init_module(py, &dotted_name)?, + )?; m.add(py, "discovery", discovery::init_module(py, &dotted_name)?)?; m.add(py, "dirstate", dirstate::init_module(py, &dotted_name)?)?; m.add(py, "revlog", revlog::init_module(py, &dotted_name)?)?;
--- a/rust/hgcli/pyoxidizer.bzl Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/hgcli/pyoxidizer.bzl Thu Dec 03 14:15:39 2020 -0500 @@ -14,6 +14,10 @@ return default_python_distribution(flavor = "standalone_dynamic") def resource_callback(policy, resource): + if not IS_WINDOWS: + resource.add_location = "in-memory" + return + # We use a custom resource routing policy to influence where things are loaded # from. # @@ -36,18 +40,22 @@ def make_exe(dist): """Builds a Rust-wrapped Mercurial binary.""" packaging_policy = dist.make_python_packaging_policy() + # Extension may depend on any Python functionality. Include all # extensions. packaging_policy.extension_module_filter = "all" packaging_policy.resources_location = "in-memory" - packaging_policy.resources_location_fallback = "filesystem-relative:lib" + if IS_WINDOWS: + packaging_policy.resources_location_fallback = "filesystem-relative:lib" packaging_policy.register_resource_callback(resource_callback) config = dist.make_python_interpreter_config() config.raw_allocator = "system" - config.run_mode = "eval:%s" % RUN_CODE + config.run_command = RUN_CODE + # We want to let the user load extensions from the file system config.filesystem_importer = True + # We need this to make resourceutil happy, since it looks for sys.frozen. config.sys_frozen = True config.legacy_windows_stdio = True
--- a/rust/rhg/Cargo.toml Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/rhg/Cargo.toml Thu Dec 03 14:15:39 2020 -0500 @@ -1,7 +1,10 @@ [package] name = "rhg" version = "0.1.0" -authors = ["Antoine Cezar <antoine.cezar@octobus.net>"] +authors = [ + "Antoine Cezar <antoine.cezar@octobus.net>", + "Raphaël Gomès <raphael.gomes@octobus.net>", +] edition = "2018" [dependencies] @@ -10,3 +13,4 @@ log = "0.4.11" micro-timer = "0.3.1" env_logger = "0.7.1" +format-bytes = "0.1.3"
--- a/rust/rhg/src/commands.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/rhg/src/commands.rs Thu Dec 03 14:15:39 2020 -0500 @@ -1,5 +1,6 @@ pub mod cat; pub mod debugdata; +pub mod debugrequirements; pub mod files; pub mod root; use crate::error::CommandError;
--- a/rust/rhg/src/commands/cat.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/rhg/src/commands/cat.rs Thu Dec 03 14:15:39 2020 -0500 @@ -4,6 +4,7 @@ use crate::ui::Ui; use hg::operations::FindRoot; use hg::operations::{CatRev, CatRevError, CatRevErrorKind}; +use hg::requirements; use hg::utils::hg_path::HgPathBuf; use micro_timer::timed; use std::convert::TryFrom; @@ -32,6 +33,7 @@ #[timed] fn run(&self, ui: &Ui) -> Result<(), CommandError> { let root = FindRoot::new().run()?; + requirements::check(&root)?; let cwd = std::env::current_dir() .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?; @@ -68,7 +70,7 @@ )), CatRevErrorKind::InvalidRevision => CommandErrorKind::Abort(Some( utf8_to_local(&format!( - "abort: invalid revision identifier{}\n", + "abort: invalid revision identifier {}\n", rev )) .into(),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/rhg/src/commands/debugrequirements.rs Thu Dec 03 14:15:39 2020 -0500 @@ -0,0 +1,30 @@ +use crate::commands::Command; +use crate::error::CommandError; +use crate::ui::Ui; +use hg::operations::FindRoot; +use hg::requirements; + +pub const HELP_TEXT: &str = " +Print the current repo requirements. +"; + +pub struct DebugRequirementsCommand {} + +impl DebugRequirementsCommand { + pub fn new() -> Self { + DebugRequirementsCommand {} + } +} + +impl Command for DebugRequirementsCommand { + fn run(&self, ui: &Ui) -> Result<(), CommandError> { + let root = FindRoot::new().run()?; + let mut output = String::new(); + for req in requirements::load(&root)? { + output.push_str(&req); + output.push('\n'); + } + ui.write_stdout(output.as_bytes())?; + Ok(()) + } +}
--- a/rust/rhg/src/commands/files.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/rhg/src/commands/files.rs Thu Dec 03 14:15:39 2020 -0500 @@ -11,6 +11,7 @@ ListRevTrackedFiles, ListRevTrackedFilesError, ListRevTrackedFilesErrorKind, }; +use hg::requirements; use hg::utils::files::{get_bytes_from_path, relativize_path}; use hg::utils::hg_path::{HgPath, HgPathBuf}; use std::path::PathBuf; @@ -57,6 +58,7 @@ impl<'a> Command for FilesCommand<'a> { fn run(&self, ui: &Ui) -> Result<(), CommandError> { let root = FindRoot::new().run()?; + requirements::check(&root)?; if let Some(rev) = self.rev { let mut operation = ListRevTrackedFiles::new(&root, rev) .map_err(|e| map_rev_error(rev, e))?; @@ -83,7 +85,7 @@ ListRevTrackedFilesErrorKind::InvalidRevision => { CommandErrorKind::Abort(Some( utf8_to_local(&format!( - "abort: invalid revision identifier{}\n", + "abort: invalid revision identifier {}\n", rev )) .into(),
--- a/rust/rhg/src/commands/root.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/rhg/src/commands/root.rs Thu Dec 03 14:15:39 2020 -0500 @@ -1,6 +1,7 @@ use crate::commands::Command; use crate::error::CommandError; use crate::ui::Ui; +use format_bytes::format_bytes; use hg::operations::FindRoot; use hg::utils::files::get_bytes_from_path; @@ -24,8 +25,7 @@ let bytes = get_bytes_from_path(path_buf); - // TODO use formating macro - ui.write_stdout(&[bytes.as_slice(), b"\n"].concat())?; + ui.write_stdout(&format_bytes!(b"{}\n", bytes.as_slice()))?; Ok(()) }
--- a/rust/rhg/src/error.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/rhg/src/error.rs Thu Dec 03 14:15:39 2020 -0500 @@ -1,6 +1,8 @@ use crate::exitcode; use crate::ui::UiError; +use format_bytes::format_bytes; use hg::operations::{FindRootError, FindRootErrorKind}; +use hg::requirements::RequirementsError; use hg::utils::files::get_bytes_from_path; use std::convert::From; use std::path::PathBuf; @@ -12,6 +14,8 @@ RootNotFound(PathBuf), /// The current directory cannot be found CurrentDirNotFound(std::io::Error), + /// `.hg/requires` + RequirementsError(RequirementsError), /// The standard output stream cannot be written to StdoutError, /// The standard error stream cannot be written to @@ -27,6 +31,10 @@ match self { CommandErrorKind::RootNotFound(_) => exitcode::ABORT, CommandErrorKind::CurrentDirNotFound(_) => exitcode::ABORT, + CommandErrorKind::RequirementsError( + RequirementsError::Unsupported { .. }, + ) => exitcode::UNIMPLEMENTED_COMMAND, + CommandErrorKind::RequirementsError(_) => exitcode::ABORT, CommandErrorKind::StdoutError => exitcode::ABORT, CommandErrorKind::StderrError => exitcode::ABORT, CommandErrorKind::Abort(_) => exitcode::ABORT, @@ -37,26 +45,21 @@ /// Return the message corresponding to the error kind if any pub fn get_error_message_bytes(&self) -> Option<Vec<u8>> { match self { - // TODO use formating macro CommandErrorKind::RootNotFound(path) => { let bytes = get_bytes_from_path(path); - Some( - [ - b"abort: no repository found in '", - bytes.as_slice(), - b"' (.hg not found)!\n", - ] - .concat(), - ) + Some(format_bytes!( + b"abort: no repository found in '{}' (.hg not found)!\n", + bytes.as_slice() + )) } - // TODO use formating macro - CommandErrorKind::CurrentDirNotFound(e) => Some( - [ - b"abort: error getting current working directory: ", - e.to_string().as_bytes(), - b"\n", - ] - .concat(), + CommandErrorKind::CurrentDirNotFound(e) => Some(format_bytes!( + b"abort: error getting current working directory: {}\n", + e.to_string().as_bytes(), + )), + CommandErrorKind::RequirementsError( + RequirementsError::Corrupted, + ) => Some( + "abort: .hg/requires is corrupted\n".as_bytes().to_owned(), ), CommandErrorKind::Abort(message) => message.to_owned(), _ => None, @@ -111,3 +114,11 @@ } } } + +impl From<RequirementsError> for CommandError { + fn from(err: RequirementsError) -> Self { + CommandError { + kind: CommandErrorKind::RequirementsError(err), + } + } +}
--- a/rust/rhg/src/main.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/rhg/src/main.rs Thu Dec 03 14:15:39 2020 -0500 @@ -83,6 +83,10 @@ .required(true) .value_name("REV"), ), + ) + .subcommand( + SubCommand::with_name("debugrequirements") + .about(commands::debugrequirements::HELP_TEXT), ); let matches = app.clone().get_matches_safe().unwrap_or_else(|err| { @@ -124,6 +128,10 @@ ("debugdata", Some(matches)) => { commands::debugdata::DebugDataCommand::try_from(matches)?.run(&ui) } + ("debugrequirements", _) => { + commands::debugrequirements::DebugRequirementsCommand::new() + .run(&ui) + } _ => unreachable!(), // Because of AppSettings::SubcommandRequired, } }
--- a/rust/rhg/src/ui.rs Thu Dec 03 13:36:24 2020 -0500 +++ b/rust/rhg/src/ui.rs Thu Dec 03 14:15:39 2020 -0500 @@ -1,3 +1,4 @@ +use format_bytes::format_bytes; use std::borrow::Cow; use std::io; use std::io::{ErrorKind, Write}; @@ -87,7 +88,10 @@ let mut stderr = io::stderr(); stderr - .write_all(&[b"abort: ", error.to_string().as_bytes(), b"\n"].concat()) + .write_all(&format_bytes!( + b"abort: {}\n", + error.to_string().as_bytes() + )) .map_err(UiError::StderrError)?; stderr.flush().map_err(UiError::StderrError)?;
--- a/setup.py Thu Dec 03 13:36:24 2020 -0500 +++ b/setup.py Thu Dec 03 14:15:39 2020 -0500 @@ -782,6 +782,9 @@ pythonlib = None + dir = os.path.dirname(self.get_ext_fullpath('dummy')) + self.hgtarget = os.path.join(dir, 'hg') + if getattr(sys, 'dllhandle', None): # Different Python installs can have different Python library # names. e.g. the official CPython distribution uses pythonXY.dll @@ -807,6 +810,19 @@ ) pythonlib = dllbasename[:-4] + # Copy the pythonXY.dll next to the binary so that it runs + # without tampering with PATH. + fsdecode = lambda x: x + if sys.version_info[0] >= 3: + fsdecode = os.fsdecode + dest = os.path.join( + os.path.dirname(self.hgtarget), + fsdecode(dllbasename), + ) + + if not os.path.exists(dest): + shutil.copy(buf.value, dest) + if not pythonlib: log.warn( 'could not determine Python DLL filename; assuming pythonXY' @@ -829,8 +845,6 @@ output_dir=self.build_temp, macros=macros, ) - dir = os.path.dirname(self.get_ext_fullpath('dummy')) - self.hgtarget = os.path.join(dir, 'hg') self.compiler.link_executable( objects, self.hgtarget, libraries=[], output_dir=self.build_temp ) @@ -1053,7 +1067,7 @@ class hginstalllib(install_lib): - ''' + """ This is a specialization of install_lib that replaces the copy_file used there so that it supports setting the mode of files after copying them, instead of just preserving the mode that the files originally had. If your @@ -1062,7 +1076,7 @@ Note that just passing keep_permissions=False to copy_file would be insufficient, as it might still be applying a umask. - ''' + """ def run(self): realcopyfile = file_util.copy_file @@ -1090,11 +1104,11 @@ class hginstallscripts(install_scripts): - ''' + """ This is a specialization of install_scripts that replaces the @LIBDIR@ with the configured directory for modules. If possible, the path is made relative to the directory for scripts. - ''' + """ def initialize_options(self): install_scripts.initialize_options(self) @@ -1387,8 +1401,7 @@ class RustExtension(Extension): - """Base classes for concrete Rust Extension classes. - """ + """Base classes for concrete Rust Extension classes.""" rusttargetdir = os.path.join('rust', 'target', 'release') @@ -1534,7 +1547,10 @@ include_dirs=common_include_dirs, extra_compile_args=common_cflags, depends=common_depends - + ['mercurial/cext/charencode.h', 'mercurial/cext/revlog.h',], + + [ + 'mercurial/cext/charencode.h', + 'mercurial/cext/revlog.h', + ], ), Extension( 'mercurial.cext.osutil', @@ -1622,10 +1638,19 @@ msvccompiler.MSVCCompiler = HackedMSVCCompiler packagedata = { - 'mercurial': ['locale/*/LC_MESSAGES/hg.mo', 'dummycert.pem',], - 'mercurial.defaultrc': ['*.rc',], - 'mercurial.helptext': ['*.txt',], - 'mercurial.helptext.internals': ['*.txt',], + 'mercurial': [ + 'locale/*/LC_MESSAGES/hg.mo', + 'dummycert.pem', + ], + 'mercurial.defaultrc': [ + '*.rc', + ], + 'mercurial.helptext': [ + '*.txt', + ], + 'mercurial.helptext.internals': [ + '*.txt', + ], }
--- a/tests/artifacts/scripts/generate-churning-bundle.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/artifacts/scripts/generate-churning-bundle.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # generate-branchy-bundle - generate a branch for a "large" branchy repository #
--- a/tests/badserverext.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/badserverext.py Thu Dec 03 14:15:39 2020 -0500 @@ -44,16 +44,24 @@ configitem = registrar.configitem(configtable) configitem( - b'badserver', b'closeafteraccept', default=False, + b'badserver', + b'closeafteraccept', + default=False, ) configitem( - b'badserver', b'closeafterrecvbytes', default=b'0', + b'badserver', + b'closeafterrecvbytes', + default=b'0', ) configitem( - b'badserver', b'closeaftersendbytes', default=b'0', + b'badserver', + b'closeaftersendbytes', + default=b'0', ) configitem( - b'badserver', b'closebeforeaccept', default=False, + b'badserver', + b'closebeforeaccept', + default=False, ) # We can't adjust __class__ on a socket instance. So we define a proxy type.
--- a/tests/check-perf-code.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/check-perf-code.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # check-perf-code - (historical) portability checker for contrib/perf.py
--- a/tests/dumbhttp.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/dumbhttp.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from __future__ import absolute_import
--- a/tests/dummysmtpd.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/dummysmtpd.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """dummy SMTP server for use in tests"""
--- a/tests/dummyssh Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/dummyssh Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from __future__ import absolute_import
--- a/tests/f Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/f Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ Utility for inspecting files in various ways.
--- a/tests/fakedirstatewritetime.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/fakedirstatewritetime.py Thu Dec 03 14:15:39 2020 -0500 @@ -27,7 +27,9 @@ configitem = registrar.configitem(configtable) configitem( - b'fakedirstatewritetime', b'fakenow', default=None, + b'fakedirstatewritetime', + b'fakenow', + default=None, ) parsers = policy.importmod('parsers')
--- a/tests/fakepatchtime.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/fakepatchtime.py Thu Dec 03 14:15:39 2020 -0500 @@ -14,7 +14,9 @@ configitem = registrar.configitem(configtable) configitem( - b'fakepatchtime', b'fakenow', default=None, + b'fakepatchtime', + b'fakenow', + default=None, )
--- a/tests/filterpyflakes.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/filterpyflakes.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Filter output by pyflakes to control which warnings we check
--- a/tests/filtertraceback.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/filtertraceback.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Filters traceback lines from stdin.
--- a/tests/flagprocessorext.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/flagprocessorext.py Thu Dec 03 14:15:39 2020 -0500 @@ -6,8 +6,8 @@ import zlib from mercurial import ( + bundlecaches, changegroup, - exchange, extensions, revlog, util, @@ -134,15 +134,25 @@ revlog.REVIDX_FLAGS_ORDER.extend(flags) # Teach exchange to use changegroup 3 - for k in exchange._bundlespeccontentopts.keys(): - exchange._bundlespeccontentopts[k][b"cg.version"] = b"03" + for k in bundlecaches._bundlespeccontentopts.keys(): + bundlecaches._bundlespeccontentopts[k][b"cg.version"] = b"03" # Register flag processors for each extension flagutil.addflagprocessor( - REVIDX_NOOP, (noopdonothingread, noopdonothing, validatehash,) + REVIDX_NOOP, + ( + noopdonothingread, + noopdonothing, + validatehash, + ), ) flagutil.addflagprocessor( - REVIDX_BASE64, (b64decode, b64encode, bypass,), + REVIDX_BASE64, + ( + b64decode, + b64encode, + bypass, + ), ) flagutil.addflagprocessor( REVIDX_GZIP, (gzipdecompress, gzipcompress, bypass)
--- a/tests/fsmonitor-run-tests.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/fsmonitor-run-tests.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # fsmonitor-run-tests.py - Run Mercurial tests with fsmonitor enabled #
--- a/tests/get-with-headers.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/get-with-headers.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """This does HTTP GET requests given a host:port and path and returns a subset of the headers plus the body of the result."""
--- a/tests/hghave Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/hghave Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """Test the running system for features availability. Exit with zero if all features are there, non-zero otherwise. If a feature name is prefixed with "no-", the absence of feature is tested.
--- a/tests/hghave.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/hghave.py Thu Dec 03 14:15:39 2020 -0500 @@ -586,7 +586,7 @@ @check("pylint", "Pylint python linter") def has_pylint(): - return matchoutput("pylint --help", br"Usage: pylint", True) + return matchoutput("pylint --help", br"Usage:[ ]+pylint", True) @check("clang-format", "clang-format C code formatter") @@ -1047,7 +1047,7 @@ version_regex = b'black, version ([0-9a-b.]+)' version = matchoutput(blackcmd, version_regex) sv = distutils.version.StrictVersion - return version and sv(_bytes2sys(version.group(1))) >= sv('19.10b0') + return version and sv(_bytes2sys(version.group(1))) >= sv('20.8b1') @check('pytype', 'the pytype type checker') @@ -1058,11 +1058,12 @@ return version and sv(_bytes2sys(version.group(0))) >= sv('2019.10.17') -@check("rustfmt", "rustfmt tool") +@check("rustfmt", "rustfmt tool at version nightly-2020-10-04") def has_rustfmt(): # We use Nightly's rustfmt due to current unstable config options. return matchoutput( - '`rustup which --toolchain nightly rustfmt` --version', b'rustfmt' + '`rustup which --toolchain nightly-2020-10-04 rustfmt` --version', + b'rustfmt', )
--- a/tests/hypothesishelpers.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/hypothesishelpers.py Thu Dec 03 14:15:39 2020 -0500 @@ -44,8 +44,7 @@ def roundtrips(data, decode, encode): - """helper to tests function that must do proper encode/decode roundtripping - """ + """helper to tests function that must do proper encode/decode roundtripping""" @given(data) def testroundtrips(value): @@ -71,6 +70,11 @@ st.builds( lambda s, e: s.encode(e), st.text(), - st.sampled_from(['utf-8', 'utf-16',]), + st.sampled_from( + [ + 'utf-8', + 'utf-16', + ] + ), ) ) | st.binary()
--- a/tests/killdaemons.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/killdaemons.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from __future__ import absolute_import import errno
--- a/tests/ls-l.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/ls-l.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # like ls -l, but do not print date, user, or non-common mode bit, to avoid # using globs in tests.
--- a/tests/md5sum.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/md5sum.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Based on python's Tools/scripts/md5sum.py #
--- a/tests/narrow-library.sh Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/narrow-library.sh Thu Dec 03 14:15:39 2020 -0500 @@ -2,7 +2,7 @@ [extensions] narrow= [ui] -ssh=python "$RUNTESTDIR/dummyssh" +ssh=$PYTHON "$RUNTESTDIR/dummyssh" [experimental] changegroup3 = True EOF
--- a/tests/printenv.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/printenv.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # simple script to be used in hooks #
--- a/tests/readlink.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/readlink.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from __future__ import absolute_import, print_function
--- a/tests/revlog-formatv0.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/revlog-formatv0.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2010 Intevation GmbH # Author(s): # Thomas Arendsen Hein <thomas@intevation.de>
--- a/tests/run-tests.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/run-tests.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # run-tests.py - Run a set of tests on Mercurial # @@ -47,6 +47,7 @@ import argparse import collections +import contextlib import difflib import distutils.version as version import errno @@ -255,9 +256,8 @@ else: family = socket.AF_INET try: - s = socket.socket(family, socket.SOCK_STREAM) - s.bind(('localhost', port)) - s.close() + with contextlib.closing(socket.socket(family, socket.SOCK_STREAM)) as s: + s.bind(('localhost', port)) return True except socket.error as exc: if exc.errno not in ( @@ -534,7 +534,9 @@ help="install and use chg wrapper in place of hg", ) hgconf.add_argument( - "--chg-debug", action="store_true", help="show chg debug logs", + "--chg-debug", + action="store_true", + help="show chg debug logs", ) hgconf.add_argument("--compiler", help="compiler to build with") hgconf.add_argument( @@ -1193,7 +1195,10 @@ if self._keeptmpdir: log( '\nKeeping testtmp dir: %s\nKeeping threadtmp dir: %s' - % (_bytes2sys(self._testtmp), _bytes2sys(self._threadtmp),) + % ( + _bytes2sys(self._testtmp), + _bytes2sys(self._threadtmp), + ) ) else: try: @@ -1439,9 +1444,11 @@ hgrc.write(b'[ui]\n') hgrc.write(b'slash = True\n') hgrc.write(b'interactive = False\n') + hgrc.write(b'detailed-exit-code = True\n') hgrc.write(b'merge = internal:merge\n') hgrc.write(b'mergemarkers = detailed\n') hgrc.write(b'promptecho = True\n') + hgrc.write(b'timeout.warn=15\n') hgrc.write(b'[defaults]\n') hgrc.write(b'[devel]\n') hgrc.write(b'all-warnings = true\n') @@ -2090,11 +2097,11 @@ @staticmethod def parsehghaveoutput(lines): - '''Parse hghave log lines. + """Parse hghave log lines. Return tuple of lists (missing, failed): * the missing/unknown features - * the features for which existence check failed''' + * the features for which existence check failed""" missing = [] failed = [] for line in lines: @@ -2154,12 +2161,10 @@ self.color = pygmentspresent def onStart(self, test): - """ Can be overriden by custom TestResult - """ + """Can be overriden by custom TestResult""" def onEnd(self): - """ Can be overriden by custom TestResult - """ + """Can be overriden by custom TestResult""" def addFailure(self, test, reason): self.failures.append((test, reason)) @@ -3167,7 +3172,9 @@ vlog("# Using HGTMP", _bytes2sys(self._hgtmp)) vlog("# Using PATH", os.environ["PATH"]) vlog( - "# Using", _bytes2sys(IMPL_PATH), _bytes2sys(osenvironb[IMPL_PATH]), + "# Using", + _bytes2sys(IMPL_PATH), + _bytes2sys(osenvironb[IMPL_PATH]), ) vlog("# Writing to directory", _bytes2sys(self._outputdir)) @@ -3433,7 +3440,7 @@ def _usecorrectpython(self): """Configure the environment to use the appropriate Python in tests.""" # Tests must use the same interpreter as us or bad things will happen. - pyexename = sys.platform == 'win32' and b'python.exe' or b'python' + pyexename = sys.platform == 'win32' and b'python.exe' or b'python3' # os.symlink() is a thing with py3 on Windows, but it requires # Administrator rights.
--- a/tests/seq.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/seq.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # A portable replacement for 'seq' #
--- a/tests/simplestorerepo.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/simplestorerepo.py Thu Dec 03 14:15:39 2020 -0500 @@ -532,6 +532,7 @@ linkmapper, transaction, addrevisioncb=None, + duplicaterevisioncb=None, maybemissingparents=False, ): if maybemissingparents: @@ -539,7 +540,7 @@ _('simple store does not support missing parents ' 'write mode') ) - nodes = [] + empty = True transaction.addbackup(self._indexpath) @@ -547,9 +548,10 @@ linkrev = linkmapper(linknode) flags = flags or revlog.REVIDX_DEFAULT_FLAGS - nodes.append(node) - if node in self._indexbynode: + if duplicaterevisioncb: + duplicaterevisioncb(self, node) + empty = False continue # Need to resolve the fulltext from the delta base. @@ -564,7 +566,8 @@ if addrevisioncb: addrevisioncb(self, node) - return nodes + empty = False + return not empty def _headrevs(self): # Assume all revisions are heads by default.
--- a/tests/svn-safe-append.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/svn-safe-append.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from __future__ import absolute_import
--- a/tests/test-absorb-filefixupstate.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-absorb-filefixupstate.py Thu Dec 03 14:15:39 2020 -0500 @@ -78,7 +78,13 @@ testfilefixup(case0, b'222', [b'', b'222']) # input case 1: 3 lines, each commit adds one line -case1 = buildcontents([(b'1', [1, 2, 3]), (b'2', [2, 3]), (b'3', [3]),]) +case1 = buildcontents( + [ + (b'1', [1, 2, 3]), + (b'2', [2, 3]), + (b'3', [3]), + ] +) # 1:1 line mapping testfilefixup(case1, b'123', case1) @@ -121,7 +127,13 @@ testfilefixup(case1, b'12b3', case1) # input case 2: delete in the middle -case2 = buildcontents([(b'11', [1, 2]), (b'22', [1]), (b'33', [1, 2]),]) +case2 = buildcontents( + [ + (b'11', [1, 2]), + (b'22', [1]), + (b'33', [1, 2]), + ] +) # deletion (optimize code should make it 2 chunks) testfilefixup( @@ -136,7 +148,13 @@ testfilefixup(case2, b'aaa', case2) # input case 3: rev 3 reverts rev 2 -case3 = buildcontents([(b'1', [1, 2, 3]), (b'2', [2]), (b'3', [1, 2, 3]),]) +case3 = buildcontents( + [ + (b'1', [1, 2, 3]), + (b'2', [2]), + (b'3', [1, 2, 3]), + ] +) # 1:1 line mapping testfilefixup(case3, b'13', case3) @@ -159,7 +177,13 @@ [ (b'1', [1, 2, 3]), (b'2', [2, 3]), - (b'3', [1, 2,]), + ( + b'3', + [ + 1, + 2, + ], + ), (b'4', [1, 3]), (b'5', [3]), (b'6', [2, 3]), @@ -183,7 +207,13 @@ testfilefixup(case4, b'', [b'', b'34', b'37', b'']) # input case 5: replace a small chunk which is near a deleted line -case5 = buildcontents([(b'12', [1, 2]), (b'3', [1]), (b'4', [1, 2]),]) +case5 = buildcontents( + [ + (b'12', [1, 2]), + (b'3', [1]), + (b'4', [1, 2]), + ] +) testfilefixup(case5, b'1cd4', [b'', b'1cd34', b'1cd4'])
--- a/tests/test-absorb-unfinished.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-absorb-unfinished.t Thu Dec 03 14:15:39 2020 -0500 @@ -17,14 +17,14 @@ $ hg commit -Aqm "foo 2" $ hg --config extensions.rebase= rebase -r 1 -d 0 - rebasing 1:c3b6dc0e177a "foo 2" (tip) + rebasing 1:c3b6dc0e177a tip "foo 2" merging foo.whole warning: conflicts while merging foo.whole! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg --config extensions.rebase= absorb abort: rebase in progress (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') - [255] + [20]
--- a/tests/test-absorb.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-absorb.t Thu Dec 03 14:15:39 2020 -0500 @@ -19,7 +19,7 @@ $ hg absorb abort: no mutable changeset to change - [255] + [10] Make some commits: @@ -229,7 +229,7 @@ $ sedi 's/Insert/insert/' a $ hg absorb --apply-changes abort: no mutable changeset to change - [255] + [10] Make working copy clean: @@ -267,7 +267,7 @@ $ echo 2 >> m2 $ hg absorb --apply-changes abort: cannot absorb into a merge - [255] + [10] $ hg revert -q -C m1 m2 Use a new repo:
--- a/tests/test-add.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-add.t Thu Dec 03 14:15:39 2020 -0500 @@ -44,11 +44,11 @@ #if no-windows $ echo foo > con.xml $ hg --config ui.portablefilenames=jump add con.xml - abort: ui.portablefilenames value is invalid ('jump') - [255] + config error: ui.portablefilenames value is invalid ('jump') + [30] $ hg --config ui.portablefilenames=abort add con.xml abort: filename contains 'con', which is reserved on Windows: con.xml - [255] + [10] $ hg st A a A b @@ -68,7 +68,7 @@ $ hg --config ui.portablefilenames=abort add adding hello:world abort: filename contains ':', which is reserved on Windows: 'hello:world' - [255] + [10] $ hg st A a A b @@ -286,7 +286,7 @@ $ hg commit -qAm "bar" $ hg forget foo --dry-run -i abort: cannot specify both --dry-run and --interactive - [255] + [10] $ hg forget foo --config ui.interactive=True -i << EOF > ?
--- a/tests/test-alias.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-alias.t Thu Dec 03 14:15:39 2020 -0500 @@ -208,8 +208,8 @@ unknown $ hg unknown - abort: alias 'unknown' resolves to unknown command 'bargle' - [255] + config error: alias 'unknown' resolves to unknown command 'bargle' + [30] $ hg help unknown alias 'unknown' resolves to unknown command 'bargle' @@ -217,8 +217,8 @@ ambiguous $ hg ambiguous - abort: alias 'ambiguous' resolves to ambiguous command 's' - [255] + config error: alias 'ambiguous' resolves to ambiguous command 's' + [30] $ hg help ambiguous alias 'ambiguous' resolves to ambiguous command 's' @@ -226,8 +226,8 @@ recursive $ hg recursive - abort: alias 'recursive' resolves to unknown command 'recursive' - [255] + config error: alias 'recursive' resolves to unknown command 'recursive' + [30] $ hg help recursive alias 'recursive' resolves to unknown command 'recursive' @@ -235,9 +235,9 @@ disabled $ hg disabled - abort: alias 'disabled' resolves to unknown command 'email' + config error: alias 'disabled' resolves to unknown command 'email' ('email' is provided by 'patchbomb' extension) - [255] + [30] $ hg help disabled alias 'disabled' resolves to unknown command 'email' @@ -251,8 +251,8 @@ no definition $ hg nodef - abort: no definition for alias 'nodefinition' - [255] + config error: no definition for alias 'nodefinition' + [30] $ hg help nodef no definition for alias 'nodefinition' @@ -260,8 +260,8 @@ no closing quotation $ hg noclosing - abort: error in definition for alias 'noclosingquotation': No closing quotation - [255] + config error: error in definition for alias 'noclosingquotation': No closing quotation + [30] $ hg help noclosing error in definition for alias 'noclosingquotation': No closing quotation @@ -275,37 +275,37 @@ invalid options $ hg no--cwd - abort: error in definition for alias 'no--cwd': --cwd may only be given on the command line - [255] + config error: error in definition for alias 'no--cwd': --cwd may only be given on the command line + [30] $ hg help no--cwd error in definition for alias 'no--cwd': --cwd may only be given on the command line $ hg no-R - abort: error in definition for alias 'no-R': -R may only be given on the command line - [255] + config error: error in definition for alias 'no-R': -R may only be given on the command line + [30] $ hg help no-R error in definition for alias 'no-R': -R may only be given on the command line $ hg no--repo - abort: error in definition for alias 'no--repo': --repo may only be given on the command line - [255] + config error: error in definition for alias 'no--repo': --repo may only be given on the command line + [30] $ hg help no--repo error in definition for alias 'no--repo': --repo may only be given on the command line $ hg no--repository - abort: error in definition for alias 'no--repository': --repository may only be given on the command line - [255] + config error: error in definition for alias 'no--repository': --repository may only be given on the command line + [30] $ hg help no--repository error in definition for alias 'no--repository': --repository may only be given on the command line $ hg no--config - abort: error in definition for alias 'no--config': --config may only be given on the command line - [255] + config error: error in definition for alias 'no--config': --config may only be given on the command line + [30] $ hg no --config alias.no='--repo elsewhere --cwd elsewhere status' - abort: error in definition for alias 'no': --repo/--cwd may only be given on the command line - [255] + config error: error in definition for alias 'no': --repo/--cwd may only be given on the command line + [30] $ hg no --config alias.no='--repo elsewhere' - abort: error in definition for alias 'no': --repo may only be given on the command line - [255] + config error: error in definition for alias 'no': --repo may only be given on the command line + [30] optional repository @@ -357,10 +357,10 @@ $ hg positional abort: too few arguments for command alias - [255] + [10] $ hg positional a abort: too few arguments for command alias - [255] + [10] $ hg positional 'node|short' rev 0 e63c23eaa88a | 1970-01-01 00:00 +0000 @@ -496,13 +496,13 @@ $ hg init sub $ cd sub $ hg count 'branch(default)' - abort: unknown revision 'default'! + abort: unknown revision 'default' 0 $ hg -v count 'branch(default)' - abort: unknown revision 'default'! + abort: unknown revision 'default' 0 $ hg -R .. count 'branch(default)' - abort: unknown revision 'default'! + abort: unknown revision 'default' 0 $ hg --cwd .. count 'branch(default)' 2 @@ -631,11 +631,11 @@ $ hg help invalidhelp non-ASCII character in alias definition 'invalidhelp:help' $ hg invaliddoc - abort: non-ASCII character in alias definition 'invaliddoc:doc' - [255] + config error: non-ASCII character in alias definition 'invaliddoc:doc' + [30] $ hg invalidhelp - abort: non-ASCII character in alias definition 'invalidhelp:help' - [255] + config error: non-ASCII character in alias definition 'invalidhelp:help' + [30] invalid arguments @@ -714,9 +714,9 @@ #if no-outer-repo $ hg root - abort: no repository found in '$TESTTMP' (.hg not found)! - [255] + abort: no repository found in '$TESTTMP' (.hg not found) + [10] $ hg --config alias.hgroot='!hg root' hgroot - abort: no repository found in '$TESTTMP' (.hg not found)! - [255] + abort: no repository found in '$TESTTMP' (.hg not found) + [10] #endif
--- a/tests/test-amend.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-amend.t Thu Dec 03 14:15:39 2020 -0500 @@ -153,7 +153,7 @@ $ echo FOO > $TESTTMP/msg $ hg amend -l $TESTTMP/msg -m BAR abort: cannot specify both --message and --logfile - [255] + [10] $ hg amend -l $TESTTMP/msg saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/974f07f28537-edb6470a-amend.hg (obsstore-off !) $ hg log -r . -T '{node|short} {desc}\n' @@ -197,7 +197,7 @@ $ echo 2 >> B $ hg amend abort: cannot amend changeset with children - [255] + [10] #if obsstore-on @@ -226,7 +226,7 @@ $ hg add bar $ hg amend --note 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy' abort: cannot store a note of more than 255 bytes - [255] + [10] $ hg amend --note "adding bar" $ hg debugobsolete -r . 112478962961147124edd43549aedd1a335e44bf be169c7e8dbe21cd10b3d79691cbe7f241e3c21c 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'} @@ -240,7 +240,7 @@ $ hg amend -m AMEND abort: cannot amend public changesets (see 'hg help phases' for details) - [255] + [10] Amend a merge changeset @@ -403,10 +403,10 @@ $ hg init $TESTTMP/repo5 $ cd $TESTTMP/repo5 $ cat <<'EOF' >> .hg/hgrc - > [ui] - > logtemplate = 'user: {user} - > date: {date|date} - > summary: {desc|firstline}\n' + > [command-templates] + > log = 'user: {user} + > date: {date|date} + > summary: {desc|firstline}\n' > EOF $ echo a>a @@ -471,7 +471,7 @@ $ hg amend -D --date '0 0' abort: cannot specify both --date and --currentdate - [255] + [10] Close branch
--- a/tests/test-ancestor.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-ancestor.py Thu Dec 03 14:15:39 2020 -0500 @@ -24,13 +24,13 @@ def buildgraph(rng, nodes=100, rootprob=0.05, mergeprob=0.2, prevprob=0.7): - '''nodes: total number of nodes in the graph + """nodes: total number of nodes in the graph rootprob: probability that a new node (not 0) will be a root mergeprob: probability that, excluding a root a node will be a merge prevprob: probability that p1 will be the previous node return value is a graph represented as an adjacency list. - ''' + """ graph = [None] * nodes for i in xrange(nodes): if i == 0 or rng.random() < rootprob: @@ -228,7 +228,11 @@ print("remaining (sorted): %s" % sorted(list(revs))) for i, (bases, revs) in enumerate( - (({10}, {11}), ({11}, {10}), ({7}, {9, 11}),) + ( + ({10}, {11}), + ({11}, {10}), + ({7}, {9, 11}), + ) ): print("%% missingancestors(), example %d" % (i + 1)) missanc = ancestor.incrementalmissingancestors(graph.get, bases)
--- a/tests/test-annotate.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-annotate.t Thu Dec 03 14:15:39 2020 -0500 @@ -930,45 +930,45 @@ $ hg up 24 --quiet $ hg log -r 'followlines()' hg: parse error: followlines takes at least 1 positional arguments - [255] + [10] $ hg log -r 'followlines(baz)' hg: parse error: followlines requires a line range - [255] + [10] $ hg log -r 'followlines(baz, x)' hg: parse error: followlines expects a line number or a range - [255] + [10] $ hg log -r 'followlines(baz, 1:2, startrev=desc("b"))' hg: parse error: followlines expects exactly one revision - [255] + [10] $ hg log -r 'followlines("glob:*", 1:2)' hg: parse error: followlines expects exactly one file - [255] + [10] $ hg log -r 'followlines(baz, 1:)' hg: parse error: line range bounds must be integers - [255] + [10] $ hg log -r 'followlines(baz, :1)' hg: parse error: line range bounds must be integers - [255] + [10] $ hg log -r 'followlines(baz, x:4)' hg: parse error: line range bounds must be integers - [255] + [10] $ hg log -r 'followlines(baz, 5:4)' hg: parse error: line range must be positive - [255] + [10] $ hg log -r 'followlines(baz, 0:4)' hg: parse error: fromline must be strictly positive - [255] + [10] $ hg log -r 'followlines(baz, 2:40)' abort: line range exceeds file size - [255] + [10] $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=[1])' hg: parse error at 43: not a prefix: [ (followlines(baz, 2:4, startrev=20, descend=[1]) ^ here) - [255] + [10] $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=a)' hg: parse error: descend argument must be a boolean - [255] + [10] Test empty annotate output
--- a/tests/test-archive.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-archive.t Thu Dec 03 14:15:39 2020 -0500 @@ -560,7 +560,7 @@ $ cd ../empty $ hg archive ../test-empty abort: no working directory: please specify a revision - [255] + [10] old file -- date clamped to 1980
--- a/tests/test-audit-path.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-audit-path.t Thu Dec 03 14:15:39 2020 -0500 @@ -177,7 +177,7 @@ $ hg up -qC 2 $ hg rebase -s 2 -d 1 --config extensions.rebase= - rebasing 2:e73c21d6b244 "file a/poisoned" (tip) + rebasing 2:e73c21d6b244 tip "file a/poisoned" abort: path 'a/poisoned' traverses symbolic link 'a' [255] $ ls ../merge-symlink-out
--- a/tests/test-audit-subrepo.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-audit-subrepo.t Thu Dec 03 14:15:39 2020 -0500 @@ -120,8 +120,8 @@ $ hg init sub $ echo '= sub' >> .hgsub $ hg ci -qAm 'add subrepo ""' - hg: parse error at .hgsub:1: = sub - [255] + config error at .hgsub:1: = sub + [30] prepare tampered repo (including the commit above): @@ -144,8 +144,8 @@ on clone (and update): $ hg clone -q emptypath emptypath2 - hg: parse error at .hgsub:1: = sub - [255] + config error at .hgsub:1: = sub + [30] Test current path -----------------
--- a/tests/test-backout.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-backout.t Thu Dec 03 14:15:39 2020 -0500 @@ -5,10 +5,10 @@ $ hg backout abort: please specify a revision to backout - [255] + [10] $ hg backout -r 0 0 abort: please specify just one revision - [255] + [10] basic operation (this also tests that editor is invoked if the commit message is not @@ -210,7 +210,7 @@ $ hg backout 1 abort: cannot backout change that is not an ancestor - [255] + [10] $ echo c > c $ hg ci -Am2 adding c @@ -227,7 +227,7 @@ $ hg backout 1 abort: cannot backout change that is not an ancestor - [255] + [10] $ hg summary parent: 2:db815d6d32e6 tip 2 @@ -464,19 +464,19 @@ $ hg backout 4 abort: cannot backout a merge changeset - [255] + [10] backout of merge with bad parent should fail $ hg backout --parent 0 4 abort: cb9a9f314b8b is not a parent of b2f3bb92043e - [255] + [10] backout of non-merge with parent should fail $ hg backout --parent 0 3 abort: cannot use --parent on non-merge changeset - [255] + [10] backout with valid parent should be ok @@ -805,7 +805,7 @@ $ hg backout --merge --no-commit 2 abort: cannot specify both --no-commit and --merge - [255] + [10] Ensure that backout out the same changeset twice performs correctly: @@ -819,5 +819,5 @@ 1 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg backout 2 removing 3 - created new head + warning: commit already existed in the repository! changeset 3:8f188de730d9 backs out changeset 2:cccc23d9d68f
--- a/tests/test-bad-pull.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bad-pull.t Thu Dec 03 14:15:39 2020 -0500 @@ -2,7 +2,7 @@ $ hg clone http://localhost:$HGPORT/ copy abort: * (glob) - [255] + [100] $ test -d copy [1] @@ -11,5 +11,5 @@ $ cat dumb.pid >> $DAEMON_PIDS $ hg clone http://localhost:$HGPORT/foo copy2 abort: HTTP Error 404: * (glob) - [255] + [100] $ killdaemons.py
--- a/tests/test-basic.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-basic.t Thu Dec 03 14:15:39 2020 -0500 @@ -9,9 +9,11 @@ lfs.usercache=$TESTTMP/.cache/lfs ui.slash=True ui.interactive=False + ui.detailed-exit-code=True ui.merge=internal:merge ui.mergemarkers=detailed ui.promptecho=True + ui.timeout.warn=15 web.address=localhost web\.ipv6=(?:True|False) (re) web.server-header=testing stub value
--- a/tests/test-batching.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-batching.py Thu Dec 03 14:15:39 2020 -0500 @@ -30,11 +30,17 @@ class localthing(thing): def foo(self, one, two=None): if one: - return b"%s and %s" % (one, two,) + return b"%s and %s" % ( + one, + two, + ) return b"Nope" def bar(self, b, a): - return b"%s und %s" % (b, a,) + return b"%s und %s" % ( + b, + a, + ) def greet(self, name=None): return b"Hello, %s" % name @@ -176,7 +182,15 @@ args = b','.join(n + b'=' + escapearg(v) for n, v in args) req.append(name + b':' + args) req = b';'.join(req) - res = self._submitone(b'batch', [(b'cmds', req,)]) + res = self._submitone( + b'batch', + [ + ( + b'cmds', + req, + ) + ], + ) for r in res.split(b';'): yield r @@ -190,7 +204,16 @@ @wireprotov1peer.batchable def foo(self, one, two=None): - encargs = [(b'one', mangle(one),), (b'two', mangle(two),)] + encargs = [ + ( + b'one', + mangle(one), + ), + ( + b'two', + mangle(two), + ), + ] encresref = wireprotov1peer.future() yield encargs, encresref yield unmangle(encresref.value) @@ -198,14 +221,33 @@ @wireprotov1peer.batchable def bar(self, b, a): encresref = wireprotov1peer.future() - yield [(b'b', mangle(b),), (b'a', mangle(a),)], encresref + yield [ + ( + b'b', + mangle(b), + ), + ( + b'a', + mangle(a), + ), + ], encresref yield unmangle(encresref.value) # greet is coded directly. It therefore does not support batching. If it # does appear in a batch, the batch is split around greet, and the call to # greet is done in its own roundtrip. def greet(self, name=None): - return unmangle(self._submitone(b'greet', [(b'name', mangle(name),)])) + return unmangle( + self._submitone( + b'greet', + [ + ( + b'name', + mangle(name), + ) + ], + ) + ) # demo remote usage
--- a/tests/test-bheads.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bheads.t Thu Dec 03 14:15:39 2020 -0500 @@ -251,7 +251,7 @@ ------- 7: Adding c branch (c) ------- - abort: unknown revision 'z'! + abort: unknown revision 'z' ------- =======
--- a/tests/test-bisect.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bisect.t Thu Dec 03 14:15:39 2020 -0500 @@ -14,167 +14,167 @@ adding a - $ hg log - changeset: 31:58c80a7c8a40 - tag: tip - user: test - date: Thu Jan 01 00:00:31 1970 +0000 - summary: msg 31 - - changeset: 30:ed2d2f24b11c - user: test - date: Thu Jan 01 00:00:30 1970 +0000 - summary: msg 30 - - changeset: 29:b5bd63375ab9 - user: test - date: Thu Jan 01 00:00:29 1970 +0000 - summary: msg 29 - - changeset: 28:8e0c2264c8af - user: test - date: Thu Jan 01 00:00:28 1970 +0000 - summary: msg 28 - - changeset: 27:288867a866e9 - user: test - date: Thu Jan 01 00:00:27 1970 +0000 - summary: msg 27 - - changeset: 26:3efc6fd51aeb - user: test - date: Thu Jan 01 00:00:26 1970 +0000 - summary: msg 26 - - changeset: 25:02a84173a97a - user: test - date: Thu Jan 01 00:00:25 1970 +0000 - summary: msg 25 - - changeset: 24:10e0acd3809e - user: test - date: Thu Jan 01 00:00:24 1970 +0000 - summary: msg 24 - - changeset: 23:5ec79163bff4 - user: test - date: Thu Jan 01 00:00:23 1970 +0000 - summary: msg 23 - - changeset: 22:06c7993750ce - user: test - date: Thu Jan 01 00:00:22 1970 +0000 - summary: msg 22 - - changeset: 21:e5db6aa3fe2a - user: test - date: Thu Jan 01 00:00:21 1970 +0000 - summary: msg 21 - - changeset: 20:7128fb4fdbc9 - user: test - date: Thu Jan 01 00:00:20 1970 +0000 - summary: msg 20 - - changeset: 19:52798545b482 - user: test - date: Thu Jan 01 00:00:19 1970 +0000 - summary: msg 19 - - changeset: 18:86977a90077e - user: test - date: Thu Jan 01 00:00:18 1970 +0000 - summary: msg 18 - - changeset: 17:03515f4a9080 - user: test - date: Thu Jan 01 00:00:17 1970 +0000 - summary: msg 17 - - changeset: 16:a2e6ea4973e9 - user: test - date: Thu Jan 01 00:00:16 1970 +0000 - summary: msg 16 - - changeset: 15:e7fa0811edb0 - user: test - date: Thu Jan 01 00:00:15 1970 +0000 - summary: msg 15 - - changeset: 14:ce8f0998e922 - user: test - date: Thu Jan 01 00:00:14 1970 +0000 - summary: msg 14 - - changeset: 13:9d7d07bc967c - user: test - date: Thu Jan 01 00:00:13 1970 +0000 - summary: msg 13 - - changeset: 12:1941b52820a5 - user: test - date: Thu Jan 01 00:00:12 1970 +0000 - summary: msg 12 - - changeset: 11:7b4cd9578619 - user: test - date: Thu Jan 01 00:00:11 1970 +0000 - summary: msg 11 - - changeset: 10:7c5eff49a6b6 - user: test - date: Thu Jan 01 00:00:10 1970 +0000 - summary: msg 10 - - changeset: 9:eb44510ef29a - user: test - date: Thu Jan 01 00:00:09 1970 +0000 - summary: msg 9 - - changeset: 8:453eb4dba229 - user: test - date: Thu Jan 01 00:00:08 1970 +0000 - summary: msg 8 - - changeset: 7:03750880c6b5 - user: test - date: Thu Jan 01 00:00:07 1970 +0000 - summary: msg 7 - - changeset: 6:a3d5c6fdf0d3 - user: test - date: Thu Jan 01 00:00:06 1970 +0000 - summary: msg 6 - - changeset: 5:7874a09ea728 - user: test - date: Thu Jan 01 00:00:05 1970 +0000 - summary: msg 5 - - changeset: 4:9b2ba8336a65 - user: test - date: Thu Jan 01 00:00:04 1970 +0000 - summary: msg 4 - - changeset: 3:b53bea5e2fcb - user: test - date: Thu Jan 01 00:00:03 1970 +0000 - summary: msg 3 - - changeset: 2:db07c04beaca - user: test - date: Thu Jan 01 00:00:02 1970 +0000 - summary: msg 2 - - changeset: 1:5cd978ea5149 - user: test - date: Thu Jan 01 00:00:01 1970 +0000 - summary: msg 1 - - changeset: 0:b99c7b9c8e11 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: msg 0 + $ hg log -G + @ changeset: 31:58c80a7c8a40 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:31 1970 +0000 + | summary: msg 31 + | + o changeset: 30:ed2d2f24b11c + | user: test + | date: Thu Jan 01 00:00:30 1970 +0000 + | summary: msg 30 + | + o changeset: 29:b5bd63375ab9 + | user: test + | date: Thu Jan 01 00:00:29 1970 +0000 + | summary: msg 29 + | + o changeset: 28:8e0c2264c8af + | user: test + | date: Thu Jan 01 00:00:28 1970 +0000 + | summary: msg 28 + | + o changeset: 27:288867a866e9 + | user: test + | date: Thu Jan 01 00:00:27 1970 +0000 + | summary: msg 27 + | + o changeset: 26:3efc6fd51aeb + | user: test + | date: Thu Jan 01 00:00:26 1970 +0000 + | summary: msg 26 + | + o changeset: 25:02a84173a97a + | user: test + | date: Thu Jan 01 00:00:25 1970 +0000 + | summary: msg 25 + | + o changeset: 24:10e0acd3809e + | user: test + | date: Thu Jan 01 00:00:24 1970 +0000 + | summary: msg 24 + | + o changeset: 23:5ec79163bff4 + | user: test + | date: Thu Jan 01 00:00:23 1970 +0000 + | summary: msg 23 + | + o changeset: 22:06c7993750ce + | user: test + | date: Thu Jan 01 00:00:22 1970 +0000 + | summary: msg 22 + | + o changeset: 21:e5db6aa3fe2a + | user: test + | date: Thu Jan 01 00:00:21 1970 +0000 + | summary: msg 21 + | + o changeset: 20:7128fb4fdbc9 + | user: test + | date: Thu Jan 01 00:00:20 1970 +0000 + | summary: msg 20 + | + o changeset: 19:52798545b482 + | user: test + | date: Thu Jan 01 00:00:19 1970 +0000 + | summary: msg 19 + | + o changeset: 18:86977a90077e + | user: test + | date: Thu Jan 01 00:00:18 1970 +0000 + | summary: msg 18 + | + o changeset: 17:03515f4a9080 + | user: test + | date: Thu Jan 01 00:00:17 1970 +0000 + | summary: msg 17 + | + o changeset: 16:a2e6ea4973e9 + | user: test + | date: Thu Jan 01 00:00:16 1970 +0000 + | summary: msg 16 + | + o changeset: 15:e7fa0811edb0 + | user: test + | date: Thu Jan 01 00:00:15 1970 +0000 + | summary: msg 15 + | + o changeset: 14:ce8f0998e922 + | user: test + | date: Thu Jan 01 00:00:14 1970 +0000 + | summary: msg 14 + | + o changeset: 13:9d7d07bc967c + | user: test + | date: Thu Jan 01 00:00:13 1970 +0000 + | summary: msg 13 + | + o changeset: 12:1941b52820a5 + | user: test + | date: Thu Jan 01 00:00:12 1970 +0000 + | summary: msg 12 + | + o changeset: 11:7b4cd9578619 + | user: test + | date: Thu Jan 01 00:00:11 1970 +0000 + | summary: msg 11 + | + o changeset: 10:7c5eff49a6b6 + | user: test + | date: Thu Jan 01 00:00:10 1970 +0000 + | summary: msg 10 + | + o changeset: 9:eb44510ef29a + | user: test + | date: Thu Jan 01 00:00:09 1970 +0000 + | summary: msg 9 + | + o changeset: 8:453eb4dba229 + | user: test + | date: Thu Jan 01 00:00:08 1970 +0000 + | summary: msg 8 + | + o changeset: 7:03750880c6b5 + | user: test + | date: Thu Jan 01 00:00:07 1970 +0000 + | summary: msg 7 + | + o changeset: 6:a3d5c6fdf0d3 + | user: test + | date: Thu Jan 01 00:00:06 1970 +0000 + | summary: msg 6 + | + o changeset: 5:7874a09ea728 + | user: test + | date: Thu Jan 01 00:00:05 1970 +0000 + | summary: msg 5 + | + o changeset: 4:9b2ba8336a65 + | user: test + | date: Thu Jan 01 00:00:04 1970 +0000 + | summary: msg 4 + | + o changeset: 3:b53bea5e2fcb + | user: test + | date: Thu Jan 01 00:00:03 1970 +0000 + | summary: msg 3 + | + o changeset: 2:db07c04beaca + | user: test + | date: Thu Jan 01 00:00:02 1970 +0000 + | summary: msg 2 + | + o changeset: 1:5cd978ea5149 + | user: test + | date: Thu Jan 01 00:00:01 1970 +0000 + | summary: msg 1 + | + o changeset: 0:b99c7b9c8e11 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: msg 0 $ hg up -C @@ -364,7 +364,7 @@ $ hg bisect -r $ hg bisect abort: cannot bisect (no known good revisions) - [255] + [20] reproduce AssertionError, issue1445 @@ -475,7 +475,7 @@ $ hg bisect --command "\"$PYTHON\" \"$TESTTMP/script.py\" and some parameters" changeset 31:58c80a7c8a40: good abort: cannot bisect (no known bad revisions) - [255] + [20] $ hg up -qr 0 $ hg bisect --command "\"$PYTHON\" \"$TESTTMP/script.py\" and some parameters" changeset 0:b99c7b9c8e11: bad @@ -545,7 +545,7 @@ $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params" changeset 31:58c80a7c8a40: good abort: cannot bisect (no known bad revisions) - [255] + [20] $ hg up -qr 0 $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params" changeset 0:b99c7b9c8e11: bad @@ -751,46 +751,46 @@ $ hg bisect -r $ hg bisect -b -c false abort: --bad and --command are incompatible - [255] + [10] $ hg bisect -b -e abort: --bad and --extend are incompatible - [255] + [10] $ hg bisect -b -g abort: --bad and --good are incompatible - [255] + [10] $ hg bisect -b -r abort: --bad and --reset are incompatible - [255] + [10] $ hg bisect -b -s abort: --bad and --skip are incompatible - [255] + [10] $ hg bisect -c false -e abort: --command and --extend are incompatible - [255] + [10] $ hg bisect -c false -g abort: --command and --good are incompatible - [255] + [10] $ hg bisect -c false -r abort: --command and --reset are incompatible - [255] + [10] $ hg bisect -c false -s abort: --command and --skip are incompatible - [255] + [10] $ hg bisect -e -g abort: --extend and --good are incompatible - [255] + [10] $ hg bisect -e -r abort: --extend and --reset are incompatible - [255] + [10] $ hg bisect -e -s abort: --extend and --skip are incompatible - [255] + [10] $ hg bisect -g -r abort: --good and --reset are incompatible - [255] + [10] $ hg bisect -g -s abort: --good and --skip are incompatible - [255] + [10] $ hg bisect -r -s abort: --reset and --skip are incompatible - [255] + [10]
--- a/tests/test-blackbox.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-blackbox.t Thu Dec 03 14:15:39 2020 -0500 @@ -482,7 +482,7 @@ #endif $ head -1 .hg/blackbox.log - 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> ** Unknown exception encountered with possibly-broken third-party extension mock + 1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> ** Unknown exception encountered with possibly-broken third-party extension "mock" (version N/A) $ tail -2 .hg/blackbox.log RuntimeError: raise
--- a/tests/test-bookflow.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bookflow.t Thu Dec 03 14:15:39 2020 -0500 @@ -140,7 +140,7 @@ $ cd ../b $ # make sure we cannot push after bookmarks diverged $ hg push -B X | grep abort - abort: push creates new remote head * with bookmark 'X'! (glob) + abort: push creates new remote head * with bookmark 'X' (glob) (pull and merge or see 'hg help push' for details about pushing new heads) [1] $ hg pull -u | grep divergent
--- a/tests/test-bookmarks-current.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bookmarks-current.t Thu Dec 03 14:15:39 2020 -0500 @@ -244,5 +244,5 @@ Y $ hg bookmarks --inactive $ hg bookmarks -ql . - abort: no active bookmark! + abort: no active bookmark [255]
--- a/tests/test-bookmarks-pushpull.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bookmarks-pushpull.t Thu Dec 03 14:15:39 2020 -0500 @@ -10,8 +10,8 @@ #require serve $ cat << EOF >> $HGRCPATH - > [ui] - > logtemplate={rev}:{node|short} {desc|firstline} + > [command-templates] + > log={rev}:{node|short} {desc|firstline} > [phases] > publish=False > [experimental] @@ -356,7 +356,7 @@ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (leaving bookmark V) $ hg push -B . ../a - abort: no active bookmark! + abort: no active bookmark [255] $ hg update -r V 0 files updated, 0 files merged, 1 files removed, 0 files unresolved @@ -386,7 +386,7 @@ $ hg pull -B anotherbadname ../a pulling from ../a abort: remote bookmark anotherbadname not found! - [255] + [10] divergent bookmarks @@ -740,7 +740,7 @@ $ hg push http://localhost:$HGPORT2/ pushing to http://localhost:$HGPORT2/ searching for changes - abort: push creates new remote head c922c0139ca0 with bookmark 'Y'! + abort: push creates new remote head c922c0139ca0 with bookmark 'Y' (merge or see 'hg help push' for details about pushing new heads) [255] $ hg -R ../a book @@ -757,7 +757,7 @@ $ hg push http://localhost:$HGPORT2/ pushing to http://localhost:$HGPORT2/ searching for changes - abort: push creates new remote head c922c0139ca0 with bookmark 'Y'! + abort: push creates new remote head c922c0139ca0 with bookmark 'Y' (merge or see 'hg help push' for details about pushing new heads) [255] $ hg -R ../a book @@ -1053,7 +1053,7 @@ pushing to $TESTTMP/addmarks searching for changes remote has heads on branch 'default' that are not known locally: a2a606d9ff1b - abort: push creates new remote head 54694f811df9 with bookmark 'X'! + abort: push creates new remote head 54694f811df9 with bookmark 'X' (pull and merge or see 'hg help push' for details about pushing new heads) [255] $ cd ../addmarks @@ -1166,7 +1166,7 @@ searching for changes no changes found pushkey-abort: prepushkey hook exited with status 1 - abort: exporting bookmark @ failed! + abort: exporting bookmark @ failed [255] #endif @@ -1194,7 +1194,7 @@ searching for changes no changes found remote: pushkey-abort: prepushkey hook exited with status 1 - abort: exporting bookmark @ failed! + abort: exporting bookmark @ failed [255] $ hg -R ../issue4455-dest/ bookmarks @@ -1205,7 +1205,7 @@ searching for changes no changes found remote: pushkey-abort: prepushkey hook exited with status 1 - exporting bookmark @ failed! + exporting bookmark @ failed [1] #endif @@ -1233,7 +1233,7 @@ searching for changes no changes found remote: pushkey-abort: prepushkey hook exited with status 1 - abort: exporting bookmark @ failed! + abort: exporting bookmark @ failed [255] $ hg -R ../issue4455-dest/ bookmarks @@ -1244,7 +1244,7 @@ searching for changes no changes found remote: pushkey-abort: prepushkey hook exited with status 1 - exporting bookmark @ failed! + exporting bookmark @ failed [1] #endif @@ -1324,7 +1324,7 @@ searching for changes no changes found remote: pushkey-abort: prepushkey.no-bm-move hook exited with status 1 - abort: updating bookmark foo failed! + abort: updating bookmark foo failed [255] #endif #if b2-binary @@ -1364,3 +1364,33 @@ no changes found (ignored 1 secret changesets) abort: cannot push bookmark foo as it points to a secret changeset [255] + +Test pushing all bookmarks + + $ hg init $TESTTMP/ab1 + $ cd $TESTTMP/ab1 + $ "$PYTHON" $TESTDIR/seq.py 1 5 | while read i; do + > echo $i > test && hg ci -Am test + > done + adding test + $ hg clone -U . ../ab2 + $ hg book -r 1 A; hg book -r 2 B; hg book -r 3 C + $ hg push ../ab2 + pushing to ../ab2 + searching for changes + no changes found + [1] + $ hg push --all-bookmarks -r 1 ../ab2 + abort: cannot specify both --all-bookmarks and --rev + [10] + $ hg push --all-bookmarks -B A ../ab2 + abort: cannot specify both --all-bookmarks and --bookmark + [10] + $ hg push --all-bookmarks ../ab2 + pushing to ../ab2 + searching for changes + no changes found + exporting bookmark A + exporting bookmark B + exporting bookmark C + [1]
--- a/tests/test-bookmarks-rebase.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bookmarks-rebase.t Thu Dec 03 14:15:39 2020 -0500 @@ -37,7 +37,7 @@ rebase $ hg rebase -s two -d one - rebasing 3:2ae46b1d99a7 "3" (two tip) + rebasing 3:2ae46b1d99a7 two tip "3" saved backup bundle to $TESTTMP/.hg/strip-backup/2ae46b1d99a7-e6b057bc-rebase.hg $ hg log @@ -77,11 +77,11 @@ created new head $ hg bookmark three $ hg rebase -s three -d two - rebasing 4:dd7c838e8362 "4" (three tip) + rebasing 4:dd7c838e8362 three tip "4" merging d warning: conflicts while merging d! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --abort rebase aborted $ hg bookmark @@ -92,11 +92,11 @@ after aborted rebase, restoring a bookmark that has been removed should not fail $ hg rebase -s three -d two - rebasing 4:dd7c838e8362 "4" (three tip) + rebasing 4:dd7c838e8362 three tip "4" merging d warning: conflicts while merging d! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg bookmark -d three $ hg rebase --abort rebase aborted
--- a/tests/test-bookmarks.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bookmarks.t Thu Dec 03 14:15:39 2020 -0500 @@ -79,13 +79,13 @@ * X2 0:f7b1eb17ad24 $ hg bookmarks -l X A Y abort: bookmark 'A' does not exist - [255] + [10] $ hg bookmarks -l -r0 abort: cannot specify both --list and --rev - [255] + [10] $ hg bookmarks -l --inactive abort: cannot specify both --inactive and --list - [255] + [10] $ hg log -T '{bookmarks % "{rev} {bookmark}\n"}' 0 X @@ -184,22 +184,22 @@ but "literal:." is not since "." seems not a literal bookmark: $ hg log -r 'bookmark("literal:.")' - abort: bookmark '.' does not exist! + abort: bookmark '.' does not exist [255] "." should fail if there's no active bookmark: $ hg bookmark --inactive $ hg log -r 'bookmark(.)' - abort: no active bookmark! + abort: no active bookmark [255] $ hg log -r 'present(bookmark(.))' $ hg log -r 'bookmark(unknown)' - abort: bookmark 'unknown' does not exist! + abort: bookmark 'unknown' does not exist [255] $ hg log -r 'bookmark("literal:unknown")' - abort: bookmark 'unknown' does not exist! + abort: bookmark 'unknown' does not exist [255] $ hg log -r 'bookmark("re:unknown")' $ hg log -r 'present(bookmark("literal:unknown"))' @@ -245,7 +245,7 @@ $ hg bookmark -m A B abort: bookmark 'A' does not exist - [255] + [10] rename to existent bookmark @@ -277,7 +277,7 @@ $ hg book rename-me $ hg book -i rename-me $ hg book -m . renamed - abort: no active bookmark! + abort: no active bookmark [255] $ hg up -q Y $ hg book -d rename-me @@ -297,7 +297,7 @@ $ hg book delete-me $ hg book -i delete-me $ hg book -d . - abort: no active bookmark! + abort: no active bookmark [255] $ hg up -q Y $ hg book -d delete-me @@ -327,28 +327,28 @@ $ hg bookmark -m Y abort: new bookmark name required - [255] + [10] $ hg bookmark -m Y Y2 Y3 abort: only one new bookmark name allowed - [255] + [10] delete without name $ hg bookmark -d abort: bookmark name required - [255] + [10] delete nonexistent bookmark $ hg bookmark -d A abort: bookmark 'A' does not exist - [255] + [10] delete with --inactive $ hg bookmark -d --inactive Y abort: cannot specify both --inactive and --delete - [255] + [10] bookmark name with spaces should be stripped @@ -385,26 +385,26 @@ $ hg bookmark ' > ' abort: bookmark names cannot consist entirely of whitespace - [255] + [10] $ hg bookmark -m Z ' > ' abort: bookmark names cannot consist entirely of whitespace - [255] + [10] bookmark with reserved name $ hg bookmark tip abort: the name 'tip' is reserved - [255] + [10] $ hg bookmark . abort: the name '.' is reserved - [255] + [10] $ hg bookmark null abort: the name 'null' is reserved - [255] + [10] bookmark with existing name @@ -431,7 +431,7 @@ $ hg bookmark 10 abort: cannot use an integer as a name - [255] + [10] bookmark with a name that matches a node id $ hg bookmark 925d80f479bb db815d6d32e6 --config "$TESTHOOK" @@ -476,15 +476,15 @@ $ hg bookmark -m Y -d Z abort: cannot specify both --delete and --rename - [255] + [10] $ hg bookmark -r 1 -d Z abort: cannot specify both --delete and --rev - [255] + [10] $ hg bookmark -r 1 -m Z Y abort: cannot specify both --rename and --rev - [255] + [10] force bookmark with existing name @@ -522,28 +522,28 @@ $ hg bookmark -r . abort: bookmark name required - [255] + [10] bookmark name with whitespace only $ hg bookmark ' ' abort: bookmark names cannot consist entirely of whitespace - [255] + [10] $ hg bookmark -m Y ' ' abort: bookmark names cannot consist entirely of whitespace - [255] + [10] invalid bookmark $ hg bookmark 'foo:bar' abort: ':' cannot be used in a name - [255] + [10] $ hg bookmark 'foo > bar' abort: '\n' cannot be used in a name - [255] + [10] the bookmark extension should be ignored now that it is part of core @@ -793,7 +793,7 @@ $ hg -R ../cloned-bookmarks-manual-update update -d 1986 abort: revision matching date not found - [255] + [10] $ hg -R ../cloned-bookmarks-manual-update update updating to active bookmark Y 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-branch-change.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-branch-change.t Thu Dec 03 14:15:39 2020 -0500 @@ -34,38 +34,38 @@ $ hg branch -r . abort: no branch name specified for the revisions - [255] + [10] Setting an invalid branch name $ hg branch -r . a:b abort: ':' cannot be used in a name - [255] + [10] $ hg branch -r . tip abort: the name 'tip' is reserved - [255] + [10] $ hg branch -r . 1234 abort: cannot use an integer as a name - [255] + [10] Change on non-linear set of commits $ hg branch -r 2 -r 4 foo abort: cannot change branch of non-linear revisions - [255] + [10] Change in middle of the stack (linear commits) $ hg branch -r 1::3 foo abort: cannot change branch of changeset with children - [255] + [10] Change with dirty working directory $ echo bar > a $ hg branch -r . foo abort: uncommitted changes - [255] + [20] $ hg revert --all reverting a @@ -74,7 +74,7 @@ $ hg branch -r 'draft() - all()' foo abort: empty revision set - [255] + [10] Changing branch on linear set of commits from head @@ -123,13 +123,13 @@ $ hg branch -r . default abort: a branch of the same name already exists - [255] + [10] Changing on a branch head which is not topological head $ hg branch -r 2 stable abort: cannot change branch of changeset with children - [255] + [10] Enabling the allowunstable config and trying to change branch on a branch head which is not a topological head @@ -143,13 +143,13 @@ Changing branch of an obsoleted changeset $ hg branch -r 4 foobar - abort: hidden revision '4' was rewritten as: 7c1991464886! + abort: hidden revision '4' was rewritten as: 7c1991464886 (use --hidden to access hidden revisions) [255] $ hg branch -r 4 --hidden foobar abort: cannot change branch of a obsolete changeset - [255] + [10] Make sure bookmark movement is correct @@ -331,7 +331,7 @@ (branch merge, don't forget to commit) $ hg branch -r . abcd abort: outstanding uncommitted merge - [255] + [20] $ hg ci -m "Merge commit" $ hg glog -r 'parents(.)::' @@ -353,7 +353,7 @@ changed branch on 1 changesets $ hg branch -r . stable abort: a branch of the same name already exists - [255] + [10] $ hg branch -r . stable --force changed branch on 1 changesets @@ -368,7 +368,7 @@ $ hg branch -r . def abort: cannot change branch of public changesets (see 'hg help phases' for details) - [255] + [10] Merge commit with conflicts, with evolution and without
--- a/tests/test-branch-option.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-branch-option.t Thu Dec 03 14:15:39 2020 -0500 @@ -57,12 +57,12 @@ unknown branch and fallback $ hg in -qbz - abort: unknown branch 'z'! + abort: unknown branch 'z' [255] $ hg in -q ../branch#z 2:f25d57ab0566 $ hg out -qbz - abort: unknown branch 'z'! + abort: unknown branch 'z' [255] in rev c branch a
--- a/tests/test-branches.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-branches.t Thu Dec 03 14:15:39 2020 -0500 @@ -51,36 +51,36 @@ $ hg branch tip abort: the name 'tip' is reserved - [255] + [10] $ hg branch null abort: the name 'null' is reserved - [255] + [10] $ hg branch . abort: the name '.' is reserved - [255] + [10] invalid characters $ hg branch 'foo:bar' abort: ':' cannot be used in a name - [255] + [10] $ hg branch 'foo > bar' abort: '\n' cannot be used in a name - [255] + [10] trailing or leading spaces should be stripped before testing duplicates $ hg branch 'b ' abort: a branch of the same name already exists (use 'hg update' to switch to it) - [255] + [10] $ hg branch ' b' abort: a branch of the same name already exists (use 'hg update' to switch to it) - [255] + [10] verify update will accept invalid legacy branch names @@ -281,7 +281,7 @@ $ hg commit -d '9 0' --close-branch -m 'close this part branch too' $ hg commit -d '9 0' --close-branch -m 're-closing this branch' abort: current revision is already a branch closing head - [255] + [10] $ hg log -r tip --debug changeset: 12:e3d49c0575d8fc2cb1cd6859c747c14f5f6d499f @@ -959,7 +959,7 @@ $ hg ci -m "closing branch" --close-branch abort: can only close branch heads (use --force-close-branch to close branch from a non-head changeset) - [255] + [10] $ hg up 0 0 files updated, 0 files merged, 1 files removed, 0 files unresolved @@ -984,7 +984,7 @@ $ hg ci -m "branch closed" --close-branch abort: can only close branch heads (use --force-close-branch to close branch from a non-head changeset) - [255] + [10] $ hg ci -m "branch closed" --force-close-branch created new head
--- a/tests/test-bundle-r.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bundle-r.t Thu Dec 03 14:15:39 2020 -0500 @@ -172,12 +172,12 @@ $ hg -R test bundle --base 2 -r tip test-bundle-branch1.hg test-3 abort: --base is incompatible with specifying a destination - [255] + [10] $ hg -R test bundle -a -r tip test-bundle-branch1.hg test-3 abort: --all is incompatible with specifying a destination - [255] + [10] $ hg -R test bundle -r tip test-bundle-branch1.hg - abort: repository default-push not found! + abort: repository default-push not found [255] $ hg -R test bundle --base 2 -r tip test-bundle-branch1.hg @@ -223,7 +223,7 @@ adding changesets transaction abort! rollback completed - abort: 00changelog.i@93ee6ab32777: unknown parent! + abort: 00changelog.i@93ee6ab32777: unknown parent [255] revision 2
--- a/tests/test-bundle-type.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bundle-type.t Thu Dec 03 14:15:39 2020 -0500 @@ -34,12 +34,12 @@ $ hg bundle -a -t unknown out.hg abort: unknown is not a recognized bundle specification (see 'hg help bundlespec' for supported values for --type) - [255] + [10] $ hg bundle -a -t unknown-v2 out.hg abort: unknown compression is not supported (see 'hg help bundlespec' for supported values for --type) - [255] + [10] $ cd .. @@ -199,7 +199,7 @@ $ hg -R tzstd bundle -a -t zstd-v1 zstd-v1 abort: compression engine zstd is not supported on v1 bundles (see 'hg help bundlespec' for supported values for --type) - [255] + [10] #else @@ -228,5 +228,5 @@ $ hg bundle -a -t garbage ../bgarbage abort: garbage is not a recognized bundle specification (see 'hg help bundlespec' for supported values for --type) - [255] + [10] $ cd ..
--- a/tests/test-bundle.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bundle.t Thu Dec 03 14:15:39 2020 -0500 @@ -288,7 +288,7 @@ $ hg -R test bundle -t packed1 packed.hg abort: packed bundles cannot be produced by "hg bundle" (use 'hg debugcreatestreamclonebundle') - [255] + [10] packed1 is produced properly @@ -349,7 +349,7 @@ $ hg -R packed unbundle packed.hg abort: packed bundles cannot be applied with "hg unbundle" (use "hg debugapplystreamclonebundle") - [255] + [10] packed1 can be consumed from debug command @@ -601,7 +601,7 @@ $ hg clone full.hg '' abort: empty destination path is not valid - [255] + [10] test for https://bz.mercurial-scm.org/216 @@ -697,13 +697,13 @@ $ cd orig $ hg incoming '../test#bundle.hg' comparing with ../test - abort: unknown revision 'bundle.hg'! + abort: unknown revision 'bundle.hg' [255] note that percent encoding is not handled: $ hg incoming ../test%23bundle.hg - abort: repository ../test%23bundle.hg not found! + abort: repository ../test%23bundle.hg not found [255] $ cd .. @@ -733,7 +733,7 @@ partial history bundle, fails w/ unknown parent $ hg -R bundle.hg verify - abort: 00changelog.i@bbd179dfa0a7: unknown parent! + abort: 00changelog.i@bbd179dfa0a7: unknown parent [255] full history bundle, refuses to verify non-local repo @@ -844,7 +844,7 @@ $ hg bundle -r 'public()' no-output.hg abort: no commits to bundle - [255] + [10] $ cd ..
--- a/tests/test-bundle2-exchange.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bundle2-exchange.t Thu Dec 03 14:15:39 2020 -0500 @@ -30,7 +30,8 @@ > bundle2-output-capture=True > [ui] > ssh="$PYTHON" "$TESTDIR/dummyssh" - > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} + > [command-templates] + > log={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} > [web] > push_ssl = false > allow_push = * @@ -986,7 +987,7 @@ abort: remote error: incompatible Mercurial client; bundle2 required (see https://www.mercurial-scm.org/wiki/IncompatibleClient) - [255] + [100] $ killdaemons.py $ cd .. @@ -1031,7 +1032,7 @@ abort: remote error: incompatible Mercurial client; bundle2 required (see https://www.mercurial-scm.org/wiki/IncompatibleClient) - [255] + [100] $ killdaemons.py @@ -1049,7 +1050,7 @@ abort: remote error: incompatible Mercurial client; bundle2 required (see https://www.mercurial-scm.org/wiki/IncompatibleClient) - [255] + [100] $ killdaemons.py $ hg --config devel.legacy.exchange=bundle1 clone ssh://user@dummy/bundle2onlyserver not-bundle2-ssh @@ -1074,7 +1075,7 @@ abort: remote error: incompatible Mercurial client; bundle2 required (see https://www.mercurial-scm.org/wiki/IncompatibleClient) - [255] + [100] $ killdaemons.py @@ -1131,7 +1132,7 @@ abort: remote error: incompatible Mercurial client; bundle2 required (see https://www.mercurial-scm.org/wiki/IncompatibleClient) - [255] + [100] (also check with ssh)
--- a/tests/test-bundle2-format.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bundle2-format.t Thu Dec 03 14:15:39 2020 -0500 @@ -235,7 +235,8 @@ > evolution.createmarkers=True > [ui] > ssh="$PYTHON" "$TESTDIR/dummyssh" - > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} + > [command-templates] + > log={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} > [web] > push_ssl = false > allow_push = *
--- a/tests/test-bundle2-multiple-changegroups.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bundle2-multiple-changegroups.t Thu Dec 03 14:15:39 2020 -0500 @@ -34,8 +34,8 @@ > EOF $ cat >> $HGRCPATH << EOF - > [ui] - > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} + > [command-templates] + > log={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} > EOF Start with a simple repository with a single commit
--- a/tests/test-bundle2-remote-changegroup.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-bundle2-remote-changegroup.t Thu Dec 03 14:15:39 2020 -0500 @@ -96,7 +96,8 @@ $ cat >> $HGRCPATH << EOF > [ui] > ssh="$PYTHON" "$TESTDIR/dummyssh" - > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} + > [command-templates] + > log={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} > EOF $ hg init repo
--- a/tests/test-cbor.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-cbor.py Thu Dec 03 14:15:39 2020 -0500 @@ -690,7 +690,12 @@ self.assertEqual( list(cborutil.streamencodearrayfromiter(source)), - [b'\x9f', b'\x43', b'foo', b'\xff',], + [ + b'\x9f', + b'\x43', + b'foo', + b'\xff', + ], ) dest = b''.join(cborutil.streamencodearrayfromiter(source)) @@ -799,7 +804,11 @@ class SetTests(TestCase): def testempty(self): self.assertEqual( - list(cborutil.streamencode(set())), [b'\xd9\x01\x02', b'\x80',] + list(cborutil.streamencode(set())), + [ + b'\xd9\x01\x02', + b'\x80', + ], ) self.assertEqual(cborutil.decodeall(b'\xd9\x01\x02\x80'), [set()]) @@ -914,14 +923,26 @@ ): cborutil.decodeall(encoded) - encoded = b''.join([b'\xd9\x01\x02', b'\x81', b'\x80',]) # empty array + encoded = b''.join( + [ + b'\xd9\x01\x02', + b'\x81', + b'\x80', + ] + ) # empty array with self.assertRaisesRegex( cborutil.CBORDecodeError, 'collections not allowed as set values' ): cborutil.decodeall(encoded) - encoded = b''.join([b'\xd9\x01\x02', b'\x81', b'\xa0',]) # empty map + encoded = b''.join( + [ + b'\xd9\x01\x02', + b'\x81', + b'\xa0', + ] + ) # empty map with self.assertRaisesRegex( cborutil.CBORDecodeError, 'collections not allowed as set values' @@ -1059,7 +1080,13 @@ ): cborutil.decodeall(encoded) - encoded = b''.join([b'\xa1', b'\x80', b'\x43foo',]) # empty array + encoded = b''.join( + [ + b'\xa1', + b'\x80', + b'\x43foo', + ] + ) # empty array with self.assertRaisesRegex( cborutil.CBORDecodeError, 'collections not supported as map keys' @@ -1260,7 +1287,10 @@ def testpartialinput(self): encoded = b''.join( - [b'\x82', b'\x01',] # array of 2 elements # integer 1 + [ + b'\x82', + b'\x01', + ] # array of 2 elements # integer 1 ) with self.assertRaisesRegex(
--- a/tests/test-check-code.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-check-code.t Thu Dec 03 14:15:39 2020 -0500 @@ -90,6 +90,6 @@ Keep Windows line endings in check - $ hg files 'set:eol(dos)' + $ testrepohg files 'set:eol(dos)' contrib/win32/hg.bat contrib/win32/mercurial.ini
--- a/tests/test-check-rust-format.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-check-rust-format.t Thu Dec 03 14:15:39 2020 -0500 @@ -3,7 +3,7 @@ $ . "$TESTDIR/helpers-testrepo.sh" $ cd "$TESTDIR"/.. - $ RUSTFMT=$(rustup which --toolchain nightly rustfmt) + $ RUSTFMT=$(rustup which --toolchain nightly-2020-10-04 rustfmt) $ for f in `testrepohg files 'glob:**/*.rs'` ; do > $RUSTFMT --check --edition=2018 --unstable-features --color=never $f > done
--- a/tests/test-chg.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-chg.t Thu Dec 03 14:15:39 2020 -0500 @@ -29,7 +29,7 @@ $ chg status $ echo '=brokenconfig' >> $HGRCPATH $ chg status - hg: parse error at * (glob) + config error at * =brokenconfig (glob) [255] $ cp $HGRCPATH.orig $HGRCPATH
--- a/tests/test-clone-update-order.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-clone-update-order.t Thu Dec 03 14:15:39 2020 -0500 @@ -22,7 +22,7 @@ $ hg clone -U -u . .#other ../b -r 0 -r 1 -r 2 -b other abort: cannot specify both --noupdate and --updaterev - [255] + [10] $ hg clone -U .#other ../b -r 0 -r 1 -r 2 -b other adding changesets
--- a/tests/test-clone.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-clone.t Thu Dec 03 14:15:39 2020 -0500 @@ -73,7 +73,7 @@ $ hg clone . '' abort: empty destination path is not valid - [255] + [10] No update, with debug option: @@ -189,7 +189,7 @@ $ hg clone --pull a '' abort: empty destination path is not valid - [255] + [10] Clone to '.': @@ -254,7 +254,7 @@ $ hg clone --noupdate --updaterev 1 a ua abort: cannot specify both --noupdate and --updaterev - [255] + [10] Testing clone -u: @@ -611,14 +611,14 @@ No local source $ hg clone a b - abort: repository a not found! + abort: repository a not found [255] Invalid URL $ hg clone http://invalid:url/a b abort: error: nonnumeric port: 'url' - [255] + [100] No remote source @@ -629,7 +629,7 @@ #else $ hg clone http://$LOCALIP:3121/a b abort: error: *refused* (glob) - [255] + [100] #endif $ rm -rf b # work around bug with http clone @@ -676,7 +676,7 @@ $ hg clone q destination directory: q abort: destination 'q' is not empty - [255] + [10] destination directory not empty @@ -684,7 +684,7 @@ $ echo stuff > a/a $ hg clone q a abort: destination 'a' is not empty - [255] + [10] #if unix-permissions no-root @@ -1106,7 +1106,7 @@ $ hg -R a id -r 0 acb14030fe0a $ hg id -R remote -r 0 - abort: repository remote not found! + abort: repository remote not found [255] $ hg --config share.pool=share -q clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" a ssh://user@dummy/remote $ hg -R remote id -r 0 @@ -1176,10 +1176,10 @@ abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path' [255] $ hg clone 'ssh://fakehost|touch%20owned/path' - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ hg clone 'ssh://fakehost%7Ctouch%20owned/path' - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ hg clone 'ssh://-oProxyCommand=touch owned%20foo@example.com/nonexistent/path' @@ -1207,14 +1207,14 @@ sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !) sending hello command sending between command - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ hg clone "ssh://example.com:%3btouch%20owned%20/" --debug running sh -c "read l; read l; read l" -p ';touch owned ' example.com 'hg -R . serve --stdio' sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !) sending hello command sending between command - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] #endif @@ -1223,7 +1223,7 @@ sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !) sending hello command sending between command - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] We should not have created a file named owned - if it exists, the
--- a/tests/test-commandserver.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-commandserver.t Thu Dec 03 14:15:39 2020 -0500 @@ -90,7 +90,7 @@ *** runcommand id 000000000000 tip *** runcommand id -runknown - abort: unknown revision 'unknown'! + abort: unknown revision 'unknown' [255] >>> from hgclient import bprint, check, readchannel @@ -148,7 +148,7 @@ ... runcommand(server, [b'log', b'-b', b'--config=alias.log=!echo pwned', ... b'default']) *** runcommand log -b --config=alias.log=!echo pwned default - abort: unknown revision '--config=alias.log=!echo pwned'! + abort: unknown revision '--config=alias.log=!echo pwned' [255] check that "histedit --commands=-" can read rules from the input channel: @@ -211,8 +211,10 @@ lfs.usercache=$TESTTMP/.cache/lfs ui.slash=True ui.interactive=False + ui.detailed-exit-code=True ui.merge=internal:merge ui.mergemarkers=detailed + ui.timeout.warn=15 ui.foo=bar ui.nontty=true web.address=localhost @@ -222,8 +224,10 @@ *** runcommand -R foo showconfig ui defaults ui.slash=True ui.interactive=False + ui.detailed-exit-code=True ui.merge=internal:merge ui.mergemarkers=detailed + ui.timeout.warn=15 ui.nontty=true #endif @@ -712,7 +716,7 @@ o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob) *** runcommand id abort: there is no Mercurial repository here (.hg not found) - [255] + [10] >>> from hgclient import check, readchannel, runcommand >>> @check @@ -729,7 +733,7 @@ $ cd repo $ hg serve --cmdserver pipe -R ../nonexistent - abort: repository ../nonexistent not found! + abort: repository ../nonexistent not found [255] $ cd .. @@ -982,8 +986,8 @@ $ cd repo3 $ cat <<EOF >> $HGRCPATH - > [ui] - > logtemplate = {rev} {desc|firstline} ({files})\n + > [command-templates] + > log = {rev} {desc|firstline} ({files})\n > > [extensions] > failafterfinalize = $TESTTMP/failafterfinalize.py
--- a/tests/test-commit-amend.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-commit-amend.t Thu Dec 03 14:15:39 2020 -0500 @@ -12,7 +12,7 @@ $ hg ci --amend abort: cannot amend public changesets (see 'hg help phases' for details) - [255] + [10] $ hg phase -r . -f -d $ echo a >> a @@ -83,7 +83,7 @@ phases: 2 draft $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend abort: empty commit message - [255] + [10] $ hg summary parent: 1:43f1ba15f28a tip amend base1 @@ -350,7 +350,7 @@ $ echo a >> a $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend abort: empty commit message - [255] + [10] $ hg book book1 1:a3b65065808c * book2 1:a3b65065808c @@ -407,7 +407,7 @@ (branch merge, don't forget to commit) $ hg ci --amend abort: cannot amend while merging - [255] + [20] $ hg ci -m 'merge' Refuse to amend if there is a merge conflict (issue5805): @@ -423,7 +423,7 @@ $ hg ci --amend abort: unresolved merge conflicts (see 'hg help resolve') - [255] + [20] $ hg up -qC . @@ -884,7 +884,7 @@ $ hg ci -m.. $ hg ci --amend --close-branch -m 'closing' abort: can only close branch heads - [255] + [10] This silliness fails: @@ -893,7 +893,7 @@ $ echo b >> b $ hg ci --close-branch -m'open and close' abort: branch "silliness" has no heads to close - [255] + [10] Test that amend with --secret creates new secret changeset forcibly ---------------------------------------------------------------------
--- a/tests/test-commit-interactive.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-commit-interactive.t Thu Dec 03 14:15:39 2020 -0500 @@ -20,14 +20,14 @@ [255] $ hg commit -i --config ui.interactive=false abort: running non-interactively - [255] + [10] $ hg commit -i empty-rw<<EOF > n > EOF diff --git a/empty-rw b/empty-rw new file mode 100644 abort: empty commit message - [255] + [10] $ hg tip -p changeset: -1:000000000000 @@ -46,7 +46,7 @@ diff --git a/empty-rw b/empty-rw new file mode 100644 abort: empty commit message - [255] + [10] $ hg tip -p changeset: -1:000000000000 @@ -61,7 +61,7 @@ $ touch untracked $ hg commit -i -m should-fail empty-rw untracked abort: untracked: file not tracked! - [255] + [10] $ rm untracked Record empty file @@ -885,7 +885,7 @@ (enter ? for help) [Ynesfdaq?] q abort: user quit - [255] + [250] Patterns @@ -1014,7 +1014,7 @@ (enter ? for help) [Ynesfdaq?] q abort: user quit - [255] + [250] s, all @@ -1350,7 +1350,7 @@ $ hg commit -i -m'will abort' abort: cannot partially commit a merge (use "hg commit" instead) - [255] + [10] $ hg up -C 0 files updated, 0 files merged, 1 files removed, 0 files unresolved @@ -1419,7 +1419,7 @@ (enter ? for help) [Ynesfdaq?] q abort: user quit - [255] + [250] $ hg revert editedfile Removing changes from patch @@ -1494,7 +1494,7 @@ Hunk #1 FAILED at 0 1 out of 1 hunks FAILED -- saving rejects to file editedfile.rej abort: patch failed to apply - [255] + [10] $ cat editedfile This change will not be committed This is the second line @@ -1540,7 +1540,7 @@ (enter ? for help) [Ynesfdaq?] e abort: error parsing patch: unhandled transition: range -> range - [255] + [10] Exiting editor with status 1, ignores the edit but does not stop the recording session @@ -1600,7 +1600,7 @@ (enter ? for help) [Ynesfdaq?] e abort: error parsing patch: unhandled transition: file -> other - [255] + [10] $ hg up -C 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-commit-unresolved.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-commit-unresolved.t Thu Dec 03 14:15:39 2020 -0500 @@ -47,7 +47,7 @@ $ hg abort abort: no merge in progress (abortflag !) abort: no operation in progress (abortcommand !) - [255] + [20] $ hg merge merging A @@ -58,10 +58,10 @@ $ hg merge --abort e4501 abort: cannot specify a node with --abort - [255] + [10] $ hg merge --abort --rev e4501 abort: cannot specify both --abort and --rev - [255] + [10] #if abortcommand when in dry-run mode @@ -101,7 +101,7 @@ $ echo "ABCD" > A $ hg commit -m "Merged" abort: unresolved merge conflicts (see 'hg help resolve') - [255] + [20] Mark the conflict as resolved and commit @@ -123,7 +123,7 @@ $ hg rm --force A $ hg commit -m merged abort: unresolved merge conflicts (see 'hg help resolve') - [255] + [20] $ hg resolve -ma (no more unresolved files) @@ -145,7 +145,7 @@ $ hg merge --preview --abort abort: cannot specify both --abort and --preview - [255] + [10] $ hg abort aborting the merge, updating back to 68352a18a7c4
--- a/tests/test-commit.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-commit.t Thu Dec 03 14:15:39 2020 -0500 @@ -11,25 +11,25 @@ $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg commit -m "" HGEDITFORM=commit.normal.normal abort: empty commit message - [255] + [10] $ hg commit -d '0 0' -m commit-1 $ echo foo >> foo $ hg commit -d '1 4444444' -m commit-3 hg: parse error: impossible time zone offset: 4444444 - [255] + [10] $ hg commit -d '1 15.1' -m commit-4 hg: parse error: invalid date: '1\t15.1' - [255] + [10] $ hg commit -d 'foo bar' -m commit-5 hg: parse error: invalid date: 'foo bar' - [255] + [10] $ hg commit -d ' 1 4444' -m commit-6 $ hg commit -d '111111111111 0' -m commit-7 hg: parse error: date exceeds 32 bits: 111111111111 - [255] + [10] $ hg commit -d '-111111111111 0' -m commit-7 hg: parse error: date exceeds 32 bits: -111111111111 - [255] + [10] $ echo foo >> foo $ hg commit -d '1901-12-13 20:45:52 +0000' -m commit-7-2 $ echo foo >> foo @@ -39,10 +39,10 @@ 2 1901-12-13 20:45:52 +0000 $ hg commit -d '1901-12-13 20:45:51 +0000' -m commit-7 hg: parse error: date exceeds 32 bits: -2147483649 - [255] + [10] $ hg commit -d '-2147483649 0' -m commit-7 hg: parse error: date exceeds 32 bits: -2147483649 - [255] + [10] commit added file that has been deleted @@ -54,7 +54,7 @@ [1] $ hg commit -m commit-8-2 bar abort: bar: file not found! - [255] + [10] $ hg -q revert -a --no-backup @@ -74,7 +74,7 @@ adding dir.file $ hg commit -m commit-10 dir dir.file abort: dir: no match under directory! - [255] + [10] $ echo >> dir/file $ mkdir bleh @@ -82,10 +82,10 @@ $ cd bleh $ hg commit -m commit-11 . abort: bleh: no match under directory! - [255] + [10] $ hg commit -m commit-12 ../dir ../dir2 abort: dir2: no match under directory! - [255] + [10] $ hg -v commit -m commit-13 ../dir committing files: dir/file @@ -96,20 +96,20 @@ $ hg commit -m commit-14 does-not-exist abort: does-not-exist: * (glob) - [255] + [10] #if symlink $ ln -s foo baz $ hg commit -m commit-15 baz abort: baz: file not tracked! - [255] + [10] $ rm baz #endif $ touch quux $ hg commit -m commit-16 quux abort: quux: file not tracked! - [255] + [10] $ echo >> dir/file $ hg -v commit -m commit-17 dir/file committing files: @@ -155,7 +155,7 @@ $ HGEDITOR=false hg ci --addremove adding newfile abort: edit failed: false exited with status 1 - [255] + [250] $ hg status ? newfile @@ -164,7 +164,7 @@ $ echo foo >> foo $ echo fake >> .hg/requires $ hg commit -m bla - abort: repository requires features unknown to this Mercurial: fake! + abort: repository requires features unknown to this Mercurial: fake (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] @@ -370,7 +370,7 @@ HG: changed changed HG: removed removed abort: empty commit message - [255] + [10] test saving last-message.txt @@ -456,7 +456,7 @@ HG: subrepo 'sub' is changed HG: subrepo 'sub2' is changed abort: empty commit message - [255] + [10] $ cat >> .hg/hgrc <<EOF > [committemplate] @@ -471,7 +471,7 @@ HG: Leave message empty to abort commit. HG: no bookmark is activated abort: empty commit message - [255] + [10] $ cat >> .hg/hgrc <<EOF > [committemplate] @@ -484,7 +484,7 @@ HG: Leave message empty to abort commit. HG: no bookmark is activated abort: empty commit message - [255] + [10] $ cat >> .hg/hgrc <<EOF > [committemplate] @@ -734,7 +734,7 @@ $ hg add foo2 $ HGEDITOR="sh $TESTTMP/notouching.sh" hg commit abort: commit message unchanged - [255] + [10] $ cd .. @@ -762,7 +762,7 @@ $ hg add foo2 $ HGEDITOR="sh $TESTTMP/notouching.sh" hg ci abort: commit message unchanged - [255] + [10] $ HGEDITOR="sh $TESTTMP/lowercaseline.sh" hg ci first line HG: this is customized commit template
--- a/tests/test-committer.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-committer.t Thu Dec 03 14:15:39 2020 -0500 @@ -102,7 +102,7 @@ $ hg commit -u ' ' -m commit-1 transaction abort! rollback completed - abort: empty username! + abort: empty username [255] # don't add tests here, previous test is unstable
--- a/tests/test-completion.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-completion.t Thu Dec 03 14:15:39 2020 -0500 @@ -131,6 +131,7 @@ debugsetparents debugsidedata debugssl + debugstrip debugsub debugsuccessorssets debugtagscache @@ -259,7 +260,7 @@ cat: output, rev, decode, include, exclude, template clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos - config: untrusted, edit, local, shared, global, template + config: untrusted, edit, local, shared, non-shared, global, template continue: dry-run copy: forget, after, at-rev, force, include, exclude, dry-run debugancestor: @@ -319,6 +320,7 @@ debugsetparents: debugsidedata: changelog, manifest, dir debugssl: + debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft debugsub: rev debugsuccessorssets: closest debugtagscache: @@ -326,7 +328,7 @@ debuguigetpass: prompt debuguiprompt: prompt debugupdatecaches: - debugupgraderepo: optimize, run, backup, changelog, manifest + debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs debugwalk: include, exclude debugwhyunstable: debugwireargs: three, four, five, ssh, remotecmd, insecure @@ -344,7 +346,7 @@ incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos init: ssh, remotecmd, insecure locate: rev, print0, fullpath, include, exclude - log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude + log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, bookmark, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude manifest: rev, all, template merge: force, rev, preview, abort, tool outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos @@ -352,7 +354,7 @@ paths: template phase: public, draft, secret, force, rev pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure - push: force, rev, bookmark, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure + push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure recover: verify remove: after, force, subrepos, include, exclude, dry-run rename: after, at-rev, force, include, exclude, dry-run
--- a/tests/test-config.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-config.t Thu Dec 03 14:15:39 2020 -0500 @@ -6,37 +6,59 @@ $ cat > .hg/hgrc << EOF > novaluekey > EOF +#if chg $ hg showconfig - hg: parse error at $TESTTMP/.hg/hgrc:1: novaluekey + config error at $TESTTMP/.hg/hgrc:1: novaluekey [255] +#else + $ hg showconfig + config error at $TESTTMP/.hg/hgrc:1: novaluekey + [30] +#endif Invalid syntax: no key $ cat > .hg/hgrc << EOF > =nokeyvalue > EOF +#if chg $ hg showconfig - hg: parse error at $TESTTMP/.hg/hgrc:1: =nokeyvalue + config error at $TESTTMP/.hg/hgrc:1: =nokeyvalue [255] +#else + $ hg showconfig + config error at $TESTTMP/.hg/hgrc:1: =nokeyvalue + [30] +#endif Test hint about invalid syntax from leading white space $ cat > .hg/hgrc << EOF > key=value > EOF +#if chg $ hg showconfig - hg: parse error at $TESTTMP/.hg/hgrc:1: key=value - unexpected leading whitespace + config error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: key=value [255] +#else + $ hg showconfig + config error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: key=value + [30] +#endif $ cat > .hg/hgrc << EOF > [section] > key=value > EOF +#if chg $ hg showconfig - hg: parse error at $TESTTMP/.hg/hgrc:1: [section] - unexpected leading whitespace + config error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: [section] [255] +#else + $ hg showconfig + config error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: [section] + [30] +#endif Reset hgrc @@ -333,7 +355,7 @@ $ HGEDITOR=false hg config --edit abort: edit failed: false exited with status 1 - [255] + [10] config affected by environment variables
--- a/tests/test-conflict.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-conflict.t Thu Dec 03 14:15:39 2020 -0500 @@ -102,6 +102,35 @@ $ hg up -q --clean . $ cat <<EOF >> .hg/hgrc + > [command-templates] + > mergemarker = '{author} {rev}' + > EOF + + $ hg merge 1 + merging a + warning: conflicts while merging a! (edit, then use 'hg resolve --mark') + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon + [1] + + $ cat a + Small Mathematical Series. + 1 + 2 + 3 + <<<<<<< working copy: test 2 + 6 + 8 + ======= + 4 + 5 + >>>>>>> merge rev: test 1 + Hop we are done. + +Verify custom conflict markers with legacy config name + + $ hg up -q --clean . + $ cat <<EOF >> .hg/hgrc > [ui] > mergemarkertemplate = '{author} {rev}' > EOF @@ -131,8 +160,8 @@ $ hg up -q --clean . $ cat >> .hg/hgrc <<EOF - > [ui] - > mergemarkertemplate={author} {rev}\nfoo\nbar\nbaz + > [command-templates] + > mergemarker={author} {rev}\nfoo\nbar\nbaz > EOF $ hg -q merge 1 @@ -170,8 +199,8 @@ $ hg --encoding utf-8 commit --logfile logfile $ cat >> .hg/hgrc <<EOF - > [ui] - > mergemarkertemplate={desc|firstline} + > [command-templates] + > mergemarker={desc|firstline} > EOF $ hg -q --encoding utf-8 merge 1
--- a/tests/test-confused-revert.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-confused-revert.t Thu Dec 03 14:15:39 2020 -0500 @@ -61,7 +61,7 @@ $ hg revert abort: uncommitted merge with no revision specified (use 'hg update' or see 'hg help revert') - [255] + [10] Revert should be ok now:
--- a/tests/test-convert-filemap.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-convert-filemap.t Thu Dec 03 14:15:39 2020 -0500 @@ -292,8 +292,8 @@ $ rm -rf source/.hg/store/data/dir/file4 #endif $ hg -q convert --filemap renames.fmap --datesort source dummydest - abort: data/dir/file3.i@e96dce0bc6a2: no match found! (reporevlogstore !) - abort: data/dir/file3/index@e96dce0bc6a2: no node! (reposimplestore !) + abort: data/dir/file3.i@e96dce0bc6a2: no match found (reporevlogstore !) + abort: data/dir/file3/index@e96dce0bc6a2: no node (reposimplestore !) [255] $ hg -q convert --filemap renames.fmap --datesort --config convert.hg.ignoreerrors=1 source renames.repo ignoring: data/dir/file3.i@e96dce0bc6a2: no match found (reporevlogstore !)
--- a/tests/test-convert-git.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-convert-git.t Thu Dec 03 14:15:39 2020 -0500 @@ -332,8 +332,8 @@ input validation $ hg convert --config convert.git.similarity=foo --datesort git-repo2 fullrepo - abort: convert.git.similarity is not a valid integer ('foo') - [255] + config error: convert.git.similarity is not a valid integer ('foo') + [30] $ hg convert --config convert.git.similarity=-1 --datesort git-repo2 fullrepo abort: similarity must be between 0 and 100 [255]
--- a/tests/test-copies-chain-merge.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-copies-chain-merge.t Thu Dec 03 14:15:39 2020 -0500 @@ -17,8 +17,8 @@ $ cat << EOF >> $HGRCPATH > [diff] > git=yes - > [ui] - > logtemplate={rev} {desc}\n + > [command-templates] + > log={rev} {desc}\n > EOF #if compatibility @@ -585,6 +585,50 @@ $ hg up null --quiet +Merging a branch where a rename was deleted with a branch where the same file was renamed +------------------------------------------------------------------------------------------ + +Create a "conflicting" merge where `d` get removed on one branch before its +rename information actually conflict with the other branch. + +(the copy information from the branch that was not deleted should win). + + $ hg up 'desc("i-0")' + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg mv b d + $ hg ci -m "h-1: b -(move)-> d" + created new head + + $ hg up 'desc("c-1")' + 1 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg merge 'desc("h-1")' + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m "mCH-delete-before-conflict-m-0" + + $ hg up 'desc("h-1")' + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge 'desc("c-1")' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m "mHC-delete-before-conflict-m-0" + created new head + $ hg log -G --rev '::(desc("mCH-delete-before-conflict-m")+desc("mHC-delete-before-conflict-m"))' + @ 36 mHC-delete-before-conflict-m-0 + |\ + +---o 35 mCH-delete-before-conflict-m-0 + | |/ + | o 34 h-1: b -(move)-> d + | | + o | 6 c-1 delete d + | | + o | 2 i-2: c -move-> d + | | + o | 1 i-1: a -move-> c + |/ + o 0 i-0 initial commit: a b h + + Test that sidedata computations during upgrades are correct =========================================================== @@ -605,6 +649,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no yes no persistent-nodemap: no no no @@ -801,6 +846,20 @@ entry-0014 size 14 '\x00\x00\x00\x01\x10\x00\x00\x00\x01\x00\x00\x00\x00d' salvaged : d, ; + ##### revision 34 ##### + 1 sidedata entries + entry-0014 size 24 + '\x00\x00\x00\x02\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00bd' + removed : b, ; + added p1: d, b; + ##### revision 35 ##### + 1 sidedata entries + entry-0014 size 4 + '\x00\x00\x00\x00' + ##### revision 36 ##### + 1 sidedata entries + entry-0014 size 4 + '\x00\x00\x00\x00' #endif @@ -1003,29 +1062,15 @@ Log output should not include a merge commit as it did not happen -#if no-changeset - $ hg log -Gfr 'desc("mBDm-0")' d - o 8 d-2 re-add d - | - ~ -#else $ hg log -Gfr 'desc("mBDm-0")' d o 8 d-2 re-add d | ~ -#endif -#if no-changeset $ hg log -Gfr 'desc("mDBm-0")' d o 8 d-2 re-add d | ~ -#else - $ hg log -Gfr 'desc("mDBm-0")' d - o 8 d-2 re-add d - | - ~ -#endif $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mBDm-0")' M b @@ -1228,6 +1273,7 @@ o 0 i-0 initial commit: a b h #else +BROKEN: `hg log --follow <file>` relies on filelog metadata to work $ hg log -Gfr 'desc("mBFm-0")' d o 22 f-2: rename i -> d | @@ -1243,6 +1289,7 @@ o 0 i-0 initial commit: a b h #else +BROKEN: `hg log --follow <file>` relies on filelog metadata to work $ hg log -Gfr 'desc("mFBm-0")' d o 22 f-2: rename i -> d | @@ -1312,6 +1359,7 @@ o 0 i-0 initial commit: a b h #else +BROKEN: `hg log --follow <file>` relies on filelog metadata to work $ hg log -Gfr 'desc("mDGm-0")' d o 26 mDGm-0 simple merge - one way |\ @@ -1340,6 +1388,7 @@ o 0 i-0 initial commit: a b h #else +BROKEN: `hg log --follow <file>` relies on filelog metadata to work $ hg log -Gfr 'desc("mDGm-0")' d o 26 mDGm-0 simple merge - one way |\ @@ -1432,6 +1481,7 @@ o 0 i-0 initial commit: a b h #else +BROKEN: `hg log --follow <file>` relies on filelog metadata to work $ hg log -Gfr 'desc("mFGm-0")' d o 28 mFGm-0 simple merge - one way |\ @@ -1461,6 +1511,7 @@ o 0 i-0 initial commit: a b h #else +BROKEN: `hg log --follow <file>` relies on filelog metadata to work $ hg log -Gfr 'desc("mGFm-0")' d o 29 mGFm-0 simple merge - the other way |\ @@ -1566,3 +1617,51 @@ A d $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mCB-revert-m-0")' $ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBC-revert-m-0")' + + +Merging a branch where a rename was deleted with a branch where the same file was renamed +------------------------------------------------------------------------------------------ + +Create a "conflicting" merge where `d` get removed on one branch before its +rename information actually conflict with the other branch. + +(the copy information from the branch that was not deleted should win). + + $ hg log -G --rev '::(desc("mCH-delete-before-conflict-m")+desc("mHC-delete-before-conflict-m"))' + @ 36 mHC-delete-before-conflict-m-0 + |\ + +---o 35 mCH-delete-before-conflict-m-0 + | |/ + | o 34 h-1: b -(move)-> d + | | + o | 6 c-1 delete d + | | + o | 2 i-2: c -move-> d + | | + o | 1 i-1: a -move-> c + |/ + o 0 i-0 initial commit: a b h + + + $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mCH-delete-before-conflict-m")' + A d + b (no-compatibility no-changeset !) + R a + R b + $ hg status --copies --rev 'desc("i-0")' --rev 'desc("mHC-delete-before-conflict-m")' + A d + b + R a + R b + $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mCH-delete-before-conflict-m")' + A d + b + R b + $ hg status --copies --rev 'desc("c-1")' --rev 'desc("mHC-delete-before-conflict-m")' + A d + b + R b + $ hg status --copies --rev 'desc("h-1")' --rev 'desc("mCH-delete-before-conflict-m")' + R a + $ hg status --copies --rev 'desc("h-1")' --rev 'desc("mHC-delete-before-conflict-m")' + R a
--- a/tests/test-copies-in-changeset.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-copies-in-changeset.t Thu Dec 03 14:15:39 2020 -0500 @@ -37,6 +37,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: yes yes no persistent-nodemap: no no no @@ -50,6 +51,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no no no persistent-nodemap: no no no @@ -344,7 +346,7 @@ $ hg mv a b $ hg ci -qm 'rename a to b' $ hg rebase -d 1 --config rebase.experimental.inmemory=yes - rebasing 2:* "rename a to b" (tip) (glob) + rebasing 2:* tip "rename a to b" (glob) merging a and b to b saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/*-*-rebase.hg (glob) $ hg st --change . --copies @@ -417,6 +419,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: yes yes no persistent-nodemap: no no no @@ -442,6 +445,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: yes yes no persistent-nodemap: no no no @@ -469,6 +473,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: yes yes no persistent-nodemap: no no no
--- a/tests/test-copies.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-copies.t Thu Dec 03 14:15:39 2020 -0500 @@ -462,6 +462,74 @@ $ hg debugpathcopies 0 5 x -> z +Create x and y, then remove y and rename x to y on one side of merge, and +modify x on the other side. The modification to x from the second side +should be propagated to y. + $ newrepo + $ echo original > x + $ hg add x + $ echo unrelated > y + $ hg add y + $ hg commit -m 'add x and y' + $ hg remove y + $ hg commit -m 'remove y' + $ hg rename x y + $ hg commit -m 'rename x to y' + $ hg checkout -q 0 + $ echo modified > x + $ hg commit -m 'modify x' + created new head + $ hg l + @ 3 modify x + | x + | o 2 rename x to y + | | x y + | o 1 remove y + |/ y + o 0 add x and y + x y +#if filelog + $ hg merge 2 + file 'x' was deleted in other [merge rev] but was modified in local [working copy]. + You can use (c)hanged version, (d)elete, or leave (u)nresolved. + What do you want to do? u + 1 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon + [1] +This should ideally be "modified", but we will probably not be able to fix +that in the filelog case. + $ cat y + original +#else + $ hg merge 2 + merging x and y to y + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ cat y + modified +#endif +Same as above, but in the opposite direction +#if filelog + $ hg co -qC 2 + $ hg merge 3 + file 'x' was deleted in local [working copy] but was modified in other [merge rev]. + You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved. + What do you want to do? u + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon + [1] +BROKEN: should be "modified" + $ cat y + original +#else + $ hg co -qC 2 + $ hg merge 3 + merging y and x to y + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ cat y + modified +#endif Create x and y, then rename x to z on one side of merge, and rename y to z and then delete z on the other side. @@ -502,7 +570,7 @@ $ hg debugpathcopies 2 4 x -> z (no-filelog !) $ hg debugpathcopies 0 4 - x -> z (filelog !) + x -> z (no-changeset no-compatibility !) $ hg debugpathcopies 1 5 $ hg debugpathcopies 2 5 x -> z (no-filelog !) @@ -625,8 +693,8 @@ a $ hg rebase -r . -d 2 -t :other - rebasing 5:5018b1509e94 "added willconflict and d" (tip) (no-changeset !) - rebasing 5:af8d273bf580 "added willconflict and d" (tip) (changeset !) + rebasing 5:5018b1509e94 tip "added willconflict and d" (no-changeset !) + rebasing 5:af8d273bf580 tip "added willconflict and d" (changeset !) $ hg up 3 -q $ hg l --hidden
--- a/tests/test-copy-move-merge.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-copy-move-merge.t Thu Dec 03 14:15:39 2020 -0500 @@ -137,7 +137,7 @@ $ hg up -qC 2 $ hg rebase --keep -d 1 -b 2 --config extensions.rebase= - rebasing 2:add3f11052fa "other" (tip) + rebasing 2:add3f11052fa tip "other" merging b and a to b merging c and a to c @@ -156,7 +156,7 @@ $ hg rebase --keep -d 1 -b 2 --config extensions.rebase= --config experimental.copytrace=off --config ui.interactive=True << EOF > c > EOF - rebasing 2:add3f11052fa "other" (tip) + rebasing 2:add3f11052fa tip "other" file 'a' was deleted in local [dest] but was modified in other [source]. You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved. What do you want to do? c @@ -238,7 +238,7 @@ file is copied from `0:a`, so the file history of the `3:b` should trace directly to `0:a`. $ hg rebase -d 2 -s 3 --config extensions.rebase= --config experimental.copytrace=off - rebasing 3:47e1a9e6273b "copy a->b (2)" (tip) + rebasing 3:47e1a9e6273b tip "copy a->b (2)" saved backup bundle to $TESTTMP/copydisable3/.hg/strip-backup/47e1a9e6273b-2d099c59-rebase.hg $ hg log -G -f b
--- a/tests/test-copy.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-copy.t Thu Dec 03 14:15:39 2020 -0500 @@ -9,7 +9,7 @@ $ hg copy a b $ hg --config ui.portablefilenames=abort copy a con.xml abort: filename contains 'con', which is reserved on Windows: con.xml - [255] + [10] $ hg status A b $ hg sum @@ -115,7 +115,7 @@ $ hg mv foo bar foo: not copying - file is not managed abort: no files to copy - [255] + [10] $ hg st -A ? foo respects ui.relative-paths @@ -124,15 +124,15 @@ $ hg mv ../foo ../bar ../foo: not copying - file is not managed abort: no files to copy - [255] + [10] $ hg mv ../foo ../bar --config ui.relative-paths=yes ../foo: not copying - file is not managed abort: no files to copy - [255] + [10] $ hg mv ../foo ../bar --config ui.relative-paths=no foo: not copying - file is not managed abort: no files to copy - [255] + [10] $ cd .. $ rmdir dir $ hg add foo
--- a/tests/test-copytrace-heuristics.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-copytrace-heuristics.t Thu Dec 03 14:15:39 2020 -0500 @@ -54,7 +54,7 @@ desc: initial $ hg rebase -s . -d 1 - rebasing 2:557f403c0afd "mod a, mod dir/file.txt" (tip) + rebasing 2:557f403c0afd tip "mod a, mod dir/file.txt" merging b and a to b merging dir2/file.txt and dir/file.txt to dir2/file.txt saved backup bundle to $TESTTMP/repo/.hg/strip-backup/557f403c0afd-9926eeff-rebase.hg @@ -87,12 +87,12 @@ desc: initial $ hg rebase -s . -d 1 - rebasing 2:d526312210b9 "mode a" (tip) + rebasing 2:d526312210b9 tip "mode a" file 'a' was deleted in local [dest] but was modified in other [source]. You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved. What do you want to do? u unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ cd .. $ rm -rf repo @@ -126,7 +126,7 @@ desc: initial $ hg rebase -s . -d 2 - rebasing 3:9d5cf99c3d9f "mod a" (tip) + rebasing 3:9d5cf99c3d9f tip "mod a" merging b and a to b saved backup bundle to $TESTTMP/repo/.hg/strip-backup/9d5cf99c3d9f-f02358cc-rebase.hg $ cd .. @@ -161,7 +161,7 @@ desc: initial $ hg rebase -s . -d 0 - rebasing 3:fbe97126b396 "mod b" (tip) + rebasing 3:fbe97126b396 tip "mod b" merging a and b to a saved backup bundle to $TESTTMP/repo/.hg/strip-backup/fbe97126b396-cf5452a1-rebase.hg $ cd .. @@ -198,7 +198,7 @@ desc: initial $ hg rebase -s . -d 2 - rebasing 3:6b2f4cece40f "mod dir/a" (tip) + rebasing 3:6b2f4cece40f tip "mod dir/a" merging dir/b and dir/a to dir/b saved backup bundle to $TESTTMP/repo/.hg/strip-backup/6b2f4cece40f-503efe60-rebase.hg $ cd .. @@ -243,13 +243,13 @@ With small limit $ hg rebase -s 2 -d 1 --config experimental.copytrace.movecandidateslimit=0 - rebasing 2:ef716627c70b "mod a" (tip) + rebasing 2:ef716627c70b tip "mod a" skipping copytracing for 'a', more candidates than the limit: 7 file 'a' was deleted in local [dest] but was modified in other [source]. You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved. What do you want to do? u unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --abort rebase aborted @@ -257,7 +257,7 @@ With default limit which is 100 $ hg rebase -s 2 -d 1 - rebasing 2:ef716627c70b "mod a" (tip) + rebasing 2:ef716627c70b tip "mod a" merging foo and a to foo saved backup bundle to $TESTTMP/repo/.hg/strip-backup/ef716627c70b-24681561-rebase.hg @@ -323,7 +323,7 @@ desc: initial $ hg rebase -s . -d 1 - rebasing 2:a33d80b6e352 "mv dir/ dir2/" (tip) + rebasing 2:a33d80b6e352 tip "mv dir/ dir2/" merging dir/a and dir2/a to dir2/a saved backup bundle to $TESTTMP/repo/.hg/strip-backup/a33d80b6e352-fecb9ada-rebase.hg $ cd .. @@ -358,7 +358,7 @@ o rev: 0 desc: initial $ hg rebase -s . -d 2 - rebasing 3:d41316942216 "mod a" (tip) + rebasing 3:d41316942216 tip "mod a" merging c and a to c saved backup bundle to $TESTTMP/repo/.hg/strip-backup/d41316942216-2b5949bc-rebase.hg @@ -431,7 +431,7 @@ desc: initial $ hg rebase -s . -d 2 - rebasing 3:ef716627c70b "mod a" (tip) + rebasing 3:ef716627c70b tip "mod a" merging b and a to b saved backup bundle to $TESTTMP/repo/.hg/strip-backup/ef716627c70b-24681561-rebase.hg $ ls -A @@ -504,7 +504,7 @@ desc: initial $ hg rebase -s . -d 1 - rebasing 2:ef716627c70b "mod a" (tip) + rebasing 2:ef716627c70b tip "mod a" merging b and a to b merging c and a to c saved backup bundle to $TESTTMP/repo/repo/.hg/strip-backup/ef716627c70b-24681561-rebase.hg @@ -631,7 +631,7 @@ desc: initial $ hg rebase -s . -d 1 --config experimental.copytrace.sourcecommitlimit=100 - rebasing 2:6207d2d318e7 "mod a" (tip) + rebasing 2:6207d2d318e7 tip "mod a" merging dir2/b and dir1/a to dir2/b saved backup bundle to $TESTTMP/repo/repo/.hg/strip-backup/6207d2d318e7-1c9779ad-rebase.hg $ cat dir2/b @@ -669,7 +669,7 @@ desc: initial $ hg rebase -s . -d 1 --config experimental.copytrace.sourcecommitlimit=100 - rebasing 2:e8919e7df8d0 "mv dir1 dir2" (tip) + rebasing 2:e8919e7df8d0 tip "mv dir1 dir2" saved backup bundle to $TESTTMP/repo/repo/.hg/strip-backup/e8919e7df8d0-f62fab62-rebase.hg $ ls dir2 a @@ -711,7 +711,7 @@ You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved. What do you want to do? u unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] But when we have "sourcecommitlimit > (no. of drafts from base to c1)", we do fullcopytracing
--- a/tests/test-default-push.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-default-push.t Thu Dec 03 14:15:39 2020 -0500 @@ -18,9 +18,9 @@ Push should provide a hint when both 'default' and 'default-push' not set: $ cd c $ hg push --config paths.default= - abort: default repository not configured! + config error: default repository not configured! (see 'hg help config.paths') - [255] + [30] $ cd .. @@ -75,7 +75,7 @@ Pushing to a path that isn't defined should not fall back to default $ hg --cwd b push doesnotexist - abort: repository doesnotexist does not exist! + abort: repository doesnotexist does not exist [255] :pushurl is used when defined @@ -137,13 +137,13 @@ $ hg --config 'paths.default:pushrev=notdefined()' push pushing to file:/*/$TESTTMP/pushurlsource/../pushurldest (glob) hg: parse error: unknown identifier: notdefined - [255] + [10] $ hg --config 'paths.default:pushrev=(' push pushing to file:/*/$TESTTMP/pushurlsource/../pushurldest (glob) hg: parse error at 1: not a prefix: end (( ^ here) - [255] + [10] $ cd ..
--- a/tests/test-devel-warnings.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-devel-warnings.t Thu Dec 03 14:15:39 2020 -0500 @@ -310,9 +310,9 @@ Test programming error failure: $ hg buggytransaction 2>&1 | egrep -v '^ ' - ** Unknown exception encountered with possibly-broken third-party extension buggylocking + ** Unknown exception encountered with possibly-broken third-party extension "buggylocking" (version N/A) ** which supports versions unknown of Mercurial. - ** Please disable buggylocking and try your action again. + ** Please disable "buggylocking" and try your action again. ** If that fixes the bug please report it to the extension author. ** Python * (glob) ** Mercurial Distributed SCM (*) (glob) @@ -322,9 +322,9 @@ *ProgrammingError: transaction requires locking (glob) $ hg programmingerror 2>&1 | egrep -v '^ ' - ** Unknown exception encountered with possibly-broken third-party extension buggylocking + ** Unknown exception encountered with possibly-broken third-party extension "buggylocking" (version N/A) ** which supports versions unknown of Mercurial. - ** Please disable buggylocking and try your action again. + ** Please disable "buggylocking" and try your action again. ** If that fixes the bug please report it to the extension author. ** Python * (glob) ** Mercurial Distributed SCM (*) (glob)
--- a/tests/test-diffdir.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-diffdir.t Thu Dec 03 14:15:39 2020 -0500 @@ -34,10 +34,10 @@ $ hg diff -r "" hg: parse error: empty query - [255] + [10] $ hg diff -r tip -r "" hg: parse error: empty query - [255] + [10] Remove a file that was added via merge. Since the file is not in parent 1, it should not be in the diff.
--- a/tests/test-directaccess.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-directaccess.t Thu Dec 03 14:15:39 2020 -0500 @@ -40,7 +40,7 @@ Testing with rev number $ hg exp 2 --config experimental.directaccess.revnums=False - abort: hidden revision '2' was rewritten as: 2443a0e66469! + abort: hidden revision '2' was rewritten as: 2443a0e66469 (use --hidden to access hidden revisions) [255] @@ -73,7 +73,7 @@ A c $ hg status --change 2 --config experimental.directaccess.revnums=False - abort: hidden revision '2' was rewritten as: 2443a0e66469! + abort: hidden revision '2' was rewritten as: 2443a0e66469 (use --hidden to access hidden revisions) [255] @@ -195,12 +195,12 @@ Commands with undefined intent should not work right now $ hg phase -r 28ad74 - abort: hidden revision '28ad74' was rewritten as: 2443a0e66469! + abort: hidden revision '28ad74' was rewritten as: 2443a0e66469 (use --hidden to access hidden revisions) [255] $ hg phase -r 2 - abort: hidden revision '2' was rewritten as: 2443a0e66469! + abort: hidden revision '2' was rewritten as: 2443a0e66469 (use --hidden to access hidden revisions) [255]
--- a/tests/test-dirstate-backup.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-dirstate-backup.t Thu Dec 03 14:15:39 2020 -0500 @@ -9,7 +9,7 @@ > EOF applying patch from stdin abort: stdin: no diffs found - [255] + [10] No dirstate backups are left behind
--- a/tests/test-dirstate-nonnormalset.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-dirstate-nonnormalset.t Thu Dec 03 14:15:39 2020 -0500 @@ -1,6 +1,6 @@ $ cat >> $HGRCPATH << EOF - > [ui] - > logtemplate="{rev}:{node|short} ({phase}) [{tags} {bookmarks}] {desc|firstline}\n" + > [command-templates] + > log="{rev}:{node|short} ({phase}) [{tags} {bookmarks}] {desc|firstline}\n" > [extensions] > dirstateparanoidcheck = $TESTDIR/../contrib/dirstatenonnormalcheck.py > [experimental]
--- a/tests/test-dirstate-race.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-dirstate-race.t Thu Dec 03 14:15:39 2020 -0500 @@ -225,7 +225,7 @@ > EOF $ hg rebase -s . -d 3 --tool test - rebasing 4:b08445fd6b2a "c4" (tip) + rebasing 4:b08445fd6b2a tip "c4" merging a custom merge tool custom merge tool end
--- a/tests/test-dispatch.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-dispatch.t Thu Dec 03 14:15:39 2020 -0500 @@ -41,10 +41,10 @@ "--" may be an option value: $ hg -R -- log - abort: repository -- not found! + abort: repository -- not found [255] $ hg log -R -- - abort: repository -- not found! + abort: repository -- not found [255] $ hg log -T -- -- (no-eol) @@ -62,21 +62,21 @@ Unparsable form of early options: $ hg cat --debugg - abort: option --debugger may not be abbreviated! - [255] + abort: option --debugger may not be abbreviated + [10] Parsing failure of early options should be detected before executing the command: $ hg log -b '--config=hooks.pre-log=false' default - abort: option --config may not be abbreviated! - [255] + abort: option --config may not be abbreviated + [10] $ hg log -b -R. default - abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo! - [255] + abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo + [10] $ hg log --cwd .. -b --cwd=. default - abort: option --cwd may not be abbreviated! - [255] + abort: option --cwd may not be abbreviated + [10] However, we can't prevent it from loading extensions and configs: @@ -85,14 +85,14 @@ > EOF $ hg log -b '--config=extensions.bad=bad.py' default *** failed to import extension bad from bad.py: bad - abort: option --config may not be abbreviated! - [255] + abort: option --config may not be abbreviated + [10] $ mkdir -p badrepo/.hg $ echo 'invalid-syntax' > badrepo/.hg/hgrc $ hg log -b -Rbadrepo default - hg: parse error at badrepo/.hg/hgrc:1: invalid-syntax - [255] + config error at badrepo/.hg/hgrc:1: invalid-syntax + [30] $ hg log -b --cwd=inexistent default abort: $ENOENT$: 'inexistent' @@ -113,8 +113,8 @@ [255] $ hg log -b '--config=defaults.log=--config=hooks.pre-log=false' - abort: option --config may not be abbreviated! - [255] + abort: option --config may not be abbreviated + [10] Shell aliases bypass any command parsing rules but for the early one: @@ -126,31 +126,31 @@ #if no-chg $ HGPLAIN=+strictflags hg log -b --config='hooks.pre-log=false' default - abort: unknown revision '--config=hooks.pre-log=false'! + abort: unknown revision '--config=hooks.pre-log=false' [255] $ HGPLAIN=+strictflags hg log -b -R. default - abort: unknown revision '-R.'! + abort: unknown revision '-R.' [255] $ HGPLAIN=+strictflags hg log -b --cwd=. default - abort: unknown revision '--cwd=.'! + abort: unknown revision '--cwd=.' [255] #endif $ HGPLAIN=+strictflags hg log -b --debugger default - abort: unknown revision '--debugger'! + abort: unknown revision '--debugger' [255] $ HGPLAIN=+strictflags hg log -b --config='alias.log=!echo pwned' default - abort: unknown revision '--config=alias.log=!echo pwned'! + abort: unknown revision '--config=alias.log=!echo pwned' [255] $ HGPLAIN=+strictflags hg log --config='hooks.pre-log=false' -b default - abort: option --config may not be abbreviated! - [255] + abort: option --config may not be abbreviated + [10] $ HGPLAIN=+strictflags hg log -q --cwd=.. -b default - abort: option --cwd may not be abbreviated! - [255] + abort: option --cwd may not be abbreviated + [10] $ HGPLAIN=+strictflags hg log -q -R . -b default - abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo! - [255] + abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo + [10] $ HGPLAIN=+strictflags hg --config='hooks.pre-log=false' log -b default abort: pre-log hook exited with status 1 @@ -197,8 +197,8 @@ No repo: $ hg cat - abort: no repository found in '$TESTTMP' (.hg not found)! - [255] + abort: no repository found in '$TESTTMP' (.hg not found) + [10] #endif
--- a/tests/test-doctest.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-doctest.py Thu Dec 03 14:15:39 2020 -0500 @@ -76,7 +76,9 @@ sys.exit(0) files = subprocess.check_output( - "hg files --print0 \"%s\"" % fileset, shell=True, cwd=cwd, + "hg files --print0 \"%s\"" % fileset, + shell=True, + cwd=cwd, ).split(b'\0') if sys.version_info[0] >= 3:
--- a/tests/test-editor-filename.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-editor-filename.t Thu Dec 03 14:15:39 2020 -0500 @@ -17,7 +17,7 @@ $ hg commit *.commit.hg.txt (glob) abort: edit failed: sh exited with status 1 - [255] + [250] Verify that the path for a histedit editor has the expected suffix. @@ -30,7 +30,7 @@ $ hg histedit *.histedit.hg.txt (glob) abort: edit failed: sh exited with status 1 - [255] + [250] Verify that when performing an action that has the side-effect of creating an editor for a diff, the file ends in .diff. @@ -61,4 +61,4 @@ (enter ? for help) [Ynesfdaq?] q abort: user quit - [255] + [250]
--- a/tests/test-eolfilename.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-eolfilename.t Thu Dec 03 14:15:39 2020 -0500 @@ -12,12 +12,12 @@ adding he\r (no-eol) (esc) llo abort: '\n' and '\r' disallowed in filenames: 'he\rllo' - [255] + [10] $ hg ci -A -m m adding he\r (no-eol) (esc) llo abort: '\n' and '\r' disallowed in filenames: 'he\rllo' - [255] + [10] $ rm "$A" $ echo foo > "hell > o" @@ -25,12 +25,12 @@ adding hell o abort: '\n' and '\r' disallowed in filenames: 'hell\no' - [255] + [10] $ hg ci -A -m m adding hell o abort: '\n' and '\r' disallowed in filenames: 'hell\no' - [255] + [10] $ echo foo > "$A" $ hg debugwalk -v * matcher: @@ -48,10 +48,10 @@ $ A=`printf 'quick\rfox'` $ hg cp quickfox "$A" abort: '\n' and '\r' disallowed in filenames: 'quick\rfox' - [255] + [10] $ hg mv quickfox "$A" abort: '\n' and '\r' disallowed in filenames: 'quick\rfox' - [255] + [10] https://bz.mercurial-scm.org/2036
--- a/tests/test-exchange-obsmarkers-case-A3.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-exchange-obsmarkers-case-A3.t Thu Dec 03 14:15:39 2020 -0500 @@ -199,7 +199,7 @@ $ hg push -R main -r 'desc(A1)' pushdest pushing to pushdest searching for changes - abort: push creates new remote head e5ea8f9c7314! + abort: push creates new remote head e5ea8f9c7314 (merge or see 'hg help push' for details about pushing new heads) [255] $ cd ..
--- a/tests/test-export.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-export.t Thu Dec 03 14:15:39 2020 -0500 @@ -337,7 +337,7 @@ hg: parse error at 3: unterminated template expansion (%m{ ^ here) - [255] + [10] $ hg export -o '%\' tip abort: invalid format spec '%\' in output filename [255] @@ -367,13 +367,13 @@ $ hg export "" hg: parse error: empty query - [255] + [10] $ hg export 999 - abort: unknown revision '999'! + abort: unknown revision '999' [255] $ hg export "not all()" abort: export requires at least one changeset - [255] + [10] Check for color output $ cat <<EOF >> $HGRCPATH
--- a/tests/test-extdata.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-extdata.t Thu Dec 03 14:15:39 2020 -0500 @@ -54,7 +54,7 @@ $ hg log -qr "extdata()" hg: parse error: extdata takes at least 1 string argument - [255] + [10] $ hg log -qr "extdata(unknown)" abort: unknown extdata source 'unknown' [255] @@ -73,7 +73,7 @@ hg: parse error at 0: not a prefix: + (+---------------------------------------+ ^ here) - [255] + [10] test template support: @@ -95,17 +95,17 @@ $ hg log -T "{extdata()}\n" hg: parse error: extdata expects one argument - [255] + [10] $ hg log -T "{extdata('unknown')}\n" abort: unknown extdata source 'unknown' [255] $ hg log -T "{extdata(unknown)}\n" hg: parse error: empty data source specified (did you mean extdata('unknown')?) - [255] + [10] $ hg log -T "{extdata('{unknown}')}\n" hg: parse error: empty data source specified - [255] + [10] we don't fix up relative file URLs, but we do run shell commands in repo root @@ -113,7 +113,7 @@ $ cd sub $ hg log -qr "extdata(filedata)" abort: error: $ENOENT$ - [255] + [100] $ hg log -qr "extdata(shelldata)" 2:f6ed99a58333
--- a/tests/test-extension.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-extension.t Thu Dec 03 14:15:39 2020 -0500 @@ -1415,37 +1415,39 @@ No declared supported version, extension complains: $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' - ** Unknown exception encountered with possibly-broken third-party extension throw + ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0 ** which supports versions unknown of Mercurial. - ** Please disable throw and try your action again. + ** Please disable "throw" and try your action again. ** If that fixes the bug please report it to the extension author. ** Python * (glob) ** Mercurial Distributed SCM * (glob) - ** Extensions loaded: throw + ** Extensions loaded: throw 1.0.0 -empty declaration of supported version, extension complains: +empty declaration of supported version, extension complains (but doesn't choke if +the value is improperly a str instead of bytes): $ echo "testedwith = ''" >> throw.py $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' - ** Unknown exception encountered with possibly-broken third-party extension throw + ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0 ** which supports versions unknown of Mercurial. - ** Please disable throw and try your action again. + ** Please disable "throw" and try your action again. ** If that fixes the bug please report it to the extension author. ** Python * (glob) ** Mercurial Distributed SCM (*) (glob) - ** Extensions loaded: throw + ** Extensions loaded: throw 1.0.0 -If the extension specifies a buglink, show that: +If the extension specifies a buglink, show that (but don't choke if the value is +improperly a str instead of bytes): $ echo 'buglink = "http://example.com/bts"' >> throw.py $ rm -f throw.pyc throw.pyo $ rm -Rf __pycache__ $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*' - ** Unknown exception encountered with possibly-broken third-party extension throw + ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0 ** which supports versions unknown of Mercurial. - ** Please disable throw and try your action again. + ** Please disable "throw" and try your action again. ** If that fixes the bug please report it to http://example.com/bts ** Python * (glob) ** Mercurial Distributed SCM (*) (glob) - ** Extensions loaded: throw + ** Extensions loaded: throw 1.0.0 If the extensions declare outdated versions, accuse the older extension first: $ echo "from mercurial import util" >> older.py @@ -1456,13 +1458,13 @@ $ rm -Rf __pycache__ $ hg --config extensions.throw=throw.py --config extensions.older=older.py \ > throw 2>&1 | egrep '^\*\*' - ** Unknown exception encountered with possibly-broken third-party extension older + ** Unknown exception encountered with possibly-broken third-party extension "older" (version N/A) ** which supports versions 1.9 of Mercurial. - ** Please disable older and try your action again. + ** Please disable "older" and try your action again. ** If that fixes the bug please report it to the extension author. ** Python * (glob) ** Mercurial Distributed SCM (version 2.2) - ** Extensions loaded: throw, older + ** Extensions loaded: older, throw 1.0.0 One extension only tested with older, one only with newer versions: $ echo "util.version = lambda:b'2.1'" >> older.py @@ -1470,13 +1472,13 @@ $ rm -Rf __pycache__ $ hg --config extensions.throw=throw.py --config extensions.older=older.py \ > throw 2>&1 | egrep '^\*\*' - ** Unknown exception encountered with possibly-broken third-party extension older + ** Unknown exception encountered with possibly-broken third-party extension "older" (version N/A) ** which supports versions 1.9 of Mercurial. - ** Please disable older and try your action again. + ** Please disable "older" and try your action again. ** If that fixes the bug please report it to the extension author. ** Python * (glob) ** Mercurial Distributed SCM (version 2.1) - ** Extensions loaded: throw, older + ** Extensions loaded: older, throw 1.0.0 Older extension is tested with current version, the other only with newer: $ echo "util.version = lambda:b'1.9.3'" >> older.py @@ -1484,13 +1486,13 @@ $ rm -Rf __pycache__ $ hg --config extensions.throw=throw.py --config extensions.older=older.py \ > throw 2>&1 | egrep '^\*\*' - ** Unknown exception encountered with possibly-broken third-party extension throw + ** Unknown exception encountered with possibly-broken third-party extension "throw" 1.0.0 ** which supports versions 2.1 of Mercurial. - ** Please disable throw and try your action again. + ** Please disable "throw" and try your action again. ** If that fixes the bug please report it to http://example.com/bts ** Python * (glob) ** Mercurial Distributed SCM (version 1.9.3) - ** Extensions loaded: throw, older + ** Extensions loaded: older, throw 1.0.0 Ability to point to a different point $ hg --config extensions.throw=throw.py --config extensions.older=older.py \ @@ -1499,7 +1501,7 @@ ** Your Local Goat Lenders ** Python * (glob) ** Mercurial Distributed SCM (*) (glob) - ** Extensions loaded: throw, older + ** Extensions loaded: older, throw 1.0.0 Declare the version as supporting this hg version, show regular bts link: $ hgver=`hg debuginstall -T '{hgver}'` @@ -1514,7 +1516,7 @@ ** https://mercurial-scm.org/wiki/BugTracker ** Python * (glob) ** Mercurial Distributed SCM (*) (glob) - ** Extensions loaded: throw + ** Extensions loaded: throw 1.0.0 Patch version is ignored during compatibility check $ echo "testedwith = b'3.2'" >> throw.py @@ -1526,7 +1528,7 @@ ** https://mercurial-scm.org/wiki/BugTracker ** Python * (glob) ** Mercurial Distributed SCM (*) (glob) - ** Extensions loaded: throw + ** Extensions loaded: throw 1.0.0 Test version number support in 'hg version': $ echo '__version__ = (1, 2, 3)' >> throw.py
--- a/tests/test-fetch.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-fetch.t Thu Dec 03 14:15:39 2020 -0500 @@ -157,7 +157,7 @@ $ hg --cwd i fetch ../h abort: uncommitted changes - [255] + [20] test fetch with named branches
--- a/tests/test-filecache.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-filecache.py Thu Dec 03 14:15:39 2020 -0500 @@ -5,7 +5,7 @@ import sys if subprocess.call( - ['python', '%s/hghave' % os.environ['TESTDIR'], 'cacheable'] + [sys.executable, '%s/hghave' % os.environ['TESTDIR'], 'cacheable'] ): sys.exit(80)
--- a/tests/test-filelog.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-filelog.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ Tests the behavior of filelog w.r.t. data starting with '\1\n' """
--- a/tests/test-fileset.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-fileset.t Thu Dec 03 14:15:39 2020 -0500 @@ -81,7 +81,7 @@ $ fileset 'a_b' $ fileset '"\xy"' hg: parse error: invalid \x escape* (glob) - [255] + [10] Test invalid syntax @@ -90,25 +90,25 @@ (string 'added') None) hg: parse error: not a symbol - [255] + [10] $ fileset -v '()()' (func (group None) None) hg: parse error: not a symbol - [255] + [10] $ fileset -v -- '-x' (negate (symbol 'x')) hg: parse error: can't use negate operator in this context - [255] + [10] $ fileset -v -- '-()' (negate (group None)) hg: parse error: can't use negate operator in this context - [255] + [10] $ fileset -p parsed 'a, b, c' * parsed: (list @@ -117,23 +117,23 @@ (symbol 'c')) hg: parse error: can't use a list in this context (see 'hg help "filesets.x or y"') - [255] + [10] $ fileset '"path":.' hg: parse error: not a symbol - [255] + [10] $ fileset 'path:foo bar' hg: parse error at 9: invalid token - [255] + [10] $ fileset 'foo:bar:baz' hg: parse error: not a symbol - [255] + [10] $ fileset 'foo:bar()' hg: parse error: pattern must be a string - [255] + [10] $ fileset 'foo:bar' hg: parse error: invalid pattern kind: foo - [255] + [10] Show parsed tree at stages: @@ -562,7 +562,7 @@ c1 $ fileset 'grep("missingparens(")' hg: parse error: invalid match pattern: (unbalanced parenthesis|missing \)).* (re) - [255] + [10] #if execbit $ chmod +x b2 @@ -589,11 +589,11 @@ $ hg add 1k 2k $ fileset 'size("bar")' hg: parse error: couldn't parse size: bar - [255] + [10] $ fileset '(1k, 2k)' hg: parse error: can't use a list in this context (see 'hg help "filesets.x or y"') - [255] + [10] $ fileset 'size(1k)' 1k $ fileset '(1k or 2k) and size("< 2k")' @@ -1018,10 +1018,10 @@ $ fileset "status('', '4', added())" hg: parse error: first argument to status must be a revision - [255] + [10] $ fileset "status('2', '', added())" hg: parse error: second argument to status must be a revision - [255] + [10] Empty revset will error at the revset layer @@ -1029,9 +1029,9 @@ hg: parse error at 1: not a prefix: end ( ^ here) - [255] + [10] $ fileset "status('2', ' ', added())" hg: parse error at 1: not a prefix: end ( ^ here) - [255] + [10]
--- a/tests/test-fix-topology.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-fix-topology.t Thu Dec 03 14:15:39 2020 -0500 @@ -22,6 +22,7 @@ > [extensions] > fix = > strip = + > debugdrawdag=$TESTDIR/drawdag.py > [fix] > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY > uppercase-whole-file:pattern=set:** @@ -366,6 +367,37 @@ XXXX $ cd .. + + $ hg init exclude-obsolete + $ cd exclude-obsolete + $ hg debugdrawdag <<'EOS' + > E C # prune: C + > | | + > D B # prune: B, D + > |/ + > A + > EOS + 1 new orphan changesets + $ hg log --graph --template '{rev} {desc}\n' + * 4 E + | + | x 3 C + | | + x | 2 D + | | + | x 1 B + |/ + o 0 A + + $ hg fix -s A + $ hg fix -s B + abort: no changesets specified + (use --source or --working-dir) + [255] + $ hg fix -s D + $ hg fix -s E + $ cd .. + #endif The --all flag should fix anything that wouldn't cause a problem if you fixed @@ -379,7 +411,7 @@ $ cd fixall $ hg fix --all --working-dir abort: cannot specify both --working-dir and --all - [255] + [10] #if obsstore-on $ printf "one\n" > foo.whole
--- a/tests/test-fix.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-fix.t Thu Dec 03 14:15:39 2020 -0500 @@ -246,15 +246,15 @@ $ hg fix abort: no changesets specified - (use --rev or --working-dir) + (use --source or --working-dir) [255] $ hg fix --whole abort: no changesets specified - (use --rev or --working-dir) + (use --source or --working-dir) [255] $ hg fix --base 0 abort: no changesets specified - (use --rev or --working-dir) + (use --source or --working-dir) [255] Fixing a public revision isn't allowed. It should abort early enough that @@ -266,11 +266,11 @@ $ hg fix -r 0 abort: cannot fix public changesets (see 'hg help phases' for details) - [255] + [10] $ hg fix -r 0 --working-dir abort: cannot fix public changesets (see 'hg help phases' for details) - [255] + [10] $ hg cat -r tip hello.whole hello $ cat hello.whole @@ -865,11 +865,11 @@ $ hg commit -Aqm "foo 2" $ hg --config extensions.rebase= rebase -r 1 -d 0 - rebasing 1:c3b6dc0e177a "foo 2" (tip) + rebasing 1:c3b6dc0e177a tip "foo 2" merging foo.whole warning: conflicts while merging foo.whole! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg --config extensions.rebase= fix --working-dir abort: unresolved conflicts @@ -879,7 +879,7 @@ $ hg --config extensions.rebase= fix -r . abort: rebase in progress (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') - [255] + [20] $ cd .. @@ -1174,7 +1174,7 @@ $ hg commit -m "second" $ hg --config experimental.evolution.allowunstable=False fix -r '.^' abort: cannot fix changeset with children - [255] + [10] $ hg fix -r '.^' 1 new orphan changesets $ hg cat -r 2 foo.whole
--- a/tests/test-flagprocessor.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-flagprocessor.t Thu Dec 03 14:15:39 2020 -0500 @@ -189,7 +189,7 @@ # TEST: ensure a missing processor is handled $ echo '[FAIL][BASE64][GZIP][NOOP]' > fail-base64-gzip-noop $ hg commit -Aqm 'fail+base64+gzip+noop' - abort: missing processor for flag '0x1'! + abort: missing processor for flag '0x1' [255] $ rm fail-base64-gzip-noop @@ -205,7 +205,7 @@ extsetup(ui) File "*/tests/flagprocessorext.py", line *, in extsetup (glob) flagutil.addflagprocessor( (py38 !) - REVIDX_NOOP, (noopdonothingread, noopdonothing, validatehash,) (no-py38 !) + validatehash, (no-py38 !) File "*/mercurial/revlogutils/flagutil.py", line *, in addflagprocessor (glob) insertflagprocessor(flag, processor, flagprocessors) File "*/mercurial/revlogutils/flagutil.py", line *, in insertflagprocessor (glob)
--- a/tests/test-git-interop.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-git-interop.t Thu Dec 03 14:15:39 2020 -0500 @@ -16,6 +16,10 @@ > } + $ hg version -v --config extensions.git= | grep '^[E ]' + Enabled extensions: + git internal (pygit2 *) (glob) + Test auto-loading extension works: $ mkdir nogit $ cd nogit @@ -26,6 +30,7 @@ [255] $ git init Initialized empty Git repository in $TESTTMP/nogit/.git/ + $ git config --global init.defaultBranch master This status invocation shows some hg gunk because we didn't use `hg init --git`, which fixes up .git/info/exclude for us. $ hg status @@ -67,8 +72,8 @@ Without creating the .hg, hg status fails: $ hg status - abort: no repository found in '$TESTTMP/foo' (.hg not found)! - [255] + abort: no repository found in '$TESTTMP/foo' (.hg not found) + [10] But if you run hg init --git, it works: $ hg init --git $ hg id --traceback @@ -304,14 +309,10 @@ $ hg status heads mismatch, rebuilding dagcache M beta - $ git status + $ git status | egrep -v '^$|^ \(use ' On branch master Changes not staged for commit: - (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - modified: beta - no changes added to commit (use "git add" and/or "git commit -a") Contents of each commit should be the same
--- a/tests/test-globalopts.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-globalopts.t Thu Dec 03 14:15:39 2020 -0500 @@ -85,15 +85,15 @@ $ hg ann a/a a/a 0: a $ hg ann a/a b/b - abort: no repository found in '$TESTTMP' (.hg not found)! - [255] + abort: no repository found in '$TESTTMP' (.hg not found) + [10] $ hg -R b ann a/a abort: a/a not under root '$TESTTMP/b' (consider using '--cwd b') [255] $ hg log - abort: no repository found in '$TESTTMP' (.hg not found)! - [255] + abort: no repository found in '$TESTTMP' (.hg not found) + [10] #endif @@ -134,23 +134,23 @@ earlygetopt with illegal abbreviations: $ hg --confi "foo.bar=baz" - abort: option --config may not be abbreviated! - [255] + abort: option --config may not be abbreviated + [10] $ hg --cw a tip - abort: option --cwd may not be abbreviated! - [255] + abort: option --cwd may not be abbreviated + [10] $ hg --rep a tip - abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo! - [255] + abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo + [10] $ hg --repositor a tip - abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo! - [255] + abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo + [10] $ hg -qR a tip - abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo! - [255] + abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo + [10] $ hg -qRa tip - abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo! - [255] + abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo + [10] Testing --cwd:
--- a/tests/test-glog-beautifygraph.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-glog-beautifygraph.t Thu Dec 03 14:15:39 2020 -0500 @@ -1602,9 +1602,9 @@ <fullreposet+ 0:37>, <user 'not-a-user'>>>> $ testlog -b not-a-branch - abort: unknown revision 'not-a-branch'! - abort: unknown revision 'not-a-branch'! - abort: unknown revision 'not-a-branch'! + abort: unknown revision 'not-a-branch' + abort: unknown revision 'not-a-branch' + abort: unknown revision 'not-a-branch' $ testlog -b 35 -b 36 --only-branch branch [] (or @@ -1682,7 +1682,7 @@ <date '2 0 to 4 0'>> $ hg log -G -d 'brace ) in a date' hg: parse error: invalid date: 'brace ) in a date' - [255] + [10] $ testlog --prune 31 --prune 32 [] (not @@ -2534,7 +2534,7 @@ node template with changesetprinter: - $ hg log -Gqr 5:7 --config ui.graphnodetemplate='"{rev}"' + $ hg log -Gqr 5:7 --config command-templates.graphnode='"{rev}"' 7 7:9febbb9c8b2e \xe2\x94\x82 (esc) 6 6:9feeac35a70a @@ -2547,7 +2547,7 @@ node template with changesettemplater (shared cache variable): $ hg log -Gr 5:7 -T '{latesttag % "{rev} {tag}+{distance}"}\n' \ - > --config ui.graphnodetemplate='{ifeq(latesttagdistance, 0, "#", graphnode)}' + > --config command-templates.graphnode='{ifeq(latesttagdistance, 0, "#", graphnode)}' \xe2\x97\x8b 7 foo-bar+1 (esc) \xe2\x94\x82 (esc) # 6 foo-bar+0 @@ -2560,7 +2560,7 @@ label() should just work in node template: $ hg log -Gqr 7 --config extensions.color= --color=debug \ - > --config ui.graphnodetemplate='{label("branch.{branch}", rev)}' + > --config command-templates.graphnode='{label("branch.{branch}", rev)}' [branch.default\xe2\x94\x827] [log.node|7:9febbb9c8b2e] (esc) \xe2\x94\x82 (esc) \xe2\x95\xa7 (esc) @@ -3084,8 +3084,8 @@ $ hg init multiroots $ cd multiroots $ cat <<EOF > .hg/hgrc - > [ui] - > logtemplate = '{rev} {desc}\n\n' + > [command-templates] + > log = '{rev} {desc}\n\n' > EOF $ touch foo
--- a/tests/test-glog-topological.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-glog-topological.t Thu Dec 03 14:15:39 2020 -0500 @@ -1,8 +1,8 @@ This test file aims at test topological iteration and the various configuration it can has. $ cat >> $HGRCPATH << EOF - > [ui] - > logtemplate={rev}\n + > [command-templates] + > log={rev}\n > EOF On this simple example, all topological branch are displayed in turn until we
--- a/tests/test-glog.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-glog.t Thu Dec 03 14:15:39 2020 -0500 @@ -1452,9 +1452,9 @@ <fullreposet+ 0:37>, <user 'not-a-user'>>>> $ testlog -b not-a-branch - abort: unknown revision 'not-a-branch'! - abort: unknown revision 'not-a-branch'! - abort: unknown revision 'not-a-branch'! + abort: unknown revision 'not-a-branch' + abort: unknown revision 'not-a-branch' + abort: unknown revision 'not-a-branch' $ testlog -b 35 -b 36 --only-branch branch [] (or @@ -1532,7 +1532,7 @@ <date '2 0 to 4 0'>> $ hg log -G -d 'brace ) in a date' hg: parse error: invalid date: 'brace ) in a date' - [255] + [10] $ testlog --prune 31 --prune 32 [] (not @@ -2384,6 +2384,18 @@ node template with changesetprinter: + $ hg log -Gqr 5:7 --config command-templates.graphnode='"{rev}"' + 7 7:9febbb9c8b2e + | + 6 6:9feeac35a70a + |\ + | ~ + 5 5:99b31f1c2782 + | + ~ + +node template with changesetprinter (legacy config): + $ hg log -Gqr 5:7 --config ui.graphnodetemplate='"{rev}"' 7 7:9febbb9c8b2e | @@ -2397,7 +2409,7 @@ node template with changesettemplater (shared cache variable): $ hg log -Gr 5:7 -T '{latesttag % "{rev} {tag}+{distance}"}\n' \ - > --config ui.graphnodetemplate='{ifeq(latesttagdistance, 0, "#", graphnode)}' + > --config command-templates.graphnode='{ifeq(latesttagdistance, 0, "#", graphnode)}' o 7 foo-bar+1 | # 6 foo-bar+0 @@ -2410,7 +2422,7 @@ label() should just work in node template: $ hg log -Gqr 7 --config extensions.color= --color=debug \ - > --config ui.graphnodetemplate='{label("branch.{branch}", rev)}' + > --config command-templates.graphnode='{label("branch.{branch}", rev)}' [branch.default|7] [log.node|7:9febbb9c8b2e] | ~ @@ -3420,8 +3432,8 @@ $ hg init multiroots $ cd multiroots $ cat <<EOF > .hg/hgrc - > [ui] - > logtemplate = '{rev} {desc}\n\n' + > [command-templates] + > log = '{rev} {desc}\n\n' > EOF $ touch foo
--- a/tests/test-graft-interrupted.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-graft-interrupted.t Thu Dec 03 14:15:39 2020 -0500 @@ -238,7 +238,7 @@ $ hg graft --stop abort: no interrupted graft found - [255] + [20] $ hg graft -r 3 grafting 3:9150fe93bec6 "added d" @@ -250,17 +250,17 @@ $ hg graft --stop --continue abort: cannot specify both --stop and --continue - [255] + [10] $ hg graft --stop -U abort: cannot specify both --stop and --user - [255] + [10] $ hg graft --stop --rev 4 abort: cannot specify both --stop and --rev - [255] + [10] $ hg graft --stop --log abort: cannot specify both --stop and --log - [255] + [10] $ hg graft --stop stopped the interrupted graft @@ -342,7 +342,7 @@ $ hg abort abort: no interrupted graft to abort (abortflag !) abort: no operation in progress (abortcommand !) - [255] + [20] when stripping is required $ hg graft -r 4 -r 5 @@ -356,19 +356,19 @@ $ hg graft --continue --abort abort: cannot specify both --abort and --continue - [255] + [10] $ hg graft --abort --stop abort: cannot specify both --abort and --stop - [255] + [10] $ hg graft --abort --currentuser abort: cannot specify both --abort and --user - [255] + [10] $ hg graft --abort --edit abort: cannot specify both --abort and --edit - [255] + [10] #if abortcommand when in dry-run mode @@ -554,15 +554,15 @@ $ hg graft 1 --no-commit -e abort: cannot specify both --no-commit and --edit - [255] + [10] $ hg graft 1 --no-commit --log abort: cannot specify both --no-commit and --log - [255] + [10] $ hg graft 1 --no-commit -D abort: cannot specify both --no-commit and --currentdate - [255] + [10] Test --no-commit is working: $ hg graft 1 --no-commit
--- a/tests/test-graft.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-graft.t Thu Dec 03 14:15:39 2020 -0500 @@ -85,14 +85,14 @@ $ hg rm -q e $ hg graft --continue abort: no graft in progress - [255] + [20] $ hg revert -r . -q e Need to specify a rev: $ hg graft abort: no revisions specified - [255] + [10] Can't graft ancestor: @@ -119,10 +119,10 @@ $ hg up -q 0 $ hg graft -U --user foo 2 abort: cannot specify both --user and --currentuser - [255] + [10] $ hg graft -D --date '0 0' 2 abort: cannot specify both --date and --currentdate - [255] + [10] Can't graft with dirty wd: @@ -130,7 +130,7 @@ $ echo foo > a $ hg graft 1 abort: uncommitted changes - [255] + [20] $ hg revert a Graft a rename: @@ -292,7 +292,7 @@ $ hg ci -m 'commit interrupted graft' abort: graft in progress (use 'hg graft --continue' or 'hg graft --stop' to stop) - [255] + [20] Abort the graft and try committing: @@ -324,7 +324,7 @@ $ hg graft -c grafting 4:9c233e8e184d "4" abort: unresolved merge conflicts (see 'hg help resolve') - [255] + [20] Fix up: @@ -337,11 +337,11 @@ $ hg graft -c 6 abort: can't specify --continue and revisions - [255] + [10] $ hg graft -c -r 6 abort: can't specify --continue and revisions - [255] + [10] Continue for real, clobber usernames
--- a/tests/test-grep.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-grep.t Thu Dec 03 14:15:39 2020 -0500 @@ -25,13 +25,13 @@ $ hg log -r 'diffcontains()' hg: parse error: diffcontains takes at least 1 argument - [255] + [10] $ hg log -r 'diffcontains(:)' hg: parse error: diffcontains requires a string pattern - [255] + [10] $ hg log -r 'diffcontains("re:**test**")' hg: parse error: invalid regular expression: nothing to repeat* (glob) - [255] + [10] simple @@ -851,8 +851,8 @@ $ cd follow $ cat <<'EOF' >> .hg/hgrc - > [ui] - > logtemplate = '{rev}: {join(files % "{status} {path}", ", ")}\n' + > [command-templates] + > log = '{rev}: {join(files % "{status} {path}", ", ")}\n' > EOF $ for f in add0 add0-mod1 add0-rm1 add0-mod2 add0-rm2 add0-mod3 add0-mod4 add0-rm4; do @@ -1018,7 +1018,7 @@ $ hg grep --diff -fr'wdir()' data add0-cp4-mod4:2147483647:+:data4 add0-mod4:2147483647:+:data4 - add0-rm4:2147483647:-:abort: add0-rm4@None: not found in manifest! + add0-rm4:2147483647:-:abort: add0-rm4@None: not found in manifest [255] $ hg grep -fr'wdir()' data
--- a/tests/test-help.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-help.t Thu Dec 03 14:15:39 2020 -0500 @@ -380,7 +380,6 @@ relink recreates hardlinks between repository clones schemes extend schemes with shortcuts to repository swarms share share a common history between several working directories - strip strip changesets and their descendants from history transplant command to transplant changesets from another branch win32mbcs allow the use of MBCS paths with problematic encodings zeroconf discover and advertise repositories on the local network @@ -1067,6 +1066,7 @@ debugsidedata dump the side data for a cl/manifest/file revision debugssl test a secure connection to a server + debugstrip strip changesets and all their descendants from the repository debugsub (no help text available) debugsuccessorssets show set of successors for revision @@ -1444,7 +1444,7 @@ - "<DATE" - at or before a given date/time - ">DATE" - on or after a given date/time - "DATE to DATE" - a date range, inclusive - - "-DAYS" - within a given number of days of today + - "-DAYS" - within a given number of days from today Test repeated config section name @@ -3281,7 +3281,7 @@ <li> "<DATE" - at or before a given date/time <li> ">DATE" - on or after a given date/time <li> "DATE to DATE" - a date range, inclusive - <li> "-DAYS" - within a given number of days of today + <li> "-DAYS" - within a given number of days from today </ul> </div>
--- a/tests/test-hgrc.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-hgrc.t Thu Dec 03 14:15:39 2020 -0500 @@ -16,7 +16,7 @@ $ echo "invalid" > $HGRC $ hg version - hg: parse error at $TESTTMP/hgrc:1: invalid + config error at $TESTTMP/hgrc:1: invalid [255] $ echo "" > $HGRC @@ -59,7 +59,7 @@ #if unix-permissions no-root $ chmod u-r $TESTTMP/included $ hg showconfig section - hg: parse error at $TESTTMP/hgrc:2: cannot include $TESTTMP/included (Permission denied) + config error at $TESTTMP/hgrc:2: cannot include $TESTTMP/included (Permission denied) [255] #endif @@ -68,8 +68,7 @@ $ echo '[foo]' > $HGRC $ echo ' x = y' >> $HGRC $ hg version - hg: parse error at $TESTTMP/hgrc:2: x = y - unexpected leading whitespace + config error at $TESTTMP/hgrc:2: unexpected leading whitespace: x = y [255] $ "$PYTHON" -c "from __future__ import print_function; print('[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n')" \ @@ -276,7 +275,7 @@ > EOF $ hg path - hg: parse error at $TESTTMP/.hg/hgrc:3: [broken + config error at $TESTTMP/.hg/hgrc:3: [broken [255] $ HGRCSKIPREPO=1 hg path foo = $TESTTMP/bar @@ -284,7 +283,7 @@ Check that hgweb respect HGRCSKIPREPO=1 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log - hg: parse error at $TESTTMP/.hg/hgrc:3: [broken + config error at $TESTTMP/.hg/hgrc:3: [broken [255] $ test -f hg.pid && (cat hg.pid >> $DAEMON_PIDS) [1] @@ -303,7 +302,7 @@ Check that zeroconf respect HGRCSKIPREPO=1 $ hg paths --config extensions.zeroconf= - hg: parse error at $TESTTMP/.hg/hgrc:3: [broken + config error at $TESTTMP/.hg/hgrc:3: [broken [255] $ HGRCSKIPREPO=1 hg paths --config extensions.zeroconf= foo = $TESTTMP/bar
--- a/tests/test-histedit-arguments.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-histedit-arguments.t Thu Dec 03 14:15:39 2020 -0500 @@ -55,11 +55,11 @@ $ hg histedit --continue abort: no histedit in progress - [255] + [20] $ hg abort abort: no histedit in progress (abortflag !) abort: no operation in progress (abortcommand !) - [255] + [20] Run a dummy edit to make sure we get tip^^ correctly via revsingle. -------------------------------------------------------------------- @@ -126,8 +126,8 @@ --------------------------- $ hg histedit --config "histedit.defaultrev=" - abort: config option histedit.defaultrev can't be empty - [255] + config error: config option histedit.defaultrev can't be empty + [30] Run on a revision not descendants of the initial parent -------------------------------------------------------------------- @@ -151,12 +151,12 @@ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved Editing (08d98a8350f3), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ hg graft --continue abort: no graft in progress (continue: hg histedit --continue) - [255] + [20] $ mv .hg/histedit-state .hg/histedit-state.back $ hg update --quiet --clean 2 @@ -187,7 +187,7 @@ > EOF hg: parse error: missing rules for changeset c8e68270e35a (use "drop c8e68270e35a" to discard, see also: 'hg help -e histedit.config') - [255] + [10] Test that extra revisions are detected --------------------------------------- @@ -199,7 +199,7 @@ > EOF hg: parse error: pick "6058cbb6cfd7" changeset was not a candidate (only use listed changesets) - [255] + [10] Test malformed line --------------------------------------- @@ -210,7 +210,7 @@ > pick 08d98a8350f3 4 five > EOF hg: parse error: malformed line "pickeb57da33312f2three" - [255] + [10] Test unknown changeset --------------------------------------- @@ -221,7 +221,7 @@ > pick 08d98a8350f3 4 five > EOF hg: parse error: unknown changeset 0123456789ab listed - [255] + [10] Test unknown command --------------------------------------- @@ -232,7 +232,7 @@ > pick 08d98a8350f3 4 five > EOF hg: parse error: unknown action "coin" - [255] + [10] Test duplicated changeset --------------------------------------- @@ -245,7 +245,7 @@ > pick 08d98a8350f3 4 five > EOF hg: parse error: duplicated command for changeset eb57da33312f - [255] + [10] Test bogus rev --------------------------------------- @@ -256,7 +256,7 @@ > pick 08d98a8350f3 4 five > EOF hg: parse error: invalid changeset 0u98 - [255] + [10] Test short version of command --------------------------------------- @@ -337,7 +337,7 @@ > EOF Editing (eb57da33312f), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ echo edit >> alpha $ hg histedit -q --continue $ hg log -G -T '{rev}:{node|short} {desc}' @@ -364,7 +364,7 @@ > EOF Editing (8fda0c726bf2), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] Corrupt histedit state file $ sed 's/8fda0c726bf2/123456789012/' .hg/histedit-state > ../corrupt-histedit $ mv ../corrupt-histedit .hg/histedit-state @@ -489,7 +489,7 @@ warning: conflicts while merging foo! (edit, then use 'hg resolve --mark') Fix up the change (pick 8cde254db839) (hg histedit --continue to resume) - [1] + [240] $ hg resolve -m --all (no more unresolved files) continue: hg histedit --continue @@ -498,14 +498,14 @@ warning: conflicts while merging foo! (edit, then use 'hg resolve --mark') Editing (6f2f0241f119), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ hg resolve -m --all (no more unresolved files) continue: hg histedit --continue $ hg commit --amend -m 'reject this fold' abort: histedit in progress (use 'hg histedit --continue' or 'hg histedit --abort') - [255] + [20] With markers enabled, histedit does not get confused, and amend should not be blocked by the ongoing histedit.
--- a/tests/test-histedit-commute.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-histedit-commute.t Thu Dec 03 14:15:39 2020 -0500 @@ -104,6 +104,32 @@ # +colors in the custom template don't show up in the editor + $ HGEDITOR=cat hg histedit 177f92b77385 --color=debug \ + > --config histedit.summary-template='I am rev {label("rev", rev)}' + pick 177f92b77385 I am rev 2 + pick 055a42cdd887 I am rev 3 + pick e860deea161a I am rev 4 + pick 652413bf663e I am rev 5 + + # Edit history between 177f92b77385 and 652413bf663e + # + # Commits are listed from least to most recent + # + # You can reorder changesets by reordering the lines + # + # Commands: + # + # e, edit = use commit, but stop for amending + # m, mess = edit commit message without changing commit content + # p, pick = use commit + # b, base = checkout changeset and apply further changesets from there + # d, drop = remove commit from history + # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description and date + # + + edit the history (use a hacky editor to check histedit-last-edit.txt backup)
--- a/tests/test-histedit-edit.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-histedit-edit.t Thu Dec 03 14:15:39 2020 -0500 @@ -63,7 +63,7 @@ $ hg histedit 177f92b77385 --commands - 2>&1 << EOF > EOF abort: uncommitted changes - [255] + [20] $ echo g > g edit the history @@ -82,7 +82,7 @@ $ hg update tip abort: histedit in progress (use 'hg histedit --continue' or 'hg histedit --abort') - [255] + [20] edit the plan via the editor $ cat >> $TESTTMP/editplan.sh <<EOF @@ -136,7 +136,7 @@ $ hg up 0 abort: histedit in progress (use 'hg histedit --continue' or 'hg histedit --abort') - [255] + [20] Try to delete necessary commit $ hg strip -r 652413b @@ -153,7 +153,7 @@ $ hg --config extensions.mq= qnew please-fail abort: histedit in progress (use 'hg histedit --continue' or 'hg histedit --abort') - [255] + [20] $ HGEDITOR='echo foobaz > ' hg histedit --continue 2>&1 | fixbundle $ hg log --graph @@ -437,7 +437,7 @@ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved Editing (cb9a9f314b8b), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ HGEDITOR=true hg histedit --continue saved backup bundle to $TESTTMP/r0/.hg/strip-backup/cb9a9f314b8b-cc5ccb0b-histedit.hg @@ -463,7 +463,7 @@ $ HGEDITOR="sh ../edit.sh" hg histedit 2 warning: histedit rules saved to: .hg/histedit-last-edit.txt hg: parse error: first changeset cannot use verb "fold" - [255] + [10] $ cat .hg/histedit-last-edit.txt fold 0012be4a27ea 2 extend a
--- a/tests/test-histedit-fold.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-histedit-fold.t Thu Dec 03 14:15:39 2020 -0500 @@ -291,7 +291,7 @@ warning: conflicts while merging file! (edit, then use 'hg resolve --mark') Fix up the change (fold 251d831eeec5) (hg histedit --continue to resume) - [1] + [240] There were conflicts, we keep P1 content. This should effectively drop the changes from +6. @@ -364,7 +364,7 @@ warning: conflicts while merging file! (edit, then use 'hg resolve --mark') Fix up the change (fold 251d831eeec5) (hg histedit --continue to resume) - [1] + [240] $ cat > file << EOF > 1 > 2 @@ -588,7 +588,7 @@ > r 5db65b93a12b > EOF hg: parse error: first changeset cannot use verb "roll" - [255] + [10] $ hg log -G -T '{node|short} {desc}' @ 5db65b93a12b cc |
--- a/tests/test-histedit-merge-tools.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-histedit-merge-tools.t Thu Dec 03 14:15:39 2020 -0500 @@ -12,8 +12,6 @@ > [extensions] > histedit= > mockmakedate = $TESTDIR/mockmakedate.py - > [ui] - > pre-merge-tool-output-template='pre-merge message for {node}\n' > EOF Merge conflict @@ -21,6 +19,11 @@ $ hg init r $ cd r + $ cat >> .hg/hgrc <<EOF + > [command-templates] + > pre-merge-tool-output='pre-merge message for {node}\n' + > EOF + $ echo foo > file $ hg add file $ hg ci -m "First" -d "1 0" @@ -55,3 +58,26 @@ merging file pre-merge message for b90fa2e91a6d11013945a5f684be45b84a8ca6ec 7181f42b8fca: skipping changeset (no changes) + $ hg histedit --abort + abort: no histedit in progress + [20] + $ cd .. + +Test legacy config name + + $ hg init r2 + $ cd r2 + $ echo foo > file + $ hg add file + $ hg ci -m "First" + $ echo bar > file + $ hg ci -m "Second" + $ echo conflict > file + $ hg co -m 0 --config ui.merge=false \ + > --config ui.pre-merge-tool-output-template='legacy config: {node}\n' + merging file + legacy config: 889c9c4d58bd4ce74815efd04a01e0f2bf6765a7 + merging file failed! + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges + [1]
--- a/tests/test-histedit-no-backup.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-histedit-no-backup.t Thu Dec 03 14:15:39 2020 -0500 @@ -52,7 +52,7 @@ merging file Editing (7d5187087c79), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ hg abort 1 files updated, 0 files merged, 0 files removed, 0 files unresolved saved backup bundle to $TESTTMP/foo/.hg/strip-backup/1d8f701c7b35-cf7be322-backup.hg @@ -74,7 +74,7 @@ merging file Editing (7d5187087c79), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ hg abort 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-histedit-no-change.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-histedit-no-change.t Thu Dec 03 14:15:39 2020 -0500 @@ -169,7 +169,7 @@ $ hg up 0 abort: histedit in progress (use 'hg histedit --continue' or 'hg histedit --abort') - [255] + [20] $ mv .hg/histedit-state .hg/histedit-state-ignore $ hg up 0 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
--- a/tests/test-histedit-obsolete.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-histedit-obsolete.t Thu Dec 03 14:15:39 2020 -0500 @@ -45,7 +45,7 @@ $ hg histedit -r 'all()' --commands plan Editing (1b2d564fad96), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ hg st A b A c @@ -72,7 +72,7 @@ $ hg histedit -r 'all()' --commands plan Editing (49d44ab2be1b), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ hg st A b A d @@ -227,7 +227,7 @@ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved Editing (b346ab9a313d), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ echo c >> c $ hg histedit --continue 1 new orphan changesets @@ -293,8 +293,8 @@ ------------------------------------------- $ cat >> $HGRCPATH << EOF - > [ui] - > logtemplate= {rev}:{node|short} ({phase}) {desc|firstline}\n + > [command-templates] + > log = {rev}:{node|short} ({phase}) {desc|firstline}\n > EOF $ hg ph -pv '.^' @@ -309,7 +309,7 @@ $ hg histedit -r '.~2' abort: cannot edit public changesets (see 'hg help phases' for details) - [255] + [10] Prepare further testing @@ -361,7 +361,7 @@ 0 files updated, 0 files merged, 6 files removed, 0 files unresolved Editing (b449568bf7fc), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ echo f >> f $ hg histedit --continue $ hg log -G @@ -403,7 +403,7 @@ 0 files updated, 0 files merged, 6 files removed, 0 files unresolved Editing (b449568bf7fc), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ echo f >> f $ hg histedit --continue $ hg log -G @@ -529,7 +529,7 @@ > EOF Editing (ee118ab9fa44), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] #if abortcommand when in dry-run mode @@ -568,7 +568,7 @@ > EOF Editing (ee118ab9fa44), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ hg histedit --continue --config experimental.evolution.track-operation=1 $ hg log -G @ 23:175d6b286a22 (secret) k
--- a/tests/test-hook.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-hook.t Thu Dec 03 14:15:39 2020 -0500 @@ -1122,8 +1122,8 @@ $ hg id loading pre-identify.npmd hook failed: - abort: No module named repo! (no-py3 !) - abort: No module named 'repo'! (py3 !) + abort: No module named repo (no-py3 !) + abort: No module named 'repo' (py3 !) [255] $ cd ../../b
--- a/tests/test-http-bad-server.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-http-bad-server.t Thu Dec 03 14:15:39 2020 -0500 @@ -41,7 +41,7 @@ $ hg clone http://localhost:$HGPORT/ clone abort: error: (\$ECONNRESET\$|\$EADDRNOTAVAIL\$) (re) - [255] + [100] (The server exits on its own, but there is a race between that and starting a new server. So ensure the process is dead.) @@ -63,7 +63,7 @@ --runs-per-test=20 on macOS 10.12 during the freeze for 4.2. $ hg clone http://localhost:$HGPORT/ clone abort: error: * (glob) - [255] + [100] $ killdaemons.py $DAEMON_PIDS @@ -74,7 +74,7 @@ $ hg clone http://localhost:$HGPORT/ clone abort: error: bad HTTP status line: * (glob) - [255] + [100] $ killdaemons.py $DAEMON_PIDS @@ -90,7 +90,7 @@ $ cat hg.pid > $DAEMON_PIDS $ hg clone http://localhost:$HGPORT/ clone abort: error: bad HTTP status line: * (glob) - [255] + [100] $ killdaemons.py $DAEMON_PIDS @@ -107,7 +107,7 @@ $ cat hg.pid > $DAEMON_PIDS $ hg clone http://localhost:$HGPORT/ clone abort: error: bad HTTP status line: * (glob) - [255] + [100] $ killdaemons.py $DAEMON_PIDS @@ -150,7 +150,7 @@ $ hg clone http://localhost:$HGPORT/ clone requesting all changes abort: error: bad HTTP status line: * (glob) - [255] + [100] $ killdaemons.py $DAEMON_PIDS @@ -217,7 +217,7 @@ $ hg clone http://localhost:$HGPORT/ clone abort: error: bad HTTP status line: * (glob) - [255] + [100] $ killdaemons.py $DAEMON_PIDS @@ -277,7 +277,7 @@ $ hg clone http://localhost:$HGPORT/ clone abort: error: bad HTTP status line: H - [255] + [100] $ killdaemons.py $DAEMON_PIDS @@ -351,7 +351,7 @@ ---%<--- (applicat) ---%<--- - ! + [255] $ killdaemons.py $DAEMON_PIDS @@ -474,7 +474,7 @@ ---%<--- (application/mercuri) ---%<--- - ! + [255] $ killdaemons.py $DAEMON_PIDS
--- a/tests/test-http-bundle1.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-http-bundle1.t Thu Dec 03 14:15:39 2020 -0500 @@ -178,7 +178,7 @@ $ hg clone http://localhost:$HGPORT/bad abort: HTTP Error 404: Not Found - [255] + [100] test http authentication + use the same server to test server side streaming preference @@ -250,7 +250,7 @@ [255] $ hg id http://user:pass2@localhost:$HGPORT2/ abort: HTTP Error 403: no - [255] + [100] $ hg -R dest-pull tag -r tip top $ hg -R dest-pull push http://user:pass@localhost:$HGPORT2/ @@ -338,7 +338,7 @@ updating to branch default cloning subrepo sub from http://localhost:$HGPORT/sub abort: HTTP Error 404: Not Found - [255] + [100] $ hg clone http://localhost:$HGPORT/ slash-clone requesting all changes adding changesets @@ -349,7 +349,7 @@ updating to branch default cloning subrepo sub from http://localhost:$HGPORT/sub abort: HTTP Error 404: Not Found - [255] + [100] check error log @@ -364,7 +364,7 @@ requesting all changes abort: remote error: this is an exercise - [255] + [100] $ cat error.log disable pull-based clones @@ -375,7 +375,7 @@ requesting all changes abort: remote error: server has pull-based clones disabled - [255] + [100] #if no-reposimplestore ... but keep stream clones working
--- a/tests/test-http-clone-r.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-http-clone-r.t Thu Dec 03 14:15:39 2020 -0500 @@ -217,6 +217,6 @@ $ hg clone http://localhost:$HGPORT/ abort: empty destination path is not valid - [255] + [10] $ cat error.log
--- a/tests/test-http-permissions.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-http-permissions.t Thu Dec 03 14:15:39 2020 -0500 @@ -765,7 +765,7 @@ no bookmarks set $ hg bookmark -d bm abort: bookmark 'bm' does not exist - [255] + [10] $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' 405 push requires POST request @@ -806,7 +806,7 @@ no bookmarks set $ hg bookmark -d bm abort: bookmark 'bm' does not exist - [255] + [10] $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' 405 push requires POST request @@ -874,13 +874,13 @@ searching for changes no changes found abort: HTTP Error 403: ssl required - [255] + [100] $ hg --cwd ../test2 push http://localhost:$HGPORT/ pushing to http://localhost:$HGPORT/ searching for changes abort: HTTP Error 403: ssl required - [255] + [100] $ killdaemons.py
--- a/tests/test-http-proxy.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-http-proxy.t Thu Dec 03 14:15:39 2020 -0500 @@ -91,7 +91,7 @@ $ http_proxy=localhost:$HGPORT2 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ f abort: error: (Connection refused|Protocol not supported|.* actively refused it|\$EADDRNOTAVAIL\$|No route to host) (re) - [255] + [100] do not use the proxy if it is in the no list
--- a/tests/test-http.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-http.t Thu Dec 03 14:15:39 2020 -0500 @@ -167,7 +167,7 @@ $ hg clone http://localhost:$HGPORT/bad abort: HTTP Error 404: Not Found - [255] + [100] test http authentication + use the same server to test server side streaming preference @@ -283,7 +283,7 @@ [255] $ hg id http://user:pass2@localhost:$HGPORT2/ abort: HTTP Error 403: no - [255] + [100] $ hg -R dest-pull tag -r tip top $ hg -R dest-pull push http://user:pass@localhost:$HGPORT2/ @@ -475,7 +475,7 @@ updating to branch default cloning subrepo sub from http://localhost:$HGPORT/sub abort: HTTP Error 404: Not Found - [255] + [100] $ hg clone http://localhost:$HGPORT/ slash-clone requesting all changes adding changesets @@ -486,7 +486,7 @@ updating to branch default cloning subrepo sub from http://localhost:$HGPORT/sub abort: HTTP Error 404: Not Found - [255] + [100] check error log @@ -588,7 +588,7 @@ $ hg id http://localhost:$HGPORT abort: HTTP Error 500: no-cookie - [255] + [100] Populate a cookies file @@ -602,7 +602,7 @@ $ hg --config auth.cookiefile=cookies.txt id http://localhost:$HGPORT/ abort: HTTP Error 500: no-cookie - [255] + [100] Add a cookie entry for our test server and verify it is sent @@ -612,4 +612,4 @@ $ hg --config auth.cookiefile=cookies.txt id http://localhost:$HGPORT/ abort: HTTP Error 500: Cookie: hgkey=localhostvalue - [255] + [100]
--- a/tests/test-https.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-https.t Thu Dec 03 14:15:39 2020 -0500 @@ -52,14 +52,14 @@ $ hg clone https://localhost:$HGPORT/ copy-pull (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error) abort: error: *certificate verify failed* (glob) - [255] + [100] #endif #if defaultcacertsloaded $ hg clone https://localhost:$HGPORT/ copy-pull (the full certificate chain may not be available locally; see "hg help debugssl") (windows !) abort: error: *certificate verify failed* (glob) - [255] + [100] #endif Specifying a per-host certificate file that doesn't exist will abort. The full @@ -84,7 +84,7 @@ (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error) (the full certificate chain may not be available locally; see "hg help debugssl") (windows !) abort: error: *certificate verify failed* (glob) - [255] + [100] A per-host certificate matching the server's cert will be accepted @@ -125,7 +125,7 @@ $ hg clone https://localhost:$HGPORT/ copy-pull $DISABLECACERTS abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server) - [255] + [150] $ hg clone --insecure https://localhost:$HGPORT/ copy-pull warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering @@ -160,7 +160,7 @@ pulling from https://localhost:$HGPORT/ abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server) - [255] + [150] $ hg pull --insecure pulling from https://localhost:$HGPORT/ @@ -227,7 +227,7 @@ pulling from https://*:$HGPORT/ (glob) abort: $LOCALIP certificate error: certificate is for localhost (glob) (set hostsecurity.$LOCALIP:certfingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e config setting or use --insecure to connect insecurely) - [255] + [150] $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \ > https://$LOCALIP:$HGPORT/ --insecure pulling from https://*:$HGPORT/ (glob) @@ -238,7 +238,7 @@ pulling from https://localhost:$HGPORT/ (the full certificate chain may not be available locally; see "hg help debugssl") (windows !) abort: error: *certificate verify failed* (glob) - [255] + [100] $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem" \ > --insecure pulling from https://localhost:$HGPORT/ @@ -255,7 +255,7 @@ pulling from https://localhost:$HGPORT1/ (the full certificate chain may not be available locally; see "hg help debugssl") (windows !) abort: error: *certificate verify failed* (glob) - [255] + [100] Test server cert which no longer is valid @@ -266,7 +266,7 @@ pulling from https://localhost:$HGPORT2/ (the full certificate chain may not be available locally; see "hg help debugssl") (windows !) abort: error: *certificate verify failed* (glob) - [255] + [100] Setting ciphers to an invalid value aborts $ P="$CERTSDIR" hg --config hostsecurity.ciphers=invalid -R copy-pull id https://localhost:$HGPORT/ @@ -319,18 +319,18 @@ $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure abort: certificate for localhost has unexpected fingerprint ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03 (check hostfingerprint configuration) - [255] + [150] $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ abort: certificate for localhost has unexpected fingerprint sha1:ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03 (check hostsecurity configuration) - [255] + [150] - fails when cert doesn't match hostname (port is ignored) $ hg -R copy-pull id https://localhost:$HGPORT1/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 abort: certificate for localhost has unexpected fingerprint f4:2f:5a:0c:3e:52:5b:db:e7:24:a8:32:1d:18:97:6d:69:b5:87:84 (check hostfingerprint configuration) - [255] + [150] - ignores that certificate doesn't match hostname @@ -375,26 +375,26 @@ (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) (see https://mercurial-scm.org/wiki/SecureConnections for more info) abort: error: .*(unsupported protocol|wrong ssl version).* (re) - [255] + [100] $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT/ (could not negotiate a common security protocol (tls1.1+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support) (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) (see https://mercurial-scm.org/wiki/SecureConnections for more info) abort: error: .*(unsupported protocol|wrong ssl version).* (re) - [255] + [100] $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT/ (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support) (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) (see https://mercurial-scm.org/wiki/SecureConnections for more info) abort: error: .*(unsupported protocol|wrong ssl version).* (re) - [255] + [100] $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT1/ (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support) (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) (see https://mercurial-scm.org/wiki/SecureConnections for more info) abort: error: .*(unsupported protocol|wrong ssl version).* (re) - [255] + [100] --insecure will allow TLS 1.0 connections and override configs @@ -417,7 +417,7 @@ (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) (see https://mercurial-scm.org/wiki/SecureConnections for more info) abort: error: .*(unsupported protocol|wrong ssl version).* (re) - [255] + [100] .hg/hgrc file [hostsecurity] settings are applied to remote ui instances (issue5305) @@ -430,7 +430,7 @@ (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) (see https://mercurial-scm.org/wiki/SecureConnections for more info) abort: error: .*(unsupported protocol|wrong ssl version).* (re) - [255] + [100] $ killdaemons.py hg0.pid $ killdaemons.py hg1.pid @@ -482,13 +482,13 @@ pulling from https://localhost:$HGPORT/ (the full certificate chain may not be available locally; see "hg help debugssl") (windows !) abort: error: *certificate verify failed* (glob) - [255] + [100] $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \ > --config web.cacerts="$CERTSDIR/pub-expired.pem" https://localhost:$HGPORT2/ pulling from https://localhost:$HGPORT2/ (the full certificate chain may not be available locally; see "hg help debugssl") (windows !) abort: error: *certificate verify failed* (glob) - [255] + [100] $ killdaemons.py hg0.pid @@ -518,7 +518,7 @@ $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ abort: error: .*(\$ECONNRESET\$|certificate required|handshake failure).* (re) - [255] + [100] with client certificate: @@ -539,7 +539,7 @@ $ env P="$CERTSDIR" hg id https://localhost:$HGPORT/ abort: error: * (glob) - [255] + [100] Missing certficate and key files result in error
--- a/tests/test-i18n.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-i18n.t Thu Dec 03 14:15:39 2020 -0500 @@ -8,20 +8,20 @@ using the "replace" error handler: $ LANGUAGE=pt_BR hg tip - abortado: n?o foi encontrado um reposit?rio em '$TESTTMP' (.hg n?o encontrado)! - [255] + abortado: n?o foi encontrado um reposit?rio em '$TESTTMP' (.hg n?o encontrado) + [10] Using a more accommodating encoding: $ HGENCODING=UTF-8 LANGUAGE=pt_BR hg tip - abortado: n\xc3\xa3o foi encontrado um reposit\xc3\xb3rio em '$TESTTMP' (.hg n\xc3\xa3o encontrado)! (esc) - [255] + abortado: n\xc3\xa3o foi encontrado um reposit\xc3\xb3rio em '$TESTTMP' (.hg n\xc3\xa3o encontrado) (esc) + [10] Different encoding: $ HGENCODING=Latin-1 LANGUAGE=pt_BR hg tip - abortado: n\xe3o foi encontrado um reposit\xf3rio em '$TESTTMP' (.hg n\xe3o encontrado)! (esc) - [255] + abortado: n\xe3o foi encontrado um reposit\xf3rio em '$TESTTMP' (.hg n\xe3o encontrado) (esc) + [10] #endif
--- a/tests/test-identify.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-identify.t Thu Dec 03 14:15:39 2020 -0500 @@ -6,7 +6,7 @@ $ hg id abort: there is no Mercurial repository here (.hg not found) - [255] + [10] #endif @@ -115,19 +115,19 @@ $ hg id -n http://localhost:$HGPORT1/ abort: can't query remote revision number, branch, or tags - [255] + [10] remote with tags? $ hg id -t http://localhost:$HGPORT1/ abort: can't query remote revision number, branch, or tags - [255] + [10] remote with branch? $ hg id -b http://localhost:$HGPORT1/ abort: can't query remote revision number, branch, or tags - [255] + [10] test bookmark support @@ -155,21 +155,21 @@ test invalid lookup $ hg id -r noNoNO http://localhost:$HGPORT1/ - abort: unknown revision 'noNoNO'! + abort: unknown revision 'noNoNO' [255] Make sure we do not obscure unknown requires file entries (issue2649) $ echo fake >> .hg/requires $ hg id - abort: repository requires features unknown to this Mercurial: fake! + abort: repository requires features unknown to this Mercurial: fake (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] $ cd .. #if no-outer-repo $ hg id test - abort: repository requires features unknown to this Mercurial: fake! + abort: repository requires features unknown to this Mercurial: fake (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] #endif
--- a/tests/test-import-bypass.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-import-bypass.t Thu Dec 03 14:15:39 2020 -0500 @@ -27,7 +27,7 @@ $ hg import --bypass --exact --edit ../test.diff abort: cannot specify both --exact and --edit - [255] + [10] $ hg import --bypass --exact ../test.diff applying ../test.diff $ shortlog @@ -189,13 +189,13 @@ $ hg import --bypass --no-commit ../test.diff abort: cannot specify both --no-commit and --bypass - [255] + [10] $ hg import --bypass --similarity 50 ../test.diff abort: cannot use --similarity with --bypass - [255] + [10] $ hg import --exact --prefix dir/ ../test.diff abort: cannot specify both --exact and --prefix - [255] + [10] Test commit editor (this also tests that editor is invoked, if the patch doesn't contain @@ -221,7 +221,7 @@ HG: branch 'default' HG: changed a abort: empty commit message - [255] + [10] Test patch.eol is handled (this also tests that editor is not invoked for '--bypass', if the
--- a/tests/test-import.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-import.t Thu Dec 03 14:15:39 2020 -0500 @@ -14,7 +14,7 @@ $ hg --cwd a import abort: need at least one patch to import - [255] + [10] generate patches for the test @@ -127,7 +127,7 @@ HG: branch 'default' HG: changed a abort: empty commit message - [255] + [10] Test avoiding editor invocation at applying the patch with --exact, even if commit message is empty @@ -374,7 +374,7 @@ $ egrep -v '^(Subject|email)' msg.patch | hg --cwd b import - applying patch from stdin abort: empty commit message - [255] + [10] $ rm -r b @@ -445,7 +445,7 @@ $ hg clone -r0 a b -q $ hg --cwd b import --no-commit --secret ../exported-tip.patch abort: cannot specify both --no-commit and --secret - [255] + [10] $ hg --cwd b import --secret ../exported-tip.patch applying ../exported-tip.patch $ hg --cwd b diff -c . --nodates @@ -1036,7 +1036,7 @@ adding a $ hg import -p foo abort: invalid value 'foo' for option -p, expected int - [255] + [10] $ hg import -p0 - << EOF > foobar > --- a Sat Apr 12 22:43:58 2008 -0400 @@ -1172,7 +1172,7 @@ transaction abort! rollback completed abort: empty.patch: no diffs found - [255] + [10] $ hg tip --template '{rev} {desc|firstline}\n' 0 commit $ hg -q status
--- a/tests/test-infinitepush-ci.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-infinitepush-ci.t Thu Dec 03 14:15:39 2020 -0500 @@ -205,7 +205,7 @@ $ hg pull -r b4e4bce660512ad3e71189e14588a70ac8e31fef pulling from $TESTTMP/repo - abort: unknown revision 'b4e4bce660512ad3e71189e14588a70ac8e31fef'! + abort: unknown revision 'b4e4bce660512ad3e71189e14588a70ac8e31fef' [255] $ hg glog o 1:6cb0989601f1 added a @@ -242,7 +242,7 @@ XXX: we should support this $ hg pull -r b4e4bce660512 pulling from ssh://user@dummy/repo - abort: unknown revision 'b4e4bce660512'! + abort: unknown revision 'b4e4bce660512' [255] XXX: we should show better message when the pull is happening from bundlestore @@ -356,7 +356,7 @@ $ hg phase -r . --draft --force $ hg rebase -r 6 -d 3 - rebasing 6:9b42578d4447 "added f" (tip) + rebasing 6:9b42578d4447 tip "added f" $ hg glog @ 7:99949238d9ac added f
--- a/tests/test-init.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-init.t Thu Dec 03 14:15:39 2020 -0500 @@ -32,10 +32,10 @@ test custom revlog chunk cache sizes $ hg --config format.chunkcachesize=0 log -R local -pv - abort: revlog chunk cache size 0 is not greater than 0! + abort: revlog chunk cache size 0 is not greater than 0 [255] $ hg --config format.chunkcachesize=1023 log -R local -pv - abort: revlog chunk cache size 1023 is not a power of 2! + abort: revlog chunk cache size 1023 is not a power of 2 [255] $ hg --config format.chunkcachesize=1024 log -R local -pv changeset: 0:08b9e9f63b32 @@ -103,7 +103,7 @@ test failure $ hg init local - abort: repository local already exists! + abort: repository local already exists [255] init+push to remote2 @@ -148,15 +148,15 @@ init to existing repo $ hg init -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote1 - abort: repository remote1 already exists! - abort: could not create remote repo! + abort: repository remote1 already exists + abort: could not create remote repo [255] clone to existing repo $ hg clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" local ssh://user@dummy/remote1 - abort: repository remote1 already exists! - abort: could not create remote repo! + abort: repository remote1 already exists + abort: could not create remote repo [255] output of dummyssh
--- a/tests/test-journal-exists.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-journal-exists.t Thu Dec 03 14:15:39 2020 -0500 @@ -9,7 +9,7 @@ $ echo foo > a $ hg ci -Am0 - abort: abandoned transaction found! + abort: abandoned transaction found (run 'hg recover' to clean up transaction) [255] @@ -21,7 +21,7 @@ $ touch .hg/store/journal $ hg ci -Am0 - abort: abandoned transaction found! + abort: abandoned transaction found (run 'hg recover' to clean up transaction) [255] $ hg recover --verify @@ -36,7 +36,7 @@ $ touch .hg/store/journal $ hg ci -Am0 - abort: abandoned transaction found! + abort: abandoned transaction found (run 'hg recover' to clean up transaction) [255] $ hg recover --no-verify
--- a/tests/test-keyword.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-keyword.t Thu Dec 03 14:15:39 2020 -0500 @@ -167,7 +167,7 @@ $ hg --debug commit abort: empty commit message - [255] + [10] $ hg status A a A b @@ -816,7 +816,7 @@ $ hg commit abort: empty commit message - [255] + [10] $ hg status M a ? c
--- a/tests/test-largefiles-misc.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-largefiles-misc.t Thu Dec 03 14:15:39 2020 -0500 @@ -23,7 +23,7 @@ > EOF $ hg config extensions - abort: repository requires features unknown to this Mercurial: largefiles! + abort: repository requires features unknown to this Mercurial: largefiles (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] @@ -42,7 +42,7 @@ $ hg config extensions \*\*\* failed to import extension largefiles from missing.py: [Errno *] $ENOENT$: 'missing.py' (glob) - abort: repository requires features unknown to this Mercurial: largefiles! + abort: repository requires features unknown to this Mercurial: largefiles (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] @@ -125,7 +125,7 @@ $ hg clone -q . ../fetch $ hg --config extensions.fetch= fetch ../fetch abort: uncommitted changes - [255] + [20] $ hg up -qC $ cd .. @@ -1009,7 +1009,7 @@ $ hg -R enabledlocally root $TESTTMP/individualenabling/enabledlocally $ hg -R notenabledlocally root - abort: repository requires features unknown to this Mercurial: largefiles! + abort: repository requires features unknown to this Mercurial: largefiles (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] @@ -1026,7 +1026,7 @@ [255] $ hg clone enabledlocally clone-dst - abort: repository requires features unknown to this Mercurial: largefiles! + abort: repository requires features unknown to this Mercurial: largefiles (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] $ test -d clone-dst
--- a/tests/test-largefiles-update.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-largefiles-update.t Thu Dec 03 14:15:39 2020 -0500 @@ -307,7 +307,7 @@ $ hg rebase -s 1 -d 2 --keep rebasing 1:72518492caa6 "#1" - rebasing 4:07d6153b5c04 "#4" (tip) + rebasing 4:07d6153b5c04 tip "#4" $ hg status -A large1 large1: $ENOENT$ @@ -594,7 +594,7 @@ merging normal1 warning: conflicts while merging normal1! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ cat .hglf/large1 58e24f733a964da346e2407a2bee99d9001184f5 $ cat large1 @@ -762,7 +762,7 @@ > hgext.largefiles.lfutil.getlfilestoupdate = getlfilestoupdate > EOF $ hg up -Cr "8" --config extensions.crashupdatelfiles=../crashupdatelfiles.py - [7] + [254] Check large1 content and status ... and that update will undo modifications: $ cat large1 large1 in #3
--- a/tests/test-largefiles-wireproto.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-largefiles-wireproto.t Thu Dec 03 14:15:39 2020 -0500 @@ -117,7 +117,7 @@ This repository uses the largefiles extension. Please enable it in your Mercurial config file. - [255] + [100] used all HGPORTs, kill all daemons $ killdaemons.py @@ -133,7 +133,7 @@ remote: - abort: remote error (check previous remote output) - [255] + [100] #if serve
--- a/tests/test-largefiles.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-largefiles.t Thu Dec 03 14:15:39 2020 -0500 @@ -412,7 +412,7 @@ $ hg revert --quiet z $ hg commit -m "Empty subdir" z abort: z: no match under directory! - [255] + [10] $ rm -rf z $ hg ci -m "standin" .hglf abort: file ".hglf" is a largefile standin @@ -1070,14 +1070,14 @@ Clone URL without path: $ hg clone file:// - abort: repository / not found! + abort: repository / not found [255] Ensure base clone command argument validation $ hg clone -U -u 0 a a-clone-failure abort: cannot specify both --noupdate and --updaterev - [255] + [10] $ hg clone --all-largefiles a ssh://localhost/a abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-legacy-exit-code.t Thu Dec 03 14:15:39 2020 -0500 @@ -0,0 +1,49 @@ +Tests that the exit code is as expected when ui.detailed-exit-code is *not* +enabled. + + $ cat >> $HGRCPATH << EOF + > [ui] + > detailed-exit-code=no + > EOF + + $ hg init + $ echo a > a +Expect exit code 0 on success + $ hg ci -Aqm initial + + $ hg co nonexistent + abort: unknown revision 'nonexistent' + [255] + + $ hg co 'none()' + abort: empty revision set + [255] + + $ hg co 'invalid(' + hg: parse error at 8: not a prefix: end + (invalid( + ^ here) + [255] + + $ hg co 'invalid(' + hg: parse error at 8: not a prefix: end + (invalid( + ^ here) + [255] + + $ hg continue + abort: no operation in progress + [255] + + $ hg st --config a=b + abort: malformed --config option: 'a=b' (use --config section.name=value) + [255] + + $ echo b > a + $ hg ci -m second + $ echo c > a + $ hg ci -m third + $ hg --config extensions.rebase= rebase -r . -d 0 -q + warning: conflicts while merging a! (edit, then use 'hg resolve --mark') + unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') + [1]
--- a/tests/test-lfconvert.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-lfconvert.t Thu Dec 03 14:15:39 2020 -0500 @@ -212,16 +212,16 @@ abort: ssh://localhost/foo is not a local Mercurial repo [255] $ hg lfconvert nosuchrepo foo - abort: repository nosuchrepo not found! + abort: repository nosuchrepo not found [255] $ hg share -q -U bigfile-repo shared $ printf 'bogus' > shared/.hg/sharedpath $ hg lfconvert shared foo - abort: .hg/sharedpath points to nonexistent directory $TESTTMP/bogus! + abort: .hg/sharedpath points to nonexistent directory $TESTTMP/bogus [255] $ hg lfconvert bigfile-repo largefiles-repo initializing destination largefiles-repo - abort: repository largefiles-repo already exists! + abort: repository largefiles-repo already exists [255] add another largefile to the new largefiles repo
--- a/tests/test-lfs-serve-access.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-lfs-serve-access.t Thu Dec 03 14:15:39 2020 -0500 @@ -30,7 +30,7 @@ $ hg -R client push http://localhost:$HGPORT pushing to http://localhost:$HGPORT/ searching for changes - abort: LFS HTTP error: HTTP Error 400: no such method: .git! + abort: LFS HTTP error: HTTP Error 400: no such method: .git (check that lfs serving is enabled on http://localhost:$HGPORT/.git/info/lfs and "upload" is supported) [255] @@ -52,7 +52,7 @@ added 1 changesets with 1 changes to 1 files new changesets 525251863cad updating to branch default - abort: LFS HTTP error: HTTP Error 400: no such method: .git! + abort: LFS HTTP error: HTTP Error 400: no such method: .git (check that lfs serving is enabled on http://localhost:$HGPORT/.git/info/lfs and "download" is supported) [255] @@ -78,14 +78,14 @@ Reasonable hint for a misconfigured blob server $ hg -R httpclone update default --config lfs.url=http://localhost:$HGPORT/missing - abort: LFS HTTP error: HTTP Error 404: Not Found! + abort: LFS HTTP error: HTTP Error 404: Not Found (the "lfs.url" config may be used to override http://localhost:$HGPORT/missing) [255] $ hg -R httpclone update default --config lfs.url=http://localhost:$HGPORT2/missing - abort: LFS error: *onnection *refused*! (glob) (?) - abort: LFS error: $EADDRNOTAVAIL$! (glob) (?) - abort: LFS error: No route to host! (?) + abort: LFS error: *onnection *refused* (glob) (?) + abort: LFS error: $EADDRNOTAVAIL$ (glob) (?) + abort: LFS error: No route to host (?) (the "lfs.url" config may be used to override http://localhost:$HGPORT2/missing) [255] @@ -266,7 +266,7 @@ added 1 changesets with 1 changes to 1 files new changesets 525251863cad updating to branch default - abort: LFS server error for "lfs.bin": Internal server error! + abort: LFS server error for "lfs.bin": Internal server error [255] Test an I/O error in localstore.verify() (Batch API) with PUT @@ -276,7 +276,7 @@ $ hg -R client push http://localhost:$HGPORT1 pushing to http://localhost:$HGPORT1/ searching for changes - abort: LFS server error for "unknown": Internal server error! + abort: LFS server error for "unknown": Internal server error [255] TODO: figure out how to associate the file name in the error above @@ -285,7 +285,7 @@ $ hg -R client push http://localhost:$HGPORT1 pushing to http://localhost:$HGPORT1/ searching for changes - abort: LFS HTTP error: HTTP Error 422: corrupt blob (oid=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, action=upload)! + abort: LFS HTTP error: HTTP Error 422: corrupt blob (oid=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, action=upload) [255] $ echo 'test lfs file' > server/lfs3.bin @@ -297,14 +297,14 @@ $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \ > -R client update -r tip - abort: LFS HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)! + abort: LFS HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download) [255] Test a checksum failure during the processing of the GET request $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \ > -R client update -r tip - abort: LFS HTTP error: HTTP Error 422: corrupt blob (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)! + abort: LFS HTTP error: HTTP Error 422: corrupt blob (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download) [255] $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS @@ -451,7 +451,7 @@ $ hg -R auth_clone push --config extensions.x=use_digests.py pushing to http://localhost:$HGPORT1/ searching for changes - abort: LFS HTTP error: HTTP Error 401: the server must support Basic Authentication! + abort: LFS HTTP error: HTTP Error 401: the server must support Basic Authentication (api=http://localhost:$HGPORT1/.git/info/lfs/objects/batch, action=upload) [255]
--- a/tests/test-lfs-serve.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-lfs-serve.t Thu Dec 03 14:15:39 2020 -0500 @@ -282,7 +282,7 @@ $ hg clone http://localhost:$HGPORT $TESTTMP/client4_clone (remote is using large file support (lfs), but it is explicitly disabled in the local configuration) - abort: repository requires features unknown to this Mercurial: lfs! + abort: repository requires features unknown to this Mercurial: lfs (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] $ grep 'lfs' $TESTTMP/client4_clone/.hg/requires $SERVER_REQUIRES @@ -510,7 +510,7 @@ Misc: process dies early if a requirement exists and the extension is disabled $ hg --config extensions.lfs=! summary - abort: repository requires features unknown to this Mercurial: lfs! + abort: repository requires features unknown to this Mercurial: lfs (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255]
--- a/tests/test-lfs-test-server.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-lfs-test-server.t Thu Dec 03 14:15:39 2020 -0500 @@ -459,7 +459,7 @@ Content-Type: text/plain; charset=utf-8 (git-server !) Date: $HTTP_DATE$ (git-server !) abort: corrupt remote lfs object: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (git-server !) - abort: LFS server error for "c": Validation error! (hg-server !) + abort: LFS server error for "c": Validation error (hg-server !) [255] The corrupted blob is not added to the usercache or local store @@ -826,7 +826,7 @@ ] "transfer": "basic" (hg-server !) } - abort: LFS server error for "b": The object does not exist! + abort: LFS server error for "b": The object does not exist [255] Check error message when object does not exist: @@ -937,7 +937,7 @@ ] "transfer": "basic" (hg-server !) } - abort: LFS server error for "a": The object does not exist! + abort: LFS server error for "a": The object does not exist [255] $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
--- a/tests/test-lfs.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-lfs.t Thu Dec 03 14:15:39 2020 -0500 @@ -22,7 +22,7 @@ > EOF $ hg config extensions - abort: repository requires features unknown to this Mercurial: lfs! + abort: repository requires features unknown to this Mercurial: lfs (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] @@ -41,7 +41,7 @@ $ hg config extensions \*\*\* failed to import extension lfs from missing.py: [Errno *] $ENOENT$: 'missing.py' (glob) - abort: repository requires features unknown to this Mercurial: lfs! + abort: repository requires features unknown to this Mercurial: lfs (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] @@ -70,7 +70,7 @@ $ hg --config lfs.track='"size(\">1000B\")"' commit -Aqm "add small file" hg: parse error: unsupported file pattern: size(">1000B") (paths must be prefixed with "path:") - [255] + [10] $ hg --config lfs.track='size(">1000B")' commit -Aqm "add small file" # Commit large file @@ -985,7 +985,7 @@ Accessing a corrupt file will complain $ hg --cwd fromcorrupt2 cat -r 0 large - abort: integrity check failed on data/large.i:0! + abort: integrity check failed on data/large.i:0 [255] lfs -> normal -> lfs round trip conversions are possible. The 'none()' @@ -1118,8 +1118,8 @@ $ echo x > file.txt $ hg ci -Aqm 'should fail' - hg: parse error at .hglfs:3: bad file ... no commit - [255] + config error at .hglfs:3: bad file ... no commit + [30] $ cat > .hglfs << EOF > [track]
--- a/tests/test-linelog.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-linelog.py Thu Dec 03 14:15:39 2020 -0500 @@ -69,29 +69,60 @@ ll.replacelines(1, 0, 0, 0, 3) self.assertEqual( [(l.rev, l.linenum) for l in ll.annotate(1)], - [(1, 0), (1, 1), (1, 2),], + [ + (1, 0), + (1, 1), + (1, 2), + ], ) # Replace line 1 with a new line ll.replacelines(2, 1, 2, 1, 2) self.assertEqual( [(l.rev, l.linenum) for l in ll.annotate(2)], - [(1, 0), (2, 1), (1, 2),], + [ + (1, 0), + (2, 1), + (1, 2), + ], ) # delete a line out of 2 ll.replacelines(3, 1, 2, 0, 0) self.assertEqual( - [(l.rev, l.linenum) for l in ll.annotate(3)], [(1, 0), (1, 2),] + [(l.rev, l.linenum) for l in ll.annotate(3)], + [ + (1, 0), + (1, 2), + ], ) # annotation of 1 is unchanged self.assertEqual( [(l.rev, l.linenum) for l in ll.annotate(1)], - [(1, 0), (1, 1), (1, 2),], + [ + (1, 0), + (1, 1), + (1, 2), + ], ) ll.annotate(3) # set internal state to revision 3 start = ll.getoffset(0) end = ll.getoffset(1) - self.assertEqual(ll.getalllines(start, end), [(1, 0), (2, 1), (1, 1),]) - self.assertEqual(ll.getalllines(), [(1, 0), (2, 1), (1, 1), (1, 2),]) + self.assertEqual( + ll.getalllines(start, end), + [ + (1, 0), + (2, 1), + (1, 1), + ], + ) + self.assertEqual( + ll.getalllines(), + [ + (1, 0), + (2, 1), + (1, 1), + (1, 2), + ], + ) def testparseclinelogfile(self): # This data is what the replacements in testsimpleedits @@ -116,14 +147,26 @@ llc = linelog.linelog.fromdata(data) self.assertEqual( [(l.rev, l.linenum) for l in llc.annotate(1)], - [(1, 0), (1, 1), (1, 2),], + [ + (1, 0), + (1, 1), + (1, 2), + ], ) self.assertEqual( [(l.rev, l.linenum) for l in llc.annotate(2)], - [(1, 0), (2, 1), (1, 2),], + [ + (1, 0), + (2, 1), + (1, 2), + ], ) self.assertEqual( - [(l.rev, l.linenum) for l in llc.annotate(3)], [(1, 0), (1, 2),] + [(l.rev, l.linenum) for l in llc.annotate(3)], + [ + (1, 0), + (1, 2), + ], ) # Check we emit the same bytecode. ll = linelog.linelog()
--- a/tests/test-lock-badness.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-lock-badness.t Thu Dec 03 14:15:39 2020 -0500 @@ -56,7 +56,7 @@ > EOF $ echo b > b/b $ hg -R b ci -A -m b --config hooks.precommit="python:`pwd`/hooks.py:sleepone" > stdout & - $ hg -R b up -q --config hooks.pre-update="python:`pwd`/hooks.py:sleephalf" \ + $ hg -R b up -q --config ui.timeout.warn=0 --config hooks.pre-update="python:`pwd`/hooks.py:sleephalf" \ > > preup-stdout 2>preup-stderr $ wait $ cat preup-stdout @@ -136,6 +136,6 @@ pushing to a searching for changes abort: could not lock repository a: Permission denied - [255] + [20] $ chmod 700 a/.hg/store
--- a/tests/test-lock.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-lock.py Thu Dec 03 14:15:39 2020 -0500 @@ -73,7 +73,10 @@ self._acquirecalled, called, 'expected acquire to be %s but was actually %s' - % (self._tocalled(called), self._tocalled(self._acquirecalled),), + % ( + self._tocalled(called), + self._tocalled(self._acquirecalled), + ), ) def resetacquirefn(self): @@ -84,7 +87,10 @@ self._releasecalled, called, 'expected release to be %s but was actually %s' - % (self._tocalled(called), self._tocalled(self._releasecalled),), + % ( + self._tocalled(called), + self._tocalled(self._releasecalled), + ), ) def assertpostreleasecalled(self, called): @@ -104,7 +110,10 @@ actual, exists, 'expected lock to %s but actually did %s' - % (self._toexists(exists), self._toexists(actual),), + % ( + self._toexists(exists), + self._toexists(actual), + ), ) def _tocalled(self, called):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-log-bookmark.t Thu Dec 03 14:15:39 2020 -0500 @@ -0,0 +1,127 @@ +Test 'hg log' with a bookmark + + +Create the repository + + $ hg init Test-D8973 + $ cd Test-D8973 + $ echo "bar" > foo.txt + $ hg add foo.txt + $ hg commit -m "Add foo in 'default'" + + +Add a bookmark for topic X + + $ hg branch -f sebhtml + marked working directory as branch sebhtml + (branches are permanent and global, did you want a bookmark?) + + $ hg bookmark sebhtml/99991-topic-X + $ hg up sebhtml/99991-topic-X + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ echo "X" > x.txt + $ hg add x.txt + $ hg commit -m "Add x.txt in 'sebhtml/99991-topic-X'" + + $ hg log -B sebhtml/99991-topic-X + changeset: 1:29f39dea9bf9 + branch: sebhtml + bookmark: sebhtml/99991-topic-X + tag: tip + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: Add x.txt in 'sebhtml/99991-topic-X' + + +Add a bookmark for topic Y + + $ hg update default + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + (leaving bookmark sebhtml/99991-topic-X) + + $ echo "Y" > y.txt + $ hg add y.txt + $ hg branch -f sebhtml + marked working directory as branch sebhtml + $ hg bookmark sebhtml/99992-topic-Y + $ hg up sebhtml/99992-topic-Y + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg commit -m "Add y.txt in 'sebhtml/99992-topic-Y'" + created new head + + $ hg log -B sebhtml/99992-topic-Y + changeset: 2:11df7969cf8d + branch: sebhtml + bookmark: sebhtml/99992-topic-Y + tag: tip + parent: 0:eaea25376a59 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: Add y.txt in 'sebhtml/99992-topic-Y' + + +The log of topic Y does not interfere with the log of topic X + + $ hg log -B sebhtml/99991-topic-X + changeset: 1:29f39dea9bf9 + branch: sebhtml + bookmark: sebhtml/99991-topic-X + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: Add x.txt in 'sebhtml/99991-topic-X' + + +Merge topics Y and X in the default branch + + $ hg update default + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + (leaving bookmark sebhtml/99992-topic-Y) + + $ hg bookmark + sebhtml/99991-topic-X 1:29f39dea9bf9 + sebhtml/99992-topic-Y 2:11df7969cf8d + + $ hg merge sebhtml/99992-topic-Y + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + + $ hg commit -m "Merge branch 'sebhtml/99992-topic-Y' into 'default'" + + $ hg update default + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg merge sebhtml/99991-topic-X + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + + $ hg commit -m "Merge branch 'sebhtml/99991-topic-X' into 'default'" + + +Check the log of topic X, topic Y, and default branch + + $ hg log -B sebhtml/99992-topic-Y + + $ hg log -B sebhtml/99991-topic-X + + $ hg log -b default + changeset: 4:c26ba8c1e1cb + tag: tip + parent: 3:2189f3fb90d6 + parent: 1:29f39dea9bf9 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: Merge branch 'sebhtml/99991-topic-X' into 'default' + + changeset: 3:2189f3fb90d6 + parent: 0:eaea25376a59 + parent: 2:11df7969cf8d + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: Merge branch 'sebhtml/99992-topic-Y' into 'default' + + changeset: 0:eaea25376a59 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: Add foo in 'default' +
--- a/tests/test-log-linerange.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-log-linerange.t Thu Dec 03 14:15:39 2020 -0500 @@ -363,7 +363,7 @@ $ hg log -f -L foo,5:7 -p bar abort: FILE arguments are not compatible with --line-range option - [255] + [10] Option --rev acts as a restriction. @@ -1135,14 +1135,14 @@ $ hg log -L foo,5:7 abort: --line-range requires --follow - [255] + [10] Non-exact pattern kinds are not allowed. $ cd .. $ hg log -f -L glob:*a*,1:2 hg: parse error: line range pattern 'glob:*a*' must match exactly one file - [255] + [10] We get an error for removed files.
--- a/tests/test-log.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-log.t Thu Dec 03 14:15:39 2020 -0500 @@ -4,13 +4,13 @@ $ cd empty $ hg log $ hg log -r 1 - abort: unknown revision '1'! + abort: unknown revision '1' [255] $ hg log -r -1:0 - abort: unknown revision '-1'! + abort: unknown revision '-1' [255] $ hg log -r 'branch(name)' - abort: unknown revision 'name'! + abort: unknown revision 'name' [255] $ hg log -r null -q -1:000000000000 @@ -450,6 +450,16 @@ a +Respects ui.logtemplate and command-templates.log configs (the latter takes +precedence) + + $ hg log -r 0 --config ui.logtemplate="foo {rev}\n" + foo 0 + $ hg log -r 0 --config command-templates.log="bar {rev}\n" + bar 0 + $ hg log -r 0 --config ui.logtemplate="foo {rev}\n" \ + > --config command-templates.log="bar {rev}\n" + bar 0 -f and multiple filelog heads @@ -1053,12 +1063,12 @@ $ hg log -r '' hg: parse error: empty query - [255] + [10] log -r <some unknown node id> $ hg log -r 1000000000000000000000000000000000000000 - abort: unknown revision '1000000000000000000000000000000000000000'! + abort: unknown revision '1000000000000000000000000000000000000000' [255] log -k r1 @@ -1122,8 +1132,8 @@ $ hg init follow-dup $ cd follow-dup $ cat <<EOF >> .hg/hgrc - > [ui] - > logtemplate = '=== {rev}: {desc}\n' + > [command-templates] + > log = '=== {rev}: {desc}\n' > [diff] > nodates = True > EOF @@ -1490,7 +1500,7 @@ log -b dummy $ hg log -b dummy - abort: unknown revision 'dummy'! + abort: unknown revision 'dummy' [255] @@ -1986,7 +1996,7 @@ 1:a765632148dc55d38c35c4f247c618701886cb2f 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05 $ hg log -r a - abort: hidden revision 'a' is pruned! + abort: hidden revision 'a' is pruned (use --hidden to access hidden revisions) [255] @@ -2050,7 +2060,7 @@ 2:94375ec45bddd2a824535fc04855bd058c926ec0 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e $ hg log -T'{rev}:{node}\n' -r:0 - abort: hidden revision '0' is pruned! + abort: hidden revision '0' is pruned (use --hidden to access hidden revisions) [255] $ hg log -T'{rev}:{node}\n' -f @@ -2425,7 +2435,7 @@ hg: parse error at 14: unexpected token: end ({shortest(node} ^ here) - [255] + [10] multi-line template with error $ hg log -r . -T 'line 1 @@ -2435,7 +2445,7 @@ hg: parse error at 27: unexpected token: end (line 1\nline2\n{shortest(node}\nline4\nline5 ^ here) - [255] + [10] $ cd ..
--- a/tests/test-logexchange.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-logexchange.t Thu Dec 03 14:15:39 2020 -0500 @@ -481,15 +481,15 @@ Testing for a literal name which does not exists, which should fail. $ hg log -r 'remotebranches(def)' -GT "{rev}:{node|short} {remotenames}\n" - abort: remote name 'def' does not exist! + abort: remote name 'def' does not exist [255] $ hg log -r 'remotebookmarks("server3")' -GT "{rev}:{node|short} {remotenames}\n" - abort: remote name 'server3' does not exist! + abort: remote name 'server3' does not exist [255] $ hg log -r 'remotenames("server3")' -GT "{rev}:{node|short} {remotenames}\n" - abort: remote name 'server3' does not exist! + abort: remote name 'server3' does not exist [255] Testing for a pattern which does not match anything, which shouldn't fail. @@ -500,15 +500,15 @@ $ hg log -r 'remotenames("re:default", "re:server2")' -GT "{rev}:{node|short} {remotenames}\n" hg: parse error: only one argument accepted - [255] + [10] $ hg log -r 'remotebranches("default/wat", "server2/wat")' -GT "{rev}:{node|short} {remotebranches}\n" hg: parse error: only one argument accepted - [255] + [10] $ hg log -r 'remotebookmarks("default/foo", "server2/foo")' -GT "{rev}:{node|short} {remotebookmarks}\n" hg: parse error: only one argument accepted - [255] + [10] Testing pattern matching
--- a/tests/test-manifest.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-manifest.py Thu Dec 03 14:15:39 2020 -0500 @@ -22,7 +22,12 @@ BIN_HASH_3 = binascii.unhexlify(HASH_3) A_SHORT_MANIFEST = ( b'bar/baz/qux.py\0%(hash2)s%(flag2)s\n' b'foo\0%(hash1)s%(flag1)s\n' -) % {b'hash1': HASH_1, b'flag1': b'', b'hash2': HASH_2, b'flag2': b'l',} +) % { + b'hash1': HASH_1, + b'flag1': b'', + b'hash2': HASH_2, + b'flag2': b'l', +} A_DEEPER_MANIFEST = ( b'a/b/c/bar.py\0%(hash3)s%(flag1)s\n' @@ -265,9 +270,9 @@ self.assertEqual(len(m), len(list(m))) def testMatchesMetadata(self): - '''Tests matches() for a few specific files to make sure that both + """Tests matches() for a few specific files to make sure that both the set of files as well as their flags and nodeids are correct in - the resulting manifest.''' + the resulting manifest.""" m = self.parsemanifest(A_HUGE_MANIFEST) match = matchmod.exact([b'file1', b'file200', b'file300']) @@ -281,9 +286,9 @@ self.assertEqual(w, m2.text()) def testMatchesNonexistentFile(self): - '''Tests matches() for a small set of specific files, including one + """Tests matches() for a small set of specific files, including one nonexistent file to make sure in only matches against existing files. - ''' + """ m = self.parsemanifest(A_DEEPER_MANIFEST) match = matchmod.exact( @@ -296,8 +301,8 @@ ) def testMatchesNonexistentDirectory(self): - '''Tests matches() for a relpath match on a directory that doesn't - actually exist.''' + """Tests matches() for a relpath match on a directory that doesn't + actually exist.""" m = self.parsemanifest(A_DEEPER_MANIFEST) match = matchmod.match( @@ -308,8 +313,7 @@ self.assertEqual([], m2.keys()) def testMatchesExactLarge(self): - '''Tests matches() for files matching a large list of exact files. - ''' + """Tests matches() for files matching a large list of exact files.""" m = self.parsemanifest(A_HUGE_MANIFEST) flist = m.keys()[80:300] @@ -328,8 +332,8 @@ self.assertEqual(m.keys(), m2.keys()) def testMatchesDirectory(self): - '''Tests matches() on a relpath match on a directory, which should - match against all files within said directory.''' + """Tests matches() on a relpath match on a directory, which should + match against all files within said directory.""" m = self.parsemanifest(A_DEEPER_MANIFEST) match = matchmod.match( @@ -353,9 +357,9 @@ ) def testMatchesExactPath(self): - '''Tests matches() on an exact match on a directory, which should + """Tests matches() on an exact match on a directory, which should result in an empty manifest because you can't perform an exact match - against a directory.''' + against a directory.""" m = self.parsemanifest(A_DEEPER_MANIFEST) match = matchmod.exact([b'a/b']) @@ -364,8 +368,8 @@ self.assertEqual([], m2.keys()) def testMatchesCwd(self): - '''Tests matches() on a relpath match with the current directory ('.') - when not in the root directory.''' + """Tests matches() on a relpath match with the current directory ('.') + when not in the root directory.""" m = self.parsemanifest(A_DEEPER_MANIFEST) match = matchmod.match( @@ -389,8 +393,8 @@ ) def testMatchesWithPattern(self): - '''Tests matches() for files matching a pattern that reside - deeper than the specified directory.''' + """Tests matches() for files matching a pattern that reside + deeper than the specified directory.""" m = self.parsemanifest(A_DEEPER_MANIFEST) match = matchmod.match(util.localpath(b'/repo'), b'', [b'a/b/*/*.txt'])
--- a/tests/test-manifest.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-manifest.t Thu Dec 03 14:15:39 2020 -0500 @@ -87,12 +87,12 @@ The next two calls are expected to abort: $ hg manifest -r 2 - abort: unknown revision '2'! + abort: unknown revision '2' [255] $ hg manifest -r tip tip abort: please specify just one revision - [255] + [10] Testing the manifest full text cache utility --------------------------------------------
--- a/tests/test-match.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-match.py Thu Dec 03 14:15:39 2020 -0500 @@ -91,7 +91,9 @@ def testVisitdirRootfilesin(self): m = matchmod.match( - util.localpath(b'/repo'), b'', patterns=[b'rootfilesin:dir/subdir'], + util.localpath(b'/repo'), + b'', + patterns=[b'rootfilesin:dir/subdir'], ) assert isinstance(m, matchmod.patternmatcher) self.assertFalse(m.visitdir(b'dir/subdir/x')) @@ -103,7 +105,9 @@ def testVisitchildrensetRootfilesin(self): m = matchmod.match( - util.localpath(b'/repo'), b'', patterns=[b'rootfilesin:dir/subdir'], + util.localpath(b'/repo'), + b'', + patterns=[b'rootfilesin:dir/subdir'], ) assert isinstance(m, matchmod.patternmatcher) self.assertEqual(m.visitchildrenset(b'dir/subdir/x'), set())
--- a/tests/test-merge-default.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-merge-default.t Thu Dec 03 14:15:39 2020 -0500 @@ -69,7 +69,7 @@ $ hg merge --config commands.merge.require-rev=True abort: configuration requires specifying revision to merge with - [255] + [10] Should succeed - 2 heads: @@ -101,7 +101,7 @@ $ hg merge --config commands.merge.require-rev=True abort: configuration requires specifying revision to merge with - [255] + [10] Should fail because at tip:
--- a/tests/test-merge-halt.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-merge-halt.t Thu Dec 03 14:15:39 2020 -0500 @@ -28,7 +28,7 @@ merging a failed! merging b failed! unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg resolve --list U a @@ -45,7 +45,7 @@ merging b merging a failed! merge halted after failed merge (see hg resolve) - [1] + [240] $ hg resolve --list U a @@ -73,7 +73,7 @@ merging b failed! continue merge operation (yn)? n merge halted after failed merge (see hg resolve) - [1] + [240] $ hg resolve --list U a @@ -102,7 +102,7 @@ merging b failed! continue merge operation (yn)? n merge halted after failed merge (see hg resolve) - [1] + [240] $ hg resolve --list R a @@ -125,7 +125,7 @@ merging b merging a failed! merge halted after failed merge (see hg resolve) - [1] + [240] $ hg resolve --list U a @@ -146,7 +146,7 @@ was merge of 'b' successful (yn)? n merging b failed! merge halted after failed merge (see hg resolve) - [1] + [240] $ hg resolve --list R a
--- a/tests/test-merge-subrepos.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-merge-subrepos.t Thu Dec 03 14:15:39 2020 -0500 @@ -46,7 +46,7 @@ $ hg up --check -r '.^' abort: uncommitted changes - [255] + [20] $ hg st -S ! a $ hg up -Cq .
--- a/tests/test-merge-tools.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-merge-tools.t Thu Dec 03 14:15:39 2020 -0500 @@ -1868,6 +1868,7 @@ $ hg update -q -C 1 $ hg mv f f.txt $ hg ci -qm "f.txt" + warning: commit already existed in the repository! $ hg update -q -C 2 $ hg merge -y -r tip --tool echo \ > --config merge-tools.echo.args='$base $local $other $output' \
--- a/tests/test-merge1.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-merge1.t Thu Dec 03 14:15:39 2020 -0500 @@ -36,7 +36,7 @@ $ hg ci abort: last update was interrupted (use 'hg update' to get a consistent checkout) - [255] + [20] $ hg sum parent: 0:538afb845929 commit #0 @@ -138,8 +138,8 @@ bad config $ hg merge 1 --config merge.checkunknown=x - abort: merge.checkunknown not valid ('x' is none of 'abort', 'ignore', 'warn') - [255] + config error: merge.checkunknown not valid ('x' is none of 'abort', 'ignore', 'warn') + [30] this merge should fail $ hg merge 1 --config merge.checkunknown=abort b: untracked file differs @@ -282,7 +282,7 @@ $ hg merge 2 abort: uncommitted changes (use 'hg status' to list changes) - [255] + [20] merge expected! $ hg merge -f 2 1 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -319,7 +319,7 @@ $ hg merge 2 abort: uncommitted changes (use 'hg status' to list changes) - [255] + [20] merge of b expected $ hg merge -f 2 merging b
--- a/tests/test-merge2.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-merge2.t Thu Dec 03 14:15:39 2020 -0500 @@ -52,6 +52,6 @@ $ hg merge 'wdir()' abort: merging with the working copy has no effect - [255] + [10] $ cd ..
--- a/tests/test-merge4.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-merge4.t Thu Dec 03 14:15:39 2020 -0500 @@ -29,10 +29,10 @@ # Bad usage $ hg log -r 'conflictlocal(foo)' hg: parse error: conflictlocal takes no arguments - [255] + [10] $ hg log -r 'conflictother(foo)' hg: parse error: conflictother takes no arguments - [255] + [10] $ hg co -C . 1 files updated, 0 files merged, 0 files removed, 0 files unresolved # No merge parents when not merging
--- a/tests/test-merge5.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-merge5.t Thu Dec 03 14:15:39 2020 -0500 @@ -16,7 +16,7 @@ $ rm b $ hg update -c 2 abort: uncommitted changes - [255] + [20] $ hg revert b $ hg update -c 2 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-merge9.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-merge9.t Thu Dec 03 14:15:39 2020 -0500 @@ -78,7 +78,7 @@ $ hg resolve abort: no files or directories specified (use --all to re-merge all unresolved files) - [255] + [10] resolve all $ hg resolve -a
--- a/tests/test-missing-capability.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-missing-capability.t Thu Dec 03 14:15:39 2020 -0500 @@ -43,4 +43,4 @@ $ hg pull ssh://user@dummy/repo1 -r tip -B a pulling from ssh://user@dummy/repo1 abort: remote bookmark a not found! - [255] + [10]
--- a/tests/test-mq-qdelete.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-mq-qdelete.t Thu Dec 03 14:15:39 2020 -0500 @@ -114,7 +114,7 @@ now at: pb $ hg qfinish -a pc - abort: unknown revision 'pc'! + abort: unknown revision 'pc' [255] $ hg qpush
--- a/tests/test-mq-qpush-fail.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-mq-qpush-fail.t Thu Dec 03 14:15:39 2020 -0500 @@ -45,7 +45,7 @@ > # Touching files truncated at "transaction.abort" causes > # forcible re-loading invalidated filecache properties > # (including repo.changelog) - > for f, o, _ignore in entries: + > for f, o in entries: > if o or not unlink: > os.utime(opener.join(f), (0.0, 0.0)) > def extsetup(ui):
--- a/tests/test-mq-qrefresh-interactive.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-mq-qrefresh-interactive.t Thu Dec 03 14:15:39 2020 -0500 @@ -125,10 +125,10 @@ $ hg commit -m aaa $ hg qrecord --config ui.interactive=false patch abort: running non-interactively, use qnew instead - [255] + [10] $ hg qnew -i --config ui.interactive=false patch abort: running non-interactively - [255] + [10] $ hg qnew -d '0 0' patch Changing files @@ -179,7 +179,7 @@ $ hg qrefresh -i --config ui.interactive=false abort: running non-interactively - [255] + [10] $ hg qrefresh -i -d '0 0' <<EOF > y > y
--- a/tests/test-mq-qrefresh.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-mq-qrefresh.t Thu Dec 03 14:15:39 2020 -0500 @@ -504,7 +504,7 @@ transaction abort! rollback completed qrefresh interrupted while patch was popped! (revert --all, qpush to recover) - abort: username 'foo\nbar' contains a newline! + abort: username 'foo\nbar' contains a newline [255] $ rm a $ cat .hg/patches/a @@ -520,7 +520,7 @@ transaction abort! rollback completed qrefresh interrupted while patch was popped! (revert --all, qpush to recover) - abort: empty username! + abort: empty username [255] $ cat .hg/patches/a # HG changeset patch
--- a/tests/test-mq.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-mq.t Thu Dec 03 14:15:39 2020 -0500 @@ -171,7 +171,7 @@ guards $ cat .hg/patches/series $ hg qinit -c - abort: repository $TESTTMP/d/.hg/patches already exists! + abort: repository $TESTTMP/d/.hg/patches already exists [255] $ cd .. @@ -253,7 +253,7 @@ init --mq with nonexistent directory $ hg init --mq nonexistentdir - abort: repository nonexistentdir not found! + abort: repository nonexistentdir not found [255] @@ -812,7 +812,7 @@ $ hg add y $ hg strip tip abort: uncommitted changes - [255] + [20] --force strip with local changes
--- a/tests/test-narrow-clone.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-narrow-clone.t Thu Dec 03 14:15:39 2020 -0500 @@ -69,7 +69,7 @@ abort: server does not support narrow clones [255] $ hg tracked -R narrow-via-localpeer - abort: repository narrow-via-localpeer not found! + abort: repository narrow-via-localpeer not found [255] $ rm -Rf narrow-via-localpeer
--- a/tests/test-narrow-copies.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-narrow-copies.t Thu Dec 03 14:15:39 2020 -0500 @@ -70,5 +70,5 @@ $ echo new > inside/f5 $ hg ci -Aqm 'add inside/f5' $ hg --config extensions.rebase= rebase -d 'public()' -r . - rebasing 6:610b60178c28 "add inside/f5" (tip) + rebasing 6:610b60178c28 tip "add inside/f5" saved backup bundle to $TESTTMP/narrow/.hg/strip-backup/610b60178c28-65716a78-rebase.hg
--- a/tests/test-narrow-exchange.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-narrow-exchange.t Thu Dec 03 14:15:39 2020 -0500 @@ -105,8 +105,8 @@ remote: adding file changes remote: transaction abort! remote: rollback completed - remote: abort: data/inside2/f.i@4a1aa07735e6: unknown parent! (reporevlogstore !) - remote: abort: data/inside2/f/index@4a1aa07735e6: no node! (reposimplestore !) + remote: abort: data/inside2/f.i@4a1aa07735e6: unknown parent (reporevlogstore !) + remote: abort: data/inside2/f/index@4a1aa07735e6: no node (reposimplestore !) abort: stream ended unexpectedly (got 0 bytes, expected 4) [255] @@ -221,5 +221,5 @@ remote: error: pretxnchangegroup.lfs hook raised an exception: data/inside2/f.i@f59b4e021835: no match found (lfs-on !) remote: transaction abort! (lfs-on !) remote: rollback completed (lfs-on !) - remote: abort: data/inside2/f.i@f59b4e021835: no match found! (lfs-on !) + remote: abort: data/inside2/f.i@f59b4e021835: no match found (lfs-on !) abort: stream ended unexpectedly (got 0 bytes, expected 4) (lfs-on !)
--- a/tests/test-narrow-rebase.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-narrow-rebase.t Thu Dec 03 14:15:39 2020 -0500 @@ -61,7 +61,7 @@ $ echo modified > inside/f2 $ hg ci -qm 'modify inside/f2' $ hg rebase -d 'desc("modify inside/f1")' - rebasing 5:c2f36d04e05d "modify inside/f2" (tip) + rebasing 5:c2f36d04e05d tip "modify inside/f2" saved backup bundle to $TESTTMP/narrow/.hg/strip-backup/*-rebase.hg (glob) Can rebase onto conflicting changes inside narrow spec @@ -70,14 +70,14 @@ $ echo conflicting > inside/f1 $ hg ci -qm 'conflicting inside/f1' $ hg rebase -d 'desc("modify inside/f1")' 2>&1 | egrep -v '(warning:|incomplete!)' - rebasing 6:cdce97fbf653 "conflicting inside/f1" (tip) + rebasing 6:cdce97fbf653 tip "conflicting inside/f1" merging inside/f1 unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') $ echo modified3 > inside/f1 $ hg resolve -m 2>&1 | grep -v continue: (no more unresolved files) $ hg continue - rebasing 6:cdce97fbf653 "conflicting inside/f1" (tip) + rebasing 6:cdce97fbf653 tip "conflicting inside/f1" saved backup bundle to $TESTTMP/narrow/.hg/strip-backup/*-rebase.hg (glob) Can rebase onto non-conflicting changes outside narrow spec @@ -86,7 +86,7 @@ $ echo modified > inside/f2 $ hg ci -qm 'modify inside/f2' $ hg rebase -d 'desc("modify outside/f1")' - rebasing 7:c2f36d04e05d "modify inside/f2" (tip) + rebasing 7:c2f36d04e05d tip "modify inside/f2" saved backup bundle to $TESTTMP/narrow/.hg/strip-backup/*-rebase.hg (glob) Rebase interrupts on conflicting changes outside narrow spec
--- a/tests/test-narrow-widen-no-ellipsis.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-narrow-widen-no-ellipsis.t Thu Dec 03 14:15:39 2020 -0500 @@ -107,7 +107,7 @@ $ hg tracked --addinclude widest/f --debug comparing with ssh://user@dummy/master - running python "*dummyssh" *user@dummy* *hg -R master serve --stdio* (glob) + running * "*dummyssh" *user@dummy* *hg -R master serve --stdio* (glob) sending hello command sending between command remote: * (glob)
--- a/tests/test-newbranch.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-newbranch.t Thu Dec 03 14:15:39 2020 -0500 @@ -32,7 +32,7 @@ $ hg branch default abort: a branch of the same name already exists (use 'hg update' to switch to it) - [255] + [10] $ hg branch -f default marked working directory as branch default @@ -61,7 +61,7 @@ $ hg branch bar abort: a branch of the same name already exists (use 'hg update' to switch to it) - [255] + [10] $ hg branch -f bar marked working directory as branch bar @@ -84,7 +84,7 @@ $ hg branch bar abort: a branch of the same name already exists (use 'hg update' to switch to it) - [255] + [10] set (other) parent branch as branch name
--- a/tests/test-obshistory.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-obshistory.t Thu Dec 03 14:15:39 2020 -0500 @@ -51,7 +51,7 @@ Actual test ----------- $ hg update 471f378eab4c - abort: hidden revision '471f378eab4c' was rewritten as: 4ae3a4151de9! + abort: hidden revision '471f378eab4c' was rewritten as: 4ae3a4151de9 (use --hidden to access hidden revisions) [255] $ hg update --hidden "desc(A0)" @@ -115,7 +115,7 @@ $ hg up 1 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg up 0dec01379d3b - abort: hidden revision '0dec01379d3b' is pruned! + abort: hidden revision '0dec01379d3b' is pruned (use --hidden to access hidden revisions) [255] $ hg up --hidden -r 'desc(B0)' @@ -193,7 +193,7 @@ Actual test ----------- $ hg update 471597cad322 - abort: hidden revision '471597cad322' was split as: 337fec4d2edc, f257fde29c7a! + abort: hidden revision '471597cad322' was split as: 337fec4d2edc, f257fde29c7a (use --hidden to access hidden revisions) [255] $ hg update --hidden 'min(desc(A0))' @@ -293,7 +293,7 @@ Actual test ----------- $ hg update de7290d8b885 - abort: hidden revision 'de7290d8b885' was split as: 337fec4d2edc, f257fde29c7a and 2 more! + abort: hidden revision 'de7290d8b885' was split as: 337fec4d2edc, f257fde29c7a and 2 more (use --hidden to access hidden revisions) [255] $ hg update --hidden 'min(desc(A0))' @@ -374,7 +374,7 @@ Actual test ----------- $ hg update 471f378eab4c - abort: hidden revision '471f378eab4c' was rewritten as: eb5a0daa2192! + abort: hidden revision '471f378eab4c' was rewritten as: eb5a0daa2192 (use --hidden to access hidden revisions) [255] $ hg update --hidden 'desc(A0)' @@ -382,7 +382,7 @@ updated to hidden changeset 471f378eab4c (hidden revision '471f378eab4c' was rewritten as: eb5a0daa2192) $ hg update 0dec01379d3b - abort: hidden revision '0dec01379d3b' was rewritten as: eb5a0daa2192! + abort: hidden revision '0dec01379d3b' was rewritten as: eb5a0daa2192 (use --hidden to access hidden revisions) [255] $ hg update --hidden 'desc(B0)' @@ -457,7 +457,7 @@ Actual test ----------- $ hg update 471f378eab4c - abort: hidden revision '471f378eab4c' has diverged! + abort: hidden revision '471f378eab4c' has diverged (use --hidden to access hidden revisions) [255] $ hg update --hidden 'desc(A0)' @@ -554,7 +554,7 @@ Actual test ----------- $ hg update 471f378eab4c - abort: hidden revision '471f378eab4c' was rewritten as: eb5a0daa2192! + abort: hidden revision '471f378eab4c' was rewritten as: eb5a0daa2192 (use --hidden to access hidden revisions) [255] $ hg update --hidden 'desc(A0)'
--- a/tests/test-obsmarker-template.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-obsmarker-template.t Thu Dec 03 14:15:39 2020 -0500 @@ -122,7 +122,7 @@ o ea207398892e - $ hg log -G --config ui.logtemplate= + $ hg log -G --config command-templates.log= o changeset: 3:d004c8f274b9 | tag: tip | parent: 0:ea207398892e
--- a/tests/test-obsmarkers-effectflag.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-obsmarkers-effectflag.t Thu Dec 03 14:15:39 2020 -0500 @@ -76,7 +76,7 @@ $ mkcommit C0 $ mkcommit D0 $ hg rebase -r . -d 'desc(B0)' - rebasing 10:c85eff83a034 "D0" (tip) + rebasing 10:c85eff83a034 tip "D0" check result
--- a/tests/test-obsolete-bundle-strip.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-obsolete-bundle-strip.t Thu Dec 03 14:15:39 2020 -0500 @@ -9,9 +9,9 @@ ------------ $ cat >> $HGRCPATH <<EOF - > [ui] + > [command-templates] > # simpler log output - > logtemplate = "{node|short}: {desc}\n" + > log = "{node|short}: {desc}\n" > > [experimental] > # enable evolution
--- a/tests/test-obsolete-checkheads.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-obsolete-checkheads.t Thu Dec 03 14:15:39 2020 -0500 @@ -3,8 +3,8 @@ > [phases] > # public changeset are not obsolete > publish=false - > [ui] - > logtemplate='{node|short} ({phase}) {desc|firstline}\n' + > [command-templates] + > log='{node|short} ({phase}) {desc|firstline}\n' > [experimental] > evolution.createmarkers=True > EOF @@ -95,7 +95,7 @@ $ hg push pushing to $TESTTMP/remote searching for changes - abort: push creates new remote head 71e3228bffe1! + abort: push creates new remote head 71e3228bffe1 (merge or see 'hg help push' for details about pushing new heads) [255] @@ -155,7 +155,7 @@ $ hg push -r 'desc("other")' pushing to $TESTTMP/remote searching for changes - abort: push creates new remote head d7d41ccbd4de! + abort: push creates new remote head d7d41ccbd4de (merge or see 'hg help push' for details about pushing new heads) [255] @@ -267,7 +267,7 @@ pushing to $TESTTMP/remote searching for changes remote has heads on branch 'default' that are not known locally: c70b08862e08 - abort: push creates new remote head 71e3228bffe1! + abort: push creates new remote head 71e3228bffe1 (pull and merge or see 'hg help push' for details about pushing new heads) [255] @@ -317,6 +317,6 @@ $ hg push pushing to $TESTTMP/remote searching for changes - abort: push creates new remote head 350a93b716be! + abort: push creates new remote head 350a93b716be (merge or see 'hg help push' for details about pushing new heads) [255]
--- a/tests/test-obsolete-distributed.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-obsolete-distributed.t Thu Dec 03 14:15:39 2020 -0500 @@ -16,8 +16,8 @@ > evolution = all > [phases] > publish = False - > [ui] - > logtemplate= {rev}:{node|short} {desc}{if(obsfate, " [{join(obsfate, "; ")}]")}\n + > [command-templates] + > log = {rev}:{node|short} {desc}{if(obsfate, " [{join(obsfate, "; ")}]")}\n > EOF Check distributed chain building @@ -544,7 +544,7 @@ adding file changes added 2 changesets with 0 changes to 2 files (+1 heads) (2 other changesets obsolete on arrival) - abort: cannot update to target: filtered revision '6'! + abort: cannot update to target: filtered revision '6' [255] $ cd ..
--- a/tests/test-obsolete.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-obsolete.t Thu Dec 03 14:15:39 2020 -0500 @@ -47,10 +47,10 @@ $ hg debugobsolete 0 abort: changeset references must be full hexadecimal node identifiers - [255] + [10] $ hg debugobsolete '00' abort: changeset references must be full hexadecimal node identifiers - [255] + [10] $ hg debugobsolete -d '0 0' `getid kill_me` -u babar 1 new obsolescence markers obsoleted 1 changesets @@ -200,10 +200,10 @@ $ hg tip 5:5601fb93a350 (draft) [tip ] add new_3_c $ hg log -r 6 - abort: unknown revision '6'! + abort: unknown revision '6' [255] $ hg log -r 4 - abort: hidden revision '4' was rewritten as: 5601fb93a350! + abort: hidden revision '4' was rewritten as: 5601fb93a350 (use --hidden to access hidden revisions) [255] $ hg debugrevspec 'rev(6)' @@ -1541,7 +1541,7 @@ 4:13bedc178fce (draft *obsolete*) [ bookb] add b [rewritten using amend as 5:a9b1f8652753] $ hg book -d bookb $ hg log -r 13bedc178fce - abort: hidden revision '13bedc178fce' was rewritten as: a9b1f8652753! + abort: hidden revision '13bedc178fce' was rewritten as: a9b1f8652753 (use --hidden to access hidden revisions) [255]
--- a/tests/test-parents.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-parents.t Thu Dec 03 14:15:39 2020 -0500 @@ -53,8 +53,8 @@ $ hg parents -r 3 c - abort: 'c' not found in manifest! - [255] + abort: 'c' not found in manifest + [10] $ hg parents -r 2 changeset: 1:d786049f033a @@ -95,7 +95,7 @@ $ hg parents -r 2 glob:a abort: can only specify an explicit filename - [255] + [10] merge working dir with 2 parents, hg parents c
--- a/tests/test-parse-date.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-parse-date.t Thu Dec 03 14:15:39 2020 -0500 @@ -18,13 +18,13 @@ $ echo "fail" >> a $ hg ci -d "should fail" -m "fail" hg: parse error: invalid date: 'should fail' - [255] + [10] $ hg ci -d "100000000000000000 1400" -m "fail" hg: parse error: date exceeds 32 bits: 100000000000000000 - [255] + [10] $ hg ci -d "100000 1400000" -m "fail" hg: parse error: impossible time zone offset: 1400000 - [255] + [10] Check with local timezone other than GMT and with DST
--- a/tests/test-parseindex2.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-parseindex2.py Thu Dec 03 14:15:39 2020 -0500 @@ -5,6 +5,7 @@ from __future__ import absolute_import, print_function +import os import struct import subprocess import sys @@ -129,7 +130,7 @@ "import sys; sys.hexversion=%s; " "import mercurial.cext.parsers" % hexversion ) - cmd = "python -c \"%s\"" % code + cmd = "\"%s\" -c \"%s\"" % (os.environ['PYTHON'], code) # We need to do these tests inside a subprocess because parser.c's # version-checking code happens inside the module init function, and # when using reload() to reimport an extension module, "The init function
--- a/tests/test-patchbomb-tls.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-patchbomb-tls.t Thu Dec 03 14:15:39 2020 -0500 @@ -73,7 +73,7 @@ (verifying remote certificate) abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server) - [255] + [150] With global certificates:
--- a/tests/test-patchbomb.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-patchbomb.t Thu Dec 03 14:15:39 2020 -0500 @@ -3100,7 +3100,7 @@ $ echo 'publicurl=$TESTTMP/missing' >> $HGRCPATH $ hg email --date '1980-1-1 0:1' -t foo -s test -r '10' unable to access public repo: $TESTTMP/missing - abort: repository $TESTTMP/missing not found! + abort: repository $TESTTMP/missing not found [255] node missing at public
--- a/tests/test-pathconflicts-update.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-pathconflicts-update.t Thu Dec 03 14:15:39 2020 -0500 @@ -129,7 +129,7 @@ R base $ hg up --check dir abort: uncommitted changes - [255] + [20] $ hg up dir a: path conflict - a file or link has the same name as a directory the local file has been renamed to a~d20a80d4def3 @@ -154,7 +154,7 @@ $ echo 9 > a/b/c $ hg up file2 --check --config merge.checkunknown=warn abort: uncommitted changes - [255] + [20] $ hg up file2 --clean 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (activating bookmark file2)
--- a/tests/test-pathencode.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-pathencode.py Thu Dec 03 14:15:39 2020 -0500 @@ -54,8 +54,8 @@ def buildprobtable(fp, cmd='hg manifest tip'): - '''Construct and print a table of probabilities for path name - components. The numbers are percentages.''' + """Construct and print a table of probabilities for path name + components. The numbers are percentages.""" counts = collections.defaultdict(lambda: 0) for line in os.popen(cmd).read().splitlines():
--- a/tests/test-persistent-nodemap.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-persistent-nodemap.t Thu Dec 03 14:15:39 2020 -0500 @@ -15,6 +15,7 @@ fncache: yes dotencode: yes generaldelta: yes + exp-sharesafe: no sparserevlog: yes sidedata: no persistent-nodemap: yes @@ -476,6 +477,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no no no persistent-nodemap: yes no no @@ -506,6 +508,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no no no persistent-nodemap: no yes no
--- a/tests/test-phabricator.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-phabricator.t Thu Dec 03 14:15:39 2020 -0500 @@ -101,7 +101,7 @@ $ hg ci --addremove -m 'create alpha for phabricator test €' adding alpha $ hg phabsend -r . --test-vcr "$VCR/phabsend-create-alpha.json" - D7915 - created - d386117f30e6: create alpha for phabricator test \xe2\x82\xac (esc) + D7915 - created - 0:d386117f30e6 tip "create alpha for phabricator test \xe2\x82\xac" (esc) new commits: ['347bf67801e5'] saved backup bundle to $TESTTMP/repo/.hg/strip-backup/d386117f30e6-24ffe649-phabsend.hg $ echo more >> alpha @@ -112,8 +112,8 @@ adding beta $ hg phabsend -r ".^::" --test-vcr "$VCR/phabsend-update-alpha-create-beta.json" c44b38f24a45 mapped to old nodes [] - D7915 - updated - c44b38f24a45: create alpha for phabricator test \xe2\x82\xac (esc) - D7916 - created - 9e6901f21d5b: create beta for phabricator test + D7915 - updated - 0:c44b38f24a45 "create alpha for phabricator test \xe2\x82\xac" (esc) + D7916 - created - 1:9e6901f21d5b tip "create beta for phabricator test" new commits: ['a692622e6937'] saved backup bundle to $TESTTMP/repo/.hg/strip-backup/9e6901f21d5b-1fcd4f0e-phabsend.hg $ unset HGENCODING @@ -127,8 +127,8 @@ $ echo 'draft change' > alpha $ hg ci -m 'create draft change for phabricator testing' $ hg phabsend --amend -r '.^::' --test-vcr "$VCR/phabsend-create-public.json" - D7917 - created - 7b4185ab5d16: create public change for phabricator testing - D7918 - created - 251c1c333fc6: create draft change for phabricator testing + D7917 - created - 2:7b4185ab5d16 "create public change for phabricator testing" + D7918 - created - 3:251c1c333fc6 tip "create draft change for phabricator testing" warning: not updating public commit 2:7b4185ab5d16 new commits: ['3244dc4a3334'] saved backup bundle to $TESTTMP/repo/.hg/strip-backup/251c1c333fc6-41cb7c3b-phabsend.hg @@ -175,7 +175,7 @@ $ hg ci --addremove -m "create comment for phabricator test" adding comment $ hg phabsend -r . -m "For default branch" --test-vcr "$VCR/phabsend-comment-created.json" - D7919 - created - d5dddca9023d: create comment for phabricator test + D7919 - created - 4:d5dddca9023d tip "create comment for phabricator test" new commits: ['f7db812bbe1d'] saved backup bundle to $TESTTMP/repo/.hg/strip-backup/d5dddca9023d-adf673ba-phabsend.hg $ echo comment2 >> comment @@ -183,12 +183,12 @@ saved backup bundle to $TESTTMP/repo/.hg/strip-backup/f7db812bbe1d-8fcded77-amend.hg $ hg phabsend -r . -m "Address review comments" --test-vcr "$VCR/phabsend-comment-updated.json" 1849d7828727 mapped to old nodes [] - D7919 - updated - 1849d7828727: create comment for phabricator test + D7919 - updated - 4:1849d7828727 tip "create comment for phabricator test" Phabsending a skipped commit: $ hg phabsend --no-amend -r . --test-vcr "$VCR/phabsend-skipped.json" 1849d7828727 mapped to old nodes ['1849d7828727'] - D7919 - skipped - 1849d7828727: create comment for phabricator test + D7919 - skipped - 4:1849d7828727 tip "create comment for phabricator test" Phabsend doesn't create an instability when restacking existing revisions on top of new revisions. @@ -210,7 +210,7 @@ $ echo "mod2" > file1.txt $ hg ci -m 'modified 2' $ hg phabsend -r . --test-vcr "$VCR/phabsend-add-parent-setup.json" - D8433 - created - 5d3959e20d1d: modified 2 + D8433 - created - 2:5d3959e20d1d tip "modified 2" new commits: ['2b4aa8a88d61'] $ hg log -G -T compact @ 3[tip]:1 2b4aa8a88d61 1970-01-01 00:00 +0000 test @@ -231,8 +231,8 @@ $ hg up -q 3 $ hg phabsend -r ".^ + ." --test-vcr "$VCR/phabsend-add-parent.json" 2b4aa8a88d61 mapped to old nodes ['2b4aa8a88d61'] - D8434 - created - d549263bcb2d: modified 1 - D8433 - updated - 2b4aa8a88d61: modified 2 + D8434 - created - 1:d549263bcb2d "modified 1" + D8433 - updated - 3:2b4aa8a88d61 "modified 2" new commits: ['876a60d024de'] new commits: ['0c6523cb1d0f'] restabilizing 1eda4bf55021 as d2c78c3a3e01 @@ -313,9 +313,9 @@ $ hg phabsend -r 5::tip --test-vcr "$VCR/phabsend-no-restack-orphan.json" 876a60d024de mapped to old nodes ['876a60d024de'] 0c6523cb1d0f mapped to old nodes ['0c6523cb1d0f'] - D8434 - updated - 876a60d024de: modified 1 - D8433 - updated - 0c6523cb1d0f: modified 2 - D8435 - created - 082be6c94150: modified A + D8434 - updated - 5:876a60d024de "modified 1" + D8433 - updated - 6:0c6523cb1d0f "modified 2" + D8435 - created - 10:082be6c94150 tip "modified A" new commits: ['b5913193c805'] not restabilizing unchanged d2c78c3a3e01 $ hg log -G @@ -374,10 +374,10 @@ $ hg ci -m 'remove binary' $ hg phabsend -r .~2:: --test-vcr "$VCR/phabsend-binary.json" uploading bin@aa24a81f55de - D8007 - created - aa24a81f55de: add binary + D8007 - created - 5:aa24a81f55de "add binary" uploading bin@d8d62a881b54 - D8008 - created - d8d62a881b54: modify binary - D8009 - created - af55645b2e29: remove binary + D8008 - created - 6:d8d62a881b54 "modify binary" + D8009 - created - 7:af55645b2e29 tip "remove binary" new commits: ['b8139fbb4a57'] new commits: ['c88ce4c2d2ad'] new commits: ['75dbbc901145'] @@ -421,14 +421,14 @@ $ hg phabsend -r .~4:: --test-vcr "$VCR/phabsend-binary-renames.json" uploading bin2@f42f9195e00c - D8128 - created - f42f9195e00c: add another binary - D8129 - created - 834ab31d80ae: moved binary - D8130 - created - 494b750e5194: copied binary + D8128 - created - 8:f42f9195e00c "add another binary" + D8129 - created - 9:834ab31d80ae "moved binary" + D8130 - created - 10:494b750e5194 "copied binary" uploading bin2_moved_again@25f766b50cc2 - D8131 - created - 25f766b50cc2: move+mod copied binary + D8131 - created - 11:25f766b50cc2 "move+mod copied binary" uploading bin2_moved_copied@1b87b363a5e4 uploading bin2_moved@1b87b363a5e4 - D8132 - created - 1b87b363a5e4: copy+mod moved binary + D8132 - created - 12:1b87b363a5e4 tip "copy+mod moved binary" new commits: ['90437c20312a'] new commits: ['f391f4da4c61'] new commits: ['da86a9f3268c'] @@ -662,9 +662,9 @@ $ hg phase -r tip --public $ hg phabsend --fold -r 1:: --test-vcr "$VCR/phabsend-fold-immutable.json" - D8386 - created - a959a3f69d8d: one: first commit to review - D8386 - created - 24a4438154ba: two: second commit to review - D8386 - created - d235829e802c: 3: a commit with no detailed message + D8386 - created - 1:a959a3f69d8d "one: first commit to review" + D8386 - created - 2:24a4438154ba "two: second commit to review" + D8386 - created - 3:d235829e802c tip "3: a commit with no detailed message" warning: not updating public commit 1:a959a3f69d8d warning: not updating public commit 2:24a4438154ba warning: not updating public commit 3:d235829e802c @@ -676,13 +676,13 @@ $ echo y | hg phabsend --fold --confirm -r 1:: \ > --test-vcr "$VCR/phabsend-fold-initial.json" - NEW - a959a3f69d8d: one: first commit to review - NEW - 24a4438154ba: two: second commit to review - NEW - d235829e802c: 3: a commit with no detailed message + NEW - 1:a959a3f69d8d "one: first commit to review" + NEW - 2:24a4438154ba "two: second commit to review" + NEW - 3:d235829e802c tip "3: a commit with no detailed message" Send the above changes to https://phab.mercurial-scm.org/ (Y/n)? y - D8387 - created - a959a3f69d8d: one: first commit to review - D8387 - created - 24a4438154ba: two: second commit to review - D8387 - created - d235829e802c: 3: a commit with no detailed message + D8387 - created - 1:a959a3f69d8d "one: first commit to review" + D8387 - created - 2:24a4438154ba "two: second commit to review" + D8387 - created - 3:d235829e802c tip "3: a commit with no detailed message" updating local commit list for D8387 new commits: ['602c4e738243', '832553266fe8', '921f8265efbd'] saved backup bundle to $TESTTMP/folded/.hg/strip-backup/a959a3f69d8d-a4a24136-phabsend.hg @@ -728,7 +728,7 @@ obsolete feature not enabled but 1 markers found! 1 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg rebase --config experimental.evolution=all --config extensions.rebase= - note: not rebasing 2:832553266fe8 "two: second commit to review", already in destination as 4:0124e5474c88 "two: second commit to review" (tip) + note: not rebasing 2:832553266fe8 "two: second commit to review", already in destination as 4:0124e5474c88 tip "two: second commit to review" rebasing 3:921f8265efbd "3: a commit with no detailed message" When commits have changed locally, the local commit list on Phabricator is @@ -740,13 +740,13 @@ 602c4e738243 mapped to old nodes ['602c4e738243'] 0124e5474c88 mapped to old nodes ['832553266fe8'] e4edb1fe3565 mapped to old nodes ['921f8265efbd'] - D8387 - 602c4e738243: one: first commit to review - D8387 - 0124e5474c88: two: second commit to review - D8387 - e4edb1fe3565: 3: a commit with no detailed message + D8387 - 1:602c4e738243 "one: first commit to review" + D8387 - 4:0124e5474c88 "two: second commit to review" + D8387 - 5:e4edb1fe3565 tip "3: a commit with no detailed message" Send the above changes to https://phab.mercurial-scm.org/ (Y/n)? y - D8387 - updated - 602c4e738243: one: first commit to review - D8387 - updated - 0124e5474c88: two: second commit to review - D8387 - updated - e4edb1fe3565: 3: a commit with no detailed message + D8387 - updated - 1:602c4e738243 "one: first commit to review" + D8387 - updated - 4:0124e5474c88 "two: second commit to review" + D8387 - updated - 5:e4edb1fe3565 tip "3: a commit with no detailed message" obsolete feature not enabled but 2 markers found! (?) updating local commit list for D8387 new commits: ['602c4e738243', '0124e5474c88', 'e4edb1fe3565'] @@ -772,9 +772,9 @@ 602c4e738243 mapped to old nodes ['602c4e738243'] 0124e5474c88 mapped to old nodes ['0124e5474c88'] e4edb1fe3565 mapped to old nodes ['e4edb1fe3565'] - D8387 - updated - 602c4e738243: one: first commit to review - D8387 - updated - 0124e5474c88: two: second commit to review - D8387 - updated - e4edb1fe3565: 3: a commit with no detailed message + D8387 - updated - 1:602c4e738243 "one: first commit to review" + D8387 - updated - 4:0124e5474c88 "two: second commit to review" + D8387 - updated - 5:e4edb1fe3565 tip "3: a commit with no detailed message" obsolete feature not enabled but 2 markers found! (?) local commit list for D8387 is already up-to-date $ hg log -Tcompact @@ -801,10 +801,10 @@ 602c4e738243 mapped to old nodes ['602c4e738243'] 0124e5474c88 mapped to old nodes ['0124e5474c88'] e4edb1fe3565 mapped to old nodes ['e4edb1fe3565'] - D8387 - updated - 602c4e738243: one: first commit to review - D8387 - updated - 0124e5474c88: two: second commit to review - D8387 - updated - e4edb1fe3565: 3: a commit with no detailed message - D8387 - created - 94aaae213b23: four: extend the fold range + D8387 - updated - 1:602c4e738243 "one: first commit to review" + D8387 - updated - 4:0124e5474c88 "two: second commit to review" + D8387 - updated - 5:e4edb1fe3565 "3: a commit with no detailed message" + D8387 - created - 6:94aaae213b23 tip "four: extend the fold range" updating local commit list for D8387 new commits: ['602c4e738243', '0124e5474c88', 'e4edb1fe3565', '51a04fea8707'] $ hg log -r . -T '{desc}\n' @@ -832,11 +832,11 @@ 0124e5474c88 mapped to old nodes ['0124e5474c88'] e4edb1fe3565 mapped to old nodes ['e4edb1fe3565'] 51a04fea8707 mapped to old nodes ['51a04fea8707'] - D8388 - created - 98d480e0d494: added file - D8388 - updated - 602c4e738243: one: first commit to review - D8388 - updated - 0124e5474c88: two: second commit to review - D8388 - updated - e4edb1fe3565: 3: a commit with no detailed message - D8388 - updated - 51a04fea8707: four: extend the fold range + D8388 - created - 0:98d480e0d494 "added file" + D8388 - updated - 1:602c4e738243 "one: first commit to review" + D8388 - updated - 4:0124e5474c88 "two: second commit to review" + D8388 - updated - 5:e4edb1fe3565 "3: a commit with no detailed message" + D8388 - updated - 7:51a04fea8707 tip "four: extend the fold range" updating local commit list for D8388 new commits: ['15e9b14b4b4c', '6320b7d714cf', '3ee132d41dbc', '30682b960804', 'ac7db67f0991'] @@ -925,12 +925,12 @@ 30682b960804 mapped to old nodes ['30682b960804'] 6bc15dc99efd mapped to old nodes ['ac7db67f0991'] b50946d5e490 mapped to old nodes ['ac7db67f0991'] - D8388 - updated - 15e9b14b4b4c: added file - D8388 - updated - 6320b7d714cf: one: first commit to review - D8388 - updated - 3ee132d41dbc: two: second commit to review - D8388 - updated - 30682b960804: 3: a commit with no detailed message - D8388 - updated - 6bc15dc99efd: four: extend the fold range - D8388 - updated - b50946d5e490: four: extend the fold range + D8388 - updated - 8:15e9b14b4b4c "added file" + D8388 - updated - 9:6320b7d714cf "one: first commit to review" + D8388 - updated - 10:3ee132d41dbc "two: second commit to review" + D8388 - updated - 11:30682b960804 "3: a commit with no detailed message" + D8388 - updated - 14:6bc15dc99efd "four: extend the fold range" + D8388 - updated - 15:b50946d5e490 tip "four: extend the fold range" updating local commit list for D8388 new commits: ['15e9b14b4b4c', '6320b7d714cf', '3ee132d41dbc', '30682b960804', '6bc15dc99efd', 'b50946d5e490'] @@ -939,7 +939,7 @@ $ hg --config experimental.evolution=all --config extensions.rebase= \ > rebase -r '.^' -r . -d '.^^' --collapse -l log.txt rebasing 14:6bc15dc99efd "four: extend the fold range" - rebasing 15:b50946d5e490 "four: extend the fold range" (tip) + rebasing 15:b50946d5e490 tip "four: extend the fold range" $ hg phabsend --fold -r 8:: --test-vcr "$VCR/phabsend-fold-fold-end.json" \ > --config experimental.evolution=all @@ -948,11 +948,11 @@ 3ee132d41dbc mapped to old nodes ['3ee132d41dbc'] 30682b960804 mapped to old nodes ['30682b960804'] e919cdf3d4fe mapped to old nodes ['6bc15dc99efd', 'b50946d5e490'] - D8388 - updated - 15e9b14b4b4c: added file - D8388 - updated - 6320b7d714cf: one: first commit to review - D8388 - updated - 3ee132d41dbc: two: second commit to review - D8388 - updated - 30682b960804: 3: a commit with no detailed message - D8388 - updated - e919cdf3d4fe: four: extend the fold range + D8388 - updated - 8:15e9b14b4b4c "added file" + D8388 - updated - 9:6320b7d714cf "one: first commit to review" + D8388 - updated - 10:3ee132d41dbc "two: second commit to review" + D8388 - updated - 11:30682b960804 "3: a commit with no detailed message" + D8388 - updated - 16:e919cdf3d4fe tip "four: extend the fold range" updating local commit list for D8388 new commits: ['15e9b14b4b4c', '6320b7d714cf', '3ee132d41dbc', '30682b960804', 'e919cdf3d4fe'] @@ -987,8 +987,8 @@ $ hg ci -m 'c2874a398f7e is my parent (generate test for phabsend)' $ hg phabsend -r 17::18 --test-vcr "$VCR/phabsend-hash-fixes.json" - D8945 - created - 133c1c6c6449: base review (generate test for phabsend) - D8946 - created - c2874a398f7e: 133c1c6c6449 is my parent (generate test for phabsend) + D8945 - created - 17:133c1c6c6449 "base review (generate test for phabsend)" + D8946 - created - 18:c2874a398f7e "133c1c6c6449 is my parent (generate test for phabsend)" new commits: ['f444f060f4d6'] new commits: ['9c9290f945b1'] restabilizing 1528c12fa2e4 as b28b20212bd4
--- a/tests/test-phases-exchange.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-phases-exchange.t Thu Dec 03 14:15:39 2020 -0500 @@ -1015,7 +1015,7 @@ $ hg push -r 435b5d83910c ../mu pushing to ../mu searching for changes - abort: push creates new remote head 435b5d83910c! + abort: push creates new remote head 435b5d83910c (merge or see 'hg help push' for details about pushing new heads) [255] $ hg push -fr 435b5d83910c ../mu # because the push will create new visible head @@ -1322,12 +1322,12 @@ error, but EEXIST) $ touch .hg/store/lock - $ hg push ../Phi --config ui.timeout=1 + $ hg push ../Phi --config ui.timeout=1 --config ui.timeout.warn=0 pushing to ../Phi waiting for lock on repository $TESTTMP/Upsilon held by '' abort: repository $TESTTMP/Upsilon: timed out waiting for lock held by '' (lock might be very busy) - [255] + [20] $ rm .hg/store/lock $ cd ..
--- a/tests/test-phases.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-phases.t Thu Dec 03 14:15:39 2020 -0500 @@ -512,8 +512,8 @@ $ mkcommit I --config phases.new-commit='babar' transaction abort! rollback completed - abort: phases.new-commit: not a valid phase name ('babar') - [255] + config error: phases.new-commit: not a valid phase name ('babar') + [30] Test phase command =================== @@ -1010,7 +1010,7 @@ $ hg up -C 1 0 files updated, 0 files merged, 4 files removed, 0 files unresolved $ mkcommit C - created new head + warning: commit already existed in the repository! $ hg phase -r 2 2: public @@ -1027,6 +1027,7 @@ 7: draft $ mkcommit F test-debug-phase: new rev 8: x -> 2 + warning: commit already existed in the repository! test-hook-close-phase: de414268ec5ce2330c590b942fbb5ff0b0ca1a0a: -> secret $ hg phase -r tip 8: secret @@ -1037,7 +1038,7 @@ 0 files updated, 0 files merged, 2 files removed, 0 files unresolved $ mkcommit H test-debug-phase: new rev 5: x -> 2 - created new head + warning: commit already existed in the repository! test-hook-close-phase: a030c6be5127abc010fcbff1851536552e6951a8: -> secret $ hg phase -r 5 5: secret
--- a/tests/test-profile.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-profile.t Thu Dec 03 14:15:39 2020 -0500 @@ -64,19 +64,19 @@ Install an extension that can sleep and guarantee a profiler has time to run - $ cat >> sleepext.py << EOF + $ cat >> sleepext_with_a_long_filename.py << EOF > import time > from mercurial import registrar > cmdtable = {} > command = registrar.command(cmdtable) > @command(b'sleep', [], b'hg sleep') - > def sleep(ui, *args, **kwargs): + > def sleep_for_at_least_one_stat_cycle(ui, *args, **kwargs): > time.sleep(0.1) > EOF $ cat >> $HGRCPATH << EOF > [extensions] - > sleep = `pwd`/sleepext.py + > sleep = `pwd`/sleepext_with_a_long_filename.py > EOF statistical profiler works @@ -90,7 +90,7 @@ $ grep -v _path_stat ../out | head -n 3 % cumulative self time seconds seconds name - * sleepext.py:*:sleep (glob) + * sleepext_with_a_long_filename.py:*:sleep_for_at_least_one_stat_cycle (glob) $ cat ../out | statprofran $ hg --profile --config profiling.statformat=bymethod sleep 2>../out || cat ../out @@ -100,6 +100,8 @@ $ hg --profile --config profiling.statformat=hotpath sleep 2>../out || cat ../out $ cat ../out | statprofran + $ grep sleepext_with_a_long_filename.py ../out + .* [0-9.]+% [0-9.]+s sleepext_with_a_long_filename.py:\s*sleep_for_at_least_one_stat_cycle, line 7: time\.sleep.* (re) $ hg --profile --config profiling.statformat=json sleep 2>../out || cat ../out $ cat ../out
--- a/tests/test-pull-bundle.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-pull-bundle.t Thu Dec 03 14:15:39 2020 -0500 @@ -2,31 +2,30 @@ $ hg init repo $ cd repo - $ echo foo > foo - $ hg ci -qAm 'add foo' - $ echo >> foo - $ hg ci -m 'change foo' - $ hg up -qC 0 - $ echo bar > bar - $ hg ci -qAm 'add bar' + $ hg debugbuilddag '+3<3+1' $ hg log - changeset: 2:effea6de0384 + changeset: 3:6100d3090acf tag: tip - parent: 0:bbd179dfa0a7 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add bar + parent: 0:1ea73414a91b + user: debugbuilddag + date: Thu Jan 01 00:00:03 1970 +0000 + summary: r3 - changeset: 1:ed1b79f46b9a - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: change foo + changeset: 2:01241442b3c2 + user: debugbuilddag + date: Thu Jan 01 00:00:02 1970 +0000 + summary: r2 - changeset: 0:bbd179dfa0a7 - user: test + changeset: 1:66f7d451a68b + user: debugbuilddag + date: Thu Jan 01 00:00:01 1970 +0000 + summary: r1 + + changeset: 0:1ea73414a91b + user: debugbuilddag date: Thu Jan 01 00:00:00 1970 +0000 - summary: add foo + summary: r0 $ cd .. @@ -47,10 +46,13 @@ 1 changesets found $ hg bundle --base 1 -r 2 .hg/2.hg 1 changesets found + $ hg bundle --base 1 -r 3 .hg/3.hg + 1 changesets found $ cat <<EOF > .hg/pullbundles.manifest - > 2.hg BUNDLESPEC=none-v2 heads=effea6de0384e684f44435651cb7bd70b8735bd4 bases=bbd179dfa0a71671c253b3ae0aa1513b60d199fa - > 1.hg BUNDLESPEC=bzip2-v2 heads=ed1b79f46b9a29f5a6efa59cf12fcfca43bead5a bases=bbd179dfa0a71671c253b3ae0aa1513b60d199fa - > 0.hg BUNDLESPEC=gzip-v2 heads=bbd179dfa0a71671c253b3ae0aa1513b60d199fa + > 3.hg BUNDLESPEC=none-v2 heads=6100d3090acf50ed11ec23196cec20f5bd7323aa bases=1ea73414a91b0920940797d8fc6a11e447f8ea1e + > 2.hg BUNDLESPEC=none-v2 heads=01241442b3c2bf3211e593b549c655ea65b295e3 bases=66f7d451a68b85ed82ff5fcc254daf50c74144bd + > 1.hg BUNDLESPEC=bzip2-v2 heads=66f7d451a68b85ed82ff5fcc254daf50c74144bd bases=1ea73414a91b0920940797d8fc6a11e447f8ea1e + > 0.hg BUNDLESPEC=gzip-v2 heads=1ea73414a91b0920940797d8fc6a11e447f8ea1e > EOF $ hg --config blackbox.track=debug --debug serve -p $HGPORT2 -d --pid-file=../repo.pid -E ../error.txt listening at http://*:$HGPORT2/ (bound to $LOCALIP:$HGPORT2) (glob) (?) @@ -60,10 +62,10 @@ adding changesets adding manifests adding file changes - added 1 changesets with 1 changes to 1 files - new changesets bbd179dfa0a7 (1 drafts) + added 1 changesets with 0 changes to 0 files + new changesets 1ea73414a91b (1 drafts) updating to branch default - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cat error.txt $ cd repo.pullbundle $ hg pull -r 1 @@ -72,24 +74,24 @@ adding changesets adding manifests adding file changes - added 1 changesets with 1 changes to 1 files - new changesets ed1b79f46b9a (1 drafts) + added 1 changesets with 0 changes to 0 files + new changesets 66f7d451a68b (1 drafts) (run 'hg update' to get a working copy) - $ hg pull -r 2 + $ hg pull -r 3 pulling from http://localhost:$HGPORT2/ searching for changes adding changesets adding manifests adding file changes - added 1 changesets with 1 changes to 1 files (+1 heads) - new changesets effea6de0384 (1 drafts) + added 1 changesets with 0 changes to 0 files (+1 heads) + new changesets 6100d3090acf (1 drafts) (run 'hg heads' to see heads, 'hg merge' to merge) $ cd .. $ killdaemons.py $ grep 'sending pullbundle ' repo/.hg/blackbox.log * sending pullbundle "0.hg" (glob) * sending pullbundle "1.hg" (glob) - * sending pullbundle "2.hg" (glob) + * sending pullbundle "3.hg" (glob) $ rm repo/.hg/blackbox.log Test pullbundle functionality for incremental pulls @@ -110,15 +112,19 @@ adding changesets adding manifests adding file changes - added 3 changesets with 3 changes to 3 files (+1 heads) - new changesets bbd179dfa0a7:ed1b79f46b9a (3 drafts) + adding changesets + adding manifests + adding file changes + added 4 changesets with 0 changes to 0 files (+1 heads) + new changesets 1ea73414a91b:01241442b3c2 (4 drafts) updating to branch default - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ killdaemons.py $ grep 'sending pullbundle ' repo/.hg/blackbox.log * sending pullbundle "0.hg" (glob) + * sending pullbundle "3.hg" (glob) + * sending pullbundle "1.hg" (glob) * sending pullbundle "2.hg" (glob) - * sending pullbundle "1.hg" (glob) $ rm repo/.hg/blackbox.log Test pullbundle functionality for incoming @@ -132,19 +138,19 @@ adding changesets adding manifests adding file changes - added 1 changesets with 1 changes to 1 files - new changesets bbd179dfa0a7 (1 drafts) + added 1 changesets with 0 changes to 0 files + new changesets 1ea73414a91b (1 drafts) updating to branch default - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd repo.pullbundle2a - $ hg incoming -r ed1b79f46b9a + $ hg incoming -r 66f7d451a68b comparing with http://localhost:$HGPORT2/ searching for changes - changeset: 1:ed1b79f46b9a + changeset: 1:66f7d451a68b tag: tip - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: change foo + user: debugbuilddag + date: Thu Jan 01 00:00:01 1970 +0000 + summary: r1 $ cd .. $ killdaemons.py @@ -157,8 +163,8 @@ $ cd repo $ cat <<EOF > .hg/pullbundles.manifest - > 0.hg heads=ed1b79f46b9a29f5a6efa59cf12fcfca43bead5a bases=bbd179dfa0a71671c253b3ae0aa1513b60d199fa - > 0.hg heads=bbd179dfa0a71671c253b3ae0aa1513b60d199fa + > 0.hg heads=66f7d451a68b85ed82ff5fcc254daf50c74144bd bases=1ea73414a91b0920940797d8fc6a11e447f8ea1e + > 0.hg heads=1ea73414a91b0920940797d8fc6a11e447f8ea1e > EOF $ hg --config blackbox.track=debug --debug serve -p $HGPORT2 -d --pid-file=../repo.pid listening at http://*:$HGPORT2/ (bound to $LOCALIP:$HGPORT2) (glob) (?) @@ -168,10 +174,10 @@ adding changesets adding manifests adding file changes - added 1 changesets with 1 changes to 1 files - new changesets bbd179dfa0a7 (1 drafts) + added 1 changesets with 0 changes to 0 files + new changesets 1ea73414a91b (1 drafts) updating to branch default - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd repo.pullbundle3 $ hg pull -r 1 pulling from http://localhost:$HGPORT2/ @@ -179,8 +185,7 @@ adding changesets adding manifests adding file changes - added 0 changesets with 0 changes to 1 files - abort: 00changelog.i@ed1b79f46b9a: no node! + abort: 00changelog.i@66f7d451a68b: no node [255] $ cd .. $ killdaemons.py @@ -193,7 +198,6 @@ $ hg --repo repo debugobsolete ed1b79f46b9a29f5a6efa59cf12fcfca43bead5a 1 new obsolescence markers - obsoleted 1 changesets $ hg serve --repo repo --config server.view=visible -p $HGPORT -d --pid-file=hg.pid -E errors.log $ cat hg.pid >> $DAEMON_PIDS $ hg clone http://localhost:$HGPORT repo-obs @@ -204,8 +208,8 @@ adding changesets adding manifests adding file changes - added 2 changesets with 2 changes to 2 files - new changesets bbd179dfa0a7:effea6de0384 + added 1 changesets with 0 changes to 0 files + new changesets 1ea73414a91b (1 drafts) updating to branch default - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ killdaemons.py
--- a/tests/test-pull-r.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-pull-r.t Thu Dec 03 14:15:39 2020 -0500 @@ -111,7 +111,7 @@ Pull a missing revision: $ hg pull -qr missing ../repo - abort: unknown revision 'missing'! + abort: unknown revision 'missing' [255] Pull multiple revisions with update:
--- a/tests/test-pull-update.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-pull-update.t Thu Dec 03 14:15:39 2020 -0500 @@ -29,7 +29,7 @@ new changesets 107cefe13e42 1 local changesets published abort: uncommitted changes - [255] + [20] $ hg --config extensions.strip= strip --no-backup tip $ hg co -qC tip
--- a/tests/test-pull.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-pull.t Thu Dec 03 14:15:39 2020 -0500 @@ -68,17 +68,17 @@ $ hg pull -r 'xxxxxxxxxxxxxxxxxxxy' pulling from http://foo@localhost:$HGPORT/ - abort: unknown revision 'xxxxxxxxxxxxxxxxxxxy'! + abort: unknown revision 'xxxxxxxxxxxxxxxxxxxy' [255] $ hg pull -r 'xxxxxxxxxxxxxxxxxx y' pulling from http://foo@localhost:$HGPORT/ - abort: unknown revision 'xxxxxxxxxxxxxxxxxx y'! + abort: unknown revision 'xxxxxxxxxxxxxxxxxx y' [255] Test pull of working copy revision $ hg pull -r 'ffffffffffff' pulling from http://foo@localhost:$HGPORT/ - abort: unknown revision 'ffffffffffff'! + abort: unknown revision 'ffffffffffff' [255] Issue622: hg init && hg pull -u URL doesn't checkout default branch @@ -140,11 +140,11 @@ [255] $ hg pull 'ssh://fakehost|touch${IFS}owned/path' pulling from ssh://fakehost%7Ctouch%24%7BIFS%7Downed/path - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ hg --config ui.timestamp-output=true pull 'ssh://fakehost%7Ctouch%20owned/path' \[20[2-9][0-9]-[01][0-9]-[0-3][0-9]T[0-5][0-9]:[0-5][0-9]:[0-5][0-9]\.[0-9][0-9][0-9][0-9][0-9][0-9]\] pulling from ssh://fakehost%7Ctouch%20owned/path (re) - \[20[2-9][0-9]-[01][0-9]-[0-3][0-9]T[0-5][0-9]:[0-5][0-9]:[0-5][0-9]\.[0-9][0-9][0-9][0-9][0-9][0-9]\] abort: no suitable response from remote hg! (re) + \[20[2-9][0-9]-[01][0-9]-[0-3][0-9]T[0-5][0-9]:[0-5][0-9]:[0-5][0-9]\.[0-9][0-9][0-9][0-9][0-9][0-9]\] abort: no suitable response from remote hg (re) [255] $ [ ! -f owned ] || echo 'you got owned'
--- a/tests/test-push-checkheads-multibranches-E3.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-checkheads-multibranches-E3.t Thu Dec 03 14:15:39 2020 -0500 @@ -87,7 +87,7 @@ $ hg push -r 'desc("C1")' pushing to $TESTTMP/E1/server searching for changes - abort: push creates new remote head dc44c53142f0! + abort: push creates new remote head dc44c53142f0 (merge or see 'hg help push' for details about pushing new heads) [255]
--- a/tests/test-push-checkheads-partial-C1.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-checkheads-partial-C1.t Thu Dec 03 14:15:39 2020 -0500 @@ -78,7 +78,7 @@ $ hg push pushing to $TESTTMP/C1/server searching for changes - abort: push creates new remote head 25c56d33e4c4! + abort: push creates new remote head 25c56d33e4c4 (merge or see 'hg help push' for details about pushing new heads) [255]
--- a/tests/test-push-checkheads-partial-C2.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-checkheads-partial-C2.t Thu Dec 03 14:15:39 2020 -0500 @@ -79,7 +79,7 @@ $ hg push --rev 'desc(A1)' pushing to $TESTTMP/C2/server searching for changes - abort: push creates new remote head f6082bc4ffef! + abort: push creates new remote head f6082bc4ffef (merge or see 'hg help push' for details about pushing new heads) [255]
--- a/tests/test-push-checkheads-partial-C3.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-checkheads-partial-C3.t Thu Dec 03 14:15:39 2020 -0500 @@ -78,7 +78,7 @@ $ hg push pushing to $TESTTMP/C3/server searching for changes - abort: push creates new remote head 0f88766e02d6! + abort: push creates new remote head 0f88766e02d6 (merge or see 'hg help push' for details about pushing new heads) [255]
--- a/tests/test-push-checkheads-partial-C4.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-checkheads-partial-C4.t Thu Dec 03 14:15:39 2020 -0500 @@ -79,7 +79,7 @@ $ hg push --rev 'desc(C0)' pushing to $TESTTMP/C4/server searching for changes - abort: push creates new remote head 0f88766e02d6! + abort: push creates new remote head 0f88766e02d6 (merge or see 'hg help push' for details about pushing new heads) [255]
--- a/tests/test-push-checkheads-unpushed-D1.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-checkheads-unpushed-D1.t Thu Dec 03 14:15:39 2020 -0500 @@ -71,7 +71,7 @@ $ hg push -r 'desc(B0)' pushing to $TESTTMP/D1/server searching for changes - abort: push creates new remote head 74ff5441d343! + abort: push creates new remote head 74ff5441d343 (merge or see 'hg help push' for details about pushing new heads) [255]
--- a/tests/test-push-checkheads-unpushed-D2.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-checkheads-unpushed-D2.t Thu Dec 03 14:15:39 2020 -0500 @@ -92,7 +92,7 @@ $ hg push --rev 'desc(C0)' pushing to $TESTTMP/D2/server searching for changes - abort: push creates new remote head 0f88766e02d6! + abort: push creates new remote head 0f88766e02d6 (merge or see 'hg help push' for details about pushing new heads) [255]
--- a/tests/test-push-checkheads-unpushed-D3.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-checkheads-unpushed-D3.t Thu Dec 03 14:15:39 2020 -0500 @@ -91,13 +91,13 @@ $ hg push --rev 'desc(A1)' pushing to $TESTTMP/D3/server searching for changes - abort: push creates new remote head f6082bc4ffef! + abort: push creates new remote head f6082bc4ffef (merge or see 'hg help push' for details about pushing new heads) [255] $ hg push --rev 'desc(B1)' pushing to $TESTTMP/D3/server searching for changes - abort: push creates new remote head 25c56d33e4c4! + abort: push creates new remote head 25c56d33e4c4 (merge or see 'hg help push' for details about pushing new heads) [255] @@ -109,7 +109,7 @@ $ hg push pushing to $TESTTMP/D3/server searching for changes - abort: push creates new remote head 25c56d33e4c4! + abort: push creates new remote head 25c56d33e4c4 (merge or see 'hg help push' for details about pushing new heads) [255]
--- a/tests/test-push-checkheads-unpushed-D4.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-checkheads-unpushed-D4.t Thu Dec 03 14:15:39 2020 -0500 @@ -109,7 +109,7 @@ $ hg push --rev 'desc(A1)' pushing to $TESTTMP/D4/server searching for changes - abort: push creates new remote head f6082bc4ffef! + abort: push creates new remote head f6082bc4ffef (merge or see 'hg help push' for details about pushing new heads) [255]
--- a/tests/test-push-checkheads-unpushed-D5.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-checkheads-unpushed-D5.t Thu Dec 03 14:15:39 2020 -0500 @@ -98,7 +98,7 @@ $ hg push --rev 'desc(B1)' pushing to $TESTTMP/D5/server searching for changes - abort: push creates new remote head 25c56d33e4c4! + abort: push creates new remote head 25c56d33e4c4 (merge or see 'hg help push' for details about pushing new heads) [255] $ hg push --rev 'desc(A1)'
--- a/tests/test-push-checkheads-unpushed-D6.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-checkheads-unpushed-D6.t Thu Dec 03 14:15:39 2020 -0500 @@ -79,7 +79,7 @@ $ hg push --rev 'desc(C0)' pushing to $TESTTMP/D6/server searching for changes - abort: push creates new remote head 0f88766e02d6! + abort: push creates new remote head 0f88766e02d6 (merge or see 'hg help push' for details about pushing new heads) [255]
--- a/tests/test-push-http.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-http.t Thu Dec 03 14:15:39 2020 -0500 @@ -41,7 +41,7 @@ searching for changes abort: HTTP Error 403: ssl required % serve errors - [255] + [100] expect authorization error
--- a/tests/test-push-warn.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push-warn.t Thu Dec 03 14:15:39 2020 -0500 @@ -25,13 +25,13 @@ pushing to ../a abort: specified revisions evaluate to an empty set (use different revision arguments) - [255] + [10] $ hg push ../a pushing to ../a searching for changes remote has heads on branch 'default' that are not known locally: 1c9246a22a0a - abort: push creates new remote head 1e108cc5548c! + abort: push creates new remote head 1e108cc5548c (pull and merge or see 'hg help push' for details about pushing new heads) [255] @@ -49,7 +49,7 @@ remote has heads on branch 'default' that are not known locally: 1c9246a22a0a new remote heads on branch 'default': 1e108cc5548c - abort: push creates new remote head 1e108cc5548c! + abort: push creates new remote head 1e108cc5548c (pull and merge or see 'hg help push' for details about pushing new heads) [255] @@ -66,7 +66,7 @@ $ hg push ../a pushing to ../a searching for changes - abort: push creates new remote head 1e108cc5548c! + abort: push creates new remote head 1e108cc5548c (merge or see 'hg help push' for details about pushing new heads) [255] @@ -119,7 +119,7 @@ $ hg push ../c pushing to ../c searching for changes - abort: push creates new remote head 6346d66eb9f5! + abort: push creates new remote head 6346d66eb9f5 (merge or see 'hg help push' for details about pushing new heads) [255] @@ -132,7 +132,7 @@ $ hg push -r 3 ../c pushing to ../c searching for changes - abort: push creates new remote head a5dda829a167! + abort: push creates new remote head a5dda829a167 (merge or see 'hg help push' for details about pushing new heads) [255] @@ -142,7 +142,7 @@ new remote heads on branch 'default': a5dda829a167 ee8fbc7a0295 - abort: push creates new remote head a5dda829a167! + abort: push creates new remote head a5dda829a167 (merge or see 'hg help push' for details about pushing new heads) [255] @@ -232,14 +232,14 @@ $ hg push ../f pushing to ../f searching for changes - abort: push creates new remote branches: c! + abort: push creates new remote branches: c (use 'hg push --new-branch' to create new remote branches) [255] $ hg push -r 4 -r 5 ../f pushing to ../f searching for changes - abort: push creates new remote branches: c! + abort: push creates new remote branches: c (use 'hg push --new-branch' to create new remote branches) [255] @@ -253,14 +253,14 @@ $ hg push ../f pushing to ../f searching for changes - abort: push creates new remote branches: c, d! + abort: push creates new remote branches: c, d (use 'hg push --new-branch' to create new remote branches) [255] $ hg push -r 4 -r 6 ../f pushing to ../f searching for changes - abort: push creates new remote branches: c, d! + abort: push creates new remote branches: c, d (use 'hg push --new-branch' to create new remote branches) [255] @@ -276,7 +276,7 @@ $ hg push -r 4 -r 7 ../f pushing to ../f searching for changes - abort: push creates new remote head 0b715ef6ff8f on branch 'a'! + abort: push creates new remote head 0b715ef6ff8f on branch 'a' (merge or see 'hg help push' for details about pushing new heads) [255] @@ -353,7 +353,7 @@ $ hg push -r 12 -r 13 ../f pushing to ../f searching for changes - abort: push creates new remote branches: e! + abort: push creates new remote branches: e (use 'hg push --new-branch' to create new remote branches) [255] @@ -425,7 +425,7 @@ pushing to h searching for changes remote has heads on branch 'default' that are not known locally: 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847 - abort: push creates new remote head 97bd0c84d346! + abort: push creates new remote head 97bd0c84d346 (pull and merge or see 'hg help push' for details about pushing new heads) [255] $ hg -R h up -q 0; echo x > h/b; hg -R h ci -qAmx @@ -433,7 +433,7 @@ pushing to h searching for changes remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 and 1 others - abort: push creates new remote head 97bd0c84d346! + abort: push creates new remote head 97bd0c84d346 (pull and merge or see 'hg help push' for details about pushing new heads) [255] $ hg -R i push h -v @@ -442,7 +442,7 @@ remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847 new remote heads on branch 'default': 97bd0c84d346 - abort: push creates new remote head 97bd0c84d346! + abort: push creates new remote head 97bd0c84d346 (pull and merge or see 'hg help push' for details about pushing new heads) [255] @@ -477,7 +477,7 @@ $ hg -R k push -r a j pushing to j searching for changes - abort: push creates new remote branches: b! + abort: push creates new remote branches: b (use 'hg push --new-branch' to create new remote branches) [255] @@ -513,7 +513,7 @@ $ hg push ../l -b b pushing to ../l searching for changes - abort: push creates new remote head 451211cc22b0 on branch 'a'! + abort: push creates new remote head 451211cc22b0 on branch 'a' (merge or see 'hg help push' for details about pushing new heads) [255] @@ -763,14 +763,14 @@ $ hg push inner pushing to inner searching for changes - abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'! + abort: push creates new remote head 7d0f4fb6cf04 on branch 'A' (merge or see 'hg help push' for details about pushing new heads) [255] $ hg push inner -r4 -r5 pushing to inner searching for changes - abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'! + abort: push creates new remote head 7d0f4fb6cf04 on branch 'A' (merge or see 'hg help push' for details about pushing new heads) [255] @@ -786,7 +786,7 @@ pushing to inner searching for changes running fail-push hook - abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'! + abort: push creates new remote head 7d0f4fb6cf04 on branch 'A' (merge or see 'hg help push' for details about pushing new heads) [255] @@ -815,7 +815,7 @@ $ hg push ../x pushing to ../x searching for changes - abort: push creates new remote branches: foo (1 closed)! + abort: push creates new remote branches: foo (1 closed) (use 'hg push --new-branch' to create new remote branches) [255] @@ -828,7 +828,7 @@ $ hg push ../x pushing to ../x searching for changes - abort: push creates new remote branches: bar, foo (2 closed)! + abort: push creates new remote branches: bar, foo (2 closed) (use 'hg push --new-branch' to create new remote branches) [255] @@ -840,7 +840,7 @@ $ hg push ../x pushing to ../x searching for changes - abort: push creates new remote branches: bar, bar1, foo (2 closed)! + abort: push creates new remote branches: bar, bar1, foo (2 closed) (use 'hg push --new-branch' to create new remote branches) [255]
--- a/tests/test-push.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-push.t Thu Dec 03 14:15:39 2020 -0500 @@ -340,11 +340,11 @@ [255] $ hg -R test-revflag push 'ssh://fakehost|touch${IFS}owned/path' pushing to ssh://fakehost%7Ctouch%24%7BIFS%7Downed/path - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ hg -R test-revflag push 'ssh://fakehost%7Ctouch%20owned/path' pushing to ssh://fakehost%7Ctouch%20owned/path - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ [ ! -f owned ] || echo 'you got owned' @@ -365,7 +365,7 @@ pushing to $TESTTMP/test-require-revs-dest abort: no revisions specified to push (did you mean "hg push -r ."?) - [255] + [10] $ hg push -r 0 pushing to $TESTTMP/test-require-revs-dest searching for changes @@ -385,7 +385,7 @@ $ hg push -b default pushing to $TESTTMP/test-require-revs-dest searching for changes - abort: push creates new remote head [0-9a-f]+! (re) + abort: push creates new remote head [0-9a-f]+ (re) (merge or see 'hg help push' for details about pushing new heads) [255] (demonstrate that even though we don't have anything to exchange, we're still @@ -394,7 +394,7 @@ pushing to $TESTTMP/test-require-revs-dest abort: no revisions specified to push (did you mean "hg push -r ."?) - [255] + [10] $ hg push --config paths.default:pushrev=0 pushing to $TESTTMP/test-require-revs-dest searching for changes
--- a/tests/test-qrecord.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-qrecord.t Thu Dec 03 14:15:39 2020 -0500 @@ -458,7 +458,7 @@ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved Editing (ea55e2ae468f), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ echo 'foo bar' > a $ hg qrecord -d '0 0' -m aaa a.patch <<EOF > y @@ -470,4 +470,4 @@ > EOF abort: histedit in progress (use 'hg histedit --continue' or 'hg histedit --abort') - [255] + [20]
--- a/tests/test-rebase-abort.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-abort.t Thu Dec 03 14:15:39 2020 -0500 @@ -78,11 +78,11 @@ $ hg rebase -s 3 -d 2 rebasing 3:3163e20567cc "L1" - rebasing 4:46f0b057b5c0 "L2" (tip) + rebasing 4:46f0b057b5c0 tip "L2" merging common warning: conflicts while merging common! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] Insert unsupported advisory merge record: @@ -145,11 +145,11 @@ $ hg rebase -s 3 -d 2 rebasing 3:3163e20567cc "L1" - rebasing 4:46f0b057b5c0 "L2" (tip) + rebasing 4:46f0b057b5c0 tip "L2" merging common warning: conflicts while merging common! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ mv .hg/rebasestate .hg/rebasestate.back $ hg update --quiet --clean 2 @@ -215,11 +215,11 @@ $ hg rebase -b 4 -d 2 rebasing 3:a6484957d6b9 "B bis" note: not rebasing 3:a6484957d6b9 "B bis", its destination already has all its changes - rebasing 4:145842775fec "C1" (tip) + rebasing 4:145842775fec tip "C1" merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg tglog % 4:draft 'C1' @@ -274,11 +274,11 @@ $ hg rebase -d master -r foo - rebasing 3:6c0f977a22d8 "C" (foo tip) + rebasing 3:6c0f977a22d8 foo tip "C" merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg abort rebase aborted $ hg log -G --template "{rev} {desc} {bookmarks}" @@ -314,9 +314,9 @@ created new head $ hg rebase -d @ -b foo --tool=internal:fail - rebasing 2:070cf4580bb5 "b2" (foo tip) + rebasing 2:070cf4580bb5 foo tip "b2" unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ mv .hg/rebasestate ./ # so we're allowed to hg up like in mercurial <2.6.3 $ hg up -C 0 # user does other stuff in the repo @@ -328,7 +328,7 @@ $ hg up 1 # user gets an error saying to run hg rebase --abort abort: rebase in progress (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') - [255] + [20] $ cat a new @@ -398,20 +398,20 @@ $ hg rebase -s 3 -d tip abort: rebase in progress (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') - [255] + [20] $ hg up . abort: rebase in progress (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') - [255] + [20] $ hg up -C . abort: rebase in progress (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') - [255] + [20] $ hg graft 3 abort: rebase in progress (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') - [255] + [20] $ hg abort saved backup bundle to $TESTTMP/interrupted/.hg/strip-backup/3d8812cf300d-93041a90-backup.hg @@ -463,7 +463,7 @@ $ hg rebase -d 1 --tool 'internal:fail' rebasing 2:e4ea5cdc9789 "conflicting 1" unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg abort rebase aborted $ hg summary @@ -504,7 +504,7 @@ note: not rebasing 3:0682fd3dabf5 "disappear draft", its destination already has all its changes warning: conflicts while merging root! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg abort rebase aborted $ cd ..
--- a/tests/test-rebase-backup.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-backup.t Thu Dec 03 14:15:39 2020 -0500 @@ -127,7 +127,7 @@ merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --abort saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/818c1a43c916-2b644d96-backup.hg rebase aborted @@ -143,7 +143,7 @@ merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --abort rebase aborted $ cd ..
--- a/tests/test-rebase-base-flag.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-base-flag.t Thu Dec 03 14:15:39 2020 -0500 @@ -36,9 +36,9 @@ > | > R > EOS - rebasing 3:d6003a550c2c "C" (C) - rebasing 5:4526cf523425 "D" (D) - rebasing 6:b296604d9846 "E" (E tip) + rebasing 3:d6003a550c2c C "C" + rebasing 5:4526cf523425 D "D" + rebasing 6:b296604d9846 E tip "E" o 6: 4870f5e7df37 E | | o 5: dc999528138a D @@ -66,9 +66,9 @@ > | > R > EOS - rebasing 2:c1e6b162678d "B" (B) - rebasing 3:d6003a550c2c "C" (C) - rebasing 6:54c8f00cb91c "E" (E tip) + rebasing 2:c1e6b162678d B "B" + rebasing 3:d6003a550c2c C "C" + rebasing 6:54c8f00cb91c E tip "E" o 6: 00598421b616 E |\ | o 5: 6b3e11729672 C @@ -94,8 +94,8 @@ > | > R > EOS - rebasing 2:c1e6b162678d "B" (B) - rebasing 5:54c8f00cb91c "E" (E tip) + rebasing 2:c1e6b162678d B "B" + rebasing 5:54c8f00cb91c E tip "E" o 5: e583bf3ff54c E |\ | o 4: 85260910e847 B @@ -119,9 +119,9 @@ > | > R > EOS - rebasing 2:c1e6b162678d "B" (B) - rebasing 3:d6003a550c2c "C" (C) - rebasing 5:54c8f00cb91c "E" (E tip) + rebasing 2:c1e6b162678d B "B" + rebasing 3:d6003a550c2c C "C" + rebasing 5:54c8f00cb91c E tip "E" o 5: 00598421b616 E |\ | o 4: 6b3e11729672 C @@ -167,12 +167,12 @@ > | > R > EOS - rebasing 3:a113dbaa660a "B1" (B1) - rebasing 5:06ce7b1cc8c2 "B2" (B2) - rebasing 6:0ac98cce32d3 "C1" (C1) - rebasing 8:781512f5e33d "C2" (C2) - rebasing 9:428d8c18f641 "E1" (E1) - rebasing 11:e1bf82f6b6df "E2" (E2) + rebasing 3:a113dbaa660a B1 "B1" + rebasing 5:06ce7b1cc8c2 B2 "B2" + rebasing 6:0ac98cce32d3 C1 "C1" + rebasing 8:781512f5e33d C2 "C2" + rebasing 9:428d8c18f641 E1 "E1" + rebasing 11:e1bf82f6b6df E2 "E2" o 12: e4a37b6fdbd2 E2 | o 11: 9675bea983df E1 @@ -210,19 +210,19 @@ > \|/ |/ |/ > A A A > EOS - rebasing 2:dc0947a82db8 "C" (C) - rebasing 8:4e4f9194f9f1 "D" (D) - rebasing 9:03ca77807e91 "E" (E) - rebasing 10:afc707c82df0 "F" (F) - rebasing 13:690dfff91e9e "G" (G) - rebasing 14:2893b886bb10 "H" (H) - rebasing 3:08ebfeb61bac "I" (I) - rebasing 4:a0a5005cec67 "J" (J) - rebasing 5:83780307a7e8 "K" (K) - rebasing 6:e131637a1cb6 "L" (L) - rebasing 11:d1f6d0c3c7e4 "M" (M) - rebasing 12:7aaec6f81888 "N" (N) - rebasing 15:325bc8f1760d "P" (P tip) + rebasing 2:dc0947a82db8 C "C" + rebasing 8:4e4f9194f9f1 D "D" + rebasing 9:03ca77807e91 E "E" + rebasing 10:afc707c82df0 F "F" + rebasing 13:690dfff91e9e G "G" + rebasing 14:2893b886bb10 H "H" + rebasing 3:08ebfeb61bac I "I" + rebasing 4:a0a5005cec67 J "J" + rebasing 5:83780307a7e8 K "K" + rebasing 6:e131637a1cb6 L "L" + rebasing 11:d1f6d0c3c7e4 M "M" + rebasing 12:7aaec6f81888 N "N" + rebasing 15:325bc8f1760d P tip "P" o 15: 6ef6a0ea3b18 P |\ | o 14: 20ba3610a7e5 N @@ -268,13 +268,13 @@ > | > M0 > EOF - rebasing 4:8817fae53c94 "C0" (C0) - rebasing 6:06ca5dfe3b5b "B2" (B2) - rebasing 7:73508237b032 "C1" (C1) - rebasing 9:fdb955e2faed "A2" (A2) - rebasing 11:4e449bd1a643 "A3" (A3) - rebasing 10:0a33b0519128 "B1" (B1) - rebasing 12:209327807c3a "B3" (B3 tip) + rebasing 4:8817fae53c94 C0 "C0" + rebasing 6:06ca5dfe3b5b B2 "B2" + rebasing 7:73508237b032 C1 "C1" + rebasing 9:fdb955e2faed A2 "A2" + rebasing 11:4e449bd1a643 A3 "A3" + rebasing 10:0a33b0519128 B1 "B1" + rebasing 12:209327807c3a B3 tip "B3" o 12: ceb984566332 B3 |\ | o 11: 19d93caac497 B1 @@ -318,8 +318,8 @@ > \|\| > C A > EOF - rebasing 2:112478962961 "B" (B) - rebasing 3:b70f76719894 "D" (D) + rebasing 2:112478962961 B "B" + rebasing 3:b70f76719894 D "D" o 4: 511efad7bf13 D | | o 3: 25c4e279af62 B @@ -349,8 +349,8 @@ > \|\| > A C > EOF - rebasing 2:f675d5a1c6a4 "B" (B) - rebasing 5:f68696fe6af8 "E" (E tip) + rebasing 2:f675d5a1c6a4 B "B" + rebasing 5:f68696fe6af8 E tip "E" o 5: f6e6f5081554 E |\ | o 4: 30cabcba27be B @@ -370,8 +370,8 @@ > \|\|\ > A C A > EOF - rebasing 2:f675d5a1c6a4 "B" (B) - rebasing 3:c2a779e13b56 "D" (D) + rebasing 2:f675d5a1c6a4 B "B" + rebasing 3:c2a779e13b56 D "D" o 4: 5eecd056b5f8 D |\ +---o 3: 30cabcba27be B
--- a/tests/test-rebase-bookmarks.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-bookmarks.t Thu Dec 03 14:15:39 2020 -0500 @@ -75,7 +75,7 @@ o 0: 1994f17a630e 'A' bookmarks: Y@diverge $ hg rebase -s Y -d 3 - rebasing 2:49cb3485fa0c "C" (Y Z) + rebasing 2:49cb3485fa0c Y Z "C" saved backup bundle to $TESTTMP/a1/.hg/strip-backup/49cb3485fa0c-126f3e97-rebase.hg $ hg tglog @@ -97,7 +97,7 @@ $ hg book W@diverge $ hg rebase -s W -d . - rebasing 3:41acb9dca9eb "D" (W tip) + rebasing 3:41acb9dca9eb W tip "D" saved backup bundle to $TESTTMP/a4/.hg/strip-backup/41acb9dca9eb-b35a6a63-rebase.hg $ hg bookmarks @@ -115,8 +115,8 @@ $ hg up -q Z $ hg rebase -s 1 -d 3 - rebasing 1:6c81ed0049f8 "B" (X) - rebasing 2:49cb3485fa0c "C" (Y Z) + rebasing 1:6c81ed0049f8 X "B" + rebasing 2:49cb3485fa0c Y Z "C" saved backup bundle to $TESTTMP/a2/.hg/strip-backup/6c81ed0049f8-a687065f-rebase.hg $ hg tglog @@ -138,8 +138,8 @@ $ hg up -q X $ hg rebase -d W - rebasing 1:6c81ed0049f8 "B" (X) - rebasing 2:49cb3485fa0c "C" (Y Z) + rebasing 1:6c81ed0049f8 X "B" + rebasing 2:49cb3485fa0c Y Z "C" saved backup bundle to $TESTTMP/a3/.hg/strip-backup/6c81ed0049f8-a687065f-rebase.hg $ hg tglog @@ -169,17 +169,17 @@ $ hg up 3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg rebase --dest 4 - rebasing 3:3d5fa227f4b5 "C" (Y Z) + rebasing 3:3d5fa227f4b5 Y Z "C" merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ echo 'c' > c $ hg resolve --mark c (no more unresolved files) continue: hg rebase --continue $ hg rebase --continue - rebasing 3:3d5fa227f4b5 "C" (Y Z) + rebasing 3:3d5fa227f4b5 Y Z "C" saved backup bundle to $TESTTMP/a3/.hg/strip-backup/3d5fa227f4b5-c6ea2371-rebase.hg $ hg tglog @ 4: 45c0f0ec1203 'C' bookmarks: Y Z @@ -209,7 +209,7 @@ $ hg rebase -r '"bisect"^^::"bisect"^' -r bisect -d Z rebasing 5:345c90f326a4 "bisect" rebasing 6:f677a2907404 "bisect2" - rebasing 7:325c16001345 "bisect3" (bisect tip) + rebasing 7:325c16001345 bisect tip "bisect3" saved backup bundle to $TESTTMP/a3/.hg/strip-backup/345c90f326a4-b4840586-rebase.hg Bookmark and working parent get moved even if --keep is set (issue5682) @@ -232,7 +232,7 @@ o 0: 426bada5c675 'A' bookmarks: A $ hg rebase -r B -d C --keep - rebasing 1:112478962961 "B" (B) + rebasing 1:112478962961 B "B" $ hg tglog @ 3: 9769fc65c4c5 'B' bookmarks: B |
--- a/tests/test-rebase-cache.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-cache.t Thu Dec 03 14:15:39 2020 -0500 @@ -165,7 +165,7 @@ o 0: 'A' $ hg rebase -s 8 -d 6 - rebasing 8:4666b71e8e32 "F" (tip) + rebasing 8:4666b71e8e32 tip "F" saved backup bundle to $TESTTMP/a2/.hg/strip-backup/4666b71e8e32-fc1c4e96-rebase.hg $ hg branches @@ -232,7 +232,7 @@ $ hg rebase -s 7 -d 6 rebasing 7:653b9feb4616 "branch3" note: not rebasing 7:653b9feb4616 "branch3", its destination already has all its changes - rebasing 8:4666b71e8e32 "F" (tip) + rebasing 8:4666b71e8e32 tip "F" saved backup bundle to $TESTTMP/a3/.hg/strip-backup/653b9feb4616-3c88de16-rebase.hg $ hg branches @@ -478,6 +478,6 @@ $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg rebase --dest 7 --source 5 -e rebasing 5:361a99976cc9 "F" HGEDITFORM=rebase.merge - rebasing 8:326cfedc031c "I" (tip) + rebasing 8:326cfedc031c tip "I" HGEDITFORM=rebase.normal saved backup bundle to $TESTTMP/a3/c4/.hg/strip-backup/361a99976cc9-35e980d0-rebase.hg
--- a/tests/test-rebase-check-restore.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-check-restore.t Thu Dec 03 14:15:39 2020 -0500 @@ -70,7 +70,7 @@ merging A warning: conflicts while merging A! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] Solve the conflict and go on: @@ -123,11 +123,11 @@ o 0:draft 'A' $ hg rebase -s 5 -d 4 --keepbranches - rebasing 5:01e6ebbd8272 "F" (tip) + rebasing 5:01e6ebbd8272 tip "F" merging A warning: conflicts while merging A! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] Solve the conflict and go on: @@ -137,7 +137,7 @@ (no more unresolved files) continue: hg rebase --continue $ hg rebase --continue - rebasing 5:01e6ebbd8272 "F" (tip) + rebasing 5:01e6ebbd8272 tip "F" saved backup bundle to $TESTTMP/a2/.hg/strip-backup/01e6ebbd8272-6fd3a015-rebase.hg $ hg tglog
--- a/tests/test-rebase-collapse.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-collapse.t Thu Dec 03 14:15:39 2020 -0500 @@ -35,9 +35,9 @@ > echo "edited manually" >> \$1 > EOF $ HGEDITOR="sh $TESTTMP/editor.sh" hg rebase --collapse --keepbranches -e --source B --dest F - rebasing 1:112478962961 "B" (B) - rebasing 3:26805aba1e60 "C" (C) - rebasing 5:f585351a92f8 "D" (D tip) + rebasing 1:112478962961 B "B" + rebasing 3:26805aba1e60 C "C" + rebasing 5:f585351a92f8 D tip "D" ==== before editing Collapsed revision * B @@ -96,8 +96,8 @@ $ hg phase --force --secret D $ hg rebase --source B --collapse --dest F - rebasing 1:112478962961 "B" (B) - rebasing 3:4e4f9194f9f1 "D" (D) + rebasing 1:112478962961 B "B" + rebasing 3:4e4f9194f9f1 D "D" saved backup bundle to $TESTTMP/linearized-merge/.hg/strip-backup/112478962961-e389075b-rebase.hg $ hg tglog @@ -141,8 +141,8 @@ > true > EOF $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg rebase --source B --collapse -m 'custom message' -e --dest D - rebasing 1:112478962961 "B" (B) - rebasing 3:26805aba1e60 "C" (C tip) + rebasing 1:112478962961 B "B" + rebasing 3:26805aba1e60 C tip "C" HGEDITFORM=rebase.collapse saved backup bundle to $TESTTMP/message/.hg/strip-backup/112478962961-f4131707-rebase.hg @@ -185,9 +185,9 @@ Rebase and collapse - E onto H: $ hg rebase -s E --dest H --collapse # root (E) is not a merge - rebasing 5:49cb92066bfd "E" (E) - rebasing 6:11abe3fb10b8 "F" (F) - rebasing 7:64e264db77f0 "G" (G tip) + rebasing 5:49cb92066bfd E "E" + rebasing 6:11abe3fb10b8 F "F" + rebasing 7:64e264db77f0 G tip "G" saved backup bundle to $TESTTMP/multiple-external-parents/.hg/strip-backup/49cb92066bfd-ee8a8a79-rebase.hg $ hg tglog @@ -287,21 +287,21 @@ > EOF $ hg rebase -s F --dest I --collapse # root (F) is not a merge - rebasing 6:c82b08f646f1 "F" (F) + rebasing 6:c82b08f646f1 F "F" file 'E' was deleted in local [dest] but was modified in other [source]. You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved. What do you want to do? u unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ echo F > E $ hg resolve -m (no more unresolved files) continue: hg rebase --continue $ hg rebase -c - rebasing 6:c82b08f646f1 "F" (F) - rebasing 7:a6db7fa104e1 "G" (G) - rebasing 8:e1d201b72d91 "H" (H tip) + rebasing 6:c82b08f646f1 F "F" + rebasing 7:a6db7fa104e1 G "G" + rebasing 8:e1d201b72d91 H tip "H" saved backup bundle to $TESTTMP/external-parent/.hg/strip-backup/c82b08f646f1-f2721fbf-rebase.hg $ hg tglog @@ -347,8 +347,8 @@ > A > EOF $ hg rebase --collapse -r 'B+C' -d D - rebasing 1:fc2b737bb2e5 "B" (B) - rebasing 2:dc0947a82db8 "C" (C) + rebasing 1:fc2b737bb2e5 B "B" + rebasing 2:dc0947a82db8 C "C" saved backup bundle to $TESTTMP/multiple-bases/.hg/strip-backup/dc0947a82db8-b0c1a7ea-rebase.hg $ hg tglog o 2: 2127ae44d291 'Collapsed revision @@ -424,10 +424,10 @@ $ hg rebase -s B --collapse --dest F - rebasing 1:112478962961 "B" (B) - rebasing 3:26805aba1e60 "C" (C) - rebasing 4:be0ef73c17ad "D" (D) - rebasing 5:02c4367d6973 "E" (E tip) + rebasing 1:112478962961 B "B" + rebasing 3:26805aba1e60 C "C" + rebasing 4:be0ef73c17ad D "D" + rebasing 5:02c4367d6973 E tip "E" saved backup bundle to $TESTTMP/internal-merge/.hg/strip-backup/112478962961-1dfb057b-rebase.hg $ hg tglog @@ -514,7 +514,7 @@ merging a and d to d merging b and e to e merging c and f to f - rebasing 3:338e84e2e558 "move2" (tip) + rebasing 3:338e84e2e558 tip "move2" merging f and c to c merging e and g to g saved backup bundle to $TESTTMP/copies/.hg/strip-backup/6e7340ee38c0-ef8ef003-rebase.hg @@ -551,13 +551,13 @@ $ hg rebase --collapse -r 1 -d 0 abort: cannot rebase changeset with children (use --keep to keep original changesets) - [255] + [10] Test collapsing in place $ hg rebase --collapse -b . -d 0 rebasing 1:1352765a01d4 "change" - rebasing 2:64b456429f67 "Collapsed revision" (tip) + rebasing 2:64b456429f67 tip "Collapsed revision" saved backup bundle to $TESTTMP/copies/.hg/strip-backup/1352765a01d4-45a352ea-rebase.hg $ hg st --change tip --copies M a @@ -631,7 +631,7 @@ $ hg book foo $ hg rebase -d 0 -r "1::2" --collapse -m collapsed rebasing 1:6d8d9f24eec3 "a" - rebasing 2:1cc73eca5ecc "b" (foo tip) + rebasing 2:1cc73eca5ecc foo tip "b" saved backup bundle to $TESTTMP/collapseaddremove/.hg/strip-backup/6d8d9f24eec3-77d3b6e2-rebase.hg $ hg log -G --template "{rev}: '{desc}' {bookmarks}" @ 1: 'collapsed' foo @@ -655,17 +655,17 @@ > A > EOF $ hg rebase --collapse -m "new message" -b B -d C - rebasing 1:81e5401e4d37 "B" (B) + rebasing 1:81e5401e4d37 B "B" merging A warning: conflicts while merging A! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ rm A.orig $ hg resolve --mark A (no more unresolved files) continue: hg rebase --continue $ hg rebase --continue - rebasing 1:81e5401e4d37 "B" (B) + rebasing 1:81e5401e4d37 B "B" saved backup bundle to $TESTTMP/collapse_remember_message/.hg/strip-backup/81e5401e4d37-96c3dd30-rebase.hg $ hg log changeset: 2:17186933e123 @@ -702,11 +702,11 @@ > A > EOF $ hg rebase --collapse -t internal:merge3 -s B -d D - rebasing 1:f899f3910ce7 "B" (B) + rebasing 1:f899f3910ce7 B "B" merging A warning: conflicts while merging A! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg tglog o 3: 63668d570d21 'C' | @@ -729,12 +729,12 @@ (no more unresolved files) continue: hg rebase --continue $ hg rebase --continue - rebasing 1:f899f3910ce7 "B" (B) - rebasing 3:63668d570d21 "C" (C tip) + rebasing 1:f899f3910ce7 B "B" + rebasing 3:63668d570d21 C tip "C" merging A warning: conflicts while merging A! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg tglog % 3: 63668d570d21 'C' | @@ -757,10 +757,10 @@ (no more unresolved files) continue: hg rebase --continue $ HGEDITOR=false hg rebase --continue --config ui.interactive=1 - already rebased 1:f899f3910ce7 "B" (B) as 82b8abf9c185 - rebasing 3:63668d570d21 "C" (C tip) + already rebased 1:f899f3910ce7 B "B" as 82b8abf9c185 + rebasing 3:63668d570d21 C tip "C" abort: edit failed: false exited with status 1 - [255] + [250] $ hg tglog o 3: 63668d570d21 'C' | @@ -771,6 +771,6 @@ o 0: 4a2df7238c3b 'A' $ hg rebase --continue - already rebased 1:f899f3910ce7 "B" (B) as 82b8abf9c185 - already rebased 3:63668d570d21 "C" (C tip) as 82b8abf9c185 + already rebased 1:f899f3910ce7 B "B" as 82b8abf9c185 + already rebased 3:63668d570d21 C tip "C" as 82b8abf9c185 saved backup bundle to $TESTTMP/aborted-editor/.hg/strip-backup/f899f3910ce7-7cab5e15-rebase.hg
--- a/tests/test-rebase-conflicts.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-conflicts.t Thu Dec 03 14:15:39 2020 -0500 @@ -57,7 +57,7 @@ $ hg rebase --continue abort: no rebase in progress - [255] + [20] Conflicting rebase: @@ -67,7 +67,7 @@ merging common warning: conflicts while merging common! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg status --config commands.status.verbose=1 M common @@ -89,7 +89,7 @@ $ hg rebase --continue abort: unresolved merge conflicts (see 'hg help resolve') - [255] + [20] Conclude rebase: @@ -100,7 +100,7 @@ $ hg rebase --continue already rebased 3:3163e20567cc "L1" as 3e046f2ecedb rebasing 4:46f0b057b5c0 "L2" - rebasing 5:8029388f38dc "L3" (mybook) + rebasing 5:8029388f38dc mybook "L3" saved backup bundle to $TESTTMP/a/.hg/strip-backup/3163e20567cc-5ca4656e-rebase.hg $ hg tglog @@ -261,7 +261,7 @@ updating the branch cache rebased as 19c888675e13 rebase status stored - rebasing 10:2f2496ddf49d "merge" (tip) + rebasing 10:2f2496ddf49d tip "merge" future parents are 11 and 7 already in destination merge against 10:2f2496ddf49d @@ -341,11 +341,11 @@ $ echo c >> a $ hg commit -q -m 'abc' $ hg rebase -s 7bc217434fc1 -d ab --keep - rebasing 13:7bc217434fc1 "abc" (tip) + rebasing 13:7bc217434fc1 tip "abc" merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg diff diff -r 328e4ab1f7cc a --- a/a Thu Jan 01 00:00:00 1970 +0000 @@ -361,11 +361,11 @@ rebase aborted $ hg up -q -C 7bc217434fc1 $ hg rebase -s . -d ab --keep -t internal:merge3 - rebasing 13:7bc217434fc1 "abc" (tip) + rebasing 13:7bc217434fc1 tip "abc" merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg diff diff -r 328e4ab1f7cc a --- a/a Thu Jan 01 00:00:00 1970 +0000 @@ -399,19 +399,19 @@ $ echo 3 > B $ hg commit --amend -m E -A B -q $ hg rebase -r B+D -d . --config experimental.evolution=true - rebasing 1:112478962961 "B" (B) + rebasing 1:112478962961 B "B" merging B warning: conflicts while merging B! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ echo 4 > B $ hg resolve -m (no more unresolved files) continue: hg rebase --continue $ hg rebase --continue --config experimental.evolution=none - rebasing 1:112478962961 "B" (B) - rebasing 3:f585351a92f8 "D" (D) + rebasing 1:112478962961 B "B" + rebasing 3:f585351a92f8 D "D" warning: orphaned descendants detected, not stripping 112478962961 saved backup bundle to $TESTTMP/b/.hg/strip-backup/f585351a92f8-e536a9e4-rebase.hg @@ -448,14 +448,14 @@ $ hg co F 5 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg rebase -d B - rebasing 2:dc0947a82db8 "C" (C) - rebasing 3:e7b3f00ed42e "D" (D) - rebasing 4:03ca77807e91 "E" (E) - rebasing 5:9a6b91dc2044 "F" (F tip) + rebasing 2:dc0947a82db8 C "C" + rebasing 3:e7b3f00ed42e D "D" + rebasing 4:03ca77807e91 E "E" + rebasing 5:9a6b91dc2044 F tip "F" merging conflict warning: conflicts while merging conflict! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg tglog @ 8:draft 'E' | @@ -480,10 +480,10 @@ (no more unresolved files) continue: hg rebase --continue $ hg rebase -c - already rebased 2:dc0947a82db8 "C" (C) as 0199610c343e - already rebased 3:e7b3f00ed42e "D" (D) as f0dd538aaa63 - already rebased 4:03ca77807e91 "E" (E) as cbf25af8347d - rebasing 5:9a6b91dc2044 "F" (F) + already rebased 2:dc0947a82db8 C "C" as 0199610c343e + already rebased 3:e7b3f00ed42e D "D" as f0dd538aaa63 + already rebased 4:03ca77807e91 E "E" as cbf25af8347d + rebasing 5:9a6b91dc2044 F "F" saved backup bundle to $TESTTMP/conflict-in-merge/.hg/strip-backup/dc0947a82db8-ca7e7d5b-rebase.hg $ hg tglog @ 5:draft 'F'
--- a/tests/test-rebase-dest.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-dest.t Thu Dec 03 14:15:39 2020 -0500 @@ -20,15 +20,15 @@ (use: hg rebase -d REV) [255] $ hg rebase -d 1 - rebasing 2:5db65b93a12b "cc" (tip) + rebasing 2:5db65b93a12b tip "cc" saved backup bundle to $TESTTMP/repo/.hg/strip-backup/5db65b93a12b-4fb789ec-rebase.hg $ hg rebase -d 0 -r . -q $ HGPLAIN=1 hg rebase - rebasing 2:889b0bc6a730 "cc" (tip) + rebasing 2:889b0bc6a730 tip "cc" saved backup bundle to $TESTTMP/repo/.hg/strip-backup/889b0bc6a730-41ec4f81-rebase.hg $ hg rebase -d 0 -r . -q $ hg --config commands.rebase.requiredest=False rebase - rebasing 2:279de9495438 "cc" (tip) + rebasing 2:279de9495438 tip "cc" saved backup bundle to $TESTTMP/repo/.hg/strip-backup/279de9495438-ab0a5128-rebase.hg Requiring dest should not break continue or other rebase options @@ -45,17 +45,17 @@ o 0 aa $ hg rebase -d 2 - rebasing 3:0537f6b50def "dc" (tip) + rebasing 3:0537f6b50def tip "dc" merging c warning: conflicts while merging c! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ echo d > c $ hg resolve --mark --all (no more unresolved files) continue: hg rebase --continue $ hg rebase --continue - rebasing 3:0537f6b50def "dc" (tip) + rebasing 3:0537f6b50def tip "dc" saved backup bundle to $TESTTMP/repo/.hg/strip-backup/0537f6b50def-be4c7386-rebase.hg $ cd .. @@ -161,7 +161,7 @@ > | | > A D > EOS - abort: unknown revision 'SRC'! + abort: unknown revision 'SRC' [255] Rebase to null should work: @@ -171,9 +171,9 @@ > | | > A B > EOS - already rebased 0:426bada5c675 "A" (A) - already rebased 2:dc0947a82db8 "C" (C) - rebasing 3:004dc1679908 "D" (D tip) + already rebased 0:426bada5c675 A "A" + already rebased 2:dc0947a82db8 C "C" + rebasing 3:004dc1679908 D tip "D" o 4: d8d8601abd5e D o 2: dc0947a82db8 C @@ -227,10 +227,10 @@ > | | > A D > EOS - rebasing 2:112478962961 "B" (B) - rebasing 4:26805aba1e60 "C" (C) - rebasing 3:cd488e83d208 "E" (E) - rebasing 5:0069ba24938a "F" (F tip) + rebasing 2:112478962961 B "B" + rebasing 4:26805aba1e60 C "C" + rebasing 3:cd488e83d208 E "E" + rebasing 5:0069ba24938a F tip "F" o 9: d150ff263fc8 F | o 8: 66f30a1a2eab E @@ -254,8 +254,8 @@ > |\| > A D > EOS - rebasing 3:a4256619d830 "B" (B) - rebasing 6:8e139e245220 "C" (C tip) + rebasing 3:a4256619d830 B "B" + rebasing 6:8e139e245220 C tip "C" o 8: d7d1169e9b1c C |\ | o 7: 2ed0c8546285 B @@ -283,9 +283,9 @@ > |/ > A > EOS - rebasing 4:33441538d4aa "F" (F) - rebasing 6:cf43ad9da869 "G" (G) - rebasing 7:eef94f3b5f03 "H" (H tip) + rebasing 4:33441538d4aa F "F" + rebasing 6:cf43ad9da869 G "G" + rebasing 7:eef94f3b5f03 H tip "H" o 10: b3d84c6666cf H | | o 5: f585351a92f8 D @@ -309,8 +309,8 @@ > \|/ > A > EOS - rebasing 2:dc0947a82db8 "C" (C) - rebasing 1:112478962961 "B" (B) + rebasing 2:dc0947a82db8 C "C" + rebasing 1:112478962961 B "B" o 5: 5fe9935d5222 B | o 4: 12d20731b9e0 C @@ -352,11 +352,11 @@ > \|/ > A > EOS - already rebased 1:112478962961 "B" (B) - already rebased 2:dc0947a82db8 "C" (C) - already rebased 3:b18e25de2cf5 "D" (D) - already rebased 4:312782b8f06e "E" (E) - already rebased 5:ad6717a6a58e "F" (F tip) + already rebased 1:112478962961 B "B" + already rebased 2:dc0947a82db8 C "C" + already rebased 3:b18e25de2cf5 D "D" + already rebased 4:312782b8f06e E "E" + already rebased 5:ad6717a6a58e F tip "F" o 5: ad6717a6a58e F | o 3: b18e25de2cf5 D @@ -380,17 +380,17 @@ > \| | > A H > EOS - rebasing 4:701514e1408d "I" (I) - rebasing 0:426bada5c675 "A" (A) - rebasing 1:e7050b6e5048 "H" (H) - rebasing 5:26805aba1e60 "C" (C) - rebasing 7:cf89f86b485b "J" (J) - rebasing 2:112478962961 "B" (B) - rebasing 3:7fb047a69f22 "E" (E) - rebasing 8:f585351a92f8 "D" (D) - rebasing 10:ae41898d7875 "K" (K tip) - rebasing 9:711f53bbef0b "G" (G) - rebasing 6:64a8289d2492 "F" (F) + rebasing 4:701514e1408d I "I" + rebasing 0:426bada5c675 A "A" + rebasing 1:e7050b6e5048 H "H" + rebasing 5:26805aba1e60 C "C" + rebasing 7:cf89f86b485b J "J" + rebasing 2:112478962961 B "B" + rebasing 3:7fb047a69f22 E "E" + rebasing 8:f585351a92f8 D "D" + rebasing 10:ae41898d7875 K tip "K" + rebasing 9:711f53bbef0b G "G" + rebasing 6:64a8289d2492 F "F" o 21: 3735afb3713a F | o 20: 07698142d7a7 G @@ -433,12 +433,12 @@ > A > EOF 6 new orphan changesets - rebasing 16:5c432343bf59 "J" (J tip) - rebasing 3:26805aba1e60 "C" (C) - rebasing 6:f585351a92f8 "D" (D) - rebasing 10:ffebc37c5d0b "E3" (E3) - rebasing 13:fb184bcfeee8 "F2" (F2) - rebasing 11:dc838ab4c0da "G" (G) + rebasing 16:5c432343bf59 J tip "J" + rebasing 3:26805aba1e60 C "C" + rebasing 6:f585351a92f8 D "D" + rebasing 10:ffebc37c5d0b E3 "E3" + rebasing 13:fb184bcfeee8 F2 "F2" + rebasing 11:dc838ab4c0da G "G" o 22: 174f63d574a8 G | o 21: c9d9fbe76705 F2
--- a/tests/test-rebase-detach.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-detach.t Thu Dec 03 14:15:39 2020 -0500 @@ -24,7 +24,7 @@ $ hg phase --force --secret D $ hg rebase -s D -d B - rebasing 3:e7b3f00ed42e "D" (D tip) + rebasing 3:e7b3f00ed42e D tip "D" saved backup bundle to $TESTTMP/a1/.hg/strip-backup/e7b3f00ed42e-6f368371-rebase.hg $ hg log -G --template "{rev}:{phase} '{desc}' {branches}\n" @@ -60,8 +60,8 @@ > EOF $ hg rebase -s D -d B - rebasing 3:e7b3f00ed42e "D" (D) - rebasing 4:69a34c08022a "E" (E tip) + rebasing 3:e7b3f00ed42e D "D" + rebasing 4:69a34c08022a E tip "E" saved backup bundle to $TESTTMP/a2/.hg/strip-backup/e7b3f00ed42e-a2ec7cea-rebase.hg $ hg tglog @@ -97,8 +97,8 @@ > EOF $ hg rebase -s C -d B - rebasing 2:dc0947a82db8 "C" (C) - rebasing 3:e7b3f00ed42e "D" (D tip) + rebasing 2:dc0947a82db8 C "C" + rebasing 3:e7b3f00ed42e D tip "D" saved backup bundle to $TESTTMP/a3/.hg/strip-backup/dc0947a82db8-b8481714-rebase.hg $ hg tglog @@ -136,8 +136,8 @@ $ hg phase --force --secret E $ hg rebase --collapse -s D -d B - rebasing 3:e7b3f00ed42e "D" (D) - rebasing 4:69a34c08022a "E" (E tip) + rebasing 3:e7b3f00ed42e D "D" + rebasing 4:69a34c08022a E tip "E" saved backup bundle to $TESTTMP/a4/.hg/strip-backup/e7b3f00ed42e-a2ec7cea-rebase.hg $ hg log -G --template "{rev}:{phase} '{desc}' {branches}\n" @@ -173,9 +173,9 @@ > EOF $ hg rebase -s C -d B - rebasing 2:dc0947a82db8 "C" (C) - rebasing 3:e7b3f00ed42e "D" (D) - rebasing 4:69a34c08022a "E" (E tip) + rebasing 2:dc0947a82db8 C "C" + rebasing 3:e7b3f00ed42e D "D" + rebasing 4:69a34c08022a E tip "E" saved backup bundle to $TESTTMP/a5/.hg/strip-backup/dc0947a82db8-3eefec98-rebase.hg $ hg tglog @@ -191,7 +191,7 @@ $ hg rebase -d 1 -s 3 rebasing 3:e9153d36a1af "D" - rebasing 4:e3d0c70d606d "E" (tip) + rebasing 4:e3d0c70d606d tip "E" saved backup bundle to $TESTTMP/a5/.hg/strip-backup/e9153d36a1af-db7388ed-rebase.hg $ hg tglog o 4: 2c24e540eccd 'E' @@ -248,9 +248,9 @@ o 0: 426bada5c675 'A' $ hg rebase -s I -d H --collapse --config ui.merge=internal:other - rebasing 5:b92d164ad3cb "I" (I) + rebasing 5:b92d164ad3cb I "I" rebasing 6:0cfbc7e8faaf "Merge" - rebasing 7:c6aaf0d259c0 "J" (tip) + rebasing 7:c6aaf0d259c0 tip "J" saved backup bundle to $TESTTMP/a6/.hg/strip-backup/b92d164ad3cb-88fd7ab7-rebase.hg $ hg tglog @@ -294,17 +294,17 @@ adding B $ hg phase --force --secret . $ hg rebase -s . -d B --config ui.merge=internal:merge - rebasing 3:17b4880d2402 "B2" (tip) + rebasing 3:17b4880d2402 tip "B2" merging B warning: conflicts while merging B! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg resolve --all -t internal:local (no more unresolved files) continue: hg rebase --continue $ hg rebase -c - rebasing 3:17b4880d2402 "B2" (tip) - note: not rebasing 3:17b4880d2402 "B2" (tip), its destination already has all its changes + rebasing 3:17b4880d2402 tip "B2" + note: not rebasing 3:17b4880d2402 tip "B2", its destination already has all its changes saved backup bundle to $TESTTMP/a7/.hg/strip-backup/17b4880d2402-1ae1f6cc-rebase.hg $ hg log -G --template "{rev}:{phase} '{desc}' {branches}\n" o 2:draft 'C'
--- a/tests/test-rebase-empty-successor.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-empty-successor.t Thu Dec 03 14:15:39 2020 -0500 @@ -24,15 +24,15 @@ $ hg rebase -s 2 -d 1 --config rewrite.empty-successor=skip --dry-run starting dry-run rebase; repository will not be changed - rebasing 2:6e2aad5e0f3c "b2" (tip) - note: not rebasing 2:6e2aad5e0f3c "b2" (tip), its destination already has all its changes + rebasing 2:6e2aad5e0f3c tip "b2" + note: not rebasing 2:6e2aad5e0f3c tip "b2", its destination already has all its changes dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase With rewrite.empty-successor=keep, b2 will be recreated although it became empty. $ hg rebase -s 2 -d 1 --config rewrite.empty-successor=keep - rebasing 2:6e2aad5e0f3c "b2" (tip) - note: created empty successor for 2:6e2aad5e0f3c "b2" (tip), its destination already has all its changes + rebasing 2:6e2aad5e0f3c tip "b2" + note: created empty successor for 2:6e2aad5e0f3c tip "b2", its destination already has all its changes saved backup bundle to $TESTTMP/.hg/strip-backup/6e2aad5e0f3c-7d7c8801-rebase.hg $ hg tglog
--- a/tests/test-rebase-emptycommit.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-emptycommit.t Thu Dec 03 14:15:39 2020 -0500 @@ -50,10 +50,10 @@ With --keep, bookmark should move $ hg rebase -r 3+4 -d E --keep - rebasing 3:e7b3f00ed42e "D" (BOOK-D) - note: not rebasing 3:e7b3f00ed42e "D" (BOOK-D), its destination already has all its changes - rebasing 4:69a34c08022a "E" (BOOK-E) - note: not rebasing 4:69a34c08022a "E" (BOOK-E), its destination already has all its changes + rebasing 3:e7b3f00ed42e BOOK-D "D" + note: not rebasing 3:e7b3f00ed42e BOOK-D "D", its destination already has all its changes + rebasing 4:69a34c08022a BOOK-E "E" + note: not rebasing 4:69a34c08022a BOOK-E "E", its destination already has all its changes $ hg log -G -T '{rev} {desc} {bookmarks}' o 7 E BOOK-D BOOK-E | @@ -82,12 +82,12 @@ "BOOK-D", and "BOOK-E" include changes introduced by "C". $ hg rebase -s 2 -d E - rebasing 2:dc0947a82db8 "C" (BOOK-C C) - rebasing 3:e7b3f00ed42e "D" (BOOK-D) - note: not rebasing 3:e7b3f00ed42e "D" (BOOK-D), its destination already has all its changes - rebasing 4:69a34c08022a "E" (BOOK-E) - note: not rebasing 4:69a34c08022a "E" (BOOK-E), its destination already has all its changes - rebasing 5:6b2aeab91270 "F" (BOOK-F F) + rebasing 2:dc0947a82db8 BOOK-C C "C" + rebasing 3:e7b3f00ed42e BOOK-D "D" + note: not rebasing 3:e7b3f00ed42e BOOK-D "D", its destination already has all its changes + rebasing 4:69a34c08022a BOOK-E "E" + note: not rebasing 4:69a34c08022a BOOK-E "E", its destination already has all its changes + rebasing 5:6b2aeab91270 BOOK-F F "F" saved backup bundle to $TESTTMP/non-merge/.hg/strip-backup/dc0947a82db8-52bb4973-rebase.hg $ hg log -G -T '{rev} {desc} {bookmarks}' o 5 F BOOK-F @@ -139,12 +139,12 @@ $ hg branch foo -q $ hg rebase -r '(A::)-(B::)-A' -d H --keepbranches - rebasing 2:dc0947a82db8 "C" (BOOK-C) - note: not rebasing 2:dc0947a82db8 "C" (BOOK-C), its destination already has all its changes - rebasing 3:b18e25de2cf5 "D" (BOOK-D) - note: not rebasing 3:b18e25de2cf5 "D" (BOOK-D), its destination already has all its changes - rebasing 4:86a1f6686812 "E" (BOOK-E E) - note: not rebasing 4:86a1f6686812 "E" (BOOK-E E), its destination already has all its changes + rebasing 2:dc0947a82db8 BOOK-C "C" + note: not rebasing 2:dc0947a82db8 BOOK-C "C", its destination already has all its changes + rebasing 3:b18e25de2cf5 BOOK-D "D" + note: not rebasing 3:b18e25de2cf5 BOOK-D "D", its destination already has all its changes + rebasing 4:86a1f6686812 BOOK-E E "E" + note: not rebasing 4:86a1f6686812 BOOK-E E "E", its destination already has all its changes saved backup bundle to $TESTTMP/merge1/.hg/strip-backup/b18e25de2cf5-1fd0a4ba-rebase.hg $ hg update null -q @@ -189,13 +189,13 @@ > EOS $ hg rebase -r '(A::)-(B::)-A' -d H - rebasing 2:dc0947a82db8 "C" (BOOK-C) - note: not rebasing 2:dc0947a82db8 "C" (BOOK-C), its destination already has all its changes - rebasing 3:b18e25de2cf5 "D" (BOOK-D D) - rebasing 4:03ca77807e91 "E" (BOOK-E E) - rebasing 5:ad6717a6a58e "F" (BOOK-F) - note: not rebasing 5:ad6717a6a58e "F" (BOOK-F), its destination already has all its changes - rebasing 6:c58e8bdac1f4 "G" (BOOK-G G) + rebasing 2:dc0947a82db8 BOOK-C "C" + note: not rebasing 2:dc0947a82db8 BOOK-C "C", its destination already has all its changes + rebasing 3:b18e25de2cf5 BOOK-D D "D" + rebasing 4:03ca77807e91 BOOK-E E "E" + rebasing 5:ad6717a6a58e BOOK-F "F" + note: not rebasing 5:ad6717a6a58e BOOK-F "F", its destination already has all its changes + rebasing 6:c58e8bdac1f4 BOOK-G G "G" saved backup bundle to $TESTTMP/merge2/.hg/strip-backup/b18e25de2cf5-2d487005-rebase.hg $ hg log -G -T '{rev} {desc} {bookmarks}'
--- a/tests/test-rebase-inmemory.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-inmemory.t Thu Dec 03 14:15:39 2020 -0500 @@ -42,7 +42,7 @@ b (no-eol) $ hg rebase --debug -r b -d c | grep rebasing rebasing in memory - rebasing 2:db0e82a16a62 "b" (b) + rebasing 2:db0e82a16a62 b "b" $ hg tglog o 3: ca58782ad1e4 'b' | @@ -102,7 +102,7 @@ somefile (no-eol) $ hg rebase --debug -s b -d a | grep rebasing rebasing in memory - rebasing 2:db0e82a16a62 "b" (b) + rebasing 2:db0e82a16a62 b "b" $ hg tglog o 3: fc055c3b4d33 'b' | @@ -118,7 +118,7 @@ b (no-eol) $ hg rebase --debug -s 1 -d 3 | grep rebasing rebasing in memory - rebasing 1:02952614a83d "d" (d) + rebasing 1:02952614a83d d "d" rebasing 2:f56b71190a8f "c" $ hg tglog o 3: 753feb6fd12a 'c' @@ -149,7 +149,7 @@ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg rebase -r 3 -d 0 --debug | grep rebasing rebasing in memory - rebasing 3:753feb6fd12a "c" (tip) + rebasing 3:753feb6fd12a tip "c" $ hg tglog @ 3: 844a7de3e617 'c' | @@ -179,7 +179,7 @@ o 0: b173517d0057 'a' $ hg rebase -r . -d 2 - rebasing 4:daf7dfc139cb "a/a" (tip) + rebasing 4:daf7dfc139cb tip "a/a" saved backup bundle to $TESTTMP/repo2/.hg/strip-backup/daf7dfc139cb-fdbfcf4f-rebase.hg $ hg tglog @@ -220,7 +220,7 @@ o 0: b173517d0057 'a' $ hg rebase -r . -d 5 - rebasing 7:855e9797387e "added a back!" (tip) + rebasing 7:855e9797387e tip "added a back!" saved backup bundle to $TESTTMP/repo2/.hg/strip-backup/855e9797387e-81ee4c5d-rebase.hg $ hg tglog @@ -246,7 +246,7 @@ $ hg ci -m 'c/subdir/file.txt' $ hg rebase -r . -d 3 -n starting dry-run rebase; repository will not be changed - rebasing 8:e147e6e3c490 "c/subdir/file.txt" (tip) + rebasing 8:e147e6e3c490 tip "c/subdir/file.txt" abort: error: 'c/subdir/file.txt' conflicts with file 'c' in 3. [255] FIXME: shouldn't need this, but when we hit path conflicts in dryrun mode, we @@ -333,10 +333,10 @@ Make sure it throws error while passing --continue or --abort with --dry-run $ hg rebase -s 2 -d 6 -n --continue abort: cannot specify both --continue and --dry-run - [255] + [10] $ hg rebase -s 2 -d 6 -n --abort abort: cannot specify both --abort and --dry-run - [255] + [10] Check dryrun gives correct results when there is no conflict in rebasing $ hg rebase -s 2 -d 6 -n @@ -465,7 +465,7 @@ merging e warning: conflicts while merging e! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --abort saved backup bundle to $TESTTMP/repo3/.hg/strip-backup/c1e524d4287c-f91f82e1-backup.hg rebase aborted @@ -484,7 +484,7 @@ transaction abort! rollback completed abort: uncommitted changes - [255] + [20] $ cat a dirty $ hg status -v @@ -505,7 +505,7 @@ $ hg rebase -s 2 -d 7 abort: outstanding uncommitted merge (use 'hg commit' or 'hg merge --abort') - [255] + [20] $ hg resolve -l U e @@ -541,13 +541,13 @@ Check it gives error when both --dryrun and --confirm is used: $ hg rebase -s 2 -d . --confirm --dry-run abort: cannot specify both --confirm and --dry-run - [255] + [10] $ hg rebase -s 2 -d . --confirm --abort abort: cannot specify both --abort and --confirm - [255] + [10] $ hg rebase -s 2 -d . --confirm --continue abort: cannot specify both --continue and --confirm - [255] + [10] Test --confirm option when there are no conflicts: $ hg rebase -s 2 -d . --keep --config ui.interactive=True --confirm << EOF @@ -711,7 +711,7 @@ $ hg ci -qAm 'add +x to foo.txt' issue5960: this was raising an AttributeError exception $ hg rebase -r . -d 1 - rebasing 2:539b93e77479 "add +x to foo.txt" (tip) + rebasing 2:539b93e77479 tip "add +x to foo.txt" saved backup bundle to $TESTTMP/no_exception/.hg/strip-backup/*.hg (glob) $ hg diff -c tip diff --git a/foo.txt b/foo.txt @@ -774,7 +774,7 @@ $ hg mv a b $ hg ci -qm 'rename a to b' $ hg rebase -d 1 - rebasing 2:b977edf6f839 "rename a to b" (tip) + rebasing 2:b977edf6f839 tip "rename a to b" merging a and b to b saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/b977edf6f839-0864f570-rebase.hg $ hg st --copies --change . @@ -795,7 +795,7 @@ $ hg mv a b $ hg ci -qm 'rename a to b' $ hg rebase -d 1 - rebasing 2:b977edf6f839 "rename a to b" (tip) + rebasing 2:b977edf6f839 tip "rename a to b" merging a and b to b saved backup bundle to $TESTTMP/rebase-rename-empty/.hg/strip-backup/b977edf6f839-0864f570-rebase.hg $ hg st --copies --change . @@ -815,7 +815,7 @@ $ echo a2 > a $ hg ci -qm 'modify a' $ hg rebase -r . -d 1 --collapse - rebasing 2:41c4ea50d4cf "modify a" (tip) + rebasing 2:41c4ea50d4cf tip "modify a" merging b and a to b saved backup bundle to $TESTTMP/rebase-rename-collapse/.hg/strip-backup/41c4ea50d4cf-b90b7994-rebase.hg $ cd .. @@ -852,13 +852,13 @@ created new head $ hg rebase -r . -d 1 --config ui.merge=internal:merge3 - rebasing 2:fb62b706688e "add b to foo" (tip) + rebasing 2:fb62b706688e tip "add b to foo" merging foo hit merge conflicts; rebasing that commit again in the working copy merging foo warning: conflicts while merging foo! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ cd $TESTTMP @@ -891,11 +891,11 @@ merging foo warning: conflicts while merging foo! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase -r 3 -d 1 -t:merge3 abort: rebase in progress (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') - [255] + [20] $ hg resolve --list U foo $ hg resolve --all --re-merge -t:other @@ -945,7 +945,7 @@ $ hg rebase -s 2 -d 3 rebasing 2:0194f1db184a "b" note: not rebasing 2:0194f1db184a "b", its destination already has all its changes - rebasing 4:59c8292117b1 "merge" (tip) + rebasing 4:59c8292117b1 tip "merge" saved backup bundle to $TESTTMP/keep_merge/.hg/strip-backup/0194f1db184a-aee31d03-rebase.hg $ hg tglog o 3: 506e2454484b 'merge' @@ -971,6 +971,6 @@ $ echo bar > test; hg add test; hg ci -m c created new head $ hg rebase -d 2 -d 1 --tool :local - rebasing 2:ca2749322ee5 "c" (tip) - note: not rebasing 2:ca2749322ee5 "c" (tip), its destination already has all its changes + rebasing 2:ca2749322ee5 tip "c" + note: not rebasing 2:ca2749322ee5 tip "c", its destination already has all its changes saved backup bundle to $TESTTMP/nofilechanges/.hg/strip-backup/ca2749322ee5-6dc7e94b-rebase.hg
--- a/tests/test-rebase-interruptions.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-interruptions.t Thu Dec 03 14:15:39 2020 -0500 @@ -62,7 +62,7 @@ merging A warning: conflicts while merging A! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] Force a commit on C during the interruption: @@ -99,7 +99,7 @@ merging A warning: conflicts while merging A! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] Solve the conflict and go on: @@ -158,7 +158,7 @@ merging A warning: conflicts while merging A! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] Force a commit on B' during the interruption: @@ -230,7 +230,7 @@ merging A warning: conflicts while merging A! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] Change phase on B and B' @@ -303,7 +303,7 @@ merging A warning: conflicts while merging A! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg tglog @ 5: 45396c49d53b 'B' | @@ -348,7 +348,7 @@ $ hg rebase --source 2 --dest 5 --tool internal:other --config 'hooks.precommit=hg status | grep "M A"' rebasing 2:965c486023db "C" M A - rebasing 6:a0b2430ebfb8 "F" (tip) + rebasing 6:a0b2430ebfb8 tip "F" abort: precommit hook exited with status 1 [255] $ hg tglogp @@ -397,7 +397,7 @@ > --config 'hooks.tonative.pretxncommit=True' --config 'hooks.pretxncommit=hg log -r $HG_NODE | grep "summary: C"' rebasing 2:965c486023db "C" summary: C - rebasing 6:a0b2430ebfb8 "F" (tip) + rebasing 6:a0b2430ebfb8 tip "F" transaction abort! rollback completed abort: pretxncommit hook exited with status 1 @@ -447,7 +447,7 @@ $ hg rebase --source 2 --dest 5 --tool internal:other --config 'hooks.pretxnclose=hg log -r tip | grep "summary: C"' rebasing 2:965c486023db "C" summary: C - rebasing 6:a0b2430ebfb8 "F" (tip) + rebasing 6:a0b2430ebfb8 tip "F" transaction abort! rollback completed abort: pretxnclose hook exited with status 1 @@ -506,7 +506,7 @@ merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ echo a > a $ echo c >> a $ hg resolve --mark a @@ -522,18 +522,18 @@ Now try again with --collapse $ hg unbundle -q .hg/strip-backup/fdaca8533b86-7fd70513-rebase.hg $ hg rebase -s 2 -d 1 --noninteractive --collapse - rebasing 2:fdaca8533b86 "b" (tip) + rebasing 2:fdaca8533b86 tip "b" merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ echo a > a $ echo c >> a $ hg resolve --mark a (no more unresolved files) continue: hg rebase --continue $ hg rebase --continue - rebasing 2:fdaca8533b86 "b" (tip) + rebasing 2:fdaca8533b86 tip "b" saved backup bundle to $TESTTMP/repo/.hg/strip-backup/fdaca8533b86-7fd70513-rebase.hg $ hg resolve --list $ test -d .hg/merge
--- a/tests/test-rebase-legacy.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-legacy.t Thu Dec 03 14:15:39 2020 -0500 @@ -58,11 +58,11 @@ #endif $ hg continue - rebasing 4:c1e6b162678d "B" (B) - rebasing 8:6f7a236de685 "D" (D) - rebasing 2:de008c61a447 "E" (E) - rebasing 7:d2fa1c02b240 "G" (G) - rebasing 9:6582e6951a9c "H" (H tip) + rebasing 4:c1e6b162678d B "B" + rebasing 8:6f7a236de685 D "D" + rebasing 2:de008c61a447 E "E" + rebasing 7:d2fa1c02b240 G "G" + rebasing 9:6582e6951a9c H tip "H" warning: orphaned descendants detected, not stripping c1e6b162678d, de008c61a447 saved backup bundle to $TESTTMP/.hg/strip-backup/6f7a236de685-9880a3dc-rebase.hg
--- a/tests/test-rebase-mq-skip.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-mq-skip.t Thu Dec 03 14:15:39 2020 -0500 @@ -57,7 +57,7 @@ $ hg up -q -C qtip $ hg rebase -v - rebasing 2:13a46ce44f60 "P0" (p0.patch qbase) + rebasing 2:13a46ce44f60 p0.patch qbase "P0" resolving manifests removing p0 getting r1 @@ -67,9 +67,9 @@ p0 committing manifest committing changelog - rebasing 3:148775c71080 "P1" (p1.patch qtip) + rebasing 3:148775c71080 p1.patch qtip "P1" resolving manifests - note: not rebasing 3:148775c71080 "P1" (p1.patch qtip), its destination already has all its changes + note: not rebasing 3:148775c71080 p1.patch qtip "P1", its destination already has all its changes rebase merging completed updating mq patch p0.patch to 5:9ecc820b1737 $TESTTMP/a/.hg/patches/p0.patch @@ -149,28 +149,28 @@ $ hg up -q qtip $ HGMERGE=internal:fail hg rebase - rebasing 1:b4bffa6e4776 "r1" (qbase r1) - note: not rebasing 1:b4bffa6e4776 "r1" (qbase r1), its destination already has all its changes - rebasing 2:c0fd129beb01 "r2" (r2) - rebasing 3:6ff5b8feed8e "r3" (r3) - note: not rebasing 3:6ff5b8feed8e "r3" (r3), its destination already has all its changes - rebasing 4:094320fec554 "r4" (r4) + rebasing 1:b4bffa6e4776 qbase r1 "r1" + note: not rebasing 1:b4bffa6e4776 qbase r1 "r1", its destination already has all its changes + rebasing 2:c0fd129beb01 r2 "r2" + rebasing 3:6ff5b8feed8e r3 "r3" + note: not rebasing 3:6ff5b8feed8e r3 "r3", its destination already has all its changes + rebasing 4:094320fec554 r4 "r4" unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ HGMERGE=internal:local hg resolve --all (no more unresolved files) continue: hg rebase --continue $ hg continue - already rebased 1:b4bffa6e4776 "r1" (qbase r1) as 057f55ff8f44 - already rebased 2:c0fd129beb01 "r2" (r2) as 1660ab13ce9a - already rebased 3:6ff5b8feed8e "r3" (r3) as 1660ab13ce9a - rebasing 4:094320fec554 "r4" (r4) - note: not rebasing 4:094320fec554 "r4" (r4), its destination already has all its changes - rebasing 5:681a378595ba "r5" (r5) - rebasing 6:512a1f24768b "r6" (qtip r6) - note: not rebasing 6:512a1f24768b "r6" (qtip r6), its destination already has all its changes + already rebased 1:b4bffa6e4776 qbase r1 "r1" as 057f55ff8f44 + already rebased 2:c0fd129beb01 r2 "r2" as 1660ab13ce9a + already rebased 3:6ff5b8feed8e r3 "r3" as 1660ab13ce9a + rebasing 4:094320fec554 r4 "r4" + note: not rebasing 4:094320fec554 r4 "r4", its destination already has all its changes + rebasing 5:681a378595ba r5 "r5" + rebasing 6:512a1f24768b qtip r6 "r6" + note: not rebasing 6:512a1f24768b qtip r6 "r6", its destination already has all its changes saved backup bundle to $TESTTMP/b/.hg/strip-backup/b4bffa6e4776-b9bfb84d-rebase.hg $ hg tglog
--- a/tests/test-rebase-mq.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-mq.t Thu Dec 03 14:15:39 2020 -0500 @@ -59,11 +59,11 @@ Rebase - generate a conflict: $ hg rebase -s 2 -d 1 - rebasing 2:3504f44bffc0 "P0" (f.patch qbase) + rebasing 2:3504f44bffc0 f.patch qbase "P0" merging f warning: conflicts while merging f! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] Fix the 1st conflict: @@ -72,12 +72,12 @@ (no more unresolved files) continue: hg rebase --continue $ hg rebase -c - rebasing 2:3504f44bffc0 "P0" (f.patch qbase) - rebasing 3:929394423cd3 "P1" (f2.patch qtip tip) + rebasing 2:3504f44bffc0 f.patch qbase "P0" + rebasing 3:929394423cd3 f2.patch qtip tip "P1" merging f warning: conflicts while merging f! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] Fix the 2nd conflict: @@ -86,8 +86,8 @@ (no more unresolved files) continue: hg rebase --continue $ hg rebase -c - already rebased 2:3504f44bffc0 "P0" (f.patch qbase) as ebe9914c0d1c - rebasing 3:929394423cd3 "P1" (f2.patch qtip) + already rebased 2:3504f44bffc0 f.patch qbase "P0" as ebe9914c0d1c + rebasing 3:929394423cd3 f2.patch qtip "P1" saved backup bundle to $TESTTMP/a/.hg/strip-backup/3504f44bffc0-30595b40-rebase.hg $ hg tglog @@ -203,8 +203,8 @@ Rebase the applied mq patches: $ hg rebase -s 2 -d 1 - rebasing 2:0c587ffcb480 "P0 (git)" (f_git.patch qbase) - rebasing 3:c7f18665e4bc "P1" (f.patch qtip tip) + rebasing 2:0c587ffcb480 f_git.patch qbase "P0 (git)" + rebasing 3:c7f18665e4bc f.patch qtip tip "P1" saved backup bundle to $TESTTMP/a/.hg/strip-backup/0c587ffcb480-0ea5695f-rebase.hg $ hg qci -m 'save patch state' @@ -337,7 +337,7 @@ foo $ [ -f .hg/patches/empty-important ] $ hg -q rebase -d 2 - note: not rebasing 1:0aaf4c3af7eb "important commit message" (empty-important qbase), its destination already has all its changes + note: not rebasing 1:0aaf4c3af7eb empty-important qbase "important commit message", its destination already has all its changes $ hg qseries guarded bar
--- a/tests/test-rebase-named-branches.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-named-branches.t Thu Dec 03 14:15:39 2020 -0500 @@ -72,7 +72,7 @@ rebasing 5:24b6387c8c8c "F" rebasing 6:eea13746799a "G" rebasing 7:02de42196ebe "H" - rebasing 9:cb039b7cae8e "dev-two named branch" (tip) + rebasing 9:cb039b7cae8e tip "dev-two named branch" saved backup bundle to $TESTTMP/a1/.hg/strip-backup/24b6387c8c8c-24cb8001-rebase.hg $ hg tglog @@ -101,7 +101,7 @@ rebasing 6:24de4aff8e28 "F" rebasing 7:4b988a958030 "G" rebasing 8:31d0e4ba75e6 "H" - rebasing 9:9e70cd31750f "dev-two named branch" (tip) + rebasing 9:9e70cd31750f tip "dev-two named branch" saved backup bundle to $TESTTMP/a1/.hg/strip-backup/643fc9128048-c4ee9ef5-rebase.hg $ hg tglog @@ -190,7 +190,7 @@ rebasing 6:679f28760620 "F" rebasing 7:549f007a9f5f "G" rebasing 8:12b2bc666e20 "H" - rebasing 9:71325f8bc082 "dev-two named branch" (tip) + rebasing 9:71325f8bc082 tip "dev-two named branch" saved backup bundle to $TESTTMP/a1/.hg/strip-backup/643fc9128048-6cdd1a52-rebase.hg $ hg tglog @@ -253,7 +253,7 @@ rebasing 6:3944801ae4ea "dev-two named branch" rebasing 7:3bdb949809d9 "B" rebasing 8:a0d543090fa4 "C" - rebasing 9:e9f862ce8bad "D" (tip) + rebasing 9:e9f862ce8bad tip "D" saved backup bundle to $TESTTMP/a1/.hg/strip-backup/3944801ae4ea-fb46ed74-rebase.hg $ hg tglog @@ -344,7 +344,7 @@ $ hg rebase -s tip -d 4 --dry-run starting dry-run rebase; repository will not be changed - rebasing 11:be1dea60f2a6 "D" (tip) + rebasing 11:be1dea60f2a6 tip "D" dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase $ hg diff diff -r 2b586e70108d A @@ -360,7 +360,7 @@ $ echo A-mod > A $ echo n | hg rebase -s tip -d 4 --confirm --config ui.interactive=True starting in-memory rebase - rebasing 11:be1dea60f2a6 "D" (tip) + rebasing 11:be1dea60f2a6 tip "D" rebase completed successfully apply changes (yn)? n $ hg diff @@ -374,7 +374,7 @@ $ echo A-mod > A $ hg rebase -s tip -d 4 --confirm starting in-memory rebase - rebasing 11:be1dea60f2a6 "D" (tip) + rebasing 11:be1dea60f2a6 tip "D" rebase completed successfully apply changes (yn)? y saved backup bundle to $TESTTMP/a1/.hg/strip-backup/be1dea60f2a6-ca6d2dac-rebase.hg @@ -392,7 +392,7 @@ $ hg rebase -s 5 -d 4 --dry-run starting dry-run rebase; repository will not be changed abort: uncommitted changes - [255] + [20] $ hg diff diff -r 2b586e70108d A --- a/A Thu Jan 01 00:00:00 1970 +0000 @@ -406,7 +406,7 @@ $ echo n | hg rebase -s 5 -d 4 --confirm --config ui.interactive=True starting in-memory rebase abort: uncommitted changes - [255] + [20] $ hg diff diff -r 2b586e70108d A --- a/A Thu Jan 01 00:00:00 1970 +0000 @@ -417,7 +417,7 @@ $ hg rebase -s 5 -d 4 --confirm starting in-memory rebase abort: uncommitted changes - [255] + [20] $ hg diff diff -r 2b586e70108d A --- a/A Thu Jan 01 00:00:00 1970 +0000 @@ -527,8 +527,8 @@ marked working directory as branch x $ hg rebase -r 3:: -d . rebasing 3:76abc1c6f8c7 "b1" - rebasing 4:8427af5d86f2 "c2 closed" (tip) - note: not rebasing 4:8427af5d86f2 "c2 closed" (tip), its destination already has all its changes + rebasing 4:8427af5d86f2 tip "c2 closed" + note: not rebasing 4:8427af5d86f2 tip "c2 closed", its destination already has all its changes saved backup bundle to $TESTTMP/case2/.hg/strip-backup/76abc1c6f8c7-cd698d13-rebase.hg $ hg tglog o 3: 117b0ed08075 'b1' x
--- a/tests/test-rebase-newancestor.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-newancestor.t Thu Dec 03 14:15:39 2020 -0500 @@ -251,7 +251,7 @@ $ echo 'other change while merging future "rebase ancestors"' > other $ hg ci -Aqm 'merge rebase ancestors' $ hg rebase -d 5 -v - rebasing 6:4c5f12f25ebe "merge rebase ancestors" (tip) + rebasing 6:4c5f12f25ebe tip "merge rebase ancestors" resolving manifests removing other resolving manifests @@ -310,9 +310,9 @@ > R > EOS $ hg rebase -r D+E+F -d Z - rebasing 5:5f2c926dfecf "D" (D) - rebasing 6:b296604d9846 "E" (E) - rebasing 7:caa9781e507d "F" (F tip) + rebasing 5:5f2c926dfecf D "D" + rebasing 6:b296604d9846 E "E" + rebasing 7:caa9781e507d F tip "F" abort: rebasing 7:caa9781e507d will include unwanted changes from 4:d6003a550c2c or 3:c1e6b162678d [255] @@ -330,9 +330,9 @@ > R > EOS $ hg rebase -r B+C+D -d Z - rebasing 3:c1e6b162678d "B" (B) - rebasing 4:d6003a550c2c "C" (C) - rebasing 5:c8f78076273e "D" (D tip) + rebasing 3:c1e6b162678d B "B" + rebasing 4:d6003a550c2c C "C" + rebasing 5:c8f78076273e D tip "D" saved backup bundle to $TESTTMP/dual-merge-base2/.hg/strip-backup/d6003a550c2c-6f1424b6-rebase.hg $ hg manifest -r 'desc(D)' B @@ -352,8 +352,8 @@ > B C Z > EOS $ hg rebase -r D+F -d Z - rebasing 3:004dc1679908 "D" (D) - rebasing 5:4be4cbf6f206 "F" (F tip) + rebasing 3:004dc1679908 D "D" + rebasing 5:4be4cbf6f206 F tip "F" saved backup bundle to $TESTTMP/chosen-merge-base1/.hg/strip-backup/004dc1679908-06a66a3c-rebase.hg $ hg manifest -r 'desc(F)' C @@ -373,8 +373,8 @@ > B C Z > EOS $ hg rebase -r E+F -d Z - rebasing 4:974e4943c210 "E" (E) - rebasing 5:4be4cbf6f206 "F" (F tip) + rebasing 4:974e4943c210 E "E" + rebasing 5:4be4cbf6f206 F tip "F" saved backup bundle to $TESTTMP/chosen-merge-base2/.hg/strip-backup/974e4943c210-b2874da5-rebase.hg $ hg manifest -r 'desc(F)' B
--- a/tests/test-rebase-obsolete.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-obsolete.t Thu Dec 03 14:15:39 2020 -0500 @@ -5,8 +5,8 @@ Enable obsolete $ cat >> $HGRCPATH << EOF - > [ui] - > logtemplate= {rev}:{node|short} {desc|firstline}{if(obsolete,' ({obsfate})')} + > [command-templates] + > log= {rev}:{node|short} {desc|firstline}{if(obsolete,' ({obsfate})')} > [experimental] > evolution.createmarkers=True > evolution.allowunstable=True @@ -210,7 +210,7 @@ $ hg rebase --source 'desc(B)' --dest 'tip' --config experimental.rebaseskipobsolete=True rebasing 8:8877864f1edb "B" - note: not rebasing 9:08483444fef9 "D", already in destination as 11:4596109a6a43 "D" (tip) + note: not rebasing 9:08483444fef9 "D", already in destination as 11:4596109a6a43 tip "D" rebasing 10:5ae4c968c6ac "C" $ hg debugobsolete 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'} @@ -258,7 +258,7 @@ grafting 11:4596109a6a43 "D" $ hg up -qr 'desc(E)' $ hg rebase -s tip -d . - rebasing 14:9e36056a46e3 "D" (tip) + rebasing 14:9e36056a46e3 tip "D" $ hg log --style default --debug -r tip changeset: 15:627d4614809036ba22b9e7cb31638ddc06ab99ab tag: tip @@ -488,7 +488,7 @@ $ cd stabilize $ hg rebase --auto-orphans '0::' -d 10 abort: cannot specify both --auto-orphans and --dest - [255] + [10] $ hg rebase --auto-orphans '0::' rebasing 9:cf44d2f5a9f4 "D" $ hg log -G @@ -518,7 +518,7 @@ $ hg rebase --dest 4 --rev '7+11+9' rebasing 9:cf44d2f5a9f4 "D" rebasing 7:02de42196ebe "H" - rebasing 11:0d8f238b634c "C" (tip) + rebasing 11:0d8f238b634c tip "C" $ hg log -G o 14:1e8370e38cca C | @@ -556,9 +556,9 @@ > EOF $ hg rebase -d G -r 'B + D + F' - rebasing 1:112478962961 "B" (B) - rebasing 2:b18e25de2cf5 "D" (D) - rebasing 6:f15c3adaf214 "F" (F tip) + rebasing 1:112478962961 B "B" + rebasing 2:b18e25de2cf5 D "D" + rebasing 6:f15c3adaf214 F tip "F" abort: cannot rebase 6:f15c3adaf214 without moving at least one of its parents [255] @@ -612,7 +612,7 @@ $ hg rebase --dest 6 --rev '((desc(H) + desc(D))::) - desc(M)' rebasing 3:32af7686d403 "D" rebasing 7:02de42196ebe "H" - rebasing 9:4bde274eefcf "I" (tip) + rebasing 9:4bde274eefcf tip "I" 1 new orphan changesets $ hg log -G @ 12:acd174b7ab39 I @@ -656,7 +656,7 @@ $ hg rebase --rev .~1::. --dest 'max(desc(D))' --traceback --config experimental.rebaseskipobsolete=off rebasing 9:4bde274eefcf "I" - rebasing 13:06edfc82198f "J" (tip) + rebasing 13:06edfc82198f tip "J" 2 new content-divergent changesets $ hg log -G @ 15:5ae8a643467b J @@ -787,7 +787,7 @@ $ hg rebase -d 'desc(B2)' note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 3:261e70097290 "B2" - rebasing 4:212cb178bcbb "C" (tip) + rebasing 4:212cb178bcbb tip "C" Even when the chain include missing node @@ -816,7 +816,7 @@ $ hg rebase -d 'desc(B2)' note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 2:261e70097290 "B2" - rebasing 5:1a79b7535141 "D" (tip) + rebasing 5:1a79b7535141 tip "D" $ hg up 4 1 files updated, 0 files merged, 1 files removed, 0 files unresolved $ echo "O" > O @@ -845,7 +845,7 @@ $ hg rebase -d 6 -r "4::" rebasing 4:ff2c4d47b71d "C" note: not rebasing 7:360bbaa7d3ce "O", it has no successor - rebasing 8:8d47583e023f "P" (tip) + rebasing 8:8d47583e023f tip "P" If all the changeset to be rebased are obsolete and present in the destination, we should display a friendly error message @@ -885,7 +885,7 @@ o 0:4a2df7238c3b A $ hg rebase -r . -d 10 - note: not rebasing 11:f44da1f4954c "nonrelevant" (tip), it has no successor + note: not rebasing 11:f44da1f4954c tip "nonrelevant", it has no successor If a rebase is going to create divergence, it should abort @@ -970,7 +970,7 @@ $ hg rebase -s 10 -d 12 --config experimental.evolution.allowdivergence=True rebasing 10:121d9e3bc4c6 "P" - rebasing 14:73568ab6879d "bar foo" (tip) + rebasing 14:73568ab6879d tip "bar foo" 2 new content-divergent changesets $ hg summary parent: 16:61bd55f69bc4 tip @@ -1033,7 +1033,7 @@ merging willconflict warning: conflicts while merging willconflict! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg resolve --mark willconflict (no more unresolved files) @@ -1041,7 +1041,7 @@ $ hg rebase --continue rebasing 19:b82fb57ea638 "willconflict second version" note: not rebasing 20:8b31da3c4919 "dummy change", already in destination as 18:601db7a18f51 "dummy change successor" - rebasing 21:7bdc8a87673d "dummy change" (tip) + rebasing 21:7bdc8a87673d tip "dummy change" $ cd .. Divergence cases due to obsolete changesets @@ -1096,11 +1096,11 @@ consequence f (descendant of d) is left behind. $ hg rebase -b 'e' -d 'x' - rebasing 1:488e1b7e7341 "b" (b) - rebasing 3:a82ac2b38757 "c" (c) - rebasing 5:027ad6c5830d "d'" (d') - rebasing 6:d60ebfa0f1cb "e" (e) - note: not rebasing 4:76be324c128b "d" (d) and its descendants as this would cause divergence + rebasing 1:488e1b7e7341 b "b" + rebasing 3:a82ac2b38757 c "c" + rebasing 5:027ad6c5830d d' "d'" + rebasing 6:d60ebfa0f1cb e "e" + note: not rebasing 4:76be324c128b d "d" and its descendants as this would cause divergence $ hg log -G -r 'a':: o 11:eb6d63fc4ed5 e | @@ -1154,9 +1154,9 @@ (to force the rebase please set experimental.evolution.allowdivergence=True) [255] $ hg rebase --config experimental.evolution.allowdivergence=true -r 'c'::'f' -d 'x' - rebasing 3:a82ac2b38757 "c" (c) - rebasing 4:76be324c128b "d" (d) - rebasing 7:1143e9adc121 "f" (f tip) + rebasing 3:a82ac2b38757 c "c" + rebasing 4:76be324c128b d "d" + rebasing 7:1143e9adc121 f tip "f" 1 new orphan changesets 2 new content-divergent changesets $ hg log -G -r 'a':: -T instabilities @@ -1187,9 +1187,9 @@ (Not skipping obsoletes means that divergence is allowed.) $ hg rebase --config experimental.rebaseskipobsolete=false -r 'c'::'f' -d 'x' - rebasing 3:a82ac2b38757 "c" (c) - rebasing 4:76be324c128b "d" (d) - rebasing 7:1143e9adc121 "f" (f tip) + rebasing 3:a82ac2b38757 c "c" + rebasing 4:76be324c128b d "d" + rebasing 7:1143e9adc121 f tip "f" 1 new orphan changesets 2 new content-divergent changesets @@ -1231,12 +1231,12 @@ o 0:b173517d0057 a $ hg rebase -b 'f' -d 'x' - rebasing 1:488e1b7e7341 "b" (b) - rebasing 3:a82ac2b38757 "c" (c) - rebasing 5:63324dc512ea "e'" (e') - rebasing 7:3ffec603ab53 "f" (f) - rebasing 4:76be324c128b "d" (d) - note: not rebasing 6:e36fae928aec "e" (e) and its descendants as this would cause divergence + rebasing 1:488e1b7e7341 b "b" + rebasing 3:a82ac2b38757 c "c" + rebasing 5:63324dc512ea e' "e'" + rebasing 7:3ffec603ab53 f "f" + rebasing 4:76be324c128b d "d" + note: not rebasing 6:e36fae928aec e "e" and its descendants as this would cause divergence $ hg log -G -r 'a': o 13:a1707a5b7c2c d | @@ -1294,7 +1294,7 @@ o 0:b173517d0057 a $ hg rebase -d 0 -r 2 - rebasing 2:a82ac2b38757 "c" (c) + rebasing 2:a82ac2b38757 c "c" $ hg log -G -r 'a': --hidden o 5:69ad416a4a26 c | @@ -1325,8 +1325,8 @@ 1 new orphan changesets $ hg rebase -d B -s D - note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B) - rebasing 4:66f1a38021c9 "F" (F tip) + note: not rebasing 2:b18e25de2cf5 D "D", already in destination as 1:112478962961 B "B" + rebasing 4:66f1a38021c9 F tip "F" $ hg log -G o 5:50e9d60b99c6 F |\ @@ -1357,8 +1357,8 @@ 1 new orphan changesets $ hg rebase -d B -s E - note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B) - rebasing 4:66f1a38021c9 "F" (F tip) + note: not rebasing 3:7fb047a69f22 E "E", already in destination as 1:112478962961 B "B" + rebasing 4:66f1a38021c9 F tip "F" $ hg log -G o 5:aae1787dacee F |\ @@ -1389,8 +1389,8 @@ 1 new orphan changesets $ hg rebase -d C -s D - note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B) - rebasing 5:66f1a38021c9 "F" (F tip) + note: not rebasing 2:b18e25de2cf5 D "D", already in destination as 1:112478962961 B "B" + rebasing 5:66f1a38021c9 F tip "F" $ hg log -G o 6:0913febf6439 F @@ -1424,8 +1424,8 @@ 1 new orphan changesets $ hg rebase -d C -s E - note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B) - rebasing 5:66f1a38021c9 "F" (F tip) + note: not rebasing 3:7fb047a69f22 E "E", already in destination as 1:112478962961 B "B" + rebasing 5:66f1a38021c9 F tip "F" $ hg log -G o 6:c6ab0cc6d220 F |\ @@ -1458,10 +1458,10 @@ 1 new orphan changesets $ hg rebase -d C -b F - rebasing 2:b18e25de2cf5 "D" (D) - note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B) - rebasing 5:66f1a38021c9 "F" (F tip) - note: not rebasing 5:66f1a38021c9 "F" (F tip), its destination already has all its changes + rebasing 2:b18e25de2cf5 D "D" + note: not rebasing 3:7fb047a69f22 E "E", already in destination as 1:112478962961 B "B" + rebasing 5:66f1a38021c9 F tip "F" + note: not rebasing 5:66f1a38021c9 F tip "F", its destination already has all its changes $ hg log -G o 6:8f47515dda15 D | @@ -1494,10 +1494,10 @@ 1 new orphan changesets $ hg rebase -d C -b F - note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B) - rebasing 3:7fb047a69f22 "E" (E) - rebasing 5:66f1a38021c9 "F" (F tip) - note: not rebasing 5:66f1a38021c9 "F" (F tip), its destination already has all its changes + note: not rebasing 2:b18e25de2cf5 D "D", already in destination as 1:112478962961 B "B" + rebasing 3:7fb047a69f22 E "E" + rebasing 5:66f1a38021c9 F tip "F" + note: not rebasing 5:66f1a38021c9 F tip "F", its destination already has all its changes $ hg log -G o 6:533690786a86 E @@ -1531,8 +1531,8 @@ > EOF $ hg rebase -d D -s B - rebasing 1:112478962961 "B" (B) - note: not rebasing 3:26805aba1e60 "C" (C) and its descendants as this would cause divergence + rebasing 1:112478962961 B "B" + note: not rebasing 3:26805aba1e60 C "C" and its descendants as this would cause divergence $ cd .. @@ -1581,9 +1581,9 @@ > EOS 1 new orphan changesets $ hg rebase -r A+B+E -d F - note: not rebasing 4:a3d17304151f "A" (A), already in destination as 0:96cc3511f894 "C" (C) - note: not rebasing 5:b23a2cc00842 "B" (B), already in destination as 1:058c1e1fb10a "D" (D) - rebasing 7:dac5d11c5a7d "E" (E tip) + note: not rebasing 4:a3d17304151f A "A", already in destination as 0:96cc3511f894 C "C" + note: not rebasing 5:b23a2cc00842 B "B", already in destination as 1:058c1e1fb10a D "D" + rebasing 7:dac5d11c5a7d E tip "E" abort: rebasing 7:dac5d11c5a7d will include unwanted changes from 3:59c792af609c, 5:b23a2cc00842 or 2:ba2b7fa7166d, 4:a3d17304151f [255] $ cd .. @@ -1600,9 +1600,9 @@ > EOS 1 new orphan changesets $ hg rebase -r A+B+D -d Z - note: not rebasing 0:426bada5c675 "A" (A), already in destination as 2:96cc3511f894 "C" (C) - rebasing 1:fc2b737bb2e5 "B" (B) - rebasing 3:b8ed089c80ad "D" (D) + note: not rebasing 0:426bada5c675 A "A", already in destination as 2:96cc3511f894 C "C" + rebasing 1:fc2b737bb2e5 B "B" + rebasing 3:b8ed089c80ad D "D" $ rm .hg/localtags $ hg log -G @@ -1631,9 +1631,9 @@ > EOS 1 new orphan changesets $ hg rebase -r B+A+D -d Z - rebasing 0:426bada5c675 "A" (A) - note: not rebasing 1:fc2b737bb2e5 "B" (B), already in destination as 2:96cc3511f894 "C" (C) - rebasing 3:b8ed089c80ad "D" (D) + rebasing 0:426bada5c675 A "A" + note: not rebasing 1:fc2b737bb2e5 B "B", already in destination as 2:96cc3511f894 C "C" + rebasing 3:b8ed089c80ad D "D" $ rm .hg/localtags $ hg log -G @@ -1669,7 +1669,7 @@ adding b created new head $ hg rebase -r 2 -d 1 - rebasing 2:1e9a3c00cbe9 "b" (tip) + rebasing 2:1e9a3c00cbe9 tip "b" $ hg log -r . # working dir is at rev 3 (successor of 2) 3:be1832deae9a b (no-eol) $ hg book -r 2 mybook --hidden # rev 2 has a bookmark on it now @@ -1679,7 +1679,7 @@ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved 2:1e9a3c00cbe9 b (rewritten using rebase as 3:be1832deae9a) (no-eol) $ hg rebase -r 2 -d 3 --config experimental.evolution.track-operation=1 - note: not rebasing 2:1e9a3c00cbe9 "b" (mybook), already in destination as 3:be1832deae9a "b" (tip) + note: not rebasing 2:1e9a3c00cbe9 mybook "b", already in destination as 3:be1832deae9a tip "b" Check that working directory and bookmark was updated to rev 3 although rev 2 was skipped $ hg log -r . @@ -1706,8 +1706,8 @@ $ hg update D1 -q $ hg bookmark book -i $ hg rebase -r B+D1 -d E - rebasing 1:112478962961 "B" (B) - note: not rebasing 5:15ecf15e0114 "D1" (book D1 tip), already in destination as 2:0807738e0be9 "D2" (D2) + rebasing 1:112478962961 B "B" + note: not rebasing 5:15ecf15e0114 book D1 tip "D1", already in destination as 2:0807738e0be9 D2 "D2" 1 new orphan changesets $ hg log -G -T '{desc} {bookmarks}' @ B book @@ -1788,7 +1788,7 @@ merging D warning: conflicts while merging D! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ cp -R . $TESTTMP/hidden-state2 @@ -1819,7 +1819,7 @@ continue: hg rebase --continue $ hg rebase --continue rebasing 1:2ec65233581b "B" - rebasing 3:7829726be4dc "C" (tip) + rebasing 3:7829726be4dc tip "C" $ hg log -G @ 5:1964d5d5b547 C | @@ -1875,7 +1875,7 @@ merging d warning: conflicts while merging d! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --stop 1 new orphan changesets $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n" @@ -1937,7 +1937,7 @@ merging d warning: conflicts while merging d! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --stop abort: cannot remove original changesets with unrebased descendants (either enable obsmarkers to allow unstable revisions or use --keep to keep original changesets) @@ -1955,7 +1955,7 @@ merging d warning: conflicts while merging d! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --stop $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n" o 7:7fffad344617 test @@ -2017,7 +2017,7 @@ merging d warning: conflicts while merging d! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --stop abort: cannot stop in --collapse session [255] @@ -2050,18 +2050,18 @@ merging d warning: conflicts while merging d! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --stop --dry-run abort: cannot specify both --stop and --dry-run - [255] + [10] $ hg rebase -s 3 -d 5 abort: rebase in progress (use 'hg rebase --continue', 'hg rebase --abort', or 'hg rebase --stop') - [255] + [20] $ hg rebase --stop --continue abort: cannot specify both --stop and --continue - [255] + [10] Test --stop moves bookmarks of original revisions to new rebased nodes: ====================================================================== @@ -2112,13 +2112,13 @@ o 0: 1994f17a630e 'A' bookmarks: $ hg rebase -s 1 -d 5 - rebasing 1:6c81ed0049f8 "B" (X) - rebasing 2:49cb3485fa0c "C" (Y) - rebasing 3:67a385d4e6f2 "D" (Z) + rebasing 1:6c81ed0049f8 X "B" + rebasing 2:49cb3485fa0c Y "C" + rebasing 3:67a385d4e6f2 Z "D" merging d warning: conflicts while merging d! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --stop 1 new orphan changesets $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
--- a/tests/test-rebase-parameters.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-parameters.t Thu Dec 03 14:15:39 2020 -0500 @@ -62,7 +62,7 @@ $ hg rebase --continue --abort abort: cannot specify both --abort and --continue - [255] + [10] $ hg rebase --continue --collapse abort: cannot use collapse with continue or abort @@ -70,18 +70,18 @@ $ hg rebase --continue --dest 4 abort: cannot specify both --continue and --dest - [255] + [10] $ hg rebase --base 5 --source 4 abort: cannot specify both --source and --base - [255] + [10] $ hg rebase --rev 5 --source 4 abort: cannot specify both --rev and --source - [255] + [10] $ hg rebase --base 5 --rev 4 abort: cannot specify both --rev and --base - [255] + [10] $ hg rebase --base 6 abort: branch 'default' has 3 heads - please rebase to an explicit rev @@ -451,8 +451,8 @@ $ cd b1 $ hg rebase -s 2 -d 1 --tool internal:local - rebasing 2:e4e3f3546619 "c2b" (tip) - note: not rebasing 2:e4e3f3546619 "c2b" (tip), its destination already has all its changes + rebasing 2:e4e3f3546619 tip "c2b" + note: not rebasing 2:e4e3f3546619 tip "c2b", its destination already has all its changes saved backup bundle to $TESTTMP/b1/.hg/strip-backup/e4e3f3546619-b0841178-rebase.hg $ hg cat c2 @@ -465,7 +465,7 @@ $ cd b2 $ hg rebase -s 2 -d 1 --tool internal:other - rebasing 2:e4e3f3546619 "c2b" (tip) + rebasing 2:e4e3f3546619 tip "c2b" saved backup bundle to $TESTTMP/b2/.hg/strip-backup/e4e3f3546619-b0841178-rebase.hg $ hg cat c2 @@ -478,9 +478,9 @@ $ cd b3 $ hg rebase -s 2 -d 1 --tool internal:fail - rebasing 2:e4e3f3546619 "c2b" (tip) + rebasing 2:e4e3f3546619 tip "c2b" unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg summary parent: 1:56daeba07f4b @@ -500,10 +500,10 @@ $ hg graft --continue abort: no graft in progress (continue: hg rebase --continue) - [255] + [20] $ hg rebase -c --tool internal:fail - rebasing 2:e4e3f3546619 "c2b" (tip) - note: not rebasing 2:e4e3f3546619 "c2b" (tip), its destination already has all its changes + rebasing 2:e4e3f3546619 tip "c2b" + note: not rebasing 2:e4e3f3546619 tip "c2b", its destination already has all its changes saved backup bundle to $TESTTMP/b3/.hg/strip-backup/e4e3f3546619-b0841178-rebase.hg $ hg rebase -i
--- a/tests/test-rebase-partial.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-partial.t Thu Dec 03 14:15:39 2020 -0500 @@ -35,8 +35,8 @@ > |/ > A > EOF - rebasing 2:b18e25de2cf5 "D" (D) - already rebased 3:26805aba1e60 "C" (C tip) + rebasing 2:b18e25de2cf5 D "D" + already rebased 3:26805aba1e60 C tip "C" o 4: fe3b4c6498fa D | | o 3: 26805aba1e60 C @@ -56,8 +56,8 @@ > |/ > A > EOF - rebasing 2:b18e25de2cf5 "D" (D) - rebasing 3:26805aba1e60 "C" (C tip) + rebasing 2:b18e25de2cf5 D "D" + rebasing 3:26805aba1e60 C tip "C" o 4: a2493f4ace65 Collapsed revision | * D | * C @@ -81,11 +81,11 @@ > A > EOF $ hg rebase -r C+D -d B - rebasing 2:ef8c0fe0897b "D" (D) + rebasing 2:ef8c0fe0897b D "D" merging file warning: conflicts while merging file! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg rebase --abort rebase aborted $ hg tglog @@ -111,8 +111,8 @@ > | > A > EOF - already rebased 1:112478962961 "B" (B) - rebasing 3:f585351a92f8 "D" (D tip) + already rebased 1:112478962961 B "B" + rebasing 3:f585351a92f8 D tip "D" o 4: 1e6da8103bc7 D | | x 3: f585351a92f8 D
--- a/tests/test-rebase-pull.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-pull.t Thu Dec 03 14:15:39 2020 -0500 @@ -80,7 +80,7 @@ $ hg pull --rebase abort: uncommitted changes (cannot pull with rebase: please commit or shelve your changes first) - [255] + [20] $ hg update --clean --quiet Abort pull early if another operation (histedit) is in progress: @@ -90,11 +90,11 @@ > EOF Editing (d80cc2da061e), you may commit or record as needed now. (hg histedit --continue to resume) - [1] + [240] $ hg pull --rebase abort: histedit in progress (use 'hg histedit --continue' or 'hg histedit --abort') - [255] + [20] $ hg histedit --abort --quiet Abort pull early with pending uncommitted merge: @@ -117,7 +117,7 @@ $ hg pull --rebase abort: outstanding uncommitted merge (cannot pull with rebase: please commit or shelve your changes first) - [255] + [20] $ hg update --clean --quiet Abort pull early with unclean subrepo:
--- a/tests/test-rebase-rename.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-rename.t Thu Dec 03 14:15:39 2020 -0500 @@ -60,7 +60,7 @@ Rebase the revision containing the rename: $ hg rebase -s 3 -d 2 - rebasing 3:73a3ee40125d "rename A" (tip) + rebasing 3:73a3ee40125d tip "rename A" saved backup bundle to $TESTTMP/a/.hg/strip-backup/73a3ee40125d-1d78ebcf-rebase.hg $ hg tglog @@ -134,8 +134,8 @@ o 0: 1994f17a630e 'A' $ hg rebase -s 5 -d 4 - rebasing 5:af8ad1f97097 "E" (tip) - note: not rebasing 5:af8ad1f97097 "E" (tip), its destination already has all its changes + rebasing 5:af8ad1f97097 tip "E" + note: not rebasing 5:af8ad1f97097 tip "E", its destination already has all its changes saved backup bundle to $TESTTMP/a/.hg/strip-backup/af8ad1f97097-c3e90708-rebase.hg $ hg tglog @ 4: 60f545c27784 'E' @@ -207,7 +207,7 @@ Rebase the revision containing the copy: $ hg rebase -s 3 -d 2 - rebasing 3:0a8162ff18a8 "copy A" (tip) + rebasing 3:0a8162ff18a8 tip "copy A" saved backup bundle to $TESTTMP/b/.hg/strip-backup/0a8162ff18a8-dd06302a-rebase.hg $ hg tglog @@ -291,7 +291,7 @@ $ hg rebase -s 4 -d 3 - rebasing 4:b918d683b091 "Another unrelated change" (tip) + rebasing 4:b918d683b091 tip "Another unrelated change" saved backup bundle to $TESTTMP/repo/.hg/strip-backup/b918d683b091-3024bc57-rebase.hg $ hg diff --stat -c . @@ -312,14 +312,14 @@ $ hg commit --message "File b created as copy of a and modified" $ hg copy b c $ echo c > c - $ hg commit --message "File c created as copy of b and modified" + $ hg commit --message "File c created as copy of b and modified" ## $ hg copy c d $ echo d > d - $ hg commit --message "File d created as copy of c and modified" + $ hg commit --message "File d created as copy of c and modified (child of 327f772bc074)" Note that there are four entries in the log for d $ hg tglog --follow d - @ 3: 421b7e82bb85 'File d created as copy of c and modified' + @ 3: 6be224292cfa 'File d created as copy of c and modified (child of 327f772bc074)' | o 2: 327f772bc074 'File c created as copy of b and modified' | @@ -342,14 +342,14 @@ $ hg rebase --source 1 --dest 4 rebasing 1:79d255d24ad2 "File b created as copy of a and modified" rebasing 2:327f772bc074 "File c created as copy of b and modified" - rebasing 3:421b7e82bb85 "File d created as copy of c and modified" - saved backup bundle to $TESTTMP/copy-gets-preserved/.hg/strip-backup/79d255d24ad2-a2265555-rebase.hg + rebasing 3:6be224292cfa "File d created as copy of c and modified (child of 327f772bc074)" + saved backup bundle to $TESTTMP/copy-gets-preserved/.hg/strip-backup/79d255d24ad2-a3e674e3-rebase.hg $ hg update 4 3 files updated, 0 files merged, 0 files removed, 0 files unresolved There should still be four entries in the log for d $ hg tglog --follow d - @ 4: dbb9ba033561 'File d created as copy of c and modified' + @ 4: afbdde3a60d5 'File d created as copy of c and modified (child of af74b229bc02)' | o 3: af74b229bc02 'File c created as copy of b and modified' | @@ -368,9 +368,9 @@ rebasing 2:68bf06433839 "File b created as copy of a and modified" rebasing 3:af74b229bc02 "File c created as copy of b and modified" merging b and c to c - rebasing 4:dbb9ba033561 "File d created as copy of c and modified" + rebasing 4:afbdde3a60d5 "File d created as copy of c and modified (child of af74b229bc02)" merging c and d to d - saved backup bundle to $TESTTMP/copy-gets-preserved/.hg/strip-backup/68bf06433839-dde37595-rebase.hg + saved backup bundle to $TESTTMP/copy-gets-preserved/.hg/strip-backup/68bf06433839-29d5057f-rebase.hg $ hg co tip 3 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -378,11 +378,24 @@ copy of 'a'. $ hg tglog --follow d - @ 3: 5a46b94210e5 'Collapsed revision + @ 3: 75708a266e56 'Collapsed revision : * File b created as copy of a and modified : * File c created as copy of b and modified - : * File d created as copy of c and modified' + : * File d created as copy of c and modified (child of af74b229bc02)' o 0: b220cd6d2326 'File a created' + $ hg log -G -Tcompact + @ 3[tip] 75708a266e56 1970-01-01 00:00 +0000 test + | Collapsed revision + | + o 2 15258cf0cf10 1970-01-01 00:00 +0000 test + | unrelated commit is unrelated + | + o 1 1d689898494b 1970-01-01 00:00 +0000 test + | Unrelated file created + | + o 0 b220cd6d2326 1970-01-01 00:00 +0000 test + File a created + $ cd ..
--- a/tests/test-rebase-scenario-global.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-scenario-global.t Thu Dec 03 14:15:39 2020 -0500 @@ -170,7 +170,7 @@ rebasing 5:24b6387c8c8c "F" rebasing 6:eea13746799a "G" note: not rebasing 6:eea13746799a "G", its destination already has all its changes - rebasing 7:02de42196ebe "H" (tip) + rebasing 7:02de42196ebe tip "H" saved backup bundle to $TESTTMP/a4/.hg/strip-backup/24b6387c8c8c-c3fe765d-rebase.hg $ hg tglog @@ -228,7 +228,7 @@ $ hg rebase -s 5 -d 1 rebasing 5:24b6387c8c8c "F" rebasing 6:eea13746799a "G" - rebasing 7:02de42196ebe "H" (tip) + rebasing 7:02de42196ebe tip "H" saved backup bundle to $TESTTMP/a6/.hg/strip-backup/24b6387c8c8c-c3fe765d-rebase.hg $ hg tglog @@ -327,44 +327,44 @@ $ hg rebase -d 0 -b 6 abort: cannot rebase public changesets (see 'hg help phases' for details) - [255] + [10] $ hg rebase -d 5 -b 6 abort: cannot rebase public changesets (see 'hg help phases' for details) - [255] + [10] $ hg rebase -d 5 -r '1 + (6::)' abort: cannot rebase public changesets (see 'hg help phases' for details) - [255] + [10] $ hg rebase -d 5 -b 6 --keep rebasing 6:e1c4361dd923 "C" - rebasing 7:c9659aac0000 "D" (tip) + rebasing 7:c9659aac0000 tip "D" Check rebasing mutable changeset Source phase greater or equal to destination phase: new changeset get the phase of source: $ hg id -n 5 $ hg rebase -s9 -d0 - rebasing 9:2b23e52411f4 "D" (tip) + rebasing 9:2b23e52411f4 tip "D" saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2b23e52411f4-f942decf-rebase.hg $ hg id -n # check we updated back to parent 5 $ hg log --template "{phase}\n" -r 9 draft $ hg rebase -s9 -d1 - rebasing 9:2cb10d0cfc6c "D" (tip) + rebasing 9:2cb10d0cfc6c tip "D" saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2cb10d0cfc6c-ddb0f256-rebase.hg $ hg log --template "{phase}\n" -r 9 draft $ hg phase --force --secret 9 $ hg rebase -s9 -d0 - rebasing 9:c5b12b67163a "D" (tip) + rebasing 9:c5b12b67163a tip "D" saved backup bundle to $TESTTMP/a7/.hg/strip-backup/c5b12b67163a-4e372053-rebase.hg $ hg log --template "{phase}\n" -r 9 secret $ hg rebase -s9 -d1 - rebasing 9:2a0524f868ac "D" (tip) + rebasing 9:2a0524f868ac tip "D" saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2a0524f868ac-cefd8574-rebase.hg $ hg log --template "{phase}\n" -r 9 secret @@ -455,13 +455,13 @@ $ hg rebase -r '2::8' -d 1 abort: cannot rebase changeset with children (use --keep to keep original changesets) - [255] + [10] $ hg rebase -r '2::8' -d 1 -k rebasing 2:c9e50f6cdc55 "C" rebasing 3:ffd453c31098 "D" rebasing 6:3d8a618087a7 "G" rebasing 7:72434a4e60b0 "H" - rebasing 8:479ddb54a924 "I" (tip) + rebasing 8:479ddb54a924 tip "I" $ hg tglog o 13: 9bf1d9358a90 'I' | @@ -501,12 +501,12 @@ $ hg rebase -r '3::8' -d 1 abort: cannot rebase changeset with children (use --keep to keep original changesets) - [255] + [10] $ hg rebase -r '3::8' -d 1 --keep rebasing 3:ffd453c31098 "D" rebasing 6:3d8a618087a7 "G" rebasing 7:72434a4e60b0 "H" - rebasing 8:479ddb54a924 "I" (tip) + rebasing 8:479ddb54a924 tip "I" $ hg tglog o 12: 9d7da0053b1c 'I' | @@ -544,7 +544,7 @@ $ hg rebase -r '3::7' -d 1 abort: cannot rebase changeset with children (use --keep to keep original changesets) - [255] + [10] $ hg rebase -r '3::7' -d 1 --keep rebasing 3:ffd453c31098 "D" rebasing 6:3d8a618087a7 "G" @@ -584,7 +584,7 @@ $ hg rebase -r '3::(7+5)' -d 1 abort: cannot rebase changeset with children (use --keep to keep original changesets) - [255] + [10] $ hg rebase -r '3::(7+5)' -d 1 --keep rebasing 3:ffd453c31098 "D" rebasing 4:c01897464e7f "E" @@ -632,7 +632,7 @@ $ hg rebase -r '6::' -d 2 rebasing 6:3d8a618087a7 "G" rebasing 7:72434a4e60b0 "H" - rebasing 8:479ddb54a924 "I" (tip) + rebasing 8:479ddb54a924 tip "I" saved backup bundle to $TESTTMP/ah5/.hg/strip-backup/3d8a618087a7-b4f73f31-rebase.hg $ hg tglog o 8: fcb52e68a694 'I' @@ -667,7 +667,7 @@ rebasing 5:41bfcc75ed73 "F" rebasing 6:3d8a618087a7 "G" rebasing 7:72434a4e60b0 "H" - rebasing 8:479ddb54a924 "I" (tip) + rebasing 8:479ddb54a924 tip "I" saved backup bundle to $TESTTMP/ah6/.hg/strip-backup/3d8a618087a7-aae93a24-rebase.hg $ hg tglog o 8: 9136df9a87cf 'I' @@ -736,7 +736,7 @@ $ hg rebase --dest 'desc(G)' --rev 'desc(K) + desc(I)' rebasing 8:e7ec4e813ba6 "I" - rebasing 10:23a4ace37988 "K" (tip) + rebasing 10:23a4ace37988 tip "K" saved backup bundle to $TESTTMP/a8/.hg/strip-backup/23a4ace37988-b06984b3-rebase.hg $ hg log --rev 'children(desc(G))' changeset: 9:adb617877056 @@ -803,7 +803,7 @@ rebasing 2:779a07b1b7a0 "first source commit" current directory was removed (rmcwd !) (consider changing to repo root: $TESTTMP/cwd-vanish) (rmcwd !) - rebasing 3:a7d6f3a00bf3 "second source with subdir" (tip) + rebasing 3:a7d6f3a00bf3 tip "second source with subdir" saved backup bundle to $TESTTMP/cwd-vanish/.hg/strip-backup/779a07b1b7a0-853e0073-rebase.hg Get back to the root of cwd-vanish. Note that even though `cd ..` @@ -979,7 +979,7 @@ > EOS $ hg rebase -s C -d B - rebasing 2:dc0947a82db8 "C" (C tip) + rebasing 2:dc0947a82db8 C tip "C" $ [ -f .hg/rebasestate ] && echo 'WRONG: rebasestate should not exist' [1]
--- a/tests/test-rebase-templates.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-templates.t Thu Dec 03 14:15:39 2020 -0500 @@ -82,3 +82,42 @@ o 0:18d04c59bb5d Added a +Respects command-templates.oneline-summary + + $ hg rebase -r 7 -d 8 -n --config command-templates.oneline-summary='rev: {rev}' + starting dry-run rebase; repository will not be changed + rebasing rev: 7 + note: not rebasing rev: 7, its destination already has all its changes + dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase + + +command-templates.oneline-summary.rebase overrides + + $ hg rebase -r 7 -d 8 -n \ + > --config command-templates.oneline-summary='global: {rev}' \ + > --config command-templates.oneline-summary.rebase='override: {rev}' + starting dry-run rebase; repository will not be changed + rebasing override: 7 + note: not rebasing override: 7, its destination already has all its changes + dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase + + +check namespaces and coloring (labels) + + $ hg tag -l -r 7 my-tag + $ hg rebase -r 7 -d 8 -n + starting dry-run rebase; repository will not be changed + rebasing 7:f48cd65c6dc3 my-tag "Added b" + note: not rebasing 7:f48cd65c6dc3 my-tag "Added b", its destination already has all its changes + dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase + $ hg bookmark -r 7 my-bookmark + $ hg rebase -r 7 -d 8 -n + starting dry-run rebase; repository will not be changed + rebasing 7:f48cd65c6dc3 my-bookmark my-tag "Added b" + note: not rebasing 7:f48cd65c6dc3 my-bookmark my-tag "Added b", its destination already has all its changes + dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase + $ hg rebase -r 7 -d 8 -n --color=debug + [ ui.status|starting dry-run rebase; repository will not be changed] + [ ui.status|rebasing [oneline-summary.changeset|7:f48cd65c6dc3] [oneline-summary.bookmarks|my-bookmark] [oneline-summary.tags|my-tag] "[oneline-summary.desc|Added b]"] + [ ui.warning|note: not rebasing [oneline-summary.changeset|7:f48cd65c6dc3] [oneline-summary.bookmarks|my-bookmark] [oneline-summary.tags|my-tag] "[oneline-summary.desc|Added b]", its destination already has all its changes] + [ ui.status|dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase]
--- a/tests/test-rebase-transaction.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rebase-transaction.t Thu Dec 03 14:15:39 2020 -0500 @@ -103,12 +103,12 @@ > A > EOF $ hg rebase --collapse -b D -d Z - rebasing 1:112478962961 "B" (B) - rebasing 3:c26739dbe603 "C" (C) + rebasing 1:112478962961 B "B" + rebasing 3:c26739dbe603 C "C" merging conflict warning: conflicts while merging conflict! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg tglog o 5: D | @@ -132,9 +132,9 @@ (no more unresolved files) continue: hg rebase --continue $ hg continue - already rebased 1:112478962961 "B" (B) as 79bc8f4973ce - rebasing 3:c26739dbe603 "C" (C) - rebasing 5:d24bb333861c "D" (D tip) + already rebased 1:112478962961 B "B" as 79bc8f4973ce + rebasing 3:c26739dbe603 C "C" + rebasing 5:d24bb333861c D tip "D" saved backup bundle to $TESTTMP/collapse-conflict/.hg/strip-backup/112478962961-b5b34645-rebase.hg $ hg tglog o 3: Collapsed revision @@ -165,13 +165,13 @@ > A > EOF $ HGEDITOR=false hg --config ui.interactive=1 rebase --collapse -b D -d Z - rebasing 1:112478962961 "B" (B) - rebasing 3:26805aba1e60 "C" (C) - rebasing 5:f585351a92f8 "D" (D tip) + rebasing 1:112478962961 B "B" + rebasing 3:26805aba1e60 C "C" + rebasing 5:f585351a92f8 D tip "D" transaction abort! rollback completed abort: edit failed: false exited with status 1 - [255] + [250] $ hg tglog o 5: D | @@ -186,9 +186,9 @@ o 0: A $ hg continue - rebasing 1:112478962961 "B" (B) - rebasing 3:26805aba1e60 "C" (C) - rebasing 5:f585351a92f8 "D" (D tip) + rebasing 1:112478962961 B "B" + rebasing 3:26805aba1e60 C "C" + rebasing 5:f585351a92f8 D tip "D" saved backup bundle to $TESTTMP/collapse-cancel-editor/.hg/strip-backup/112478962961-cb2a9b47-rebase.hg $ hg tglog o 3: Collapsed revision
--- a/tests/test-record.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-record.t Thu Dec 03 14:15:39 2020 -0500 @@ -77,7 +77,7 @@ diff --git a/empty-rw b/empty-rw new file mode 100644 abort: empty commit message - [255] + [10] $ hg tip -p changeset: -1:000000000000
--- a/tests/test-remotefilelog-bgprefetch.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-remotefilelog-bgprefetch.t Thu Dec 03 14:15:39 2020 -0500 @@ -229,7 +229,7 @@ .. flaky, the core the test is checked when checking the cache dir, so .. hopefully this flakyness is not hiding any actual bug. $ hg rebase -s temporary -d foo - rebasing 3:d9cf06e3b5b6 "b" (temporary tip) + rebasing 3:d9cf06e3b5b6 temporary tip "b" saved backup bundle to $TESTTMP/shallow/.hg/strip-backup/d9cf06e3b5b6-e5c3dc63-rebase.hg ? files fetched over ? fetches - (? misses, 0.00% hit ratio) over *s (glob) $ find $CACHEDIR -type f | sort @@ -271,9 +271,7 @@ $ hg up -r 3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ clearcache - $ hg prefetch --repack - waiting for lock on prefetching in $TESTTMP/shallow held by process * on host * (glob) (?) - got lock after * seconds (glob) (?) + $ hg prefetch --repack --config ui.timeout.warn=-1 (running background incremental repack) * files fetched over 1 fetches - (* misses, 0.00% hit ratio) over *s (glob) (?) @@ -312,9 +310,7 @@ # Check that foreground prefetch fetches revs specified by '. + draft() + bgprefetchrevs + pullprefetch' $ clearcache - $ hg prefetch --repack - waiting for lock on prefetching in $TESTTMP/shallow held by process * on host * (glob) (?) - got lock after * seconds (glob) (?) + $ hg prefetch --repack --config ui.timeout.warn=-1 (running background incremental repack) * files fetched over 1 fetches - (* misses, 0.00% hit ratio) over *s (glob) (?)
--- a/tests/test-remotefilelog-datapack.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-remotefilelog-datapack.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from __future__ import absolute_import, print_function import hashlib @@ -82,8 +82,7 @@ return self.datapackreader(path) def _testAddSingle(self, content): - """Test putting a simple blob into a pack and reading it out. - """ + """Test putting a simple blob into a pack and reading it out.""" filename = b"foo" node = self.getHash(content) @@ -124,8 +123,7 @@ self.assertEqual(content, chain[0][4]) def testAddDeltas(self): - """Test putting multiple delta blobs into a pack and read the chain. - """ + """Test putting multiple delta blobs into a pack and read the chain.""" revisions = [] filename = b"foo" lastnode = nullid @@ -148,8 +146,7 @@ self.assertEqual(content, chain[-i - 1][4]) def testPackMany(self): - """Pack many related and unrelated objects. - """ + """Pack many related and unrelated objects.""" # Build a random pack file revisions = [] blobs = {} @@ -198,8 +195,7 @@ self.assertEqual(parsedmeta, origmeta) def testGetMissing(self): - """Test the getmissing() api. - """ + """Test the getmissing() api.""" revisions = [] filename = b"foo" lastnode = nullid
--- a/tests/test-remotefilelog-histpack.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-remotefilelog-histpack.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from __future__ import absolute_import import hashlib @@ -76,8 +76,7 @@ return historypack.historypack(path) def testAddSingle(self): - """Test putting a single entry into a pack and reading it out. - """ + """Test putting a single entry into a pack and reading it out.""" filename = b"foo" node = self.getFakeHash() p1 = self.getFakeHash() @@ -140,8 +139,7 @@ self.assertEqual(acopyfrom, copyfrom) def testPackMany(self): - """Pack many related and unrelated ancestors. - """ + """Pack many related and unrelated ancestors.""" # Build a random pack file allentries = {} ancestorcounts = {} @@ -201,8 +199,7 @@ self.assertEqual(acopyfrom, copyfrom) def testGetMissing(self): - """Test the getmissing() api. - """ + """Test the getmissing() api.""" revisions = [] filename = b"foo" for i in range(10):
--- a/tests/test-remotefilelog-linknodes.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-remotefilelog-linknodes.t Thu Dec 03 14:15:39 2020 -0500 @@ -32,7 +32,7 @@ b292c1e3311f $ hg rebase -d 1 - rebasing 2:0632994590a8 "xx" (tip) + rebasing 2:0632994590a8 tip "xx" saved backup bundle to $TESTTMP/shallow/.hg/strip-backup/0632994590a8-0bc786d8-rebase.hg (glob) $ hg log -f x --template "{node|short}\n" 81deab2073bc @@ -41,14 +41,14 @@ # Rebase back, log -f still works $ hg rebase -d 0 -r 2 - rebasing 2:81deab2073bc "xx" (tip) + rebasing 2:81deab2073bc tip "xx" saved backup bundle to $TESTTMP/shallow/.hg/strip-backup/81deab2073bc-80cb4fda-rebase.hg (glob) $ hg log -f x --template "{node|short}\n" b3fca10fb42d b292c1e3311f $ hg rebase -d 1 -r 2 - rebasing 2:b3fca10fb42d "xx" (tip) + rebasing 2:b3fca10fb42d tip "xx" saved backup bundle to $TESTTMP/shallow/.hg/strip-backup/b3fca10fb42d-da73a0c7-rebase.hg (glob) $ cd ..
--- a/tests/test-remotefilelog-local.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-remotefilelog-local.t Thu Dec 03 14:15:39 2020 -0500 @@ -204,5 +204,6 @@ $ hg update -r '.^' -q $ echo 1 > A $ hg commit -m foo -A A + warning: commit already existed in the repository! $ hg log -r . -T '{node}\n' 383ce605500277f879b7460a16ba620eb6930b7f
--- a/tests/test-remotefilelog-prefetch.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-remotefilelog-prefetch.t Thu Dec 03 14:15:39 2020 -0500 @@ -232,14 +232,14 @@ $ hg mv z2 z3 z2: not copying - file is not managed abort: no files to copy - [255] + [10] $ find $CACHEDIR -type f | sort .. The following output line about files fetches is globed because it is .. flaky, the core the test is checked when checking the cache dir, so .. hopefully this flakyness is not hiding any actual bug. $ hg revert -a -r 1 || true ? files fetched over 1 fetches - (? misses, 0.00% hit ratio) over * (glob) - abort: z2@109c3a557a73: not found in manifest! (?) + abort: z2@109c3a557a73: not found in manifest (?) $ find $CACHEDIR -type f | sort $TESTTMP/hgcache/master/11/f6ad8ec52a2984abaafd7c3b516503785c2072/ef95c5376f34698742fe34f315fd82136f8f68c0 $TESTTMP/hgcache/master/39/5df8f7c51f007019cb30201c49e884b46b92fa/69a1b67522704ec122181c0890bd16e9d3e7516a
--- a/tests/test-remotefilelog-repack.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-remotefilelog-repack.t Thu Dec 03 14:15:39 2020 -0500 @@ -306,7 +306,7 @@ $ hg prefetch -r 2 1 files fetched over 1 fetches - (1 misses, 0.00% hit ratio) over * (glob) $ hg prefetch -r 38 - abort: unknown revision '38'! + abort: unknown revision '38' [255] $ ls_l $TESTTMP/hgcache/master/packs/ | grep datapack -r--r--r-- 70 052643fdcdebbd42d7c180a651a30d46098e6fe1.datapack
--- a/tests/test-remotefilelog-sparse.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-remotefilelog-sparse.t Thu Dec 03 14:15:39 2020 -0500 @@ -99,4 +99,4 @@ $ hg prefetch -r '. + .^' -I x -I z 4 files fetched over 1 fetches - (4 misses, 0.00% hit ratio) over * (glob) $ hg rebase -d 2 --keep - rebasing 1:876b1317060d "x2" (foo) + rebasing 1:876b1317060d foo "x2"
--- a/tests/test-rename-after-merge.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rename-after-merge.t Thu Dec 03 14:15:39 2020 -0500 @@ -124,10 +124,10 @@ $ hg copy --forget --at-rev . b2 abort: cannot mark/unmark copy in merge commit - [255] + [10] $ hg copy --after --at-rev . b1 b2 abort: cannot mark/unmark copy in merge commit - [255] + [10] $ cd ..
--- a/tests/test-rename-rev.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rename-rev.t Thu Dec 03 14:15:39 2020 -0500 @@ -23,16 +23,16 @@ # Errors out without --after for now $ hg cp --at-rev . d1/b d1/d abort: --at-rev requires --after - [255] + [10] # Errors out with non-existent source $ hg cp -A --at-rev . d1/non-existent d1/d d1/non-existent: no such file in rev 55d1fd85ef0a abort: no files to copy - [255] + [10] # Errors out with non-existent destination $ hg cp -A --at-rev . d1/b d1/non-existent abort: d1/non-existent: copy destination does not exist in 8a9d70fa20c9 - [255] + [10] # Successful invocation $ hg cp -A --at-rev . d1/b d1/d saved backup bundle to $TESTTMP/.hg/strip-backup/8a9d70fa20c9-973ae357-copy.hg @@ -103,5 +103,5 @@ created new head $ hg cp -A --at-rev . d1 d3 abort: d3: --at-rev does not support a directory as destination - [255] + [10]
--- a/tests/test-rename.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rename.t Thu Dec 03 14:15:39 2020 -0500 @@ -13,7 +13,7 @@ $ hg rename d1/d11/a1 d2/c $ hg --config ui.portablefilenames=abort rename d1/a d1/con.xml abort: filename contains 'con', which is reserved on Windows: d1/con.xml - [255] + [10] $ hg sum parent: 0:9b4b6e7b2c26 tip 1 @@ -295,7 +295,7 @@ $ hg rename d1/a dx/ abort: destination dx/ is not a directory - [255] + [10] $ hg status -C $ hg update -C 0 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -304,7 +304,7 @@ $ hg rename 'glob:d1/**' dx abort: with multiple sources, destination must be an existing directory - [255] + [10] move every file under d1 to d2/d21
--- a/tests/test-repo-compengines.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-repo-compengines.t Thu Dec 03 14:15:39 2020 -0500 @@ -37,7 +37,7 @@ $ cd unknownrequirement $ echo exp-compression-unknown >> .hg/requires $ hg log - abort: repository requires features unknown to this Mercurial: exp-compression-unknown! + abort: repository requires features unknown to this Mercurial: exp-compression-unknown (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] @@ -129,9 +129,9 @@ > revlog.zlib.level=foobar > EOF $ commitone zlib-level-invalid - abort: storage.revlog.zlib.level is not a valid integer ('foobar') - abort: storage.revlog.zlib.level is not a valid integer ('foobar') - [255] + config error: storage.revlog.zlib.level is not a valid integer ('foobar') + config error: storage.revlog.zlib.level is not a valid integer ('foobar') + [30] $ hg init zlib-level-out-of-range $ cat << EOF >> zlib-level-out-of-range/.hg/hgrc @@ -186,9 +186,9 @@ > revlog.zstd.level=foobar > EOF $ commitone zstd-level-invalid - abort: storage.revlog.zstd.level is not a valid integer ('foobar') - abort: storage.revlog.zstd.level is not a valid integer ('foobar') - [255] + config error: storage.revlog.zstd.level is not a valid integer ('foobar') + config error: storage.revlog.zstd.level is not a valid integer ('foobar') + [30] $ hg init zstd-level-out-of-range --config format.revlog-compression=zstd $ cat << EOF >> zstd-level-out-of-range/.hg/hgrc
--- a/tests/test-requires.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-requires.t Thu Dec 03 14:15:39 2020 -0500 @@ -5,16 +5,16 @@ $ hg commit -m test $ rm .hg/requires $ hg tip - abort: unknown version (2) in revlog 00changelog.i! + abort: unknown version (2) in revlog 00changelog.i [255] $ echo indoor-pool > .hg/requires $ hg tip - abort: repository requires features unknown to this Mercurial: indoor-pool! + abort: repository requires features unknown to this Mercurial: indoor-pool (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] $ echo outdoor-pool >> .hg/requires $ hg tip - abort: repository requires features unknown to this Mercurial: indoor-pool outdoor-pool! + abort: repository requires features unknown to this Mercurial: indoor-pool outdoor-pool (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] $ cd .. @@ -71,7 +71,7 @@ [255] $ hg clone supported clone-dst - abort: repository requires features unknown to this Mercurial: featuresetup-test! + abort: repository requires features unknown to this Mercurial: featuresetup-test (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] $ hg clone --pull supported clone-dst
--- a/tests/test-resolve.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-resolve.t Thu Dec 03 14:15:39 2020 -0500 @@ -132,13 +132,13 @@ $ hg resolve --all abort: resolve command not applicable when not merging - [255] + [20] resolve -m should abort when no merge in progress $ hg resolve -m abort: resolve command not applicable when not merging - [255] + [20] can not update or merge when there are unresolved conflicts @@ -191,7 +191,7 @@ $ hg resolve abort: no files or directories specified (use --all to re-merge all unresolved files) - [255] + [10] resolve --all should re-merge all unresolved files $ hg resolve --all @@ -332,7 +332,7 @@ file2 abort: conflict markers detected (use --all to mark anyway) - [255] + [20] $ hg resolve -l U file1 U file2 @@ -406,7 +406,7 @@ R file2 $ hg resolve --mark --re-merge abort: too many actions specified - [255] + [10] $ hg resolve --re-merge --all merging file1 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') @@ -416,7 +416,7 @@ $ hg resolve --config commands.resolve.explicit-re-merge=1 --all abort: no action specified (use --mark, --unmark, --list or --re-merge) - [255] + [10] $ hg resolve --config commands.resolve.explicit-re-merge=1 --re-merge --all merging file1 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') @@ -464,7 +464,7 @@ warning: conflicts while merging emp2! (edit, then use 'hg resolve --mark') warning: conflicts while merging emp3! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] Test when commands.resolve.confirm config option is not set: =========================================================== @@ -489,13 +489,13 @@ $ hg resolve abort: no files or directories specified (use --all to re-merge all unresolved files) - [255] + [10] $ hg resolve --all << EOF > n > EOF re-merge all unresolved files (yn)? n abort: user quit - [255] + [250] $ hg resolve --all << EOF > y @@ -523,7 +523,7 @@ > EOF mark all unresolved files as resolved (yn)? n abort: user quit - [255] + [250] $ hg resolve -m << EOF > y @@ -551,7 +551,7 @@ > EOF mark all resolved files as unresolved (yn)? n abort: user quit - [255] + [250] $ hg resolve -m << EOF > y
--- a/tests/test-revert-interactive.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-revert-interactive.t Thu Dec 03 14:15:39 2020 -0500 @@ -153,7 +153,7 @@ (enter ? for help) [Ynesfdaq?] q abort: user quit - [255] + [250] $ ls folder1/ g
--- a/tests/test-revert.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-revert.t Thu Dec 03 14:15:39 2020 -0500 @@ -11,7 +11,7 @@ $ hg revert abort: no files or directories specified (use --all to revert all files) - [255] + [10] $ hg revert --all Introduce some changes and revert them @@ -250,7 +250,7 @@ $ hg revert -rtip abort: no files or directories specified (use --all to revert all files, or 'hg update 1' to update) - [255] + [10] call `hg revert` with -I ---------------------------
--- a/tests/test-revisions.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-revisions.t Thu Dec 03 14:15:39 2020 -0500 @@ -36,7 +36,7 @@ 1:9 7 was ambiguous and still is $ hg l -r 7 - abort: 00changelog.i@7: ambiguous identifier! + abort: 00changelog.i@7: ambiguous identifier [255] 7b is no longer ambiguous $ hg l -r 7b
--- a/tests/test-revlog-raw.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-revlog-raw.py Thu Dec 03 14:15:39 2020 -0500 @@ -87,10 +87,10 @@ def appendrev(rlog, text, tr, isext=False, isdelta=True): - '''Append a revision. If isext is True, set the EXTSTORED flag so flag + """Append a revision. If isext is True, set the EXTSTORED flag so flag processor will be used (and rawtext is different from text). If isdelta is True, force the revision to be a delta, otherwise it's full text. - ''' + """ nextrev = len(rlog) p1 = rlog.node(nextrev - 1) p2 = node.nullid @@ -111,7 +111,7 @@ def addgroupcopy(rlog, tr, destname=b'_destrevlog.i', optimaldelta=True): - '''Copy revlog to destname using revlog.addgroup. Return the copied revlog. + """Copy revlog to destname using revlog.addgroup. Return the copied revlog. This emulates push or pull. They use changegroup. Changegroup requires repo to work. We don't have a repo, so a dummy changegroup is used. @@ -122,7 +122,7 @@ This exercises some revlog.addgroup (and revlog._addrevision(text=None)) code path, which is not covered by "appendrev" alone. - ''' + """ class dummychangegroup(object): @staticmethod @@ -174,10 +174,10 @@ def lowlevelcopy(rlog, tr, destname=b'_destrevlog.i'): - '''Like addgroupcopy, but use the low level revlog._addrevision directly. + """Like addgroupcopy, but use the low level revlog._addrevision directly. It exercises some code paths that are hard to reach easily otherwise. - ''' + """ dlog = newrevlog(destname, recreate=True) for r in rlog: p1 = rlog.node(r - 1) @@ -218,13 +218,13 @@ def genbits(n): - '''Given a number n, generate (2 ** (n * 2) + 1) numbers in range(2 ** n). + """Given a number n, generate (2 ** (n * 2) + 1) numbers in range(2 ** n). i.e. the generated numbers have a width of n bits. The combination of two adjacent numbers will cover all possible cases. That is to say, given any x, y where both x, and y are in range(2 ** n), there is an x followed immediately by y in the generated sequence. - ''' + """ m = 2 ** n # Gray Code. See https://en.wikipedia.org/wiki/Gray_code @@ -255,7 +255,7 @@ def writecases(rlog, tr): - '''Write some revisions interested to the test. + """Write some revisions interested to the test. The test is interested in 3 properties of a revision: @@ -281,7 +281,7 @@ mentioned above. Return expected [(text, rawtext)]. - ''' + """ result = [] for i, x in enumerate(genbits(3)): isdelta, isext, isempty = bool(x & 1), bool(x & 2), bool(x & 4)
--- a/tests/test-revlog-v2.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-revlog-v2.t Thu Dec 03 14:15:39 2020 -0500 @@ -6,7 +6,7 @@ $ cd invalidreq $ echo exp-revlogv2.unknown >> .hg/requires $ hg log - abort: repository requires features unknown to this Mercurial: exp-revlogv2.unknown! + abort: repository requires features unknown to this Mercurial: exp-revlogv2.unknown (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255] $ cd .. @@ -35,7 +35,7 @@ ... fh.write(b'\xff\x00\xde\xad') and None $ hg log - abort: unknown flags (0xff00) in version 57005 revlog 00changelog.i! + abort: unknown flags (0xff00) in version 57005 revlog 00changelog.i [255] $ cd ..
--- a/tests/test-revlog.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-revlog.t Thu Dec 03 14:15:39 2020 -0500 @@ -7,7 +7,7 @@ ... fh.write(b'\x00\x01\x00\x00') and None $ hg log - abort: unknown flags (0x01) in version 0 revlog 00changelog.i! + abort: unknown flags (0x01) in version 0 revlog 00changelog.i [255] Unknown flags on revlog version 1 are rejected @@ -16,7 +16,7 @@ ... fh.write(b'\x00\x04\x00\x01') and None $ hg log - abort: unknown flags (0x04) in version 1 revlog 00changelog.i! + abort: unknown flags (0x04) in version 1 revlog 00changelog.i [255] Unknown version is rejected @@ -25,7 +25,7 @@ ... fh.write(b'\x00\x00\x00\x02') and None $ hg log - abort: unknown version (2) in revlog 00changelog.i! + abort: unknown version (2) in revlog 00changelog.i [255] $ cd ..
--- a/tests/test-revset-legacy-lookup.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-revset-legacy-lookup.t Thu Dec 03 14:15:39 2020 -0500 @@ -1,7 +1,7 @@ $ cat >> $HGRCPATH << EOF - > [ui] - > logtemplate="{rev}:{node|short} {desc} [{tags}]\n" + > [command-templates] + > log="{rev}:{node|short} {desc} [{tags}]\n" > EOF $ hg init legacy-lookup @@ -95,10 +95,10 @@ $ hg log -r '"foo"' 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"] $ hg log -r '("foo")' - abort: unknown revision 'foo'! + abort: unknown revision 'foo' [255] $ hg log -r 'revset("foo")' - abort: unknown revision 'foo'! + abort: unknown revision 'foo' [255] $ hg log -r '("\"foo\"")' 2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"] @@ -125,10 +125,10 @@ $ hg log -r 'foo+bar' 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar] $ hg log -r '(foo+bar)' - abort: unknown revision 'foo'! + abort: unknown revision 'foo' [255] $ hg log -r 'revset(foo+bar)' - abort: unknown revision 'foo'! + abort: unknown revision 'foo' [255] $ hg log -r '"foo+bar"' 4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar] @@ -172,10 +172,10 @@ 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)] $ hg log -r '(release_4.1(candidate1))' hg: parse error: unknown identifier: release_4.1 - [255] + [10] $ hg log -r 'revset(release_4.1(candidate1))' hg: parse error: unknown identifier: release_4.1 - [255] + [10] $ hg log -r '"release_4.1(candidate1)"' 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)] $ hg log -r '("release_4.1(candidate1)")' @@ -190,7 +190,7 @@ 6:db72e24fe069 Added tag 1.2 for changeset ff42fde8edbb [release_4.1(candidate1)] $ hg log -r '::release_4.1(candidate1)' hg: parse error: unknown identifier: release_4.1 - [255] + [10] Test tag with parenthesis and other function like char @@ -200,10 +200,10 @@ 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)] $ hg log -r '(release_4.1(arch=x86,arm))' hg: parse error: unknown identifier: release_4.1 - [255] + [10] $ hg log -r 'revset(release_4.1(arch=x86,arm))' hg: parse error: unknown identifier: release_4.1 - [255] + [10] $ hg log -r '"release_4.1(arch=x86,arm)"' 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)] $ hg log -r '("release_4.1(arch=x86,arm)")' @@ -219,7 +219,7 @@ 7:b29b25d7d687 Added tag release_4.1(candidate1) for changeset db72e24fe069 [release_4.1(arch=x86,arm)] $ hg log -r '::release_4.1(arch=x86,arm)' hg: parse error: unknown identifier: release_4.1 - [255] + [10] Test tag conflicting with revset function @@ -229,10 +229,10 @@ 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)] $ hg log -r '(secret(team=foo,project=bar))' hg: parse error: secret takes no arguments - [255] + [10] $ hg log -r 'revset(secret(team=foo,project=bar))' hg: parse error: secret takes no arguments - [255] + [10] $ hg log -r '"secret(team=foo,project=bar)"' 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)] $ hg log -r '("secret(team=foo,project=bar)")' @@ -249,7 +249,7 @@ 8:6b2e2d4ea455 Added tag release_4.1(arch=x86,arm) for changeset b29b25d7d687 [secret(team=foo,project=bar)] $ hg log -r '::secret(team=foo,project=bar)' hg: parse error: secret takes no arguments - [255] + [10] Test tag with space @@ -261,12 +261,12 @@ hg: parse error at 4: unexpected token: symbol ((my little version) ^ here) - [255] + [10] $ hg log -r 'revset(my little version)' hg: parse error at 10: unexpected token: symbol (revset(my little version) ^ here) - [255] + [10] $ hg log -r '"my little version"' 9:269192bf8fc3 Added tag secret(team=foo,project=bar) for changeset 6b2e2d4ea455 [my little version] $ hg log -r '("my little version")' @@ -286,4 +286,4 @@ hg: parse error at 5: invalid token (::my little version ^ here) - [255] + [10]
--- a/tests/test-revset-outgoing.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-revset-outgoing.t Thu Dec 03 14:15:39 2020 -0500 @@ -105,11 +105,11 @@ green = ../a#default $ hg tout green - abort: repository green does not exist! + abort: repository green does not exist [255] $ hg tlog -r 'outgoing("green")' - abort: repository green does not exist! + abort: repository green does not exist [255] $ cd ..
--- a/tests/test-revset.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-revset.t Thu Dec 03 14:15:39 2020 -0500 @@ -305,7 +305,7 @@ (symbol 'c')) (negate (symbol 'a'))) - abort: unknown revision '-a'! + abort: unknown revision '-a' [255] $ try é (symbol '\xc3\xa9') @@ -401,29 +401,29 @@ hg: parse error at 10: unexpected token: symbol (date(this is a test) ^ here) - [255] + [10] $ log 'date()' hg: parse error: date requires a string - [255] + [10] $ log 'date' - abort: unknown revision 'date'! + abort: unknown revision 'date' [255] $ log 'date(' hg: parse error at 5: not a prefix: end (date( ^ here) - [255] + [10] $ log 'date("\xy")' hg: parse error: invalid \x escape* (glob) - [255] + [10] $ log 'date(tip)' hg: parse error: invalid date: 'tip' - [255] + [10] $ log '0:date' - abort: unknown revision 'date'! + abort: unknown revision 'date' [255] $ log '::"date"' - abort: unknown revision 'date'! + abort: unknown revision 'date' [255] $ hg book date -r 4 $ log '0:date' @@ -450,7 +450,7 @@ $ log '"date"(2005)' hg: parse error: not a symbol - [255] + [10] keyword arguments @@ -459,25 +459,25 @@ $ log 'extra(branch, a, b)' hg: parse error: extra takes at most 2 positional arguments - [255] + [10] $ log 'extra(a, label=b)' hg: parse error: extra got multiple values for keyword argument 'label' - [255] + [10] $ log 'extra(label=branch, default)' hg: parse error: extra got an invalid argument - [255] + [10] $ log 'extra(branch, foo+bar=baz)' hg: parse error: extra got an invalid argument - [255] + [10] $ log 'extra(unknown=branch)' hg: parse error: extra got an unexpected keyword argument 'unknown' - [255] + [10] $ log 'extra((), x)' hg: parse error: first argument to extra must be a string - [255] + [10] $ log 'extra(label=x, ())' hg: parse error: extra got an invalid argument - [255] + [10] $ try 'foo=bar|baz' (keyvalue @@ -487,7 +487,7 @@ (symbol 'bar') (symbol 'baz')))) hg: parse error: can't use a key-value pair in this context - [255] + [10] right-hand side should be optimized recursively @@ -506,7 +506,7 @@ (symbol '_notpublic') None)) hg: parse error: can't use a key-value pair in this context - [255] + [10] relation-subscript operator has the highest binding strength (as function call): @@ -565,7 +565,7 @@ (symbol 'tip') (symbol '0')) hg: parse error: can't use a subscript in this context - [255] + [10] $ hg debugrevspec -p analyzed 'tip#rel[0]' * analyzed: @@ -574,7 +574,7 @@ (symbol 'rel') (symbol '0')) hg: parse error: unknown identifier: rel - [255] + [10] $ hg debugrevspec -p analyzed '(tip#rel)[0]' * analyzed: @@ -584,7 +584,7 @@ (symbol 'rel')) (symbol '0')) hg: parse error: can't use a subscript in this context - [255] + [10] $ hg debugrevspec -p analyzed 'tip#rel[0][1]' * analyzed: @@ -595,7 +595,7 @@ (symbol '0')) (symbol '1')) hg: parse error: can't use a subscript in this context - [255] + [10] $ hg debugrevspec -p analyzed 'tip#rel0#rel1[1]' * analyzed: @@ -606,7 +606,7 @@ (symbol 'rel1') (symbol '1')) hg: parse error: unknown identifier: rel1 - [255] + [10] $ hg debugrevspec -p analyzed 'tip#rel0[0]#rel1[1]' * analyzed: @@ -618,7 +618,7 @@ (symbol 'rel1') (symbol '1')) hg: parse error: unknown identifier: rel1 - [255] + [10] parse errors of relation, subscript and relation-subscript operators: @@ -626,48 +626,48 @@ hg: parse error at 0: not a prefix: [ ([0] ^ here) - [255] + [10] $ hg debugrevspec '.#' hg: parse error at 2: not a prefix: end (.# ^ here) - [255] + [10] $ hg debugrevspec '#rel' hg: parse error at 0: not a prefix: # (#rel ^ here) - [255] + [10] $ hg debugrevspec '.#rel[0' hg: parse error at 7: unexpected token: end (.#rel[0 ^ here) - [255] + [10] $ hg debugrevspec '.]' hg: parse error at 1: invalid token (.] ^ here) - [255] + [10] $ hg debugrevspec '.#generations[a]' hg: parse error: relation subscript must be an integer or a range - [255] + [10] $ hg debugrevspec '.#generations[1-2]' hg: parse error: relation subscript must be an integer or a range - [255] + [10] $ hg debugrevspec '.#generations[foo:bar]' hg: parse error: relation subscript bounds must be integers - [255] + [10] suggested relations $ hg debugrevspec '.#generafions[0]' hg: parse error: unknown identifier: generafions (did you mean generations?) - [255] + [10] $ hg debugrevspec '.#f[0]' hg: parse error: unknown identifier: f - [255] + [10] parsed tree at stages: @@ -686,7 +686,7 @@ * optimized: None hg: parse error: missing argument - [255] + [10] $ hg debugrevspec --no-optimized -p all '()' * parsed: @@ -701,7 +701,7 @@ * analyzed: None hg: parse error: missing argument - [255] + [10] $ hg debugrevspec -p parsed -p analyzed -p optimized '(0|1)-1' * parsed: @@ -899,7 +899,7 @@ (rangepre (symbol '2')))) hg: parse error: ^ expects a number 0, 1, or 2 - [255] + [10] x^:y should be resolved recursively @@ -1005,7 +1005,7 @@ (rangepre (symbol '2'))) hg: parse error: ^ expects a number 0, 1, or 2 - [255] + [10] '::' itself isn't a valid expression @@ -1013,7 +1013,7 @@ (dagrangeall None) hg: parse error: can't use '::' in this context - [255] + [10] ancestor can accept 0 or more arguments @@ -1170,10 +1170,10 @@ $ log 'ancestors(., depth=-1)' hg: parse error: negative depth - [255] + [10] $ log 'ancestors(., depth=foo)' hg: parse error: ancestors expects an integer depth - [255] + [10] test descendants @@ -1447,10 +1447,10 @@ (symbol 'grep') (string '(')) hg: parse error: invalid match pattern: (unbalanced parenthesis|missing \),.*) (re) - [255] + [10] $ log 'desc("re:(")' hg: parse error: invalid regular expression: (unbalanced parenthesis|missing \),.*) (re) - [255] + [10] $ try 'grep("\bissue\d+")' (func (symbol 'grep') @@ -1472,7 +1472,7 @@ hg: parse error at 7: unterminated string (grep(r"\") ^ here) - [255] + [10] $ log 'head()' 0 1 @@ -1530,15 +1530,15 @@ $ log 'limit(author("re:bob|test"), offset=10)' $ log 'limit(all(), 1, -1)' hg: parse error: negative offset - [255] + [10] $ log 'limit(all(), -1)' hg: parse error: negative number to select - [255] + [10] $ log 'limit(all(), 0)' $ log 'last(all(), -1)' hg: parse error: negative number to select - [255] + [10] $ log 'last(all(), 0)' $ log 'last(all(), 1)' 9 @@ -1861,7 +1861,7 @@ $ log 'rev(10)' $ log 'rev(tip)' hg: parse error: rev expects a number - [255] + [10] Test hexadecimal revision $ log 'id(2)' @@ -1873,7 +1873,7 @@ 3 $ hg log --template '{rev}\n' -r 'id(x)' $ hg log --template '{rev}\n' -r 'x' - abort: 00changelog.i@: ambiguous identifier! + abort: 00changelog.i@: ambiguous identifier [255] $ log 'id(23268)' 4 @@ -1965,7 +1965,7 @@ $ hg debugrevspec 'wdir()^2' $ hg debugrevspec 'wdir()^3' hg: parse error: ^ expects a number 0, 1, or 2 - [255] + [10] For tests consistency $ hg up 9 1 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -2040,13 +2040,13 @@ obsoleted 1 changesets $ hg debugrevspec 'fff' - abort: 00changelog.i@fff: ambiguous identifier! + abort: 00changelog.i@fff: ambiguous identifier [255] $ hg debugrevspec 'ffff' - abort: 00changelog.i@ffff: ambiguous identifier! + abort: 00changelog.i@ffff: ambiguous identifier [255] $ hg debugrevspec 'fffb' - abort: 00changelog.i@fffb: ambiguous identifier! + abort: 00changelog.i@fffb: ambiguous identifier [255] BROKEN should be '2' (node lookup uses unfiltered repo) $ hg debugrevspec 'id(fffb)' @@ -2532,10 +2532,10 @@ $ log '0:2 & sort()' hg: parse error: sort requires one or two arguments - [255] + [10] $ log '0:2 & sort(all(), -invalid)' hg: parse error: unknown sort key '-invalid' - [255] + [10] for 'A & f(B)', 'B' should not be affected by the order of 'A': @@ -2762,7 +2762,7 @@ $ log 'sort(all(), -invalid)' hg: parse error: unknown sort key '-invalid' - [255] + [10] $ cd .. @@ -2980,11 +2980,11 @@ $ hg log -r 'sort(all(), "topo user")' hg: parse error: topo sort order cannot be combined with other sort keys - [255] + [10] $ hg log -r 'sort(all(), user, topo.firstbranch=book1)' hg: parse error: topo.firstbranch can only be used when using the topo sort key - [255] + [10] topo.firstbranch should accept any kind of expressions: @@ -3003,7 +3003,7 @@ hg: parse error at 9: not a prefix: end ( . + .^ + ^ here) - [255] + [10] $ hg debugrevspec -v 'revset(first(rev(0)))' -p all * parsed: (func @@ -3052,10 +3052,10 @@ abort if the revset doesn't expect given size $ log 'expectsize()' hg: parse error: invalid set of arguments - [255] + [10] $ log 'expectsize(0:2, a)' hg: parse error: expectsize requires a size range or a positive integer - [255] + [10] $ log 'expectsize(0:2, 3)' 0 1 @@ -3066,30 +3066,30 @@ 1 0 $ log 'expectsize(0:1, 1)' - abort: revset size mismatch. expected 1, got 2! + abort: revset size mismatch. expected 1, got 2 [255] $ log 'expectsize(0:4, -1)' hg: parse error: negative size - [255] + [10] $ log 'expectsize(0:2, 2:4)' 0 1 2 $ log 'expectsize(0:1, 3:5)' - abort: revset size mismatch. expected between 3 and 5, got 2! + abort: revset size mismatch. expected between 3 and 5, got 2 [255] $ log 'expectsize(0:1, -1:2)' hg: parse error: negative size - [255] + [10] $ log 'expectsize(0:1, 1:-2)' hg: parse error: negative size - [255] + [10] $ log 'expectsize(0:2, a:4)' hg: parse error: size range bounds must be integers - [255] + [10] $ log 'expectsize(0:2, 2:b)' hg: parse error: size range bounds must be integers - [255] + [10] $ log 'expectsize(0:2, 2:)' 0 1 @@ -3103,8 +3103,8 @@ 1 2 $ log 'expectsize(0:2, 4:)' - abort: revset size mismatch. expected between 4 and 11, got 3! + abort: revset size mismatch. expected between 4 and 11, got 3 [255] $ log 'expectsize(0:2, :2)' - abort: revset size mismatch. expected between 0 and 2, got 3! + abort: revset size mismatch. expected between 0 and 2, got 3 [255]
--- a/tests/test-revset2.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-revset2.t Thu Dec 03 14:15:39 2020 -0500 @@ -319,7 +319,7 @@ test unknown revision in `_list` $ log '0|unknown' - abort: unknown revision 'unknown'! + abort: unknown revision 'unknown' [255] test integer range in `_list` @@ -329,11 +329,11 @@ 0 $ log '-10|-11' - abort: unknown revision '-11'! + abort: unknown revision '-11' [255] $ log '9|10' - abort: unknown revision '10'! + abort: unknown revision '10' [255] test '0000' != '0' in `_list` @@ -346,7 +346,7 @@ $ log '0,1' hg: parse error: can't use a list in this context (see 'hg help "revsets.x or y"') - [255] + [10] $ try '0,1,2' (list (symbol '0') @@ -354,7 +354,7 @@ (symbol '2')) hg: parse error: can't use a list in this context (see 'hg help "revsets.x or y"') - [255] + [10] test that chained `or` operations make balanced addsets @@ -407,7 +407,7 @@ (symbol '0') None)) hg: parse error: missing argument - [255] + [10] test that chained `or` operations never eat up stack (issue4624) (uses `0:1` instead of `0` to avoid future optimization of trivial revisions) @@ -510,7 +510,7 @@ (symbol '1')) None) hg: parse error: missing argument - [255] + [10] optimization to only() works only if ancestors() takes only one argument @@ -568,20 +568,20 @@ $ log '"ancestors"(6) and not ancestors(4)' hg: parse error: not a symbol - [255] + [10] $ log 'ancestors(6) and not "ancestors"(4)' hg: parse error: not a symbol - [255] + [10] test empty string $ log '' hg: parse error: empty query - [255] + [10] $ log 'parents("")' hg: parse error: empty string is not a valid revision - [255] + [10] test empty revset $ hg log 'none()' @@ -589,7 +589,7 @@ we can use patterns when searching for tags $ log 'tag("1..*")' - abort: tag '1..*' does not exist! + abort: tag '1..*' does not exist [255] $ log 'tag("re:1..*")' 6 @@ -600,16 +600,16 @@ $ log 'tag("re:0..*")' $ log 'tag(unknown)' - abort: tag 'unknown' does not exist! + abort: tag 'unknown' does not exist [255] $ log 'tag("re:unknown")' $ log 'present(tag("unknown"))' $ log 'present(tag("re:unknown"))' $ log 'branch(unknown)' - abort: unknown revision 'unknown'! + abort: unknown revision 'unknown' [255] $ log 'branch("literal:unknown")' - abort: branch 'unknown' does not exist! + abort: branch 'unknown' does not exist [255] $ log 'branch("re:unknown")' $ log 'present(branch("unknown"))' @@ -665,7 +665,7 @@ 1 $ log 'named("unknown")' - abort: namespace 'unknown' does not exist! + abort: namespace 'unknown' does not exist [255] $ log 'named("re:unknown")' $ log 'present(named("unknown"))' @@ -701,7 +701,7 @@ hg: parse error at 2: invalid token (1 OR 2 ^ here) - [255] + [10] or operator should preserve ordering: $ log 'reverse(2::4) or tip' @@ -755,39 +755,39 @@ $ log 'tip^foo' hg: parse error: ^ expects a number 0, 1, or 2 - [255] + [10] $ log 'branchpoint()~-1' - abort: revision in set has more than one child! + abort: revision in set has more than one child [255] Bogus function gets suggestions $ log 'add()' hg: parse error: unknown identifier: add (did you mean adds?) - [255] + [10] $ log 'added()' hg: parse error: unknown identifier: added (did you mean adds?) - [255] + [10] $ log 'remo()' hg: parse error: unknown identifier: remo (did you mean one of remote, removes?) - [255] + [10] $ log 'babar()' hg: parse error: unknown identifier: babar - [255] + [10] Bogus function with a similar internal name doesn't suggest the internal name $ log 'matches()' hg: parse error: unknown identifier: matches (did you mean matching?) - [255] + [10] Undocumented functions aren't suggested as similar either $ log 'tagged2()' hg: parse error: unknown identifier: tagged2 - [255] + [10] multiple revspecs @@ -869,7 +869,7 @@ $ export HGPLAIN $ try m (symbol 'm') - abort: unknown revision 'm'! + abort: unknown revision 'm' [255] $ HGPLAINEXCEPT=revsetalias @@ -949,7 +949,7 @@ $ try recurse1 (symbol 'recurse1') hg: parse error: infinite expansion of revset alias "recurse1" detected - [255] + [10] $ echo 'level1($1, $2) = $1 or $2' >> .hg/hgrc $ echo 'level2($1, $2) = level1($2, $1)' >> .hg/hgrc @@ -1060,7 +1060,7 @@ (func (symbol 'max') (string '$1'))) - abort: unknown revision '$1'! + abort: unknown revision '$1' [255] test scope of alias expansion: 'universe' is expanded prior to 'shadowall(0)', @@ -1185,13 +1185,13 @@ (symbol 'rs') None) hg: parse error: invalid number of arguments: 0 - [255] + [10] $ try 'rs(2)' (func (symbol 'rs') (symbol '2')) hg: parse error: invalid number of arguments: 1 - [255] + [10] $ try 'rs(2, data, 7)' (func (symbol 'rs') @@ -1200,7 +1200,7 @@ (symbol 'data') (symbol '7'))) hg: parse error: invalid number of arguments: 3 - [255] + [10] $ try 'rs4(2 or 3, x, x, date)' (func (symbol 'rs4') @@ -1575,7 +1575,7 @@ hg: parse error at 3: syntax error in revset 'foo\\' (foo\\ ^ here) - [255] + [10] $ cd .. @@ -1603,7 +1603,7 @@ $ hg debugrevspec "custom1()" *** failed to import extension custompredicate from $TESTTMP/custompredicate.py: intentional failure of loading extension hg: parse error: unknown identifier: custom1 - [255] + [10] Test repo.anyrevs with customized revset overrides
--- a/tests/test-rhg.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rhg.t Thu Dec 03 14:15:39 2020 -0500 @@ -90,3 +90,78 @@ file1\x00b8e02f6433738021a065f94175c7cd23db5f05be (esc) file2\x005d9299349fc01ddd25d0070d149b124d8f10411e (esc) file3\x002661d26c649684b482d10f91960cc3db683c38b4 (esc) + +Debuging with full node id + $ rhg debugdata -c `hg log -r 0 -T '{node}'` + c8e64718e1ca0312eeee0f59d37f8dc612793856 + test + 0 0 + file1 + + commit 1 (no-eol) + +Cat files + $ cd $TESTTMP + $ rm -rf repository + $ hg init repository + $ cd repository + $ echo "original content" > original + $ hg add original + $ hg commit -m "add original" original + $ rhg cat -r 0 original + original content +Cat copied file should not display copy metadata + $ hg copy original copy_of_original + $ hg commit -m "add copy of original" + $ rhg cat -r 1 copy_of_original + original content + +Specifying revisions by changeset ID + $ hg log + changeset: 1:41263439dc17 + tag: tip + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add copy of original + + changeset: 0:1c9e69808da7 + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: add original + + $ rhg files -r 41263439dc17 + abort: invalid revision identifier 41263439dc17 + [255] + $ rhg cat -r 41263439dc17 original + abort: invalid revision identifier 41263439dc17 + [255] + +Requirements + $ rhg debugrequirements + dotencode + fncache + generaldelta + revlogv1 + sparserevlog + store + + $ echo indoor-pool >> .hg/requires + $ rhg files + [252] + + $ rhg cat -r 1 copy_of_original + [252] + + $ rhg debugrequirements + dotencode + fncache + generaldelta + revlogv1 + sparserevlog + store + indoor-pool + + $ echo -e '\xFF' >> .hg/requires + $ rhg debugrequirements + abort: .hg/requires is corrupted + [255]
--- a/tests/test-run-tests.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-run-tests.t Thu Dec 03 14:15:39 2020 -0500 @@ -1412,7 +1412,7 @@ > This should print the start of check-code. If this passes but the > previous check failed, that means we found a copy of check-code at whatever > RUNTESTSDIR ended up containing, even though it doesn't match TESTDIR. - > $ head -n 3 "\$RUNTESTDIR"/../contrib/check-code.py | sed 's@.!.*python@#!USRBINENVPY@' + > $ head -n 3 "\$RUNTESTDIR"/../contrib/check-code.py | sed 's@.!.*python3@#!USRBINENVPY@' > #!USRBINENVPY > # > # check-code - a style and portability checker for Mercurial
--- a/tests/test-rust-revlog.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-rust-revlog.py Thu Dec 03 14:15:39 2020 -0500 @@ -17,7 +17,8 @@ @unittest.skipIf( - rustext is None, "rustext module revlog relies on is not available", + rustext is None, + "rustext module revlog relies on is not available", ) class RustRevlogIndexTest(revlogtesting.RevlogBasedTestBase): def test_heads(self):
--- a/tests/test-serve.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-serve.t Thu Dec 03 14:15:39 2020 -0500 @@ -90,10 +90,10 @@ $ hg id http://localhost:$HGPORT/some/dir7 abort: HTTP Error 404: Not Found - [255] + [100] $ hg id http://localhost:$HGPORT/some abort: HTTP Error 404: Not Found - [255] + [100] $ cat access.log errors.log $LOCALIP - - [$LOGDATE$] "GET /some/dir7?cmd=capabilities HTTP/1.1" 404 - (glob)
--- a/tests/test-share-safe.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-share-safe.t Thu Dec 03 14:15:39 2020 -0500 @@ -36,7 +36,7 @@ $ HGEDITOR=cat hg config --shared abort: repository is not shared; can't use --shared - [255] + [10] $ cd .. Create a shared repo and check the requirements are shared and read correctly @@ -81,6 +81,36 @@ $ hg showconfig ui.curses true +Test that extensions of source repository are also loaded + + $ hg debugextensions + share + $ hg extdiff -p echo + hg: unknown command 'extdiff' + 'extdiff' is provided by the following extension: + + extdiff command to allow external programs to compare revisions + + (use 'hg help extensions' for information on enabling extensions) + [255] + + $ echo "[extensions]" >> ../source/.hg/hgrc + $ echo "extdiff=" >> ../source/.hg/hgrc + + $ hg debugextensions -R ../source + extdiff + share + $ hg extdiff -R ../source -p echo + +BROKEN: the command below will not work if config of shared source is not loaded +on dispatch but debugextensions says that extension +is loaded + $ hg debugextensions + extdiff + share + + $ hg extdiff -p echo + However, local .hg/hgrc should override the config set by share source $ echo "[ui]" >> .hg/hgrc @@ -92,6 +122,8 @@ $ HGEDITOR=cat hg config --shared [ui] curses=true + [extensions] + extdiff= $ HGEDITOR=cat hg config --local [ui] @@ -221,6 +253,25 @@ date: Thu Jan 01 00:00:00 1970 +0000 summary: added c + +Testing that nonsharedrc is loaded for source and not shared + + $ cd ../source + $ touch .hg/hgrc-not-shared + $ echo "[ui]" >> .hg/hgrc-not-shared + $ echo "traceback=true" >> .hg/hgrc-not-shared + + $ hg showconfig ui.traceback + true + + $ HGEDITOR=cat hg config --non-shared + [ui] + traceback=true + + $ cd ../shared1 + $ hg showconfig ui.traceback + [1] + Unsharing works $ hg unshare @@ -241,3 +292,165 @@ [255] $ hg showconfig ui.curses -R ../shared1 false + + $ cd ../ + +Test that upgrading using debugupgraderepo works +================================================= + + $ hg init non-share-safe --config format.exp-share-safe=false + $ cd non-share-safe + $ hg debugrequirements + dotencode + fncache + generaldelta + revlogv1 + sparserevlog + store + $ echo foo > foo + $ hg ci -Aqm 'added foo' + $ echo bar > bar + $ hg ci -Aqm 'added bar' + +Create a share before upgrading + + $ cd .. + $ hg share non-share-safe nss-share + updating working directory + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg debugrequirements -R nss-share + dotencode + fncache + generaldelta + revlogv1 + shared + sparserevlog + store + $ cd non-share-safe + +Upgrade + + $ hg debugupgraderepo -q + requirements + preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store + added: exp-sharesafe + + $ hg debugupgraderepo --run -q + upgrade will perform the following actions: + + requirements + preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store + added: exp-sharesafe + + repository upgraded to share safe mode, existing shares will still work in old non-safe mode. Re-share existing shares to use them in safe mode New shares will be created in safe mode. + + $ hg debugrequirements + dotencode + exp-sharesafe + fncache + generaldelta + revlogv1 + sparserevlog + store + + $ cat .hg/requires + exp-sharesafe + + $ cat .hg/store/requires + dotencode + fncache + generaldelta + revlogv1 + sparserevlog + store + + $ hg log -GT "{node}: {desc}\n" + @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar + | + o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo + + +Make sure existing shares still works + + $ hg log -GT "{node}: {desc}\n" -R ../nss-share + warning: source repository supports share-safe functionality. Reshare to upgrade. + @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar + | + o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo + + + +Create a safe share from upgrade one + + $ cd .. + $ hg share non-share-safe ss-share + updating working directory + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd ss-share + $ hg log -GT "{node}: {desc}\n" + @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar + | + o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo + + $ cd ../non-share-safe + +Test that downgrading works too + + $ cat >> $HGRCPATH <<EOF + > [extensions] + > share = + > [format] + > exp-share-safe = False + > EOF + + $ hg debugupgraderepo -q + requirements + preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store + removed: exp-sharesafe + + $ hg debugupgraderepo -q --run + upgrade will perform the following actions: + + requirements + preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store + removed: exp-sharesafe + + repository downgraded to not use share safe mode, existing shares will not work and needs to be reshared. + + $ hg debugrequirements + dotencode + fncache + generaldelta + revlogv1 + sparserevlog + store + + $ cat .hg/requires + dotencode + fncache + generaldelta + revlogv1 + sparserevlog + store + + $ test -f .hg/store/requires + [1] + + $ hg log -GT "{node}: {desc}\n" + @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar + | + o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo + + +Make sure existing shares still works + + $ hg log -GT "{node}: {desc}\n" -R ../nss-share + @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar + | + o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo + + $ hg unshare -R ../nss-share + + $ hg log -GT "{node}: {desc}\n" -R ../ss-share + abort: share source does not support exp-sharesafe requirement + [255]
--- a/tests/test-share.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-share.t Thu Dec 03 14:15:39 2020 -0500 @@ -211,7 +211,7 @@ $TESTTMP/thisdir/rel $ mv thisdir thatdir $ hg -R thatdir/abs root - abort: .hg/sharedpath points to nonexistent directory $TESTTMP/thisdir/orig/.hg! + abort: .hg/sharedpath points to nonexistent directory $TESTTMP/thisdir/orig/.hg [255] $ hg -R thatdir/rel root $TESTTMP/thatdir/rel @@ -247,7 +247,7 @@ We cannot open the repo with the unknown requirement $ hg -R sharenewrequires status - abort: repository requires features unknown to this Mercurial: missing-requirement! + abort: repository requires features unknown to this Mercurial: missing-requirement (see https://mercurial-scm.org/wiki/MissingRequirement for more information) [255]
--- a/tests/test-shelve.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-shelve.t Thu Dec 03 14:15:39 2020 -0500 @@ -209,7 +209,7 @@ $ hg shelve --list --addremove abort: options '--list' and '--addremove' may not be used together - [255] + [10] delete our older shelved change @@ -366,7 +366,7 @@ merging a/a warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ hg status -v M a/a M b.rename/b @@ -442,7 +442,7 @@ $ hg shelve abort: unshelve already in progress (use 'hg unshelve --continue' or 'hg unshelve --abort') - [255] + [20] abort the unshelve and be happy @@ -474,7 +474,7 @@ $ hg unshelve -c abort: no unshelve in progress - [255] + [20] $ hg status A foo/foo ? a/a.orig @@ -484,7 +484,7 @@ $ hg unshelve -q warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] attempt to continue @@ -501,12 +501,12 @@ $ hg commit -m 'commit while unshelve in progress' abort: unshelve already in progress (use 'hg unshelve --continue' or 'hg unshelve --abort') - [255] + [20] $ hg graft --continue abort: no graft in progress (continue: hg unshelve --continue) - [255] + [20] $ hg unshelve -c unshelve of 'default' complete @@ -648,13 +648,13 @@ $ hg shelve --cleanup --delete abort: options '--cleanup' and '--delete' may not be used together - [255] + [10] $ hg shelve --cleanup --patch abort: options '--cleanup' and '--patch' may not be used together - [255] + [10] $ hg shelve --cleanup --message MESSAGE abort: options '--cleanup' and '--message' may not be used together - [255] + [10] test bookmarks @@ -705,7 +705,7 @@ merging a/a warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ hg bookmark test (4|13):33f7f61e6c5e (re) @@ -737,10 +737,10 @@ $ hg shelve --delete --stat abort: options '--delete' and '--stat' may not be used together - [255] + [10] $ hg shelve --delete --name NAME abort: options '--delete' and '--name' may not be used together - [255] + [10] Test interactive shelve $ cat <<EOF >> $HGRCPATH @@ -767,7 +767,7 @@ a $ hg shelve --interactive --config ui.interactive=false abort: running non-interactively - [255] + [10] $ hg shelve --interactive << EOF > y > y @@ -810,6 +810,8 @@ ? foo/foo $ hg bookmark \* test (4|13):33f7f61e6c5e (re) +there shouldn't be a merge state + $ hg resolve -l $ hg unshelve unshelving change 'test' temporarily committing pending changes (restore with 'hg unshelve --abort') @@ -954,13 +956,13 @@ unshelving change 'default' $ hg shelve --keep --list abort: options '--list' and '--keep' may not be used together - [255] + [10] $ hg shelve --keep --patch abort: options '--patch' and '--keep' may not be used together - [255] + [10] $ hg shelve --keep --delete abort: options '--delete' and '--keep' may not be used together - [255] + [10] $ hg shelve --keep shelved as default $ hg diff @@ -1184,7 +1186,7 @@ $ hg unshelve abort: outstanding uncommitted merge (use 'hg commit' or 'hg merge --abort') - [255] + [20] $ cd .. @@ -1387,7 +1389,7 @@ warning: conflicts while merging bar1! (edit, then use 'hg resolve --mark') warning: conflicts while merging bar2! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ cat > bar1 <<EOF > A @@ -1483,7 +1485,7 @@ $ hg unshelve --continue abort: no unshelve in progress - [255] + [20] $ hg shelve --list default-01 (*)* changes to: add A to bars (glob)
--- a/tests/test-shelve2.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-shelve2.t Thu Dec 03 14:15:39 2020 -0500 @@ -54,7 +54,7 @@ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg rebase -d 6c103be8f4e4 --config extensions.rebase= - rebasing 2:323bfa07f744 "xyz"( \(tip\))? (re) + rebasing 2:323bfa07f744( tip)? "xyz" (re) merging x saved backup bundle to \$TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-(78114325|7ae538ef)-rebase.hg (re) $ hg unshelve @@ -219,7 +219,7 @@ merging f warning: conflicts while merging f! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] #if phasebased $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}' @@ -290,7 +290,7 @@ merging f warning: conflicts while merging f! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ hg st M f ? f.orig @@ -345,7 +345,7 @@ $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups' warning: conflicts while merging root! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ ls .hg/origbackups root $ rm -rf .hg/origbackups @@ -563,7 +563,7 @@ merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ echo "aaabbbccc" > a $ rm a.orig $ hg resolve --mark a @@ -637,7 +637,7 @@ merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] Removing restore branch information from shelvedstate file(making it looks like in previous versions) and running unshelve --continue @@ -715,7 +715,7 @@ merging file warning: conflicts while merging file! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ echo somethingsomething > .hg/shelvedstate Unshelve --continue fails with appropriate message if shelvedstate is corrupted @@ -737,7 +737,7 @@ #if abortflag $ hg unshelve --abort abort: no unshelve in progress - [255] + [20] #else $ hg abort aborting the merge, updating back to 9451eaa6eee3 @@ -762,7 +762,7 @@ merging file warning: conflicts while merging file! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ hg resolve --mark file (no more unresolved files) continue: hg unshelve --continue @@ -819,7 +819,7 @@ merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] putting v1 shelvedstate file in place of a created v2 $ cat << EOF > .hg/shelvedstate > 1 @@ -860,7 +860,7 @@ merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ hg abort unshelve of 'default' aborted @@ -877,7 +877,7 @@ merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ cat .hg/shelved/default.shelve node=82e0cb9893247d12667017593ce1e5655860f1ac $ hg abort @@ -905,14 +905,14 @@ merging a warning: conflicts while merging a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ hg log --template '{desc|firstline} {author} {date|isodate} \n' -r . pending changes temporary commit shelve@localhost 1970-01-01 00:00 +0000 $ hg merge --abort abort: cannot abort merge with unshelve in progress (use 'hg unshelve --continue' or 'hg unshelve --abort') - [255] + [20] $ hg unshelve --abort unshelve of 'default' aborted @@ -934,7 +934,7 @@ $ hg unshelve -q warning: conflicts while merging foo! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue') - [1] + [240] $ cat foo r0 <<<<<<< working-copy: 0b2fcf2a90e9 - shelve: pending changes temporary commit
--- a/tests/test-sidedata.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-sidedata.t Thu Dec 03 14:15:39 2020 -0500 @@ -54,6 +54,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no no no persistent-nodemap: no no no @@ -66,6 +67,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no yes no persistent-nodemap: no no no @@ -84,6 +86,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: yes no no persistent-nodemap: no no no @@ -96,6 +99,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: yes no no persistent-nodemap: no no no
--- a/tests/test-simple-update.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-simple-update.t Thu Dec 03 14:15:39 2020 -0500 @@ -55,7 +55,7 @@ $ hg upd -d foo 0 abort: you can't specify a revision and a date - [255] + [10] update by date @@ -71,7 +71,7 @@ $ hg update -d '>1970-01-01 00:00:02 +0000' abort: revision matching date not found - [255] + [10] $ hg update -d '>1970-01-01 00:00:01 +0000' found revision 1 from Thu Jan 01 00:00:01 1970 +0000 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-sparse-profiles.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-sparse-profiles.t Thu Dec 03 14:15:39 2020 -0500 @@ -201,7 +201,7 @@ warning: conflicts while merging backend.sparse! (edit, then use 'hg resolve --mark') warning: conflicts while merging data.py! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ rm *.orig $ ls -A .hg
--- a/tests/test-sparse-requirement.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-sparse-requirement.t Thu Dec 03 14:15:39 2020 -0500 @@ -46,7 +46,7 @@ Client without sparse enabled reacts properly $ hg files - abort: repository is using sparse feature but sparse is not enabled; enable the "sparse" extensions to access! + abort: repository is using sparse feature but sparse is not enabled; enable the "sparse" extensions to access [255] Requirement for sparse is removed when sparse is disabled
--- a/tests/test-sparse.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-sparse.t Thu Dec 03 14:15:39 2020 -0500 @@ -196,12 +196,12 @@ Verify rebase temporarily includes excluded files $ hg rebase -d 1 -r 2 --config extensions.rebase= - rebasing 2:b91df4f39e75 "edit hide" (tip) + rebasing 2:b91df4f39e75 tip "edit hide" temporarily included 2 file(s) in the sparse checkout for merging merging hide warning: conflicts while merging hide! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg rebase --continue') - [1] + [240] $ hg debugsparse [exclude] @@ -279,7 +279,7 @@ $ hg commit -Aqm "add show2" $ hg rebase -d 1 --config extensions.rebase= - rebasing 2:bdde55290160 "add show2" (tip) + rebasing 2:bdde55290160 tip "add show2" saved backup bundle to $TESTTMP/myrepo/.hg/strip-backup/bdde55290160-216ed9c6-rebase.hg Verify log --sparse only shows commits that affect the sparse checkout
--- a/tests/test-split.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-split.t Thu Dec 03 14:15:39 2020 -0500 @@ -51,7 +51,7 @@ $ hg commit -m empty --config ui.allowemptycommit=1 $ hg split abort: cannot split an empty revision - [255] + [10] $ rm -rf .hg $ hg init @@ -60,7 +60,7 @@ $ hg split -r 'wdir()' abort: cannot split working directory - [255] + [10] Generate some content. The sed filter drop CR on Windows, which is dropped in the a > b line. @@ -79,7 +79,7 @@ $ hg split . abort: cannot split public changesets (see 'hg help phases' for details) - [255] + [10] $ hg phase --draft -f -r 'all()' @@ -89,7 +89,7 @@ $ hg add dirty $ hg split . abort: uncommitted changes - [255] + [20] $ hg forget dirty $ rm dirty @@ -103,7 +103,7 @@ $ hg split 'all()' abort: cannot split multiple revisions - [255] + [10] This function splits a bit strangely primarily to avoid changing the behavior of the test after a bug was fixed with how split/commit --interactive handled @@ -159,7 +159,7 @@ transaction abort! rollback completed abort: edit failed: false exited with status 1 - [255] + [250] $ hg status $ HGEDITOR="\"$PYTHON\" $TESTTMP/editor.py" @@ -216,7 +216,7 @@ (enter ? for help) [Ynesfdaq?] y EDITOR: HG: Splitting 1df0d5c5a3ab. So far it has been split into: - EDITOR: HG: - e704349bd21b: split 1 + EDITOR: HG: - 2:e704349bd21b tip "split 1" EDITOR: HG: Write commit message for the next split changeset. EDITOR: a2 EDITOR: @@ -239,8 +239,8 @@ (enter ? for help) [Ynesfdaq?] y EDITOR: HG: Splitting 1df0d5c5a3ab. So far it has been split into: - EDITOR: HG: - e704349bd21b: split 1 - EDITOR: HG: - a09ad58faae3: split 2 + EDITOR: HG: - 2:e704349bd21b tip "split 1" + EDITOR: HG: - 3:a09ad58faae3 "split 2" EDITOR: HG: Write commit message for the next split changeset. EDITOR: a2 EDITOR: @@ -368,9 +368,9 @@ $ cp -R . ../d $ runsplit -r 1 | grep rebasing - rebasing 2:b5c5ea414030 "d1" (d1) - rebasing 3:f4a0a8d004cc "d2" (d2) - rebasing 4:777940761eba "d3" (d3) + rebasing 2:b5c5ea414030 d1 "d1" + rebasing 3:f4a0a8d004cc d2 "d2" + rebasing 4:777940761eba d3 "d3" #if obsstore-off $ hg bookmark d1 4:c4b449ef030e @@ -467,7 +467,7 @@ #if obsstore-off $ runsplit -r 1 --no-rebase abort: cannot split changeset with children - [255] + [10] #else $ runsplit -r 1 --no-rebase >/dev/null 3 new orphan changesets @@ -518,7 +518,7 @@ $ rm .hg/localtags $ hg split $B --config experimental.evolution=createmarkers abort: cannot split changeset with children - [255] + [10] $ cat > $TESTTMP/messages <<EOF > Split B > EOF @@ -661,7 +661,7 @@ (enter ? for help) [Ynesfdaq?] f EDITOR: HG: Splitting dd3c45017cbf. So far it has been split into: - EDITOR: HG: - f205aea1c624: split 1 + EDITOR: HG: - 2:f205aea1c624 tip "split 1" EDITOR: HG: Write commit message for the next split changeset. EDITOR: splitme EDITOR: @@ -718,7 +718,7 @@ (enter ? for help) [Ynesfdaq?] f EDITOR: HG: Splitting 904c80b40a4a. So far it has been split into: - EDITOR: HG: - ffecf40fa954: split 1 + EDITOR: HG: - 2:ffecf40fa954 tip "split 1" EDITOR: HG: Write commit message for the next split changeset. EDITOR: splitme EDITOR: @@ -843,7 +843,7 @@ (enter ? for help) [Ynesfdaq?] a EDITOR: HG: Splitting 8c42fa635116. So far it has been split into: - EDITOR: HG: - 478be2a70c27: split1, keeping only the numbered lines + EDITOR: HG: - 2:478be2a70c27 tip "split1, keeping only the numbered lines" EDITOR: HG: Write commit message for the next split changeset. EDITOR: move and modify EDITOR: @@ -941,7 +941,7 @@ (enter ? for help) [Ynesfdaq?] a EDITOR: HG: Splitting 41c861dfa61e. So far it has been split into: - EDITOR: HG: - 4b19e06610eb: split1, keeping "file" and only the numbered lines in file2 + EDITOR: HG: - 2:4b19e06610eb tip "split1, keeping "file" and only the numbered lines in file2" EDITOR: HG: Write commit message for the next split changeset. EDITOR: copy file->file2, modify both EDITOR: @@ -976,3 +976,73 @@ 2 3 4 + +Test that color codes don't end up in the commit message template +---------------------------------------------------- + + $ hg init $TESTTMP/colorless + $ cd $TESTTMP/colorless + $ echo 1 > file1 + $ echo 1 > file2 + $ hg ci -qAm initial + $ echo 2 > file1 + $ echo 2 > file2 + $ cat > $TESTTMP/messages <<EOF + > split1, modifying file1 + > -- + > split2, modifying file2 + > EOF + $ hg ci + EDITOR: + EDITOR: + EDITOR: HG: Enter commit message. Lines beginning with 'HG:' are removed. + EDITOR: HG: Leave message empty to abort commit. + EDITOR: HG: -- + EDITOR: HG: user: test + EDITOR: HG: branch 'default' + EDITOR: HG: changed file1 + EDITOR: HG: changed file2 + $ printf 'f\nn\na\n' | hg split --color=debug \ + > --config command-templates.oneline-summary='{label("rev", rev)} {desc}' + [diff.diffline|diff --git a/file1 b/file1] + 1 hunks, 1 lines changed + [ ui.prompt|examine changes to 'file1'? + (enter ? for help) [Ynesfdaq?]] [ ui.promptecho|f] + + [diff.diffline|diff --git a/file2 b/file2] + 1 hunks, 1 lines changed + [ ui.prompt|examine changes to 'file2'? + (enter ? for help) [Ynesfdaq?]] [ ui.promptecho|n] + + EDITOR: HG: Splitting 6432c65c3078. Write commit message for the first split changeset. + EDITOR: split1, modifying file1 + EDITOR: + EDITOR: + EDITOR: HG: Enter commit message. Lines beginning with 'HG:' are removed. + EDITOR: HG: Leave message empty to abort commit. + EDITOR: HG: -- + EDITOR: HG: user: test + EDITOR: HG: branch 'default' + EDITOR: HG: changed file1 + [ ui.status|created new head] + [diff.diffline|diff --git a/file2 b/file2] + 1 hunks, 1 lines changed + [ ui.prompt|examine changes to 'file2'? + (enter ? for help) [Ynesfdaq?]] [ ui.promptecho|a] + + EDITOR: HG: Splitting 6432c65c3078. So far it has been split into: + EDITOR: HG: - 2 split2, modifying file2 + EDITOR: HG: Write commit message for the next split changeset. + EDITOR: split1, modifying file1 + EDITOR: + EDITOR: + EDITOR: HG: Enter commit message. Lines beginning with 'HG:' are removed. + EDITOR: HG: Leave message empty to abort commit. + EDITOR: HG: -- + EDITOR: HG: user: test + EDITOR: HG: branch 'default' + EDITOR: HG: changed file2 + [ ui.warning|transaction abort!] + [ ui.warning|rollback completed] + [ ui.error|abort: empty commit message] + [10]
--- a/tests/test-ssh-bundle1.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-ssh-bundle1.t Thu Dec 03 14:15:39 2020 -0500 @@ -53,16 +53,16 @@ repo not found error $ hg clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local - remote: abort: repository nonexistent not found! - abort: no suitable response from remote hg! + remote: abort: repository nonexistent not found + abort: no suitable response from remote hg [255] non-existent absolute path #if no-msys $ hg clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy//`pwd`/nonexistent local - remote: abort: repository /$TESTTMP/nonexistent not found! - abort: no suitable response from remote hg! + remote: abort: repository /$TESTTMP/nonexistent not found + abort: no suitable response from remote hg [255] #endif @@ -147,8 +147,8 @@ $ hg pull -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist pulling from ssh://user@dummy/doesnotexist - remote: abort: repository doesnotexist not found! - abort: no suitable response from remote hg! + remote: abort: repository doesnotexist not found + abort: no suitable response from remote hg [255] local change @@ -340,7 +340,7 @@ $ hg push ssh://user:erroneouspwd@dummy/remote pushing to ssh://user:*@dummy/remote (glob) - abort: password in URL not supported! + abort: password in URL not supported [255] $ cd $TESTTMP @@ -359,7 +359,7 @@ 73649e48688a $ hg id --ssh "\"$PYTHON\" \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO" - abort: unknown revision 'noNoNO'! + abort: unknown revision 'noNoNO' [255] Test (non-)escaping of remote paths with spaces when cloning (issue3145): @@ -367,7 +367,7 @@ $ hg clone --ssh "\"$PYTHON\" \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" destination directory: a repo abort: destination 'a repo' is not empty - [255] + [10] Test hg-ssh using a helper script that will restore PYTHONPATH (which might have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right @@ -387,12 +387,12 @@ $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo" remote: Illegal repository "$TESTTMP/a'repo" - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo" remote: Illegal command "hacking -R 'a'\''repo' serve --stdio" - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ SSH_ORIGINAL_COMMAND="'hg' serve -R 'a'repo' --stdio" "$PYTHON" "$TESTDIR/../contrib/hg-ssh"
--- a/tests/test-ssh-proto.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-ssh-proto.t Thu Dec 03 14:15:39 2020 -0500 @@ -270,7 +270,7 @@ sending between command remote: 0 remote: 1 - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] Sending an unknown command to the server results in an empty response to that command
--- a/tests/test-ssh-repoerror.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-ssh-repoerror.t Thu Dec 03 14:15:39 2020 -0500 @@ -17,7 +17,7 @@ $ hg id ssh://user@dummy/no-read remote: abort: Permission denied: *$TESTTMP/no-read/.hg* (glob) - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] special case files are visible, but unreadable @@ -35,7 +35,7 @@ $ hg id ssh://user@dummy/other remote: abort: Permission denied: '$TESTTMP/other/.hg/requires' - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] directory toward the repository is read only @@ -51,7 +51,7 @@ $ hg id ssh://user@dummy/deep/nested remote: abort: Permission denied: *$TESTTMP/deep/nested/.hg* (glob) - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] repository has wrong requirement @@ -62,7 +62,7 @@ 000000000000 $ echo flying-car >> repo-future/.hg/requires $ hg id ssh://user@dummy/repo-future - remote: abort: repository requires features unknown to this Mercurial: flying-car! + remote: abort: repository requires features unknown to this Mercurial: flying-car remote: (see https://mercurial-scm.org/wiki/MissingRequirement for more information) - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255]
--- a/tests/test-ssh.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-ssh.t Thu Dec 03 14:15:39 2020 -0500 @@ -43,19 +43,19 @@ repo not found error $ hg clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local - remote: abort: repository nonexistent not found! - abort: no suitable response from remote hg! + remote: abort: repository nonexistent not found + abort: no suitable response from remote hg [255] $ hg clone -q -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local - remote: abort: repository nonexistent not found! - abort: no suitable response from remote hg! + remote: abort: repository nonexistent not found + abort: no suitable response from remote hg [255] non-existent absolute path $ hg clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/`pwd`/nonexistent local - remote: abort: repository $TESTTMP/nonexistent not found! - abort: no suitable response from remote hg! + remote: abort: repository $TESTTMP/nonexistent not found + abort: no suitable response from remote hg [255] clone remote via stream @@ -135,8 +135,8 @@ $ hg pull -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist pulling from ssh://user@dummy/doesnotexist - remote: abort: repository doesnotexist not found! - abort: no suitable response from remote hg! + remote: abort: repository doesnotexist not found + abort: no suitable response from remote hg [255] local change @@ -360,7 +360,7 @@ $ hg push ssh://user:erroneouspwd@dummy/remote pushing to ssh://user:*@dummy/remote (glob) - abort: password in URL not supported! + abort: password in URL not supported [255] $ cd $TESTTMP @@ -379,7 +379,7 @@ 73649e48688a $ hg id --ssh "\"$PYTHON\" \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO" - abort: unknown revision 'noNoNO'! + abort: unknown revision 'noNoNO' [255] Test (non-)escaping of remote paths with spaces when cloning (issue3145): @@ -387,7 +387,7 @@ $ hg clone --ssh "\"$PYTHON\" \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" destination directory: a repo abort: destination 'a repo' is not empty - [255] + [10] Make sure hg is really paranoid in serve --stdio mode. It used to be possible to get a debugger REPL by specifying a repo named --debugger. @@ -420,12 +420,12 @@ $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo" remote: Illegal repository "$TESTTMP/a'repo" - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo" remote: Illegal command "hacking -R 'a'\''repo' serve --stdio" - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" "$PYTHON" "$TESTDIR/../contrib/hg-ssh" @@ -675,7 +675,7 @@ $ hg pull ssh://brokenrepository -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" pulling from ssh://brokenrepository/ - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] abort with configured error hint when there is a ssh problem when pulling @@ -683,7 +683,7 @@ $ hg pull ssh://brokenrepository -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" \ > --config ui.ssherrorhint="Please see http://company/internalwiki/ssh.html" pulling from ssh://brokenrepository/ - abort: no suitable response from remote hg! + abort: no suitable response from remote hg (Please see http://company/internalwiki/ssh.html) [255] @@ -696,11 +696,11 @@ $ hg pull ssh://something --config ui.ssh="sh dumpenv" pulling from ssh://something/ remote: - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ hg pull ssh://something --config ui.ssh="sh dumpenv" --config sshenv.VAR=17 pulling from ssh://something/ remote: 17 - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255]
--- a/tests/test-state-extension.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-state-extension.t Thu Dec 03 14:15:39 2020 -0500 @@ -101,7 +101,7 @@ merging file1 warning: conflicts while merging file1! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg chainify --continue') - [1] + [240] $ hg status --config commands.status.verbose=True M file1 ? file1.orig
--- a/tests/test-static-http.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-static-http.t Thu Dec 03 14:15:39 2020 -0500 @@ -2,7 +2,7 @@ $ hg clone http://localhost:$HGPORT/ copy abort: * (glob) - [255] + [100] $ test -d copy [1] @@ -94,7 +94,7 @@ $ cd .. $ hg clone -r doesnotexist static-http://localhost:$HGPORT/remote local0 - abort: unknown revision 'doesnotexist'! + abort: unknown revision 'doesnotexist' [255] $ hg clone -r 0 static-http://localhost:$HGPORT/remote local0 adding changesets @@ -169,7 +169,7 @@ $ cd .. $ mkdir notarepo $ hg clone static-http://localhost:$HGPORT/notarepo local3 - abort: 'http://localhost:$HGPORT/notarepo' does not appear to be an hg repository! + abort: 'http://localhost:$HGPORT/notarepo' does not appear to be an hg repository [255] Clone with tags and branches works
--- a/tests/test-status-inprocess.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-status-inprocess.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 from __future__ import absolute_import, print_function import sys
--- a/tests/test-status-terse.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-status-terse.t Thu Dec 03 14:15:39 2020 -0500 @@ -24,7 +24,7 @@ ? x/bb.o $ hg status --terse f abort: 'f' not recognized - [255] + [10] Add a .hgignore so that we can also have ignored files @@ -224,7 +224,7 @@ $ hg status --terse marduic --rev 0 --rev 1 abort: cannot use --terse with --rev - [255] + [10] Config item to set the default terseness $ cat <<EOF >> $HGRCPATH
--- a/tests/test-stdio.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-stdio.py Thu Dec 03 14:15:39 2020 -0500 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ Tests the buffering behavior of stdio streams in `mercurial.utils.procutil`. """
--- a/tests/test-strip.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-strip.t Thu Dec 03 14:15:39 2020 -0500 @@ -10,7 +10,7 @@ > hg up -C $1 > echo % before update $1, strip $2 > hg log -G -T '{rev}:{node}' - > hg --traceback strip $2 + > hg --traceback debugstrip $2 > echo % after update $1, strip $2 > hg log -G -T '{rev}:{node}' > restore @@ -317,7 +317,7 @@ $ hg strip 4 abort: outstanding uncommitted merge (use 'hg commit' or 'hg merge --abort') - [255] + [20] ##strip allowed --force with merge in progress $ hg strip 4 --force 1 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -606,7 +606,7 @@ $ echo c > b $ hg strip tip abort: uncommitted changes - [255] + [20] $ hg strip tip --keep saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob) $ hg log --graph @@ -708,7 +708,7 @@ saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob) bookmark 'todelete' deleted $ hg id -ir dcbb326fdec2 - abort: unknown revision 'dcbb326fdec2'! + abort: unknown revision 'dcbb326fdec2' [255] $ hg id -ir d62d843c9a01 d62d843c9a01 @@ -724,17 +724,17 @@ bookmark 'multipledelete1' deleted bookmark 'multipledelete2' deleted $ hg id -ir e46a4836065c - abort: unknown revision 'e46a4836065c'! + abort: unknown revision 'e46a4836065c' [255] $ hg id -ir b4594d867745 - abort: unknown revision 'b4594d867745'! + abort: unknown revision 'b4594d867745' [255] $ hg strip -B singlenode1 -B singlenode2 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/43227190fef8-8da858f2-backup.hg bookmark 'singlenode1' deleted bookmark 'singlenode2' deleted $ hg id -ir 43227190fef8 - abort: unknown revision '43227190fef8'! + abort: unknown revision '43227190fef8' [255] $ hg strip -B unknownbookmark abort: bookmark 'unknownbookmark' not found @@ -749,7 +749,7 @@ saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob) bookmark 'delete' deleted $ hg id -ir 6:2702dd0c91e7 - abort: unknown revision '2702dd0c91e7'! + abort: unknown revision '2702dd0c91e7' [255] $ hg update B 0 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -758,20 +758,18 @@ $ hg add a $ hg strip -B B abort: uncommitted changes - [255] + [20] $ hg bookmarks * B 6:ff43616e5d0f Make sure no one adds back a -b option: $ hg strip -b tip - hg strip: option -b not recognized - hg strip [-k] [-f] [-B bookmark] [-r] REV... + hg debugstrip: option -b not recognized + hg debugstrip [-k] [-f] [-B bookmark] [-r] REV... strip changesets and all their descendants from the repository - (use 'hg help -e strip' to show help for the strip extension) - options ([+] can be repeated): -r --rev REV [+] strip specified revision (optional, can specify @@ -783,7 +781,7 @@ -B --bookmark BOOKMARK [+] remove revs only reachable from given bookmark --mq operate on patch repository - (use 'hg strip -h' to show more help) + (use 'hg debugstrip -h' to show more help) [255] $ cd ..
--- a/tests/test-subrepo-deep-nested-change.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-subrepo-deep-nested-change.t Thu Dec 03 14:15:39 2020 -0500 @@ -110,7 +110,7 @@ updating to branch default cloning subrepo sub1 from http://localhost:$HGPORT/../sub1 abort: HTTP Error 404: Not Found - [255] + [100] $ cat access.log * "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
--- a/tests/test-subrepo-recursion.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-subrepo-recursion.t Thu Dec 03 14:15:39 2020 -0500 @@ -575,7 +575,7 @@ $ hg --config progress.disable=True clone ../empty2 ../empty_clone updating to branch default cloning subrepo foo from $TESTTMP/empty2/foo - abort: repository $TESTTMP/empty2/foo not found! + abort: repository $TESTTMP/empty2/foo not found [255] Disable progress extension and cleanup: @@ -682,7 +682,7 @@ $ hg incoming -S --bundle incoming.hg abort: cannot specify both --subrepos and --bundle - [255] + [10] Test missing subrepo:
--- a/tests/test-subrepo-relative-path.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-subrepo-relative-path.t Thu Dec 03 14:15:39 2020 -0500 @@ -85,7 +85,7 @@ searching for changes no changes found abort: HTTP Error 403: ssl required - [255] + [100] Checking cloned repo ids
--- a/tests/test-subrepo.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-subrepo.t Thu Dec 03 14:15:39 2020 -0500 @@ -571,7 +571,7 @@ no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss pushing subrepo s to $TESTTMP/t/s searching for changes - abort: push creates new remote head 12a213df6fa9! (in subrepository "s") + abort: push creates new remote head 12a213df6fa9 (in subrepository "s") (merge or see 'hg help push' for details about pushing new heads) [255] $ hg push -f @@ -1013,7 +1013,7 @@ created new head $ hg -R repo2 ci -m3 $ hg -q -R repo2 push - abort: push creates new remote head cc505f09a8b2! (in subrepository "s") + abort: push creates new remote head cc505f09a8b2 (in subrepository "s") (merge or see 'hg help push' for details about pushing new heads) [255] $ hg -R repo update @@ -1280,7 +1280,7 @@ ../shared/subrepo-2/.hg/wcache/manifestfulltextcache (reporevlogstore !) ../shared/subrepo-2/file $ hg -R ../shared in - abort: repository default not found! + abort: repository default not found [255] $ hg -R ../shared/subrepo-2 showconfig paths paths.default=$TESTTMP/subrepo-status/subrepo-2 @@ -1964,7 +1964,7 @@ $ hg clone malicious-proxycommand malicious-proxycommand-clone updating to branch default cloning subrepo s from ssh://fakehost%7Ctouch%24%7BIFS%7Downed/path - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ [ ! -f owned ] || echo 'you got owned' @@ -1978,7 +1978,7 @@ $ hg clone malicious-proxycommand malicious-proxycommand-clone updating to branch default cloning subrepo s from ssh://fakehost%7Ctouch%20owned/path - abort: no suitable response from remote hg! + abort: no suitable response from remote hg [255] $ [ ! -f owned ] || echo 'you got owned'
--- a/tests/test-symlinks.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-symlinks.t Thu Dec 03 14:15:39 2020 -0500 @@ -198,7 +198,7 @@ $ ln -s nothing dangling $ hg commit -m 'commit symlink without adding' dangling abort: dangling: file not tracked! - [255] + [10] $ hg add dangling $ hg commit -m 'add symlink'
--- a/tests/test-tag.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-tag.t Thu Dec 03 14:15:39 2020 -0500 @@ -30,7 +30,7 @@ $ hg tag ' ' abort: tag names cannot consist entirely of whitespace - [255] + [10] (this tests also that editor is not invoked, if '--edit' is not specified) @@ -61,29 +61,29 @@ $ hg revert .hgtags $ hg tag -r 0 x y z y y z abort: tag names must be unique - [255] + [10] $ hg tag tap nada dot tip abort: the name 'tip' is reserved - [255] + [10] $ hg tag . abort: the name '.' is reserved - [255] + [10] $ hg tag null abort: the name 'null' is reserved - [255] + [10] $ hg tag "bleah" abort: tag 'bleah' already exists (use -f to force) - [255] + [10] $ hg tag "blecch" "bleah" abort: tag 'bleah' already exists (use -f to force) - [255] + [10] $ hg tag --remove "blecch" abort: tag 'blecch' does not exist - [255] + [10] $ hg tag --remove "bleah" "blecch" "blough" abort: tag 'blecch' does not exist - [255] + [10] $ hg tag -r 0 "bleah0" hook: tag changes detected @@ -105,13 +105,13 @@ $ hg tag "bleah " abort: tag 'bleah' already exists (use -f to force) - [255] + [10] $ hg tag " bleah" abort: tag 'bleah' already exists (use -f to force) - [255] + [10] $ hg tag " bleah" abort: tag 'bleah' already exists (use -f to force) - [255] + [10] $ hg tag -r 0 " bleahbleah " hook: tag changes detected hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleahbleah @@ -144,7 +144,7 @@ $ hg tag -l localblah $ hg tag "foobar" abort: working directory is not at a branch head (use -f to force) - [255] + [10] $ hg tag -f "foobar" hook: tag changes detected hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 foobar @@ -157,10 +157,10 @@ $ hg tag -l 'xx > newline' abort: '\n' cannot be used in a name - [255] + [10] $ hg tag -l 'xx:xx' abort: ':' cannot be used in a name - [255] + [10] cloning local tags @@ -401,16 +401,16 @@ 0 files updated, 0 files merged, 2 files removed, 0 files unresolved $ hg tag nullrev abort: working directory is not at a branch head (use -f to force) - [255] + [10] $ hg init empty $ hg tag -R empty nullrev abort: cannot tag null revision - [255] + [10] $ hg tag -R empty -r 00000000000 -f nulltag abort: cannot tag null revision - [255] + [10] issue5539: pruned tags do not appear in .hgtags @@ -492,11 +492,11 @@ $ hg tag t1 abort: uncommitted merge - [255] + [20] $ hg status $ hg tag --rev 1 t2 abort: uncommitted merge - [255] + [20] $ hg tag --rev 1 --local t3 $ hg tags -v tip 2:2a156e8887cc
--- a/tests/test-tags.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-tags.t Thu Dec 03 14:15:39 2020 -0500 @@ -505,7 +505,7 @@ $ hg tag --remove foobar abort: tag 'foobar' does not exist - [255] + [10] $ hg tip changeset: 5:5f6e8655b1c7 tag: tip @@ -555,7 +555,7 @@ $ hg tag -r 3 bar abort: tag 'bar' already exists (use -f to force) - [255] + [10] $ hg tags tip 6:735c3ca72986 bar 0:bbd179dfa0a7 @@ -622,12 +622,12 @@ $ hg tag -r 0 -l localtag $ hg tag --remove localtag abort: tag 'localtag' is not a global tag - [255] + [10] $ $ hg tag -r 0 globaltag $ hg tag --remove -l globaltag abort: tag 'globaltag' is not a local tag - [255] + [10] $ hg tags -v tip 1:a0b6fe111088 localtag 0:bbd179dfa0a7 local @@ -824,7 +824,7 @@ $ hg tag --remove a abort: tag 'a' is already removed - [255] + [10] $ hg log changeset: 2:e7feacc7ec9e tag: tip
--- a/tests/test-template-basic.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-template-basic.t Thu Dec 03 14:15:39 2020 -0500 @@ -139,7 +139,7 @@ * keywords: * functions: stringify hg: parse error: arithmetic only defined on integers - [255] + [10] $ hg debugtemplate -r0 -v '{-3|stringify}\n' (template (| @@ -179,7 +179,7 @@ * keywords: bar, foo * functions: baz hg: parse error: can't use a key-value pair in this context - [255] + [10] $ hg debugtemplate '{pad("foo", width=10, left=true)}\n' foo @@ -190,7 +190,7 @@ $ hg debugtemplate '{("not", "an", "argument", "list")|separate}' hg: parse error: can't use a list in this context (check place of comma and parens) - [255] + [10] Second branch starting at nullrev: @@ -307,34 +307,34 @@ $ echo 'style = t' >> .hg/hgrc $ hg log hg: parse error at t:3: unmatched quotes - [255] + [10] $ hg log -T '{date' hg: parse error at 1: unterminated template expansion ({date ^ here) - [255] + [10] $ hg log -T '{date(}' hg: parse error at 6: not a prefix: end ({date(} ^ here) - [255] + [10] $ hg log -T '{date)}' hg: parse error at 5: invalid token ({date)} ^ here) - [255] + [10] $ hg log -T '{date date}' hg: parse error at 6: invalid token ({date date} ^ here) - [255] + [10] $ hg log -T '{}' hg: parse error at 1: not a prefix: end ({} ^ here) - [255] + [10] $ hg debugtemplate -v '{()}' (template (group @@ -342,7 +342,7 @@ * keywords: * functions: hg: parse error: missing argument - [255] + [10] Behind the scenes, this would throw TypeError without intype=bytes @@ -356,7 +356,7 @@ $ hg log -l 3 --template 'line: {desc|shortdate}\n' hg: parse error: invalid date: 'Modify, add, remove, rename' (template filter 'shortdate' is not compatible with keyword 'desc') - [255] + [10] Behind the scenes, this would throw AttributeError without intype=bytes @@ -367,23 +367,23 @@ $ hg log -l 3 --template 'line: {extras|localdate}\n' hg: parse error: localdate expects a date information - [255] + [10] Behind the scenes, this will throw ValueError $ hg tip --template '{author|email|date}\n' hg: parse error: date expects a date information - [255] + [10] $ hg tip -T '{author|email|shortdate}\n' hg: parse error: invalid date: 'test' (template filter 'shortdate' is not compatible with keyword 'author') - [255] + [10] $ hg tip -T '{get(extras, "branch")|shortdate}\n' hg: parse error: invalid date: 'default' (incompatible use of template filter 'shortdate') - [255] + [10] Error in nested template: @@ -391,19 +391,19 @@ hg: parse error at 2: unterminated string ({"date ^ here) - [255] + [10] $ hg log -T '{"foo{date|?}"}' hg: parse error at 11: syntax error ({"foo{date|?}"} ^ here) - [255] + [10] Thrown an error if a template function doesn't exist $ hg tip --template '{foo()}\n' hg: parse error: unknown function 'foo' - [255] + [10] $ cd .. @@ -453,13 +453,13 @@ $ hg log -R latesttag -r tip -T '{rev % "a"}\n' hg: parse error: 11 is not iterable of mappings (keyword 'rev' does not support map operation) - [255] + [10] $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "a"}\n' hg: parse error: None is not iterable of mappings - [255] + [10] $ hg log -R latesttag -r tip -T '{extras % "{key}\n" % "{key}\n"}' hg: parse error: list of strings is not mappable - [255] + [10] Test new-style inline templating of non-list/dict type: @@ -474,7 +474,7 @@ branch: default $ hg log -R latesttag -r tip -T '{get(extras, "unknown") % "{key}\n"}' hg: parse error: None is not iterable of mappings - [255] + [10] $ hg log -R latesttag -r tip -T '{min(extras) % "{key}: {value}\n"}' branch: default $ hg log -R latesttag -l1 -T '{min(revset("0:9")) % "{rev}:{node|short}\n"}' @@ -506,7 +506,7 @@ (symbol 'bar') (symbol 'baz'))) (string '\n')) - [255] + [10] $ hg debugtemplate -R latesttag -r0 -v '{foo.bar()}\n' 2> /dev/null (template (. @@ -517,7 +517,7 @@ (string '\n')) * keywords: foo * functions: bar - [255] + [10] Test evaluation of dot operator: @@ -531,10 +531,10 @@ $ hg log -R latesttag -l1 -T '{author.invalid}\n' hg: parse error: 'test' is not a dictionary (keyword 'author' does not support member operation) - [255] + [10] $ hg log -R latesttag -l1 -T '{min("abc").invalid}\n' hg: parse error: 'a' is not a dictionary - [255] + [10] Test integer literal: @@ -567,10 +567,10 @@ hg: parse error at 3: not a prefix: ) ({(-)}\n ^ here) - [255] + [10] $ hg debugtemplate '{(-a)}\n' hg: parse error: negation needs an integer argument - [255] + [10] top-level integer literal is interpreted as symbol (i.e. variable name): @@ -607,10 +607,10 @@ $ hg log -Ra -r0 -T '{desc|1}\n' hg: parse error: expected a symbol, got 'integer' - [255] + [10] $ hg log -Ra -r0 -T '{1()}\n' hg: parse error: expected a symbol, got 'integer' - [255] + [10] Test string literal: @@ -748,13 +748,13 @@ hg: parse error at 21: unterminated string ({if(rev, "{if(rev, \")}")}\n ^ here) - [255] + [10] $ hg log -r 2 -T '{if(rev, \"\\"")}\n' hg: parse error: trailing \ in string - [255] + [10] $ hg log -r 2 -T '{if(rev, r\"\\"")}\n' hg: parse error: trailing \ in string - [255] + [10] $ cd .. @@ -900,7 +900,7 @@ text.1:wrapped (no-eol) $ hg log -l1 -T '{fill(desc, date, "", "")}\n' hg: parse error: fill expects an integer width - [255] + [10] $ hg log -l 1 --template '{sub(r"[0-9]", "-", author)}' {node|short} (no-eol) @@ -926,16 +926,16 @@ $ hg log -Gv -R a --template '{desc|user()}' hg: parse error: expected a symbol, got 'func' - [255] + [10] Test broken string escapes: $ hg log -T "bogus\\" -R a hg: parse error: trailing \ in string - [255] + [10] $ hg log -T "\\xy" -R a hg: parse error: invalid \x escape* (glob) - [255] + [10] Templater supports aliases of symbol and func() styles:
--- a/tests/test-template-functions.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-template-functions.t Thu Dec 03 14:15:39 2020 -0500 @@ -240,7 +240,7 @@ $ hg log -r null -T '{rev|commondir}' hg: parse error: argument is not a list of text (template filter 'commondir' is not compatible with keyword 'rev') - [255] + [10] Add a dummy commit to make up for the instability of the above: @@ -283,7 +283,7 @@ $ hg log -l1 -T '{termwidth|count}\n' hg: parse error: not countable (template filter 'count' is not compatible with keyword 'termwidth') - [255] + [10] Upper/lower filters: @@ -478,25 +478,25 @@ $ hg log -R a -r 0 -T '{filter()}\n' hg: parse error: filter expects one or two arguments - [255] + [10] $ hg log -R a -r 0 -T '{filter(date)}\n' hg: parse error: date is not iterable - [255] + [10] $ hg log -R a -r 0 -T '{filter(rev)}\n' hg: parse error: 0 is not iterable - [255] + [10] $ hg log -R a -r 0 -T '{filter(desc|firstline)}\n' hg: parse error: 'line 1' is not filterable - [255] + [10] $ hg log -R a -r 0 -T '{filter(manifest)}\n' hg: parse error: '0:a0c8bcbbb45c' is not filterable - [255] + [10] $ hg log -R a -r 0 -T '{filter(succsandmarkers)}\n' hg: parse error: not filterable without template - [255] + [10] $ hg log -R a -r 0 -T '{filter(desc|splitlines % "{line}", "")}\n' hg: parse error: not filterable by expression - [255] + [10] Test manifest/get() can be join()-ed as string, though it's silly: @@ -514,7 +514,7 @@ $ hg log -R latesttag -r tip -T '{join(rev, "")}\n' hg: parse error: 11 is not iterable - [255] + [10] Test min/max of integers @@ -542,47 +542,47 @@ $ hg debugtemplate '{min(1)}' hg: parse error: 1 is not iterable (min first argument should be an iterable) - [255] + [10] $ hg debugtemplate '{max(2)}' hg: parse error: 2 is not iterable (max first argument should be an iterable) - [255] + [10] $ hg log -R latesttag -l1 -T '{min(date)}' hg: parse error: date is not iterable (min first argument should be an iterable) - [255] + [10] $ hg log -R latesttag -l1 -T '{max(date)}' hg: parse error: date is not iterable (max first argument should be an iterable) - [255] + [10] Test min/max of empty sequence: $ hg debugtemplate '{min("")}' hg: parse error: empty string (min first argument should be an iterable) - [255] + [10] $ hg debugtemplate '{max("")}' hg: parse error: empty string (max first argument should be an iterable) - [255] + [10] $ hg debugtemplate '{min(dict())}' hg: parse error: empty sequence (min first argument should be an iterable) - [255] + [10] $ hg debugtemplate '{max(dict())}' hg: parse error: empty sequence (max first argument should be an iterable) - [255] + [10] $ hg debugtemplate '{min(dict() % "")}' hg: parse error: empty sequence (min first argument should be an iterable) - [255] + [10] $ hg debugtemplate '{max(dict() % "")}' hg: parse error: empty sequence (max first argument should be an iterable) - [255] + [10] Test min/max of if() result @@ -606,7 +606,7 @@ $ hg debugtemplate '{count(0)}' hg: parse error: not countable (incompatible use of template filter 'count') - [255] + [10] $ hg debugtemplate '{if(true, "", count(0))}' $ hg debugtemplate '{if(false, count(0), "")}' $ hg debugtemplate '{ifcontains("a", "aa", "", count(0))}' @@ -654,10 +654,10 @@ $ hg log -R a -r2 -T '{search(r"(?P<0>.)", desc) % "{0}"}\n' hg: parse error: search got an invalid pattern: (?P<0>.) - [255] + [10] $ hg log -R a -r2 -T '{search(r"(?P<repo>.)", desc) % "{repo}"}\n' hg: parse error: invalid group 'repo' in search pattern: (?P<repo>.) - [255] + [10] Test the sub function of templating for expansion: @@ -666,10 +666,10 @@ $ hg log -R latesttag -r 10 -T '{sub("[", "x", rev)}\n' hg: parse error: sub got an invalid pattern: [ - [255] + [10] $ hg log -R latesttag -r 10 -T '{sub("[0-9]", r"\1", rev)}\n' hg: parse error: sub got an invalid replacement: \1 - [255] + [10] Test the strip function with chars specified: @@ -721,7 +721,7 @@ $ hg log -R latesttag -T '{date(rev)}\n' hg: parse error: date expects a date information - [255] + [10] Set up repository containing template fragments in commit metadata: @@ -789,17 +789,17 @@ $ hg log -r 0 -T '{dict(rev, rev=rev)}\n' hg: parse error: duplicated dict key 'rev' inferred - [255] + [10] $ hg log -r 0 -T '{dict(node, node|short)}\n' hg: parse error: duplicated dict key 'node' inferred - [255] + [10] $ hg log -r 0 -T '{dict(1 + 2)}' hg: parse error: dict key cannot be inferred - [255] + [10] $ hg log -r 0 -T '{dict(x=rev, x=node)}' hg: parse error: dict got multiple values for keyword argument 'x' - [255] + [10] Test get function: @@ -810,7 +810,7 @@ $ hg log -r 0 --template '{get(files, "should_fail")}\n' hg: parse error: not a dictionary (get() expects a dict as first argument) - [255] + [10] Test json filter applied to wrapped object: @@ -836,7 +836,7 @@ 1970-01-01 00:00 +0000 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "blahUTC")|isodate}\n' hg: parse error: localdate expects a timezone - [255] + [10] $ TZ=JST-09 hg log -r0 -T '{localdate(date, "+0200")|isodate}\n' 1970-01-01 02:00 +0200 $ TZ=JST-09 hg log -r0 -T '{localdate(date, "0")|isodate}\n' @@ -845,10 +845,10 @@ 1970-01-01 00:00 +0000 $ hg log -r0 -T '{localdate(date, "invalid")|isodate}\n' hg: parse error: localdate expects a timezone - [255] + [10] $ hg log -r0 -T '{localdate(date, date)|isodate}\n' hg: parse error: localdate expects a timezone - [255] + [10] Test shortest(node) function: @@ -871,7 +871,7 @@ f7769ec2ab $ hg log -r 0 -T '{shortest(node, "not an int")}\n' hg: parse error: shortest() expects an integer minlength - [255] + [10] $ hg log -r 'wdir()' -T '{node|shortest}\n' ffff @@ -1070,16 +1070,16 @@ 0 test $ hg log -r 0 -T '{pad(rev, "not an int")}\n' hg: parse error: pad() expects an integer width - [255] + [10] Test invalid fillchar passed to pad function $ hg log -r 0 -T '{pad(rev, 10, "")}\n' hg: parse error: pad() expects a single fill character - [255] + [10] $ hg log -r 0 -T '{pad(rev, 10, "--")}\n' hg: parse error: pad() expects a single fill character - [255] + [10] Test boolean argument passed to pad function @@ -1294,60 +1294,60 @@ $ hg log -T '{revset("%d", rev)}\n' -r'null' -1 $ hg log -T '{revset("%d", rev + 1)}\n' -r'tip' - abort: unknown revision '3'! + abort: unknown revision '3' [255] $ hg log -T '{revset("%d", rev - 1)}\n' -r'null' - abort: unknown revision '-2'! + abort: unknown revision '-2' [255] Invalid arguments passed to revset() $ hg log -T '{revset("%whatever", 0)}\n' hg: parse error: unexpected revspec format character w - [255] + [10] $ hg log -T '{revset("%lwhatever", files)}\n' hg: parse error: unexpected revspec format character w - [255] + [10] $ hg log -T '{revset("%s %s", 0)}\n' hg: parse error: missing argument for revspec - [255] + [10] $ hg log -T '{revset("", 0)}\n' hg: parse error: too many revspec arguments specified - [255] + [10] $ hg log -T '{revset("%s", 0, 1)}\n' hg: parse error: too many revspec arguments specified - [255] + [10] $ hg log -T '{revset("%", 0)}\n' hg: parse error: incomplete revspec format character - [255] + [10] $ hg log -T '{revset("%l", 0)}\n' hg: parse error: incomplete revspec format character - [255] + [10] $ hg log -T '{revset("%d", 'foo')}\n' hg: parse error: invalid argument for revspec - [255] + [10] $ hg log -T '{revset("%ld", files)}\n' hg: parse error: invalid argument for revspec - [255] + [10] $ hg log -T '{revset("%ls", 0)}\n' hg: parse error: invalid argument for revspec - [255] + [10] $ hg log -T '{revset("%b", 'foo')}\n' hg: parse error: invalid argument for revspec - [255] + [10] $ hg log -T '{revset("%lb", files)}\n' hg: parse error: invalid argument for revspec - [255] + [10] $ hg log -T '{revset("%r", 0)}\n' hg: parse error: invalid argument for revspec - [255] + [10] Invalid operation on revset() $ hg log -T '{get(revset(":"), "foo")}\n' hg: parse error: not a dictionary (get() expects a dict as first argument) - [255] + [10] Test files function @@ -1432,7 +1432,7 @@ Test startswith $ hg log -Gv -R a --template "{startswith(desc)}" hg: parse error: startswith expects two arguments - [255] + [10] $ hg log -Gv -R a --template "{startswith('line', desc)}" @ @@ -1514,11 +1514,11 @@ $ hg log -Gv -R a --template "{word('0')}" hg: parse error: word expects two or three arguments, got 1 - [255] + [10] $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}" hg: parse error: word expects two or three arguments, got 7 - [255] + [10] Test word for integer literal @@ -1529,7 +1529,7 @@ $ hg log -Gv -R a --template "{word('a', desc)}" hg: parse error: word expects an integer index - [255] + [10] Test word for out of range
--- a/tests/test-template-graph.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-template-graph.t Thu Dec 03 14:15:39 2020 -0500 @@ -381,13 +381,13 @@ $ hg log -T '{subsetparents()}\n' hg: parse error: subsetparents expects two arguments - [255] + [10] $ hg log -T '{subsetparents("a")}\n' hg: parse error: subsetparents expects two arguments - [255] + [10] $ hg log -T '{subsetparents(rev, extras)}\n' hg: parse error: subsetparents expects a queried revset - [255] + [10] $ cd ..
--- a/tests/test-template-keywords.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-template-keywords.t Thu Dec 03 14:15:39 2020 -0500 @@ -114,6 +114,30 @@ | o 0 (public): -1 (public) -1 (public) +Test {onelinesummary} + + $ hg log -G -T '{onelinesummary}' + @ 8:95c24699272e tip "third" + | + o 7:29114dbae42b "second" + + o 6:d41e714fe50d "merge" + |\ + | o 5:13207e5a10d9 "new head" + | | + o | 4:bbe44766e73d "new branch" + |/ + o 3:10e46f2dcbf4 "no user, no domain" + | + o 2:97054abb4ab8 "no person" + | + o 1:b608e9d1a3f0 "other 1" + | + o 0:1e4e1b8f71e0 "line 1" + + $ hg log -T '{onelinesummary}' -r 0 \ + > --config command-templates.oneline-summary='{rev} - {desc}' + 0 - line 1 (no-eol) Keys work:
--- a/tests/test-template-map.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-template-map.t Thu Dec 03 14:15:39 2020 -0500 @@ -48,8 +48,9 @@ Make sure user/global hgrc does not affect tests + $ echo '[command-templates]' > .hg/hgrc + $ echo 'log =' >> .hg/hgrc $ echo '[ui]' > .hg/hgrc - $ echo 'logtemplate =' >> .hg/hgrc $ echo 'style =' >> .hg/hgrc Add some simple styles to settings @@ -1241,7 +1242,7 @@ hg: parse error at 6: not a prefix: ) (json(-) ^ here) - [255] + [10] For backward compatibility, the following examples are not parsed as function-style references: @@ -1300,7 +1301,7 @@ $ echo 'changeset =' > t $ hg log --style t hg: parse error at t:1: missing value - [255] + [10] Error if include fails:
--- a/tests/test-transplant.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-transplant.t Thu Dec 03 14:15:39 2020 -0500 @@ -19,10 +19,10 @@ [255] $ hg transplant --continue --all abort: cannot specify both --continue and --all - [255] + [10] $ hg transplant --stop --all abort: cannot specify both --stop and --all - [255] + [10] $ hg transplant --all tip abort: --all requires a branch revision [255] @@ -53,12 +53,12 @@ $ hg transplant 1 abort: outstanding uncommitted merge (use 'hg commit' or 'hg merge --abort') - [255] + [20] $ hg up -qC tip $ echo b0 > b1 $ hg transplant 1 abort: uncommitted changes - [255] + [20] $ hg up -qC tip $ echo b2 > b2 $ hg ci -Amb2 -d '1 0' @@ -513,10 +513,10 @@ $ hg continue abort: no transplant to continue (continueflag !) abort: no operation in progress (no-continueflag !) - [255] + [20] $ hg transplant --stop abort: no interrupted transplant found - [255] + [20] $ hg transplant 1 applying 46ae92138f3c patching file foo @@ -571,7 +571,7 @@ $ hg transplant 1:3 abort: transplant in progress (use 'hg transplant --continue' or 'hg transplant --stop') - [255] + [20] $ hg status -v A bar ? added.rej
--- a/tests/test-treediscovery-legacy.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-treediscovery-legacy.t Thu Dec 03 14:15:39 2020 -0500 @@ -122,7 +122,7 @@ $ cd empty1 $ hg incoming $remote --rev name1 comparing with http://localhost:$HGPORT/ - abort: cannot look up remote changes; remote repository does not support the 'changegroupsubset' capability! + abort: cannot look up remote changes; remote repository does not support the 'changegroupsubset' capability [255] $ hg incoming $remote comparing with http://localhost:$HGPORT/ @@ -285,7 +285,7 @@ $ hg push $remote pushing to http://localhost:$HGPORT/ searching for changes - abort: push creates new remote branches: both, name1! + abort: push creates new remote branches: both, name1 (use 'hg push --new-branch' to create new remote branches) [255] $ hg push $remote --new-branch @@ -311,7 +311,7 @@ $ hg init partial; cd partial $ hg incoming $remote --rev name2 comparing with http://localhost:$HGPORT/ - abort: cannot look up remote changes; remote repository does not support the 'changegroupsubset' capability! + abort: cannot look up remote changes; remote repository does not support the 'changegroupsubset' capability [255] $ hg pull $remote --rev name2 pulling from http://localhost:$HGPORT/
--- a/tests/test-treediscovery.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-treediscovery.t Thu Dec 03 14:15:39 2020 -0500 @@ -3,8 +3,8 @@ $ CAP="getbundle bundle2" $ . "$TESTDIR/notcapable" $ cat >> $HGRCPATH <<EOF - > [ui] - > logtemplate="{rev} {node|short}: {desc} {branches}\n" + > [command-templates] + > log="{rev} {node|short}: {desc} {branches}\n" > EOF Setup HTTP server control: @@ -269,7 +269,7 @@ $ hg push $remote pushing to http://localhost:$HGPORT/ searching for changes - abort: push creates new remote branches: both, name1! + abort: push creates new remote branches: both, name1 (use 'hg push --new-branch' to create new remote branches) [255] $ hg push $remote --new-branch
--- a/tests/test-trusted.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-trusted.py Thu Dec 03 14:15:39 2020 -0500 @@ -254,26 +254,15 @@ f.write(b'foo') f.close() -# This is a hack to remove b'' prefixes from ParseError.__bytes__ on -# Python 3. -def normalizeparseerror(e): - if pycompat.ispy3: - args = [a.decode('utf-8') for a in e.args] - else: - args = e.args - - return error.ParseError(*args) - - try: testui(user=b'abc', group=b'def', silent=True) -except error.ParseError as inst: - bprint(normalizeparseerror(inst)) +except error.ConfigError as inst: + bprint(inst.format()) try: testui(debug=True, silent=True) -except error.ParseError as inst: - bprint(normalizeparseerror(inst)) +except error.ConfigError as inst: + bprint(inst.format()) print() bprint(b'# access typed information')
--- a/tests/test-trusted.py.out Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-trusted.py.out Thu Dec 03 14:15:39 2020 -0500 @@ -174,9 +174,10 @@ # parse error # different user, different group not trusting file .hg/hgrc from untrusted user abc, group def -ignored: ('foo', '.hg/hgrc:1') +ignored .hg/hgrc:1: foo # same user, same group -ParseError('foo', '.hg/hgrc:1') +config error at .hg/hgrc:1: foo + # access typed information # different user, different group
--- a/tests/test-unamend.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-unamend.t Thu Dec 03 14:15:39 2020 -0500 @@ -284,7 +284,7 @@ $ hg --config experimental.evolution=createmarkers unamend abort: cannot unamend changeset with children - [255] + [10] $ hg unamend 3 new orphan changesets @@ -298,7 +298,7 @@ $ hg unamend abort: cannot unamend public changesets (see 'hg help phases' for details) - [255] + [10] Testing whether unamend retains copies or not @@ -405,8 +405,10 @@ $ hg co -q 0 $ hg mv a b $ hg ci -qm 'move to a b' + warning: commit already existed in the repository! $ hg mv b c $ hg amend + warning: commit already existed in the repository! $ hg mv c d $ hg unamend $ hg st --copies --change .
--- a/tests/test-uncommit.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-uncommit.t Thu Dec 03 14:15:39 2020 -0500 @@ -53,7 +53,7 @@ $ hg uncommit abort: cannot uncommit null changeset (no changeset checked out) - [255] + [10] Create some commits @@ -168,11 +168,11 @@ $ hg uncommit abort: uncommitted changes (requires --allow-dirty-working-copy to uncommit) - [255] + [20] $ hg uncommit files abort: uncommitted changes (requires --allow-dirty-working-copy to uncommit) - [255] + [20] $ cat files abcde foo @@ -184,7 +184,7 @@ $ hg uncommit abort: uncommitted changes (requires --allow-dirty-working-copy to uncommit) - [255] + [20] $ hg uncommit --config experimental.uncommitondirtywdir=True $ hg commit -m "files abcde + foo" @@ -407,11 +407,11 @@ $ hg uncommit abort: outstanding uncommitted merge (requires --allow-dirty-working-copy to uncommit) - [255] + [20] $ hg uncommit --config experimental.uncommitondirtywdir=True abort: cannot uncommit while merging - [255] + [20] $ hg status M a @@ -507,7 +507,7 @@ $ hg uncommit b abort: uncommitted changes (requires --allow-dirty-working-copy to uncommit) - [255] + [20] $ hg uncommit --allow-dirty-working-copy b $ hg log changeset: 3:30fa958635b2 @@ -556,10 +556,10 @@ $ hg rollback -q --config ui.rollback=True $ hg uncommit -U --user 'user' abort: cannot specify both --user and --currentuser - [255] + [10] $ hg uncommit -D --date today abort: cannot specify both --date and --currentdate - [255] + [10] `uncommit <dir>` and `cd <dir> && uncommit .` behave the same...
--- a/tests/test-update-branches.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-update-branches.t Thu Dec 03 14:15:39 2020 -0500 @@ -57,8 +57,8 @@ $ cd .. $ hg update b1 - abort: no repository found in '$TESTTMP' (.hg not found)! - [255] + abort: no repository found in '$TESTTMP' (.hg not found) + [10] $ cd b1 Test helper functions: @@ -348,7 +348,7 @@ $ rm a.orig $ hg ci -m empty abort: unresolved merge conflicts (see 'hg help resolve') - [255] + [20] $ hg resolve -m a (no more unresolved files) $ hg resolve -l @@ -701,6 +701,6 @@ > EOF $ hg co 2 abort: uncommitted changes - [255] + [20] $ hg co --no-check 2 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-update-dest.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-update-dest.t Thu Dec 03 14:15:39 2020 -0500 @@ -11,7 +11,7 @@ $ hg up abort: you must specify a destination (for example: hg update ".::") - [255] + [10] $ hg up . 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ HGPLAIN=1 hg up @@ -32,7 +32,7 @@ $ hg pull --update abort: update destination required by configuration (use hg pull followed by hg update DEST) - [255] + [10] $ cd ..
--- a/tests/test-update-issue1456.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-update-issue1456.t Thu Dec 03 14:15:39 2020 -0500 @@ -19,7 +19,7 @@ $ echo dirty > foo $ hg up -c abort: uncommitted changes - [255] + [20] $ hg up -q $ cat foo dirty
--- a/tests/test-upgrade-repo.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-upgrade-repo.t Thu Dec 03 14:15:39 2020 -0500 @@ -56,6 +56,7 @@ fncache: yes dotencode: yes generaldelta: yes + exp-sharesafe: no sparserevlog: yes sidedata: no persistent-nodemap: no @@ -68,6 +69,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no no no persistent-nodemap: no no no @@ -80,6 +82,7 @@ fncache: yes no yes dotencode: yes no yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no no no persistent-nodemap: no no no @@ -92,6 +95,7 @@ [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes] [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes] [formatvariant.name.uptodate|generaldelta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes] + [formatvariant.name.uptodate|exp-sharesafe: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] [formatvariant.name.uptodate|sparserevlog: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes] [formatvariant.name.uptodate|sidedata: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] @@ -120,6 +124,12 @@ "repo": true }, { + "config": false, + "default": false, + "name": "exp-sharesafe", + "repo": false + }, + { "config": true, "default": true, "name": "sparserevlog", @@ -266,6 +276,7 @@ fncache: no dotencode: no generaldelta: no + exp-sharesafe: no sparserevlog: no sidedata: no persistent-nodemap: no @@ -278,6 +289,7 @@ fncache: no yes yes dotencode: no yes yes generaldelta: no yes yes + exp-sharesafe: no no no sparserevlog: no yes yes sidedata: no no no persistent-nodemap: no no no @@ -290,6 +302,7 @@ fncache: no yes yes dotencode: no yes yes generaldelta: no no yes + exp-sharesafe: no no no sparserevlog: no no yes sidedata: no no no persistent-nodemap: no no no @@ -302,6 +315,7 @@ [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes] [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes] [formatvariant.name.mismatchdefault|generaldelta: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes] + [formatvariant.name.uptodate|exp-sharesafe: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] [formatvariant.name.mismatchdefault|sparserevlog: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes] [formatvariant.name.uptodate|sidedata: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] @@ -1289,6 +1303,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no no no persistent-nodemap: no no no @@ -1319,6 +1334,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no no no persistent-nodemap: no no no @@ -1352,6 +1368,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no no no persistent-nodemap: no no no @@ -1389,6 +1406,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: yes no no persistent-nodemap: no no no @@ -1426,6 +1444,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: no no no persistent-nodemap: no no no @@ -1463,6 +1482,7 @@ fncache: yes yes yes dotencode: yes yes yes generaldelta: yes yes yes + exp-sharesafe: no no no sparserevlog: yes yes yes sidedata: yes yes no persistent-nodemap: no no no
--- a/tests/test-username-newline.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-username-newline.t Thu Dec 03 14:15:39 2020 -0500 @@ -22,6 +22,6 @@ adding a transaction abort! rollback completed - abort: username 'foo\nbar3' contains a newline! + abort: username 'foo\nbar3' contains a newline [255]
--- a/tests/test-verify-repo-operations.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-verify-repo-operations.py Thu Dec 03 14:15:39 2020 -0500 @@ -112,7 +112,13 @@ min_size=1, ).map(lambda s: s.encode('utf-8')) -extensions = st.sampled_from(('shelve', 'mq', 'blackbox',)) +extensions = st.sampled_from( + ( + 'shelve', + 'mq', + 'blackbox', + ) +) @contextmanager @@ -233,7 +239,12 @@ t = r.read() assert ext not in t, t output = subprocess.check_output( - [runtests, tf, "--local",], stderr=subprocess.STDOUT + [ + runtests, + tf, + "--local", + ], + stderr=subprocess.STDOUT, ) assert "Ran 1 test" in output, output except subprocess.CalledProcessError as e: @@ -307,7 +318,8 @@ return content @rule( - target=branches, name=safetext, + target=branches, + name=safetext, ) def genbranch(self, name): return name @@ -343,7 +355,10 @@ "$ python -c 'import binascii; " "print(binascii.unhexlify(\"%s\"))' > %s" ) - % (binascii.hexlify(content), pipes.quote(path),) + % ( + binascii.hexlify(content), + pipes.quote(path), + ) ) @rule(path=paths) @@ -354,7 +369,9 @@ @rule(path=paths) def forgetpath(self, path): if os.path.exists(path): - with acceptableerrors("file is already untracked",): + with acceptableerrors( + "file is already untracked", + ): self.hg("forget", "--", path) @rule(s=st.none() | st.integers(0, 100)) @@ -420,7 +437,9 @@ return self.configperrepo.setdefault(self.currentrepo, {}) @rule( - target=repos, source=repos, name=reponames, + target=repos, + source=repos, + name=reponames, ) def clone(self, source, name): if not os.path.exists(os.path.join("..", name)): @@ -430,7 +449,8 @@ return name @rule( - target=repos, name=reponames, + target=repos, + name=reponames, ) def fresh(self, name): if not os.path.exists(os.path.join("..", name)): @@ -453,14 +473,16 @@ @rule() def pull(self, repo=repos): with acceptableerrors( - "repository default not found", "repository is unrelated", + "repository default not found", + "repository is unrelated", ): self.hg("pull") @rule(newbranch=st.booleans()) def push(self, newbranch): with acceptableerrors( - "default repository not configured", "no changes found", + "default repository not configured", + "no changes found", ): if newbranch: self.hg("push", "--new-branch") @@ -507,7 +529,8 @@ @rule(branch=branches, clean=st.booleans()) def update(self, branch, clean): with acceptableerrors( - 'unknown revision', 'parse error', + 'unknown revision', + 'parse error', ): if clean: self.hg("update", "-C", "--", branch) @@ -570,7 +593,12 @@ settings.register_profile( - 'default', settings(timeout=300, stateful_step_count=50, max_examples=10,) + 'default', + settings( + timeout=300, + stateful_step_count=50, + max_examples=10, + ), ) settings.register_profile(
--- a/tests/test-wireproto-caching.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-wireproto-caching.t Thu Dec 03 14:15:39 2020 -0500 @@ -451,7 +451,7 @@ > EOF creating http peer for wire protocol version 2 sending manifestdata command - abort: unknown node: \xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa! (esc) + abort: unknown node: \xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa (esc) [255] $ cat .hg/blackbox.log
--- a/tests/test-wireproto-clientreactor.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-wireproto-clientreactor.py Thu Dec 03 14:15:39 2020 -0500 @@ -486,13 +486,19 @@ response1 = b''.join( cborutil.streamencode( - {b'status': b'ok', b'extra': b'response1' * 10,} + { + b'status': b'ok', + b'extra': b'response1' * 10, + } ) ) response2 = b''.join( cborutil.streamencode( - {b'status': b'error', b'extra': b'response2' * 10,} + { + b'status': b'error', + b'extra': b'response2' * 10, + } ) ) @@ -678,13 +684,19 @@ response1 = b''.join( cborutil.streamencode( - {b'status': b'ok', b'extra': b'response1' * 10,} + { + b'status': b'ok', + b'extra': b'response1' * 10, + } ) ) response2 = b''.join( cborutil.streamencode( - {b'status': b'error', b'extra': b'response2' * 10,} + { + b'status': b'error', + b'extra': b'response2' * 10, + } ) )
--- a/tests/test-wireproto-command-changesetdata.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-wireproto-command-changesetdata.t Thu Dec 03 14:15:39 2020 -0500 @@ -44,7 +44,7 @@ > EOF creating http peer for wire protocol version 2 sending changesetdata command - abort: missing required arguments: revisions! + abort: missing required arguments: revisions [255] Missing nodes for changesetexplicit results in error @@ -55,7 +55,7 @@ > EOF creating http peer for wire protocol version 2 sending changesetdata command - abort: nodes key not present in changesetexplicit revision specifier! + abort: nodes key not present in changesetexplicit revision specifier [255] changesetexplicitdepth requires nodes and depth keys @@ -66,7 +66,7 @@ > EOF creating http peer for wire protocol version 2 sending changesetdata command - abort: nodes key not present in changesetexplicitdepth revision specifier! + abort: nodes key not present in changesetexplicitdepth revision specifier [255] $ sendhttpv2peer << EOF @@ -75,7 +75,7 @@ > EOF creating http peer for wire protocol version 2 sending changesetdata command - abort: depth key not present in changesetexplicitdepth revision specifier! + abort: depth key not present in changesetexplicitdepth revision specifier [255] $ sendhttpv2peer << EOF @@ -84,7 +84,7 @@ > EOF creating http peer for wire protocol version 2 sending changesetdata command - abort: nodes key not present in changesetexplicitdepth revision specifier! + abort: nodes key not present in changesetexplicitdepth revision specifier [255] changesetdagrange requires roots and heads keys @@ -95,7 +95,7 @@ > EOF creating http peer for wire protocol version 2 sending changesetdata command - abort: roots key not present in changesetdagrange revision specifier! + abort: roots key not present in changesetdagrange revision specifier [255] $ sendhttpv2peer << EOF @@ -104,7 +104,7 @@ > EOF creating http peer for wire protocol version 2 sending changesetdata command - abort: heads key not present in changesetdagrange revision specifier! + abort: heads key not present in changesetdagrange revision specifier [255] $ sendhttpv2peer << EOF @@ -113,7 +113,7 @@ > EOF creating http peer for wire protocol version 2 sending changesetdata command - abort: roots key not present in changesetdagrange revision specifier! + abort: roots key not present in changesetdagrange revision specifier [255] Empty changesetdagrange heads results in an error @@ -124,7 +124,7 @@ > EOF creating http peer for wire protocol version 2 sending changesetdata command - abort: heads key in changesetdagrange cannot be empty! + abort: heads key in changesetdagrange cannot be empty [255] Sending just dagrange heads sends all revisions
--- a/tests/test-wireproto-command-filedata.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-wireproto-command-filedata.t Thu Dec 03 14:15:39 2020 -0500 @@ -78,7 +78,7 @@ > EOF creating http peer for wire protocol version 2 sending filedata command - abort: missing required arguments: nodes, path! + abort: missing required arguments: nodes, path [255] $ sendhttpv2peer << EOF @@ -87,7 +87,7 @@ > EOF creating http peer for wire protocol version 2 sending filedata command - abort: missing required arguments: path! + abort: missing required arguments: path [255] Unknown node is an error @@ -99,7 +99,7 @@ > EOF creating http peer for wire protocol version 2 sending filedata command - abort: unknown file node: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa! + abort: unknown file node: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [255] Fetching a single revision returns just metadata by default
--- a/tests/test-wireproto-command-filesdata.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-wireproto-command-filesdata.t Thu Dec 03 14:15:39 2020 -0500 @@ -71,7 +71,7 @@ > EOF creating http peer for wire protocol version 2 sending filesdata command - abort: missing required arguments: revisions! + abort: missing required arguments: revisions [255] Bad pattern to pathfilter is rejected @@ -87,7 +87,7 @@ > EOF creating http peer for wire protocol version 2 sending filesdata command - abort: include pattern must begin with `path:` or `rootfilesin:`; got bad:foo! + abort: include pattern must begin with `path:` or `rootfilesin:`; got bad:foo [255] $ sendhttpv2peer << EOF @@ -101,7 +101,7 @@ > EOF creating http peer for wire protocol version 2 sending filesdata command - abort: exclude pattern must begin with `path:` or `rootfilesin:`; got glob:foo! + abort: exclude pattern must begin with `path:` or `rootfilesin:`; got glob:foo [255] Fetching a single changeset without parents fetches all files
--- a/tests/test-wireproto-command-manifestdata.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-wireproto-command-manifestdata.t Thu Dec 03 14:15:39 2020 -0500 @@ -49,7 +49,7 @@ > EOF creating http peer for wire protocol version 2 sending manifestdata command - abort: missing required arguments: nodes, tree! + abort: missing required arguments: nodes, tree [255] $ sendhttpv2peer << EOF @@ -58,7 +58,7 @@ > EOF creating http peer for wire protocol version 2 sending manifestdata command - abort: missing required arguments: tree! + abort: missing required arguments: tree [255] Unknown node is an error @@ -70,7 +70,7 @@ > EOF creating http peer for wire protocol version 2 sending manifestdata command - abort: unknown node: \xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa! (esc) + abort: unknown node: \xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa (esc) [255] Fetching a single revision returns just metadata by default
--- a/tests/test-wireproto-command-rawstorefiledata.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-wireproto-command-rawstorefiledata.t Thu Dec 03 14:15:39 2020 -0500 @@ -31,7 +31,7 @@ > EOF creating http peer for wire protocol version 2 sending rawstorefiledata command - abort: missing required arguments: files! + abort: missing required arguments: files [255] Unknown files value results in error @@ -42,7 +42,7 @@ > EOF creating http peer for wire protocol version 2 sending rawstorefiledata command - abort: unknown file type: unknown! + abort: unknown file type: unknown [255] Requesting just changelog works
--- a/tests/test-wireproto-framing.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-wireproto-framing.py Thu Dec 03 14:15:39 2020 -0500 @@ -192,7 +192,12 @@ stream = framing.stream(1) val = list( framing.createtextoutputframe( - stream, 1, [(b'foo', [], []), (b'bar', [], []),] + stream, + 1, + [ + (b'foo', [], []), + (b'bar', [], []), + ], ) ) @@ -210,7 +215,11 @@ stream = framing.stream(1) val = list( framing.createtextoutputframe( - stream, 1, [(b'foo %s', [b'val1'], []),] + stream, + 1, + [ + (b'foo %s', [b'val1'], []), + ], ) ) @@ -228,7 +237,11 @@ stream = framing.stream(1) val = list( framing.createtextoutputframe( - stream, 1, [(b'foo %s %s', [b'val', b'value'], []),] + stream, + 1, + [ + (b'foo %s %s', [b'val', b'value'], []), + ], ) ) @@ -246,7 +259,11 @@ stream = framing.stream(1) val = list( framing.createtextoutputframe( - stream, 1, [(b'foo', [], [b'label']),] + stream, + 1, + [ + (b'foo', [], [b'label']), + ], ) ) @@ -264,7 +281,11 @@ stream = framing.stream(1) val = list( framing.createtextoutputframe( - stream, 1, [(b'foo %s', [b'arg'], [b'label']),] + stream, + 1, + [ + (b'foo %s', [b'arg'], [b'label']), + ], ) )
--- a/tests/test-wireproto-serverreactor.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-wireproto-serverreactor.py Thu Dec 03 14:15:39 2020 -0500 @@ -202,7 +202,10 @@ { b'requestid': 1, b'command': b'command', - b'args': {b'key': b'val', b'foo': b'bar',}, + b'args': { + b'key': b'val', + b'foo': b'bar', + }, b'redirect': None, b'data': b'value1value2', }, @@ -356,7 +359,10 @@ self.assertaction(results[0], b'wantframe') self.assertaction(results[1], b'error') self.assertEqual( - results[1][1], {b'message': b'request with ID 1 already received',} + results[1][1], + { + b'message': b'request with ID 1 already received', + }, ) def testinterleavedcommands(self): @@ -364,7 +370,10 @@ cborutil.streamencode( { b'name': b'command1', - b'args': {b'foo': b'bar', b'key1': b'val',}, + b'args': { + b'foo': b'bar', + b'key1': b'val', + }, } ) ) @@ -372,7 +381,10 @@ cborutil.streamencode( { b'name': b'command3', - b'args': {b'biz': b'baz', b'key': b'val',}, + b'args': { + b'biz': b'baz', + b'key': b'val', + }, } ) ) @@ -461,7 +473,10 @@ self.assertaction(results[0], b'wantframe') self.assertaction(results[1], b'error') self.assertEqual( - results[1][1], {b'message': b'command data frame without flags',} + results[1][1], + { + b'message': b'command data frame without flags', + }, ) def testframefornonreceivingrequest(self): @@ -651,7 +666,10 @@ self.assertaction(results[0], b'error') self.assertEqual( - results[0][1], {b'message': b'request with ID 1 is already active',} + results[0][1], + { + b'message': b'request with ID 1 is already active', + }, ) def testduplicaterequestonactivecommandnosend(self): @@ -668,7 +686,10 @@ results = list(sendcommandframes(reactor, instream, 1, b'command1', {})) self.assertaction(results[0], b'error') self.assertEqual( - results[0][1], {b'message': b'request with ID 1 is already active',} + results[0][1], + { + b'message': b'request with ID 1 is already active', + }, ) def testduplicaterequestaftersend(self): @@ -763,7 +784,9 @@ data = b''.join( cborutil.streamencode( - {b'contentencodings': [b'value1', b'value2'],} + { + b'contentencodings': [b'value1', b'value2'], + } ) ) @@ -811,7 +834,10 @@ ) self.assertaction(result, b'error') self.assertEqual( - result[1], {b'message': b'expected command request frame; got 8',} + result[1], + { + b'message': b'expected command request frame; got 8', + }, )
--- a/tests/test-worker.t Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-worker.t Thu Dec 03 14:15:39 2020 -0500 @@ -85,11 +85,13 @@ [255] $ hg --config "extensions.t=$abspath" --config 'worker.numcpus=8' \ - > test 100000.0 abort --traceback 2>&1 | egrep '(SystemExit|Abort)' + > test 100000.0 abort --traceback 2>&1 | egrep '(WorkerError|Abort)' raise error.Abort(b'known exception') mercurial.error.Abort: known exception (py3 !) Abort: known exception (no-py3 !) - SystemExit: 255 + raise error.WorkerError(status) + WorkerError: 255 (no-py3 !) + mercurial.error.WorkerError: 255 (py3 !) Traceback must be printed for unknown exceptions
--- a/tests/test-wsgirequest.py Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/test-wsgirequest.py Thu Dec 03 14:15:39 2020 -0500 @@ -49,7 +49,12 @@ self.assertEqual(len(r.headers), 0) def testcustomport(self): - r = parse(DEFAULT_ENV, extra={'SERVER_PORT': '8000',}) + r = parse( + DEFAULT_ENV, + extra={ + 'SERVER_PORT': '8000', + }, + ) self.assertEqual(r.url, b'http://testserver:8000') self.assertEqual(r.baseurl, b'http://testserver:8000') @@ -58,7 +63,10 @@ r = parse( DEFAULT_ENV, - extra={'SERVER_PORT': '4000', 'wsgi.url_scheme': 'https',}, + extra={ + 'SERVER_PORT': '4000', + 'wsgi.url_scheme': 'https', + }, ) self.assertEqual(r.url, b'https://testserver:4000') @@ -67,7 +75,12 @@ self.assertEqual(r.advertisedbaseurl, b'https://testserver:4000') def testhttphost(self): - r = parse(DEFAULT_ENV, extra={'HTTP_HOST': 'altserver',}) + r = parse( + DEFAULT_ENV, + extra={ + 'HTTP_HOST': 'altserver', + }, + ) self.assertEqual(r.url, b'http://altserver') self.assertEqual(r.baseurl, b'http://altserver') @@ -75,7 +88,12 @@ self.assertEqual(r.advertisedbaseurl, b'http://testserver') def testscriptname(self): - r = parse(DEFAULT_ENV, extra={'SCRIPT_NAME': '',}) + r = parse( + DEFAULT_ENV, + extra={ + 'SCRIPT_NAME': '', + }, + ) self.assertEqual(r.url, b'http://testserver') self.assertEqual(r.baseurl, b'http://testserver') @@ -85,7 +103,12 @@ self.assertEqual(r.dispatchparts, []) self.assertIsNone(r.dispatchpath) - r = parse(DEFAULT_ENV, extra={'SCRIPT_NAME': '/script',}) + r = parse( + DEFAULT_ENV, + extra={ + 'SCRIPT_NAME': '/script', + }, + ) self.assertEqual(r.url, b'http://testserver/script') self.assertEqual(r.baseurl, b'http://testserver') @@ -95,7 +118,12 @@ self.assertEqual(r.dispatchparts, []) self.assertIsNone(r.dispatchpath) - r = parse(DEFAULT_ENV, extra={'SCRIPT_NAME': '/multiple words',}) + r = parse( + DEFAULT_ENV, + extra={ + 'SCRIPT_NAME': '/multiple words', + }, + ) self.assertEqual(r.url, b'http://testserver/multiple%20words') self.assertEqual(r.baseurl, b'http://testserver') @@ -106,7 +134,12 @@ self.assertIsNone(r.dispatchpath) def testpathinfo(self): - r = parse(DEFAULT_ENV, extra={'PATH_INFO': '',}) + r = parse( + DEFAULT_ENV, + extra={ + 'PATH_INFO': '', + }, + ) self.assertEqual(r.url, b'http://testserver') self.assertEqual(r.baseurl, b'http://testserver') @@ -116,7 +149,12 @@ self.assertEqual(r.dispatchparts, []) self.assertEqual(r.dispatchpath, b'') - r = parse(DEFAULT_ENV, extra={'PATH_INFO': '/pathinfo',}) + r = parse( + DEFAULT_ENV, + extra={ + 'PATH_INFO': '/pathinfo', + }, + ) self.assertEqual(r.url, b'http://testserver/pathinfo') self.assertEqual(r.baseurl, b'http://testserver') @@ -126,7 +164,12 @@ self.assertEqual(r.dispatchparts, [b'pathinfo']) self.assertEqual(r.dispatchpath, b'pathinfo') - r = parse(DEFAULT_ENV, extra={'PATH_INFO': '/one/two/',}) + r = parse( + DEFAULT_ENV, + extra={ + 'PATH_INFO': '/one/two/', + }, + ) self.assertEqual(r.url, b'http://testserver/one/two/') self.assertEqual(r.baseurl, b'http://testserver') @@ -139,7 +182,10 @@ def testscriptandpathinfo(self): r = parse( DEFAULT_ENV, - extra={'SCRIPT_NAME': '/script', 'PATH_INFO': '/pathinfo',}, + extra={ + 'SCRIPT_NAME': '/script', + 'PATH_INFO': '/pathinfo', + }, ) self.assertEqual(r.url, b'http://testserver/script/pathinfo') @@ -208,7 +254,9 @@ parse( DEFAULT_ENV, reponame=b'repo', - extra={'PATH_INFO': '/pathinfo',}, + extra={ + 'PATH_INFO': '/pathinfo', + }, ) with self.assertRaisesRegex( @@ -217,13 +265,17 @@ parse( DEFAULT_ENV, reponame=b'repo', - extra={'PATH_INFO': '/repoextra/path',}, + extra={ + 'PATH_INFO': '/repoextra/path', + }, ) r = parse( DEFAULT_ENV, reponame=b'repo', - extra={'PATH_INFO': '/repo/path1/path2',}, + extra={ + 'PATH_INFO': '/repo/path1/path2', + }, ) self.assertEqual(r.url, b'http://testserver/repo/path1/path2') @@ -238,7 +290,9 @@ r = parse( DEFAULT_ENV, reponame=b'prefix/repo', - extra={'PATH_INFO': '/prefix/repo/path1/path2',}, + extra={ + 'PATH_INFO': '/prefix/repo/path1/path2', + }, ) self.assertEqual(r.url, b'http://testserver/prefix/repo/path1/path2') @@ -307,7 +361,9 @@ r = parse( DEFAULT_ENV, altbaseurl=b'http://altserver', - extra={'PATH_INFO': '/path1/path2',}, + extra={ + 'PATH_INFO': '/path1/path2', + }, ) self.assertEqual(r.url, b'http://testserver/path1/path2') self.assertEqual(r.baseurl, b'http://testserver') @@ -347,7 +403,9 @@ r = parse( DEFAULT_ENV, altbaseurl=b'http://altserver/altpath', - extra={'PATH_INFO': '/path1/path2',}, + extra={ + 'PATH_INFO': '/path1/path2', + }, ) self.assertEqual(r.url, b'http://testserver/path1/path2') self.assertEqual(r.baseurl, b'http://testserver') @@ -365,7 +423,9 @@ r = parse( DEFAULT_ENV, altbaseurl=b'http://altserver/altpath/', - extra={'PATH_INFO': '/path1/path2',}, + extra={ + 'PATH_INFO': '/path1/path2', + }, ) self.assertEqual(r.url, b'http://testserver/path1/path2') self.assertEqual(r.baseurl, b'http://testserver') @@ -383,7 +443,10 @@ r = parse( DEFAULT_ENV, altbaseurl=b'http://altserver', - extra={'SCRIPT_NAME': '/script', 'PATH_INFO': '/path1/path2',}, + extra={ + 'SCRIPT_NAME': '/script', + 'PATH_INFO': '/path1/path2', + }, ) self.assertEqual(r.url, b'http://testserver/script/path1/path2') self.assertEqual(r.baseurl, b'http://testserver') @@ -399,7 +462,10 @@ r = parse( DEFAULT_ENV, altbaseurl=b'http://altserver/altroot', - extra={'SCRIPT_NAME': '/script', 'PATH_INFO': '/path1/path2',}, + extra={ + 'SCRIPT_NAME': '/script', + 'PATH_INFO': '/path1/path2', + }, ) self.assertEqual(r.url, b'http://testserver/script/path1/path2') self.assertEqual(r.baseurl, b'http://testserver') @@ -418,7 +484,10 @@ DEFAULT_ENV, reponame=b'repo', altbaseurl=b'http://altserver/altroot', - extra={'SCRIPT_NAME': '/script', 'PATH_INFO': '/repo/path1/path2',}, + extra={ + 'SCRIPT_NAME': '/script', + 'PATH_INFO': '/repo/path1/path2', + }, ) self.assertEqual(r.url, b'http://testserver/script/repo/path1/path2')
--- a/tests/testlib/exchange-obsmarker-util.sh Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/testlib/exchange-obsmarker-util.sh Thu Dec 03 14:15:39 2020 -0500 @@ -14,9 +14,9 @@ push_ssl = false allow_push = * -[ui] +[command-templates] # simpler log output -logtemplate ="{node|short} ({phase}): {desc}\n" +log ="{node|short} ({phase}): {desc}\n" [phases] # non publishing server
--- a/tests/testlib/push-checkheads-util.sh Thu Dec 03 13:36:24 2020 -0500 +++ b/tests/testlib/push-checkheads-util.sh Thu Dec 03 14:15:39 2020 -0500 @@ -1,9 +1,9 @@ # setup config and various utility to test new heads checks on push cat >> $HGRCPATH <<EOF -[ui] +[command-templates] # simpler log output -logtemplate ="{node|short} ({phase}): {desc}\n" +log ="{node|short} ({phase}): {desc}\n" [phases] # non publishing server