Mercurial > hg
changeset 47859:155a2ec8a9dc
merge with stable
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Sun, 22 Aug 2021 16:32:06 -0400 |
parents | de2e04fe4897 (current diff) df94c13ddf60 (diff) |
children | 08f16b3331df |
files | hgext/fix.py mercurial/configitems.py |
diffstat | 67 files changed, 2277 insertions(+), 305 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgsigs Tue Jul 20 17:20:19 2021 +0200 +++ b/.hgsigs Sun Aug 22 16:32:06 2021 -0400 @@ -211,3 +211,7 @@ f67b8946bb1b6cfa8328dbf8d6a9128b69ccdcb4 0 iQJEBAABCAAuFiEEK8zhT1xnJaouqK63ucncgkqlvdUFAmB+71MQHHJhZkBkdXJpbjQyLmNvbQAKCRC5ydyCSqW91Vj+EADBa/tHfgyymKmXXl9DSlzwEhX1DkCE0aRcsbfXujnpOQrDi09pfHvtYEbgJfl6m8JEUOjuRRcxofnIWOC9UJCGC3ZfW5tTcHomCFlqjHhUxGKsvQ1Wcec1IH3mmzhqLnd0X57EgnNC6APwgxNVRmC0q7M7rSlNiE8BkHEUuyCau5FvpgdF31Aqa9IQP95pmmeDwL4ByPR1Nssu2/8N5vbcQm55gdjcggNjBvNEbaFHDS9NlGS8quvCMwRZkr3meDfTeCs9d2MveXXvV8GVOFq+WHMoURVijTjON+HuXB7HLegyhVOcigfbU5zxGY/IAJ/tAYEzBLWSYW6wjsN5uuZP267XhKpd2FT8Cfe9t3OnN1K21ndltlaMSdGyAynuepzVE0IELOCiKlgBZkdnft2XkUt2DDg/TqhOeXmUBzIFVze5KULSgrFvjkx71iV22LUGkIxzIuW5ieBMeZotKHzI+ZXO7xNSDIdoSfERKUqfYJKbksnBQLRxYUO77KetjocsMMYyB4Dpzu05+eWpYtZs2u5PsqP/Jv84Mz3QR0szAI1h3KlhmbkvKxnWnFYasAdFPMluX4G4X+9+MulODCwgw/RvQhh13M2QP0vGb1Xzu/JOuxRr3zuliTUfszd7YHVJoROzuT9PlcZ4criwZwv+fvbCN+F9LRbeI/BQBVZi6w== 8d2b62d716b095507effaa8d56f87cd27ba659ab 0 iQJEBAABCAAuFiEEK8zhT1xnJaouqK63ucncgkqlvdUFAmCAO3gQHHJhZkBkdXJpbjQyLmNvbQAKCRC5ydyCSqW91YvWD/4kn4nLsu6W6hpSmB6qZB7y9adX8mqwzpSfnt0hwesk5FiBmGnDWHT5IvGHRTq0B3+peG9NH5R0h1WgtCdyh6YxGg0CZwNoarv64U8llS+PTXp8YZo/bVex7QGKQJr45Xik4ZH6htJ0muJUhzpHa6wkthTxK2OuaTTJvJ53lY8dR4lmefxSYPAwWs/jOzkmPwIeK8EnG0ZcBtmheJESOzKnmmOF6N4GnUGFFz/W5q8Gfeqj9xKKDt+zdPHXCEZUYivBcMPL7UNti2kvrp3R7VXBzbw/bPAJTrq68M4Z9mFb0qRZ88ubGXu+LEufsG2Dls/ZF0GnBPeReuFFrg9jimQqo6Rf/+4vV+GtFBY71aofFDDex9/s0q7skNEBxLP6r/KfsachYzvdciRS46zLelrL/NhpDvM6mHOLWmuycCeYShYctGbc2zDK7vD136Da6xlWU5Qci/+6zTtAjaKqdIpJuIzBfKdhaakri8vlpplpNLIDMfTTLyYKVAuHUtZcwHcHWmx54b2ulAmNXtc5yB/JqRIUined+Z6KlYc7c7MKEo2FB2/0okIbx7bIiXbV2of4j3ufv+NPIQel1qsnX58vbYL1spdfynNMTHQ+TYc9lUvuq31znu2LLJ9ZhTOiLEt1QZB28lTukzNuH2MEpGWtrOBIC9AcXjyyZ8HlIwEWMA== 067f2c53fb24506c9e9fb4639871b13b19a85f8a 0 iQJJBAABCgAzFiEEgY2HzRrBgMOUyG5jOjPeRg2ew58FAmCQMXEVHDc4OTVwdWxraXRAZ21haWwuY29tAAoJEDoz3kYNnsOfpJgP/isIDkbMuhot376RY2SwilSCkjJRoKRCDyLjJReBUF29t+DPWs8h971t2v5DIasfuQZthMv9A6DYcyEs1Q3NTKvT4TMKTTrqQfIe8UMmUa9PI1SIuTShiWbwonrN8rrVMVVcjPO/gookMV8/uoYW3wn/SThkBEYYauONBBVKbQ/Bt31/OPbEeAEdb/IEJ9X9PL1sfQkf+/DA/cwawS+xn01GAxWybx8eJkcJFdGdUcl/PYWgX76RSUhGvD6aHRJTZ1+sXy7+ligfpdPkNrQ248mVEEQkmZaCQ39dQPMX5zLa2hEX6eW9b1BEhNjHzbDfyqwc+F5czLw+R56vjPUyRCkxAZ6Q5Q3vkgLPBlZ2Ay0Lta/5+qGWcX+nDzfKfr2FhBLAnRZG/M+M2ckzR+8twyKg7/vdD8e/B3+Oxmu5QTS8xuj1628Brf9IehedQHoEPDe2M5ynhlEcybkbLz1R7zWKrh2h76OGQtspcjF997W1uZFx+DH6kHSznIm/8zEXy13R2nZk/0YtGX2UjZDv9bZ5X3B7T1673uscx3VpiT8YLJVKX7FyFLMgUbVY9ZGFlQ/pzUP3gTGa5rAB8b72U45jlXdKKvCn9B3hbS4j9OzJKpjsspWDmFHl2/a01ZOL/SZtMlm7FeYymUXKc10dndXlXTlGxHFUJQsii6t3dDyf +411dc27fd9fd076d6a031a08fcaace659afe2fe3 0 iQJJBAABCgAzFiEEgY2HzRrBgMOUyG5jOjPeRg2ew58FAmDnSgwVHDc4OTVwdWxraXRAZ21haWwuY29tAAoJEDoz3kYNnsOftvQP/j1mvheFHsv5TSJ2IEKgEK4G/cIxt+taoWpecEUVN5JAk7q4Y1xnzcoyqQdAyvZcTu7m4ESx865XW6Jvc0I2pG+uKcmO7ZfwrAOugoXXxrlXtopVfDDFZOLlk72x+Z5tQpL9QcBUgetkuOZLFhT+1ETjnFd2H4P4pwPjdTpn+YBmDmh1tWTMzllTDDzvZeE6iAjIpM9IQKL4jKxcEjPAX2XDa1xWhd/o9NZC9kYSTIBQvbFWAz3A0PSAudz0lu5YDXKJNtIHlzZtMFmcUlqJGM4MlD6v9tm8EQbCWTgOm0+wB5miDqv05aC6axD3LnSgrlPsmRDZCIRAws1JHEjKYFob7VRMxpivW7GDSd6QrmUbTHYN5eY0v1YB62dCa8W9qk2E7R5VdLRi4haFTv42u7jOZT0tSzRv/R0QppoVQ7/Fpqpps+aoZBM6EGj/pAxRgBTHeyI9WTFUAYDbhRuN9EoJAqRUCpXn39oR+TsaD9COENAJroX2WLIY8XFD3UzrpA9NPt7JE9mufWoNipNqLdLY7k3p3UxX0/SDboVlax6ORpQN+YzYhCesJaAOhlTAXMRMyXsfw/ScYttXxmIJ7BINYEMSXM55uiUPYFjE/GuZjbjgqk3dmJr7ceAyGa5v+m5Hr6efPSRHKUAxkEcDsXpcTHyEOVt3l7Qwfd+oUumK +d7515d29761d5ada7d9c765f517db67db75dea9a 0 iQJJBAABCgAzFiEEgY2HzRrBgMOUyG5jOjPeRg2ew58FAmD4lQMVHDc4OTVwdWxraXRAZ21haWwuY29tAAoJEDoz3kYNnsOfVsMP/19G6aZBokNRdErXcT86ahVy82IquR/CmLJcdj/4nehmBXToLCmdeqKe17ZKgZ7bnPnevhO07zPub7RUhDixnb7OxpbXiyP7x67FAqAfKvi8rZggmeWZT5kpiltoBIvHDlOlQhsgtfea0REULyn4zNB6dLED5zh2Ddr5LcWIjfOvIWo1F0eFMcRszL8f2u2ei2dERDuG8MSzMsiFHMAPRMHJjm+YukJBuz78CH4qT/Inkq52ao+3GCh4fFBhPG5+IABeCn1J4cAAK06mPcJqa7fbv7NfUCN9MeDNQUsUGGfIhKzGHJTb7PwXkKJ3qpLPs4FYGV1ZTucrIU1i65hXuf66QcYGlAQmKavS7xDOfZhzrZrAKe65dLpWdEH5mpTMcjaMBS+mhfMJT7DQg9T/9jISiKeqiFNkNOy1cobpJWes8iFwihEBtEhCtiVgnf7i7IzZY/spmSmP4ot/MEBi3jMjvAEaH1HyDGOPuBuqRSIRU+Mf5o1yB2kZmGL9vHWUzm/ySjQFYte061OyE9bZrbF9daOTdRip/CXPApOneVBIMwXc7fWDu45cKyVg7kYo8a0gcFfg39Ceja3Z8iJSFtJTuj1Sd9q8YU6pxqDrfPm1byJJlb7SvAoZfIGQPFk+DF6UVEcWRC0MYRm2bHXlaZwNVpgmFv6ZOVja3jxCJkw8 +2813d406b03607cdb8c06cb04c44efcc9a79d9a2 0 iQJJBAABCgAzFiEEgY2HzRrBgMOUyG5jOjPeRg2ew58FAmESg/wVHDc4OTVwdWxraXRAZ21haWwuY29tAAoJEDoz3kYNnsOf6kAP/1w3elvhAYQcK9hkEVCg4sQgnvcatOafCNaK0dVW9OOFbt+8DNUcHbtUHZtR6ETmSAMlWilIr/1vRMjy0Zic6afJ30oq8i+4f6DgLyTsLQL/QdwJQIwi2fZmHebv1PSrhT9tJAwtH6oG3cNhSq8KMme4l7sVR7ekB34Cmzk3fa5udMOuQG9xWbGTmeEsx0kYb+1oag+NnnZJqVTi68gGGxRW8TYZ1APXJcrZVfkldtaIWx6U1UdkWSTqWHV4fnnctp/1M+IgXCLT0iupY5LnxqGKQcMte7WKRPPdfhGF1ta+LN+QPHbwXhDRDIWPBVbDeHxjKcjz3h+DOeF0b7c5vKDADgo9LtHui9QhBJiCDHwsM+8gA+kNEDbtvIYYQ6CLxX9m1TttxI4ASIzFGIQF6nBr3mjQCzmOoWtgVh7R4dsQ9YZgm4twjsIg3g0MDhmgs71jn6Gp4BficF25nY8J6Ct8YopkPs2sfiBYJmyh9NJLDjwqNnjq3MBervPX3B+7p1dfIsK4JoSuop5A4lc4OOEhrwm5BKIxm30R4NtB15RZ7nI0DcRFcwNQiTYPG+nOaPsFzeZD6lj8+YnuLyo2aCnf4K26/1YTlE1wOFkCb1reL99++i8FP94poHBKZ7+6HT6gk4Mmnfb52II4yWlh/CYLeKEzFFfAiOTvfhzpIvqg +53221078e0de65d1a821ce5311dec45a7a978301 0 iQJJBAABCgAzFiEEgY2HzRrBgMOUyG5jOjPeRg2ew58FAmEeqLUVHDc4OTVwdWxraXRAZ21haWwuY29tAAoJEDoz3kYNnsOfMb4P/R4oPBjSKrlGbuxYClNdP0lV4C1NUU1SPa+Il4QwGQteKD+RDfvp8z8+c45rVIEGiUNzaSJP/ZEyhBVW657rYzIhBnZgqnpwBzOViqe4Q3lHiq6wPKjEDIRJafcqMb6MaViPS6iRn6hhMlAcPcoabwhXrUgv8QyxVSTFlJm0RGbUVekQLIWKEAnwcWLHKt0d2DrB0/706xXtKxdJ8N/2WCVOOkr7UvpdLXo3quOz1S930/o1iF/csggsi9q4oZYj2XBdBGHayoqkhKAQMyBfXH19RqW3SWZafY8whrZDCz+9AAmJJk8hjQl6xrT/ZVweRfqvRoMJBgjQdFTi58wjC8995ZXKEC7jsJCEblyRJkc23opuAArPEkJXLDR+oK1vOfikaRjmQoMPAMDjbxTUyVOuHcX+PxMtq9NAO0MKcnSr+D2Xc28TGY9PkBhRkEnN3nlZH5z7DvF8GfOnUt5SGhFiQHhXnL6jDBCQVDKAoCJn0WKDG9+29I6st2eGEwKaIjZQ9NCtaLASiauopMOyWWbHeM58bCl80TBXuj+3W+mo+zDSLoGwWJc5oFdFpmnGGTQtkxPDiV4ksIgJAMb/KHkGY+RxnEsWgX1VcR2c1sYD4nzOjrt4RuvX1i+cfzRjLOchPiru7BbrBQRTXGhrvNzsS9laTCxCH2oDazIudia4
--- a/.hgtags Tue Jul 20 17:20:19 2021 +0200 +++ b/.hgtags Sun Aug 22 16:32:06 2021 -0400 @@ -224,3 +224,7 @@ f67b8946bb1b6cfa8328dbf8d6a9128b69ccdcb4 5.8rc0 8d2b62d716b095507effaa8d56f87cd27ba659ab 5.8rc1 067f2c53fb24506c9e9fb4639871b13b19a85f8a 5.8 +411dc27fd9fd076d6a031a08fcaace659afe2fe3 5.8.1 +d7515d29761d5ada7d9c765f517db67db75dea9a 5.9rc0 +2813d406b03607cdb8c06cb04c44efcc9a79d9a2 5.9rc1 +53221078e0de65d1a821ce5311dec45a7a978301 5.9
--- a/Makefile Tue Jul 20 17:20:19 2021 +0200 +++ b/Makefile Sun Aug 22 16:32:06 2021 -0400 @@ -270,9 +270,27 @@ pyoxidizer: $(PYOXIDIZER) build --path ./rust/hgcli --release + +PYOX_DIR=build/pyoxidizer/x86_64-pc-windows-msvc/release/app + +# a temporary target to setup all we need for run-tests.py --pyoxidizer +# (should go away as the run-tests implementation improves +pyoxidizer-windows-tests: pyoxidizer + rm -rf $(PYOX_DIR)/templates + cp -ar $(PYOX_DIR)/lib/mercurial/templates $(PYOX_DIR)/templates + rm -rf $(PYOX_DIR)/helptext + cp -ar $(PYOX_DIR)/lib/mercurial/helptext $(PYOX_DIR)/helptext + rm -rf $(PYOX_DIR)/defaultrc + cp -ar $(PYOX_DIR)/lib/mercurial/defaultrc $(PYOX_DIR)/defaultrc + rm -rf $(PYOX_DIR)/contrib + cp -ar contrib $(PYOX_DIR)/contrib + rm -rf $(PYOX_DIR)/doc + cp -ar doc $(PYOX_DIR)/doc + + .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 pyoxidizer \ + update-pot pyoxidizer pyoxidizer-windows-tests \ $(packaging_targets) \ osx
--- a/contrib/check-code.py Tue Jul 20 17:20:19 2021 +0200 +++ b/contrib/check-code.py Sun Aug 22 16:32:06 2021 -0400 @@ -340,11 +340,6 @@ (r'[^\n]\Z', "no trailing newline"), (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"), ( - r'^\s+(self\.)?[A-Za-z][a-z0-9]+[A-Z]\w* = ', - "don't use camelcase in identifiers", - r'#.*camelcase-required', - ), - ( r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+', "linebreak after :", ),
--- a/contrib/heptapod-ci.yml Tue Jul 20 17:20:19 2021 +0200 +++ b/contrib/heptapod-ci.yml Sun Aug 22 16:32:06 2021 -0400 @@ -10,7 +10,11 @@ HG_CI_IMAGE_TAG: "latest" TEST_HGTESTS_ALLOW_NETIO: "0" +.all_template: &all + when: always + .runtests_template: &runtests + <<: *all stage: tests # The runner made a clone as root. # We make a new clone owned by user used to run the step. @@ -38,6 +42,7 @@ PYTHON: python3 rust-cargo-test-py2: &rust_cargo_test + <<: *all stage: tests script: - echo "python used, $PYTHON" @@ -50,6 +55,7 @@ PYTHON: python3 phabricator-refresh: + <<: *all stage: phabricator variables: DEFAULT_COMMENT: ":white_check_mark: refresh by Heptapod after a successful CI run (:octopus: :green_heart:)" @@ -128,7 +134,6 @@ check-pytype-py3: extends: .runtests_template - when: manual before_script: - hg clone . /tmp/mercurial-ci/ --noupdate --config phases.publish=no - hg -R /tmp/mercurial-ci/ update `hg log --rev '.' --template '{node}'` @@ -137,6 +142,7 @@ - $PYTHON -m pip install --user -U pytype==2021.04.15 variables: RUNTEST_ARGS: " --allow-slow-tests tests/test-check-pytype.t" + HGTEST_TIMEOUT: "3600" PYTHON: python3 TEST_HGMODULEPOLICY: "c" @@ -146,11 +152,10 @@ # run-tests.py- it is needed to make run-tests.py generate a `python3` script # that satisfies the various shebang lines and delegates to `py -3`. .window_runtests_template: &windows_runtests + <<: *all stage: tests before_script: - # Temporary until this is adjusted in the environment - - $Env:TEMP="C:/Temp" - - $Env:TMP="C:/Temp" + - C:/MinGW/msys/1.0/bin/sh.exe --login -c 'cd "$OLDPWD" && ls -1 tests/test-check-*.* > C:/Temp/check-tests.txt' # TODO: find/install cvs, bzr, perforce, gpg, sqlite3 script: @@ -159,16 +164,25 @@ - Invoke-Expression "$Env:PYTHON -V" - Invoke-Expression "$Env:PYTHON -m black --version" - echo "$Env:RUNTEST_ARGS" + - echo "$Env:TMP" + - echo "$Env:TEMP" - C:/MinGW/msys/1.0/bin/sh.exe --login -c 'cd "$OLDPWD" && HGTESTS_ALLOW_NETIO="$TEST_HGTESTS_ALLOW_NETIO" HGMODULEPOLICY="$TEST_HGMODULEPOLICY" $PYTHON tests/run-tests.py --color=always $RUNTEST_ARGS' windows-py3: <<: *windows_runtests - when: manual tags: - windows - timeout: 2h variables: TEST_HGMODULEPOLICY: "c" - RUNTEST_ARGS: "--blacklist /tmp/check-tests.txt" + RUNTEST_ARGS: "--blacklist C:/Temp/check-tests.txt" PYTHON: py -3 + +windows-py3-pyox: + <<: *windows_runtests + tags: + - windows + variables: + TEST_HGMODULEPOLICY: "c" + RUNTEST_ARGS: "--blacklist C:/Temp/check-tests.txt --pyoxidized" + PYTHON: py -3
--- a/contrib/import-checker.py Tue Jul 20 17:20:19 2021 +0200 +++ b/contrib/import-checker.py Sun Aug 22 16:32:06 2021 -0400 @@ -278,6 +278,8 @@ ): continue for top, dirs, files in os.walk(libpath): + if 'dist-packages' in top.split(os.path.sep): + continue for i, d in reversed(list(enumerate(dirs))): if ( not os.path.exists(os.path.join(top, d, '__init__.py'))
--- a/contrib/install-windows-dependencies.ps1 Tue Jul 20 17:20:19 2021 +0200 +++ b/contrib/install-windows-dependencies.ps1 Sun Aug 22 16:32:06 2021 -0400 @@ -19,14 +19,6 @@ $VS_BUILD_TOOLS_URL = "https://download.visualstudio.microsoft.com/download/pr/a1603c02-8a66-4b83-b821-811e3610a7c4/aa2db8bb39e0cbd23e9940d8951e0bc3/vs_buildtools.exe" $VS_BUILD_TOOLS_SHA256 = "911E292B8E6E5F46CBC17003BDCD2D27A70E616E8D5E6E69D5D489A605CAA139" -$VC9_PYTHON_URL = "https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi" -$VC9_PYTHON_SHA256 = "070474db76a2e625513a5835df4595df9324d820f9cc97eab2a596dcbc2f5cbf" - -$PYTHON27_x64_URL = "https://www.python.org/ftp/python/2.7.18/python-2.7.18.amd64.msi" -$PYTHON27_x64_SHA256 = "b74a3afa1e0bf2a6fc566a7b70d15c9bfabba3756fb077797d16fffa27800c05" -$PYTHON27_X86_URL = "https://www.python.org/ftp/python/2.7.18/python-2.7.18.msi" -$PYTHON27_X86_SHA256 = "d901802e90026e9bad76b8a81f8dd7e43c7d7e8269d9281c9e9df7a9c40480a9" - $PYTHON37_x86_URL = "https://www.python.org/ftp/python/3.7.9/python-3.7.9.exe" $PYTHON37_x86_SHA256 = "769bb7c74ad1df6d7d74071cc16a984ff6182e4016e11b8949b93db487977220" $PYTHON37_X64_URL = "https://www.python.org/ftp/python/3.7.9/python-3.7.9-amd64.exe" @@ -46,18 +38,15 @@ $PIP_URL = "https://github.com/pypa/get-pip/raw/309a56c5fd94bd1134053a541cb4657a4e47e09d/get-pip.py" $PIP_SHA256 = "57e3643ff19f018f8a00dfaa6b7e4620e3c1a7a2171fd218425366ec006b3bfe" -$VIRTUALENV_URL = "https://files.pythonhosted.org/packages/66/f0/6867af06d2e2f511e4e1d7094ff663acdebc4f15d4a0cb0fed1007395124/virtualenv-16.7.5.tar.gz" -$VIRTUALENV_SHA256 = "f78d81b62d3147396ac33fc9d77579ddc42cc2a98dd9ea38886f616b33bc7fb2" - $INNO_SETUP_URL = "http://files.jrsoftware.org/is/5/innosetup-5.6.1-unicode.exe" $INNO_SETUP_SHA256 = "27D49E9BC769E9D1B214C153011978DB90DC01C2ACD1DDCD9ED7B3FE3B96B538" $MINGW_BIN_URL = "https://osdn.net/frs/redir.php?m=constant&f=mingw%2F68260%2Fmingw-get-0.6.3-mingw32-pre-20170905-1-bin.zip" $MINGW_BIN_SHA256 = "2AB8EFD7C7D1FC8EAF8B2FA4DA4EEF8F3E47768284C021599BC7435839A046DF" -$MERCURIAL_WHEEL_FILENAME = "mercurial-5.1.2-cp27-cp27m-win_amd64.whl" -$MERCURIAL_WHEEL_URL = "https://files.pythonhosted.org/packages/6d/47/e031e47f7fe9b16e4e3383da47e2b0a7eae6e603996bc67a03ec4fa1b3f4/$MERCURIAL_WHEEL_FILENAME" -$MERCURIAL_WHEEL_SHA256 = "1d18c7f6ca1456f0f62ee65c9a50c14cbba48ce6e924930cdb10537f5c9eaf5f" +$MERCURIAL_WHEEL_FILENAME = "mercurial-5.8.1-cp39-cp39-win_amd64.whl" +$MERCURIAL_WHEEL_URL = "https://files.pythonhosted.org/packages/5c/b5/a5fa664761eef29b6c90eb24cb09ab8fe2c9b4b86af41d42c17476aff29b/$MERCURIAL_WHEEL_FILENAME" +$MERCURIAL_WHEEL_SHA256 = "cbf3efa68fd7ebf94691bd00d2c86bbd47ca73620c8faa4f18b6c394bf5f82b0" $RUSTUP_INIT_URL = "https://static.rust-lang.org/rustup/archive/1.21.1/x86_64-pc-windows-gnu/rustup-init.exe" $RUSTUP_INIT_SHA256 = "d17df34ba974b9b19cf5c75883a95475aa22ddc364591d75d174090d55711c72" @@ -91,6 +80,8 @@ } function Invoke-Process($path, $arguments) { + echo "$path $arguments" + $p = Start-Process -FilePath $path -ArgumentList $arguments -Wait -PassThru -WindowStyle Hidden if ($p.ExitCode -ne 0) { @@ -135,9 +126,6 @@ $pip = "${prefix}\assets\get-pip.py" - Secure-Download $VC9_PYTHON_URL ${prefix}\assets\VCForPython27.msi $VC9_PYTHON_SHA256 - Secure-Download $PYTHON27_x86_URL ${prefix}\assets\python27-x86.msi $PYTHON27_x86_SHA256 - Secure-Download $PYTHON27_x64_URL ${prefix}\assets\python27-x64.msi $PYTHON27_x64_SHA256 Secure-Download $PYTHON37_x86_URL ${prefix}\assets\python37-x86.exe $PYTHON37_x86_SHA256 Secure-Download $PYTHON37_x64_URL ${prefix}\assets\python37-x64.exe $PYTHON37_x64_SHA256 Secure-Download $PYTHON38_x86_URL ${prefix}\assets\python38-x86.exe $PYTHON38_x86_SHA256 @@ -145,7 +133,6 @@ Secure-Download $PYTHON39_x86_URL ${prefix}\assets\python39-x86.exe $PYTHON39_x86_SHA256 Secure-Download $PYTHON39_x64_URL ${prefix}\assets\python39-x64.exe $PYTHON39_x64_SHA256 Secure-Download $PIP_URL ${pip} $PIP_SHA256 - Secure-Download $VIRTUALENV_URL ${prefix}\assets\virtualenv.tar.gz $VIRTUALENV_SHA256 Secure-Download $VS_BUILD_TOOLS_URL ${prefix}\assets\vs_buildtools.exe $VS_BUILD_TOOLS_SHA256 Secure-Download $INNO_SETUP_URL ${prefix}\assets\InnoSetup.exe $INNO_SETUP_SHA256 Secure-Download $MINGW_BIN_URL ${prefix}\assets\mingw-get-bin.zip $MINGW_BIN_SHA256 @@ -153,20 +140,10 @@ Secure-Download $RUSTUP_INIT_URL ${prefix}\assets\rustup-init.exe $RUSTUP_INIT_SHA256 Secure-Download $PYOXIDIZER_URL ${prefix}\assets\PyOxidizer.msi $PYOXIDIZER_SHA256 - Write-Output "installing Python 2.7 32-bit" - Invoke-Process msiexec.exe "/i ${prefix}\assets\python27-x86.msi /l* ${prefix}\assets\python27-x86.log /q TARGETDIR=${prefix}\python27-x86 ALLUSERS=" - Invoke-Process ${prefix}\python27-x86\python.exe ${prefix}\assets\get-pip.py - Invoke-Process ${prefix}\python27-x86\Scripts\pip.exe "install ${prefix}\assets\virtualenv.tar.gz" - - Write-Output "installing Python 2.7 64-bit" - Invoke-Process msiexec.exe "/i ${prefix}\assets\python27-x64.msi /l* ${prefix}\assets\python27-x64.log /q TARGETDIR=${prefix}\python27-x64 ALLUSERS=" - Invoke-Process ${prefix}\python27-x64\python.exe ${prefix}\assets\get-pip.py - Invoke-Process ${prefix}\python27-x64\Scripts\pip.exe "install ${prefix}\assets\virtualenv.tar.gz" - Install-Python3 "Python 3.7 32-bit" ${prefix}\assets\python37-x86.exe ${prefix}\python37-x86 ${pip} Install-Python3 "Python 3.7 64-bit" ${prefix}\assets\python37-x64.exe ${prefix}\python37-x64 ${pip} Install-Python3 "Python 3.8 32-bit" ${prefix}\assets\python38-x86.exe ${prefix}\python38-x86 ${pip} - Install-Python3 "Python 3.8 64-bit" ${prefix}\assets\python38-x64.exe ${prefix}\python38-x64 ${pip} +# Install-Python3 "Python 3.8 64-bit" ${prefix}\assets\python38-x64.exe ${prefix}\python38-x64 ${pip} Install-Python3 "Python 3.9 32-bit" ${prefix}\assets\python39-x86.exe ${prefix}\python39-x86 ${pip} Install-Python3 "Python 3.9 64-bit" ${prefix}\assets\python39-x64.exe ${prefix}\python39-x64 ${pip} @@ -178,9 +155,6 @@ Install-Rust ${prefix} - Write-Output "installing Visual C++ 9.0 for Python 2.7" - Invoke-Process msiexec.exe "/i ${prefix}\assets\VCForPython27.msi /l* ${prefix}\assets\VCForPython27.log /q" - Write-Output "installing Inno Setup" Invoke-Process ${prefix}\assets\InnoSetup.exe "/SP- /VERYSILENT /SUPPRESSMSGBOXES" @@ -196,7 +170,7 @@ # Construct a virtualenv useful for bootstrapping. It conveniently contains a # Mercurial install. Write-Output "creating bootstrap virtualenv with Mercurial" - Invoke-Process "$prefix\python27-x64\Scripts\virtualenv.exe" "${prefix}\venv-bootstrap" + Invoke-Process "$prefix\python39-x64\python.exe" "-m venv ${prefix}\venv-bootstrap" Invoke-Process "${prefix}\venv-bootstrap\Scripts\pip.exe" "install ${prefix}\assets\${MERCURIAL_WHEEL_FILENAME}" } @@ -204,7 +178,7 @@ Write-Output "cloning $repo_url to $dest" # TODO Figure out why CA verification isn't working in EC2 and remove # --insecure. - Invoke-Process "${prefix}\venv-bootstrap\Scripts\hg.exe" "clone --insecure $repo_url $dest" + Invoke-Process "${prefix}\venv-bootstrap\Scripts\python.exe" "${prefix}\venv-bootstrap\Scripts\hg clone --insecure $repo_url $dest" # Mark repo as non-publishing by default for convenience. Add-Content -Path "$dest\.hg\hgrc" -Value "`n[phases]`npublish = false"
--- a/contrib/packaging/requirements-windows-py3.txt Tue Jul 20 17:20:19 2021 +0200 +++ b/contrib/packaging/requirements-windows-py3.txt Sun Aug 22 16:32:06 2021 -0400 @@ -4,6 +4,14 @@ # # pip-compile --generate-hashes --output-file=contrib/packaging/requirements-windows-py3.txt contrib/packaging/requirements-windows.txt.in # +atomicwrites==1.4.0 \ + --hash=sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197 \ + --hash=sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a \ + # via pytest +attrs==21.2.0 \ + --hash=sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1 \ + --hash=sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb \ + # via pytest cached-property==1.5.2 \ --hash=sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130 \ --hash=sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0 \ @@ -48,6 +56,10 @@ --hash=sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b \ --hash=sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f \ # via pygit2 +colorama==0.4.4 \ + --hash=sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b \ + --hash=sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2 \ + # via pytest docutils==0.16 \ --hash=sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af \ --hash=sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc \ @@ -67,14 +79,76 @@ --hash=sha256:e5871b86a079e9e290f52ab14559cea1b694a0b8ed2b9ebb898f6ced7f14a406 \ --hash=sha256:e593f514b8ac740b4ceeb047745b4719bfc9f334904245c6edcb3a9d002f577b \ # via -r contrib/packaging/requirements-windows.txt.in +fuzzywuzzy==0.18.0 \ + --hash=sha256:45016e92264780e58972dca1b3d939ac864b78437422beecebb3095f8efd00e8 \ + # via -r contrib/packaging/requirements-windows.txt.in +idna==3.2 \ + --hash=sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a \ + --hash=sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3 \ + # via yarl importlib-metadata==3.1.0 \ --hash=sha256:590690d61efdd716ff82c39ca9a9d4209252adfe288a4b5721181050acbd4175 \ --hash=sha256:d9b8a46a0885337627a6430db287176970fff18ad421becec1d64cfc763c2099 \ - # via keyring + # via keyring, pluggy, pytest +iniconfig==1.1.1 \ + --hash=sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3 \ + --hash=sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32 \ + # via pytest keyring==21.4.0 \ --hash=sha256:4e34ea2fdec90c1c43d6610b5a5fafa1b9097db1802948e90caf5763974b8f8d \ --hash=sha256:9aeadd006a852b78f4b4ef7c7556c2774d2432bbef8ee538a3e9089ac8b11466 \ # via -r contrib/packaging/requirements-windows.txt.in +multidict==5.1.0 \ + --hash=sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a \ + --hash=sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93 \ + --hash=sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632 \ + --hash=sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656 \ + --hash=sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79 \ + --hash=sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7 \ + --hash=sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d \ + --hash=sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5 \ + --hash=sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224 \ + --hash=sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26 \ + --hash=sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea \ + --hash=sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348 \ + --hash=sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6 \ + --hash=sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76 \ + --hash=sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1 \ + --hash=sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f \ + --hash=sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952 \ + --hash=sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a \ + --hash=sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37 \ + --hash=sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9 \ + --hash=sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359 \ + --hash=sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8 \ + --hash=sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da \ + --hash=sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3 \ + --hash=sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d \ + --hash=sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf \ + --hash=sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841 \ + --hash=sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d \ + --hash=sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93 \ + --hash=sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f \ + --hash=sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647 \ + --hash=sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635 \ + --hash=sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456 \ + --hash=sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda \ + --hash=sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5 \ + --hash=sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281 \ + --hash=sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80 \ + # via yarl +packaging==21.0 \ + --hash=sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7 \ + --hash=sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14 \ + # via pytest +pluggy==0.13.1 \ + --hash=sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0 \ + --hash=sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d \ + # via pytest +py==1.10.0 \ + --hash=sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3 \ + --hash=sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a \ + # via pytest pycparser==2.20 \ --hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 \ --hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705 \ @@ -102,14 +176,73 @@ --hash=sha256:307543fe65c0947b126e83dd5a61bd8acbd84abec11f43caebaf5534cbc17998 \ --hash=sha256:926c3f319eda178d1bd90851e4317e6d8cdb5e292a3386aac9bd75eca29cf9c7 \ # via -r contrib/packaging/requirements-windows.txt.in +pyparsing==2.4.7 \ + --hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 \ + --hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b \ + # via packaging +pytest-vcr==1.0.2 \ + --hash=sha256:23ee51b75abbcc43d926272773aae4f39f93aceb75ed56852d0bf618f92e1896 \ + # via -r contrib/packaging/requirements-windows.txt.in +pytest==6.2.4 \ + --hash=sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b \ + --hash=sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890 \ + # via pytest-vcr pywin32-ctypes==0.2.0 \ --hash=sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942 \ --hash=sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98 \ # via -r contrib/packaging/requirements-windows.txt.in, keyring +pyyaml==5.4.1 \ + --hash=sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf \ + --hash=sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696 \ + --hash=sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393 \ + --hash=sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77 \ + --hash=sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922 \ + --hash=sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5 \ + --hash=sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8 \ + --hash=sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10 \ + --hash=sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc \ + --hash=sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018 \ + --hash=sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e \ + --hash=sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253 \ + --hash=sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347 \ + --hash=sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183 \ + --hash=sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541 \ + --hash=sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb \ + --hash=sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185 \ + --hash=sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc \ + --hash=sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db \ + --hash=sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa \ + --hash=sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46 \ + --hash=sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122 \ + --hash=sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b \ + --hash=sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63 \ + --hash=sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df \ + --hash=sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc \ + --hash=sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247 \ + --hash=sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6 \ + --hash=sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0 \ + # via vcrpy +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 \ + # via vcrpy +toml==0.10.2 \ + --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ + --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f \ + # via pytest +typing-extensions==3.10.0.0 \ + --hash=sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497 \ + --hash=sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342 \ + --hash=sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84 \ + # via yarl urllib3==1.25.11 \ --hash=sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2 \ --hash=sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e \ # via dulwich +vcrpy==4.1.1 \ + --hash=sha256:12c3fcdae7b88ecf11fc0d3e6d77586549d4575a2ceee18e82eee75c1f626162 \ + --hash=sha256:57095bf22fc0a2d99ee9674cdafebed0f3ba763018582450706f7d3a74fff599 \ + # via pytest-vcr windows-curses==2.2.0 \ --hash=sha256:1452d771ec6f9b3fef037da2b169196a9a12be4e86a6c27dd579adac70c42028 \ --hash=sha256:267544e4f60c09af6505e50a69d7f01d7f8a281cf4bd4fc7efc3b32b9a4ef64e \ @@ -120,6 +253,48 @@ --hash=sha256:c5cd032bc7d0f03224ab55c925059d98e81795098d59bbd10f7d05c7ea9677ce \ --hash=sha256:fc0be372fe6da3c39d7093154ce029115a927bf287f34b4c615e2b3f8c23dfaa \ # via -r contrib/packaging/requirements-windows.txt.in +wrapt==1.12.1 \ + --hash=sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7 \ + # via vcrpy +yarl==1.6.3 \ + --hash=sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e \ + --hash=sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434 \ + --hash=sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366 \ + --hash=sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3 \ + --hash=sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec \ + --hash=sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959 \ + --hash=sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e \ + --hash=sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c \ + --hash=sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6 \ + --hash=sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a \ + --hash=sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6 \ + --hash=sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424 \ + --hash=sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e \ + --hash=sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f \ + --hash=sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50 \ + --hash=sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2 \ + --hash=sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc \ + --hash=sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4 \ + --hash=sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970 \ + --hash=sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10 \ + --hash=sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0 \ + --hash=sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406 \ + --hash=sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896 \ + --hash=sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643 \ + --hash=sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721 \ + --hash=sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478 \ + --hash=sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724 \ + --hash=sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e \ + --hash=sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8 \ + --hash=sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96 \ + --hash=sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25 \ + --hash=sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76 \ + --hash=sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2 \ + --hash=sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2 \ + --hash=sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c \ + --hash=sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a \ + --hash=sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71 \ + # via vcrpy zipp==3.4.0 \ --hash=sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108 \ --hash=sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb \
--- a/contrib/packaging/requirements-windows.txt.in Tue Jul 20 17:20:19 2021 +0200 +++ b/contrib/packaging/requirements-windows.txt.in Sun Aug 22 16:32:06 2021 -0400 @@ -2,9 +2,17 @@ # Pinned to an old version because 0.20 drops Python 3 compatibility. dulwich < 0.20 ; python_version <= '2.7' dulwich ; python_version >= '3' + +# Needed by the release note tooling +fuzzywuzzy + keyring pygit2 ; python_version >= '3' pygments + +# Needed by the phabricator tests +pytest-vcr + # Need to list explicitly so dependency gets pulled in when # not running on Windows. pywin32-ctypes
--- a/hgext/fix.py Tue Jul 20 17:20:19 2021 +0200 +++ b/hgext/fix.py Sun Aug 22 16:32:06 2021 -0400 @@ -132,6 +132,7 @@ from mercurial.i18n import _ from mercurial.node import ( + nullid, nullrev, wdirrev, ) @@ -751,16 +752,17 @@ Directly updates the dirstate for the affected files. """ + assert repo.dirstate.p2() == nullid + for path, data in pycompat.iteritems(filedata): fctx = ctx[path] fctx.write(data, fctx.flags()) - if repo.dirstate[path] == b'n': - repo.dirstate.set_possibly_dirty(path) - oldparentnodes = repo.dirstate.parents() - newparentnodes = [replacements.get(n, n) for n in oldparentnodes] - if newparentnodes != oldparentnodes: - repo.setparents(*newparentnodes) + oldp1 = repo.dirstate.p1() + newp1 = replacements.get(oldp1, oldp1) + if newp1 != oldp1: + with repo.dirstate.parentchange(): + scmutil.movedirstate(repo, repo[newp1]) def replacerev(ui, repo, ctx, filedata, replacements):
--- a/hgext/git/dirstate.py Tue Jul 20 17:20:19 2021 +0200 +++ b/hgext/git/dirstate.py Sun Aug 22 16:32:06 2021 -0400 @@ -74,6 +74,8 @@ self._root = os.path.dirname(root) self.git = gitrepo self._plchangecallbacks = {} + # TODO: context.poststatusfixup is bad and uses this attribute + self._dirty = False def p1(self): try: @@ -255,12 +257,12 @@ if match(p): yield p - def normal(self, f, parentfiledata=None): + def set_clean(self, f, parentfiledata=None): """Mark a file normal and clean.""" # TODO: for now we just let libgit2 re-stat the file. We can # clearly do better. - def normallookup(self, f): + def set_possibly_dirty(self, f): """Mark a file normal, but possibly dirty.""" # TODO: for now we just let libgit2 re-stat the file. We can # clearly do better. @@ -296,6 +298,16 @@ # TODO: figure out a strategy for saving index backups. pass + def set_tracked(self, f): + uf = pycompat.fsdecode(f) + if uf in self.git.index: + return False + index = self.git.index + index.read() + index.add(uf) + index.write() + return True + def add(self, f): index = self.git.index index.read() @@ -310,6 +322,16 @@ index.remove(fs) index.write() + def set_untracked(self, f): + index = self.git.index + index.read() + fs = pycompat.fsdecode(f) + if fs in index: + index.remove(fs) + index.write() + return True + return False + def remove(self, f): index = self.git.index index.read() @@ -324,6 +346,10 @@ # TODO pass + def update_file(self, *args, **kwargs): + # TODO + pass + @contextlib.contextmanager def parentchange(self): # TODO: track this maybe?
--- a/hgext/releasenotes.py Tue Jul 20 17:20:19 2021 +0200 +++ b/hgext/releasenotes.py Sun Aug 22 16:32:06 2021 -0400 @@ -39,9 +39,22 @@ command = registrar.command(cmdtable) try: - import fuzzywuzzy.fuzz as fuzz + # Silence a warning about python-Levenshtein. + # + # We don't need the the performance that much and it get anoying in tests. + import warnings - fuzz.token_set_ratio + with warnings.catch_warnings(): + warnings.filterwarnings( + action="ignore", + message=".*python-Levenshtein.*", + category=UserWarning, + module="fuzzywuzzy.fuzz", + ) + + import fuzzywuzzy.fuzz as fuzz + + fuzz.token_set_ratio except ImportError: fuzz = None
--- a/hgext/remotefilelog/remotefilelogserver.py Tue Jul 20 17:20:19 2021 +0200 +++ b/hgext/remotefilelog/remotefilelogserver.py Sun Aug 22 16:32:06 2021 -0400 @@ -186,7 +186,7 @@ yield (t, u, e, s) for x in repo.store.topfiles(): - if state.noflatmf and x[0][:11] == b'00manifest.': + if state.noflatmf and x[1][:11] == b'00manifest.': continue yield x
--- a/mercurial/commands.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/commands.py Sun Aug 22 16:32:06 2021 -0400 @@ -75,12 +75,6 @@ urlutil, ) -if pycompat.TYPE_CHECKING: - from typing import ( - List, - ) - - table = {} table.update(debugcommandsmod.command._table) @@ -3341,7 +3335,8 @@ ) # checking that newnodes exist because old state files won't have it elif statedata.get(b'newnodes') is not None: - nn = statedata[b'newnodes'] # type: List[bytes] + nn = statedata[b'newnodes'] + assert isinstance(nn, list) # list of bytes nn.append(node) # remove state when we complete successfully
--- a/mercurial/configitems.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/configitems.py Sun Aug 22 16:32:06 2021 -0400 @@ -1897,6 +1897,11 @@ default=True, alias=[(b'format', b'aggressivemergedeltas')], ) +coreconfigitem( + b'storage', + b'revlog.issue6528.fix-incoming', + default=True, +) # experimental as long as rust is experimental (or a C version is implemented) coreconfigitem( b'storage',
--- a/mercurial/debugcommands.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/debugcommands.py Sun Aug 22 16:32:06 2021 -0400 @@ -71,6 +71,7 @@ registrar, repair, repoview, + requirements, revlog, revset, revsetlang, @@ -105,6 +106,7 @@ from .revlogutils import ( deltas as deltautil, nodemap, + rewrite, sidedata, ) @@ -1451,6 +1453,80 @@ ui.write(b"%s\n" % f) +@command( + b"debug-repair-issue6528", + [ + ( + b'', + b'to-report', + b'', + _(b'build a report of affected revisions to this file'), + _(b'FILE'), + ), + ( + b'', + b'from-report', + b'', + _(b'repair revisions listed in this report file'), + _(b'FILE'), + ), + ( + b'', + b'paranoid', + False, + _(b'check that both detection methods do the same thing'), + ), + ] + + cmdutil.dryrunopts, +) +def debug_repair_issue6528(ui, repo, **opts): + """find affected revisions and repair them. See issue6528 for more details. + + The `--to-report` and `--from-report` flags allow you to cache and reuse the + computation of affected revisions for a given repository across clones. + The report format is line-based (with empty lines ignored): + + ``` + <ascii-hex of the affected revision>,... <unencoded filelog index filename> + ``` + + There can be multiple broken revisions per filelog, they are separated by + a comma with no spaces. The only space is between the revision(s) and the + filename. + + Note that this does *not* mean that this repairs future affected revisions, + that needs a separate fix at the exchange level that hasn't been written yet + (as of 5.9rc0). + + There is a `--paranoid` flag to test that the fast implementation is correct + by checking it against the slow implementation. Since this matter is quite + urgent and testing every edge-case is probably quite costly, we use this + method to test on large repositories as a fuzzing method of sorts. + """ + cmdutil.check_incompatible_arguments( + opts, 'to_report', ['from_report', 'dry_run'] + ) + dry_run = opts.get('dry_run') + to_report = opts.get('to_report') + from_report = opts.get('from_report') + paranoid = opts.get('paranoid') + # TODO maybe add filelog pattern and revision pattern parameters to help + # narrow down the search for users that know what they're looking for? + + if requirements.REVLOGV1_REQUIREMENT not in repo.requirements: + msg = b"can only repair revlogv1 repositories, v2 is not affected" + raise error.Abort(_(msg)) + + rewrite.repair_issue6528( + ui, + repo, + dry_run=dry_run, + to_report=to_report, + from_report=from_report, + paranoid=paranoid, + ) + + @command(b'debugformat', [] + cmdutil.formatteropts) def debugformat(ui, repo, **opts): """display format information about the current repository
--- a/mercurial/dirstate.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/dirstate.py Sun Aug 22 16:32:06 2021 -0400 @@ -599,7 +599,7 @@ This function must be called within a `dirstate.parentchange` context. - note: the API is at an early stage and we might need to ajust it + note: the API is at an early stage and we might need to adjust it depending of what information ends up being relevant and useful to other processing. """ @@ -828,7 +828,7 @@ ) else: util.nouideprecwarn( - b"do not use `remove` outside of update/merge context." + b"do not use `add` outside of update/merge context." b" Use `set_tracked`", b'6.0', stacklevel=2,
--- a/mercurial/filelog.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/filelog.py Sun Aug 22 16:32:06 2021 -0400 @@ -20,6 +20,7 @@ from .utils import storageutil from .revlogutils import ( constants as revlog_constants, + rewrite, ) @@ -37,6 +38,8 @@ # Used by LFS. self._revlog.filename = path self.nullid = self._revlog.nullid + opts = opener.options + self._fix_issue6528 = opts.get(b'issue6528.fix-incoming', True) def __len__(self): return len(self._revlog) @@ -157,13 +160,18 @@ ) ) - return self._revlog.addgroup( - deltas, - linkmapper, - transaction, - addrevisioncb=addrevisioncb, - duplicaterevisioncb=duplicaterevisioncb, - ) + with self._revlog._writing(transaction): + + if self._fix_issue6528: + deltas = rewrite.filter_delta_issue6528(self._revlog, deltas) + + return self._revlog.addgroup( + deltas, + linkmapper, + transaction, + addrevisioncb=addrevisioncb, + duplicaterevisioncb=duplicaterevisioncb, + ) def getstrippoint(self, minlink): return self._revlog.getstrippoint(minlink)
--- a/mercurial/helptext/config.txt Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/helptext/config.txt Sun Aug 22 16:32:06 2021 -0400 @@ -906,13 +906,21 @@ with the Rust part might actually suffer some slowdown. For this reason, Such version will by default refuse to access such repositories. That behavior can be controlled by configuration. Check - :hg:`help config.storage.revlog.persistent-nodemap.slowpath` for details. + :hg:`help config.storage.revlog.persistent-nodemap.slow-path` for details. Repository with this on-disk format require Mercurial version 5.4 or above. By default this format variant is disabled if fast implementation is not available and enabled by default if the fast implementation is available. + To accomodate install of Mercurial without the fast implementation you can + downgrade your repository. To do so run the following command: + + $ hg debugupgraderepo \ + --run \ + --config format.use-persistent-nodemap=False \ + --config storage.revlog.persistent-nodemap.slow-path=allow + ``use-share-safe`` Enforce "safe" behaviors for all "shares" that access this repository. @@ -1838,7 +1846,7 @@ ``json`` Render profiling data as JSON. -``frequency`` +``freq`` Sampling frequency. Specific to the ``stat`` sampling profiler. (default: 1000) @@ -2035,6 +2043,21 @@ Control the strategy Mercurial uses internally to store history. Options in this category impact performance and repository size. +``revlog.issue6528.fix-incoming`` + Version 5.8 of Mercurial had a bug leading to altering the parent of file + revision with copy information (or any other metadata) on exchange. This + leads to the copy metadata to be overlooked by various internal logic. The + issue was fixed in Mercurial 5.8.1. + (See https://bz.mercurial-scm.org/show_bug.cgi?id=6528 for details) + + As a result Mercurial is now checking and fixing incoming file revisions to + make sure there parents are in the right order. This behavior can be + disabled by setting this option to `no`. This apply to revisions added + through push, pull, clone and unbundle. + + To fix affected revisions that already exist within the repository, one can + use :hg:`debug-repair-issue-6528`. + ``revlog.optimize-delta-parent-choice`` When storing a merge revision, both parents will be equally considered as a possible delta base. This results in better delta selection and improved
--- a/mercurial/localrepo.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/localrepo.py Sun Aug 22 16:32:06 2021 -0400 @@ -1043,6 +1043,9 @@ ) options[b'deltabothparents'] = deltabothparents + issue6528 = ui.configbool(b'storage', b'revlog.issue6528.fix-incoming') + options[b'issue6528.fix-incoming'] = issue6528 + lazydelta = ui.configbool(b'storage', b'revlog.reuse-external-delta') lazydeltabase = False if lazydelta:
--- a/mercurial/pycompat.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/pycompat.py Sun Aug 22 16:32:06 2021 -0400 @@ -40,6 +40,8 @@ def future_set_exception_info(f, exc_info): f.set_exception_info(*exc_info) + # this is close enough for our usage + FileNotFoundError = OSError else: import concurrent.futures as futures @@ -53,6 +55,8 @@ def future_set_exception_info(f, exc_info): f.set_exception(exc_info[0]) + FileNotFoundError = __builtins__['FileNotFoundError'] + def identity(a): return a
--- a/mercurial/revlog.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/revlog.py Sun Aug 22 16:32:06 2021 -0400 @@ -897,10 +897,8 @@ if rev == wdirrev: raise error.WdirUnsupported raise - if entry[5] == nullrev: - return entry[6], entry[5] - else: - return entry[5], entry[6] + + return entry[5], entry[6] # fast parentrevs(rev) where rev isn't filtered _uncheckedparentrevs = parentrevs @@ -921,11 +919,7 @@ def parents(self, node): i = self.index d = i[self.rev(node)] - # inline node() to avoid function call overhead - if d[5] == self.nullid: - return i[d[6]][7], i[d[5]][7] - else: - return i[d[5]][7], i[d[6]][7] + return i[d[5]][7], i[d[6]][7] # map revisions to nodes inline def chainlen(self, rev): return self._chaininfo(rev)[0] @@ -2122,6 +2116,8 @@ dfh = self._datafp(b"w+") transaction.add(self._datafile, dsize) if self._sidedatafile is not None: + # revlog-v2 does not inline, help Pytype + assert dfh is not None try: sdfh = self.opener(self._sidedatafile, mode=b"r+") dfh.seek(self._docket.sidedata_end, os.SEEK_SET) @@ -2584,6 +2580,8 @@ assert not sidedata self._enforceinlinesize(transaction) if self._docket is not None: + # revlog-v2 always has 3 writing handles, help Pytype + assert self._writinghandles[2] is not None self._docket.index_end = self._writinghandles[0].tell() self._docket.data_end = self._writinghandles[1].tell() self._docket.sidedata_end = self._writinghandles[2].tell()
--- a/mercurial/revlogutils/rewrite.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/revlogutils/rewrite.py Sun Aug 22 16:32:06 2021 -0400 @@ -7,8 +7,10 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. +import binascii import contextlib import os +import struct from ..node import ( nullrev, @@ -27,6 +29,7 @@ ENTRY_SIDEDATA_COMPRESSED_LENGTH, ENTRY_SIDEDATA_COMPRESSION_MODE, ENTRY_SIDEDATA_OFFSET, + REVIDX_ISCENSORED, REVLOGV0, REVLOGV1, ) @@ -34,6 +37,7 @@ from .. import ( error, + mdiff, pycompat, revlogutils, util, @@ -472,3 +476,411 @@ new_index_file.write(entry_bin) revlog._docket.index_end = new_index_file.tell() revlog._docket.data_end = new_data_file.tell() + + +def _get_filename_from_filelog_index(path): + # Drop the extension and the `data/` prefix + path_part = path.rsplit(b'.', 1)[0].split(b'/', 1) + if len(path_part) < 2: + msg = _(b"cannot recognize filelog from filename: '%s'") + msg %= path + raise error.Abort(msg) + + return path_part[1] + + +def _filelog_from_filename(repo, path): + """Returns the filelog for the given `path`. Stolen from `engine.py`""" + + from .. import filelog # avoid cycle + + fl = filelog.filelog(repo.svfs, path) + return fl + + +def _write_swapped_parents(repo, rl, rev, offset, fp): + """Swaps p1 and p2 and overwrites the revlog entry for `rev` in `fp`""" + from ..pure import parsers # avoid cycle + + if repo._currentlock(repo._lockref) is None: + # Let's be paranoid about it + msg = "repo needs to be locked to rewrite parents" + raise error.ProgrammingError(msg) + + index_format = parsers.IndexObject.index_format + entry = rl.index[rev] + new_entry = list(entry) + new_entry[5], new_entry[6] = entry[6], entry[5] + packed = index_format.pack(*new_entry[:8]) + fp.seek(offset) + fp.write(packed) + + +def _reorder_filelog_parents(repo, fl, to_fix): + """ + Swaps p1 and p2 for all `to_fix` revisions of filelog `fl` and writes the + new version to disk, overwriting the old one with a rename. + """ + from ..pure import parsers # avoid cycle + + ui = repo.ui + assert len(to_fix) > 0 + rl = fl._revlog + if rl._format_version != constants.REVLOGV1: + msg = "expected version 1 revlog, got version '%d'" % rl._format_version + raise error.ProgrammingError(msg) + + index_file = rl._indexfile + new_file_path = index_file + b'.tmp-parents-fix' + repaired_msg = _(b"repaired revision %d of 'filelog %s'\n") + + with ui.uninterruptible(): + try: + util.copyfile( + rl.opener.join(index_file), + rl.opener.join(new_file_path), + checkambig=rl._checkambig, + ) + + with rl.opener(new_file_path, mode=b"r+") as fp: + if rl._inline: + index = parsers.InlinedIndexObject(fp.read()) + for rev in fl.revs(): + if rev in to_fix: + offset = index._calculate_index(rev) + _write_swapped_parents(repo, rl, rev, offset, fp) + ui.write(repaired_msg % (rev, index_file)) + else: + index_format = parsers.IndexObject.index_format + for rev in to_fix: + offset = rev * index_format.size + _write_swapped_parents(repo, rl, rev, offset, fp) + ui.write(repaired_msg % (rev, index_file)) + + rl.opener.rename(new_file_path, index_file) + rl.clearcaches() + rl._loadindex() + finally: + util.tryunlink(new_file_path) + + +def _is_revision_affected(fl, filerev, metadata_cache=None): + full_text = lambda: fl._revlog.rawdata(filerev) + parent_revs = lambda: fl._revlog.parentrevs(filerev) + return _is_revision_affected_inner( + full_text, parent_revs, filerev, metadata_cache + ) + + +def _is_revision_affected_inner( + full_text, + parents_revs, + filerev, + metadata_cache=None, +): + """Mercurial currently (5.9rc0) uses `p1 == nullrev and p2 != nullrev` as a + special meaning compared to the reverse in the context of filelog-based + copytracing. issue6528 exists because new code assumed that parent ordering + didn't matter, so this detects if the revision contains metadata (since + it's only used for filelog-based copytracing) and its parents are in the + "wrong" order.""" + try: + raw_text = full_text() + except error.CensoredNodeError: + # We don't care about censored nodes as they never carry metadata + return False + has_meta = raw_text.startswith(b'\x01\n') + if metadata_cache is not None: + metadata_cache[filerev] = has_meta + if has_meta: + (p1, p2) = parents_revs() + if p1 != nullrev and p2 == nullrev: + return True + return False + + +def _is_revision_affected_fast(repo, fl, filerev, metadata_cache): + rl = fl._revlog + is_censored = lambda: rl.iscensored(filerev) + delta_base = lambda: rl.deltaparent(filerev) + delta = lambda: rl._chunk(filerev) + full_text = lambda: rl.rawdata(filerev) + parent_revs = lambda: rl.parentrevs(filerev) + return _is_revision_affected_fast_inner( + is_censored, + delta_base, + delta, + full_text, + parent_revs, + filerev, + metadata_cache, + ) + + +def _is_revision_affected_fast_inner( + is_censored, + delta_base, + delta, + full_text, + parent_revs, + filerev, + metadata_cache, +): + """Optimization fast-path for `_is_revision_affected`. + + `metadata_cache` is a dict of `{rev: has_metadata}` which allows any + revision to check if its base has metadata, saving computation of the full + text, instead looking at the current delta. + + This optimization only works if the revisions are looked at in order.""" + + if is_censored(): + # Censored revisions don't contain metadata, so they cannot be affected + metadata_cache[filerev] = False + return False + + p1, p2 = parent_revs() + if p1 == nullrev or p2 != nullrev: + return False + + delta_parent = delta_base() + parent_has_metadata = metadata_cache.get(delta_parent) + if parent_has_metadata is None: + return _is_revision_affected_inner( + full_text, + parent_revs, + filerev, + metadata_cache, + ) + + chunk = delta() + if not len(chunk): + # No diff for this revision + return parent_has_metadata + + header_length = 12 + if len(chunk) < header_length: + raise error.Abort(_(b"patch cannot be decoded")) + + start, _end, _length = struct.unpack(b">lll", chunk[:header_length]) + + if start < 2: # len(b'\x01\n') == 2 + # This delta does *something* to the metadata marker (if any). + # Check it the slow way + is_affected = _is_revision_affected_inner( + full_text, + parent_revs, + filerev, + metadata_cache, + ) + return is_affected + + # The diff did not remove or add the metadata header, it's then in the same + # situation as its parent + metadata_cache[filerev] = parent_has_metadata + return parent_has_metadata + + +def _from_report(ui, repo, context, from_report, dry_run): + """ + Fix the revisions given in the `from_report` file, but still checks if the + revisions are indeed affected to prevent an unfortunate cyclic situation + where we'd swap well-ordered parents again. + + See the doc for `debug_fix_issue6528` for the format documentation. + """ + ui.write(_(b"loading report file '%s'\n") % from_report) + + with context(), open(from_report, mode='rb') as f: + for line in f.read().split(b'\n'): + if not line: + continue + filenodes, filename = line.split(b' ', 1) + fl = _filelog_from_filename(repo, filename) + to_fix = set( + fl.rev(binascii.unhexlify(n)) for n in filenodes.split(b',') + ) + excluded = set() + + for filerev in to_fix: + if _is_revision_affected(fl, filerev): + msg = b"found affected revision %d for filelog '%s'\n" + ui.warn(msg % (filerev, filename)) + else: + msg = _(b"revision %s of file '%s' is not affected\n") + msg %= (binascii.hexlify(fl.node(filerev)), filename) + ui.warn(msg) + excluded.add(filerev) + + to_fix = to_fix - excluded + if not to_fix: + msg = _(b"no affected revisions were found for '%s'\n") + ui.write(msg % filename) + continue + if not dry_run: + _reorder_filelog_parents(repo, fl, sorted(to_fix)) + + +def filter_delta_issue6528(revlog, deltas_iter): + """filter incomind deltas to repaire issue 6528 on the fly""" + metadata_cache = {} + + deltacomputer = deltas.deltacomputer(revlog) + + for rev, d in enumerate(deltas_iter, len(revlog)): + ( + node, + p1_node, + p2_node, + linknode, + deltabase, + delta, + flags, + sidedata, + ) = d + + if not revlog.index.has_node(deltabase): + raise error.LookupError( + deltabase, revlog.radix, _(b'unknown parent') + ) + base_rev = revlog.rev(deltabase) + if not revlog.index.has_node(p1_node): + raise error.LookupError(p1_node, revlog.radix, _(b'unknown parent')) + p1_rev = revlog.rev(p1_node) + if not revlog.index.has_node(p2_node): + raise error.LookupError(p2_node, revlog.radix, _(b'unknown parent')) + p2_rev = revlog.rev(p2_node) + + is_censored = lambda: bool(flags & REVIDX_ISCENSORED) + delta_base = lambda: revlog.rev(delta_base) + delta_base = lambda: base_rev + parent_revs = lambda: (p1_rev, p2_rev) + + def full_text(): + # note: being able to reuse the full text computation in the + # underlying addrevision would be useful however this is a bit too + # intrusive the for the "quick" issue6528 we are writing before the + # 5.8 release + textlen = mdiff.patchedsize(revlog.size(base_rev), delta) + + revinfo = revlogutils.revisioninfo( + node, + p1_node, + p2_node, + [None], + textlen, + (base_rev, delta), + flags, + ) + # cached by the global "writing" context + assert revlog._writinghandles is not None + if revlog._inline: + fh = revlog._writinghandles[0] + else: + fh = revlog._writinghandles[1] + return deltacomputer.buildtext(revinfo, fh) + + is_affected = _is_revision_affected_fast_inner( + is_censored, + delta_base, + lambda: delta, + full_text, + parent_revs, + rev, + metadata_cache, + ) + if is_affected: + d = ( + node, + p2_node, + p1_node, + linknode, + deltabase, + delta, + flags, + sidedata, + ) + yield d + + +def repair_issue6528( + ui, repo, dry_run=False, to_report=None, from_report=None, paranoid=False +): + from .. import store # avoid cycle + + @contextlib.contextmanager + def context(): + if dry_run or to_report: # No need for locking + yield + else: + with repo.wlock(), repo.lock(): + yield + + if from_report: + return _from_report(ui, repo, context, from_report, dry_run) + + report_entries = [] + + with context(): + files = list( + (file_type, path) + for (file_type, path, _e, _s) in repo.store.datafiles() + if path.endswith(b'.i') and file_type & store.FILEFLAGS_FILELOG + ) + + progress = ui.makeprogress( + _(b"looking for affected revisions"), + unit=_(b"filelogs"), + total=len(files), + ) + found_nothing = True + + for file_type, path in files: + if ( + not path.endswith(b'.i') + or not file_type & store.FILEFLAGS_FILELOG + ): + continue + progress.increment() + filename = _get_filename_from_filelog_index(path) + fl = _filelog_from_filename(repo, filename) + + # Set of filerevs (or hex filenodes if `to_report`) that need fixing + to_fix = set() + metadata_cache = {} + for filerev in fl.revs(): + affected = _is_revision_affected_fast( + repo, fl, filerev, metadata_cache + ) + if paranoid: + slow = _is_revision_affected(fl, filerev) + if slow != affected: + msg = _(b"paranoid check failed for '%s' at node %s") + node = binascii.hexlify(fl.node(filerev)) + raise error.Abort(msg % (filename, node)) + if affected: + msg = b"found affected revision %d for filelog '%s'\n" + ui.warn(msg % (filerev, path)) + found_nothing = False + if not dry_run: + if to_report: + to_fix.add(binascii.hexlify(fl.node(filerev))) + else: + to_fix.add(filerev) + + if to_fix: + to_fix = sorted(to_fix) + if to_report: + report_entries.append((filename, to_fix)) + else: + _reorder_filelog_parents(repo, fl, to_fix) + + if found_nothing: + ui.write(_(b"no affected revisions were found\n")) + + if to_report and report_entries: + with open(to_report, mode="wb") as f: + for path, to_fix in report_entries: + f.write(b"%s %s\n" % (b",".join(to_fix), path)) + + progress.complete()
--- a/mercurial/rewriteutil.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/rewriteutil.py Sun Aug 22 16:32:06 2021 -0400 @@ -207,7 +207,12 @@ hashes = re.findall(NODE_RE, commitmsg) unfi = repo.unfiltered() for h in hashes: - fullnode = scmutil.resolvehexnodeidprefix(unfi, h) + try: + fullnode = scmutil.resolvehexnodeidprefix(unfi, h) + except error.WdirUnsupported: + # Someone has an fffff... in a commit message we're + # rewriting. Don't try rewriting that. + continue if fullnode is None: continue ctx = unfi[fullnode]
--- a/mercurial/store.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/store.py Sun Aug 22 16:32:06 2021 -0400 @@ -569,6 +569,11 @@ self.vfs = vfsmod.filtervfs(vfs, encodefilename) self.opener = self.vfs + # note: topfiles would also need a decode phase. It is just that in + # practice we do not have any file outside of `data/` that needs encoding. + # However that might change so we should probably add a test and encoding + # decoding for it too. see issue6548 + def datafiles(self, matcher=None): for t, a, b, size in super(encodedstore, self).datafiles(): try:
--- a/mercurial/streamclone.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/streamclone.py Sun Aug 22 16:32:06 2021 -0400 @@ -565,6 +565,16 @@ def _emit2(repo, entries, totalfilesize): """actually emit the stream bundle""" vfsmap = _makemap(repo) + # we keep repo.vfs out of the on purpose, ther are too many danger there + # (eg: .hg/hgrc), + # + # this assert is duplicated (from _makemap) as author might think this is + # fine, while this is really not fine. + if repo.vfs in vfsmap.values(): + raise error.ProgrammingError( + b'repo.vfs must not be added to vfsmap for security reasons' + ) + progress = repo.ui.makeprogress( _(b'bundle'), total=totalfilesize, unit=_(b'bytes') ) @@ -573,7 +583,7 @@ # copy is delayed until we are in the try entries = [_filterfull(e, copy, vfsmap) for e in entries] yield None # this release the lock on the repository - seen = 0 + totalbytecount = 0 for src, name, ftype, data in entries: vfs = vfsmap[src] @@ -585,6 +595,7 @@ elif ftype == _filefull: fp = open(data, b'rb') size = util.fstat(fp).st_size + bytecount = 0 try: yield util.uvarintencode(size) yield name @@ -593,9 +604,20 @@ else: chunks = util.filechunkiter(fp, limit=size) for chunk in chunks: - seen += len(chunk) - progress.update(seen) + bytecount += len(chunk) + totalbytecount += len(chunk) + progress.update(totalbytecount) yield chunk + if bytecount != size: + # Would most likely be caused by a race due to `hg strip` or + # a revlog split + raise error.Abort( + _( + b'clone could only read %d bytes from %s, but ' + b'expected %d bytes' + ) + % (bytecount, name, size) + ) finally: fp.close() @@ -713,6 +735,15 @@ progress.update(0) vfsmap = _makemap(repo) + # we keep repo.vfs out of the on purpose, ther are too many danger + # there (eg: .hg/hgrc), + # + # this assert is duplicated (from _makemap) as author might think this + # is fine, while this is really not fine. + if repo.vfs in vfsmap.values(): + raise error.ProgrammingError( + b'repo.vfs must not be added to vfsmap for security reasons' + ) with repo.transaction(b'clone'): ctxs = (vfs.backgroundclosing(repo.ui) for vfs in vfsmap.values())
--- a/mercurial/subrepo.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/subrepo.py Sun Aug 22 16:32:06 2021 -0400 @@ -458,12 +458,14 @@ create = allowcreate and not r.wvfs.exists(b'%s/.hg' % path) # repository constructor does expand variables in path, which is # unsafe since subrepo path might come from untrusted source. - if os.path.realpath(util.expandpath(root)) != root: + norm_root = os.path.normcase(root) + real_root = os.path.normcase(os.path.realpath(util.expandpath(root))) + if real_root != norm_root: raise error.Abort( _(b'subrepo path contains illegal component: %s') % path ) self._repo = hg.repository(r.baseui, root, create=create) - if self._repo.root != root: + if os.path.normcase(self._repo.root) != os.path.normcase(root): raise error.ProgrammingError( b'failed to reject unsafe subrepo ' b'path: %s (expanded to %s)' % (root, self._repo.root)
--- a/mercurial/templater.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/templater.py Sun Aug 22 16:32:06 2021 -0400 @@ -71,7 +71,10 @@ import os from .i18n import _ -from .pycompat import getattr +from .pycompat import ( + FileNotFoundError, + getattr, +) from . import ( config, encoding, @@ -833,6 +836,13 @@ def _readmapfile(fp, mapfile): """Load template elements from the given map file""" + if pycompat.iswindows: + # quick hack to make sure we can process '/' in the code dealing with + # ressource. Ideally we would make sure we use `/` instead of `ossep` + # in the templater code, but that seems a bigger and less certain + # change that we better left for the default branch. + name_paths = mapfile.split(pycompat.ossep) + mapfile = b'/'.join(name_paths) base = os.path.dirname(mapfile) conf = config.config() @@ -845,9 +855,12 @@ if not subresource: if pycompat.ossep not in rel: abs = rel - subresource = resourceutil.open_resource( - b'mercurial.templates', rel - ) + try: + subresource = resourceutil.open_resource( + b'mercurial.templates', rel + ) + except FileNotFoundError: + subresource = None else: dir = templatedir() if dir: @@ -1117,6 +1130,13 @@ return f, open(f, mode='rb') # Otherwise try to read it using the resources API + if pycompat.iswindows: + # quick hack to make sure we can process '/' in the code dealing with + # ressource. Ideally we would make sure we use `/` instead of `ossep` + # in the templater code, but that seems a bigger and less certain + # change that we better left for the default branch. + name_paths = name.split(pycompat.ossep) + name = b'/'.join(name_paths) name_parts = name.split(b'/') package_name = b'.'.join([b'mercurial', b'templates'] + name_parts[:-1]) return (
--- a/mercurial/testing/__init__.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/testing/__init__.py Sun Aug 22 16:32:06 2021 -0400 @@ -33,5 +33,11 @@ def write_file(path, content=b''): - with open(path, 'wb') as f: + if content: + write_path = b'%s.tmp' % path + else: + write_path = path + with open(write_path, 'wb') as f: f.write(content) + if path != write_path: + os.rename(write_path, path)
--- a/mercurial/upgrade_utils/engine.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/upgrade_utils/engine.py Sun Aug 22 16:32:06 2021 -0400 @@ -66,7 +66,7 @@ # drop the extension and the `data/` prefix path_part = path.rsplit(b'.', 1)[0].split(b'/', 1) if len(path_part) < 2: - msg = _('cannot recognize revlog from filename: %s') + msg = _(b'cannot recognize revlog from filename: %s') msg %= path raise error.Abort(msg) path = path_part[1]
--- a/mercurial/vfs.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/vfs.py Sun Aug 22 16:32:06 2021 -0400 @@ -50,6 +50,14 @@ class abstractvfs(object): """Abstract base class; cannot be instantiated""" + # default directory separator for vfs + # + # Other vfs code always use `/` and this works fine because python file API + # abstract the use of `/` and make it work transparently. For consistency + # vfs will always use `/` when joining. This avoid some confusion in + # encoded vfs (see issue6546) + _dir_sep = b'/' + def __init__(self, *args, **kwargs): '''Prevent instantiation; don't call this from subclasses.''' raise NotImplementedError('attempted instantiating ' + str(type(self))) @@ -152,12 +160,22 @@ mode = st.st_mode return stat.S_ISREG(mode) or stat.S_ISLNK(mode) + def _join(self, *paths): + root_idx = 0 + for idx, p in enumerate(paths): + if os.path.isabs(p) or p.startswith(self._dir_sep): + root_idx = idx + if root_idx != 0: + paths = paths[root_idx:] + paths = [p for p in paths if p] + return self._dir_sep.join(paths) + def reljoin(self, *paths): """join various elements of a path together (as os.path.join would do) The vfs base is not injected so that path stay relative. This exists to allow handling of strange encoding if needed.""" - return os.path.join(*paths) + return self._join(*paths) def split(self, path): """split top-most element of a path (as os.path.split would do) @@ -528,7 +546,9 @@ def join(self, path, *insidef): if path: - return os.path.join(self.base, path, *insidef) + parts = [self.base, path] + parts.extend(insidef) + return self._join(*parts) else: return self.base
--- a/mercurial/windows.py Tue Jul 20 17:20:19 2021 +0200 +++ b/mercurial/windows.py Sun Aug 22 16:32:06 2021 -0400 @@ -200,20 +200,20 @@ This shouldn't be called directly- use ``ui.getpass()`` instead, which checks if the session is interactive first. """ - pw = "" + pw = u"" while True: c = msvcrt.getwch() # pytype: disable=module-attr - if c == '\r' or c == '\n': + if c == u'\r' or c == u'\n': break - if c == '\003': + if c == u'\003': raise KeyboardInterrupt - if c == '\b': + if c == u'\b': pw = pw[:-1] else: pw = pw + c - msvcrt.putwch('\r') # pytype: disable=module-attr - msvcrt.putwch('\n') # pytype: disable=module-attr - return encoding.strtolocal(pw) + msvcrt.putwch(u'\r') # pytype: disable=module-attr + msvcrt.putwch(u'\n') # pytype: disable=module-attr + return encoding.unitolocal(pw) class winstdout(object):
--- a/rust/hg-core/src/errors.rs Tue Jul 20 17:20:19 2021 +0200 +++ b/rust/hg-core/src/errors.rs Sun Aug 22 16:32:06 2021 -0400 @@ -47,6 +47,8 @@ /// Details about where an I/O error happened #[derive(Debug)] pub enum IoErrorContext { + /// `std::fs::metadata` + ReadingMetadata(std::path::PathBuf), ReadingFile(std::path::PathBuf), WritingFile(std::path::PathBuf), RemovingFile(std::path::PathBuf), @@ -108,6 +110,9 @@ impl fmt::Display for IoErrorContext { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { + IoErrorContext::ReadingMetadata(path) => { + write!(f, "when reading metadata of {}", path.display()) + } IoErrorContext::ReadingFile(path) => { write!(f, "when reading {}", path.display()) }
--- a/rust/hg-core/src/repo.rs Tue Jul 20 17:20:19 2021 +0200 +++ b/rust/hg-core/src/repo.rs Sun Aug 22 16:32:06 2021 -0400 @@ -6,6 +6,7 @@ use crate::utils::SliceExt; use memmap::{Mmap, MmapOptions}; use std::collections::HashSet; +use std::io::ErrorKind; use std::path::{Path, PathBuf}; /// A repository on disk @@ -51,7 +52,7 @@ // ancestors() is inclusive: it first yields `current_directory` // as-is. for ancestor in current_directory.ancestors() { - if ancestor.join(".hg").is_dir() { + if is_dir(ancestor.join(".hg"))? { return Ok(ancestor.to_path_buf()); } } @@ -73,9 +74,9 @@ explicit_path: Option<PathBuf>, ) -> Result<Self, RepoError> { if let Some(root) = explicit_path { - if root.join(".hg").is_dir() { + if is_dir(root.join(".hg"))? { Self::new_at_path(root.to_owned(), config) - } else if root.is_file() { + } else if is_file(&root)? { Err(HgError::unsupported("bundle repository").into()) } else { Err(RepoError::NotFound { @@ -130,7 +131,7 @@ if relative { shared_path = dot_hg.join(shared_path) } - if !shared_path.is_dir() { + if !is_dir(&shared_path)? { return Err(HgError::corrupted(format!( ".hg/sharedpath points to nonexistent directory {}", shared_path.display() @@ -286,3 +287,29 @@ .with_context(|| IoErrorContext::RenamingFile { from, to }) } } + +fn fs_metadata( + path: impl AsRef<Path>, +) -> Result<Option<std::fs::Metadata>, HgError> { + let path = path.as_ref(); + match std::fs::metadata(path) { + Ok(meta) => Ok(Some(meta)), + Err(error) => match error.kind() { + // TODO: when we require a Rust version where `NotADirectory` is + // stable, invert this logic and return None for it and `NotFound` + // and propagate any other error. + ErrorKind::PermissionDenied => Err(error).with_context(|| { + IoErrorContext::ReadingMetadata(path.to_owned()) + }), + _ => Ok(None), + }, + } +} + +fn is_dir(path: impl AsRef<Path>) -> Result<bool, HgError> { + Ok(fs_metadata(path)?.map_or(false, |meta| meta.is_dir())) +} + +fn is_file(path: impl AsRef<Path>) -> Result<bool, HgError> { + Ok(fs_metadata(path)?.map_or(false, |meta| meta.is_file())) +}
--- a/rust/hg-cpython/src/revlog.rs Tue Jul 20 17:20:19 2021 +0200 +++ b/rust/hg-cpython/src/revlog.rs Sun Aug 22 16:32:06 2021 -0400 @@ -59,12 +59,22 @@ /// Return Revision if found, raises a bare `error.RevlogError` /// in case of ambiguity, same as C version does - def get_rev(&self, node: PyBytes) -> PyResult<Option<Revision>> { + def get_rev(&self, pynode: PyBytes) -> PyResult<Option<Revision>> { let opt = self.get_nodetree(py)?.borrow(); let nt = opt.as_ref().unwrap(); let idx = &*self.cindex(py).borrow(); - let node = node_from_py_bytes(py, &node)?; - nt.find_bin(idx, node.into()).map_err(|e| nodemap_error(py, e)) + let node = node_from_py_bytes(py, &pynode)?; + match nt.find_bin(idx, node.into()) + { + Ok(None) => + // fallback to C implementation, remove once + // https://bz.mercurial-scm.org/show_bug.cgi?id=6554 + // is fixed (a simple backout should do) + self.call_cindex(py, "get_rev", &PyTuple::new(py, &[pynode.into_object()]), None)? + .extract(py), + Ok(Some(rev)) => Ok(Some(rev)), + Err(e) => Err(nodemap_error(py, e)), + } } /// same as `get_rev()` but raises a bare `error.RevlogError` if node @@ -94,27 +104,34 @@ } } - def partialmatch(&self, node: PyObject) -> PyResult<Option<PyBytes>> { + def partialmatch(&self, pynode: PyObject) -> PyResult<Option<PyBytes>> { let opt = self.get_nodetree(py)?.borrow(); let nt = opt.as_ref().unwrap(); let idx = &*self.cindex(py).borrow(); let node_as_string = if cfg!(feature = "python3-sys") { - node.cast_as::<PyString>(py)?.to_string(py)?.to_string() + pynode.cast_as::<PyString>(py)?.to_string(py)?.to_string() } else { - let node = node.extract::<PyBytes>(py)?; + let node = pynode.extract::<PyBytes>(py)?; String::from_utf8_lossy(node.data(py)).to_string() }; let prefix = NodePrefix::from_hex(&node_as_string).map_err(|_| PyErr::new::<ValueError, _>(py, "Invalid node or prefix"))?; - nt.find_bin(idx, prefix) - // TODO make an inner API returning the node directly - .map(|opt| opt.map( - |rev| PyBytes::new(py, idx.node(rev).unwrap().as_bytes()))) - .map_err(|e| nodemap_error(py, e)) - + match nt.find_bin(idx, prefix) { + Ok(None) => + // fallback to C implementation, remove once + // https://bz.mercurial-scm.org/show_bug.cgi?id=6554 + // is fixed (a simple backout should do) + self.call_cindex( + py, "partialmatch", + &PyTuple::new(py, &[pynode]), None + )?.extract(py), + Ok(Some(rev)) => + Ok(Some(PyBytes::new(py, idx.node(rev).unwrap().as_bytes()))), + Err(e) => Err(nodemap_error(py, e)), + } } /// append an index entry
--- a/rust/hgcli/pyoxidizer.bzl Tue Jul 20 17:20:19 2021 +0200 +++ b/rust/hgcli/pyoxidizer.bzl Sun Aug 22 16:32:06 2021 -0400 @@ -35,7 +35,20 @@ IS_WINDOWS = "windows" in BUILD_TARGET_TRIPLE # Code to run in Python interpreter. -RUN_CODE = "import hgdemandimport; hgdemandimport.enable(); from mercurial import dispatch; dispatch.run()" +RUN_CODE = """ +import os +import sys +extra_path = os.environ.get('PYTHONPATH') +if extra_path is not None: + # extensions and hooks expect a working python environment + # We do not prepend the values because the Mercurial library wants to be in + # the front of the sys.path to avoid picking up other installations. + sys.path.extend(extra_path.split(os.pathsep)) +import hgdemandimport; +hgdemandimport.enable(); +from mercurial import dispatch; +dispatch.run(); +""" set_build_path(ROOT + "/build/pyoxidizer")
--- a/rust/rhg/README.md Tue Jul 20 17:20:19 2021 +0200 +++ b/rust/rhg/README.md Sun Aug 22 16:32:06 2021 -0400 @@ -1,4 +1,77 @@ -# rhg +# `rhg` + +The `rhg` executable implements a subset of the functionnality of `hg` +using only Rust, to avoid the startup cost of a Python interpreter. +This subset is initially small but grows over time as `rhg` is improved. +When fallback to the Python implementation is configured (see below), +`rhg` aims to be a drop-in replacement for `hg` that should behave the same, +except that some commands run faster. + + +## Building + +To compile `rhg`, either run `cargo build --release` from this `rust/rhg/` +directory, or run `make build-rhg` from the repository root. +The executable can then be found at `rust/target/release/rhg`. + + +## Mercurial configuration + +`rhg` reads Mercurial configuration from the usual sources: +the user’s `~/.hgrc`, a repository’s `.hg/hgrc`, command line `--config`, etc. +It has some specific configuration in the `[rhg]` section: + +* `on-unsupported` governs the behavior of `rhg` when it encounters something + that it does not support but “full” `hg` possibly does. + This can be in configuration, on the command line, or in a repository. + + - `abort`, the default value, makes `rhg` print a message to stderr + to explain what is not supported, then terminate with a 252 exit code. + - `abort-silent` makes it terminate with the same exit code, + but without printing anything. + - `fallback` makes it silently call a (presumably Python-based) `hg` + subprocess with the same command-line parameters. + The `rhg.fallback-executable` configuration must be set. + +* `fallback-executable`: path to the executable to run in a sub-process + when falling back to a Python implementation of Mercurial. -This project provides a fastpath Rust implementation of the Mercurial (`hg`) -version control tool. +* `allowed-extensions`: a list of extension names that `rhg` can ignore. + + Mercurial extensions can modify the behavior of existing `hg` sub-commands, + including those that `rhg` otherwise supports. + Because it cannot load Python extensions, finding them + enabled in configuration is considered “unsupported” (see above). + A few exceptions are made for extensions that `rhg` does know about, + with the Rust implementation duplicating their behavior. + + This configuration makes additional exceptions: `rhg` will proceed even if + those extensions are enabled. + + +## Installation and configuration example + +For example, to install `rhg` as `hg` for the current user with fallback to +the system-wide install of Mercurial, and allow it to run even though the +`rebase` and `absorb` extensions are enabled, on a Unix-like platform: + +* Build `rhg` (see above) +* Make sure the `~/.local/bin` exists and is in `$PATH` +* From the repository root, make a symbolic link with + `ln -s rust/target/release/rhg ~/.local/bin/hg` +* Configure `~/.hgrc` with: + +``` +[rhg] +on-unsupported = fallback +fallback-executable = /usr/bin/hg +allowed-extensions = rebase, absorb +``` + +* Check that the output of running + `hg notarealsubcommand` + starts with `hg: unknown command`, which indicates fallback. + +* Check that the output of running + `hg notarealsubcommand --config rhg.on-unsupported=abort` + starts with `unsupported feature:`.
--- a/tests/dummyssh Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/dummyssh Sun Aug 22 16:32:06 2021 -0400 @@ -31,5 +31,5 @@ hgcmd = shlex.join(cmds) # shlex generate windows incompatible string... hgcmd = hgcmd.replace("'", '"') -r = subprocess.call(hgcmd, shell=True) +r = subprocess.call(hgcmd, shell=True, close_fds=True) sys.exit(bool(r))
--- a/tests/hghave.py Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/hghave.py Sun Aug 22 16:32:06 2021 -0400 @@ -199,6 +199,11 @@ return 'RHG_INSTALLED_AS_HG' in os.environ +@check("pyoxidizer", "running with pyoxidizer build as 'hg'") +def has_rhg(): + return 'PYOXIDIZED_INSTALLED_AS_HG' in os.environ + + @check("cvs", "cvs client/server") def has_cvs(): re = br'Concurrent Versions System.*?server'
--- a/tests/run-tests.py Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/run-tests.py Sun Aug 22 16:32:06 2021 -0400 @@ -594,6 +594,11 @@ action="store_true", help="install and use rhg Rust implementation in place of hg", ) + hgconf.add_argument( + "--pyoxidized", + action="store_true", + help="build the hg binary using pyoxidizer", + ) hgconf.add_argument("--compiler", help="compiler to build with") hgconf.add_argument( '--extra-config-opt', @@ -731,6 +736,8 @@ parser.error( '--local cannot be used with --with-hg or --with-rhg or --with-chg' ) + if options.pyoxidized: + parser.error('--pyoxidized does not work with --local (yet)') testdir = os.path.dirname(_sys2bytes(canonpath(sys.argv[0]))) reporootdir = os.path.dirname(testdir) pathandattrs = [(b'hg', 'with_hg')] @@ -764,6 +771,8 @@ parser.error('chg does not work on %s' % os.name) if (options.rhg or options.with_rhg) and WINDOWS: parser.error('rhg does not work on %s' % os.name) + if options.pyoxidized and not WINDOWS: + parser.error('--pyoxidized is currently Windows only') if options.with_chg: options.chg = False # no installation to temporary location options.with_chg = canonpath(_sys2bytes(options.with_chg)) @@ -1546,6 +1555,8 @@ hgrc.write(b'mergemarkers = detailed\n') hgrc.write(b'promptecho = True\n') hgrc.write(b'timeout.warn=15\n') + hgrc.write(b'[chgserver]\n') + hgrc.write(b'idletimeout=60\n') hgrc.write(b'[defaults]\n') hgrc.write(b'[devel]\n') hgrc.write(b'all-warnings = true\n') @@ -1587,6 +1598,7 @@ proc = subprocess.Popen( _bytes2sys(cmd), shell=True, + close_fds=closefds, cwd=_bytes2sys(self._testtmp), env=env, ) @@ -3220,6 +3232,20 @@ rhgbindir = os.path.dirname(os.path.realpath(self.options.with_rhg)) self._hgcommand = os.path.basename(self.options.with_rhg) + if self.options.pyoxidized: + testdir = os.path.dirname(_sys2bytes(canonpath(sys.argv[0]))) + reporootdir = os.path.dirname(testdir) + # XXX we should ideally install stuff instead of using the local build + bin_path = ( + b'build/pyoxidizer/x86_64-pc-windows-msvc/release/app/hg.exe' + ) + full_path = os.path.join(reporootdir, bin_path) + self._hgcommand = full_path + # Affects hghave.py + osenvironb[b'PYOXIDIZED_INSTALLED_AS_HG'] = b'1' + else: + osenvironb.pop(b'PYOXIDIZED_INSTALLED_AS_HG', None) + osenvironb[b"BINDIR"] = self._bindir osenvironb[b"PYTHON"] = PYTHON @@ -3460,6 +3486,8 @@ if self.options.rhg: assert self._installdir self._installrhg() + elif self.options.pyoxidized: + self._build_pyoxidized() self._use_correct_mercurial() log( @@ -3872,6 +3900,37 @@ sys.stdout.write(out) sys.exit(1) + def _build_pyoxidized(self): + """build a pyoxidized version of mercurial into the test environment + + Ideally this function would be `install_pyoxidier` and would both build + and install pyoxidier. However we are starting small to get pyoxidizer + build binary to testing quickly. + """ + vlog('# build a pyoxidized version of Mercurial') + assert os.path.dirname(self._bindir) == self._installdir + assert self._hgroot, 'must be called after _installhg()' + cmd = b'"%(make)s" pyoxidizer-windows-tests' % { + b'make': b'make', + } + cwd = self._hgroot + vlog("# Running", cmd) + proc = subprocess.Popen( + _bytes2sys(cmd), + shell=True, + cwd=_bytes2sys(cwd), + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + out, _err = proc.communicate() + if proc.returncode != 0: + if PYTHON3: + sys.stdout.buffer.write(out) + else: + sys.stdout.write(out) + sys.exit(1) + def _outputcoverage(self): """Produce code coverage output.""" import coverage
--- a/tests/test-annotate.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-annotate.t Sun Aug 22 16:32:06 2021 -0400 @@ -631,7 +631,7 @@ $ rm baz $ hg annotate -ncr "wdir()" baz - abort: $TESTTMP\repo\baz: $ENOENT$ (windows !) + abort: $TESTTMP\repo/baz: $ENOENT$ (windows !) abort: $ENOENT$: '$TESTTMP/repo/baz' (no-windows !) [255] @@ -640,7 +640,7 @@ $ hg rm baz $ hg annotate -ncr "wdir()" baz - abort: $TESTTMP\repo\baz: $ENOENT$ (windows !) + abort: $TESTTMP\repo/baz: $ENOENT$ (windows !) abort: $ENOENT$: '$TESTTMP/repo/baz' (no-windows !) [255]
--- a/tests/test-bad-extension.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-bad-extension.t Sun Aug 22 16:32:06 2021 -0400 @@ -20,7 +20,8 @@ show help for a given topic or a help overview error in exit handlers: Traceback (most recent call last): - File "*/mercurial/dispatch.py", line *, in _runexithandlers (glob) + File "*/mercurial/dispatch.py", line *, in _runexithandlers (glob) (no-pyoxidizer !) + File "mercurial.dispatch", line *, in _runexithandlers (glob) (pyoxidizer !) func(*args, **kwargs) File "$TESTTMP/bailatexit.py", line *, in bail (glob) raise RuntimeError('ui.atexit handler exception')
--- a/tests/test-basic.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-basic.t Sun Aug 22 16:32:06 2021 -0400 @@ -2,6 +2,7 @@ #if no-extraextensions $ hg config + chgserver.idletimeout=60 devel.all-warnings=true devel.default-date=0 0 extensions.fsmonitor= (fsmonitor !)
--- a/tests/test-clone-uncompressed.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-clone-uncompressed.t Sun Aug 22 16:32:06 2021 -0400 @@ -89,6 +89,13 @@ $ echo foo > store/undo.foo.d $ echo foo > store/undo.foo.n $ echo foo > store/undo.babar + +Name with special characters + + $ echo foo > store/CélesteVille_is_a_Capital_City + +All all that + $ hg add . adding 00changelog-ab349180a0405010.nd adding 00changelog.d @@ -132,6 +139,7 @@ adding savanah/undo.i adding savanah/undo.n adding savanah/undo.py + adding store/C\xc3\xa9lesteVille_is_a_Capital_City (esc) adding store/foo.d adding store/foo.i adding store/foo.n @@ -156,6 +164,19 @@ $ cat hg.pid > $DAEMON_PIDS $ cd .. +Check local clone +================== + +The logic is close enough of uncompressed. +This is present here to reuse the testing around file with "special" names. + + $ hg clone server local-clone + updating to branch default + 1087 files updated, 0 files merged, 0 files removed, 0 files unresolved + +Check uncompressed +================== + Cannot stream clone when server.uncompressed is set $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out' @@ -211,8 +232,8 @@ adding changesets adding manifests adding file changes - added 3 changesets with 1086 changes to 1086 files - new changesets 96ee1d7354c4:7406a3463c3d + added 3 changesets with 1087 changes to 1087 files + new changesets 96ee1d7354c4:42e820400e84 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1" 200 Script output follows @@ -278,8 +299,8 @@ adding changesets adding manifests adding file changes - added 3 changesets with 1086 changes to 1086 files - new changesets 96ee1d7354c4:7406a3463c3d + added 3 changesets with 1087 changes to 1087 files + new changesets 96ee1d7354c4:42e820400e84 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1" 200 Script output follows @@ -309,10 +330,10 @@ #if stream-legacy $ hg clone --stream -U http://localhost:$HGPORT clone1 streaming all changes - 1088 files to transfer, 101 KB of data (no-zstd !) + 1089 files to transfer, 101 KB of data (no-zstd !) transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !) - 1088 files to transfer, 98.4 KB of data (zstd !) - transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) + 1089 files to transfer, 98.5 KB of data (zstd !) + transferred 98.5 KB in * seconds (*/sec) (glob) (zstd !) searching for changes no changes found $ cat server/errors.txt @@ -320,10 +341,10 @@ #if stream-bundle2 $ hg clone --stream -U http://localhost:$HGPORT clone1 streaming all changes - 1091 files to transfer, 101 KB of data (no-zstd !) + 1092 files to transfer, 101 KB of data (no-zstd !) transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !) - 1091 files to transfer, 98.5 KB of data (zstd !) - transferred 98.5 KB in * seconds (* */sec) (glob) (zstd !) + 1092 files to transfer, 98.6 KB of data (zstd !) + transferred 98.6 KB in * seconds (* */sec) (glob) (zstd !) $ ls -1 clone1/.hg/cache branch2-base @@ -348,12 +369,12 @@ #if no-zstd no-rust $ f --size --hex --bytes 256 body - body: size=118551 + body: size=118737 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| 0010: 80 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......| 0020: 06 09 04 0c 44 62 79 74 65 63 6f 75 6e 74 31 30 |....Dbytecount10| - 0030: 33 36 39 35 66 69 6c 65 63 6f 75 6e 74 31 30 39 |3695filecount109| - 0040: 31 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |1requirementsdot| + 0030: 33 38 33 34 66 69 6c 65 63 6f 75 6e 74 31 30 39 |3834filecount109| + 0040: 32 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |2requirementsdot| 0050: 65 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 |encode%2Cfncache| 0060: 25 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 |%2Cgeneraldelta%| 0070: 32 43 72 65 76 6c 6f 67 76 31 25 32 43 73 70 61 |2Crevlogv1%2Cspa| @@ -368,12 +389,12 @@ #endif #if zstd no-rust $ f --size --hex --bytes 256 body - body: size=115738 + body: size=115921 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| 0010: 9a 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......| 0020: 06 09 04 0c 5e 62 79 74 65 63 6f 75 6e 74 31 30 |....^bytecount10| - 0030: 30 38 35 36 66 69 6c 65 63 6f 75 6e 74 31 30 39 |0856filecount109| - 0040: 31 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |1requirementsdot| + 0030: 30 39 39 32 66 69 6c 65 63 6f 75 6e 74 31 30 39 |0992filecount109| + 0040: 32 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |2requirementsdot| 0050: 65 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 |encode%2Cfncache| 0060: 25 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 |%2Cgeneraldelta%| 0070: 32 43 72 65 76 6c 6f 67 2d 63 6f 6d 70 72 65 73 |2Crevlog-compres| @@ -388,12 +409,12 @@ #endif #if zstd rust no-dirstate-v2 $ f --size --hex --bytes 256 body - body: size=115759 + body: size=115942 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| 0010: af 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......| 0020: 06 09 04 0c 73 62 79 74 65 63 6f 75 6e 74 31 30 |....sbytecount10| - 0030: 30 38 35 36 66 69 6c 65 63 6f 75 6e 74 31 30 39 |0856filecount109| - 0040: 31 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |1requirementsdot| + 0030: 30 39 39 32 66 69 6c 65 63 6f 75 6e 74 31 30 39 |0992filecount109| + 0040: 32 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 |2requirementsdot| 0050: 65 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 |encode%2Cfncache| 0060: 25 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 |%2Cgeneraldelta%| 0070: 32 43 70 65 72 73 69 73 74 65 6e 74 2d 6e 6f 64 |2Cpersistent-nod| @@ -408,7 +429,7 @@ #endif #if zstd dirstate-v2 $ f --size --hex --bytes 256 body - body: size=109449 + body: size=109549 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......| 0010: c0 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......| 0020: 05 09 04 0c 85 62 79 74 65 63 6f 75 6e 74 39 35 |.....bytecount95| @@ -432,20 +453,20 @@ #if stream-legacy $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed streaming all changes - 1088 files to transfer, 101 KB of data (no-zstd !) + 1089 files to transfer, 101 KB of data (no-zstd !) transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !) - 1088 files to transfer, 98.4 KB of data (zstd !) - transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) + 1089 files to transfer, 98.5 KB of data (zstd !) + transferred 98.5 KB in * seconds (*/sec) (glob) (zstd !) searching for changes no changes found #endif #if stream-bundle2 $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed streaming all changes - 1091 files to transfer, 101 KB of data (no-zstd !) + 1092 files to transfer, 101 KB of data (no-zstd !) transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) - 1091 files to transfer, 98.5 KB of data (zstd !) - transferred 98.5 KB in * seconds (* */sec) (glob) (zstd !) + 1092 files to transfer, 98.6 KB of data (zstd !) + transferred 98.6 KB in * seconds (* */sec) (glob) (zstd !) #endif Clone with background file closing enabled @@ -457,12 +478,12 @@ sending branchmap command streaming all changes sending stream_out command - 1088 files to transfer, 101 KB of data (no-zstd !) - 1088 files to transfer, 98.4 KB of data (zstd !) + 1089 files to transfer, 101 KB of data (no-zstd !) + 1089 files to transfer, 98.5 KB of data (zstd !) starting 4 threads for background file closing updating the branch cache transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !) - transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) + transferred 98.5 KB in * seconds (*/sec) (glob) (zstd !) query 1; heads sending batch command searching for changes @@ -489,15 +510,15 @@ bundle2-input-bundle: with-transaction bundle2-input-part: "stream2" (params: 3 mandatory) supported applying stream bundle - 1091 files to transfer, 101 KB of data (no-zstd !) - 1091 files to transfer, 98.5 KB of data (zstd !) + 1092 files to transfer, 101 KB of data (no-zstd !) + 1092 files to transfer, 98.6 KB of data (zstd !) starting 4 threads for background file closing starting 4 threads for background file closing updating the branch cache transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) - bundle2-input-part: total payload size 118382 (no-zstd !) - transferred 98.5 KB in * seconds (* */sec) (glob) (zstd !) - bundle2-input-part: total payload size 115543 (zstd !) + bundle2-input-part: total payload size 118568 (no-zstd !) + transferred 98.6 KB in * seconds (* */sec) (glob) (zstd !) + bundle2-input-part: total payload size 115726 (zstd !) bundle2-input-part: "listkeys" (params: 1 mandatory) supported bundle2-input-bundle: 2 parts total checking for updated bookmarks @@ -529,20 +550,20 @@ #if stream-legacy $ hg clone --stream -U http://localhost:$HGPORT secret-allowed streaming all changes - 1088 files to transfer, 101 KB of data (no-zstd !) + 1089 files to transfer, 101 KB of data (no-zstd !) transferred 101 KB in * seconds (*/sec) (glob) (no-zstd !) - 1088 files to transfer, 98.4 KB of data (zstd !) - transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) + 1089 files to transfer, 98.5 KB of data (zstd !) + transferred 98.5 KB in * seconds (*/sec) (glob) (zstd !) searching for changes no changes found #endif #if stream-bundle2 $ hg clone --stream -U http://localhost:$HGPORT secret-allowed streaming all changes - 1091 files to transfer, 101 KB of data (no-zstd !) + 1092 files to transfer, 101 KB of data (no-zstd !) transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) - 1091 files to transfer, 98.5 KB of data (zstd !) - transferred 98.5 KB in * seconds (* */sec) (glob) (zstd !) + 1092 files to transfer, 98.6 KB of data (zstd !) + transferred 98.6 KB in * seconds (* */sec) (glob) (zstd !) #endif $ killdaemons.py @@ -681,33 +702,33 @@ #if stream-legacy $ hg clone --stream http://localhost:$HGPORT with-bookmarks streaming all changes - 1088 files to transfer, 101 KB of data (no-zstd !) + 1089 files to transfer, 101 KB of data (no-zstd !) transferred 101 KB in * seconds (*) (glob) (no-zstd !) - 1088 files to transfer, 98.4 KB of data (zstd !) - transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) + 1089 files to transfer, 98.5 KB of data (zstd !) + transferred 98.5 KB in * seconds (*/sec) (glob) (zstd !) searching for changes no changes found updating to branch default - 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1087 files updated, 0 files merged, 0 files removed, 0 files unresolved #endif #if stream-bundle2 $ hg clone --stream http://localhost:$HGPORT with-bookmarks streaming all changes - 1094 files to transfer, 101 KB of data (no-zstd !) - transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) - 1094 files to transfer, 98.7 KB of data (zstd !) - transferred 98.7 KB in * seconds (* */sec) (glob) (zstd !) + 1095 files to transfer, 102 KB of data (no-zstd !) + transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !) + 1095 files to transfer, 98.8 KB of data (zstd !) + transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !) updating to branch default - 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1087 files updated, 0 files merged, 0 files removed, 0 files unresolved #endif $ hg verify -R with-bookmarks checking changesets checking manifests crosschecking files in changesets and manifests checking files - checked 3 changesets with 1086 changes to 1086 files + checked 3 changesets with 1087 changes to 1087 files $ hg -R with-bookmarks bookmarks - some-bookmark 2:7406a3463c3d + some-bookmark 2:42e820400e84 Stream repository with phases ----------------------------- @@ -722,31 +743,31 @@ #if stream-legacy $ hg clone --stream http://localhost:$HGPORT phase-publish streaming all changes - 1088 files to transfer, 101 KB of data (no-zstd !) + 1089 files to transfer, 101 KB of data (no-zstd !) transferred 101 KB in * seconds (*) (glob) (no-zstd !) - 1088 files to transfer, 98.4 KB of data (zstd !) - transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) + 1089 files to transfer, 98.5 KB of data (zstd !) + transferred 98.5 KB in * seconds (*/sec) (glob) (zstd !) searching for changes no changes found updating to branch default - 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1087 files updated, 0 files merged, 0 files removed, 0 files unresolved #endif #if stream-bundle2 $ hg clone --stream http://localhost:$HGPORT phase-publish streaming all changes - 1094 files to transfer, 101 KB of data (no-zstd !) - transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) - 1094 files to transfer, 98.7 KB of data (zstd !) - transferred 98.7 KB in * seconds (* */sec) (glob) (zstd !) + 1095 files to transfer, 102 KB of data (no-zstd !) + transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !) + 1095 files to transfer, 98.8 KB of data (zstd !) + transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !) updating to branch default - 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1087 files updated, 0 files merged, 0 files removed, 0 files unresolved #endif $ hg verify -R phase-publish checking changesets checking manifests crosschecking files in changesets and manifests checking files - checked 3 changesets with 1086 changes to 1086 files + checked 3 changesets with 1087 changes to 1087 files $ hg -R phase-publish phase -r 'all()' 0: public 1: public @@ -769,14 +790,14 @@ $ hg clone --stream http://localhost:$HGPORT phase-no-publish streaming all changes - 1088 files to transfer, 101 KB of data (no-zstd !) + 1089 files to transfer, 101 KB of data (no-zstd !) transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) - 1088 files to transfer, 98.4 KB of data (zstd !) - transferred 98.4 KB in * seconds (*/sec) (glob) (zstd !) + 1089 files to transfer, 98.5 KB of data (zstd !) + transferred 98.5 KB in * seconds (*/sec) (glob) (zstd !) searching for changes no changes found updating to branch default - 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1087 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -R phase-no-publish phase -r 'all()' 0: public 1: public @@ -785,12 +806,12 @@ #if stream-bundle2 $ hg clone --stream http://localhost:$HGPORT phase-no-publish streaming all changes - 1095 files to transfer, 101 KB of data (no-zstd !) - transferred 101 KB in * seconds (* */sec) (glob) (no-zstd !) - 1095 files to transfer, 98.7 KB of data (zstd !) - transferred 98.7 KB in * seconds (* */sec) (glob) (zstd !) + 1096 files to transfer, 102 KB of data (no-zstd !) + transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !) + 1096 files to transfer, 98.8 KB of data (zstd !) + transferred 98.8 KB in * seconds (* */sec) (glob) (zstd !) updating to branch default - 1086 files updated, 0 files merged, 0 files removed, 0 files unresolved + 1087 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -R phase-no-publish phase -r 'all()' 0: draft 1: draft @@ -801,7 +822,7 @@ checking manifests crosschecking files in changesets and manifests checking files - checked 3 changesets with 1086 changes to 1086 files + checked 3 changesets with 1087 changes to 1087 files $ killdaemons.py @@ -840,22 +861,22 @@ $ hg clone -U --stream http://localhost:$HGPORT with-obsolescence streaming all changes - 1096 files to transfer, 102 KB of data (no-zstd !) + 1097 files to transfer, 102 KB of data (no-zstd !) transferred 102 KB in * seconds (* */sec) (glob) (no-zstd !) - 1096 files to transfer, 99.1 KB of data (zstd !) - transferred 99.1 KB in * seconds (* */sec) (glob) (zstd !) + 1097 files to transfer, 99.2 KB of data (zstd !) + transferred 99.2 KB in * seconds (* */sec) (glob) (zstd !) $ hg -R with-obsolescence log -T '{rev}: {phase}\n' 2: draft 1: draft 0: draft $ hg debugobsolete -R with-obsolescence - aa82d3f59e13f41649d8ba3324e1ac8849ba78e7 0 {7406a3463c3de22c4288b4306d199705369a285a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + e53e122156df12330d3a0b72351e3a84bfd14195 0 {42e820400e843bc479ad36068ff772a69c8affe9} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} $ hg verify -R with-obsolescence checking changesets checking manifests crosschecking files in changesets and manifests checking files - checked 4 changesets with 1087 changes to 1086 files + checked 4 changesets with 1088 changes to 1087 files $ hg clone -U --stream --config experimental.evolution=0 http://localhost:$HGPORT with-obsolescence-no-evolution streaming all changes
--- a/tests/test-commandserver.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-commandserver.t Sun Aug 22 16:32:06 2021 -0400 @@ -214,6 +214,7 @@ ... runcommand(server, [b'-R', b'foo', b'showconfig', b'ui', b'defaults']) *** runcommand showconfig bundle.mainreporoot=$TESTTMP/repo + chgserver.idletimeout=60 devel.all-warnings=true devel.default-date=0 0 extensions.fsmonitor= (fsmonitor !)
--- a/tests/test-completion.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-completion.t Sun Aug 22 16:32:06 2021 -0400 @@ -74,6 +74,7 @@ Show debug commands if there are no other candidates $ hg debugcomplete debug + debug-repair-issue6528 debugancestor debugantivirusrunning debugapplystreamclonebundle @@ -266,6 +267,7 @@ config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template continue: dry-run copy: forget, after, at-rev, force, include, exclude, dry-run + debug-repair-issue6528: to-report, from-report, paranoid, dry-run debugancestor: debugantivirusrunning: debugapplystreamclonebundle:
--- a/tests/test-devel-warnings.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-devel-warnings.t Sun Aug 22 16:32:06 2021 -0400 @@ -98,7 +98,7 @@ > EOF $ hg buggylocking devel-warn: "wlock" acquired after "lock" at: $TESTTMP/buggylocking.py:* (buggylocking) (glob) -#if no-chg +#if no-chg no-pyoxidizer $ hg buggylocking --traceback devel-warn: "wlock" acquired after "lock" at: */hg:* in <module> (glob) (?) @@ -115,7 +115,8 @@ */mercurial/dispatch.py:* in <lambda> (glob) */mercurial/util.py:* in check (glob) $TESTTMP/buggylocking.py:* in buggylocking (glob) -#else +#endif +#if chg no-pyoxidizer $ hg buggylocking --traceback devel-warn: "wlock" acquired after "lock" at: */hg:* in <module> (glob) (?) @@ -156,6 +157,24 @@ */mercurial/util.py:* in check (glob) $TESTTMP/buggylocking.py:* in buggylocking (glob) #endif +#if pyoxidizer + $ hg buggylocking --traceback + devel-warn: "wlock" acquired after "lock" at: + <string>:* (glob) + mercurial.dispatch:* in run (glob) + mercurial.dispatch:* in dispatch (glob) + mercurial.dispatch:* in _rundispatch (glob) + mercurial.dispatch:* in _runcatch (glob) + mercurial.dispatch:* in _callcatch (glob) + mercurial.scmutil:* in callcatch (glob) + mercurial.dispatch:* in _runcatchfunc (glob) + mercurial.dispatch:* in _dispatch (glob) + mercurial.dispatch:* in runcommand (glob) + mercurial.dispatch:* in _runcommand (glob) + mercurial.dispatch:* in <lambda> (glob) + mercurial.util:* in check (glob) + $TESTTMP/buggylocking.py:* in buggylocking (glob) +#endif $ hg properlocking $ hg nowaitlocking @@ -180,7 +199,7 @@ devel-warn: foorbar is deprecated, go shopping (compatibility will be dropped after Mercurial-42.1337, update your code.) at: $TESTTMP/buggylocking.py:* (oldanddeprecated) (glob) -#if no-chg +#if no-chg no-pyoxidizer $ hg oldanddeprecated --traceback devel-warn: foorbar is deprecated, go shopping (compatibility will be dropped after Mercurial-42.1337, update your code.) at: @@ -198,7 +217,8 @@ */mercurial/dispatch.py:* in <lambda> (glob) */mercurial/util.py:* in check (glob) $TESTTMP/buggylocking.py:* in oldanddeprecated (glob) -#else +#endif +#if chg no-pyoxidizer $ hg oldanddeprecated --traceback devel-warn: foorbar is deprecated, go shopping (compatibility will be dropped after Mercurial-42.1337, update your code.) at: @@ -240,8 +260,27 @@ */mercurial/util.py:* in check (glob) $TESTTMP/buggylocking.py:* in oldanddeprecated (glob) #endif +#if pyoxidizer + $ hg oldanddeprecated --traceback + devel-warn: foorbar is deprecated, go shopping + (compatibility will be dropped after Mercurial-42.1337, update your code.) at: + <string>:* (glob) + mercurial.dispatch:* in run (glob) + mercurial.dispatch:* in dispatch (glob) + mercurial.dispatch:* in _rundispatch (glob) + mercurial.dispatch:* in _runcatch (glob) + mercurial.dispatch:* in _callcatch (glob) + mercurial.scmutil:* in callcatch (glob) + mercurial.dispatch:* in _runcatchfunc (glob) + mercurial.dispatch:* in _dispatch (glob) + mercurial.dispatch:* in runcommand (glob) + mercurial.dispatch:* in _runcommand (glob) + mercurial.dispatch:* in <lambda> (glob) + mercurial.util:* in check (glob) + $TESTTMP/buggylocking.py:* in oldanddeprecated (glob) +#endif -#if no-chg +#if no-chg no-pyoxidizer $ hg blackbox -l 7 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> oldanddeprecated 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> devel-warn: foorbar is deprecated, go shopping @@ -266,7 +305,8 @@ $TESTTMP/buggylocking.py:* in oldanddeprecated (glob) 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> oldanddeprecated --traceback exited 0 after * seconds (glob) 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> blackbox -l 7 -#else +#endif +#if chg no-pyoxidizer $ hg blackbox -l 7 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> oldanddeprecated 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> devel-warn: foorbar is deprecated, go shopping @@ -315,6 +355,32 @@ 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> oldanddeprecated --traceback exited 0 after * seconds (glob) 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> blackbox -l 7 #endif +#if pyoxidizer + $ hg blackbox -l 7 + 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> oldanddeprecated + 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> devel-warn: foorbar is deprecated, go shopping + (compatibility will be dropped after Mercurial-42.1337, update your code.) at: $TESTTMP/buggylocking.py:* (oldanddeprecated) (glob) + 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> oldanddeprecated exited 0 after * seconds (glob) + 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> oldanddeprecated --traceback + 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> devel-warn: foorbar is deprecated, go shopping + (compatibility will be dropped after Mercurial-42.1337, update your code.) at: + <string>:* in <module> (glob) + mercurial.dispatch:* in run (glob) + mercurial.dispatch:* in dispatch (glob) + mercurial.dispatch:* in _rundispatch (glob) + mercurial.dispatch:* in _runcatch (glob) + mercurial.dispatch:* in _callcatch (glob) + mercurial.scmutil* in callcatch (glob) + mercurial.dispatch:* in _runcatchfunc (glob) + mercurial.dispatch:* in _dispatch (glob) + mercurial.dispatch:* in runcommand (glob) + mercurial.dispatch:* in _runcommand (glob) + mercurial.dispatch:* in <lambda> (glob) + mercurial.util:* in check (glob) + $TESTTMP/buggylocking.py:* in oldanddeprecated (glob) + 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> oldanddeprecated --traceback exited 0 after * seconds (glob) + 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> blackbox -l 7 +#endif Test programming error failure: @@ -389,8 +455,10 @@ > EOF $ hg --config "extensions.buggyconfig=${TESTTMP}/buggyconfig.py" buggyconfig - devel-warn: extension 'buggyconfig' overwrite config item 'ui.interactive' at: */mercurial/extensions.py:* (_loadextra) (glob) - devel-warn: extension 'buggyconfig' overwrite config item 'ui.quiet' at: */mercurial/extensions.py:* (_loadextra) (glob) + devel-warn: extension 'buggyconfig' overwrite config item 'ui.interactive' at: */mercurial/extensions.py:* (_loadextra) (glob) (no-pyoxidizer !) + devel-warn: extension 'buggyconfig' overwrite config item 'ui.quiet' at: */mercurial/extensions.py:* (_loadextra) (glob) (no-pyoxidizer !) + devel-warn: extension 'buggyconfig' overwrite config item 'ui.interactive' at: mercurial.extensions:* (_loadextra) (glob) (pyoxidizer !) + devel-warn: extension 'buggyconfig' overwrite config item 'ui.quiet' at: mercurial.extensions:* (_loadextra) (glob) (pyoxidizer !) devel-warn: specifying a mismatched default value for a registered config item: 'ui.quiet' 'True' at: $TESTTMP/buggyconfig.py:* (cmdbuggyconfig) (glob) devel-warn: specifying a mismatched default value for a registered config item: 'ui.interactive' 'False' at: $TESTTMP/buggyconfig.py:* (cmdbuggyconfig) (glob) devel-warn: specifying a mismatched default value for a registered config item: 'test.some' 'bar' at: $TESTTMP/buggyconfig.py:* (cmdbuggyconfig) (glob)
--- a/tests/test-extension.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-extension.t Sun Aug 22 16:32:06 2021 -0400 @@ -668,7 +668,8 @@ Even though the extension fails during uisetup, hg is still basically usable: $ hg --config extensions.baduisetup=$TESTTMP/baduisetup.py version Traceback (most recent call last): - File "*/mercurial/extensions.py", line *, in _runuisetup (glob) + File "*/mercurial/extensions.py", line *, in _runuisetup (glob) (no-pyoxidizer !) + File "mercurial.extensions", line *, in _runuisetup (glob) (pyoxidizer !) uisetup(ui) File "$TESTTMP/baduisetup.py", line 2, in uisetup 1 / 0 @@ -1377,6 +1378,18 @@ (use 'hg help extensions' for information on enabling extensions) +Help can find unimported extensions +----------------------------------- + +XXX-PYOXIDIZER since the frozen binary does not have source directory tree, +this make the checking for actual file under `hgext` a bit complicated. In +addition these tests do some strange dance to ensure some other module are the +first in `sys.path` (since the current install path is always in front +otherwise) that are fragile and that does not match reality in the field. So +for now we disable this test untill a deeper rework of that logic is done. + +#if no-pyoxidizer + Broken disabled extension and command: $ mkdir hgext @@ -1412,6 +1425,10 @@ (try 'hg help --keyword foo') [255] +#endif + +--- + $ cat > throw.py <<EOF > from mercurial import commands, registrar, util > cmdtable = {}
--- a/tests/test-fix.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-fix.t Sun Aug 22 16:32:06 2021 -0400 @@ -3,6 +3,7 @@ $ UPPERCASEPY="$TESTTMP/uppercase.py" $ cat > $UPPERCASEPY <<EOF + > import re > import sys > from mercurial.utils.procutil import setbinary > setbinary(sys.stdin) @@ -10,16 +11,18 @@ > stdin = getattr(sys.stdin, 'buffer', sys.stdin) > stdout = getattr(sys.stdout, 'buffer', sys.stdout) > lines = set() + > def format(text): + > return re.sub(b' +', b' ', text.upper()) > for arg in sys.argv[1:]: > if arg == 'all': - > stdout.write(stdin.read().upper()) + > stdout.write(format(stdin.read())) > sys.exit(0) > else: > first, last = arg.split('-') > lines.update(range(int(first), int(last) + 1)) > for i, line in enumerate(stdin.readlines()): > if i + 1 in lines: - > stdout.write(line.upper()) + > stdout.write(format(line)) > else: > stdout.write(line) > EOF @@ -354,6 +357,23 @@ $ cd .. +Test that the working copy is reported clean if formatting of the parent makes +it clean. + $ hg init wc-already-formatted + $ cd wc-already-formatted + + $ printf "hello world\n" > hello.whole + $ hg commit -Am initial + adding hello.whole + $ hg fix -w * + $ hg st + M hello.whole + $ hg fix -s . * + $ hg st + $ hg diff + + $ cd .. + Test the effect of fixing the working directory for each possible status, with and without providing explicit file arguments.
--- a/tests/test-flagprocessor.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-flagprocessor.t Sun Aug 22 16:32:06 2021 -0400 @@ -201,14 +201,17 @@ > EOF $ hg debugrebuilddirstate Traceback (most recent call last): - File "*/mercurial/extensions.py", line *, in _runextsetup (glob) + File "*/mercurial/extensions.py", line *, in _runextsetup (glob) (no-pyoxidizer !) + File "mercurial.extensions", line *, in _runextsetup (glob) (pyoxidizer !) extsetup(ui) File "*/tests/flagprocessorext.py", line *, in extsetup (glob) flagutil.addflagprocessor( (py38 !) validatehash, (no-py38 !) - File "*/mercurial/revlogutils/flagutil.py", line *, in addflagprocessor (glob) + File "*/mercurial/revlogutils/flagutil.py", line *, in addflagprocessor (glob) (no-pyoxidizer !) + File "mercurial.revlogutils.flagutil", line *, in addflagprocessor (glob) (pyoxidizer !) insertflagprocessor(flag, processor, flagprocessors) - File "*/mercurial/revlogutils/flagutil.py", line *, in insertflagprocessor (glob) + File "*/mercurial/revlogutils/flagutil.py", line *, in insertflagprocessor (glob) (no-pyoxidizer !) + File "mercurial.revlogutils.flagutil", line *, in insertflagprocessor (glob) (pyoxidizer !) raise error.Abort(msg) mercurial.error.Abort: cannot register multiple processors on flag '0x8'. (py3 !) Abort: cannot register multiple processors on flag '0x8'. (no-py3 !)
--- a/tests/test-help.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-help.t Sun Aug 22 16:32:06 2021 -0400 @@ -975,6 +975,9 @@ $ hg help debug debug commands (internal and unsupported): + debug-repair-issue6528 + find affected revisions and repair them. See issue6528 for more + details. debugancestor find the ancestor revision of two revisions in a given index debugantivirusrunning
--- a/tests/test-hgrc.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-hgrc.t Sun Aug 22 16:32:06 2021 -0400 @@ -303,5 +303,16 @@ $ hg paths --config extensions.zeroconf= config error at $TESTTMP/.hg/hgrc:3: [broken [255] + +XXX-PYOXIDIZER Pyoxidizer build have trouble with zeroconf for unclear reason, +we accept the bad output for now as this is the last thing in the way of +testing the pyoxidizer build. + +#if no-pyoxidizer $ HGRCSKIPREPO=1 hg paths --config extensions.zeroconf= foo = $TESTTMP/bar +#else + $ HGRCSKIPREPO=1 hg paths --config extensions.zeroconf= + abort: An invalid argument was supplied (known-bad-output !) + [255] +#endif
--- a/tests/test-install.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-install.t Sun Aug 22 16:32:06 2021 -0400 @@ -5,7 +5,8 @@ checking Python implementation (*) (glob) checking Python version (2.*) (glob) (no-py3 !) checking Python version (3.*) (glob) (py3 !) - checking Python lib (.*[Ll]ib.*)... (re) + checking Python lib (.*[Ll]ib.*)... (re) (no-pyoxidizer !) + checking Python lib (.*pyoxidizer.*)... (re) (pyoxidizer !) checking Python security support (*) (glob) TLS 1.2 not supported by Python install; network connections lack modern security (?) SNI not supported by Python install; may have connectivity issues with some servers (?) @@ -18,8 +19,10 @@ checking available compression engines (*zlib*) (glob) checking available compression engines for wire protocol (*zlib*) (glob) checking "re2" regexp engine \((available|missing)\) (re) - checking templates (*mercurial?templates)... (glob) - checking default template (*mercurial?templates?map-cmdline.default) (glob) + checking templates (*mercurial?templates)... (glob) (no-pyoxidizer !) + checking templates (*app?templates)... (glob) (pyoxidizer !) + checking default template (*mercurial?templates?map-cmdline.default) (glob) (no-pyoxidizer !) + checking default template (*app?templates?map-cmdline.default) (glob) (pyoxidizer !) checking commit editor... (*) (glob) checking username (test) no problems detected @@ -31,7 +34,8 @@ "compengines": ["bz2", "bz2truncated", "none", "zlib"*], (glob) "compenginesavail": ["bz2", "bz2truncated", "none", "zlib"*], (glob) "compenginesserver": [*"zlib"*], (glob) - "defaulttemplate": "*mercurial?templates?map-cmdline.default", (glob) + "defaulttemplate": "*mercurial?templates?map-cmdline.default", (glob) (no-pyoxidizer !) + "defaulttemplate": "*app?templates?map-cmdline.default", (glob) (pyoxidizer !) "defaulttemplateerror": null, "defaulttemplatenotfound": "default", "editor": "*", (glob) @@ -50,7 +54,8 @@ "pythonsecurity": [*], (glob) "pythonver": "*.*.*", (glob) "re2": (true|false), (re) - "templatedirs": "*mercurial?templates", (glob) + "templatedirs": "*mercurial?templates", (glob) (no-pyoxidizer !) + "templatedirs": "*app?templates", (glob) (pyoxidizer !) "username": "test", "usernameerror": null, "vinotfound": false @@ -64,7 +69,8 @@ checking Python implementation (*) (glob) checking Python version (2.*) (glob) (no-py3 !) checking Python version (3.*) (glob) (py3 !) - checking Python lib (.*[Ll]ib.*)... (re) + checking Python lib (.*[Ll]ib.*)... (re) (no-pyoxidizer !) + checking Python lib (.*pyoxidizer.*)... (re) (pyoxidizer !) checking Python security support (*) (glob) TLS 1.2 not supported by Python install; network connections lack modern security (?) SNI not supported by Python install; may have connectivity issues with some servers (?) @@ -77,8 +83,10 @@ checking available compression engines (*zlib*) (glob) checking available compression engines for wire protocol (*zlib*) (glob) checking "re2" regexp engine \((available|missing)\) (re) - checking templates (*mercurial?templates)... (glob) - checking default template (*mercurial?templates?map-cmdline.default) (glob) + checking templates (*mercurial?templates)... (glob) (no-pyoxidizer !) + checking templates (*app?templates)... (glob) (pyoxidizer !) + checking default template (*mercurial?templates?map-cmdline.default) (glob) (no-pyoxidizer !) + checking default template (*app?templates?map-cmdline.default) (glob) (pyoxidizer !) checking commit editor... (*) (glob) checking username... no username supplied @@ -111,7 +119,8 @@ checking Python implementation (*) (glob) checking Python version (2.*) (glob) (no-py3 !) checking Python version (3.*) (glob) (py3 !) - checking Python lib (.*[Ll]ib.*)... (re) + checking Python lib (.*[Ll]ib.*)... (re) (no-pyoxidizer !) + checking Python lib (.*pyoxidizer.*)... (re) (pyoxidizer !) checking Python security support (*) (glob) TLS 1.2 not supported by Python install; network connections lack modern security (?) SNI not supported by Python install; may have connectivity issues with some servers (?) @@ -124,8 +133,10 @@ checking available compression engines (*zlib*) (glob) checking available compression engines for wire protocol (*zlib*) (glob) checking "re2" regexp engine \((available|missing)\) (re) - checking templates (*mercurial?templates)... (glob) - checking default template (*mercurial?templates?map-cmdline.default) (glob) + checking templates (*mercurial?templates)... (glob) (no-pyoxidizer !) + checking templates (*app?templates)... (glob) (pyoxidizer !) + checking default template (*mercurial?templates?map-cmdline.default) (glob) (no-pyoxidizer !) + checking default template (*app?templates?map-cmdline.default) (glob) (pyoxidizer !) checking commit editor... ($TESTTMP/tools/testeditor.exe) checking username (test) no problems detected @@ -138,7 +149,8 @@ checking Python implementation (*) (glob) checking Python version (2.*) (glob) (no-py3 !) checking Python version (3.*) (glob) (py3 !) - checking Python lib (.*[Ll]ib.*)... (re) + checking Python lib (.*[Ll]ib.*)... (re) (no-pyoxidizer !) + checking Python lib (.*pyoxidizer.*)... (re) (pyoxidizer !) checking Python security support (*) (glob) TLS 1.2 not supported by Python install; network connections lack modern security (?) SNI not supported by Python install; may have connectivity issues with some servers (?) @@ -151,8 +163,10 @@ checking available compression engines (*zlib*) (glob) checking available compression engines for wire protocol (*zlib*) (glob) checking "re2" regexp engine \((available|missing)\) (re) - checking templates (*mercurial?templates)... (glob) - checking default template (*mercurial?templates?map-cmdline.default) (glob) + checking templates (*mercurial?templates)... (glob) (no-pyoxidizer !) + checking templates (*app?templates)... (glob) (pyoxidizer !) + checking default template (*mercurial?templates?map-cmdline.default) (glob) (no-pyoxidizer !) + checking default template (*app?templates?map-cmdline.default) (glob) (pyoxidizer !) checking commit editor... (c:\foo\bar\baz.exe) (windows !) Can't find editor 'c:\foo\bar\baz.exe' in PATH (windows !) checking commit editor... (c:foobarbaz.exe) (no-windows !) @@ -184,7 +198,7 @@ $ cd $TESTTMP $ unset PYTHONPATH -#if py3 ensurepip network-io +#if py3 ensurepip network-io no-pyoxidizer $ "$PYTHON" -m venv installenv >> pip.log Hack: Debian does something a bit different in ensurepip.bootstrap. This makes @@ -224,7 +238,7 @@ no problems detected #endif -#if virtualenv no-py3 network-io +#if virtualenv no-py3 network-io no-pyoxidizer Note: --no-site-packages is the default for all versions enabled by hghave
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-issue6528.t Sun Aug 22 16:32:06 2021 -0400 @@ -0,0 +1,627 @@ +=============================================================== +Test non-regression on the corruption associated with issue6528 +=============================================================== + +Setup +===== + + $ hg init base-repo + $ cd base-repo + + $ cat <<EOF > a.txt + > 1 + > 2 + > 3 + > 4 + > 5 + > 6 + > EOF + + $ hg add a.txt + $ hg commit -m 'c_base_c - create a.txt' + +Modify a.txt + + $ sed -e 's/1/foo/' a.txt > a.tmp; mv a.tmp a.txt + $ hg commit -m 'c_modify_c - modify a.txt' + +Modify and rename a.txt to b.txt + + $ hg up -r "desc('c_base_c')" + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ sed -e 's/6/bar/' a.txt > a.tmp; mv a.tmp a.txt + $ hg mv a.txt b.txt + $ hg commit -m 'c_rename_c - rename and modify a.txt to b.txt' + created new head + +Merge each branch + + $ hg merge -r "desc('c_modify_c')" + merging b.txt and a.txt to b.txt + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg commit -m 'c_merge_c: commit merge' + + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 000000000000 05b806ebe5ea + +Check commit Graph + + $ hg log -G + @ changeset: 3:a1cc2bdca0aa + |\ tag: tip + | | parent: 2:615c6ccefd15 + | | parent: 1:373d507f4667 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: c_merge_c: commit merge + | | + | o changeset: 2:615c6ccefd15 + | | parent: 0:f5a5a568022f + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: c_rename_c - rename and modify a.txt to b.txt + | | + o | changeset: 1:373d507f4667 + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: c_modify_c - modify a.txt + | + o changeset: 0:f5a5a568022f + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: c_base_c - create a.txt + + + $ hg cat -r . b.txt + foo + 2 + 3 + 4 + 5 + bar + $ cat b.txt + foo + 2 + 3 + 4 + 5 + bar + $ cd .. + + +Check the lack of corruption +============================ + + $ hg clone --pull base-repo cloned + requesting all changes + adding changesets + adding manifests + adding file changes + added 4 changesets with 4 changes to 2 files + new changesets f5a5a568022f:a1cc2bdca0aa + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd cloned + $ hg up -r "desc('c_merge_c')" + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + + +Status is buggy, even with debugrebuilddirstate + + $ hg cat -r . b.txt + foo + 2 + 3 + 4 + 5 + bar + $ cat b.txt + foo + 2 + 3 + 4 + 5 + bar + $ hg status + $ hg debugrebuilddirstate + $ hg status + +the history was altered + +in theory p1/p2 order does not matter but in practice p1 == nullid is used as a +marker that some metadata are present and should be fetched. + + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 000000000000 05b806ebe5ea + +Check commit Graph + + $ hg log -G + @ changeset: 3:a1cc2bdca0aa + |\ tag: tip + | | parent: 2:615c6ccefd15 + | | parent: 1:373d507f4667 + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: c_merge_c: commit merge + | | + | o changeset: 2:615c6ccefd15 + | | parent: 0:f5a5a568022f + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: c_rename_c - rename and modify a.txt to b.txt + | | + o | changeset: 1:373d507f4667 + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: c_modify_c - modify a.txt + | + o changeset: 0:f5a5a568022f + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: c_base_c - create a.txt + + +Test the command that fixes the issue +===================================== + +Restore a broken repository with multiple broken revisions and a filename that +would get encoded to test the `report` options. +It's a tarball because unbundle might magically fix the issue later. + + $ cd .. + $ mkdir repo-to-fix + $ cd repo-to-fix +#if windows +tar interprets `:` in paths (like `C:`) as being remote, force local on Windows +only since some versions of tar don't have this flag. + + $ tar --force-local -xf $TESTDIR/bundles/issue6528.tar +#else + $ tar xf $TESTDIR/bundles/issue6528.tar +#endif + +Check that the issue is present + $ hg st + M D.txt + M b.txt + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 05b806ebe5ea 000000000000 + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 216a5fe8b8ed 000000000000 + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 2a8d3833f2fb 000000000000 + +Dry-run the fix + $ hg debug-repair-issue6528 --dry-run + found affected revision 1 for filelog 'data/D.txt.i' + found affected revision 1 for filelog 'data/b.txt.i' + found affected revision 3 for filelog 'data/b.txt.i' + $ hg st + M D.txt + M b.txt + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 05b806ebe5ea 000000000000 + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 216a5fe8b8ed 000000000000 + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 2a8d3833f2fb 000000000000 + +Test the --paranoid option + $ hg debug-repair-issue6528 --dry-run --paranoid + found affected revision 1 for filelog 'data/D.txt.i' + found affected revision 1 for filelog 'data/b.txt.i' + found affected revision 3 for filelog 'data/b.txt.i' + $ hg st + M D.txt + M b.txt + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 05b806ebe5ea 000000000000 + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 216a5fe8b8ed 000000000000 + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 2a8d3833f2fb 000000000000 + +Run the fix + $ hg debug-repair-issue6528 + found affected revision 1 for filelog 'data/D.txt.i' + repaired revision 1 of 'filelog data/D.txt.i' + found affected revision 1 for filelog 'data/b.txt.i' + found affected revision 3 for filelog 'data/b.txt.i' + repaired revision 1 of 'filelog data/b.txt.i' + repaired revision 3 of 'filelog data/b.txt.i' + +Check that the fix worked and that running it twice does nothing + $ hg st + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 000000000000 05b806ebe5ea + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 000000000000 2a8d3833f2fb + $ hg debug-repair-issue6528 + no affected revisions were found + $ hg st + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 000000000000 05b806ebe5ea + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 000000000000 2a8d3833f2fb + +Try the using the report options +-------------------------------- + + $ cd .. + $ mkdir repo-to-fix-report + $ cd repo-to-fix +#if windows +tar interprets `:` in paths (like `C:`) as being remote, force local on Windows +only since some versions of tar don't have this flag. + + $ tar --force-local -xf $TESTDIR/bundles/issue6528.tar +#else + $ tar xf $TESTDIR/bundles/issue6528.tar +#endif + + $ hg debug-repair-issue6528 --to-report $TESTTMP/report.txt + found affected revision 1 for filelog 'data/D.txt.i' + found affected revision 1 for filelog 'data/b.txt.i' + found affected revision 3 for filelog 'data/b.txt.i' + $ cat $TESTTMP/report.txt + 2a80419dfc31d7dfb308ac40f3f138282de7d73b D.txt + a58b36ad6b6545195952793099613c2116f3563b,ea4f2f2463cca5b29ddf3461012b8ce5c6dac175 b.txt + + $ hg debug-repair-issue6528 --from-report $TESTTMP/report.txt --dry-run + loading report file '$TESTTMP/report.txt' + found affected revision 1 for filelog 'D.txt' + found affected revision 1 for filelog 'b.txt' + found affected revision 3 for filelog 'b.txt' + $ hg st + M D.txt + M b.txt + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 05b806ebe5ea 000000000000 + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 216a5fe8b8ed 000000000000 + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 2a8d3833f2fb 000000000000 + + $ hg debug-repair-issue6528 --from-report $TESTTMP/report.txt + loading report file '$TESTTMP/report.txt' + found affected revision 1 for filelog 'D.txt' + repaired revision 1 of 'filelog data/D.txt.i' + found affected revision 1 for filelog 'b.txt' + found affected revision 3 for filelog 'b.txt' + repaired revision 1 of 'filelog data/b.txt.i' + repaired revision 3 of 'filelog data/b.txt.i' + $ hg st + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 000000000000 05b806ebe5ea + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 000000000000 2a8d3833f2fb + +Check that the revision is not "fixed" again + + $ hg debug-repair-issue6528 --from-report $TESTTMP/report.txt + loading report file '$TESTTMP/report.txt' + revision 2a80419dfc31d7dfb308ac40f3f138282de7d73b of file 'D.txt' is not affected + no affected revisions were found for 'D.txt' + revision a58b36ad6b6545195952793099613c2116f3563b of file 'b.txt' is not affected + revision ea4f2f2463cca5b29ddf3461012b8ce5c6dac175 of file 'b.txt' is not affected + no affected revisions were found for 'b.txt' + $ hg st + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 000000000000 05b806ebe5ea + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 000000000000 2a8d3833f2fb + +Try it with a non-inline revlog +------------------------------- + + $ cd .. + $ mkdir $TESTTMP/ext + $ cat << EOF > $TESTTMP/ext/small_inline.py + > from mercurial import revlog + > revlog._maxinline = 8 + > EOF + + $ cat << EOF >> $HGRCPATH + > [extensions] + > small_inline=$TESTTMP/ext/small_inline.py + > EOF + + $ mkdir repo-to-fix-not-inline + $ cd repo-to-fix-not-inline +#if windows +tar interprets `:` in paths (like `C:`) as being remote, force local on Windows +only since some versions of tar don't have this flag. + + $ tar --force-local -xf $TESTDIR/bundles/issue6528.tar +#else + $ tar xf $TESTDIR/bundles/issue6528.tar +#endif + $ echo b >> b.txt + $ hg commit -qm "inline -> separate" + $ find .hg -name *b.txt.d + .hg/store/data/b.txt.d + +Status is correct, but the problem is still there, in the earlier revision + $ hg st + $ hg up 3 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg st + M b.txt + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 05b806ebe5ea 000000000000 + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 216a5fe8b8ed 000000000000 + 4 8 db234885e2fe ea4f2f2463cc 000000000000 + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 2a8d3833f2fb 000000000000 + 2 8 65aecc89bb5d 2a80419dfc31 000000000000 + +Run the fix on the non-inline revlog + $ hg debug-repair-issue6528 + found affected revision 1 for filelog 'data/D.txt.i' + repaired revision 1 of 'filelog data/D.txt.i' + found affected revision 1 for filelog 'data/b.txt.i' + found affected revision 3 for filelog 'data/b.txt.i' + repaired revision 1 of 'filelog data/b.txt.i' + repaired revision 3 of 'filelog data/b.txt.i' + +Check that it worked + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 000000000000 05b806ebe5ea + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed + 4 8 db234885e2fe ea4f2f2463cc 000000000000 + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 000000000000 2a8d3833f2fb + 2 8 65aecc89bb5d 2a80419dfc31 000000000000 + $ hg debug-repair-issue6528 + no affected revisions were found + $ hg st + + $ cd .. + +Applying a bad bundle should fix it on the fly +---------------------------------------------- + +from a v1 bundle +~~~~~~~~~~~~~~~~ + + $ hg debugbundle --spec "$TESTDIR"/bundles/issue6528.hg-v1 + bzip2-v1 + + $ hg init unbundle-v1 + $ cd unbundle-v1 + + $ hg unbundle "$TESTDIR"/bundles/issue6528.hg-v1 + adding changesets + adding manifests + adding file changes + added 8 changesets with 12 changes to 4 files + new changesets f5a5a568022f:3beabb508514 (8 drafts) + (run 'hg update' to get a working copy) + +Check that revision were fixed on the fly + + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 000000000000 05b806ebe5ea + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed + + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 000000000000 2a8d3833f2fb + +That we don't see the symptoms of the bug + + $ hg up -- -1 + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg status + +And that the repair command does not find anything to fix + + $ hg debug-repair-issue6528 + no affected revisions were found + + $ cd .. + +from a v2 bundle +~~~~~~~~~~~~~~~~ + + $ hg debugbundle --spec "$TESTDIR"/bundles/issue6528.hg-v2 + bzip2-v2 + + $ hg init unbundle-v2 + $ cd unbundle-v2 + + $ hg unbundle "$TESTDIR"/bundles/issue6528.hg-v2 + adding changesets + adding manifests + adding file changes + added 8 changesets with 12 changes to 4 files + new changesets f5a5a568022f:3beabb508514 (8 drafts) + (run 'hg update' to get a working copy) + +Check that revision were fixed on the fly + + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 000000000000 05b806ebe5ea + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 000000000000 216a5fe8b8ed + + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 000000000000 2a8d3833f2fb + +That we don't see the symptoms of the bug + + $ hg up -- -1 + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg status + +And that the repair command does not find anything to fix + + $ hg debug-repair-issue6528 + no affected revisions were found + + $ cd .. + +A config option can disable the fixing of the bad bundle on the fly +------------------------------------------------------------------- + + + +from a v1 bundle +~~~~~~~~~~~~~~~~ + + $ hg debugbundle --spec "$TESTDIR"/bundles/issue6528.hg-v1 + bzip2-v1 + + $ hg init unbundle-v1-no-fix + $ cd unbundle-v1-no-fix + + $ hg unbundle "$TESTDIR"/bundles/issue6528.hg-v1 --config storage.revlog.issue6528.fix-incoming=no + adding changesets + adding manifests + adding file changes + added 8 changesets with 12 changes to 4 files + new changesets f5a5a568022f:3beabb508514 (8 drafts) + (run 'hg update' to get a working copy) + +Check that revision were not fixed on the fly + + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 05b806ebe5ea 000000000000 + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 216a5fe8b8ed 000000000000 + + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 2a8d3833f2fb 000000000000 + +That we do see the symptoms of the bug + + $ hg up -- -1 + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg status + M D.txt (?) + M b.txt (?) + +And that the repair command find issue to fix. + + $ hg debug-repair-issue6528 --dry-run + found affected revision 1 for filelog 'data/D.txt.i' + found affected revision 1 for filelog 'data/b.txt.i' + found affected revision 3 for filelog 'data/b.txt.i' + + $ cd .. + +from a v2 bundle +~~~~~~~~~~~~~~~~ + + $ hg debugbundle --spec "$TESTDIR"/bundles/issue6528.hg-v2 + bzip2-v2 + + $ hg init unbundle-v2-no-fix + $ cd unbundle-v2-no-fix + + $ hg unbundle "$TESTDIR"/bundles/issue6528.hg-v2 --config storage.revlog.issue6528.fix-incoming=no + adding changesets + adding manifests + adding file changes + added 8 changesets with 12 changes to 4 files + new changesets f5a5a568022f:3beabb508514 (8 drafts) + (run 'hg update' to get a working copy) + +Check that revision were not fixed on the fly + + $ hg debugrevlogindex b.txt + rev linkrev nodeid p1 p2 + 0 2 05b806ebe5ea 000000000000 000000000000 + 1 3 a58b36ad6b65 05b806ebe5ea 000000000000 + 2 6 216a5fe8b8ed 000000000000 000000000000 + 3 7 ea4f2f2463cc 216a5fe8b8ed 000000000000 + + $ hg debugrevlogindex D.txt + rev linkrev nodeid p1 p2 + 0 6 2a8d3833f2fb 000000000000 000000000000 + 1 7 2a80419dfc31 2a8d3833f2fb 000000000000 + +That we do see the symptoms of the bug + + $ hg up -- -1 + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg status + M D.txt (?) + M b.txt (?) + +And that the repair command find issue to fix. + + $ hg debug-repair-issue6528 --dry-run + found affected revision 1 for filelog 'data/D.txt.i' + found affected revision 1 for filelog 'data/b.txt.i' + found affected revision 3 for filelog 'data/b.txt.i' + + $ cd ..
--- a/tests/test-narrow-shallow-merges.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-narrow-shallow-merges.t Sun Aug 22 16:32:06 2021 -0400 @@ -179,7 +179,7 @@ $ hg log -T '{if(ellipsis,"...")}{node|short} {p1node|short} {p2node|short} {desc}\n' | sort - ...2a20009de83e 3ac1f5779de3 000000000000 outside 10 + ...2a20009de83e 000000000000 3ac1f5779de3 outside 10 ...3ac1f5779de3 bb96a08b062a 465567bdfb2d merge a/b/c/d 9 ...8d874d57adea 7ef88b4dd4fa 000000000000 outside 12 ...b844052e7b3b 000000000000 000000000000 outside 2c
--- a/tests/test-nointerrupt.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-nointerrupt.t Sun Aug 22 16:32:06 2021 -0400 @@ -5,85 +5,90 @@ buggy. This need to be resolved sooner than later. Dummy extension simulating unsafe long running command - $ cat > sleepext.py <<EOF - > import itertools + $ SYNC_FILE="$TESTTMP/sync-file" + $ export SYNC_FILE + $ DONE_FILE="$TESTTMP/done-file" + $ export DONE_FILE + $ + $ cat > wait_ext.py <<EOF + > import os > import time > > from mercurial.i18n import _ > from mercurial import registrar + > from mercurial import testing > > cmdtable = {} > command = registrar.command(cmdtable) > - > @command(b'sleep', [], _(b'TIME'), norepo=True) - > def sleep(ui, sleeptime=b"1", **opts): + > @command(b'wait-signal', [], _(b'SYNC_FILE DONE_FILE'), norepo=True) + > def sleep(ui, sync_file=b"$SYNC_FILE", done_file=b"$DONE_FILE", **opts): + > start = time.time() > with ui.uninterruptible(): - > for _i in itertools.repeat(None, int(sleeptime)): - > time.sleep(1) + > testing.write_file(sync_file, b'%d' % os.getpid()) + > testing.wait_file(done_file) + > # make sure we get rescheduled and the signal get a chance to be handled + > time.sleep(0.1) > ui.warn(b"end of unsafe operation\n") - > ui.warn(b"%s second(s) passed\n" % sleeptime) + > ui.warn(b"%d second(s) passed\n" % int(time.time() - start)) > EOF + $ cat > send-signal.sh << EOF + > #!/bin/sh + > SIG=\$1 + > if [ -z "\$SIG" ]; then + > echo "send-signal.sh requires one argument" >&2 + > exit 1 + > fi + > "$RUNTESTDIR/testlib/wait-on-file" 10 "$SYNC_FILE" || exit 2 + > kill -s \$SIG \`cat "$SYNC_FILE"\` + > sleep 1 + > touch "$DONE_FILE" + > EOF + +#if no-windows + $ chmod +x send-signal.sh +#endif + Kludge to emulate timeout(1) which is not generally available. - $ cat > timeout.py <<EOF - > from __future__ import print_function - > import argparse - > import signal - > import subprocess - > import sys - > import time - > - > ap = argparse.ArgumentParser() - > ap.add_argument('-s', nargs=1, default='SIGTERM') - > ap.add_argument('duration', nargs=1, type=int) - > ap.add_argument('argv', nargs='*') - > opts = ap.parse_args() - > try: - > sig = int(opts.s[0]) - > except ValueError: - > sname = opts.s[0] - > if not sname.startswith('SIG'): - > sname = 'SIG' + sname - > sig = getattr(signal, sname) - > proc = subprocess.Popen(opts.argv) - > time.sleep(opts.duration[0]) - > proc.poll() - > if proc.returncode is None: - > proc.send_signal(sig) - > proc.wait() - > sys.exit(124) - > EOF Set up repository $ hg init repo $ cd repo $ cat >> $HGRCPATH << EOF > [extensions] - > sleepext = ../sleepext.py + > wait_ext = $TESTTMP/wait_ext.py > EOF + Test ctrl-c - $ "$PYTHON" $TESTTMP/timeout.py -s INT 1 hg sleep 2 + $ rm -f $SYNC_FILE $DONE_FILE + $ sh -c "../send-signal.sh INT" & + $ hg wait-signal interrupted! - [124] + [255] $ cat >> $HGRCPATH << EOF > [experimental] > nointerrupt = yes > EOF - $ "$PYTHON" $TESTTMP/timeout.py -s INT 1 hg sleep 2 + $ rm -f $SYNC_FILE $DONE_FILE + $ sh -c "../send-signal.sh INT" & + $ hg wait-signal interrupted! - [124] + [255] $ cat >> $HGRCPATH << EOF > [experimental] > nointerrupt-interactiveonly = False > EOF - $ "$PYTHON" $TESTTMP/timeout.py -s INT 1 hg sleep 2 + $ rm -f $SYNC_FILE $DONE_FILE + $ sh -c "../send-signal.sh INT" & + $ hg wait-signal shutting down cleanly press ^C again to terminate immediately (dangerous) end of unsafe operation interrupted! - [124] + [255]
--- a/tests/test-pager.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-pager.t Sun Aug 22 16:32:06 2021 -0400 @@ -219,27 +219,27 @@ #endif A complicated pager command gets worse behavior. Bonus points if you can -improve this. Windows apparently does this better? +improve this. Windows apparently does this better, but only sometimes? #if windows $ hg log --limit 3 \ > --config pager.pager='this-command-better-never-exist --seriously' \ > 2>/dev/null || true - \x1b[0;33mchangeset: 10:46106edeeb38\x1b[0m (esc) - tag: tip - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: modify a 10 - - \x1b[0;33mchangeset: 9:6dd8ea7dd621\x1b[0m (esc) - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: modify a 9 - - \x1b[0;33mchangeset: 8:cff05a6312fe\x1b[0m (esc) - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: modify a 8 - + \x1b[0;33mchangeset: 10:46106edeeb38\x1b[0m (esc) (?) + tag: tip (?) + user: test (?) + date: Thu Jan 01 00:00:00 1970 +0000 (?) + summary: modify a 10 (?) + (?) + \x1b[0;33mchangeset: 9:6dd8ea7dd621\x1b[0m (esc) (?) + user: test (?) + date: Thu Jan 01 00:00:00 1970 +0000 (?) + summary: modify a 9 (?) + (?) + \x1b[0;33mchangeset: 8:cff05a6312fe\x1b[0m (esc) (?) + user: test (?) + date: Thu Jan 01 00:00:00 1970 +0000 (?) + summary: modify a 8 (?) + (?) #else $ hg log --limit 3 \ > --config pager.pager='this-command-better-never-exist --seriously' \
--- a/tests/test-paths.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-paths.t Sun Aug 22 16:32:06 2021 -0400 @@ -140,11 +140,22 @@ zeroconf wraps ui.configitems(), which shouldn't crash at least: +XXX-PYOXIDIZER Pyoxidizer build have trouble with zeroconf for unclear reason, +we accept the bad output for now as this is the last thing in the way of +testing the pyoxidizer build. + +#if no-pyoxidizer $ hg paths --config extensions.zeroconf= dupe = $TESTTMP/b#tip dupe:pushurl = https://example.com/dupe expand = $TESTTMP/a/$SOMETHING/bar insecure = http://foo:***@example.com/ +#else + $ hg paths --config extensions.zeroconf= + abort: An invalid argument was supplied (known-bad-output !) + [255] +#endif + $ cd ..
--- a/tests/test-persistent-nodemap.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-persistent-nodemap.t Sun Aug 22 16:32:06 2021 -0400 @@ -428,6 +428,46 @@ data-length: 121088 data-unused: 0 data-unused: 0.000% + +Sub-case: fallback for corrupted data file +------------------------------------------ + +Sabotaging the data file so that nodemap resolutions fail, triggering fallback to +(non-persistent) C implementation. + + + $ UUID=`hg debugnodemap --metadata| grep 'uid:' | \ + > sed 's/uid: //'` + $ FILE=.hg/store/00changelog-"${UUID}".nd + $ python -c "fobj = open('$FILE', 'r+b'); fobj.write(b'\xff' * 121088); fobj.close()" + +The nodemap data file is still considered in sync with the docket. This +would fail without the fallback to the (non-persistent) C implementation: + + $ hg log -r b355ef8adce0949b8bdf6afc72ca853740d65944 -T '{rev}\n' --traceback + 5002 + +The nodemap data file hasn't been fixed, more tests can be inserted: + + $ hg debugnodemap --dump-disk | f --bytes=256 --hexdump --size + size=121088 + 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 0030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 0060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 00a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + 00f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + $ mv ../tmp-data-file $FILE $ mv ../tmp-docket .hg/store/00changelog.n
--- a/tests/test-phases.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-phases.t Sun Aug 22 16:32:06 2021 -0400 @@ -898,11 +898,11 @@ A X $ hg --config "phases.new-commit=internal" commit -m "my test internal commit" 2>&1 | grep ProgrammingError ** ProgrammingError: this repository does not support the internal phase - raise error.ProgrammingError(msg) + raise error.ProgrammingError(msg) (no-pyoxidizer !) *ProgrammingError: this repository does not support the internal phase (glob) $ hg --config "phases.new-commit=archived" commit -m "my test archived commit" 2>&1 | grep ProgrammingError ** ProgrammingError: this repository does not support the archived phase - raise error.ProgrammingError(msg) + raise error.ProgrammingError(msg) (no-pyoxidizer !) *ProgrammingError: this repository does not support the archived phase (glob) $ cd ..
--- a/tests/test-rebase-inmemory.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-rebase-inmemory.t Sun Aug 22 16:32:06 2021 -0400 @@ -963,6 +963,46 @@ o 0: d20a80d4def3 'base' +Test that update_hash_refs works. + $ hg co 0 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo update_hash_refs > update_hash_refs + $ hg add update_hash_refs + $ hg ci -m 'this will change hash' + created new head + $ echo changed >> update_hash_refs + $ hg ci -m "this starts as the child of `hg log -r . -T'{node|short}'` but not 506e2454484b. Also, ffffffffffffffff" + $ hg tglog + @ 5: a8b42cbbde83 'this starts as the child of 98789aa60148 but not 506e2454484b. Also, ffffffffffffffff' + | + o 4: 98789aa60148 'this will change hash' + | + | o 3: 506e2454484b 'merge' + | |\ + +---o 2: 531f80391e4a 'c' + | | + | o 1: 6f252845ea45 'a' + |/ + o 0: d20a80d4def3 'base' + + $ hg rebase -r '.^::' -d 3 + rebasing 4:98789aa60148 "this will change hash" + rebasing 5:a8b42cbbde83 tip "this starts as the child of 98789aa60148 but not 506e2454484b. Also, ffffffffffffffff" + saved backup bundle to $TESTTMP/keep_merge/.hg/strip-backup/98789aa60148-da3f4c2c-rebase.hg + $ hg tglog + @ 5: 0fd2912e6cc1 'this starts as the child of c16c25696fe7 but not 506e2454484b. Also, ffffffffffffffff' + | + o 4: c16c25696fe7 'this will change hash' + | + o 3: 506e2454484b 'merge' + |\ + | o 2: 531f80391e4a 'c' + | | + o | 1: 6f252845ea45 'a' + |/ + o 0: d20a80d4def3 'base' + + $ cd .. Test (virtual) working directory without changes, created by merge conflict
--- a/tests/test-serve.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-serve.t Sun Aug 22 16:32:06 2021 -0400 @@ -44,13 +44,20 @@ listening at http://localhost/ (bound to *$LOCALIP*:HGPORT2) (glob) (?) % errors -With -v and -p daytime (should fail because low port) +With -v and -p daytime -#if no-root no-windows +# On some system this will fails because port < 1024 are not bindable by normal +# users. +# +# On some others the kernel is configured to allow any user to bind them and +# this will work fine + +#if no-windows $ KILLQUIETLY=Y $ hgserve -p daytime - abort: cannot start server at 'localhost:13': Permission denied - abort: child process failed to start + abort: cannot start server at 'localhost:13': Permission denied (?) + abort: child process failed to start (?) + listening at http://localhost/ (bound to $LOCALIP:13) (?) % errors $ KILLQUIETLY=N #endif
--- a/tests/test-subrepo-git.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-subrepo-git.t Sun Aug 22 16:32:06 2021 -0400 @@ -1,5 +1,20 @@ #require git +# XXX-CHG When running with python2 + chg this test tend to get stuck and end up +# as a time-out error. My effort to reproduce this outside of the CI failed. The +# test itself seems to pass fine, but never "complete". Debugging it is slow and +# tedious. This as a bad impact on the development process as most CI run end up +# wasting abotu 1h until that one fails. +# +# Pierre-Yves David, Augie Fackler and Raphaël Gomès all agreed to disable this +# case in that specific case until we figure this out (or we drop python2 o:-) ) + +#if no-py3 chg + $ echo 'skipped: this test get stuck on the CI with python2 + chg. investigation needed' + $ exit 80 +#endif + + make git commits repeatable $ cat >> $HGRCPATH <<EOF
--- a/tests/test-transaction-safety.t Tue Jul 20 17:20:19 2021 +0200 +++ b/tests/test-transaction-safety.t Sun Aug 22 16:32:06 2021 -0400 @@ -41,7 +41,23 @@ setup ----- -synchronisation+output script: +synchronisation+output script using the following schedule: + +[A1] "external" is started +[A2] "external" waits on EXT_UNLOCK +[A2] "external" + creates EXT_WAITING → unlocks [C1] +[B1] "hg commit/pull" is started +[B2] "hg commit/pull" is ready to be committed +[B3] "hg commit/pull" spawn "internal" using a pretxnclose hook (need [C4]) +[C1] "internal" waits on EXT_WAITING (need [A2]) +[C2] "internal" creates EXT_UNLOCK → unlocks [A2] +[C3] "internal" show the tipmost revision (inside of the transaction) +[C4] "internal" waits on EXT_DONE (need [A4]) +[A3] "external" show the tipmost revision (outside of the transaction) +[A4] "external" creates EXT_DONE → unlocks [C4] +[C5] "internal" end of execution -> unlock [B3] +[B4] "hg commit/pull" transaction is committed on disk + $ mkdir sync $ mkdir output @@ -60,8 +76,10 @@ > EOF $ cat << EOF > script/internal.sh > #!/bin/sh + > "$RUNTESTDIR/testlib/wait-on-file" 5 "$HG_TEST_FILE_EXT_WAITING" + > touch "$HG_TEST_FILE_EXT_UNLOCK" > hg log --rev 'tip' -T 'internal: {rev} {desc}\n' > "$TESTTMP/output/internal.out" - > "$RUNTESTDIR/testlib/wait-on-file" 5 "$HG_TEST_FILE_EXT_DONE" "$HG_TEST_FILE_EXT_UNLOCK" + > "$RUNTESTDIR/testlib/wait-on-file" 5 "$HG_TEST_FILE_EXT_DONE" > EOF