Show More
@@ -0,0 +1,15 b'' | |||
|
1 | FROM centos:centos8 | |
|
2 | ||
|
3 | RUN groupadd -g %GID% build && \ | |
|
4 | useradd -u %UID% -g %GID% -s /bin/bash -d /build -m build | |
|
5 | ||
|
6 | RUN yum install -y \ | |
|
7 | gcc \ | |
|
8 | gettext \ | |
|
9 | make \ | |
|
10 | python3-devel \ | |
|
11 | python3-docutils \ | |
|
12 | rpm-build | |
|
13 | ||
|
14 | # For creating repo meta data | |
|
15 | RUN yum install -y createrepo |
@@ -0,0 +1,6 b'' | |||
|
1 | from __future__ import absolute_import, print_function | |
|
2 | ||
|
3 | import re | |
|
4 | import sys | |
|
5 | ||
|
6 | print(re.sub(r"(?<=Message-Id:) \n ", " ", sys.stdin.read()), end="") |
@@ -185,3 +185,5 b' e386b5f4f8360dbb43a576dd9b1368e386fefa5b' | |||
|
185 | 185 | e91930d712e8507d1bc1b2dffd96c83edc4cbed3 0 iQJEBAABCAAuFiEEK8zhT1xnJaouqK63ucncgkqlvdUFAl1DD/sQHHJhZkBkdXJpbjQyLmNvbQAKCRC5ydyCSqW91bvmD/4/QDZZGVe+WiMUxbT+grfFjwjX4nkg7Vt+6vQbjN68NC5XpSiCzW8uu0LRemX0KJKoOfQxqHk3YKkZZHIk10Fe6RSLWt8dqlfa2J9B2U8DwMEBykCOuxcLlDe7DGaaMXlXXRhNXebRheNPLeNe+r7beMAAjwchTIIJD5xcFnPRFR0nN7Vj7eRUdWIQ9H/s7TolPz1Mf7IWqapLjPtofiwSgtRoXfIAkuuabnE4eMVJ8rsLwcuMhxWP2zjEfEg68YkiGBAFmlnRk+3lJpiB9kVapB3cWcsWv2OBhz0D3NgGp82eWkjJCZZhZ+zHHrQ6L9zbiArzW9NVvPEAKLbl3XUhFUzFTUD+S38wsYLYL5RkzhlCI2/K1LJLOtj7r0Seen0v8X842p0cXmxTg/o1Vg3JOm04l9AwzCsnqwIqV7Ru//KPqH91MFFH6T6tbfjtLHRmjxRjMZmVt7ZQjS84opVCZwgUTZZJB2kd1goROjdowQVK6qsEonlzGjWb9zc3el5L9uzDeim3e5t2GNRVt8veQaLc+U2hHWniVsDJMvqp2Hr9IWUKp+bu/35B1nElvooS40gj2WhkfkCbbXSg9qnVLwGxxcGdF28Z0nhQcfKiJAc+8l9l19GNhdKxOi4zUXlp90opPWfT7wGQmysvTjQeFL2zX9ziuHUZZwlW1YbeMQ== |
|
186 | 186 | a4e32fd539ab41489a51b2aa88bda9a73b839562 0 iQJEBAABCAAuFiEEK8zhT1xnJaouqK63ucncgkqlvdUFAl1xTxUQHHJhZkBkdXJpbjQyLmNvbQAKCRC5ydyCSqW91ZQgD/96mViQ6fEh84l4XyAlY6Dq3SgMqEXttsUpk/GPoW4ykDFKN6VoiOaPoyNODO/46V3yeAjYjy3vX7Ua4/MY1NlnNoliQcTYtRV3SlDdoueTPOLfO6YSV27LG+dX/HYvPc/htCVmIVItU1JL+KEpXnv+bT50Bk+m6OgzfJMDzdHQ5ICImT8gW7UXlH/mlNtWMOrJDk3cArGhGs/pTFVrfgRTfDfDGSA9xW0/QvsNI5iwZHgMYaqoPFDnw6d/NXWRlk77KNiXkBEOKHf6UEWecMKmiSCm8RePSiX9ezqdcBAHygOg4KUeiR2kPNl4QJtskyG4CwWxlmGlfgKx07s7rGafE+DWLEYC9Wa8qK6/LPiowm17m/UlAYxdFXaBCiN0wgEw7oNmjcx/791ez+CL1+h6pd0+iSVI4bO9/YZ8LPROYef18MFm+IFIDIOgZU4eUbpBrzBb3IM1a519xgnmWXAjtRtGWEZMuHaSoLJf2pDXvaUPX6YpJeqCBFO3q/swbiJsQsy6xRW0Dwtn7umU1PGdmMoTnskTRKy9Kgzv7lf/nsUuRbzzM4ut9m1TOo27AulObMrmQB4YvLi/LEnYaRNx18yaqOceMxb/mS0tHLgcZToy9rTV+vtC21vgwfzGia2neLLe50tnIsBPP/AdTOw9ZDMRfXMCajWM22hPxvnGcw== |
|
187 | 187 | 181e52f2b62f4768aa0d988936c929dc7c4a41a0 0 iQJEBAABCAAuFiEEK8zhT1xnJaouqK63ucncgkqlvdUFAl2UzlMQHHJhZkBkdXJpbjQyLmNvbQAKCRC5ydyCSqW91SDzD/0YZqtN+LK5AusJjWaTa61DRIPhJQoZD+HKg4kAzjL8zw8SxBGLxMZkGmve9QFMNzqIr5kkPk6yEKrEWYqyPtpwrv5Xh5D4d8AKfphdzwSr+BvMk4fBEvwnBhrUJtKDEiuYQdbh4+OQfQs1c3xhtinjXn30160uzFvLQY6/h4hxai2XWj4trgoNXqPHDHlQKc6kRfPpmNO2UZhG+2Xfsava2JpcP4xA2R0XkI10be5MDoGU4AFCMUcXZzIto0DYT+HOezowoNpdC1EWVHfa+bdrlzHHO7WPaTLzEPy44/IhXmNhbwFKOk5RZ/qBADQvs9BDfmIDczOoZKTC5+ESZM0PR2np5t7+JFMUeeRcINqBdSc4Aszw3iHjgNbJJ3viU72JZvGGGd9MglP590tA0proVGxQgvXDq3mtq3Se5yOLAjmRnktW5Tnt8/Z3ycuZz+QsTEMXR5uIZvgz63ibfsCGTXFYUz9h7McGgmhfKWvQw9+MH6kRbE9U8qaUumgf4zi4HNzmf8AyaMJo07DIMwWVgjlVUdWUlN/Eg61fU3wC79mV8mLVsi5/TZ986obz4csoYSYXyyez5ScRji+znSw8vUx0YhoiOQbDms/y2QZR/toyon554tHkDZsya2lhpwXs8T0IFZhERXsmz/XmT3fWnhSzyrUe6VjBMep1zn6lvQ== |
|
188 | 59338f9561099de77c684c00f76507f11e46ebe8 0 iQJEBAABCAAuFiEEK8zhT1xnJaouqK63ucncgkqlvdUFAl2ty1MQHHJhZkBkdXJpbjQyLmNvbQAKCRC5ydyCSqW91XBUD/wJqwW0cuMCUvuUODLIfWa7ZxNl1mV9eW3tFQEuLGry97s12KDwBe0Erdjj7DASl4/6Xpc4PYxelZwSw4xT1UQg7wd/C3daCq/cDXrAkl7ZNTAHu6iAnHh25mOpIBfhMbh4j3YD0A2OoI17QGScU6S7Uv0Gz1CY20lJmEqsMzuuDPm2zrdPnTWffRUuPgskAg3czaw45Na7nUBeaxN1On0O5WqMYZsCGyi14g5S0Z0LHMKRJzc/s48JUTDjTbbzJ6HBxrxWTW2v8gN2J6QDYykcLBB9kV6laal9jhWs9n/w0yWwHfBfJ+E4EiMXeRdZgGA55OCOuDxnmmONs1/Z0WwPo+vQlowEnjDMT0jPrPePZ5P4BDXZD3tGsmdXDHM7j+VfDyPh1FBFpcaej44t84X1OWtAnLZ3VMPLwobz9MOzz4wr9UuHq23hus0Fen+FJYOAlTx9qPAqBrCTpGl+h1DMKD62D7lF8Z1CxTlqg9PPBB7IZNCXoN7FZ4Wfhv1AarMVNNUgBx6m0r6OScCXrluuFklYDSIZrfgiwosXxsHW27RjxktrV4O+J1GT/chLBJFViTZg/gX/9UC3eLkzp1t6gC6T9SQ+lq0/I+1/rHQkxNaywLycBPOG1yb/59mibEwB9+Mu9anRYKFNHEktNoEmyw5G9UoZhD+1tHt4tkJCwA== | |
|
189 | ca3dca416f8d5863ca6f5a4a6a6bb835dcd5feeb 0 iQJEBAABCAAuFiEEK8zhT1xnJaouqK63ucncgkqlvdUFAl3BrQ4QHHJhZkBkdXJpbjQyLmNvbQAKCRC5ydyCSqW91ZXjEACfBdZczf0a4bmeaaxRwxXAniSS4rVkF790g22fsvSZFvQEpmwqNtsvbTt3N1V2QSDSZyhBa+/qfpuZ689VXMlR3rcJOVjo/7193QLXHOPfRn7sDeeCxjsbtXXLbLa8UT56gtT5gUa4i0LC2kHBEi+UhV9EGgSaDTBxWUFJ9RY2sosy1XFiOUlkUoHUbqUF28J3/CxEXzULWkqTOPwh94JYsgXSSS69WNZEfsuEBSPCzn8Gd7z7lWudZ/VTZBTpTji7HQxpFtSZxNzpwmcmVOH9HlEKoA1K4JoR+1TMHqSytQXlz3FMF6c6Z1G+OPpwTGCjGTkB9ZAusP3gU8KIZTTEXthiEluRtnRq1yu4K2LTyY172JPJvANAWpVEvBvn4k5c9tDOEt9RCAPqCrgNGzDTrw02+gZyyNkjcS6hPn+cDJ6OQ1j2eCQtHlqfHLSc7FsRjUSTiKSEUTdWvHbNfOYe6Yth/tnQ7TnpnS9S0eiugFzZs2f8P85Gfa3uTFQIDm67Ud+8Yu1uOxa6bhECLaXEACnLofzz8sioLsJMiOoG2HmwhyPyfZUHXlb2zdsSP3LC+gKN39VvzSxhhjrIUJoM4ulP0GP1/lkMVzOady66iLaEwDvEn4FLmu395SubHwbre1Jx83hiCQpZfPkI0PhKnh4yVm+BRGUpX97rMTGjzw== |
@@ -198,3 +198,5 b' e386b5f4f8360dbb43a576dd9b1368e386fefa5b' | |||
|
198 | 198 | e91930d712e8507d1bc1b2dffd96c83edc4cbed3 5.1 |
|
199 | 199 | a4e32fd539ab41489a51b2aa88bda9a73b839562 5.1.1 |
|
200 | 200 | 181e52f2b62f4768aa0d988936c929dc7c4a41a0 5.1.2 |
|
201 | 59338f9561099de77c684c00f76507f11e46ebe8 5.2rc0 | |
|
202 | ca3dca416f8d5863ca6f5a4a6a6bb835dcd5feeb 5.2 |
@@ -183,16 +183,15 b' packaging_targets := \\' | |||
|
183 | 183 | centos5 \ |
|
184 | 184 | centos6 \ |
|
185 | 185 | centos7 \ |
|
186 | centos8 \ | |
|
186 | 187 | deb \ |
|
187 | 188 | docker-centos5 \ |
|
188 | 189 | docker-centos6 \ |
|
189 | 190 | docker-centos7 \ |
|
191 | docker-centos8 \ | |
|
190 | 192 | docker-debian-jessie \ |
|
191 | 193 | docker-debian-stretch \ |
|
192 |
docker-fedora |
|
|
193 | docker-fedora21 \ | |
|
194 | docker-fedora28 \ | |
|
195 | docker-fedora29 \ | |
|
194 | docker-fedora \ | |
|
196 | 195 | docker-ubuntu-trusty \ |
|
197 | 196 | docker-ubuntu-trusty-ppa \ |
|
198 | 197 | docker-ubuntu-xenial \ |
@@ -201,10 +200,7 b' packaging_targets := \\' | |||
|
201 | 200 | docker-ubuntu-artful-ppa \ |
|
202 | 201 | docker-ubuntu-bionic \ |
|
203 | 202 | docker-ubuntu-bionic-ppa \ |
|
204 |
fedora |
|
|
205 | fedora21 \ | |
|
206 | fedora28 \ | |
|
207 | fedora29 \ | |
|
203 | fedora \ | |
|
208 | 204 | linux-wheels \ |
|
209 | 205 | linux-wheels-x86_64 \ |
|
210 | 206 | linux-wheels-i686 \ |
@@ -9,9 +9,7 b' build/' | |||
|
9 | 9 | | \.mypy_cache/ |
|
10 | 10 | | \.venv/ |
|
11 | 11 | | mercurial/thirdparty/ |
|
12 | | hgext/fsmonitor/pywatchman/ | |
|
13 | 12 | | contrib/python-zstandard/ |
|
14 | | contrib/grey.py | |
|
15 | 13 | ''' |
|
16 | 14 | skip-string-normalization = true |
|
17 | 15 | quiet = true |
@@ -191,6 +191,10 b" winrm set winrm/config/client/auth '@{Ba" | |||
|
191 | 191 | $Setting = 'LocalAccountTokenFilterPolicy' |
|
192 | 192 | Set-ItemProperty -Path $Key -Name $Setting -Value 1 -Force |
|
193 | 193 | |
|
194 | # Avoid long usernames in the temp directory path because the '~' causes extra quoting in ssh output | |
|
195 | [System.Environment]::SetEnvironmentVariable('TMP', 'C:\Temp', [System.EnvironmentVariableTarget]::User) | |
|
196 | [System.Environment]::SetEnvironmentVariable('TEMP', 'C:\Temp', [System.EnvironmentVariableTarget]::User) | |
|
197 | ||
|
194 | 198 | # Configure and restart the WinRM Service; Enable the required firewall exception |
|
195 | 199 | Stop-Service -Name WinRM |
|
196 | 200 | Set-Service -Name WinRM -StartupType Automatic |
@@ -25,12 +25,12 b' DISTROS = {' | |||
|
25 | 25 | } |
|
26 | 26 | |
|
27 | 27 | INSTALL_PYTHONS = r''' |
|
28 |
PYENV2_VERSIONS="2.7.1 |
|
|
29 |
PYENV3_VERSIONS="3.5.7 3.6.9 3.7. |
|
|
28 | PYENV2_VERSIONS="2.7.17 pypy2.7-7.2.0" | |
|
29 | PYENV3_VERSIONS="3.5.7 3.6.9 3.7.5 3.8.0 pypy3.5-7.0.0 pypy3.6-7.2.0" | |
|
30 | 30 | |
|
31 | 31 | git clone https://github.com/pyenv/pyenv.git /hgdev/pyenv |
|
32 | 32 | pushd /hgdev/pyenv |
|
33 | git checkout d6d6bc8bb08bcdcbf4eb79509aa7061011ade1c4 | |
|
33 | git checkout 0e7cfc3b3d4eca46ad83d632e1505f5932cd179b | |
|
34 | 34 | popd |
|
35 | 35 | |
|
36 | 36 | export PYENV_ROOT="/hgdev/pyenv" |
@@ -266,6 +266,7 b' PACKAGES="\\' | |||
|
266 | 266 | python3-fuzzywuzzy \ |
|
267 | 267 | python3-pygments \ |
|
268 | 268 | python3-vcr \ |
|
269 | python3-venv \ | |
|
269 | 270 | rsync \ |
|
270 | 271 | sqlite3 \ |
|
271 | 272 | subversion \ |
@@ -4,10 +4,25 b'' | |||
|
4 | 4 | # |
|
5 | 5 | # pip-compile --generate-hashes --output-file=contrib/automation/linux-requirements-py3.txt contrib/automation/linux-requirements.txt.in |
|
6 | 6 | # |
|
7 | appdirs==1.4.3 \ | |
|
8 | --hash=sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92 \ | |
|
9 | --hash=sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e \ | |
|
10 | # via black | |
|
7 | 11 | astroid==2.2.5 \ |
|
8 | 12 | --hash=sha256:6560e1e1749f68c64a4b5dee4e091fce798d2f0d84ebe638cf0e0585a343acf4 \ |
|
9 | 13 | --hash=sha256:b65db1bbaac9f9f4d190199bb8680af6f6f84fd3769a5ea883df8a91fe68b4c4 \ |
|
10 | 14 | # via pylint |
|
15 | attrs==19.3.0 \ | |
|
16 | --hash=sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c \ | |
|
17 | --hash=sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72 \ | |
|
18 | # via black | |
|
19 | black==19.10b0 ; python_version >= "3.6" and platform_python_implementation != "PyPy" \ | |
|
20 | --hash=sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b \ | |
|
21 | --hash=sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539 | |
|
22 | click==7.0 \ | |
|
23 | --hash=sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13 \ | |
|
24 | --hash=sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7 \ | |
|
25 | # via black | |
|
11 | 26 | docutils==0.15.2 \ |
|
12 | 27 | --hash=sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0 \ |
|
13 | 28 | --hash=sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827 \ |
@@ -78,6 +93,9 b' multidict==4.5.2 \\' | |||
|
78 | 93 | --hash=sha256:d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7 \ |
|
79 | 94 | --hash=sha256:db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b \ |
|
80 | 95 | # via yarl |
|
96 | pathspec==0.6.0 \ | |
|
97 | --hash=sha256:e285ccc8b0785beadd4c18e5708b12bb8fcf529a1e61215b3feff1d1e559ea5c \ | |
|
98 | # via black | |
|
81 | 99 | pyflakes==2.1.1 \ |
|
82 | 100 | --hash=sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0 \ |
|
83 | 101 | --hash=sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2 |
@@ -104,10 +122,27 b' pyyaml==5.1.2 \\' | |||
|
104 | 122 | --hash=sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41 \ |
|
105 | 123 | --hash=sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8 \ |
|
106 | 124 | # via vcrpy |
|
125 | regex==2019.11.1 \ | |
|
126 | --hash=sha256:15454b37c5a278f46f7aa2d9339bda450c300617ca2fca6558d05d870245edc7 \ | |
|
127 | --hash=sha256:1ad40708c255943a227e778b022c6497c129ad614bb7a2a2f916e12e8a359ee7 \ | |
|
128 | --hash=sha256:5e00f65cc507d13ab4dfa92c1232d004fa202c1d43a32a13940ab8a5afe2fb96 \ | |
|
129 | --hash=sha256:604dc563a02a74d70ae1f55208ddc9bfb6d9f470f6d1a5054c4bd5ae58744ab1 \ | |
|
130 | --hash=sha256:720e34a539a76a1fedcebe4397290604cc2bdf6f81eca44adb9fb2ea071c0c69 \ | |
|
131 | --hash=sha256:7caf47e4a9ac6ef08cabd3442cc4ca3386db141fb3c8b2a7e202d0470028e910 \ | |
|
132 | --hash=sha256:c31eaf28c6fe75ea329add0022efeed249e37861c19681960f99bbc7db981fb2 \ | |
|
133 | --hash=sha256:c7393597191fc2043c744db021643549061e12abe0b3ff5c429d806de7b93b66 \ | |
|
134 | --hash=sha256:d2b302f8cdd82c8f48e9de749d1d17f85ce9a0f082880b9a4859f66b07037dc6 \ | |
|
135 | --hash=sha256:e3d8dd0ec0ea280cf89026b0898971f5750a7bd92cb62c51af5a52abd020054a \ | |
|
136 | --hash=sha256:ec032cbfed59bd5a4b8eab943c310acfaaa81394e14f44454ad5c9eba4f24a74 \ | |
|
137 | # via black | |
|
107 | 138 | six==1.12.0 \ |
|
108 | 139 | --hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \ |
|
109 | 140 | --hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73 \ |
|
110 | 141 | # via astroid, vcrpy |
|
142 | toml==0.10.0 \ | |
|
143 | --hash=sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c \ | |
|
144 | --hash=sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e \ | |
|
145 | # via black | |
|
111 | 146 | typed-ast==1.4.0 ; python_version >= "3.0" and platform_python_implementation != "PyPy" \ |
|
112 | 147 | --hash=sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e \ |
|
113 | 148 | --hash=sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e \ |
@@ -146,4 +181,4 b' yarl==1.3.0 \\' | |||
|
146 | 181 | |
|
147 | 182 | # WARNING: The following packages were not pinned, but pip requires them to be |
|
148 | 183 | # pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag. |
|
149 |
# setuptools==41. |
|
|
184 | # setuptools==41.6.0 # via python-levenshtein |
@@ -1,3 +1,5 b'' | |||
|
1 | # black pulls in typed-ast, which doesn't install on PyPy. | |
|
2 | black ; python_version >= '3.6' and platform_python_implementation != 'PyPy' | |
|
1 | 3 | # Bazaar doesn't work with Python 3 nor PyPy. |
|
2 | 4 | bzr ; python_version <= '2.7' and platform_python_implementation == 'CPython' |
|
3 | 5 | docutils |
@@ -339,7 +339,7 b' def main():' | |||
|
339 | 339 | |
|
340 | 340 | |
|
341 | 341 | if __name__ == '__main__': |
|
342 |
if sys.version_info |
|
|
343 | print('This script must be run under Python 3.') | |
|
342 | if sys.version_info[0:2] < (3, 7): | |
|
343 | print('This script must be run under Python 3.7+') | |
|
344 | 344 | sys.exit(3) |
|
345 | 345 | main() |
@@ -5,11 +5,5 b' clang-format:pattern = (**.c or **.cc or' | |||
|
5 | 5 | rustfmt:command = rustfmt {rootpath} |
|
6 | 6 | rustfmt:pattern = set:**.rs |
|
7 | 7 | |
|
8 | # We use black, but currently with | |
|
9 | # https://github.com/psf/black/pull/826 applied. For now | |
|
10 | # contrib/grey.py is our fork of black. You need to pip install | |
|
11 | # git+https://github.com/python/black/@d9e71a75ccfefa3d9156a64c03313a0d4ad981e5 | |
|
12 | # to have the dependencies for grey. | |
|
13 | # | |
|
14 | # black:command = python3.7 contrib/grey.py --config=black.toml - | |
|
15 | # black:pattern = set:**.py - hgext/fsmonitor/pywatchman/** - mercurial/thirdparty/** - "contrib/python-zstandard/** - contrib/grey.py" | |
|
8 | black:command = black --config=black.toml - | |
|
9 | black:pattern = set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" |
@@ -4,6 +4,7 b' from __future__ import absolute_import, ' | |||
|
4 | 4 | |
|
5 | 5 | import ast |
|
6 | 6 | import collections |
|
7 | import io | |
|
7 | 8 | import os |
|
8 | 9 | import sys |
|
9 | 10 | |
@@ -754,7 +755,11 b' def sources(f, modname):' | |||
|
754 | 755 | yield src.read(), modname, f, 0 |
|
755 | 756 | py = True |
|
756 | 757 | if py or f.endswith('.t'): |
|
757 | with open(f, 'r') as src: | |
|
758 | # Strictly speaking we should sniff for the magic header that denotes | |
|
759 | # Python source file encoding. But in reality we don't use anything | |
|
760 | # other than ASCII (mainly) and UTF-8 (in a few exceptions), so | |
|
761 | # simplicity is fine. | |
|
762 | with io.open(f, 'r', encoding='utf-8') as src: | |
|
758 | 763 | for script, modname, t, line in embedded(f, modname, src): |
|
759 | 764 | yield script, modname.encode('utf8'), t, line |
|
760 | 765 |
@@ -22,10 +22,10 b'' | |||
|
22 | 22 | $VC9_PYTHON_URL = "https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi" |
|
23 | 23 | $VC9_PYTHON_SHA256 = "070474db76a2e625513a5835df4595df9324d820f9cc97eab2a596dcbc2f5cbf" |
|
24 | 24 | |
|
25 |
$PYTHON27_x64_URL = "https://www.python.org/ftp/python/2.7.1 |
|
|
26 | $PYTHON27_x64_SHA256 = "7c0f45993019152d46041a7db4b947b919558fdb7a8f67bcd0535bc98d42b603" | |
|
27 |
$PYTHON27_X86_URL = "https://www.python.org/ftp/python/2.7.1 |
|
|
28 | $PYTHON27_X86_SHA256 = "d57dc3e1ba490aee856c28b4915d09e3f49442461e46e481bc6b2d18207831d7" | |
|
25 | $PYTHON27_x64_URL = "https://www.python.org/ftp/python/2.7.17/python-2.7.17.amd64.msi" | |
|
26 | $PYTHON27_x64_SHA256 = "3b934447e3620e51d2daf5b2f258c9b617bcc686ca2f777a49aa3b47893abf1b" | |
|
27 | $PYTHON27_X86_URL = "https://www.python.org/ftp/python/2.7.17/python-2.7.17.msi" | |
|
28 | $PYTHON27_X86_SHA256 = "a4e3a321517c6b0c2693d6f712a0d18c82600b3d0c759c299b3d14384a17f863" | |
|
29 | 29 | |
|
30 | 30 | $PYTHON35_x86_URL = "https://www.python.org/ftp/python/3.5.4/python-3.5.4.exe" |
|
31 | 31 | $PYTHON35_x86_SHA256 = "F27C2D67FD9688E4970F3BFF799BB9D722A0D6C2C13B04848E1F7D620B524B0E" |
@@ -37,10 +37,10 b'' | |||
|
37 | 37 | $PYTHON36_x64_URL = "https://www.python.org/ftp/python/3.6.8/python-3.6.8-amd64.exe" |
|
38 | 38 | $PYTHON36_x64_SHA256 = "96088A58B7C43BC83B84E6B67F15E8706C614023DD64F9A5A14E81FF824ADADC" |
|
39 | 39 | |
|
40 |
$PYTHON37_x86_URL = "https://www.python.org/ftp/python/3.7. |
|
|
41 | $PYTHON37_x86_SHA256 = "9a30ab5568ba37bfbcae5cdee19e9dc30765c42cf066f605221563ff8b20ee34" | |
|
42 |
$PYTHON37_X64_URL = "https://www.python.org/ftp/python/3.7. |
|
|
43 | $PYTHON37_x64_SHA256 = "bab92f987320975c7826171a072bfd64f8f0941aaf2cdeba6924b7025c9968a3" | |
|
40 | $PYTHON37_x86_URL = "https://www.python.org/ftp/python/3.7.5/python-3.7.5.exe" | |
|
41 | $PYTHON37_x86_SHA256 = "3c2ae8f72b48e6e0c2b482206e322bf5d0344ff91abc3b3c200cec9e275c7168" | |
|
42 | $PYTHON37_X64_URL = "https://www.python.org/ftp/python/3.7.5/python-3.7.5-amd64.exe" | |
|
43 | $PYTHON37_x64_SHA256 = "f3d60c127e7a92ed547efa3321bf70cd96b75c53bf4b903147015257c1314981" | |
|
44 | 44 | |
|
45 | 45 | $PYTHON38_x86_URL = "https://www.python.org/ftp/python/3.8.0/python-3.8.0.exe" |
|
46 | 46 | $PYTHON38_x86_SHA256 = "b471908de5e10d8fb5c3351a5affb1172da7790c533e0c9ffbaeec9c11611b15" |
@@ -11,19 +11,17 b' UBUNTU_CODENAMES := \\' | |||
|
11 | 11 | cosmic \ |
|
12 | 12 | disco |
|
13 | 13 | |
|
14 |
FEDORA_RELEASE |
|
|
15 | 20 \ | |
|
16 | 21 \ | |
|
17 | 28 \ | |
|
18 | 29 | |
|
14 | FEDORA_RELEASE := 31 | |
|
19 | 15 | |
|
20 | 16 | CENTOS_RELEASES := \ |
|
21 | 17 | 5 \ |
|
22 | 18 | 6 \ |
|
23 | 7 | |
|
19 | 7 \ | |
|
20 | 8 | |
|
24 | 21 | |
|
25 | 22 | # Build a Python for these CentOS releases. |
|
26 | 23 | CENTOS_WITH_PYTHON_RELEASES := 5 6 |
|
24 | CENTOS_WITH_NONVERSIONED_PYTHON := 5 6 7 | |
|
27 | 25 | |
|
28 | 26 | help: |
|
29 | 27 | @echo 'Packaging Make Targets' |
@@ -34,8 +32,8 b' help:' | |||
|
34 | 32 | @echo 'docker-debian-{$(strip $(DEBIAN_CODENAMES))}' |
|
35 | 33 | @echo ' Build Debian packages specific to a Debian distro using Docker.' |
|
36 | 34 | @echo '' |
|
37 |
@echo 'docker-fedora |
|
|
38 |
@echo ' Build an RPM for a |
|
|
35 | @echo 'docker-fedora' | |
|
36 | @echo ' Build an RPM for a Fedora $(FEDORA_RELEASE) using Docker.' | |
|
39 | 37 | @echo '' |
|
40 | 38 | @echo 'docker-ubuntu-{$(strip $(UBUNTU_CODENAMES))}' |
|
41 | 39 | @echo ' Build Debian package specific to an Ubuntu distro using Docker.' |
@@ -59,8 +57,8 b' help:' | |||
|
59 | 57 | @echo 'centos{$(strip $(CENTOS_RELEASES))}' |
|
60 | 58 | @echo ' Build an RPM for a specific CentOS version locally' |
|
61 | 59 | @echo '' |
|
62 | @echo 'fedora{$(strip $(FEDORA_RELEASES))}' | |
|
63 |
@echo ' Build an RPM for |
|
|
60 | @echo 'fedora' | |
|
61 | @echo ' Build an RPM for Fedora $(FEDORA_RELEASE) locally' | |
|
64 | 62 | |
|
65 | 63 | .PHONY: help |
|
66 | 64 | |
@@ -97,37 +95,30 b' endef' | |||
|
97 | 95 | $(foreach codename,$(UBUNTU_CODENAMES),$(eval $(call ubuntu_targets,$(codename)))) |
|
98 | 96 | |
|
99 | 97 | # Fedora targets. |
|
100 | define fedora_targets | |
|
101 | .PHONY: fedora$(1) | |
|
102 | fedora$(1): | |
|
103 | mkdir -p $$(HGROOT)/packages/fedora$(1) | |
|
98 | .PHONY: fedora | |
|
99 | fedora: | |
|
100 | mkdir -p $(HGROOT)/packages/fedora$(FEDORA_RELEASE) | |
|
104 | 101 | ./buildrpm |
|
105 |
cp |
|
|
106 |
cp |
|
|
102 | cp $(HGROOT)/contrib/packaging/rpmbuild/RPMS/*/* $(HGROOT)/packages/fedora$(FEDORA_RELEASE) | |
|
103 | cp $(HGROOT)/contrib/packaging/rpmbuild/SRPMS/* $(HGROOT)/packages/fedora$(FEDORA_RELEASE) | |
|
107 | 104 | rm -rf $(HGROOT)/rpmbuild |
|
108 | 105 | |
|
109 |
.PHONY: docker-fedora |
|
|
110 |
docker-fedora |
|
|
111 | mkdir -p $$(HGROOT)/packages/fedora$(1) | |
|
112 | ./dockerrpm fedora$(1) | |
|
113 | ||
|
114 | endef | |
|
115 | ||
|
116 | $(foreach release,$(FEDORA_RELEASES),$(eval $(call fedora_targets,$(release)))) | |
|
106 | .PHONY: docker-fedora | |
|
107 | docker-fedora: | |
|
108 | ./dockerrpm fedora$(FEDORA_RELEASE) | |
|
117 | 109 | |
|
118 | 110 | # CentOS targets. |
|
119 | 111 | define centos_targets |
|
120 | 112 | .PHONY: centos$(1) |
|
121 | 113 | centos$(1): |
|
122 | 114 | mkdir -p $$(HGROOT)/packages/centos$(1) |
|
123 | ./buildrpm $$(if $$(filter $(1),$$(CENTOS_WITH_PYTHON_RELEASES)),--withpython) | |
|
115 | ./buildrpm $$(if $$(filter $(1),$$(CENTOS_WITH_PYTHON_RELEASES)),--withpython,$$(if $$(filter $(1),$$(CENTOS_WITH_NONVERSIONED_PYTHON)),--python python,)) | |
|
124 | 116 | cp $$(HGROOT)/contrib/packaging/rpmbuild/RPMS/*/* $$(HGROOT)/packages/centos$(1) |
|
125 | 117 | cp $$(HGROOT)/contrib/packaging/rpmbuild/SRPMS/* $$(HGROOT)/packages/centos$(1) |
|
126 | 118 | |
|
127 | 119 | .PHONY: docker-centos$(1) |
|
128 | 120 | docker-centos$(1): |
|
129 | mkdir -p $$(HGROOT)/packages/centos$(1) | |
|
130 | ./dockerrpm centos$(1) $$(if $$(filter $(1),$$(CENTOS_WITH_PYTHON_RELEASES)),--withpython) | |
|
121 | ./dockerrpm centos$(1) $$(if $$(filter $(1),$$(CENTOS_WITH_PYTHON_RELEASES)),--withpython,$$(if $$(filter $(1),$$(CENTOS_WITH_NONVERSIONED_PYTHON)),--python python,)) | |
|
131 | 122 | |
|
132 | 123 | endef |
|
133 | 124 |
@@ -106,10 +106,10 b' if [ "$CLEANUP" ] ; then' | |||
|
106 | 106 | echo |
|
107 | 107 | OUTPUTDIR=${OUTPUTDIR:=packages/$DISTID-$CODENAME} |
|
108 | 108 | mkdir -p "$OUTPUTDIR" |
|
109 | find ../mercurial*.deb ../mercurial_*.build ../mercurial_*.changes \ | |
|
109 | find ../mercurial*.deb ../mercurial_*.build* ../mercurial_*.changes \ | |
|
110 | 110 | ../mercurial*.dsc ../mercurial*.gz \ |
|
111 | 111 | -type f -newer $control -print0 2>/dev/null | \ |
|
112 | 112 | xargs -Inarf -0 mv narf "$OUTPUTDIR" |
|
113 | 113 | echo "Built packages for $debver:" |
|
114 |
find "$ |
|
|
114 | find "$OUTPUTDIR" -type f -newer $control -name '*.deb' | |
|
115 | 115 | fi |
@@ -1,16 +1,12 b'' | |||
|
1 | 1 | #!/bin/bash -e |
|
2 | 2 | # |
|
3 | # Build a Mercurial RPM from the current repo | |
|
4 | # | |
|
5 | # Tested on | |
|
6 | # - Fedora 20 | |
|
7 | # - CentOS 5 | |
|
8 | # - centOS 6 | |
|
3 | # Build a Mercurial RPM from the current repo, mainly for Fedora/CentOS/RHEL | |
|
9 | 4 | |
|
10 | 5 | . $(dirname $0)/packagelib.sh |
|
11 | 6 | |
|
12 | 7 | BUILD=1 |
|
13 | 8 | RPMBUILDDIR="$PWD/rpmbuild" |
|
9 | PYTHONEXE=python3 | |
|
14 | 10 | |
|
15 | 11 | while [ "$1" ]; do |
|
16 | 12 | case "$1" in |
@@ -18,10 +14,16 b' while [ "$1" ]; do' | |||
|
18 | 14 | shift |
|
19 | 15 | BUILD= |
|
20 | 16 | ;; |
|
17 | --python) | |
|
18 | shift | |
|
19 | PYTHONEXE=$1 | |
|
20 | shift | |
|
21 | ;; | |
|
21 | 22 | --withpython | --with-python) |
|
22 | 23 | shift |
|
23 | 24 | PYTHONVER=2.7.16 |
|
24 | 25 | PYTHONMD5=f1a2ace631068444831d01485466ece0 |
|
26 | PYTHONEXE=python | |
|
25 | 27 | ;; |
|
26 | 28 | --rpmbuilddir ) |
|
27 | 29 | shift |
@@ -96,6 +98,7 b' rpmspec=$RPMBUILDDIR/SPECS/mercurial.spe' | |||
|
96 | 98 | |
|
97 | 99 | sed -e "s,^Version:.*,Version: $version," \ |
|
98 | 100 | -e "s,^Release:.*,Release: $release," \ |
|
101 | -e "s/^%global pythonexe .*/%global pythonexe $PYTHONEXE/" \ | |
|
99 | 102 | $specfile > $rpmspec |
|
100 | 103 | |
|
101 | 104 | echo >> $rpmspec |
@@ -121,8 +124,8 b' for l in sorted(changelog, reverse=True)' | |||
|
121 | 124 | if prevtitle != title: |
|
122 | 125 | prevtitle = title |
|
123 | 126 | |
|
124 |
print |
|
|
125 |
print |
|
|
127 | print(title) | |
|
128 | print("- %s" % l[3].strip()) | |
|
126 | 129 | ' >> $rpmspec |
|
127 | 130 | |
|
128 | 131 | else |
@@ -138,7 +141,7 b' def datestr(date, format):' | |||
|
138 | 141 | for l in sys.stdin.readlines(): |
|
139 | 142 | tok = l.split("\t") |
|
140 | 143 | hgdate = tuple(int(v) for v in tok[0].split()) |
|
141 |
print |
|
|
144 | print("* %s %s\n- %s" % (datestr(hgdate, "%a %b %d %Y"), tok[1], tok[2])) | |
|
142 | 145 | ' >> $rpmspec |
|
143 | 146 | |
|
144 | 147 | fi |
@@ -7,21 +7,24 b' Build-Depends:' | |||
|
7 | 7 | dh-python, |
|
8 | 8 | less, |
|
9 | 9 | netbase, |
|
10 | python-all, | |
|
11 | python-all-dev, | |
|
12 | python-docutils, | |
|
10 | python3-all, | |
|
11 | python3-all-dev, | |
|
12 | python3-docutils, | |
|
13 | 13 | unzip, |
|
14 | 14 | zip |
|
15 | 15 | Standards-Version: 3.9.4 |
|
16 |
X-Python-Version: >= |
|
|
16 | X-Python3-Version: >= 3.5 | |
|
17 | 17 | |
|
18 | 18 | Package: mercurial |
|
19 | 19 | Depends: |
|
20 | python, | |
|
20 | sensible-utils, | |
|
21 | 21 | ${shlibs:Depends}, |
|
22 | 22 | ${misc:Depends}, |
|
23 | ${python:Depends}, | |
|
24 | mercurial-common (= ${source:Version}) | |
|
23 | ${python3:Depends}, | |
|
24 | Recommends: ca-certificates | |
|
25 | Suggests: wish | |
|
26 | Replaces: mercurial-common | |
|
27 | Breaks: mercurial-common | |
|
25 | 28 | Architecture: any |
|
26 | 29 | Description: fast, easy to use, distributed revision control tool. |
|
27 | 30 | Mercurial is a fast, lightweight Source Control Management system designed |
@@ -36,19 +39,3 b' Description: fast, easy to use, distribu' | |||
|
36 | 39 | * Easy-to-use command-line interface |
|
37 | 40 | * Integrated stand-alone web interface |
|
38 | 41 | * Small Python codebase |
|
39 | ||
|
40 | Package: mercurial-common | |
|
41 | Architecture: all | |
|
42 | Depends: | |
|
43 | ${misc:Depends}, | |
|
44 | ${python:Depends}, | |
|
45 | Recommends: mercurial (= ${source:Version}), ca-certificates | |
|
46 | Suggests: wish | |
|
47 | Breaks: mercurial (<< ${source:Version}) | |
|
48 | Replaces: mercurial (<< 2.6.3) | |
|
49 | Description: easy-to-use, scalable distributed version control system (common files) | |
|
50 | Mercurial is a fast, lightweight Source Control Management system designed | |
|
51 | for efficient handling of very large distributed projects. | |
|
52 | . | |
|
53 | This package contains the architecture independent components of Mercurial, | |
|
54 | and is generally useless without the mercurial package. |
@@ -4,41 +4,41 b'' | |||
|
4 | 4 | |
|
5 | 5 | CPUS=$(shell cat /proc/cpuinfo | grep -E ^processor | wc -l) |
|
6 | 6 | |
|
7 | export HGPYTHON3=1 | |
|
8 | export PYTHON=python3 | |
|
9 | ||
|
7 | 10 | %: |
|
8 |
dh $@ --with python |
|
|
11 | dh $@ --with python3 | |
|
9 | 12 | |
|
10 | 13 | override_dh_auto_test: |
|
11 | 14 | http_proxy='' dh_auto_test -- TESTFLAGS="-j$(CPUS)" |
|
12 | 15 | |
|
13 |
override_dh_python |
|
|
14 | dh_python2 | |
|
15 | find debian/mercurial/usr/share -type d -empty -delete | |
|
16 | override_dh_python3: | |
|
17 | dh_python3 --shebang=/usr/bin/python3 | |
|
18 | ||
|
19 | override_dh_auto_clean: | |
|
20 | $(MAKE) cleanbutpackages | |
|
21 | $(MAKE) -C contrib/chg clean | |
|
16 | 22 | |
|
17 |
override_dh_ |
|
|
18 | python$(PYVERS) setup.py install --root "$(CURDIR)"/debian/mercurial --install-layout=deb | |
|
23 | override_dh_auto_build: | |
|
24 | $(MAKE) all | |
|
25 | $(MAKE) -C contrib/chg all | |
|
26 | ||
|
27 | override_dh_auto_install: | |
|
28 | python3 setup.py install --root "$(CURDIR)"/debian/mercurial --install-layout=deb | |
|
19 | 29 | # chg |
|
20 | 30 | make -C contrib/chg \ |
|
21 | 31 | DESTDIR="$(CURDIR)"/debian/mercurial \ |
|
22 | 32 | PREFIX=/usr \ |
|
23 |
|
|
|
24 | # remove arch-independent python stuff | |
|
25 |
|
|
|
26 | ! -name '*.so' ! -type d -delete , \ | |
|
27 | -type d -empty -delete | |
|
28 | python$(PYVERS) setup.py install --root "$(CURDIR)/debian/mercurial-common" --install-layout=deb | |
|
29 | make install-doc PREFIX="$(CURDIR)"/debian/mercurial-common/usr | |
|
30 | # remove arch-dependent python stuff | |
|
31 | find "$(CURDIR)"/debian/mercurial-common/usr/lib \ | |
|
32 | -name '*.so' ! -type d -delete , \ | |
|
33 | -type d -empty -delete | |
|
34 | cp contrib/hg-ssh "$(CURDIR)"/debian/mercurial-common/usr/bin | |
|
35 | mkdir -p "$(CURDIR)"/debian/mercurial-common/usr/share/mercurial | |
|
36 | cp contrib/hgk "$(CURDIR)"/debian/mercurial-common/usr/share/mercurial | |
|
37 | mkdir -p "$(CURDIR)"/debian/mercurial-common/etc/mercurial/hgrc.d/ | |
|
38 | cp contrib/packaging/debian/*.rc "$(CURDIR)"/debian/mercurial-common/etc/mercurial/hgrc.d/ | |
|
33 | install | |
|
34 | make install-doc PREFIX="$(CURDIR)"/debian/mercurial/usr | |
|
35 | cp contrib/hg-ssh "$(CURDIR)"/debian/mercurial/usr/bin | |
|
36 | mkdir -p "$(CURDIR)"/debian/mercurial/usr/share/mercurial | |
|
37 | cp contrib/hgk "$(CURDIR)"/debian/mercurial/usr/share/mercurial | |
|
38 | mkdir -p "$(CURDIR)"/debian/mercurial/etc/mercurial/hgrc.d/ | |
|
39 | cp contrib/packaging/debian/*.rc "$(CURDIR)"/debian/mercurial/etc/mercurial/hgrc.d/ | |
|
39 | 40 | # completions |
|
40 |
mkdir -p "$(CURDIR)"/debian/mercurial |
|
|
41 |
cp contrib/bash_completion "$(CURDIR)"/debian/mercurial |
|
|
42 |
mkdir -p "$(CURDIR)"/debian/mercurial |
|
|
43 |
cp contrib/zsh_completion "$(CURDIR)"/debian/mercurial |
|
|
44 | rm "$(CURDIR)"/debian/mercurial-common/usr/bin/hg | |
|
41 | mkdir -p "$(CURDIR)"/debian/mercurial/usr/share/bash-completion/completions | |
|
42 | cp contrib/bash_completion "$(CURDIR)"/debian/mercurial/usr/share/bash-completion/completions/hg | |
|
43 | mkdir -p "$(CURDIR)"/debian/mercurial/usr/share/zsh/vendor-completions | |
|
44 | cp contrib/zsh_completion "$(CURDIR)"/debian/mercurial/usr/share/zsh/vendor-completions/_hg |
@@ -1,4 +1,4 b'' | |||
|
1 |
FROM fedora: |
|
|
1 | FROM fedora:%OS_RELEASE% | |
|
2 | 2 | |
|
3 | 3 | RUN groupadd -g 1000 build && \ |
|
4 | 4 | useradd -u 1000 -g 1000 -s /bin/bash -d /build -m build |
@@ -7,8 +7,8 b' RUN dnf install -y \\' | |||
|
7 | 7 | gcc \ |
|
8 | 8 | gettext \ |
|
9 | 9 | make \ |
|
10 | python-devel \ | |
|
11 | python-docutils \ | |
|
10 | python3-devel \ | |
|
11 | python3-docutils \ | |
|
12 | 12 | rpm-build |
|
13 | 13 | |
|
14 | 14 | # For creating repo meta data |
@@ -6,6 +6,14 b' export ROOTDIR=$(cd $BUILDDIR/../..; pwd' | |||
|
6 | 6 | PLATFORM="$1" |
|
7 | 7 | shift # extra params are passed to buildrpm |
|
8 | 8 | |
|
9 | DOCKERFILE="$PLATFORM" | |
|
10 | OS_RELEASE="${PLATFORM//[a-z]/}" | |
|
11 | case "$PLATFORM" in | |
|
12 | fedora*) | |
|
13 | DOCKERFILE="${PLATFORM//[0-9]/}.template" | |
|
14 | ;; | |
|
15 | esac | |
|
16 | ||
|
9 | 17 | DOCKER=$($BUILDDIR/hg-docker docker-path) |
|
10 | 18 | |
|
11 | 19 | CONTAINER=hg-docker-$PLATFORM |
@@ -18,9 +26,14 b' else' | |||
|
18 | 26 | DOCKERGID=$(id -g) |
|
19 | 27 | fi |
|
20 | 28 | |
|
21 | $BUILDDIR/hg-docker build --build-arg UID=$DOCKERUID --build-arg GID=$DOCKERGID $BUILDDIR/docker/$PLATFORM $CONTAINER | |
|
29 | $BUILDDIR/hg-docker build \ | |
|
30 | --build-arg UID=$DOCKERUID \ | |
|
31 | --build-arg GID=$DOCKERGID \ | |
|
32 | --build-arg OS_RELEASE=${OS_RELEASE:-latest} \ | |
|
33 | $BUILDDIR/docker/$DOCKERFILE $CONTAINER | |
|
22 | 34 | |
|
23 | 35 | RPMBUILDDIR=$ROOTDIR/packages/$PLATFORM |
|
36 | mkdir -p $RPMBUILDDIR | |
|
24 | 37 | $ROOTDIR/contrib/packaging/buildrpm --rpmbuilddir $RPMBUILDDIR --prepare $* |
|
25 | 38 | |
|
26 | 39 | DSHARED=/mnt/shared |
@@ -2,37 +2,119 b'' | |||
|
2 | 2 | # This file is autogenerated by pip-compile |
|
3 | 3 | # To update, run: |
|
4 | 4 | # |
|
5 |
# pip-compile --generate-hashes contrib/packaging/inno/requirements.txt |
|
|
5 | # pip-compile --generate-hashes --output-file=contrib/packaging/inno/requirements.txt contrib/packaging/inno/requirements.txt.in | |
|
6 | 6 | # |
|
7 |
certifi==201 |
|
|
8 | --hash=sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7 \ | |
|
9 | --hash=sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033 \ | |
|
7 | certifi==2019.9.11 \ | |
|
8 | --hash=sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50 \ | |
|
9 | --hash=sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef \ | |
|
10 | 10 | # via dulwich |
|
11 | configparser==3.7.3 \ | |
|
12 | --hash=sha256:27594cf4fc279f321974061ac69164aaebd2749af962ac8686b20503ac0bcf2d \ | |
|
13 | --hash=sha256:9d51fe0a382f05b6b117c5e601fc219fede4a8c71703324af3f7d883aef476a3 \ | |
|
11 | cffi==1.13.1 \ | |
|
12 | --hash=sha256:00d890313797d9fe4420506613384b43099ad7d2b905c0752dbcc3a6f14d80fa \ | |
|
13 | --hash=sha256:0cf9e550ac6c5e57b713437e2f4ac2d7fd0cd10336525a27224f5fc1ec2ee59a \ | |
|
14 | --hash=sha256:0ea23c9c0cdd6778146a50d867d6405693ac3b80a68829966c98dd5e1bbae400 \ | |
|
15 | --hash=sha256:193697c2918ecdb3865acf6557cddf5076bb39f1f654975e087b67efdff83365 \ | |
|
16 | --hash=sha256:1ae14b542bf3b35e5229439c35653d2ef7d8316c1fffb980f9b7647e544baa98 \ | |
|
17 | --hash=sha256:1e389e069450609c6ffa37f21f40cce36f9be7643bbe5051ab1de99d5a779526 \ | |
|
18 | --hash=sha256:263242b6ace7f9cd4ea401428d2d45066b49a700852334fd55311bde36dcda14 \ | |
|
19 | --hash=sha256:33142ae9807665fa6511cfa9857132b2c3ee6ddffb012b3f0933fc11e1e830d5 \ | |
|
20 | --hash=sha256:364f8404034ae1b232335d8c7f7b57deac566f148f7222cef78cf8ae28ef764e \ | |
|
21 | --hash=sha256:47368f69fe6529f8f49a5d146ddee713fc9057e31d61e8b6dc86a6a5e38cecc1 \ | |
|
22 | --hash=sha256:4895640844f17bec32943995dc8c96989226974dfeb9dd121cc45d36e0d0c434 \ | |
|
23 | --hash=sha256:558b3afef987cf4b17abd849e7bedf64ee12b28175d564d05b628a0f9355599b \ | |
|
24 | --hash=sha256:5ba86e1d80d458b338bda676fd9f9d68cb4e7a03819632969cf6d46b01a26730 \ | |
|
25 | --hash=sha256:63424daa6955e6b4c70dc2755897f5be1d719eabe71b2625948b222775ed5c43 \ | |
|
26 | --hash=sha256:6381a7d8b1ebd0bc27c3bc85bc1bfadbb6e6f756b4d4db0aa1425c3719ba26b4 \ | |
|
27 | --hash=sha256:6381ab708158c4e1639da1f2a7679a9bbe3e5a776fc6d1fd808076f0e3145331 \ | |
|
28 | --hash=sha256:6fd58366747debfa5e6163ada468a90788411f10c92597d3b0a912d07e580c36 \ | |
|
29 | --hash=sha256:728ec653964655d65408949b07f9b2219df78badd601d6c49e28d604efe40599 \ | |
|
30 | --hash=sha256:7cfcfda59ef1f95b9f729c56fe8a4041899f96b72685d36ef16a3440a0f85da8 \ | |
|
31 | --hash=sha256:819f8d5197c2684524637f940445c06e003c4a541f9983fd30d6deaa2a5487d8 \ | |
|
32 | --hash=sha256:825ecffd9574557590e3225560a8a9d751f6ffe4a49e3c40918c9969b93395fa \ | |
|
33 | --hash=sha256:9009e917d8f5ef780c2626e29b6bc126f4cb2a4d43ca67aa2b40f2a5d6385e78 \ | |
|
34 | --hash=sha256:9c77564a51d4d914ed5af096cd9843d90c45b784b511723bd46a8a9d09cf16fc \ | |
|
35 | --hash=sha256:a19089fa74ed19c4fe96502a291cfdb89223a9705b1d73b3005df4256976142e \ | |
|
36 | --hash=sha256:a40ed527bffa2b7ebe07acc5a3f782da072e262ca994b4f2085100b5a444bbb2 \ | |
|
37 | --hash=sha256:bb75ba21d5716abc41af16eac1145ab2e471deedde1f22c6f99bd9f995504df0 \ | |
|
38 | --hash=sha256:e22a00c0c81ffcecaf07c2bfb3672fa372c50e2bd1024ffee0da191c1b27fc71 \ | |
|
39 | --hash=sha256:e55b5a746fb77f10c83e8af081979351722f6ea48facea79d470b3731c7b2891 \ | |
|
40 | --hash=sha256:ec2fa3ee81707a5232bf2dfbd6623fdb278e070d596effc7e2d788f2ada71a05 \ | |
|
41 | --hash=sha256:fd82eb4694be712fcae03c717ca2e0fc720657ac226b80bbb597e971fc6928c2 \ | |
|
42 | # via cryptography | |
|
43 | configparser==4.0.2 \ | |
|
44 | --hash=sha256:254c1d9c79f60c45dfde850850883d5aaa7f19a23f13561243a050d5a7c3fe4c \ | |
|
45 | --hash=sha256:c7d282687a5308319bf3d2e7706e575c635b0a470342641c93bea0ea3b5331df \ | |
|
14 | 46 | # via entrypoints |
|
15 | docutils==0.14 \ | |
|
16 | --hash=sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6 \ | |
|
17 | --hash=sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274 \ | |
|
18 | --hash=sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6 | |
|
19 | dulwich==0.19.11 \ | |
|
20 | --hash=sha256:afbe070f6899357e33f63f3f3696e601731fef66c64a489dea1bc9f539f4a725 | |
|
47 | cryptography==2.8 \ | |
|
48 | --hash=sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c \ | |
|
49 | --hash=sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595 \ | |
|
50 | --hash=sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad \ | |
|
51 | --hash=sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651 \ | |
|
52 | --hash=sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2 \ | |
|
53 | --hash=sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff \ | |
|
54 | --hash=sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d \ | |
|
55 | --hash=sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42 \ | |
|
56 | --hash=sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d \ | |
|
57 | --hash=sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e \ | |
|
58 | --hash=sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912 \ | |
|
59 | --hash=sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793 \ | |
|
60 | --hash=sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13 \ | |
|
61 | --hash=sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7 \ | |
|
62 | --hash=sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0 \ | |
|
63 | --hash=sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879 \ | |
|
64 | --hash=sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f \ | |
|
65 | --hash=sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9 \ | |
|
66 | --hash=sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2 \ | |
|
67 | --hash=sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf \ | |
|
68 | --hash=sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8 \ | |
|
69 | # via secretstorage | |
|
70 | docutils==0.15.2 \ | |
|
71 | --hash=sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0 \ | |
|
72 | --hash=sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827 \ | |
|
73 | --hash=sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99 | |
|
74 | dulwich==0.19.13 \ | |
|
75 | --hash=sha256:0e442f6f96e6d97270a7cca4e75306b6b0228627bdf57dde3759e0e345a6b523 \ | |
|
76 | --hash=sha256:667f49536ccba09d3b90bac80d44048e45566f84b98a5e139cc8c70757a6ae60 \ | |
|
77 | --hash=sha256:82792a9d49b112fa2151fa0fb29b01667855a843ff99325b1c1578a4aec11b57 \ | |
|
78 | --hash=sha256:aa628449c5f594a9a282f4d9e5993fef65481ef5e3b9b6c52ff31200f8f5dc95 \ | |
|
79 | --hash=sha256:ab4668bc4e1996d12eb1910e123a09edcff8e166e7ec46db5aafb5c7e250b99f \ | |
|
80 | --hash=sha256:c35ed2cd5b263ce0d67758ffba590c0466ff13b048457ff060b7d2e6cb55a40e \ | |
|
81 | --hash=sha256:c8b48079a14850cbeb788b38e1061ae6db75061431c1c0f91382460be4c84bbe \ | |
|
82 | --hash=sha256:dfcd9943c69f963dd61a027f480d16f548ea5905c2485be8f4b8f130df2c32de \ | |
|
83 | --hash=sha256:e3693c3238c1a5fc1e4427281c4455d78549f4797f2a7107a5f4443b21efafb4 | |
|
21 | 84 | entrypoints==0.3 \ |
|
22 | 85 | --hash=sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19 \ |
|
23 | 86 | --hash=sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451 \ |
|
24 | 87 | # via keyring |
|
88 | enum34==1.1.6 \ | |
|
89 | --hash=sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850 \ | |
|
90 | --hash=sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a \ | |
|
91 | --hash=sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79 \ | |
|
92 | --hash=sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1 \ | |
|
93 | # via cryptography | |
|
94 | ipaddress==1.0.23 \ | |
|
95 | --hash=sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc \ | |
|
96 | --hash=sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2 \ | |
|
97 | # via cryptography | |
|
25 | 98 | keyring==18.0.1 \ |
|
26 | 99 | --hash=sha256:67d6cc0132bd77922725fae9f18366bb314fd8f95ff4d323a4df41890a96a838 \ |
|
27 | 100 | --hash=sha256:7b29ebfcf8678c4da531b2478a912eea01e80007e5ddca9ee0c7038cb3489ec6 |
|
28 | pygments==2.3.1 \ | |
|
29 | --hash=sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a \ | |
|
30 | --hash=sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d | |
|
101 | pycparser==2.19 \ | |
|
102 | --hash=sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3 \ | |
|
103 | # via cffi | |
|
104 | pygments==2.4.2 \ | |
|
105 | --hash=sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127 \ | |
|
106 | --hash=sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297 | |
|
31 | 107 | pywin32-ctypes==0.2.0 \ |
|
32 | 108 | --hash=sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942 \ |
|
33 |
--hash=sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98 |
|
|
109 | --hash=sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98 | |
|
110 | secretstorage==2.3.1 \ | |
|
111 | --hash=sha256:3af65c87765323e6f64c83575b05393f9e003431959c9395d1791d51497f29b6 \ | |
|
34 | 112 | # via keyring |
|
35 |
|
|
|
36 | --hash=sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39 \ | |
|
37 | --hash=sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22 \ | |
|
113 | six==1.12.0 \ | |
|
114 | --hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \ | |
|
115 | --hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73 \ | |
|
116 | # via cryptography | |
|
117 | urllib3==1.25.6 \ | |
|
118 | --hash=sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398 \ | |
|
119 | --hash=sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86 \ | |
|
38 | 120 | # via dulwich |
@@ -2,3 +2,6 b' docutils' | |||
|
2 | 2 | dulwich |
|
3 | 3 | keyring |
|
4 | 4 | pygments |
|
5 | # Need to list explicitly so dependency gets pulled in when | |
|
6 | # not running on Windows. | |
|
7 | pywin32-ctypes |
@@ -2,6 +2,8 b'' | |||
|
2 | 2 | |
|
3 | 3 | %define withpython %{nil} |
|
4 | 4 | |
|
5 | %global pythonexe python3 | |
|
6 | ||
|
5 | 7 | %if "%{?withpython}" |
|
6 | 8 | |
|
7 | 9 | %global pythonver %{withpython} |
@@ -15,7 +17,7 b'' | |||
|
15 | 17 | |
|
16 | 18 | %else |
|
17 | 19 | |
|
18 |
%global pythonver %(python -c 'import sys;print |
|
|
20 | %global pythonver %(%{pythonexe} -c 'import sys;print(".".join(map(str, sys.version_info[:2])))') | |
|
19 | 21 | |
|
20 | 22 | %endif |
|
21 | 23 | |
@@ -37,8 +39,8 b' BuildRequires: make, gcc, gettext' | |||
|
37 | 39 | %if "%{?withpython}" |
|
38 | 40 | BuildRequires: readline-devel, openssl-devel, ncurses-devel, zlib-devel, bzip2-devel |
|
39 | 41 | %else |
|
40 |
BuildRequires: python >= |
|
|
41 |
Requires: python >= |
|
|
42 | BuildRequires: %{pythonexe} >= %{pythonver}, %{pythonexe}-devel, %{pythonexe}-docutils >= 0.5 | |
|
43 | Requires: %{pythonexe} >= %{pythonver} | |
|
42 | 44 | %endif |
|
43 | 45 | # The hgk extension uses the wish tcl interpreter, but we don't enforce it |
|
44 | 46 | #Requires: tk |
@@ -52,13 +54,15 b' for efficient handling of very large dis' | |||
|
52 | 54 | %if "%{?withpython}" |
|
53 | 55 | %setup -q -n mercurial-%{version}-%{release} -a1 -a2 |
|
54 | 56 | # despite the comments in cgi.py, we do this to prevent rpmdeps from picking /usr/local/bin/python up |
|
55 | sed -i '1c#! /usr/bin/env python' %{pythonname}/Lib/cgi.py | |
|
57 | sed -i '1c#! /usr/bin/env %{pythonexe}' %{pythonname}/Lib/cgi.py | |
|
56 | 58 | %else |
|
57 | 59 | %setup -q -n mercurial-%{version}-%{release} |
|
58 | 60 | %endif |
|
59 | 61 | |
|
60 | 62 | %build |
|
61 | 63 | |
|
64 | export HGPYTHON3=1 | |
|
65 | ||
|
62 | 66 | %if "%{?withpython}" |
|
63 | 67 | |
|
64 | 68 | PYPATH=$PWD/%{pythonname} |
@@ -82,12 +86,16 b' export PYTHONPATH=$PWD/%{docutilsname}' | |||
|
82 | 86 | |
|
83 | 87 | %endif |
|
84 | 88 | |
|
85 | make all | |
|
89 | make all PYTHON=%{pythonexe} | |
|
86 | 90 | make -C contrib/chg |
|
87 | 91 | |
|
92 | sed -i -e '1s|#!/usr/bin/env python$|#!/usr/bin/env %{pythonexe}|' contrib/hg-ssh | |
|
93 | ||
|
88 | 94 | %install |
|
89 | 95 | rm -rf $RPM_BUILD_ROOT |
|
90 | 96 | |
|
97 | export HGPYTHON3=1 | |
|
98 | ||
|
91 | 99 | %if "%{?withpython}" |
|
92 | 100 | |
|
93 | 101 | PYPATH=$PWD/%{pythonname} |
@@ -101,14 +109,14 b' cd %{docutilsname}' | |||
|
101 | 109 | LD_LIBRARY_PATH=$PYPATH $PYPATH/python setup.py install --root="$RPM_BUILD_ROOT" |
|
102 | 110 | cd - |
|
103 | 111 | |
|
104 | PATH=$PYPATH:$PATH LD_LIBRARY_PATH=$PYPATH make install DESTDIR=$RPM_BUILD_ROOT PREFIX=%{hgpyprefix} MANDIR=%{_mandir} | |
|
112 | PATH=$PYPATH:$PATH LD_LIBRARY_PATH=$PYPATH make install PYTHON=%{pythonexe} DESTDIR=$RPM_BUILD_ROOT PREFIX=%{hgpyprefix} MANDIR=%{_mandir} | |
|
105 | 113 | mkdir -p $RPM_BUILD_ROOT%{_bindir} |
|
106 | 114 | ( cd $RPM_BUILD_ROOT%{_bindir}/ && ln -s ../..%{hgpyprefix}/bin/hg . ) |
|
107 | 115 | ( cd $RPM_BUILD_ROOT%{_bindir}/ && ln -s ../..%{hgpyprefix}/bin/python2.? %{pythonhg} ) |
|
108 | 116 | |
|
109 | 117 | %else |
|
110 | 118 | |
|
111 | make install DESTDIR=$RPM_BUILD_ROOT PREFIX=%{_prefix} MANDIR=%{_mandir} | |
|
119 | make install PYTHON=%{pythonexe} DESTDIR=$RPM_BUILD_ROOT PREFIX=%{_prefix} MANDIR=%{_mandir} | |
|
112 | 120 | |
|
113 | 121 | %endif |
|
114 | 122 | |
@@ -135,7 +143,7 b' rm -rf $RPM_BUILD_ROOT' | |||
|
135 | 143 | |
|
136 | 144 | %files |
|
137 | 145 | %defattr(-,root,root,-) |
|
138 | %doc CONTRIBUTORS COPYING doc/README doc/hg*.txt doc/hg*.html *.cgi contrib/*.fcgi | |
|
146 | %doc CONTRIBUTORS COPYING doc/README doc/hg*.txt doc/hg*.html *.cgi contrib/*.fcgi contrib/*.wsgi | |
|
139 | 147 | %doc %attr(644,root,root) %{_mandir}/man?/hg* |
|
140 | 148 | %doc %attr(644,root,root) contrib/*.svg |
|
141 | 149 | %dir %{_datadir}/zsh/ |
@@ -2,12 +2,12 b'' | |||
|
2 | 2 | # This file is autogenerated by pip-compile |
|
3 | 3 | # To update, run: |
|
4 | 4 | # |
|
5 |
# pip-compile --generate-hashes contrib/packaging/wix/requirements.txt |
|
|
5 | # pip-compile --generate-hashes --output-file=contrib/packaging/wix/requirements.txt contrib/packaging/wix/requirements.txt.in | |
|
6 | 6 | # |
|
7 |
docutils==0.1 |
|
|
8 | --hash=sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6 \ | |
|
9 | --hash=sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274 \ | |
|
10 | --hash=sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6 | |
|
11 |
pygments==2. |
|
|
12 | --hash=sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a \ | |
|
13 | --hash=sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d | |
|
7 | docutils==0.15.2 \ | |
|
8 | --hash=sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0 \ | |
|
9 | --hash=sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827 \ | |
|
10 | --hash=sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99 | |
|
11 | pygments==2.4.2 \ | |
|
12 | --hash=sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127 \ | |
|
13 | --hash=sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297 |
@@ -18,6 +18,7 b' from mercurial import (' | |||
|
18 | 18 | ) |
|
19 | 19 | from mercurial.utils import ( |
|
20 | 20 | procutil, |
|
21 | stringutil | |
|
21 | 22 | ) |
|
22 | 23 | |
|
23 | 24 | options = [(b'L', b'label', [], _(b'labels to use on conflict markers')), |
@@ -75,8 +76,7 b' try:' | |||
|
75 | 76 | context.arbitraryfilectx(other), |
|
76 | 77 | **pycompat.strkwargs(opts))) |
|
77 | 78 | except ParseError as e: |
|
78 | if pycompat.ispy3: | |
|
79 | e = str(e).encode('utf8') | |
|
79 | e = stringutil.forcebytestr(e) | |
|
80 | 80 | pycompat.stdout.write(b"%s: %s\n" % (sys.argv[0].encode('utf8'), e)) |
|
81 | 81 | showhelp() |
|
82 | 82 | sys.exit(1) |
@@ -53,9 +53,13 b' class _lazyloaderex(importlib.util.LazyL' | |||
|
53 | 53 | |
|
54 | 54 | # This is 3.6+ because with Python 3.5 it isn't possible to lazily load |
|
55 | 55 | # extensions. See the discussion in https://bugs.python.org/issue26186 for more. |
|
56 | if sys.version_info[0:2] >= (3, 6): | |
|
56 | 57 | _extensions_loader = _lazyloaderex.factory( |
|
57 | 58 | importlib.machinery.ExtensionFileLoader |
|
58 | 59 | ) |
|
60 | else: | |
|
61 | _extensions_loader = importlib.machinery.ExtensionFileLoader | |
|
62 | ||
|
59 | 63 | _bytecode_loader = _lazyloaderex.factory( |
|
60 | 64 | importlib.machinery.SourcelessFileLoader |
|
61 | 65 | ) |
@@ -955,7 +955,7 b' class bzrestapi(bzaccess):' | |||
|
955 | 955 | def _fetch(self, burl): |
|
956 | 956 | try: |
|
957 | 957 | resp = url.open(self.ui, burl) |
|
958 |
return |
|
|
958 | return pycompat.json_loads(resp.read()) | |
|
959 | 959 | except util.urlerr.httperror as inst: |
|
960 | 960 | if inst.code == 401: |
|
961 | 961 | raise error.Abort(_(b'authorization failed')) |
@@ -978,7 +978,7 b' class bzrestapi(bzaccess):' | |||
|
978 | 978 | req = request_type(burl, data, {b'Content-Type': b'application/json'}) |
|
979 | 979 | try: |
|
980 | 980 | resp = url.opener(self.ui).open(req) |
|
981 |
return |
|
|
981 | return pycompat.json_loads(resp.read()) | |
|
982 | 982 | except util.urlerr.httperror as inst: |
|
983 | 983 | if inst.code == 401: |
|
984 | 984 | raise error.Abort(_(b'authorization failed')) |
@@ -7,7 +7,6 b'' | |||
|
7 | 7 | # GNU General Public License version 2 or any later version. |
|
8 | 8 | from __future__ import absolute_import |
|
9 | 9 | |
|
10 | import email.parser as emailparser | |
|
11 | 10 | import os |
|
12 | 11 | import shutil |
|
13 | 12 | import stat |
@@ -17,6 +16,7 b' from mercurial.i18n import _' | |||
|
17 | 16 | from mercurial import ( |
|
18 | 17 | encoding, |
|
19 | 18 | error, |
|
19 | mail, | |
|
20 | 20 | pycompat, |
|
21 | 21 | util, |
|
22 | 22 | ) |
@@ -69,7 +69,6 b' class gnuarch_source(common.converter_so' | |||
|
69 | 69 | self.changes = {} |
|
70 | 70 | self.parents = {} |
|
71 | 71 | self.tags = {} |
|
72 | self.catlogparser = emailparser.Parser() | |
|
73 | 72 | self.encoding = encoding.encoding |
|
74 | 73 | self.archives = [] |
|
75 | 74 | |
@@ -299,26 +298,29 b' class gnuarch_source(common.converter_so' | |||
|
299 | 298 | |
|
300 | 299 | def _parsecatlog(self, data, rev): |
|
301 | 300 | try: |
|
302 |
catlog = |
|
|
301 | catlog = mail.parsebytes(data) | |
|
303 | 302 | |
|
304 | 303 | # Commit date |
|
305 | 304 | self.changes[rev].date = dateutil.datestr( |
|
306 |
dateutil.strdate(catlog[ |
|
|
305 | dateutil.strdate(catlog[r'Standard-date'], b'%Y-%m-%d %H:%M:%S') | |
|
307 | 306 | ) |
|
308 | 307 | |
|
309 | 308 | # Commit author |
|
310 |
self.changes[rev].author = self.recode(catlog[ |
|
|
309 | self.changes[rev].author = self.recode(catlog[r'Creator']) | |
|
311 | 310 | |
|
312 | 311 | # Commit description |
|
313 | 312 | self.changes[rev].summary = b'\n\n'.join( |
|
314 | (catlog[b'Summary'], catlog.get_payload()) | |
|
313 | ( | |
|
314 | self.recode(catlog[r'Summary']), | |
|
315 | self.recode(catlog.get_payload()), | |
|
316 | ) | |
|
315 | 317 | ) |
|
316 | 318 | self.changes[rev].summary = self.recode(self.changes[rev].summary) |
|
317 | 319 | |
|
318 | 320 | # Commit revision origin when dealing with a branch or tag |
|
319 |
if |
|
|
321 | if r'Continuation-of' in catlog: | |
|
320 | 322 | self.changes[rev].continuationof = self.recode( |
|
321 |
catlog[ |
|
|
323 | catlog[r'Continuation-of'] | |
|
322 | 324 | ) |
|
323 | 325 | except Exception: |
|
324 | 326 | raise error.Abort(_(b'could not parse cat-log of %s') % rev) |
@@ -126,7 +126,6 b' from __future__ import absolute_import' | |||
|
126 | 126 | |
|
127 | 127 | import collections |
|
128 | 128 | import itertools |
|
129 | import json | |
|
130 | 129 | import os |
|
131 | 130 | import re |
|
132 | 131 | import subprocess |
@@ -642,7 +641,7 b' def fixfile(ui, repo, opts, fixers, fixc' | |||
|
642 | 641 | if fixer.shouldoutputmetadata(): |
|
643 | 642 | try: |
|
644 | 643 | metadatajson, newerdata = stdout.split(b'\0', 1) |
|
645 |
metadata[fixername] = |
|
|
644 | metadata[fixername] = pycompat.json_loads(metadatajson) | |
|
646 | 645 | except ValueError: |
|
647 | 646 | ui.warn( |
|
648 | 647 | _(b'ignored invalid output from fixer tool: %s\n') |
@@ -132,6 +132,7 b' from mercurial import (' | |||
|
132 | 132 | util, |
|
133 | 133 | ) |
|
134 | 134 | from mercurial import match as matchmod |
|
135 | from mercurial.utils import stringutil | |
|
135 | 136 | |
|
136 | 137 | from . import ( |
|
137 | 138 | pywatchman, |
@@ -189,10 +190,10 b' def debuginstall(ui, fm):' | |||
|
189 | 190 | fm.write( |
|
190 | 191 | b"fsmonitor-watchman-version", |
|
191 | 192 | _(b" watchman binary version %s\n"), |
|
192 |
v[ |
|
|
193 | pycompat.bytestr(v["version"]), | |
|
193 | 194 | ) |
|
194 | 195 | except watchmanclient.Unavailable as e: |
|
195 | err = str(e) | |
|
196 | err = stringutil.forcebytestr(e) | |
|
196 | 197 | fm.condwrite( |
|
197 | 198 | err, |
|
198 | 199 | b"fsmonitor-watchman-error", |
@@ -207,15 +208,23 b' def _handleunavailable(ui, state, ex):' | |||
|
207 | 208 | if isinstance(ex, watchmanclient.Unavailable): |
|
208 | 209 | # experimental config: fsmonitor.verbose |
|
209 | 210 | if ex.warn and ui.configbool(b'fsmonitor', b'verbose'): |
|
210 | if b'illegal_fstypes' not in str(ex): | |
|
211 | ui.warn(str(ex) + b'\n') | |
|
211 | if b'illegal_fstypes' not in stringutil.forcebytestr(ex): | |
|
212 | ui.warn(stringutil.forcebytestr(ex) + b'\n') | |
|
212 | 213 | if ex.invalidate: |
|
213 | 214 | state.invalidate() |
|
214 | 215 | # experimental config: fsmonitor.verbose |
|
215 | 216 | if ui.configbool(b'fsmonitor', b'verbose'): |
|
216 | ui.log(b'fsmonitor', b'Watchman unavailable: %s\n', ex.msg) | |
|
217 | ui.log( | |
|
218 | b'fsmonitor', | |
|
219 | b'Watchman unavailable: %s\n', | |
|
220 | stringutil.forcebytestr(ex.msg), | |
|
221 | ) | |
|
217 | 222 | else: |
|
218 | ui.log(b'fsmonitor', b'Watchman exception: %s\n', ex) | |
|
223 | ui.log( | |
|
224 | b'fsmonitor', | |
|
225 | b'Watchman exception: %s\n', | |
|
226 | stringutil.forcebytestr(ex), | |
|
227 | ) | |
|
219 | 228 | |
|
220 | 229 | |
|
221 | 230 | def _hashignore(ignore): |
@@ -227,8 +236,8 b' def _hashignore(ignore):' | |||
|
227 | 236 | |
|
228 | 237 | """ |
|
229 | 238 | sha1 = hashlib.sha1() |
|
230 | sha1.update(repr(ignore)) | |
|
231 | return sha1.hexdigest() | |
|
239 | sha1.update(pycompat.byterepr(ignore)) | |
|
240 | return pycompat.sysbytes(sha1.hexdigest()) | |
|
232 | 241 | |
|
233 | 242 | |
|
234 | 243 | _watchmanencoding = pywatchman.encoding.get_local_encoding() |
@@ -245,12 +254,14 b' def _watchmantofsencoding(path):' | |||
|
245 | 254 | try: |
|
246 | 255 | decoded = path.decode(_watchmanencoding) |
|
247 | 256 | except UnicodeDecodeError as e: |
|
248 | raise error.Abort(str(e), hint=b'watchman encoding error') | |
|
257 | raise error.Abort( | |
|
258 | stringutil.forcebytestr(e), hint=b'watchman encoding error' | |
|
259 | ) | |
|
249 | 260 | |
|
250 | 261 | try: |
|
251 | 262 | encoded = decoded.encode(_fsencoding, 'strict') |
|
252 | 263 | except UnicodeEncodeError as e: |
|
253 | raise error.Abort(str(e)) | |
|
264 | raise error.Abort(stringutil.forcebytestr(e)) | |
|
254 | 265 | |
|
255 | 266 | return encoded |
|
256 | 267 | |
@@ -372,7 +383,7 b' def overridewalk(orig, self, match, subr' | |||
|
372 | 383 | else: |
|
373 | 384 | # We need to propagate the last observed clock up so that we |
|
374 | 385 | # can use it for our next query |
|
375 | state.setlastclock(result[b'clock']) | |
|
386 | state.setlastclock(pycompat.sysbytes(result[b'clock'])) | |
|
376 | 387 | if result[b'is_fresh_instance']: |
|
377 | 388 | if state.walk_on_invalidate: |
|
378 | 389 | state.invalidate() |
@@ -396,8 +407,15 b' def overridewalk(orig, self, match, subr' | |||
|
396 | 407 | # for name case changes. |
|
397 | 408 | for entry in result[b'files']: |
|
398 | 409 | fname = entry[b'name'] |
|
410 | ||
|
411 | # Watchman always give us a str. Normalize to bytes on Python 3 | |
|
412 | # using Watchman's encoding, if needed. | |
|
413 | if not isinstance(fname, bytes): | |
|
414 | fname = fname.encode(_watchmanencoding) | |
|
415 | ||
|
399 | 416 | if _fixencoding: |
|
400 | 417 | fname = _watchmantofsencoding(fname) |
|
418 | ||
|
401 | 419 | if switch_slashes: |
|
402 | 420 | fname = fname.replace(b'\\', b'/') |
|
403 | 421 | if normalize: |
@@ -486,9 +504,9 b' def overridewalk(orig, self, match, subr' | |||
|
486 | 504 | for f in auditfail: |
|
487 | 505 | results[f] = None |
|
488 | 506 | |
|
489 |
nf = iter(auditpass) |
|
|
507 | nf = iter(auditpass) | |
|
490 | 508 | for st in util.statfiles([join(f) for f in auditpass]): |
|
491 |
f = nf |
|
|
509 | f = next(nf) | |
|
492 | 510 | if st or f in dmap: |
|
493 | 511 | results[f] = st |
|
494 | 512 | |
@@ -916,7 +934,7 b' def reposetup(ui, repo):' | |||
|
916 | 934 | return |
|
917 | 935 | |
|
918 | 936 | try: |
|
919 |
client = watchmanclient.client(repo.ui, repo. |
|
|
937 | client = watchmanclient.client(repo.ui, repo.root) | |
|
920 | 938 | except Exception as ex: |
|
921 | 939 | _handleunavailable(ui, fsmonitorstate, ex) |
|
922 | 940 | return |
This diff has been collapsed as it changes many lines, (580 lines changed) Show them Hide them | |||
@@ -26,10 +26,8 b'' | |||
|
26 | 26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
27 | 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
28 | 28 | |
|
29 | from __future__ import absolute_import | |
|
30 | from __future__ import division | |
|
31 | from __future__ import print_function | |
|
32 | 29 | # no unicode literals |
|
30 | from __future__ import absolute_import, division, print_function | |
|
33 | 31 | |
|
34 | 32 | import inspect |
|
35 | 33 | import math |
@@ -38,33 +36,22 b' import socket' | |||
|
38 | 36 | import subprocess |
|
39 | 37 | import time |
|
40 | 38 | |
|
39 | from . import capabilities, compat, encoding, load | |
|
40 | ||
|
41 | ||
|
41 | 42 | # Sometimes it's really hard to get Python extensions to compile, |
|
42 | 43 | # so fall back to a pure Python implementation. |
|
43 | 44 | try: |
|
44 | 45 | from . import bser |
|
46 | ||
|
45 | 47 | # Demandimport causes modules to be loaded lazily. Force the load now |
|
46 | 48 | # so that we can fall back on pybser if bser doesn't exist |
|
47 | 49 | bser.pdu_info |
|
48 | 50 | except ImportError: |
|
49 | 51 | from . import pybser as bser |
|
50 | 52 | |
|
51 | from mercurial.utils import ( | |
|
52 | procutil, | |
|
53 | ) | |
|
54 | 53 | |
|
55 | from mercurial import ( | |
|
56 | pycompat, | |
|
57 | ) | |
|
58 | ||
|
59 | from . import ( | |
|
60 | capabilities, | |
|
61 | compat, | |
|
62 | encoding, | |
|
63 | load, | |
|
64 | ) | |
|
65 | ||
|
66 | ||
|
67 | if os.name == 'nt': | |
|
54 | if os.name == "nt": | |
|
68 | 55 | import ctypes |
|
69 | 56 | import ctypes.wintypes |
|
70 | 57 | |
@@ -73,7 +60,7 b" if os.name == 'nt':" | |||
|
73 | 60 | GENERIC_WRITE = 0x40000000 |
|
74 | 61 | FILE_FLAG_OVERLAPPED = 0x40000000 |
|
75 | 62 | OPEN_EXISTING = 3 |
|
76 | INVALID_HANDLE_VALUE = -1 | |
|
63 | INVALID_HANDLE_VALUE = ctypes.c_void_p(-1).value | |
|
77 | 64 | FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000 |
|
78 | 65 | FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100 |
|
79 | 66 | FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200 |
@@ -92,9 +79,11 b" if os.name == 'nt':" | |||
|
92 | 79 | |
|
93 | 80 | class OVERLAPPED(ctypes.Structure): |
|
94 | 81 | _fields_ = [ |
|
95 |
("Internal", ULONG_PTR), |
|
|
96 | ("Offset", wintypes.DWORD), ("OffsetHigh", wintypes.DWORD), | |
|
97 |
(" |
|
|
82 | ("Internal", ULONG_PTR), | |
|
83 | ("InternalHigh", ULONG_PTR), | |
|
84 | ("Offset", wintypes.DWORD), | |
|
85 | ("OffsetHigh", wintypes.DWORD), | |
|
86 | ("hEvent", wintypes.HANDLE), | |
|
98 | 87 | ] |
|
99 | 88 | |
|
100 | 89 | def __init__(self): |
@@ -107,9 +96,15 b" if os.name == 'nt':" | |||
|
107 | 96 | LPDWORD = ctypes.POINTER(wintypes.DWORD) |
|
108 | 97 | |
|
109 | 98 | CreateFile = ctypes.windll.kernel32.CreateFileA |
|
110 | CreateFile.argtypes = [wintypes.LPSTR, wintypes.DWORD, wintypes.DWORD, | |
|
111 | wintypes.LPVOID, wintypes.DWORD, wintypes.DWORD, | |
|
112 | wintypes.HANDLE] | |
|
99 | CreateFile.argtypes = [ | |
|
100 | wintypes.LPSTR, | |
|
101 | wintypes.DWORD, | |
|
102 | wintypes.DWORD, | |
|
103 | wintypes.LPVOID, | |
|
104 | wintypes.DWORD, | |
|
105 | wintypes.DWORD, | |
|
106 | wintypes.HANDLE, | |
|
107 | ] | |
|
113 | 108 | CreateFile.restype = wintypes.HANDLE |
|
114 | 109 | |
|
115 | 110 | CloseHandle = ctypes.windll.kernel32.CloseHandle |
@@ -117,13 +112,23 b" if os.name == 'nt':" | |||
|
117 | 112 | CloseHandle.restype = wintypes.BOOL |
|
118 | 113 | |
|
119 | 114 | ReadFile = ctypes.windll.kernel32.ReadFile |
|
120 | ReadFile.argtypes = [wintypes.HANDLE, wintypes.LPVOID, wintypes.DWORD, | |
|
121 | LPDWORD, ctypes.POINTER(OVERLAPPED)] | |
|
115 | ReadFile.argtypes = [ | |
|
116 | wintypes.HANDLE, | |
|
117 | wintypes.LPVOID, | |
|
118 | wintypes.DWORD, | |
|
119 | LPDWORD, | |
|
120 | ctypes.POINTER(OVERLAPPED), | |
|
121 | ] | |
|
122 | 122 | ReadFile.restype = wintypes.BOOL |
|
123 | 123 | |
|
124 | 124 | WriteFile = ctypes.windll.kernel32.WriteFile |
|
125 | WriteFile.argtypes = [wintypes.HANDLE, wintypes.LPVOID, wintypes.DWORD, | |
|
126 | LPDWORD, ctypes.POINTER(OVERLAPPED)] | |
|
125 | WriteFile.argtypes = [ | |
|
126 | wintypes.HANDLE, | |
|
127 | wintypes.LPVOID, | |
|
128 | wintypes.DWORD, | |
|
129 | LPDWORD, | |
|
130 | ctypes.POINTER(OVERLAPPED), | |
|
131 | ] | |
|
127 | 132 | WriteFile.restype = wintypes.BOOL |
|
128 | 133 | |
|
129 | 134 | GetLastError = ctypes.windll.kernel32.GetLastError |
@@ -135,34 +140,56 b" if os.name == 'nt':" | |||
|
135 | 140 | SetLastError.restype = None |
|
136 | 141 | |
|
137 | 142 | FormatMessage = ctypes.windll.kernel32.FormatMessageA |
|
138 | FormatMessage.argtypes = [wintypes.DWORD, wintypes.LPVOID, wintypes.DWORD, | |
|
139 | wintypes.DWORD, ctypes.POINTER(wintypes.LPSTR), | |
|
140 | wintypes.DWORD, wintypes.LPVOID] | |
|
143 | FormatMessage.argtypes = [ | |
|
144 | wintypes.DWORD, | |
|
145 | wintypes.LPVOID, | |
|
146 | wintypes.DWORD, | |
|
147 | wintypes.DWORD, | |
|
148 | ctypes.POINTER(wintypes.LPSTR), | |
|
149 | wintypes.DWORD, | |
|
150 | wintypes.LPVOID, | |
|
151 | ] | |
|
141 | 152 | FormatMessage.restype = wintypes.DWORD |
|
142 | 153 | |
|
143 | 154 | LocalFree = ctypes.windll.kernel32.LocalFree |
|
144 | 155 | |
|
145 | 156 | GetOverlappedResult = ctypes.windll.kernel32.GetOverlappedResult |
|
146 |
GetOverlappedResult.argtypes = [ |
|
|
147 | ctypes.POINTER(OVERLAPPED), LPDWORD, | |
|
148 | wintypes.BOOL] | |
|
157 | GetOverlappedResult.argtypes = [ | |
|
158 | wintypes.HANDLE, | |
|
159 | ctypes.POINTER(OVERLAPPED), | |
|
160 | LPDWORD, | |
|
161 | wintypes.BOOL, | |
|
162 | ] | |
|
149 | 163 | GetOverlappedResult.restype = wintypes.BOOL |
|
150 | 164 | |
|
151 |
GetOverlappedResultEx = getattr( |
|
|
152 | 'GetOverlappedResultEx', None) | |
|
165 | GetOverlappedResultEx = getattr( | |
|
166 | ctypes.windll.kernel32, "GetOverlappedResultEx", None | |
|
167 | ) | |
|
153 | 168 | if GetOverlappedResultEx is not None: |
|
154 |
GetOverlappedResultEx.argtypes = [ |
|
|
155 | ctypes.POINTER(OVERLAPPED), LPDWORD, | |
|
156 | wintypes.DWORD, wintypes.BOOL] | |
|
169 | GetOverlappedResultEx.argtypes = [ | |
|
170 | wintypes.HANDLE, | |
|
171 | ctypes.POINTER(OVERLAPPED), | |
|
172 | LPDWORD, | |
|
173 | wintypes.DWORD, | |
|
174 | wintypes.BOOL, | |
|
175 | ] | |
|
157 | 176 | GetOverlappedResultEx.restype = wintypes.BOOL |
|
158 | 177 | |
|
159 | 178 | WaitForSingleObjectEx = ctypes.windll.kernel32.WaitForSingleObjectEx |
|
160 |
WaitForSingleObjectEx.argtypes = [ |
|
|
179 | WaitForSingleObjectEx.argtypes = [ | |
|
180 | wintypes.HANDLE, | |
|
181 | wintypes.DWORD, | |
|
182 | wintypes.BOOL, | |
|
183 | ] | |
|
161 | 184 | WaitForSingleObjectEx.restype = wintypes.DWORD |
|
162 | 185 | |
|
163 | 186 | CreateEvent = ctypes.windll.kernel32.CreateEventA |
|
164 | CreateEvent.argtypes = [LPDWORD, wintypes.BOOL, wintypes.BOOL, | |
|
165 | wintypes.LPSTR] | |
|
187 | CreateEvent.argtypes = [ | |
|
188 | LPDWORD, | |
|
189 | wintypes.BOOL, | |
|
190 | wintypes.BOOL, | |
|
191 | wintypes.LPSTR, | |
|
192 | ] | |
|
166 | 193 | CreateEvent.restype = wintypes.HANDLE |
|
167 | 194 | |
|
168 | 195 | # Windows Vista is the minimum supported client for CancelIoEx. |
@@ -178,9 +205,15 b' sniff_len = 13' | |||
|
178 | 205 | if _debugging: |
|
179 | 206 | |
|
180 | 207 | def log(fmt, *args): |
|
181 |
print( |
|
|
182 | (time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime()), | |
|
183 |
|
|
|
208 | print( | |
|
209 | "[%s] %s" | |
|
210 | % ( | |
|
211 | time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime()), | |
|
212 | fmt % args[:], | |
|
213 | ) | |
|
214 | ) | |
|
215 | ||
|
216 | ||
|
184 | 217 | else: |
|
185 | 218 | |
|
186 | 219 | def log(fmt, *args): |
@@ -193,8 +226,16 b' def _win32_strerror(err):' | |||
|
193 | 226 | # FormatMessage will allocate memory and assign it here |
|
194 | 227 | buf = ctypes.c_char_p() |
|
195 | 228 | FormatMessage( |
|
196 |
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
197 | | FORMAT_MESSAGE_IGNORE_INSERTS, None, err, 0, buf, 0, None) | |
|
229 | FORMAT_MESSAGE_FROM_SYSTEM | |
|
230 | | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
|
231 | | FORMAT_MESSAGE_IGNORE_INSERTS, | |
|
232 | None, | |
|
233 | err, | |
|
234 | 0, | |
|
235 | buf, | |
|
236 | 0, | |
|
237 | None, | |
|
238 | ) | |
|
198 | 239 | try: |
|
199 | 240 | return buf.value |
|
200 | 241 | finally: |
@@ -211,21 +252,30 b' class WatchmanError(Exception):' | |||
|
211 | 252 | |
|
212 | 253 | def __str__(self): |
|
213 | 254 | if self.cmd: |
|
214 |
return |
|
|
255 | return "%s, while executing %s" % (self.msg, self.cmd) | |
|
215 | 256 | return self.msg |
|
216 | 257 | |
|
217 | 258 | |
|
259 | class BSERv1Unsupported(WatchmanError): | |
|
260 | pass | |
|
261 | ||
|
262 | ||
|
263 | class UseAfterFork(WatchmanError): | |
|
264 | pass | |
|
265 | ||
|
266 | ||
|
218 | 267 | class WatchmanEnvironmentError(WatchmanError): |
|
219 | 268 | def __init__(self, msg, errno, errmsg, cmd=None): |
|
220 | 269 | super(WatchmanEnvironmentError, self).__init__( |
|
221 |
|
|
|
222 |
|
|
|
270 | "{0}: errno={1} errmsg={2}".format(msg, errno, errmsg), cmd | |
|
271 | ) | |
|
223 | 272 | |
|
224 | 273 | |
|
225 | 274 | class SocketConnectError(WatchmanError): |
|
226 | 275 | def __init__(self, sockpath, exc): |
|
227 | 276 | super(SocketConnectError, self).__init__( |
|
228 |
|
|
|
277 | "unable to connect to %s: %s" % (sockpath, exc) | |
|
278 | ) | |
|
229 | 279 | self.sockpath = sockpath |
|
230 | 280 | self.exc = exc |
|
231 | 281 | |
@@ -245,15 +295,16 b' class CommandError(WatchmanError):' | |||
|
245 | 295 | |
|
246 | 296 | self.msg is the message returned by watchman. |
|
247 | 297 | """ |
|
298 | ||
|
248 | 299 | def __init__(self, msg, cmd=None): |
|
249 | 300 | super(CommandError, self).__init__( |
|
250 |
|
|
|
251 | cmd, | |
|
301 | "watchman command error: %s" % (msg,), cmd | |
|
252 | 302 | ) |
|
253 | 303 | |
|
254 | 304 | |
|
255 | 305 | class Transport(object): |
|
256 | 306 | """ communication transport to the watchman server """ |
|
307 | ||
|
257 | 308 | buf = None |
|
258 | 309 | |
|
259 | 310 | def close(self): |
@@ -289,7 +340,7 b' class Transport(object):' | |||
|
289 | 340 | while True: |
|
290 | 341 | b = self.readBytes(4096) |
|
291 | 342 | if b"\n" in b: |
|
292 |
result = b |
|
|
343 | result = b"".join(self.buf) | |
|
293 | 344 | (line, b) = b.split(b"\n", 1) |
|
294 | 345 | self.buf = [b] |
|
295 | 346 | return result + line |
@@ -298,6 +349,7 b' class Transport(object):' | |||
|
298 | 349 | |
|
299 | 350 | class Codec(object): |
|
300 | 351 | """ communication encoding for the watchman server """ |
|
352 | ||
|
301 | 353 | transport = None |
|
302 | 354 | |
|
303 | 355 | def __init__(self, transport): |
@@ -315,9 +367,10 b' class Codec(object):' | |||
|
315 | 367 | |
|
316 | 368 | class UnixSocketTransport(Transport): |
|
317 | 369 | """ local unix domain socket transport """ |
|
370 | ||
|
318 | 371 | sock = None |
|
319 | 372 | |
|
320 |
def __init__(self, sockpath, timeout |
|
|
373 | def __init__(self, sockpath, timeout): | |
|
321 | 374 | self.sockpath = sockpath |
|
322 | 375 | self.timeout = timeout |
|
323 | 376 | |
@@ -331,6 +384,7 b' class UnixSocketTransport(Transport):' | |||
|
331 | 384 | raise SocketConnectError(self.sockpath, e) |
|
332 | 385 | |
|
333 | 386 | def close(self): |
|
387 | if self.sock: | |
|
334 | 388 | self.sock.close() |
|
335 | 389 | self.sock = None |
|
336 | 390 | |
@@ -342,16 +396,16 b' class UnixSocketTransport(Transport):' | |||
|
342 | 396 | try: |
|
343 | 397 | buf = [self.sock.recv(size)] |
|
344 | 398 | if not buf[0]: |
|
345 |
raise WatchmanError( |
|
|
399 | raise WatchmanError("empty watchman response") | |
|
346 | 400 | return buf[0] |
|
347 | 401 | except socket.timeout: |
|
348 |
raise SocketTimeout( |
|
|
402 | raise SocketTimeout("timed out waiting for response") | |
|
349 | 403 | |
|
350 | 404 | def write(self, data): |
|
351 | 405 | try: |
|
352 | 406 | self.sock.sendall(data) |
|
353 | 407 | except socket.timeout: |
|
354 |
raise SocketTimeout( |
|
|
408 | raise SocketTimeout("timed out sending query command") | |
|
355 | 409 | |
|
356 | 410 | |
|
357 | 411 | def _get_overlapped_result_ex_impl(pipe, olap, nbytes, millis, alertable): |
@@ -364,7 +418,7 b' def _get_overlapped_result_ex_impl(pipe,' | |||
|
364 | 418 | source code (see get_overlapped_result_ex_impl in stream_win.c). This |
|
365 | 419 | way, maintenance should be simplified. |
|
366 | 420 | """ |
|
367 |
log( |
|
|
421 | log("Preparing to wait for maximum %dms", millis) | |
|
368 | 422 | if millis != 0: |
|
369 | 423 | waitReturnCode = WaitForSingleObjectEx(olap.hEvent, millis, alertable) |
|
370 | 424 | if waitReturnCode == WAIT_OBJECT_0: |
@@ -383,12 +437,12 b' def _get_overlapped_result_ex_impl(pipe,' | |||
|
383 | 437 | elif waitReturnCode == WAIT_FAILED: |
|
384 | 438 | # something went wrong calling WaitForSingleObjectEx |
|
385 | 439 | err = GetLastError() |
|
386 |
log( |
|
|
440 | log("WaitForSingleObjectEx failed: %s", _win32_strerror(err)) | |
|
387 | 441 | return False |
|
388 | 442 | else: |
|
389 | 443 | # unexpected situation deserving investigation. |
|
390 | 444 | err = GetLastError() |
|
391 |
log( |
|
|
445 | log("Unexpected error: %s", _win32_strerror(err)) | |
|
392 | 446 | return False |
|
393 | 447 | |
|
394 | 448 | return GetOverlappedResult(pipe, olap, nbytes, False) |
@@ -397,36 +451,52 b' def _get_overlapped_result_ex_impl(pipe,' | |||
|
397 | 451 | class WindowsNamedPipeTransport(Transport): |
|
398 | 452 | """ connect to a named pipe """ |
|
399 | 453 | |
|
400 |
def __init__(self, sockpath, timeout |
|
|
454 | def __init__(self, sockpath, timeout): | |
|
401 | 455 | self.sockpath = sockpath |
|
402 | 456 | self.timeout = int(math.ceil(timeout * 1000)) |
|
403 | 457 | self._iobuf = None |
|
404 | 458 | |
|
405 | self.pipe = CreateFile(sockpath, GENERIC_READ | GENERIC_WRITE, 0, None, | |
|
406 | OPEN_EXISTING, FILE_FLAG_OVERLAPPED, None) | |
|
459 | if compat.PYTHON3: | |
|
460 | sockpath = os.fsencode(sockpath) | |
|
461 | self.pipe = CreateFile( | |
|
462 | sockpath, | |
|
463 | GENERIC_READ | GENERIC_WRITE, | |
|
464 | 0, | |
|
465 | None, | |
|
466 | OPEN_EXISTING, | |
|
467 | FILE_FLAG_OVERLAPPED, | |
|
468 | None, | |
|
469 | ) | |
|
407 | 470 | |
|
408 | if self.pipe == INVALID_HANDLE_VALUE: | |
|
471 | err = GetLastError() | |
|
472 | if self.pipe == INVALID_HANDLE_VALUE or self.pipe == 0: | |
|
409 | 473 | self.pipe = None |
|
410 | self._raise_win_err('failed to open pipe %s' % sockpath, | |
|
411 | GetLastError()) | |
|
474 | raise SocketConnectError(self.sockpath, self._make_win_err("", err)) | |
|
412 | 475 | |
|
413 | 476 | # event for the overlapped I/O operations |
|
414 | 477 | self._waitable = CreateEvent(None, True, False, None) |
|
478 | err = GetLastError() | |
|
415 | 479 | if self._waitable is None: |
|
416 |
self._raise_win_err( |
|
|
480 | self._raise_win_err("CreateEvent failed", err) | |
|
417 | 481 | |
|
418 | 482 | self._get_overlapped_result_ex = GetOverlappedResultEx |
|
419 | if (os.getenv('WATCHMAN_WIN7_COMPAT') == '1' or | |
|
420 | self._get_overlapped_result_ex is None): | |
|
483 | if ( | |
|
484 | os.getenv("WATCHMAN_WIN7_COMPAT") == "1" | |
|
485 | or self._get_overlapped_result_ex is None | |
|
486 | ): | |
|
421 | 487 | self._get_overlapped_result_ex = _get_overlapped_result_ex_impl |
|
422 | 488 | |
|
423 | 489 | def _raise_win_err(self, msg, err): |
|
424 | raise IOError('%s win32 error code: %d %s' % | |
|
425 | (msg, err, _win32_strerror(err))) | |
|
490 | raise self._make_win_err(msg, err) | |
|
491 | ||
|
492 | def _make_win_err(self, msg, err): | |
|
493 | return IOError( | |
|
494 | "%s win32 error code: %d %s" % (msg, err, _win32_strerror(err)) | |
|
495 | ) | |
|
426 | 496 | |
|
427 | 497 | def close(self): |
|
428 | 498 | if self.pipe: |
|
429 |
log( |
|
|
499 | log("Closing pipe") | |
|
430 | 500 | CloseHandle(self.pipe) |
|
431 | 501 | self.pipe = None |
|
432 | 502 | |
@@ -460,7 +530,7 b' class WindowsNamedPipeTransport(Transpor' | |||
|
460 | 530 | olap = OVERLAPPED() |
|
461 | 531 | olap.hEvent = self._waitable |
|
462 | 532 | |
|
463 |
log( |
|
|
533 | log("made read buff of size %d", size) | |
|
464 | 534 | |
|
465 | 535 | # ReadFile docs warn against sending in the nread parameter for async |
|
466 | 536 | # operations, so we always collect it via GetOverlappedResultEx |
@@ -469,23 +539,23 b' class WindowsNamedPipeTransport(Transpor' | |||
|
469 | 539 | if not immediate: |
|
470 | 540 | err = GetLastError() |
|
471 | 541 | if err != ERROR_IO_PENDING: |
|
472 |
self._raise_win_err( |
|
|
473 | GetLastError()) | |
|
542 | self._raise_win_err("failed to read %d bytes" % size, err) | |
|
474 | 543 | |
|
475 | 544 | nread = wintypes.DWORD() |
|
476 |
if not self._get_overlapped_result_ex( |
|
|
477 |
|
|
|
478 | True): | |
|
545 | if not self._get_overlapped_result_ex( | |
|
546 | self.pipe, olap, nread, 0 if immediate else self.timeout, True | |
|
547 | ): | |
|
479 | 548 | err = GetLastError() |
|
480 | 549 | CancelIoEx(self.pipe, olap) |
|
481 | 550 | |
|
482 | 551 | if err == WAIT_TIMEOUT: |
|
483 |
log( |
|
|
484 |
raise SocketTimeout( |
|
|
485 |
|
|
|
552 | log("GetOverlappedResultEx timedout") | |
|
553 | raise SocketTimeout( | |
|
554 | "timed out after waiting %dms for read" % self.timeout | |
|
555 | ) | |
|
486 | 556 | |
|
487 |
log( |
|
|
488 |
self._raise_win_err( |
|
|
557 | log("GetOverlappedResultEx reports error %d", err) | |
|
558 | self._raise_win_err("error while waiting for read", err) | |
|
489 | 559 | |
|
490 | 560 | nread = nread.value |
|
491 | 561 | if nread == 0: |
@@ -494,7 +564,7 b' class WindowsNamedPipeTransport(Transpor' | |||
|
494 | 564 | # other way this shows up is if the client has gotten in a weird |
|
495 | 565 | # state, so let's bail out |
|
496 | 566 | CancelIoEx(self.pipe, olap) |
|
497 |
raise IOError( |
|
|
567 | raise IOError("Async read yielded 0 bytes; unpossible!") | |
|
498 | 568 | |
|
499 | 569 | # Holds precisely the bytes that we read from the prior request |
|
500 | 570 | buf = buf[:nread] |
@@ -511,21 +581,25 b' class WindowsNamedPipeTransport(Transpor' | |||
|
511 | 581 | olap = OVERLAPPED() |
|
512 | 582 | olap.hEvent = self._waitable |
|
513 | 583 | |
|
514 | immediate = WriteFile(self.pipe, ctypes.c_char_p(data), len(data), | |
|
515 | None, olap) | |
|
584 | immediate = WriteFile( | |
|
585 | self.pipe, ctypes.c_char_p(data), len(data), None, olap | |
|
586 | ) | |
|
516 | 587 | |
|
517 | 588 | if not immediate: |
|
518 | 589 | err = GetLastError() |
|
519 | 590 | if err != ERROR_IO_PENDING: |
|
520 |
self._raise_win_err( |
|
|
521 | GetLastError()) | |
|
591 | self._raise_win_err( | |
|
592 | "failed to write %d bytes to handle %r" | |
|
593 | % (len(data), self.pipe), | |
|
594 | err, | |
|
595 | ) | |
|
522 | 596 | |
|
523 | 597 | # Obtain results, waiting if needed |
|
524 | 598 | nwrote = wintypes.DWORD() |
|
525 |
if self._get_overlapped_result_ex( |
|
|
526 |
|
|
|
527 | True): | |
|
528 |
log( |
|
|
599 | if self._get_overlapped_result_ex( | |
|
600 | self.pipe, olap, nwrote, 0 if immediate else self.timeout, True | |
|
601 | ): | |
|
602 | log("made write of %d bytes", nwrote.value) | |
|
529 | 603 | return nwrote.value |
|
530 | 604 | |
|
531 | 605 | err = GetLastError() |
@@ -535,10 +609,21 b' class WindowsNamedPipeTransport(Transpor' | |||
|
535 | 609 | CancelIoEx(self.pipe, olap) |
|
536 | 610 | |
|
537 | 611 | if err == WAIT_TIMEOUT: |
|
538 |
raise SocketTimeout( |
|
|
539 |
|
|
|
540 | self._raise_win_err('error while waiting for write of %d bytes' % | |
|
541 | len(data), err) | |
|
612 | raise SocketTimeout( | |
|
613 | "timed out after waiting %dms for write" % self.timeout | |
|
614 | ) | |
|
615 | self._raise_win_err( | |
|
616 | "error while waiting for write of %d bytes" % len(data), err | |
|
617 | ) | |
|
618 | ||
|
619 | ||
|
620 | def _default_binpath(binpath=None): | |
|
621 | if binpath: | |
|
622 | return binpath | |
|
623 | # The test harness sets WATCHMAN_BINARY to the binary under test, | |
|
624 | # so we use that by default, otherwise, allow resolving watchman | |
|
625 | # from the users PATH. | |
|
626 | return os.environ.get("WATCHMAN_BINARY", "watchman") | |
|
542 | 627 | |
|
543 | 628 | |
|
544 | 629 | class CLIProcessTransport(Transport): |
@@ -560,13 +645,14 b' class CLIProcessTransport(Transport):' | |||
|
560 | 645 | It is the responsibility of the caller to set the send and |
|
561 | 646 | receive codecs appropriately. |
|
562 | 647 | """ |
|
648 | ||
|
563 | 649 | proc = None |
|
564 | 650 | closed = True |
|
565 | 651 | |
|
566 |
def __init__(self, sockpath, timeout, |
|
|
652 | def __init__(self, sockpath, timeout, binpath=None): | |
|
567 | 653 | self.sockpath = sockpath |
|
568 | 654 | self.timeout = timeout |
|
569 | self.watchman_exe = watchman_exe | |
|
655 | self.binpath = _default_binpath(binpath) | |
|
570 | 656 | |
|
571 | 657 | def close(self): |
|
572 | 658 | if self.proc: |
@@ -574,32 +660,32 b' class CLIProcessTransport(Transport):' | |||
|
574 | 660 | self.proc.kill() |
|
575 | 661 | self.proc.stdin.close() |
|
576 | 662 | self.proc.stdout.close() |
|
663 | self.proc.wait() | |
|
577 | 664 | self.proc = None |
|
578 | 665 | |
|
579 | 666 | def _connect(self): |
|
580 | 667 | if self.proc: |
|
581 | 668 | return self.proc |
|
582 | 669 | args = [ |
|
583 |
self. |
|
|
584 |
|
|
|
585 |
|
|
|
586 |
|
|
|
587 |
|
|
|
588 |
|
|
|
589 |
|
|
|
590 |
|
|
|
670 | self.binpath, | |
|
671 | "--sockname={0}".format(self.sockpath), | |
|
672 | "--logfile=/BOGUS", | |
|
673 | "--statefile=/BOGUS", | |
|
674 | "--no-spawn", | |
|
675 | "--no-local", | |
|
676 | "--no-pretty", | |
|
677 | "-j", | |
|
591 | 678 | ] |
|
592 |
self.proc = subprocess.Popen( |
|
|
593 | args), | |
|
594 | stdin=subprocess.PIPE, | |
|
595 | stdout=subprocess.PIPE) | |
|
679 | self.proc = subprocess.Popen( | |
|
680 | args, stdin=subprocess.PIPE, stdout=subprocess.PIPE | |
|
681 | ) | |
|
596 | 682 | return self.proc |
|
597 | 683 | |
|
598 | 684 | def readBytes(self, size): |
|
599 | 685 | self._connect() |
|
600 | 686 | res = self.proc.stdout.read(size) |
|
601 |
if res |
|
|
602 |
raise WatchmanError( |
|
|
687 | if not res: | |
|
688 | raise WatchmanError("EOF on CLI process transport") | |
|
603 | 689 | return res |
|
604 | 690 | |
|
605 | 691 | def write(self, data): |
@@ -616,13 +702,22 b' class CLIProcessTransport(Transport):' | |||
|
616 | 702 | class BserCodec(Codec): |
|
617 | 703 | """ use the BSER encoding. This is the default, preferred codec """ |
|
618 | 704 | |
|
705 | def __init__(self, transport, value_encoding, value_errors): | |
|
706 | super(BserCodec, self).__init__(transport) | |
|
707 | self._value_encoding = value_encoding | |
|
708 | self._value_errors = value_errors | |
|
709 | ||
|
619 | 710 | def _loads(self, response): |
|
620 |
return bser.loads( |
|
|
711 | return bser.loads( | |
|
712 | response, | |
|
713 | value_encoding=self._value_encoding, | |
|
714 | value_errors=self._value_errors, | |
|
715 | ) | |
|
621 | 716 | |
|
622 | 717 | def receive(self): |
|
623 | 718 | buf = [self.transport.readBytes(sniff_len)] |
|
624 | 719 | if not buf[0]: |
|
625 |
raise WatchmanError( |
|
|
720 | raise WatchmanError("empty watchman response") | |
|
626 | 721 | |
|
627 | 722 | _1, _2, elen = bser.pdu_info(buf[0]) |
|
628 | 723 | |
@@ -631,12 +726,12 b' class BserCodec(Codec):' | |||
|
631 | 726 | buf.append(self.transport.readBytes(elen - rlen)) |
|
632 | 727 | rlen += len(buf[-1]) |
|
633 | 728 | |
|
634 |
response = b |
|
|
729 | response = b"".join(buf) | |
|
635 | 730 | try: |
|
636 | 731 | res = self._loads(response) |
|
637 | 732 | return res |
|
638 | 733 | except ValueError as e: |
|
639 |
raise WatchmanError( |
|
|
734 | raise WatchmanError("watchman response decode error: %s" % e) | |
|
640 | 735 | |
|
641 | 736 | def send(self, *args): |
|
642 | 737 | cmd = bser.dumps(*args) # Defaults to BSER v1 |
@@ -648,41 +743,51 b' class ImmutableBserCodec(BserCodec):' | |||
|
648 | 743 | immutable object support """ |
|
649 | 744 | |
|
650 | 745 | def _loads(self, response): |
|
651 | return bser.loads(response, False) # Defaults to BSER v1 | |
|
746 | return bser.loads( | |
|
747 | response, | |
|
748 | False, | |
|
749 | value_encoding=self._value_encoding, | |
|
750 | value_errors=self._value_errors, | |
|
751 | ) | |
|
652 | 752 | |
|
653 | 753 | |
|
654 | 754 | class Bser2WithFallbackCodec(BserCodec): |
|
655 | 755 | """ use BSER v2 encoding """ |
|
656 | 756 | |
|
657 | def __init__(self, transport): | |
|
658 |
super(Bser2WithFallbackCodec, self).__init__( |
|
|
659 | # Once the server advertises support for bser-v2 we should switch this | |
|
660 | # to 'required' on Python 3. | |
|
661 | self.send(["version", {"optional": ["bser-v2"]}]) | |
|
757 | def __init__(self, transport, value_encoding, value_errors): | |
|
758 | super(Bser2WithFallbackCodec, self).__init__( | |
|
759 | transport, value_encoding, value_errors | |
|
760 | ) | |
|
761 | if compat.PYTHON3: | |
|
762 | bserv2_key = "required" | |
|
763 | else: | |
|
764 | bserv2_key = "optional" | |
|
765 | ||
|
766 | self.send(["version", {bserv2_key: ["bser-v2"]}]) | |
|
662 | 767 | |
|
663 | 768 | capabilities = self.receive() |
|
664 | 769 | |
|
665 |
if |
|
|
666 |
raise |
|
|
770 | if "error" in capabilities: | |
|
771 | raise BSERv1Unsupported( | |
|
772 | "The watchman server version does not support Python 3. Please " | |
|
773 | "upgrade your watchman server." | |
|
774 | ) | |
|
667 | 775 | |
|
668 |
if capabilities[ |
|
|
776 | if capabilities["capabilities"]["bser-v2"]: | |
|
669 | 777 | self.bser_version = 2 |
|
670 | 778 | self.bser_capabilities = 0 |
|
671 | 779 | else: |
|
672 | 780 | self.bser_version = 1 |
|
673 | 781 | self.bser_capabilities = 0 |
|
674 | 782 | |
|
675 | def _loads(self, response): | |
|
676 | return bser.loads(response) | |
|
677 | ||
|
678 | 783 | def receive(self): |
|
679 | 784 | buf = [self.transport.readBytes(sniff_len)] |
|
680 | 785 | if not buf[0]: |
|
681 |
raise WatchmanError( |
|
|
786 | raise WatchmanError("empty watchman response") | |
|
682 | 787 | |
|
683 | 788 | recv_bser_version, recv_bser_capabilities, elen = bser.pdu_info(buf[0]) |
|
684 | 789 | |
|
685 |
if hasattr(self, |
|
|
790 | if hasattr(self, "bser_version"): | |
|
686 | 791 | # Readjust BSER version and capabilities if necessary |
|
687 | 792 | self.bser_version = max(self.bser_version, recv_bser_version) |
|
688 | 793 | self.capabilities = self.bser_capabilities & recv_bser_capabilities |
@@ -692,30 +797,42 b' class Bser2WithFallbackCodec(BserCodec):' | |||
|
692 | 797 | buf.append(self.transport.readBytes(elen - rlen)) |
|
693 | 798 | rlen += len(buf[-1]) |
|
694 | 799 | |
|
695 |
response = b |
|
|
800 | response = b"".join(buf) | |
|
696 | 801 | try: |
|
697 | 802 | res = self._loads(response) |
|
698 | 803 | return res |
|
699 | 804 | except ValueError as e: |
|
700 |
raise WatchmanError( |
|
|
805 | raise WatchmanError("watchman response decode error: %s" % e) | |
|
701 | 806 | |
|
702 | 807 | def send(self, *args): |
|
703 |
if hasattr(self, |
|
|
704 |
cmd = bser.dumps( |
|
|
705 | capabilities=self.bser_capabilities) | |
|
808 | if hasattr(self, "bser_version"): | |
|
809 | cmd = bser.dumps( | |
|
810 | *args, | |
|
811 | version=self.bser_version, | |
|
812 | capabilities=self.bser_capabilities | |
|
813 | ) | |
|
706 | 814 | else: |
|
707 | 815 | cmd = bser.dumps(*args) |
|
708 | 816 | self.transport.write(cmd) |
|
709 | 817 | |
|
710 | 818 | |
|
819 | class ImmutableBser2Codec(Bser2WithFallbackCodec, ImmutableBserCodec): | |
|
820 | """ use the BSER encoding, decoding values using the newer | |
|
821 | immutable object support """ | |
|
822 | ||
|
823 | pass | |
|
824 | ||
|
825 | ||
|
711 | 826 | class JsonCodec(Codec): |
|
712 | 827 | """ Use json codec. This is here primarily for testing purposes """ |
|
828 | ||
|
713 | 829 | json = None |
|
714 | 830 | |
|
715 | 831 | def __init__(self, transport): |
|
716 | 832 | super(JsonCodec, self).__init__(transport) |
|
717 | 833 | # optional dep on json, only if JsonCodec is used |
|
718 | 834 | import json |
|
835 | ||
|
719 | 836 | self.json = json |
|
720 | 837 | |
|
721 | 838 | def receive(self): |
@@ -727,7 +844,7 b' class JsonCodec(Codec):' | |||
|
727 | 844 | # but it's possible we might get non-ASCII bytes that are valid |
|
728 | 845 | # UTF-8. |
|
729 | 846 | if compat.PYTHON3: |
|
730 |
line = line.decode( |
|
|
847 | line = line.decode("utf-8") | |
|
731 | 848 | return self.json.loads(line) |
|
732 | 849 | except Exception as e: |
|
733 | 850 | print(e, line) |
@@ -739,12 +856,13 b' class JsonCodec(Codec):' | |||
|
739 | 856 | # containing Unicode strings to Unicode string. Even with (the default) |
|
740 | 857 | # ensure_ascii=True, dumps returns a Unicode string. |
|
741 | 858 | if compat.PYTHON3: |
|
742 |
cmd = cmd.encode( |
|
|
859 | cmd = cmd.encode("ascii") | |
|
743 | 860 | self.transport.write(cmd + b"\n") |
|
744 | 861 | |
|
745 | 862 | |
|
746 | 863 | class client(object): |
|
747 | 864 | """ Handles the communication with the watchman service """ |
|
865 | ||
|
748 | 866 | sockpath = None |
|
749 | 867 | transport = None |
|
750 | 868 | sendCodec = None |
@@ -754,60 +872,100 b' class client(object):' | |||
|
754 | 872 | subs = {} # Keyed by subscription name |
|
755 | 873 | sub_by_root = {} # Keyed by root, then by subscription name |
|
756 | 874 | logs = [] # When log level is raised |
|
757 |
unilateral = [ |
|
|
875 | unilateral = ["log", "subscription"] | |
|
758 | 876 | tport = None |
|
759 | 877 | useImmutableBser = None |
|
760 | watchman_exe = None | |
|
878 | pid = None | |
|
761 | 879 | |
|
762 |
def __init__( |
|
|
880 | def __init__( | |
|
881 | self, | |
|
763 | 882 |
|
|
764 | 883 |
|
|
765 | 884 |
|
|
766 | 885 |
|
|
767 | 886 |
|
|
768 | 887 |
|
|
769 | watchman_exe=None): | |
|
888 | # use False for these two because None has a special | |
|
889 | # meaning | |
|
890 | valueEncoding=False, | |
|
891 | valueErrors=False, | |
|
892 | binpath=None, | |
|
893 | ): | |
|
770 | 894 | self.sockpath = sockpath |
|
771 | 895 | self.timeout = timeout |
|
772 | 896 | self.useImmutableBser = useImmutableBser |
|
773 | self.watchman_exe = watchman_exe | |
|
897 | self.binpath = _default_binpath(binpath) | |
|
774 | 898 | |
|
775 | 899 | if inspect.isclass(transport) and issubclass(transport, Transport): |
|
776 | 900 | self.transport = transport |
|
777 | 901 | else: |
|
778 |
transport = transport or os.getenv( |
|
|
779 |
if transport == |
|
|
902 | transport = transport or os.getenv("WATCHMAN_TRANSPORT") or "local" | |
|
903 | if transport == "local" and os.name == "nt": | |
|
780 | 904 | self.transport = WindowsNamedPipeTransport |
|
781 |
elif transport == |
|
|
905 | elif transport == "local": | |
|
782 | 906 | self.transport = UnixSocketTransport |
|
783 |
elif transport == |
|
|
907 | elif transport == "cli": | |
|
784 | 908 | self.transport = CLIProcessTransport |
|
785 | 909 | if sendEncoding is None: |
|
786 |
sendEncoding = |
|
|
910 | sendEncoding = "json" | |
|
787 | 911 | if recvEncoding is None: |
|
788 | 912 | recvEncoding = sendEncoding |
|
789 | 913 | else: |
|
790 |
raise WatchmanError( |
|
|
914 | raise WatchmanError("invalid transport %s" % transport) | |
|
791 | 915 | |
|
792 | sendEncoding = str(sendEncoding or os.getenv('WATCHMAN_ENCODING') or | |
|
793 | 'bser') | |
|
794 | recvEncoding = str(recvEncoding or os.getenv('WATCHMAN_ENCODING') or | |
|
795 | 'bser') | |
|
916 | sendEncoding = str( | |
|
917 | sendEncoding or os.getenv("WATCHMAN_ENCODING") or "bser" | |
|
918 | ) | |
|
919 | recvEncoding = str( | |
|
920 | recvEncoding or os.getenv("WATCHMAN_ENCODING") or "bser" | |
|
921 | ) | |
|
796 | 922 | |
|
797 | 923 | self.recvCodec = self._parseEncoding(recvEncoding) |
|
798 | 924 | self.sendCodec = self._parseEncoding(sendEncoding) |
|
799 | 925 | |
|
926 | # We want to act like the native OS methods as much as possible. This | |
|
927 | # means returning bytestrings on Python 2 by default and Unicode | |
|
928 | # strings on Python 3. However we take an optional argument that lets | |
|
929 | # users override this. | |
|
930 | if valueEncoding is False: | |
|
931 | if compat.PYTHON3: | |
|
932 | self.valueEncoding = encoding.get_local_encoding() | |
|
933 | self.valueErrors = encoding.default_local_errors | |
|
934 | else: | |
|
935 | self.valueEncoding = None | |
|
936 | self.valueErrors = None | |
|
937 | else: | |
|
938 | self.valueEncoding = valueEncoding | |
|
939 | if valueErrors is False: | |
|
940 | self.valueErrors = encoding.default_local_errors | |
|
941 | else: | |
|
942 | self.valueErrors = valueErrors | |
|
943 | ||
|
944 | def _makeBSERCodec(self, codec): | |
|
945 | def make_codec(transport): | |
|
946 | return codec(transport, self.valueEncoding, self.valueErrors) | |
|
947 | ||
|
948 | return make_codec | |
|
949 | ||
|
800 | 950 | def _parseEncoding(self, enc): |
|
801 |
if enc == |
|
|
951 | if enc == "bser": | |
|
802 | 952 | if self.useImmutableBser: |
|
803 | return ImmutableBserCodec | |
|
804 | return BserCodec | |
|
805 |
elif enc == |
|
|
806 | return Bser2WithFallbackCodec | |
|
807 | elif enc == 'json': | |
|
953 | return self._makeBSERCodec(ImmutableBser2Codec) | |
|
954 | return self._makeBSERCodec(Bser2WithFallbackCodec) | |
|
955 | elif enc == "bser-v1": | |
|
956 | if compat.PYTHON3: | |
|
957 | raise BSERv1Unsupported( | |
|
958 | "Python 3 does not support the BSER v1 encoding: specify " | |
|
959 | '"bser" or omit the sendEncoding and recvEncoding ' | |
|
960 | "arguments" | |
|
961 | ) | |
|
962 | if self.useImmutableBser: | |
|
963 | return self._makeBSERCodec(ImmutableBserCodec) | |
|
964 | return self._makeBSERCodec(BserCodec) | |
|
965 | elif enc == "json": | |
|
808 | 966 | return JsonCodec |
|
809 | 967 | else: |
|
810 |
raise WatchmanError( |
|
|
968 | raise WatchmanError("invalid encoding %s" % enc) | |
|
811 | 969 | |
|
812 | 970 | def _hasprop(self, result, name): |
|
813 | 971 | if self.useImmutableBser: |
@@ -817,26 +975,25 b' class client(object):' | |||
|
817 | 975 | def _resolvesockname(self): |
|
818 | 976 | # if invoked via a trigger, watchman will set this env var; we |
|
819 | 977 | # should use it unless explicitly set otherwise |
|
820 |
path = os.getenv( |
|
|
978 | path = os.getenv("WATCHMAN_SOCK") | |
|
821 | 979 | if path: |
|
822 | 980 | return path |
|
823 | 981 | |
|
824 |
cmd = [self. |
|
|
982 | cmd = [self.binpath, "--output-encoding=bser", "get-sockname"] | |
|
825 | 983 | try: |
|
826 |
args = dict( |
|
|
827 |
|
|
|
828 | close_fds=os.name != 'nt') | |
|
984 | args = dict( | |
|
985 | stdout=subprocess.PIPE, stderr=subprocess.PIPE | |
|
986 | ) # noqa: C408 | |
|
829 | 987 | |
|
830 |
if os.name == |
|
|
988 | if os.name == "nt": | |
|
831 | 989 | # if invoked via an application with graphical user interface, |
|
832 | 990 | # this call will cause a brief command window pop-up. |
|
833 | 991 | # Using the flag STARTF_USESHOWWINDOW to avoid this behavior. |
|
834 | 992 | startupinfo = subprocess.STARTUPINFO() |
|
835 | 993 | startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW |
|
836 |
args[ |
|
|
994 | args["startupinfo"] = startupinfo | |
|
837 | 995 | |
|
838 |
p = subprocess.Popen( |
|
|
839 | **args) | |
|
996 | p = subprocess.Popen(cmd, **args) | |
|
840 | 997 | |
|
841 | 998 | except OSError as e: |
|
842 | 999 | raise WatchmanError('"watchman" executable not in PATH (%s)' % e) |
@@ -848,27 +1005,43 b' class client(object):' | |||
|
848 | 1005 | raise WatchmanError("watchman exited with code %d" % exitcode) |
|
849 | 1006 | |
|
850 | 1007 | result = bser.loads(stdout) |
|
851 |
if |
|
|
852 |
raise WatchmanError( |
|
|
1008 | if "error" in result: | |
|
1009 | raise WatchmanError("get-sockname error: %s" % result["error"]) | |
|
853 | 1010 | |
|
854 |
return result[ |
|
|
1011 | return result["sockname"] | |
|
855 | 1012 | |
|
856 | 1013 | def _connect(self): |
|
857 | 1014 | """ establish transport connection """ |
|
858 | 1015 | |
|
859 | 1016 | if self.recvConn: |
|
1017 | if self.pid != os.getpid(): | |
|
1018 | raise UseAfterFork( | |
|
1019 | "do not re-use a connection after fork; open a new client instead" | |
|
1020 | ) | |
|
860 | 1021 | return |
|
861 | 1022 | |
|
862 | 1023 | if self.sockpath is None: |
|
863 | 1024 | self.sockpath = self._resolvesockname() |
|
864 | 1025 | |
|
865 | self.tport = self.transport(self.sockpath, self.timeout, self.watchman_exe) | |
|
1026 | kwargs = {} | |
|
1027 | if self.transport == CLIProcessTransport: | |
|
1028 | kwargs["binpath"] = self.binpath | |
|
1029 | ||
|
1030 | self.tport = self.transport(self.sockpath, self.timeout, **kwargs) | |
|
866 | 1031 | self.sendConn = self.sendCodec(self.tport) |
|
867 | 1032 | self.recvConn = self.recvCodec(self.tport) |
|
1033 | self.pid = os.getpid() | |
|
868 | 1034 | |
|
869 | 1035 | def __del__(self): |
|
870 | 1036 | self.close() |
|
871 | 1037 | |
|
1038 | def __enter__(self): | |
|
1039 | self._connect() | |
|
1040 | return self | |
|
1041 | ||
|
1042 | def __exit__(self, exc_type, exc_value, exc_traceback): | |
|
1043 | self.close() | |
|
1044 | ||
|
872 | 1045 | def close(self): |
|
873 | 1046 | if self.tport: |
|
874 | 1047 | self.tport.close() |
@@ -893,26 +1066,20 b' class client(object):' | |||
|
893 | 1066 | |
|
894 | 1067 | self._connect() |
|
895 | 1068 | result = self.recvConn.receive() |
|
896 |
if self._hasprop(result, |
|
|
897 |
|
|
|
898 | if compat.PYTHON3 and isinstance(self.recvConn, BserCodec): | |
|
899 | error = result['error'].decode('utf-8', 'surrogateescape') | |
|
900 | raise CommandError(error) | |
|
1069 | if self._hasprop(result, "error"): | |
|
1070 | raise CommandError(result["error"]) | |
|
901 | 1071 | |
|
902 |
if self._hasprop(result, |
|
|
903 |
|
|
|
904 | if compat.PYTHON3 and isinstance(self.recvConn, BserCodec): | |
|
905 | log = log.decode('utf-8', 'surrogateescape') | |
|
906 | self.logs.append(log) | |
|
1072 | if self._hasprop(result, "log"): | |
|
1073 | self.logs.append(result["log"]) | |
|
907 | 1074 | |
|
908 |
if self._hasprop(result, |
|
|
909 |
sub = result[ |
|
|
1075 | if self._hasprop(result, "subscription"): | |
|
1076 | sub = result["subscription"] | |
|
910 | 1077 | if not (sub in self.subs): |
|
911 | 1078 | self.subs[sub] = [] |
|
912 | 1079 | self.subs[sub].append(result) |
|
913 | 1080 | |
|
914 | 1081 | # also accumulate in {root,sub} keyed store |
|
915 |
root = os.path.normcase(result[ |
|
|
1082 | root = os.path.normpath(os.path.normcase(result["root"])) | |
|
916 | 1083 | if not root in self.sub_by_root: |
|
917 | 1084 | self.sub_by_root[root] = {} |
|
918 | 1085 | if not sub in self.sub_by_root[root]: |
@@ -922,7 +1089,7 b' class client(object):' | |||
|
922 | 1089 | return result |
|
923 | 1090 | |
|
924 | 1091 | def isUnilateralResponse(self, res): |
|
925 |
if |
|
|
1092 | if "unilateral" in res and res["unilateral"]: | |
|
926 | 1093 | return True |
|
927 | 1094 | # Fall back to checking for known unilateral responses |
|
928 | 1095 | for k in self.unilateral: |
@@ -955,18 +1122,11 b' class client(object):' | |||
|
955 | 1122 | remove processing impacts both the unscoped and scoped stores |
|
956 | 1123 | for the subscription data. |
|
957 | 1124 | """ |
|
958 | if compat.PYTHON3 and issubclass(self.recvCodec, BserCodec): | |
|
959 | # People may pass in Unicode strings here -- but currently BSER only | |
|
960 | # returns bytestrings. Deal with that. | |
|
961 | if isinstance(root, str): | |
|
962 | root = encoding.encode_local(root) | |
|
963 | if isinstance(name, str): | |
|
964 | name = name.encode('utf-8') | |
|
965 | ||
|
966 | 1125 | if root is not None: |
|
967 | if not root in self.sub_by_root: | |
|
1126 | root = os.path.normpath(os.path.normcase(root)) | |
|
1127 | if root not in self.sub_by_root: | |
|
968 | 1128 | return None |
|
969 |
if not |
|
|
1129 | if name not in self.sub_by_root[root]: | |
|
970 | 1130 | return None |
|
971 | 1131 | sub = self.sub_by_root[root][name] |
|
972 | 1132 | if remove: |
@@ -976,7 +1136,7 b' class client(object):' | |||
|
976 | 1136 | del self.subs[name] |
|
977 | 1137 | return sub |
|
978 | 1138 | |
|
979 |
if not |
|
|
1139 | if name not in self.subs: | |
|
980 | 1140 | return None |
|
981 | 1141 | sub = self.subs[name] |
|
982 | 1142 | if remove: |
@@ -992,7 +1152,7 b' class client(object):' | |||
|
992 | 1152 | and NOT returned via this method. |
|
993 | 1153 | """ |
|
994 | 1154 | |
|
995 |
log( |
|
|
1155 | log("calling client.query") | |
|
996 | 1156 | self._connect() |
|
997 | 1157 | try: |
|
998 | 1158 | self.sendConn.send(args) |
@@ -1006,27 +1166,27 b' class client(object):' | |||
|
1006 | 1166 | # When we can depend on Python 3, we can use PEP 3134 |
|
1007 | 1167 | # exception chaining here. |
|
1008 | 1168 | raise WatchmanEnvironmentError( |
|
1009 |
|
|
|
1169 | "I/O error communicating with watchman daemon", | |
|
1010 | 1170 | ee.errno, |
|
1011 | 1171 | ee.strerror, |
|
1012 |
args |
|
|
1172 | args, | |
|
1173 | ) | |
|
1013 | 1174 | except WatchmanError as ex: |
|
1014 | 1175 | ex.setCommand(args) |
|
1015 | 1176 | raise |
|
1016 | 1177 | |
|
1017 | 1178 | def capabilityCheck(self, optional=None, required=None): |
|
1018 | 1179 | """ Perform a server capability check """ |
|
1019 |
res = self.query( |
|
|
1020 |
|
|
|
1021 | 'required': required or [] | |
|
1022 | }) | |
|
1180 | res = self.query( | |
|
1181 | "version", {"optional": optional or [], "required": required or []} | |
|
1182 | ) | |
|
1023 | 1183 | |
|
1024 |
if not self._hasprop(res, |
|
|
1184 | if not self._hasprop(res, "capabilities"): | |
|
1025 | 1185 | # Server doesn't support capabilities, so we need to |
|
1026 | 1186 | # synthesize the results based on the version |
|
1027 | 1187 | capabilities.synthesize(res, optional) |
|
1028 |
if |
|
|
1029 |
raise CommandError(res[ |
|
|
1188 | if "error" in res: | |
|
1189 | raise CommandError(res["error"]) | |
|
1030 | 1190 | |
|
1031 | 1191 | return res |
|
1032 | 1192 |
@@ -175,7 +175,22 b' static PyObject* bserobj_getattrro(PyObj' | |||
|
175 | 175 | const char* item_name = NULL; |
|
176 | 176 | PyObject* key = PyTuple_GET_ITEM(obj->keys, i); |
|
177 | 177 | |
|
178 | if (PyUnicode_Check(key)) { | |
|
179 | #if PY_MAJOR_VERSION >= 3 | |
|
180 | item_name = PyUnicode_AsUTF8(key); | |
|
181 | #else | |
|
182 | PyObject* utf = PyUnicode_AsEncodedString(key, "utf-8", "ignore"); | |
|
183 | if (utf == NULL) { | |
|
184 | goto bail; | |
|
185 | } | |
|
186 | item_name = PyBytes_AsString(utf); | |
|
187 | #endif | |
|
188 | } else { | |
|
178 | 189 | item_name = PyBytes_AsString(key); |
|
190 | } | |
|
191 | if (item_name == NULL) { | |
|
192 | goto bail; | |
|
193 | } | |
|
179 | 194 | if (!strcmp(item_name, namestr)) { |
|
180 | 195 | ret = PySequence_GetItem(obj->values, i); |
|
181 | 196 | goto bail; |
@@ -1147,11 +1162,15 b' static PyObject* bser_loads(PyObject* se' | |||
|
1147 | 1162 | } |
|
1148 | 1163 | |
|
1149 | 1164 | static PyObject* bser_load(PyObject* self, PyObject* args, PyObject* kw) { |
|
1150 |
PyObject |
|
|
1165 | PyObject* load; | |
|
1166 | PyObject* load_method; | |
|
1167 | PyObject* string; | |
|
1168 | PyObject* load_method_args; | |
|
1169 | PyObject* load_method_kwargs; | |
|
1151 | 1170 | PyObject* fp = NULL; |
|
1152 | 1171 | PyObject* mutable_obj = NULL; |
|
1153 |
c |
|
|
1154 |
c |
|
|
1172 | PyObject* value_encoding = NULL; | |
|
1173 | PyObject* value_errors = NULL; | |
|
1155 | 1174 | |
|
1156 | 1175 | static char* kw_list[] = { |
|
1157 | 1176 | "fp", "mutable", "value_encoding", "value_errors", NULL}; |
@@ -1159,7 +1178,7 b' static PyObject* bser_load(PyObject* sel' | |||
|
1159 | 1178 | if (!PyArg_ParseTupleAndKeywords( |
|
1160 | 1179 | args, |
|
1161 | 1180 | kw, |
|
1162 |
"OO |
|
|
1181 | "O|OOO:load", | |
|
1163 | 1182 | kw_list, |
|
1164 | 1183 | &fp, |
|
1165 | 1184 | &mutable_obj, |
@@ -1172,8 +1191,33 b' static PyObject* bser_load(PyObject* sel' | |||
|
1172 | 1191 | if (load == NULL) { |
|
1173 | 1192 | return NULL; |
|
1174 | 1193 | } |
|
1175 | string = PyObject_CallMethod( | |
|
1176 | load, "load", "OOzz", fp, mutable_obj, value_encoding, value_errors); | |
|
1194 | load_method = PyObject_GetAttrString(load, "load"); | |
|
1195 | if (load_method == NULL) { | |
|
1196 | return NULL; | |
|
1197 | } | |
|
1198 | // Mandatory method arguments | |
|
1199 | load_method_args = Py_BuildValue("(O)", fp); | |
|
1200 | if (load_method_args == NULL) { | |
|
1201 | return NULL; | |
|
1202 | } | |
|
1203 | // Optional method arguments | |
|
1204 | load_method_kwargs = PyDict_New(); | |
|
1205 | if (load_method_kwargs == NULL) { | |
|
1206 | return NULL; | |
|
1207 | } | |
|
1208 | if (mutable_obj) { | |
|
1209 | PyDict_SetItemString(load_method_kwargs, "mutable", mutable_obj); | |
|
1210 | } | |
|
1211 | if (value_encoding) { | |
|
1212 | PyDict_SetItemString(load_method_kwargs, "value_encoding", value_encoding); | |
|
1213 | } | |
|
1214 | if (value_errors) { | |
|
1215 | PyDict_SetItemString(load_method_kwargs, "value_errors", value_errors); | |
|
1216 | } | |
|
1217 | string = PyObject_Call(load_method, load_method_args, load_method_kwargs); | |
|
1218 | Py_DECREF(load_method_kwargs); | |
|
1219 | Py_DECREF(load_method_args); | |
|
1220 | Py_DECREF(load_method); | |
|
1177 | 1221 | Py_DECREF(load); |
|
1178 | 1222 | return string; |
|
1179 | 1223 | } |
@@ -26,20 +26,20 b'' | |||
|
26 | 26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
27 | 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
28 | 28 | |
|
29 | from __future__ import absolute_import | |
|
30 | from __future__ import division | |
|
31 | from __future__ import print_function | |
|
32 | 29 | # no unicode literals |
|
30 | from __future__ import absolute_import, division, print_function | |
|
33 | 31 | |
|
34 | 32 | import re |
|
35 | 33 | |
|
34 | ||
|
36 | 35 | def parse_version(vstr): |
|
37 | 36 | res = 0 |
|
38 |
for n in vstr.split( |
|
|
37 | for n in vstr.split("."): | |
|
39 | 38 | res = res * 1000 |
|
40 | 39 | res = res + int(n) |
|
41 | 40 | return res |
|
42 | 41 | |
|
42 | ||
|
43 | 43 | cap_versions = { |
|
44 | 44 | "cmd-watch-del-all": "3.1.1", |
|
45 | 45 | "cmd-watch-project": "3.1", |
@@ -49,23 +49,29 b' cap_versions = {' | |||
|
49 | 49 | "wildmatch": "3.7", |
|
50 | 50 | } |
|
51 | 51 | |
|
52 | ||
|
52 | 53 | def check(version, name): |
|
53 | 54 | if name in cap_versions: |
|
54 | 55 | return version >= parse_version(cap_versions[name]) |
|
55 | 56 | return False |
|
56 | 57 | |
|
58 | ||
|
57 | 59 | def synthesize(vers, opts): |
|
58 | 60 | """ Synthesize a capability enabled version response |
|
59 | 61 | This is a very limited emulation for relatively recent feature sets |
|
60 | 62 | """ |
|
61 |
parsed_version = parse_version(vers[ |
|
|
62 |
vers[ |
|
|
63 |
for name in opts[ |
|
|
64 |
vers[ |
|
|
65 | for name in opts['required']: | |
|
63 | parsed_version = parse_version(vers["version"]) | |
|
64 | vers["capabilities"] = {} | |
|
65 | for name in opts["optional"]: | |
|
66 | vers["capabilities"][name] = check(parsed_version, name) | |
|
67 | failed = False # noqa: F841 T25377293 Grandfathered in | |
|
68 | for name in opts["required"]: | |
|
66 | 69 | have = check(parsed_version, name) |
|
67 |
vers[ |
|
|
70 | vers["capabilities"][name] = have | |
|
68 | 71 | if not have: |
|
69 | vers['error'] = 'client required capability `' + name + \ | |
|
70 | '` is not supported by this server' | |
|
72 | vers["error"] = ( | |
|
73 | "client required capability `" | |
|
74 | + name | |
|
75 | + "` is not supported by this server" | |
|
76 | ) | |
|
71 | 77 | return vers |
@@ -26,20 +26,22 b'' | |||
|
26 | 26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
27 | 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
28 | 28 | |
|
29 | from __future__ import absolute_import | |
|
30 | from __future__ import division | |
|
31 | from __future__ import print_function | |
|
32 | 29 | # no unicode literals |
|
33 | ||
|
34 | '''Compatibility module across Python 2 and 3.''' | |
|
30 | from __future__ import absolute_import, division, print_function | |
|
35 | 31 | |
|
36 | 32 | import sys |
|
37 | 33 | |
|
34 | ||
|
35 | """Compatibility module across Python 2 and 3.""" | |
|
36 | ||
|
37 | ||
|
38 | PYTHON2 = sys.version_info < (3, 0) | |
|
38 | 39 | PYTHON3 = sys.version_info >= (3, 0) |
|
39 | 40 | |
|
40 | 41 | # This is adapted from https://bitbucket.org/gutworth/six, and used under the |
|
41 | 42 | # MIT license. See LICENSE for a full copyright notice. |
|
42 | 43 | if PYTHON3: |
|
44 | ||
|
43 | 45 | def reraise(tp, value, tb=None): |
|
44 | 46 | try: |
|
45 | 47 | if value is None: |
@@ -50,16 +52,20 b' if PYTHON3:' | |||
|
50 | 52 | finally: |
|
51 | 53 | value = None |
|
52 | 54 | tb = None |
|
55 | ||
|
56 | ||
|
53 | 57 | else: |
|
54 |
exec( |
|
|
58 | exec( | |
|
59 | """ | |
|
55 | 60 |
|
|
56 | 61 |
|
|
57 | 62 |
|
|
58 | 63 |
|
|
59 | 64 |
|
|
60 |
|
|
|
65 | """.strip() | |
|
66 | ) | |
|
61 | 67 | |
|
62 | 68 | if PYTHON3: |
|
63 | 69 | UNICODE = str |
|
64 | 70 | else: |
|
65 | UNICODE = unicode | |
|
71 | UNICODE = unicode # noqa: F821 We handled versioning above |
@@ -26,48 +26,50 b'' | |||
|
26 | 26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
27 | 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
28 | 28 | |
|
29 | from __future__ import absolute_import | |
|
30 | from __future__ import division | |
|
31 | from __future__ import print_function | |
|
32 | 29 | # no unicode literals |
|
33 | ||
|
34 | '''Module to deal with filename encoding on the local system, as returned by | |
|
35 | Watchman.''' | |
|
30 | from __future__ import absolute_import, division, print_function | |
|
36 | 31 | |
|
37 | 32 | import sys |
|
38 | 33 | |
|
39 |
from . import |
|
|
40 | compat, | |
|
41 | ) | |
|
34 | from . import compat | |
|
35 | ||
|
36 | ||
|
37 | """Module to deal with filename encoding on the local system, as returned by | |
|
38 | Watchman.""" | |
|
39 | ||
|
42 | 40 | |
|
43 | 41 | if compat.PYTHON3: |
|
44 |
default_local_errors = |
|
|
42 | default_local_errors = "surrogateescape" | |
|
45 | 43 | |
|
46 | 44 | def get_local_encoding(): |
|
47 |
if sys.platform == |
|
|
45 | if sys.platform == "win32": | |
|
48 | 46 | # Watchman always returns UTF-8 encoded strings on Windows. |
|
49 |
return |
|
|
47 | return "utf-8" | |
|
50 | 48 | # On the Python 3 versions we support, sys.getfilesystemencoding never |
|
51 | 49 | # returns None. |
|
52 | 50 | return sys.getfilesystemencoding() |
|
51 | ||
|
52 | ||
|
53 | 53 | else: |
|
54 | 54 | # Python 2 doesn't support surrogateescape, so use 'strict' by |
|
55 | 55 | # default. Users can register a custom surrogateescape error handler and use |
|
56 | 56 | # that if they so desire. |
|
57 |
default_local_errors = |
|
|
57 | default_local_errors = "strict" | |
|
58 | 58 | |
|
59 | 59 | def get_local_encoding(): |
|
60 |
if sys.platform == |
|
|
60 | if sys.platform == "win32": | |
|
61 | 61 | # Watchman always returns UTF-8 encoded strings on Windows. |
|
62 |
return |
|
|
62 | return "utf-8" | |
|
63 | 63 | fsencoding = sys.getfilesystemencoding() |
|
64 | 64 | if fsencoding is None: |
|
65 | 65 | # This is very unlikely to happen, but if it does, just use UTF-8 |
|
66 |
fsencoding = |
|
|
66 | fsencoding = "utf-8" | |
|
67 | 67 | return fsencoding |
|
68 | 68 | |
|
69 | ||
|
69 | 70 | def encode_local(s): |
|
70 | 71 | return s.encode(get_local_encoding(), default_local_errors) |
|
71 | 72 | |
|
73 | ||
|
72 | 74 | def decode_local(bs): |
|
73 | 75 | return bs.decode(get_local_encoding(), default_local_errors) |
@@ -26,17 +26,17 b'' | |||
|
26 | 26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
27 | 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
28 | 28 | |
|
29 | from __future__ import absolute_import | |
|
30 | from __future__ import division | |
|
31 | from __future__ import print_function | |
|
32 | 29 | # no unicode literals |
|
30 | from __future__ import absolute_import, division, print_function | |
|
31 | ||
|
32 | import ctypes | |
|
33 | ||
|
33 | 34 | |
|
34 | 35 | try: |
|
35 | 36 | from . import bser |
|
36 | 37 | except ImportError: |
|
37 | 38 | from . import pybser as bser |
|
38 | 39 | |
|
39 | import ctypes | |
|
40 | 40 | |
|
41 | 41 | EMPTY_HEADER = b"\x00\x01\x05\x00\x00\x00\x00" |
|
42 | 42 | |
@@ -95,13 +95,15 b' def load(fp, mutable=True, value_encodin' | |||
|
95 | 95 | ctypes.resize(buf, total_len) |
|
96 | 96 | |
|
97 | 97 | body = (ctypes.c_char * (total_len - len(header))).from_buffer( |
|
98 |
buf, len(header) |
|
|
98 | buf, len(header) | |
|
99 | ) | |
|
99 | 100 | read_len = _read_bytes(fp, body) |
|
100 | 101 | if read_len < len(body): |
|
101 |
raise RuntimeError( |
|
|
102 | raise RuntimeError("bser data ended early") | |
|
102 | 103 | |
|
103 | 104 | return bser.loads( |
|
104 | 105 | (ctypes.c_char * total_len).from_buffer(buf, 0), |
|
105 | 106 | mutable, |
|
106 | 107 | value_encoding, |
|
107 |
value_errors |
|
|
108 | value_errors, | |
|
109 | ) |
@@ -26,10 +26,8 b'' | |||
|
26 | 26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
27 | 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
28 | 28 | |
|
29 | from __future__ import absolute_import | |
|
30 | from __future__ import division | |
|
31 | from __future__ import print_function | |
|
32 | 29 | # no unicode literals |
|
30 | from __future__ import absolute_import, division, print_function | |
|
33 | 31 | |
|
34 | 32 | import binascii |
|
35 | 33 | import collections |
@@ -37,30 +35,31 b' import ctypes' | |||
|
37 | 35 | import struct |
|
38 | 36 | import sys |
|
39 | 37 | |
|
40 |
from . import |
|
|
41 | compat, | |
|
42 | ) | |
|
38 | from . import compat | |
|
39 | ||
|
43 | 40 | |
|
44 |
BSER_ARRAY = b |
|
|
45 |
BSER_OBJECT = b |
|
|
46 |
BSER_BYTESTRING = b |
|
|
47 |
BSER_INT8 = b |
|
|
48 |
BSER_INT16 = b |
|
|
49 |
BSER_INT32 = b |
|
|
50 |
BSER_INT64 = b |
|
|
51 |
BSER_REAL = b |
|
|
52 |
BSER_TRUE = b |
|
|
53 |
BSER_FALSE = b |
|
|
54 |
BSER_NULL = b |
|
|
55 |
BSER_TEMPLATE = b |
|
|
56 |
BSER_SKIP = b |
|
|
57 |
BSER_UTF8STRING = b |
|
|
41 | BSER_ARRAY = b"\x00" | |
|
42 | BSER_OBJECT = b"\x01" | |
|
43 | BSER_BYTESTRING = b"\x02" | |
|
44 | BSER_INT8 = b"\x03" | |
|
45 | BSER_INT16 = b"\x04" | |
|
46 | BSER_INT32 = b"\x05" | |
|
47 | BSER_INT64 = b"\x06" | |
|
48 | BSER_REAL = b"\x07" | |
|
49 | BSER_TRUE = b"\x08" | |
|
50 | BSER_FALSE = b"\x09" | |
|
51 | BSER_NULL = b"\x0a" | |
|
52 | BSER_TEMPLATE = b"\x0b" | |
|
53 | BSER_SKIP = b"\x0c" | |
|
54 | BSER_UTF8STRING = b"\x0d" | |
|
58 | 55 | |
|
59 | 56 | if compat.PYTHON3: |
|
60 | 57 | STRING_TYPES = (str, bytes) |
|
61 | 58 | unicode = str |
|
59 | ||
|
62 | 60 | def tobytes(i): |
|
63 |
return str(i).encode( |
|
|
61 | return str(i).encode("ascii") | |
|
62 | ||
|
64 | 63 | long = int |
|
65 | 64 | else: |
|
66 | 65 | STRING_TYPES = (unicode, str) |
@@ -72,6 +71,7 b' else:' | |||
|
72 | 71 | EMPTY_HEADER = b"\x00\x01\x05\x00\x00\x00\x00" |
|
73 | 72 | EMPTY_HEADER_V2 = b"\x00\x02\x00\x00\x00\x00\x05\x00\x00\x00\x00" |
|
74 | 73 | |
|
74 | ||
|
75 | 75 | def _int_size(x): |
|
76 | 76 | """Return the smallest size int that can store the value""" |
|
77 | 77 | if -0x80 <= x <= 0x7F: |
@@ -83,29 +83,34 b' def _int_size(x):' | |||
|
83 | 83 | elif long(-0x8000000000000000) <= x <= long(0x7FFFFFFFFFFFFFFF): |
|
84 | 84 | return 8 |
|
85 | 85 | else: |
|
86 |
raise RuntimeError( |
|
|
86 | raise RuntimeError("Cannot represent value: " + str(x)) | |
|
87 | ||
|
87 | 88 | |
|
88 | 89 | def _buf_pos(buf, pos): |
|
89 | 90 | ret = buf[pos] |
|
90 | # In Python 2, buf is a str array so buf[pos] is a string. In Python 3, buf | |
|
91 | # is a bytes array and buf[pos] is an integer. | |
|
92 | if compat.PYTHON3: | |
|
91 | # Normalize the return type to bytes | |
|
92 | if compat.PYTHON3 and not isinstance(ret, bytes): | |
|
93 | 93 | ret = bytes((ret,)) |
|
94 | 94 | return ret |
|
95 | 95 | |
|
96 | ||
|
96 | 97 | class _bser_buffer(object): |
|
97 | ||
|
98 | 98 | def __init__(self, version): |
|
99 | 99 | self.bser_version = version |
|
100 | 100 | self.buf = ctypes.create_string_buffer(8192) |
|
101 | 101 | if self.bser_version == 1: |
|
102 | struct.pack_into(tobytes(len(EMPTY_HEADER)) + b's', self.buf, 0, | |
|
103 | EMPTY_HEADER) | |
|
102 | struct.pack_into( | |
|
103 | tobytes(len(EMPTY_HEADER)) + b"s", self.buf, 0, EMPTY_HEADER | |
|
104 | ) | |
|
104 | 105 | self.wpos = len(EMPTY_HEADER) |
|
105 | 106 | else: |
|
106 | 107 | assert self.bser_version == 2 |
|
107 | struct.pack_into(tobytes(len(EMPTY_HEADER_V2)) + b's', self.buf, 0, | |
|
108 |
|
|
|
108 | struct.pack_into( | |
|
109 | tobytes(len(EMPTY_HEADER_V2)) + b"s", | |
|
110 | self.buf, | |
|
111 | 0, | |
|
112 | EMPTY_HEADER_V2, | |
|
113 | ) | |
|
109 | 114 | self.wpos = len(EMPTY_HEADER_V2) |
|
110 | 115 | |
|
111 | 116 | def ensure_size(self, size): |
@@ -117,42 +122,68 b' class _bser_buffer(object):' | |||
|
117 | 122 | to_write = size + 1 |
|
118 | 123 | self.ensure_size(to_write) |
|
119 | 124 | if size == 1: |
|
120 |
struct.pack_into(b |
|
|
125 | struct.pack_into(b"=cb", self.buf, self.wpos, BSER_INT8, val) | |
|
121 | 126 | elif size == 2: |
|
122 |
struct.pack_into(b |
|
|
127 | struct.pack_into(b"=ch", self.buf, self.wpos, BSER_INT16, val) | |
|
123 | 128 | elif size == 4: |
|
124 |
struct.pack_into(b |
|
|
129 | struct.pack_into(b"=ci", self.buf, self.wpos, BSER_INT32, val) | |
|
125 | 130 | elif size == 8: |
|
126 |
struct.pack_into(b |
|
|
131 | struct.pack_into(b"=cq", self.buf, self.wpos, BSER_INT64, val) | |
|
127 | 132 | else: |
|
128 |
raise RuntimeError( |
|
|
133 | raise RuntimeError("Cannot represent this long value") | |
|
129 | 134 | self.wpos += to_write |
|
130 | 135 | |
|
131 | ||
|
132 | 136 | def append_string(self, s): |
|
133 | 137 | if isinstance(s, unicode): |
|
134 |
s = s.encode( |
|
|
138 | s = s.encode("utf-8") | |
|
135 | 139 | s_len = len(s) |
|
136 | 140 | size = _int_size(s_len) |
|
137 | 141 | to_write = 2 + size + s_len |
|
138 | 142 | self.ensure_size(to_write) |
|
139 | 143 | if size == 1: |
|
140 | struct.pack_into(b'=ccb' + tobytes(s_len) + b's', self.buf, | |
|
141 | self.wpos, BSER_BYTESTRING, BSER_INT8, s_len, s) | |
|
144 | struct.pack_into( | |
|
145 | b"=ccb" + tobytes(s_len) + b"s", | |
|
146 | self.buf, | |
|
147 | self.wpos, | |
|
148 | BSER_BYTESTRING, | |
|
149 | BSER_INT8, | |
|
150 | s_len, | |
|
151 | s, | |
|
152 | ) | |
|
142 | 153 | elif size == 2: |
|
143 | struct.pack_into(b'=cch' + tobytes(s_len) + b's', self.buf, | |
|
144 | self.wpos, BSER_BYTESTRING, BSER_INT16, s_len, s) | |
|
154 | struct.pack_into( | |
|
155 | b"=cch" + tobytes(s_len) + b"s", | |
|
156 | self.buf, | |
|
157 | self.wpos, | |
|
158 | BSER_BYTESTRING, | |
|
159 | BSER_INT16, | |
|
160 | s_len, | |
|
161 | s, | |
|
162 | ) | |
|
145 | 163 | elif size == 4: |
|
146 | struct.pack_into(b'=cci' + tobytes(s_len) + b's', self.buf, | |
|
147 | self.wpos, BSER_BYTESTRING, BSER_INT32, s_len, s) | |
|
164 | struct.pack_into( | |
|
165 | b"=cci" + tobytes(s_len) + b"s", | |
|
166 | self.buf, | |
|
167 | self.wpos, | |
|
168 | BSER_BYTESTRING, | |
|
169 | BSER_INT32, | |
|
170 | s_len, | |
|
171 | s, | |
|
172 | ) | |
|
148 | 173 | elif size == 8: |
|
149 | struct.pack_into(b'=ccq' + tobytes(s_len) + b's', self.buf, | |
|
150 | self.wpos, BSER_BYTESTRING, BSER_INT64, s_len, s) | |
|
174 | struct.pack_into( | |
|
175 | b"=ccq" + tobytes(s_len) + b"s", | |
|
176 | self.buf, | |
|
177 | self.wpos, | |
|
178 | BSER_BYTESTRING, | |
|
179 | BSER_INT64, | |
|
180 | s_len, | |
|
181 | s, | |
|
182 | ) | |
|
151 | 183 | else: |
|
152 |
raise RuntimeError( |
|
|
184 | raise RuntimeError("Cannot represent this string value") | |
|
153 | 185 | self.wpos += to_write |
|
154 | 186 | |
|
155 | ||
|
156 | 187 | def append_recursive(self, val): |
|
157 | 188 | if isinstance(val, bool): |
|
158 | 189 | needed = 1 |
@@ -161,12 +192,12 b' class _bser_buffer(object):' | |||
|
161 | 192 | to_encode = BSER_TRUE |
|
162 | 193 | else: |
|
163 | 194 | to_encode = BSER_FALSE |
|
164 |
struct.pack_into(b |
|
|
195 | struct.pack_into(b"=c", self.buf, self.wpos, to_encode) | |
|
165 | 196 | self.wpos += needed |
|
166 | 197 | elif val is None: |
|
167 | 198 | needed = 1 |
|
168 | 199 | self.ensure_size(needed) |
|
169 |
struct.pack_into(b |
|
|
200 | struct.pack_into(b"=c", self.buf, self.wpos, BSER_NULL) | |
|
170 | 201 | self.wpos += needed |
|
171 | 202 | elif isinstance(val, (int, long)): |
|
172 | 203 | self.append_long(val) |
@@ -175,61 +206,106 b' class _bser_buffer(object):' | |||
|
175 | 206 | elif isinstance(val, float): |
|
176 | 207 | needed = 9 |
|
177 | 208 | self.ensure_size(needed) |
|
178 |
struct.pack_into(b |
|
|
209 | struct.pack_into(b"=cd", self.buf, self.wpos, BSER_REAL, val) | |
|
179 | 210 | self.wpos += needed |
|
180 |
elif isinstance(val, collections.Mapping) and |
|
|
181 |
|
|
|
211 | elif isinstance(val, collections.Mapping) and isinstance( | |
|
212 | val, collections.Sized | |
|
213 | ): | |
|
182 | 214 | val_len = len(val) |
|
183 | 215 | size = _int_size(val_len) |
|
184 | 216 | needed = 2 + size |
|
185 | 217 | self.ensure_size(needed) |
|
186 | 218 | if size == 1: |
|
187 |
struct.pack_into( |
|
|
188 |
|
|
|
219 | struct.pack_into( | |
|
220 | b"=ccb", | |
|
221 | self.buf, | |
|
222 | self.wpos, | |
|
223 | BSER_OBJECT, | |
|
224 | BSER_INT8, | |
|
225 | val_len, | |
|
226 | ) | |
|
189 | 227 | elif size == 2: |
|
190 |
struct.pack_into( |
|
|
191 |
|
|
|
228 | struct.pack_into( | |
|
229 | b"=cch", | |
|
230 | self.buf, | |
|
231 | self.wpos, | |
|
232 | BSER_OBJECT, | |
|
233 | BSER_INT16, | |
|
234 | val_len, | |
|
235 | ) | |
|
192 | 236 | elif size == 4: |
|
193 |
struct.pack_into( |
|
|
194 |
|
|
|
237 | struct.pack_into( | |
|
238 | b"=cci", | |
|
239 | self.buf, | |
|
240 | self.wpos, | |
|
241 | BSER_OBJECT, | |
|
242 | BSER_INT32, | |
|
243 | val_len, | |
|
244 | ) | |
|
195 | 245 | elif size == 8: |
|
196 |
struct.pack_into( |
|
|
197 |
|
|
|
246 | struct.pack_into( | |
|
247 | b"=ccq", | |
|
248 | self.buf, | |
|
249 | self.wpos, | |
|
250 | BSER_OBJECT, | |
|
251 | BSER_INT64, | |
|
252 | val_len, | |
|
253 | ) | |
|
198 | 254 | else: |
|
199 |
raise RuntimeError( |
|
|
255 | raise RuntimeError("Cannot represent this mapping value") | |
|
200 | 256 | self.wpos += needed |
|
201 | 257 | if compat.PYTHON3: |
|
202 | 258 | iteritems = val.items() |
|
203 | 259 | else: |
|
204 | iteritems = val.iteritems() | |
|
260 | iteritems = val.iteritems() # noqa: B301 Checked version above | |
|
205 | 261 | for k, v in iteritems: |
|
206 | 262 | self.append_string(k) |
|
207 | 263 | self.append_recursive(v) |
|
208 |
elif isinstance(val, collections.Iterable) and |
|
|
209 |
|
|
|
264 | elif isinstance(val, collections.Iterable) and isinstance( | |
|
265 | val, collections.Sized | |
|
266 | ): | |
|
210 | 267 | val_len = len(val) |
|
211 | 268 | size = _int_size(val_len) |
|
212 | 269 | needed = 2 + size |
|
213 | 270 | self.ensure_size(needed) |
|
214 | 271 | if size == 1: |
|
215 |
struct.pack_into( |
|
|
216 |
BSER_INT8, val_len |
|
|
272 | struct.pack_into( | |
|
273 | b"=ccb", self.buf, self.wpos, BSER_ARRAY, BSER_INT8, val_len | |
|
274 | ) | |
|
217 | 275 | elif size == 2: |
|
218 |
struct.pack_into( |
|
|
219 |
|
|
|
276 | struct.pack_into( | |
|
277 | b"=cch", | |
|
278 | self.buf, | |
|
279 | self.wpos, | |
|
280 | BSER_ARRAY, | |
|
281 | BSER_INT16, | |
|
282 | val_len, | |
|
283 | ) | |
|
220 | 284 | elif size == 4: |
|
221 |
struct.pack_into( |
|
|
222 |
|
|
|
285 | struct.pack_into( | |
|
286 | b"=cci", | |
|
287 | self.buf, | |
|
288 | self.wpos, | |
|
289 | BSER_ARRAY, | |
|
290 | BSER_INT32, | |
|
291 | val_len, | |
|
292 | ) | |
|
223 | 293 | elif size == 8: |
|
224 |
struct.pack_into( |
|
|
225 |
|
|
|
294 | struct.pack_into( | |
|
295 | b"=ccq", | |
|
296 | self.buf, | |
|
297 | self.wpos, | |
|
298 | BSER_ARRAY, | |
|
299 | BSER_INT64, | |
|
300 | val_len, | |
|
301 | ) | |
|
226 | 302 | else: |
|
227 |
raise RuntimeError( |
|
|
303 | raise RuntimeError("Cannot represent this sequence value") | |
|
228 | 304 | self.wpos += needed |
|
229 | 305 | for v in val: |
|
230 | 306 | self.append_recursive(v) |
|
231 | 307 | else: |
|
232 |
raise RuntimeError( |
|
|
308 | raise RuntimeError("Cannot represent unknown value type") | |
|
233 | 309 | |
|
234 | 310 | |
|
235 | 311 | def dumps(obj, version=1, capabilities=0): |
@@ -238,18 +314,19 b' def dumps(obj, version=1, capabilities=0' | |||
|
238 | 314 | # Now fill in the overall length |
|
239 | 315 | if version == 1: |
|
240 | 316 | obj_len = bser_buf.wpos - len(EMPTY_HEADER) |
|
241 |
struct.pack_into(b |
|
|
317 | struct.pack_into(b"=i", bser_buf.buf, 3, obj_len) | |
|
242 | 318 | else: |
|
243 | 319 | obj_len = bser_buf.wpos - len(EMPTY_HEADER_V2) |
|
244 |
struct.pack_into(b |
|
|
245 |
struct.pack_into(b |
|
|
320 | struct.pack_into(b"=i", bser_buf.buf, 2, capabilities) | |
|
321 | struct.pack_into(b"=i", bser_buf.buf, 7, obj_len) | |
|
246 | 322 | return bser_buf.buf.raw[:bser_buf.wpos] |
|
247 | 323 | |
|
324 | ||
|
248 | 325 | # This is a quack-alike with the bserObjectType in bser.c |
|
249 | 326 | # It provides by getattr accessors and getitem for both index |
|
250 | 327 | # and name. |
|
251 | 328 | class _BunserDict(object): |
|
252 |
__slots__ = ( |
|
|
329 | __slots__ = ("_keys", "_values") | |
|
253 | 330 | |
|
254 | 331 | def __init__(self, keys, values): |
|
255 | 332 | self._keys = keys |
@@ -261,18 +338,19 b' class _BunserDict(object):' | |||
|
261 | 338 | def __getitem__(self, key): |
|
262 | 339 | if isinstance(key, (int, long)): |
|
263 | 340 | return self._values[key] |
|
264 |
elif key.startswith( |
|
|
341 | elif key.startswith("st_"): | |
|
265 | 342 | # hack^Wfeature to allow mercurial to use "st_size" to |
|
266 | 343 | # reference "size" |
|
267 | 344 | key = key[3:] |
|
268 | 345 | try: |
|
269 | 346 | return self._values[self._keys.index(key)] |
|
270 | 347 | except ValueError: |
|
271 |
raise KeyError( |
|
|
348 | raise KeyError("_BunserDict has no key %s" % key) | |
|
272 | 349 | |
|
273 | 350 | def __len__(self): |
|
274 | 351 | return len(self._keys) |
|
275 | 352 | |
|
353 | ||
|
276 | 354 | class Bunser(object): |
|
277 | 355 | def __init__(self, mutable=True, value_encoding=None, value_errors=None): |
|
278 | 356 | self.mutable = mutable |
@@ -281,7 +359,7 b' class Bunser(object):' | |||
|
281 | 359 | if value_encoding is None: |
|
282 | 360 | self.value_errors = None |
|
283 | 361 | elif value_errors is None: |
|
284 |
self.value_errors = |
|
|
362 | self.value_errors = "strict" | |
|
285 | 363 | else: |
|
286 | 364 | self.value_errors = value_errors |
|
287 | 365 | |
@@ -290,33 +368,35 b' class Bunser(object):' | |||
|
290 | 368 | try: |
|
291 | 369 | int_type = _buf_pos(buf, pos) |
|
292 | 370 | except IndexError: |
|
293 |
raise ValueError( |
|
|
371 | raise ValueError("Invalid bser int encoding, pos out of range") | |
|
294 | 372 | if int_type == BSER_INT8: |
|
295 | 373 | needed = 2 |
|
296 |
fmt = b |
|
|
374 | fmt = b"=b" | |
|
297 | 375 | elif int_type == BSER_INT16: |
|
298 | 376 | needed = 3 |
|
299 |
fmt = b |
|
|
377 | fmt = b"=h" | |
|
300 | 378 | elif int_type == BSER_INT32: |
|
301 | 379 | needed = 5 |
|
302 |
fmt = b |
|
|
380 | fmt = b"=i" | |
|
303 | 381 | elif int_type == BSER_INT64: |
|
304 | 382 | needed = 9 |
|
305 |
fmt = b |
|
|
383 | fmt = b"=q" | |
|
306 | 384 | else: |
|
307 |
raise ValueError( |
|
|
308 | binascii.hexlify(int_type).decode('ascii')) | |
|
385 | raise ValueError( | |
|
386 | "Invalid bser int encoding 0x%s at position %s" | |
|
387 | % (binascii.hexlify(int_type).decode("ascii"), pos) | |
|
388 | ) | |
|
309 | 389 | int_val = struct.unpack_from(fmt, buf, pos + 1)[0] |
|
310 | 390 | return (int_val, pos + needed) |
|
311 | 391 | |
|
312 | 392 | def unser_utf8_string(self, buf, pos): |
|
313 | 393 | str_len, pos = self.unser_int(buf, pos + 1) |
|
314 |
str_val = struct.unpack_from(tobytes(str_len) + b |
|
|
315 |
return (str_val.decode( |
|
|
394 | str_val = struct.unpack_from(tobytes(str_len) + b"s", buf, pos)[0] | |
|
395 | return (str_val.decode("utf-8"), pos + str_len) | |
|
316 | 396 | |
|
317 | 397 | def unser_bytestring(self, buf, pos): |
|
318 | 398 | str_len, pos = self.unser_int(buf, pos + 1) |
|
319 |
str_val = struct.unpack_from(tobytes(str_len) + b |
|
|
399 | str_val = struct.unpack_from(tobytes(str_len) + b"s", buf, pos)[0] | |
|
320 | 400 | if self.value_encoding is not None: |
|
321 | 401 | str_val = str_val.decode(self.value_encoding, self.value_errors) |
|
322 | 402 | # str_len stays the same because that's the length in bytes |
@@ -325,7 +405,7 b' class Bunser(object):' | |||
|
325 | 405 | def unser_array(self, buf, pos): |
|
326 | 406 | arr_len, pos = self.unser_int(buf, pos + 1) |
|
327 | 407 | arr = [] |
|
328 |
for |
|
|
408 | for _ in range(arr_len): | |
|
329 | 409 | arr_item, pos = self.loads_recursive(buf, pos) |
|
330 | 410 | arr.append(arr_item) |
|
331 | 411 | |
@@ -342,7 +422,7 b' class Bunser(object):' | |||
|
342 | 422 | keys = [] |
|
343 | 423 | vals = [] |
|
344 | 424 | |
|
345 |
for |
|
|
425 | for _ in range(obj_len): | |
|
346 | 426 | key, pos = self.unser_utf8_string(buf, pos) |
|
347 | 427 | val, pos = self.loads_recursive(buf, pos) |
|
348 | 428 | if self.mutable: |
@@ -359,13 +439,13 b' class Bunser(object):' | |||
|
359 | 439 | def unser_template(self, buf, pos): |
|
360 | 440 | val_type = _buf_pos(buf, pos + 1) |
|
361 | 441 | if val_type != BSER_ARRAY: |
|
362 |
raise RuntimeError( |
|
|
442 | raise RuntimeError("Expect ARRAY to follow TEMPLATE") | |
|
363 | 443 | # force UTF-8 on keys |
|
364 |
keys_bunser = Bunser(mutable=self.mutable, value_encoding= |
|
|
444 | keys_bunser = Bunser(mutable=self.mutable, value_encoding="utf-8") | |
|
365 | 445 | keys, pos = keys_bunser.unser_array(buf, pos + 1) |
|
366 | 446 | nitems, pos = self.unser_int(buf, pos) |
|
367 | 447 | arr = [] |
|
368 |
for |
|
|
448 | for _ in range(nitems): | |
|
369 | 449 | if self.mutable: |
|
370 | 450 | obj = {} |
|
371 | 451 | else: |
@@ -392,11 +472,15 b' class Bunser(object):' | |||
|
392 | 472 | |
|
393 | 473 | def loads_recursive(self, buf, pos): |
|
394 | 474 | val_type = _buf_pos(buf, pos) |
|
395 | if (val_type == BSER_INT8 or val_type == BSER_INT16 or | |
|
396 |
val_type == BSER_INT |
|
|
475 | if ( | |
|
476 | val_type == BSER_INT8 | |
|
477 | or val_type == BSER_INT16 | |
|
478 | or val_type == BSER_INT32 | |
|
479 | or val_type == BSER_INT64 | |
|
480 | ): | |
|
397 | 481 | return self.unser_int(buf, pos) |
|
398 | 482 | elif val_type == BSER_REAL: |
|
399 |
val = struct.unpack_from(b |
|
|
483 | val = struct.unpack_from(b"=d", buf, pos + 1)[0] | |
|
400 | 484 | return (val, pos + 9) |
|
401 | 485 | elif val_type == BSER_TRUE: |
|
402 | 486 | return (True, pos + 1) |
@@ -415,23 +499,26 b' class Bunser(object):' | |||
|
415 | 499 | elif val_type == BSER_TEMPLATE: |
|
416 | 500 | return self.unser_template(buf, pos) |
|
417 | 501 | else: |
|
418 |
raise ValueError( |
|
|
419 | binascii.hexlify(val_type).decode('ascii')) | |
|
502 | raise ValueError( | |
|
503 | "unhandled bser opcode 0x%s" | |
|
504 | % binascii.hexlify(val_type).decode("ascii") | |
|
505 | ) | |
|
420 | 506 | |
|
421 | 507 | |
|
422 | 508 | def _pdu_info_helper(buf): |
|
509 | bser_version = -1 | |
|
423 | 510 | if buf[0:2] == EMPTY_HEADER[0:2]: |
|
424 | 511 | bser_version = 1 |
|
425 | 512 | bser_capabilities = 0 |
|
426 | 513 | expected_len, pos2 = Bunser.unser_int(buf, 2) |
|
427 | 514 | elif buf[0:2] == EMPTY_HEADER_V2[0:2]: |
|
428 | 515 | if len(buf) < 8: |
|
429 |
raise ValueError( |
|
|
516 | raise ValueError("Invalid BSER header") | |
|
430 | 517 | bser_version = 2 |
|
431 | 518 | bser_capabilities = struct.unpack_from("I", buf, 2)[0] |
|
432 | 519 | expected_len, pos2 = Bunser.unser_int(buf, 6) |
|
433 | 520 | else: |
|
434 |
raise ValueError( |
|
|
521 | raise ValueError("Invalid BSER header") | |
|
435 | 522 | |
|
436 | 523 | return bser_version, bser_capabilities, expected_len, pos2 |
|
437 | 524 | |
@@ -470,14 +557,20 b' def loads(buf, mutable=True, value_encod' | |||
|
470 | 557 | pos = info[3] |
|
471 | 558 | |
|
472 | 559 | if len(buf) != expected_len + pos: |
|
473 |
raise ValueError( |
|
|
560 | raise ValueError( | |
|
561 | "bser data len %d != header len %d" % (expected_len + pos, len(buf)) | |
|
562 | ) | |
|
474 | 563 | |
|
475 | bunser = Bunser(mutable=mutable, value_encoding=value_encoding, | |
|
476 | value_errors=value_errors) | |
|
564 | bunser = Bunser( | |
|
565 | mutable=mutable, | |
|
566 | value_encoding=value_encoding, | |
|
567 | value_errors=value_errors, | |
|
568 | ) | |
|
477 | 569 | |
|
478 | 570 | return bunser.loads_recursive(buf, pos)[0] |
|
479 | 571 | |
|
480 | 572 | |
|
481 | 573 | def load(fp, mutable=True, value_encoding=None, value_errors=None): |
|
482 | 574 | from . import load |
|
575 | ||
|
483 | 576 | return load.load(fp, mutable, value_encoding, value_errors) |
@@ -14,6 +14,7 b' import struct' | |||
|
14 | 14 | |
|
15 | 15 | from mercurial.i18n import _ |
|
16 | 16 | from mercurial import ( |
|
17 | encoding, | |
|
17 | 18 | pathutil, |
|
18 | 19 | util, |
|
19 | 20 | ) |
@@ -81,7 +82,7 b' class state(object):' | |||
|
81 | 82 | self.invalidate() |
|
82 | 83 | return None, None, None |
|
83 | 84 | diskhostname = state[0] |
|
84 | hostname = socket.gethostname() | |
|
85 | hostname = encoding.strtolocal(socket.gethostname()) | |
|
85 | 86 | if diskhostname != hostname: |
|
86 | 87 | # file got moved to a different host |
|
87 | 88 | self._ui.log( |
@@ -127,7 +128,7 b' class state(object):' | |||
|
127 | 128 | |
|
128 | 129 | with file: |
|
129 | 130 | file.write(struct.pack(_versionformat, _version)) |
|
130 | file.write(socket.gethostname() + b'\0') | |
|
131 | file.write(encoding.strtolocal(socket.gethostname()) + b'\0') | |
|
131 | 132 | file.write(clock + b'\0') |
|
132 | 133 | file.write(ignorehash + b'\0') |
|
133 | 134 | if notefiles: |
@@ -9,7 +9,14 b' from __future__ import absolute_import' | |||
|
9 | 9 | |
|
10 | 10 | import getpass |
|
11 | 11 | |
|
12 |
from mercurial import |
|
|
12 | from mercurial import ( | |
|
13 | encoding, | |
|
14 | util, | |
|
15 | ) | |
|
16 | from mercurial.utils import ( | |
|
17 | procutil, | |
|
18 | stringutil, | |
|
19 | ) | |
|
13 | 20 | |
|
14 | 21 | from . import pywatchman |
|
15 | 22 | |
@@ -22,12 +29,14 b' class Unavailable(Exception):' | |||
|
22 | 29 | self.warn = False |
|
23 | 30 | self.invalidate = invalidate |
|
24 | 31 | |
|
25 |
def __ |
|
|
32 | def __bytes__(self): | |
|
26 | 33 | if self.warn: |
|
27 | 34 | return b'warning: Watchman unavailable: %s' % self.msg |
|
28 | 35 | else: |
|
29 | 36 | return b'Watchman unavailable: %s' % self.msg |
|
30 | 37 | |
|
38 | __str__ = encoding.strmethod(__bytes__) | |
|
39 | ||
|
31 | 40 | |
|
32 | 41 | class WatchmanNoRoot(Unavailable): |
|
33 | 42 | def __init__(self, root, msg): |
@@ -92,15 +101,17 b' class client(object):' | |||
|
92 | 101 | self._watchmanclient = pywatchman.client( |
|
93 | 102 | timeout=self._timeout, |
|
94 | 103 | useImmutableBser=True, |
|
95 |
watchman_exe |
|
|
104 | binpath=procutil.tonativestr(watchman_exe), | |
|
96 | 105 | ) |
|
97 | 106 | return self._watchmanclient.query(*watchmanargs) |
|
98 | 107 | except pywatchman.CommandError as ex: |
|
99 | 108 | if b'unable to resolve root' in ex.msg: |
|
100 |
raise WatchmanNoRoot( |
|
|
109 | raise WatchmanNoRoot( | |
|
110 | self._root, stringutil.forcebytestr(ex.msg) | |
|
111 | ) | |
|
101 | 112 | raise Unavailable(ex.msg) |
|
102 | 113 | except pywatchman.WatchmanError as ex: |
|
103 | raise Unavailable(str(ex)) | |
|
114 | raise Unavailable(stringutil.forcebytestr(ex)) | |
|
104 | 115 | |
|
105 | 116 | def command(self, *args): |
|
106 | 117 | try: |
@@ -76,10 +76,9 b' class gpg(object):' | |||
|
76 | 76 | fp = os.fdopen(fd, r'wb') |
|
77 | 77 | fp.write(data) |
|
78 | 78 | fp.close() |
|
79 | gpgcmd = b"%s --logger-fd 1 --status-fd 1 --verify \"%s\" \"%s\"" % ( | |
|
80 | self.path, | |
|
81 | sigfile, | |
|
82 | datafile, | |
|
79 | gpgcmd = ( | |
|
80 | b"%s --logger-fd 1 --status-fd 1 --verify \"%s\" \"%s\"" | |
|
81 | % (self.path, sigfile, datafile,) | |
|
83 | 82 | ) |
|
84 | 83 | ret = procutil.filter(b"", gpgcmd) |
|
85 | 84 | finally: |
@@ -217,6 +217,7 b' from mercurial import (' | |||
|
217 | 217 | copies, |
|
218 | 218 | destutil, |
|
219 | 219 | discovery, |
|
220 | encoding, | |
|
220 | 221 | error, |
|
221 | 222 | exchange, |
|
222 | 223 | extensions, |
@@ -1117,7 +1118,7 b' class histeditrule(object):' | |||
|
1117 | 1118 | self.pos = pos |
|
1118 | 1119 | self.conflicts = [] |
|
1119 | 1120 | |
|
1120 |
def __ |
|
|
1121 | def __bytes__(self): | |
|
1121 | 1122 | # Some actions ('fold' and 'roll') combine a patch with a previous one. |
|
1122 | 1123 | # Add a marker showing which patch they apply to, and also omit the |
|
1123 | 1124 | # description for 'roll' (since it will get discarded). Example display: |
@@ -1135,10 +1136,16 b' class histeditrule(object):' | |||
|
1135 | 1136 | desc = self.ctx.description().splitlines()[0].strip() |
|
1136 | 1137 | if self.action == b'roll': |
|
1137 | 1138 | desc = b'' |
|
1138 | return b"#{0:<2} {1:<6} {2}:{3} {4}".format( | |
|
1139 | self.origpos, action, r, h, desc | |
|
1139 | return b"#%s %s %d:%s %s" % ( | |
|
1140 | (b'%d' % self.origpos).ljust(2), | |
|
1141 | action.ljust(6), | |
|
1142 | r, | |
|
1143 | h, | |
|
1144 | desc, | |
|
1140 | 1145 | ) |
|
1141 | 1146 | |
|
1147 | __str__ = encoding.strmethod(__bytes__) | |
|
1148 | ||
|
1142 | 1149 | def checkconflicts(self, other): |
|
1143 | 1150 | if other.pos > self.pos and other.origpos <= self.origpos: |
|
1144 | 1151 | if set(other.ctx.files()) & set(self.ctx.files()) != set(): |
@@ -1315,7 +1322,7 b' def makecommands(rules):' | |||
|
1315 | 1322 | our list of rules""" |
|
1316 | 1323 | commands = [] |
|
1317 | 1324 | for rules in rules: |
|
1318 |
commands.append(b |
|
|
1325 | commands.append(b'%s %s\n' % (rules.action, rules.ctx)) | |
|
1319 | 1326 | return commands |
|
1320 | 1327 | |
|
1321 | 1328 | |
@@ -1324,7 +1331,7 b' def addln(win, y, x, line, color=None):' | |||
|
1324 | 1331 | whitespace characters, so that the color appears on the whole line""" |
|
1325 | 1332 | maxy, maxx = win.getmaxyx() |
|
1326 | 1333 | length = maxx - 1 - x |
|
1327 |
line = |
|
|
1334 | line = bytes(line).ljust(length)[:length] | |
|
1328 | 1335 | if y < 0: |
|
1329 | 1336 | y = maxy + y |
|
1330 | 1337 | if x < 0: |
@@ -1395,17 +1402,17 b' def _chisteditmain(repo, rules, stdscr):' | |||
|
1395 | 1402 | maxy, maxx = win.getmaxyx() |
|
1396 | 1403 | length = maxx - 3 |
|
1397 | 1404 | |
|
1398 |
line = b"changeset: |
|
|
1405 | line = b"changeset: %d:%s" % (ctx.rev(), ctx.hex()[:12]) | |
|
1399 | 1406 | win.addstr(1, 1, line[:length]) |
|
1400 | 1407 | |
|
1401 |
line = b"user: |
|
|
1408 | line = b"user: %s" % ctx.user() | |
|
1402 | 1409 | win.addstr(2, 1, line[:length]) |
|
1403 | 1410 | |
|
1404 | 1411 | bms = repo.nodebookmarks(ctx.node()) |
|
1405 |
line = b"bookmark: |
|
|
1412 | line = b"bookmark: %s" % b' '.join(bms) | |
|
1406 | 1413 | win.addstr(3, 1, line[:length]) |
|
1407 | 1414 | |
|
1408 |
line = b"summary: |
|
|
1415 | line = b"summary: %s" % (ctx.description().splitlines()[0]) | |
|
1409 | 1416 | win.addstr(4, 1, line[:length]) |
|
1410 | 1417 | |
|
1411 | 1418 | line = b"files: " |
@@ -1425,8 +1432,8 b' def _chisteditmain(repo, rules, stdscr):' | |||
|
1425 | 1432 | |
|
1426 | 1433 | conflicts = rule.conflicts |
|
1427 | 1434 | if len(conflicts) > 0: |
|
1428 |
conflictstr = b','.join(map(lambda r: |
|
|
1429 |
conflictstr = b"changed files overlap with |
|
|
1435 | conflictstr = b','.join(map(lambda r: r.ctx.hex()[:12], conflicts)) | |
|
1436 | conflictstr = b"changed files overlap with %s" % conflictstr | |
|
1430 | 1437 | else: |
|
1431 | 1438 | conflictstr = b'no overlap' |
|
1432 | 1439 | |
@@ -1464,7 +1471,9 b' pgup/K: move patch up, pgdn/J: move patc' | |||
|
1464 | 1471 | |
|
1465 | 1472 | conflicts = [r.ctx for r in rules if r.conflicts] |
|
1466 | 1473 | if len(conflicts) > 0: |
|
1467 |
line = b"potential conflict in %s" % b','.join( |
|
|
1474 | line = b"potential conflict in %s" % b','.join( | |
|
1475 | map(pycompat.bytestr, conflicts) | |
|
1476 | ) | |
|
1468 | 1477 | addln(rulesscr, -1, 0, line, curses.color_pair(COLOR_WARN)) |
|
1469 | 1478 | |
|
1470 | 1479 | for y, rule in enumerate(rules[start:]): |
@@ -1601,7 +1610,7 b' pgup/K: move patch up, pgdn/J: move patc' | |||
|
1601 | 1610 | renderhelp(helpwin, state) |
|
1602 | 1611 | curses.doupdate() |
|
1603 | 1612 | # done rendering |
|
1604 | ch = stdscr.getkey() | |
|
1613 | ch = encoding.strtolocal(stdscr.getkey()) | |
|
1605 | 1614 | except curses.error: |
|
1606 | 1615 | pass |
|
1607 | 1616 | |
@@ -1675,11 +1684,10 b' def _chistedit(ui, repo, *freeargs, **op' | |||
|
1675 | 1684 | if type(rc) is list: |
|
1676 | 1685 | ui.status(_(b"performing changes\n")) |
|
1677 | 1686 | rules = makecommands(rc) |
|
1678 |
|
|
|
1679 | with open(filename, b'w+') as fp: | |
|
1687 | with repo.vfs(b'chistedit', b'w+') as fp: | |
|
1680 | 1688 | for r in rules: |
|
1681 | 1689 | fp.write(r) |
|
1682 |
opts[ |
|
|
1690 | opts['commands'] = fp.name | |
|
1683 | 1691 | return _texthistedit(ui, repo, *freeargs, **opts) |
|
1684 | 1692 | except KeyboardInterrupt: |
|
1685 | 1693 | pass |
@@ -959,7 +959,7 b' def logservicecall(logger, service, **kw' | |||
|
959 | 959 | service, |
|
960 | 960 | eventtype=b'failure', |
|
961 | 961 | elapsedms=(time.time() - start) * 1000, |
|
962 | errormsg=str(e), | |
|
962 | errormsg=stringutil.forcebytestr(e), | |
|
963 | 963 | **kwargs |
|
964 | 964 | ) |
|
965 | 965 | raise |
@@ -1223,7 +1223,7 b' def storebundle(op, params, bundlefile):' | |||
|
1223 | 1223 | scratchbranchparttype, |
|
1224 | 1224 | eventtype=b'failure', |
|
1225 | 1225 | elapsedms=(time.time() - parthandlerstart) * 1000, |
|
1226 | errormsg=str(e), | |
|
1226 | errormsg=stringutil.forcebytestr(e), | |
|
1227 | 1227 | ) |
|
1228 | 1228 | raise |
|
1229 | 1229 | finally: |
@@ -363,7 +363,7 b' class _gitlfsremote(object):' | |||
|
363 | 363 | _(b'LFS error: %s') % _urlerrorreason(ex), hint=hint |
|
364 | 364 | ) |
|
365 | 365 | try: |
|
366 |
response = |
|
|
366 | response = pycompat.json_loads(rawjson) | |
|
367 | 367 | except ValueError: |
|
368 | 368 | raise LfsRemoteError( |
|
369 | 369 | _(b'LFS server returns invalid JSON: %s') |
@@ -133,7 +133,7 b' def _processbatchrequest(repo, req, res)' | |||
|
133 | 133 | return True |
|
134 | 134 | |
|
135 | 135 | # XXX: specify an encoding? |
|
136 |
lfsreq = |
|
|
136 | lfsreq = pycompat.json_loads(req.bodyfh.read()) | |
|
137 | 137 | |
|
138 | 138 | # If no transfer handlers are explicitly requested, 'basic' is assumed. |
|
139 | 139 | if r'basic' not in lfsreq.get(r'transfers', [r'basic']): |
@@ -148,7 +148,7 b' web.baseurl' | |||
|
148 | 148 | from __future__ import absolute_import |
|
149 | 149 | |
|
150 | 150 | import email.errors as emailerrors |
|
151 |
import email. |
|
|
151 | import email.utils as emailutils | |
|
152 | 152 | import fnmatch |
|
153 | 153 | import hashlib |
|
154 | 154 | import socket |
@@ -382,9 +382,8 b' class notifier(object):' | |||
|
382 | 382 | ) |
|
383 | 383 | return |
|
384 | 384 | |
|
385 | p = emailparser.Parser() | |
|
386 | 385 | try: |
|
387 |
msg = |
|
|
386 | msg = mail.parsebytes(data) | |
|
388 | 387 | except emailerrors.MessageParseError as inst: |
|
389 | 388 | raise error.Abort(inst) |
|
390 | 389 | |
@@ -392,16 +391,16 b' class notifier(object):' | |||
|
392 | 391 | sender = msg[r'From'] |
|
393 | 392 | subject = msg[r'Subject'] |
|
394 | 393 | if sender is not None: |
|
395 |
sender = |
|
|
394 | sender = mail.headdecode(sender) | |
|
396 | 395 | if subject is not None: |
|
397 |
subject = |
|
|
396 | subject = mail.headdecode(subject) | |
|
398 | 397 | del msg[r'From'], msg[r'Subject'] |
|
399 | 398 | |
|
400 | 399 | if not msg.is_multipart(): |
|
401 | 400 | # create fresh mime message from scratch |
|
402 | 401 | # (multipart templates must take care of this themselves) |
|
403 | 402 | headers = msg.items() |
|
404 | payload = msg.get_payload() | |
|
403 | payload = msg.get_payload(decode=pycompat.ispy3) | |
|
405 | 404 | # for notification prefer readability over data precision |
|
406 | 405 | msg = mail.mimeencode(self.ui, payload, self.charsets, self.test) |
|
407 | 406 | # reinstate custom headers |
@@ -440,7 +439,7 b' class notifier(object):' | |||
|
440 | 439 | msg[r'Message-Id'] = messageid(ctx, self.domain, self.messageidseed) |
|
441 | 440 | msg[r'To'] = encoding.strfromlocal(b', '.join(sorted(subs))) |
|
442 | 441 | |
|
443 |
msgtext = |
|
|
442 | msgtext = msg.as_bytes() if pycompat.ispy3 else msg.as_string() | |
|
444 | 443 | if self.test: |
|
445 | 444 | self.ui.write(msgtext) |
|
446 | 445 | if not msgtext.endswith(b'\n'): |
@@ -452,7 +451,7 b' class notifier(object):' | |||
|
452 | 451 | ) |
|
453 | 452 | mail.sendmail( |
|
454 | 453 | self.ui, |
|
455 |
|
|
|
454 | emailutils.parseaddr(msg[r'From'])[1], | |
|
456 | 455 | subs, |
|
457 | 456 | msgtext, |
|
458 | 457 | mbox=self.mbox, |
@@ -960,7 +960,10 b' def email(ui, repo, *revs, **opts):' | |||
|
960 | 960 | hdr = pycompat.strurl(hdr) |
|
961 | 961 | change = True |
|
962 | 962 | if isinstance(val, bytes): |
|
963 | val = pycompat.strurl(val) | |
|
963 | # header value should be ASCII since it's encoded by | |
|
964 | # mail.headencode(), but -n/--test disables it and raw | |
|
965 | # value of platform encoding is stored. | |
|
966 | val = encoding.strfromlocal(val) | |
|
964 | 967 | if not change: |
|
965 | 968 | # prevent duplicate headers |
|
966 | 969 | del m[hdr] |
@@ -152,8 +152,8 b' def vcrcommand(name, flags, spec, helpca' | |||
|
152 | 152 | value = r1params[key][0] |
|
153 | 153 | # we want to compare json payloads without worrying about ordering |
|
154 | 154 | if value.startswith(b'{') and value.endswith(b'}'): |
|
155 |
r1json = |
|
|
156 |
r2json = |
|
|
155 | r1json = pycompat.json_loads(value) | |
|
156 | r2json = pycompat.json_loads(r2params[key][0]) | |
|
157 | 157 | if r1json != r2json: |
|
158 | 158 | return False |
|
159 | 159 | elif r2params[key][0] != value: |
@@ -307,7 +307,7 b' def callconduit(ui, name, params):' | |||
|
307 | 307 | if isinstance(x, pycompat.unicode) |
|
308 | 308 | else x, |
|
309 | 309 | # json.loads only accepts bytes from py3.6+ |
|
310 |
|
|
|
310 | pycompat.json_loads(encoding.unifromlocal(body)), | |
|
311 | 311 | ) |
|
312 | 312 | if parsed.get(b'error_code'): |
|
313 | 313 | msg = _(b'Conduit Error (%s): %s') % ( |
@@ -332,7 +332,7 b' def debugcallconduit(ui, repo, name):' | |||
|
332 | 332 | lambda x: encoding.unitolocal(x) |
|
333 | 333 | if isinstance(x, pycompat.unicode) |
|
334 | 334 | else x, |
|
335 |
|
|
|
335 | pycompat.json_loads(rawparams), | |
|
336 | 336 | ) |
|
337 | 337 | # json.dumps only accepts unicode strings |
|
338 | 338 | result = pycompat.rapply( |
@@ -441,7 +441,7 b' def getoldnodedrevmap(repo, nodelist):' | |||
|
441 | 441 | ) |
|
442 | 442 | unfi.ui.warn( |
|
443 | 443 | _( |
|
444 |
b'D% |
|
|
444 | b'D%d: local tag removed - does not match ' | |
|
445 | 445 | b'Differential history\n' |
|
446 | 446 | ) |
|
447 | 447 | % drev |
@@ -1168,7 +1168,7 b' def phabsend(ui, repo, *revs, **opts):' | |||
|
1168 | 1168 | writediffproperties(unfi[newnode], diffmap[old.node()]) |
|
1169 | 1169 | except util.urlerr.urlerror: |
|
1170 | 1170 | ui.warnnoi18n( |
|
1171 |
b'Failed to update metadata for D% |
|
|
1171 | b'Failed to update metadata for D%d\n' % drevid | |
|
1172 | 1172 | ) |
|
1173 | 1173 | # Remove local tags since it's no longer necessary |
|
1174 | 1174 | tagname = b'D%d' % drevid |
@@ -1208,7 +1208,7 b' def _confirmbeforesend(repo, revs, oldma' | |||
|
1208 | 1208 | desc = ctx.description().splitlines()[0] |
|
1209 | 1209 | oldnode, olddiff, drevid = oldmap.get(ctx.node(), (None, None, None)) |
|
1210 | 1210 | if drevid: |
|
1211 |
drevdesc = ui.label(b'D% |
|
|
1211 | drevdesc = ui.label(b'D%d' % drevid, b'phabricator.drev') | |
|
1212 | 1212 | else: |
|
1213 | 1213 | drevdesc = ui.label(_(b'NEW'), b'phabricator.drev') |
|
1214 | 1214 | |
@@ -1613,7 +1613,7 b' def phabupdate(ui, repo, spec, **opts):' | |||
|
1613 | 1613 | |
|
1614 | 1614 | actions = [] |
|
1615 | 1615 | for f in flags: |
|
1616 |
actions.append({b'type': f, b'value': |
|
|
1616 | actions.append({b'type': f, b'value': True}) | |
|
1617 | 1617 | |
|
1618 | 1618 | drevs = querydrev(repo, spec) |
|
1619 | 1619 | for i, drev in enumerate(drevs): |
@@ -2267,7 +2267,13 b' def config(ui, repo, *values, **opts):' | |||
|
2267 | 2267 | fm.write(b'value', b'%s\n', value) |
|
2268 | 2268 | else: |
|
2269 | 2269 | fm.write(b'name value', b'%s=%s\n', entryname, value) |
|
2270 | if formatter.isprintable(defaultvalue): | |
|
2270 | 2271 | fm.data(defaultvalue=defaultvalue) |
|
2272 | elif isinstance(defaultvalue, list) and all( | |
|
2273 | formatter.isprintable(e) for e in defaultvalue | |
|
2274 | ): | |
|
2275 | fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value')) | |
|
2276 | # TODO: no idea how to process unsupported defaultvalue types | |
|
2271 | 2277 | matched = True |
|
2272 | 2278 | fm.end() |
|
2273 | 2279 | if matched: |
@@ -212,11 +212,9 b' class config(object):' | |||
|
212 | 212 | def read(self, path, fp=None, sections=None, remap=None): |
|
213 | 213 | if not fp: |
|
214 | 214 | fp = util.posixfile(path, b'rb') |
|
215 | assert ( | |
|
216 | getattr(fp, 'mode', r'rb') == r'rb' | |
|
217 | ), b'config files must be opened in binary mode, got fp=%r mode=%r' % ( | |
|
218 | fp, | |
|
219 | fp.mode, | |
|
215 | assert getattr(fp, 'mode', r'rb') == r'rb', ( | |
|
216 | b'config files must be opened in binary mode, got fp=%r mode=%r' | |
|
217 | % (fp, fp.mode,) | |
|
220 | 218 | ) |
|
221 | 219 | self.parse( |
|
222 | 220 | path, fp.read(), sections=sections, remap=remap, include=self.read |
@@ -1187,10 +1187,9 b' class filectx(basefilectx):' | |||
|
1187 | 1187 | |
|
1188 | 1188 | assert ( |
|
1189 | 1189 | changeid is not None or fileid is not None or changectx is not None |
|
1190 | ), b"bad args: changeid=%r, fileid=%r, changectx=%r" % ( | |
|
1191 | changeid, | |
|
1192 | fileid, | |
|
1193 | changectx, | |
|
1190 | ), ( | |
|
1191 | b"bad args: changeid=%r, fileid=%r, changectx=%r" | |
|
1192 | % (changeid, fileid, changectx,) | |
|
1194 | 1193 | ) |
|
1195 | 1194 | |
|
1196 | 1195 | if filelog is not None: |
@@ -1816,7 +1816,7 b' are you sure you want to review/edit and' | |||
|
1816 | 1816 | try: |
|
1817 | 1817 | patch = self.ui.edit(patch.getvalue(), b"", action=b"diff") |
|
1818 | 1818 | except error.Abort as exc: |
|
1819 | self.errorstr = str(exc) | |
|
1819 | self.errorstr = stringutil.forcebytestr(exc) | |
|
1820 | 1820 | return None |
|
1821 | 1821 | finally: |
|
1822 | 1822 | self.stdscr.clear() |
@@ -111,6 +111,14 b' class Abort(Hint, Exception):' | |||
|
111 | 111 | |
|
112 | 112 | __bytes__ = _tobytes |
|
113 | 113 | |
|
114 | if pycompat.ispy3: | |
|
115 | ||
|
116 | def __str__(self): | |
|
117 | # the output would be unreadable if the message was translated, | |
|
118 | # but do not replace it with encoding.strfromlocal(), which | |
|
119 | # may raise another exception. | |
|
120 | return pycompat.sysstr(self.__bytes__()) | |
|
121 | ||
|
114 | 122 | |
|
115 | 123 | class HookLoadError(Abort): |
|
116 | 124 | """raised when loading a hook fails, aborting an operation |
@@ -136,6 +136,16 b' from .utils import (' | |||
|
136 | 136 | pickle = util.pickle |
|
137 | 137 | |
|
138 | 138 | |
|
139 | def isprintable(obj): | |
|
140 | """Check if the given object can be directly passed in to formatter's | |
|
141 | write() and data() functions | |
|
142 | ||
|
143 | Returns False if the object is unsupported or must be pre-processed by | |
|
144 | formatdate(), formatdict(), or formatlist(). | |
|
145 | """ | |
|
146 | return isinstance(obj, (type(None), bool, int, pycompat.long, float, bytes)) | |
|
147 | ||
|
148 | ||
|
139 | 149 | class _nullconverter(object): |
|
140 | 150 | '''convert non-primitive data types to be processed by formatter''' |
|
141 | 151 | |
@@ -505,6 +515,10 b' class templateformatter(baseformatter):' | |||
|
505 | 515 | if part not in self._parts: |
|
506 | 516 | return |
|
507 | 517 | ref = self._parts[part] |
|
518 | # None can't be put in the mapping dict since it means <unset> | |
|
519 | for k, v in item.items(): | |
|
520 | if v is None: | |
|
521 | item[k] = templateutil.wrappedvalue(v) | |
|
508 | 522 | self._out.write(self._t.render(ref, item)) |
|
509 | 523 | |
|
510 | 524 | @util.propertycache |
@@ -1417,7 +1417,7 b' class localrepository(object):' | |||
|
1417 | 1417 | |
|
1418 | 1418 | def _refreshchangelog(self): |
|
1419 | 1419 | """make sure the in memory changelog match the on-disk one""" |
|
1420 |
if |
|
|
1420 | if 'changelog' in vars(self) and self.currenttransaction() is None: | |
|
1421 | 1421 | del self.changelog |
|
1422 | 1422 | |
|
1423 | 1423 | @property |
@@ -342,6 +342,7 b' def _encode(ui, s, charsets):' | |||
|
342 | 342 | s.decode('ascii') |
|
343 | 343 | except UnicodeDecodeError: |
|
344 | 344 | for ics in (encoding.encoding, encoding.fallbackencoding): |
|
345 | ics = pycompat.sysstr(ics) | |
|
345 | 346 | try: |
|
346 | 347 | u = s.decode(ics) |
|
347 | 348 | except UnicodeDecodeError: |
@@ -362,13 +363,13 b' def headencode(ui, s, charsets=None, dis' | |||
|
362 | 363 | if not display: |
|
363 | 364 | # split into words? |
|
364 | 365 | s, cs = _encode(ui, s, charsets) |
|
365 | return str(email.header.Header(s, cs)) | |
|
366 | return encoding.strtolocal(email.header.Header(s, cs).encode()) | |
|
366 | 367 | return s |
|
367 | 368 | |
|
368 | 369 | |
|
369 | 370 | def _addressencode(ui, name, addr, charsets=None): |
|
370 | 371 | assert isinstance(addr, bytes) |
|
371 | name = headencode(ui, name, charsets) | |
|
372 | name = encoding.strfromlocal(headencode(ui, name, charsets)) | |
|
372 | 373 | try: |
|
373 | 374 | acc, dom = addr.split(b'@') |
|
374 | 375 | acc.decode('ascii') |
@@ -440,6 +441,10 b' if pycompat.ispy3:' | |||
|
440 | 441 | finally: |
|
441 | 442 | fp.detach() |
|
442 | 443 | |
|
444 | def parsebytes(data): | |
|
445 | ep = email.parser.BytesParser() | |
|
446 | return ep.parsebytes(data) | |
|
447 | ||
|
443 | 448 | |
|
444 | 449 | else: |
|
445 | 450 | |
@@ -449,6 +454,10 b' else:' | |||
|
449 | 454 | ep = email.parser.Parser() |
|
450 | 455 | return ep.parse(fp) |
|
451 | 456 | |
|
457 | def parsebytes(data): | |
|
458 | ep = email.parser.Parser() | |
|
459 | return ep.parsestr(data) | |
|
460 | ||
|
452 | 461 | |
|
453 | 462 | def headdecode(s): |
|
454 | 463 | '''Decodes RFC-2047 header''' |
@@ -458,7 +467,7 b' def headdecode(s):' | |||
|
458 | 467 | try: |
|
459 | 468 | uparts.append(part.decode(charset)) |
|
460 | 469 | continue |
|
461 | except UnicodeDecodeError: | |
|
470 | except (UnicodeDecodeError, LookupError): | |
|
462 | 471 | pass |
|
463 | 472 | # On Python 3, decode_header() may return either bytes or unicode |
|
464 | 473 | # depending on whether the header has =?<charset>? or not |
@@ -867,13 +867,16 b' class treemanifest(object):' | |||
|
867 | 867 | return not self._dirs or all(m._isempty() for m in self._dirs.values()) |
|
868 | 868 | |
|
869 | 869 | def __repr__(self): |
|
870 | return b'<treemanifest dir=%s, node=%s, loaded=%s, dirty=%s at 0x%x>' % ( | |
|
870 | return ( | |
|
871 | b'<treemanifest dir=%s, node=%s, loaded=%s, dirty=%s at 0x%x>' | |
|
872 | % ( | |
|
871 | 873 | self._dir, |
|
872 | 874 | hex(self._node), |
|
873 | 875 | bool(self._loadfunc is _noop), |
|
874 | 876 | self._dirty, |
|
875 | 877 | id(self), |
|
876 | 878 | ) |
|
879 | ) | |
|
877 | 880 | |
|
878 | 881 | def dir(self): |
|
879 | 882 | '''The directory that this tree manifest represents, including a |
@@ -12,6 +12,7 b' from __future__ import absolute_import' | |||
|
12 | 12 | |
|
13 | 13 | import getopt |
|
14 | 14 | import inspect |
|
15 | import json | |
|
15 | 16 | import os |
|
16 | 17 | import shlex |
|
17 | 18 | import sys |
@@ -88,6 +89,7 b' def rapply(f, xs):' | |||
|
88 | 89 | |
|
89 | 90 | if ispy3: |
|
90 | 91 | import builtins |
|
92 | import codecs | |
|
91 | 93 | import functools |
|
92 | 94 | import io |
|
93 | 95 | import struct |
@@ -347,6 +349,48 b' if ispy3:' | |||
|
347 | 349 | iteritems = lambda x: x.items() |
|
348 | 350 | itervalues = lambda x: x.values() |
|
349 | 351 | |
|
352 | # Python 3.5's json.load and json.loads require str. We polyfill its | |
|
353 | # code for detecting encoding from bytes. | |
|
354 | if sys.version_info[0:2] < (3, 6): | |
|
355 | ||
|
356 | def _detect_encoding(b): | |
|
357 | bstartswith = b.startswith | |
|
358 | if bstartswith((codecs.BOM_UTF32_BE, codecs.BOM_UTF32_LE)): | |
|
359 | return 'utf-32' | |
|
360 | if bstartswith((codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE)): | |
|
361 | return 'utf-16' | |
|
362 | if bstartswith(codecs.BOM_UTF8): | |
|
363 | return 'utf-8-sig' | |
|
364 | ||
|
365 | if len(b) >= 4: | |
|
366 | if not b[0]: | |
|
367 | # 00 00 -- -- - utf-32-be | |
|
368 | # 00 XX -- -- - utf-16-be | |
|
369 | return 'utf-16-be' if b[1] else 'utf-32-be' | |
|
370 | if not b[1]: | |
|
371 | # XX 00 00 00 - utf-32-le | |
|
372 | # XX 00 00 XX - utf-16-le | |
|
373 | # XX 00 XX -- - utf-16-le | |
|
374 | return 'utf-16-le' if b[2] or b[3] else 'utf-32-le' | |
|
375 | elif len(b) == 2: | |
|
376 | if not b[0]: | |
|
377 | # 00 XX - utf-16-be | |
|
378 | return 'utf-16-be' | |
|
379 | if not b[1]: | |
|
380 | # XX 00 - utf-16-le | |
|
381 | return 'utf-16-le' | |
|
382 | # default | |
|
383 | return 'utf-8' | |
|
384 | ||
|
385 | def json_loads(s, *args, **kwargs): | |
|
386 | if isinstance(s, (bytes, bytearray)): | |
|
387 | s = s.decode(_detect_encoding(s), 'surrogatepass') | |
|
388 | ||
|
389 | return json.loads(s, *args, **kwargs) | |
|
390 | ||
|
391 | else: | |
|
392 | json_loads = json.loads | |
|
393 | ||
|
350 | 394 | else: |
|
351 | 395 | import cStringIO |
|
352 | 396 | |
@@ -424,6 +468,7 b' else:' | |||
|
424 | 468 | getargspec = inspect.getargspec |
|
425 | 469 | iteritems = lambda x: x.iteritems() |
|
426 | 470 | itervalues = lambda x: x.itervalues() |
|
471 | json_loads = json.loads | |
|
427 | 472 | |
|
428 | 473 | isjython = sysplatform.startswith(b'java') |
|
429 | 474 |
@@ -1854,7 +1854,7 b' class simplekeyvaluefile(object):' | |||
|
1854 | 1854 | raise error.CorruptedState(e % self.firstlinekey) |
|
1855 | 1855 | d.update(updatedict) |
|
1856 | 1856 | except ValueError as e: |
|
1857 | raise error.CorruptedState(str(e)) | |
|
1857 | raise error.CorruptedState(stringutil.forcebytestr(e)) | |
|
1858 | 1858 | return d |
|
1859 | 1859 | |
|
1860 | 1860 | def write(self, data, firstline=None): |
@@ -31,9 +31,6 b' from .utils import (' | |||
|
31 | 31 | urlerr = util.urlerr |
|
32 | 32 | urlreq = util.urlreq |
|
33 | 33 | |
|
34 | if pycompat.ispy3: | |
|
35 | long = int | |
|
36 | ||
|
37 | 34 | # filters are callables like: |
|
38 | 35 | # fn(obj) |
|
39 | 36 | # with: |
@@ -329,7 +326,7 b' def json(obj, paranoid=True):' | |||
|
329 | 326 | return b'false' |
|
330 | 327 | elif obj is True: |
|
331 | 328 | return b'true' |
|
332 | elif isinstance(obj, (int, long, float)): | |
|
329 | elif isinstance(obj, (int, pycompat.long, float)): | |
|
333 | 330 | return pycompat.bytestr(obj) |
|
334 | 331 | elif isinstance(obj, bytes): |
|
335 | 332 | return b'"%s"' % encoding.jsonescape(obj, paranoid=paranoid) |
@@ -1564,6 +1564,7 b' class ui(object):' | |||
|
1564 | 1564 | # - http://bugs.python.org/issue12833 |
|
1565 | 1565 | with self.timeblockedsection(b'stdio'): |
|
1566 | 1566 | if usereadline: |
|
1567 | self.flush() | |
|
1567 | 1568 | prompt = encoding.strfromlocal(prompt) |
|
1568 | 1569 | line = encoding.strtolocal(pycompat.rawinput(prompt)) |
|
1569 | 1570 | # When stdin is in binary mode on Windows, it can cause |
@@ -6,17 +6,12 b'' | |||
|
6 | 6 | |
|
7 | 7 | import os |
|
8 | 8 | |
|
9 | supportedpy = '~= 2.7' | |
|
10 | if os.environ.get('HGALLOWPYTHON3', ''): | |
|
11 | 9 |
|
|
12 | 10 |
|
|
13 | 11 |
|
|
14 | 12 |
|
|
15 | 13 |
|
|
16 | 14 |
|
|
17 | # | |
|
18 | # TODO: when we actually work on Python 3, use this string as the | |
|
19 | # actual supportedpy string. | |
|
20 | 15 |
|
|
21 | 16 |
|
|
22 | 17 |
|
@@ -89,39 +84,6 b' Python {py} detected.' | |||
|
89 | 84 | printf(error, file=sys.stderr) |
|
90 | 85 | sys.exit(1) |
|
91 | 86 | |
|
92 | # We don't yet officially support Python 3. But we want to allow developers to | |
|
93 | # hack on. Detect and disallow running on Python 3 by default. But provide a | |
|
94 | # backdoor to enable working on Python 3. | |
|
95 | if sys.version_info[0] != 2: | |
|
96 | badpython = True | |
|
97 | ||
|
98 | # Allow Python 3 from source checkouts. | |
|
99 | if os.path.isdir('.hg') or 'HGPYTHON3' in os.environ: | |
|
100 | badpython = False | |
|
101 | ||
|
102 | if badpython: | |
|
103 | error = """ | |
|
104 | Python {py} detected. | |
|
105 | ||
|
106 | Mercurial currently has beta support for Python 3 and use of Python 2.7 is | |
|
107 | recommended for the best experience. | |
|
108 | ||
|
109 | Please re-run with Python 2.7 for a faster, less buggy experience. | |
|
110 | ||
|
111 | If you would like to beta test Mercurial with Python 3, this error can | |
|
112 | be suppressed by defining the HGPYTHON3 environment variable when invoking | |
|
113 | this command. No special environment variables or configuration changes are | |
|
114 | necessary to run `hg` with Python 3. | |
|
115 | ||
|
116 | See https://www.mercurial-scm.org/wiki/Python3 for more on Mercurial's | |
|
117 | Python 3 support. | |
|
118 | """.format( | |
|
119 | py='.'.join('%d' % x for x in sys.version_info[0:2]) | |
|
120 | ) | |
|
121 | ||
|
122 | printf(error, file=sys.stderr) | |
|
123 | sys.exit(1) | |
|
124 | ||
|
125 | 87 | if sys.version_info[0] >= 3: |
|
126 | 88 | DYLIB_SUFFIX = sysconfig.get_config_vars()['EXT_SUFFIX'] |
|
127 | 89 | else: |
@@ -98,7 +98,7 b' def request(host, path, show):' | |||
|
98 | 98 | if formatjson: |
|
99 | 99 | # json.dumps() will print trailing newlines. Eliminate them |
|
100 | 100 | # to make tests easier to write. |
|
101 |
data = |
|
|
101 | data = pycompat.json_loads(data) | |
|
102 | 102 | lines = json.dumps(data, sort_keys=True, indent=2).splitlines() |
|
103 | 103 | for line in lines: |
|
104 | 104 | bodyfh.write(pycompat.sysbytes(line.rstrip())) |
@@ -1,5 +1,6 b'' | |||
|
1 | 1 | from __future__ import absolute_import, print_function |
|
2 | 2 | |
|
3 | import distutils.version | |
|
3 | 4 | import os |
|
4 | 5 | import re |
|
5 | 6 | import socket |
@@ -828,6 +829,17 b' def has_dev_full():' | |||
|
828 | 829 | return os.path.exists('/dev/full') |
|
829 | 830 | |
|
830 | 831 | |
|
832 | @check("ensurepip", "ensurepip module") | |
|
833 | def has_ensurepip(): | |
|
834 | try: | |
|
835 | import ensurepip | |
|
836 | ||
|
837 | ensurepip.bootstrap | |
|
838 | return True | |
|
839 | except ImportError: | |
|
840 | return False | |
|
841 | ||
|
842 | ||
|
831 | 843 | @check("virtualenv", "Python virtualenv support") |
|
832 | 844 | def has_virtualenv(): |
|
833 | 845 | try: |
@@ -980,12 +992,10 b' def has_emacs():' | |||
|
980 | 992 | return matchoutput('emacs --version', b'GNU Emacs 2(4.4|4.5|5|6|7|8|9)') |
|
981 | 993 | |
|
982 | 994 | |
|
983 |
|
|
|
984 | @check('grey', 'grey, the fork of the black formatter for python') | |
|
995 | @check('black', 'the black formatter for python') | |
|
985 | 996 | def has_black(): |
|
986 | # use that to actual black as soon as possible | |
|
987 | # blackcmd = 'black --version' | |
|
988 | blackcmd = 'python3 $RUNTESTDIR/../contrib/grey.py --version' | |
|
989 | # version_regex = b'black, version \d' | |
|
990 | version_regex = b'grey.py, version \d' | |
|
991 | return matchoutput(blackcmd, version_regex) | |
|
997 | blackcmd = 'black --version' | |
|
998 | version_regex = b'black, version ([0-9a-b.]+)' | |
|
999 | version = matchoutput(blackcmd, version_regex) | |
|
1000 | sv = distutils.version.StrictVersion | |
|
1001 | return version and sv(_strpath(version.group(1))) >= sv('19.10b0') |
@@ -1504,7 +1504,7 b' class PythonTest(Test):' | |||
|
1504 | 1504 | py3switch = self._py3warnings and b' -3' or b'' |
|
1505 | 1505 | # Quote the python(3) executable for Windows |
|
1506 | 1506 | cmd = b'"%s"%s "%s"' % (PYTHON, py3switch, self.path) |
|
1507 | vlog("# Running", cmd) | |
|
1507 | vlog("# Running", cmd.decode("utf-8")) | |
|
1508 | 1508 | normalizenewlines = os.name == 'nt' |
|
1509 | 1509 | result = self._runcommand(cmd, env, normalizenewlines=normalizenewlines) |
|
1510 | 1510 | if self._aborted: |
@@ -1589,7 +1589,7 b' class TTest(Test):' | |||
|
1589 | 1589 | f.write(l) |
|
1590 | 1590 | |
|
1591 | 1591 | cmd = b'%s "%s"' % (self._shell, fname) |
|
1592 | vlog("# Running", cmd) | |
|
1592 | vlog("# Running", cmd.decode("utf-8")) | |
|
1593 | 1593 | |
|
1594 | 1594 | exitcode, output = self._runcommand(cmd, env) |
|
1595 | 1595 | |
@@ -1770,7 +1770,9 b' class TTest(Test):' | |||
|
1770 | 1770 | if l.startswith(b'#require'): |
|
1771 | 1771 | lsplit = l.split() |
|
1772 | 1772 | if len(lsplit) < 2 or lsplit[0] != b'#require': |
|
1773 |
after.setdefault(pos, []).append( |
|
|
1773 | after.setdefault(pos, []).append( | |
|
1774 | b' !!! invalid #require\n' | |
|
1775 | ) | |
|
1774 | 1776 | if not skipping: |
|
1775 | 1777 | haveresult, message = self._hghave(lsplit[1:]) |
|
1776 | 1778 | if not haveresult: |
@@ -1780,19 +1782,19 b' class TTest(Test):' | |||
|
1780 | 1782 | elif l.startswith(b'#if'): |
|
1781 | 1783 | lsplit = l.split() |
|
1782 | 1784 | if len(lsplit) < 2 or lsplit[0] != b'#if': |
|
1783 | after.setdefault(pos, []).append(' !!! invalid #if\n') | |
|
1785 | after.setdefault(pos, []).append(b' !!! invalid #if\n') | |
|
1784 | 1786 | if skipping is not None: |
|
1785 | after.setdefault(pos, []).append(' !!! nested #if\n') | |
|
1787 | after.setdefault(pos, []).append(b' !!! nested #if\n') | |
|
1786 | 1788 | skipping = not self._iftest(lsplit[1:]) |
|
1787 | 1789 | after.setdefault(pos, []).append(l) |
|
1788 | 1790 | elif l.startswith(b'#else'): |
|
1789 | 1791 | if skipping is None: |
|
1790 | after.setdefault(pos, []).append(' !!! missing #if\n') | |
|
1792 | after.setdefault(pos, []).append(b' !!! missing #if\n') | |
|
1791 | 1793 | skipping = not skipping |
|
1792 | 1794 | after.setdefault(pos, []).append(l) |
|
1793 | 1795 | elif l.startswith(b'#endif'): |
|
1794 | 1796 | if skipping is None: |
|
1795 | after.setdefault(pos, []).append(' !!! missing #if\n') | |
|
1797 | after.setdefault(pos, []).append(b' !!! missing #if\n') | |
|
1796 | 1798 | skipping = None |
|
1797 | 1799 | after.setdefault(pos, []).append(l) |
|
1798 | 1800 | elif skipping: |
@@ -1841,7 +1843,7 b' class TTest(Test):' | |||
|
1841 | 1843 | if inpython: |
|
1842 | 1844 | script.append(b'EOF\n') |
|
1843 | 1845 | if skipping is not None: |
|
1844 | after.setdefault(pos, []).append(' !!! missing #endif\n') | |
|
1846 | after.setdefault(pos, []).append(b' !!! missing #endif\n') | |
|
1845 | 1847 | addsalt(n + 1, False) |
|
1846 | 1848 | # Need to end any current per-command trace |
|
1847 | 1849 | if activetrace: |
@@ -3111,12 +3113,14 b' class TestRunner(object):' | |||
|
3111 | 3113 | 'extensions.logexceptions=%s' % logexceptions.decode('utf-8') |
|
3112 | 3114 | ) |
|
3113 | 3115 | |
|
3114 | vlog("# Using TESTDIR", self._testdir) | |
|
3115 | vlog("# Using RUNTESTDIR", osenvironb[b'RUNTESTDIR']) | |
|
3116 | vlog("# Using HGTMP", self._hgtmp) | |
|
3116 | vlog("# Using TESTDIR", _strpath(self._testdir)) | |
|
3117 | vlog("# Using RUNTESTDIR", _strpath(osenvironb[b'RUNTESTDIR'])) | |
|
3118 | vlog("# Using HGTMP", _strpath(self._hgtmp)) | |
|
3117 | 3119 | vlog("# Using PATH", os.environ["PATH"]) |
|
3118 | vlog("# Using", IMPL_PATH, osenvironb[IMPL_PATH]) | |
|
3119 | vlog("# Writing to directory", self._outputdir) | |
|
3120 | vlog( | |
|
3121 | "# Using", _strpath(IMPL_PATH), _strpath(osenvironb[IMPL_PATH]), | |
|
3122 | ) | |
|
3123 | vlog("# Writing to directory", _strpath(self._outputdir)) | |
|
3120 | 3124 | |
|
3121 | 3125 | try: |
|
3122 | 3126 | return self._runtests(testdescs) or 0 |
@@ -3357,7 +3361,7 b' class TestRunner(object):' | |||
|
3357 | 3361 | if self.options.keep_tmpdir: |
|
3358 | 3362 | return |
|
3359 | 3363 | |
|
3360 | vlog("# Cleaning up HGTMP", self._hgtmp) | |
|
3364 | vlog("# Cleaning up HGTMP", _strpath(self._hgtmp)) | |
|
3361 | 3365 | shutil.rmtree(self._hgtmp, True) |
|
3362 | 3366 | for f in self._createdfiles: |
|
3363 | 3367 | try: |
@@ -3468,7 +3472,7 b' class TestRunner(object):' | |||
|
3468 | 3472 | makedirs(self._pythondir) |
|
3469 | 3473 | makedirs(self._bindir) |
|
3470 | 3474 | |
|
3471 | vlog("# Running", cmd) | |
|
3475 | vlog("# Running", cmd.decode("utf-8")) | |
|
3472 | 3476 | if subprocess.call(_strpath(cmd), shell=True) == 0: |
|
3473 | 3477 | if not self.options.verbose: |
|
3474 | 3478 | try: |
@@ -3643,13 +3647,11 b' class TestRunner(object):' | |||
|
3643 | 3647 | if os.name == 'nt' and not p.endswith(b'.exe'): |
|
3644 | 3648 | p += b'.exe' |
|
3645 | 3649 | found = self._findprogram(p) |
|
3650 | p = p.decode("utf-8") | |
|
3646 | 3651 | if found: |
|
3647 | vlog("# Found prerequisite", p, "at", found) | |
|
3652 | vlog("# Found prerequisite", p, "at", _strpath(found)) | |
|
3648 | 3653 | else: |
|
3649 | print( | |
|
3650 | "WARNING: Did not find prerequisite tool: %s " | |
|
3651 | % p.decode("utf-8") | |
|
3652 | ) | |
|
3654 | print("WARNING: Did not find prerequisite tool: %s " % p) | |
|
3653 | 3655 | |
|
3654 | 3656 | |
|
3655 | 3657 | def aggregateexceptions(path): |
@@ -1,4 +1,4 b'' | |||
|
1 | #require py3 | |
|
1 | #require py37 | |
|
2 | 2 | |
|
3 | 3 | $ byteify_strings () { |
|
4 | 4 | > $PYTHON "$TESTDIR/../contrib/byteify-strings.py" "$@" |
@@ -21,7 +21,6 b' New errors are not allowed. Warnings are' | |||
|
21 | 21 | Skipping contrib/automation/hgautomation/try_server.py it has no-che?k-code (glob) |
|
22 | 22 | Skipping contrib/automation/hgautomation/windows.py it has no-che?k-code (glob) |
|
23 | 23 | Skipping contrib/automation/hgautomation/winrm.py it has no-che?k-code (glob) |
|
24 | Skipping contrib/grey.py it has no-che?k-code (glob) | |
|
25 | 24 | Skipping contrib/packaging/hgpackaging/downloads.py it has no-che?k-code (glob) |
|
26 | 25 | Skipping contrib/packaging/hgpackaging/inno.py it has no-che?k-code (glob) |
|
27 | 26 | Skipping contrib/packaging/hgpackaging/py2exe.py it has no-che?k-code (glob) |
@@ -1,7 +1,5 b'' | |||
|
1 |
#require |
|
|
2 | ||
|
3 | (this should use the actual black as soon as possible) | |
|
1 | #require black | |
|
4 | 2 | |
|
5 | 3 | $ cd $RUNTESTDIR/.. |
|
6 |
$ |
|
|
4 | $ black --config=black.toml --check --diff `hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"'` | |
|
7 | 5 |
@@ -20,7 +20,6 b' outputs, which should be fixed later.' | |||
|
20 | 20 | > -X setup.py \ |
|
21 | 21 | > -X contrib/automation/ \ |
|
22 | 22 | > -X contrib/debugshell.py \ |
|
23 | > -X contrib/grey.py \ | |
|
24 | 23 | > -X contrib/hgweb.fcgi \ |
|
25 | 24 | > -X contrib/packaging/hg-docker \ |
|
26 | 25 | > -X contrib/packaging/hgpackaging/ \ |
@@ -6,7 +6,6 b'' | |||
|
6 | 6 | #if no-py3 |
|
7 | 7 | $ testrepohg files 'set:(**.py)' \ |
|
8 | 8 | > -X contrib/automation/ \ |
|
9 | > -X contrib/grey.py \ | |
|
10 | 9 | > -X contrib/packaging/hgpackaging/ \ |
|
11 | 10 | > -X contrib/packaging/inno/ \ |
|
12 | 11 | > -X contrib/packaging/wix/ \ |
@@ -87,6 +87,172 b' Test case sensitive configuration' | |||
|
87 | 87 | } |
|
88 | 88 | ] |
|
89 | 89 | |
|
90 | Test config default of various types: | |
|
91 | ||
|
92 | {"defaultvalue": ""} for -T'json(defaultvalue)' looks weird, but that's | |
|
93 | how the templater works. Unknown keywords are evaluated to "". | |
|
94 | ||
|
95 | dynamicdefault | |
|
96 | ||
|
97 | $ hg config --config alias.foo= alias -Tjson | |
|
98 | [ | |
|
99 | { | |
|
100 | "name": "alias.foo", | |
|
101 | "source": "--config", | |
|
102 | "value": "" | |
|
103 | } | |
|
104 | ] | |
|
105 | $ hg config --config alias.foo= alias -T'json(defaultvalue)' | |
|
106 | [ | |
|
107 | {"defaultvalue": ""} | |
|
108 | ] | |
|
109 | $ hg config --config alias.foo= alias -T'{defaultvalue}\n' | |
|
110 | ||
|
111 | ||
|
112 | null | |
|
113 | ||
|
114 | $ hg config --config auth.cookiefile= auth -Tjson | |
|
115 | [ | |
|
116 | { | |
|
117 | "defaultvalue": null, | |
|
118 | "name": "auth.cookiefile", | |
|
119 | "source": "--config", | |
|
120 | "value": "" | |
|
121 | } | |
|
122 | ] | |
|
123 | $ hg config --config auth.cookiefile= auth -T'json(defaultvalue)' | |
|
124 | [ | |
|
125 | {"defaultvalue": null} | |
|
126 | ] | |
|
127 | $ hg config --config auth.cookiefile= auth -T'{defaultvalue}\n' | |
|
128 | ||
|
129 | ||
|
130 | false | |
|
131 | ||
|
132 | $ hg config --config commands.commit.post-status= commands -Tjson | |
|
133 | [ | |
|
134 | { | |
|
135 | "defaultvalue": false, | |
|
136 | "name": "commands.commit.post-status", | |
|
137 | "source": "--config", | |
|
138 | "value": "" | |
|
139 | } | |
|
140 | ] | |
|
141 | $ hg config --config commands.commit.post-status= commands -T'json(defaultvalue)' | |
|
142 | [ | |
|
143 | {"defaultvalue": false} | |
|
144 | ] | |
|
145 | $ hg config --config commands.commit.post-status= commands -T'{defaultvalue}\n' | |
|
146 | False | |
|
147 | ||
|
148 | true | |
|
149 | ||
|
150 | $ hg config --config format.dotencode= format -Tjson | |
|
151 | [ | |
|
152 | { | |
|
153 | "defaultvalue": true, | |
|
154 | "name": "format.dotencode", | |
|
155 | "source": "--config", | |
|
156 | "value": "" | |
|
157 | } | |
|
158 | ] | |
|
159 | $ hg config --config format.dotencode= format -T'json(defaultvalue)' | |
|
160 | [ | |
|
161 | {"defaultvalue": true} | |
|
162 | ] | |
|
163 | $ hg config --config format.dotencode= format -T'{defaultvalue}\n' | |
|
164 | True | |
|
165 | ||
|
166 | bytes | |
|
167 | ||
|
168 | $ hg config --config commands.resolve.mark-check= commands -Tjson | |
|
169 | [ | |
|
170 | { | |
|
171 | "defaultvalue": "none", | |
|
172 | "name": "commands.resolve.mark-check", | |
|
173 | "source": "--config", | |
|
174 | "value": "" | |
|
175 | } | |
|
176 | ] | |
|
177 | $ hg config --config commands.resolve.mark-check= commands -T'json(defaultvalue)' | |
|
178 | [ | |
|
179 | {"defaultvalue": "none"} | |
|
180 | ] | |
|
181 | $ hg config --config commands.resolve.mark-check= commands -T'{defaultvalue}\n' | |
|
182 | none | |
|
183 | ||
|
184 | empty list | |
|
185 | ||
|
186 | $ hg config --config commands.show.aliasprefix= commands -Tjson | |
|
187 | [ | |
|
188 | { | |
|
189 | "defaultvalue": [], | |
|
190 | "name": "commands.show.aliasprefix", | |
|
191 | "source": "--config", | |
|
192 | "value": "" | |
|
193 | } | |
|
194 | ] | |
|
195 | $ hg config --config commands.show.aliasprefix= commands -T'json(defaultvalue)' | |
|
196 | [ | |
|
197 | {"defaultvalue": []} | |
|
198 | ] | |
|
199 | $ hg config --config commands.show.aliasprefix= commands -T'{defaultvalue}\n' | |
|
200 | ||
|
201 | ||
|
202 | nonempty list | |
|
203 | ||
|
204 | $ hg config --config progress.format= progress -Tjson | |
|
205 | [ | |
|
206 | { | |
|
207 | "defaultvalue": ["topic", "bar", "number", "estimate"], | |
|
208 | "name": "progress.format", | |
|
209 | "source": "--config", | |
|
210 | "value": "" | |
|
211 | } | |
|
212 | ] | |
|
213 | $ hg config --config progress.format= progress -T'json(defaultvalue)' | |
|
214 | [ | |
|
215 | {"defaultvalue": ["topic", "bar", "number", "estimate"]} | |
|
216 | ] | |
|
217 | $ hg config --config progress.format= progress -T'{defaultvalue}\n' | |
|
218 | topic bar number estimate | |
|
219 | ||
|
220 | int | |
|
221 | ||
|
222 | $ hg config --config profiling.freq= profiling -Tjson | |
|
223 | [ | |
|
224 | { | |
|
225 | "defaultvalue": 1000, | |
|
226 | "name": "profiling.freq", | |
|
227 | "source": "--config", | |
|
228 | "value": "" | |
|
229 | } | |
|
230 | ] | |
|
231 | $ hg config --config profiling.freq= profiling -T'json(defaultvalue)' | |
|
232 | [ | |
|
233 | {"defaultvalue": 1000} | |
|
234 | ] | |
|
235 | $ hg config --config profiling.freq= profiling -T'{defaultvalue}\n' | |
|
236 | 1000 | |
|
237 | ||
|
238 | float | |
|
239 | ||
|
240 | $ hg config --config profiling.showmax= profiling -Tjson | |
|
241 | [ | |
|
242 | { | |
|
243 | "defaultvalue": 0.999, | |
|
244 | "name": "profiling.showmax", | |
|
245 | "source": "--config", | |
|
246 | "value": "" | |
|
247 | } | |
|
248 | ] | |
|
249 | $ hg config --config profiling.showmax= profiling -T'json(defaultvalue)' | |
|
250 | [ | |
|
251 | {"defaultvalue": 0.999} | |
|
252 | ] | |
|
253 | $ hg config --config profiling.showmax= profiling -T'{defaultvalue}\n' | |
|
254 | 0.999 | |
|
255 | ||
|
90 | 256 | Test empty config source: |
|
91 | 257 | |
|
92 | 258 | $ cat <<EOF > emptysource.py |
@@ -13,18 +13,16 b" Ensure debuild doesn't run the testsuite" | |||
|
13 | 13 | $ make deb > $OUTPUTDIR/build.log 2>&1 |
|
14 | 14 | $ cd $OUTPUTDIR |
|
15 | 15 | $ ls *.deb | grep -v 'dbg' |
|
16 | mercurial-common_*.deb (glob) | |
|
17 | 16 | mercurial_*.deb (glob) |
|
18 |
|
|
|
17 | should have .so and .py | |
|
19 | 18 | $ dpkg --contents mercurial_*.deb | egrep '(localrepo|parsers)' |
|
20 |
* ./usr/lib/python |
|
|
21 | mercurial-common should have py but no .so or pyc | |
|
22 | $ dpkg --contents mercurial-common_*.deb | egrep '(localrepo|parsers.*so)' | |
|
23 | * ./usr/lib/python2.7/dist-packages/mercurial/localrepo.py (glob) | |
|
24 | zsh completions should be in the common package | |
|
25 | $ dpkg --contents mercurial-common_*.deb | egrep 'zsh.*[^/]$' | |
|
19 | * ./usr/lib/python3/dist-packages/mercurial/cext/parsers*.so (glob) | |
|
20 | * ./usr/lib/python3/dist-packages/mercurial/localrepo.py (glob) | |
|
21 | * ./usr/lib/python3/dist-packages/mercurial/pure/parsers.py (glob) | |
|
22 | should have zsh completions | |
|
23 | $ dpkg --contents mercurial_*.deb | egrep 'zsh.*[^/]$' | |
|
26 | 24 | * ./usr/share/zsh/vendor-completions/_hg (glob) |
|
27 | chg should be installed alongside hg, in the 'mercurial' package | |
|
25 | should have chg | |
|
28 | 26 | $ dpkg --contents mercurial_*.deb | egrep 'chg$' |
|
29 | 27 | * ./usr/bin/chg (glob) |
|
30 | 28 | chg should come with a man page |
@@ -209,12 +209,12 b' Ensure the data got to the server OK' | |||
|
209 | 209 | insertflagprocessor(flag, processor, flagprocessors) |
|
210 | 210 | File "*/mercurial/revlogutils/flagutil.py", line *, in insertflagprocessor (glob) |
|
211 | 211 | raise error.Abort(msg) |
|
212 |
mercurial.error.Abort: |
|
|
212 | mercurial.error.Abort: cannot register multiple processors on flag '0x8'. (py3 !) | |
|
213 | 213 | Abort: cannot register multiple processors on flag '0x8'. (no-py3 !) |
|
214 | 214 | *** failed to set up extension duplicate: cannot register multiple processors on flag '0x8'. |
|
215 | 215 | $ hg st 2>&1 | egrep 'cannot register multiple processors|flagprocessorext' |
|
216 | 216 | File "*/tests/flagprocessorext.py", line *, in extsetup (glob) |
|
217 |
mercurial.error.Abort: |
|
|
217 | mercurial.error.Abort: cannot register multiple processors on flag '0x8'. (py3 !) | |
|
218 | 218 | Abort: cannot register multiple processors on flag '0x8'. (no-py3 !) |
|
219 | 219 | *** failed to set up extension duplicate: cannot register multiple processors on flag '0x8'. |
|
220 | 220 | File "*/tests/flagprocessorext.py", line *, in b64decode (glob) |
@@ -966,7 +966,9 b' errors encountered' | |||
|
966 | 966 | $ cd .. |
|
967 | 967 | $ hg init eucjp |
|
968 | 968 | $ cd eucjp |
|
969 | $ "$PYTHON" -c 'print("\265\376")' >> eucjp.txt # Japanese kanji "Kyo" | |
|
969 | >>> with open('eucjp.txt', 'wb') as fh: | |
|
970 | ... # Japanese kanji "Kyo" | |
|
971 | ... fh.write(u'\265\376'.encode('utf-8')) and None | |
|
970 | 972 | $ hg ci -Ama |
|
971 | 973 | adding eucjp.txt |
|
972 | 974 | $ hgserveget () { |
@@ -988,7 +988,7 b' test python hooks' | |||
|
988 | 988 | ModuleNotFoundError: No module named 'hgext_syntaxerror' (py36 !) |
|
989 | 989 | Traceback (most recent call last): (py3 !) |
|
990 | 990 | HookLoadError: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed (no-py3 !) |
|
991 |
mercurial.error.HookLoadError: |
|
|
991 | mercurial.error.HookLoadError: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed (py3 !) | |
|
992 | 992 | abort: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed |
|
993 | 993 | |
|
994 | 994 | $ echo '[hooks]' > ../a/.hg/hgrc |
@@ -1161,7 +1161,7 b' make sure --traceback works on hook impo' | |||
|
1161 | 1161 | ModuleNotFoundError: No module named 'hgext_importfail' (py36 !) |
|
1162 | 1162 | Traceback (most recent call last): |
|
1163 | 1163 | HookLoadError: precommit.importfail hook is invalid: import of "importfail" failed (no-py3 !) |
|
1164 |
mercurial.error.HookLoadError: |
|
|
1164 | mercurial.error.HookLoadError: precommit.importfail hook is invalid: import of "importfail" failed (py3 !) | |
|
1165 | 1165 | abort: precommit.importfail hook is invalid: import of "importfail" failed |
|
1166 | 1166 | |
|
1167 | 1167 | Issue1827: Hooks Update & Commit not completely post operation |
@@ -236,25 +236,56 b' Verify the json works too:' | |||
|
236 | 236 | |
|
237 | 237 | #endif |
|
238 | 238 | |
|
239 | #if py3 | |
|
240 | $ HGALLOWPYTHON3=1 | |
|
241 | $ export HGALLOWPYTHON3 | |
|
242 | #endif | |
|
243 | ||
|
244 | #if virtualenv | |
|
245 | ||
|
246 | 239 |
|
|
247 | 240 | the last test in this file, because we do some nasty things to the |
|
248 | 241 | shell environment in order to make the virtualenv work reliably. |
|
249 | 242 | |
|
243 | On Python 3, we use the venv module, which is part of the standard library. | |
|
244 | But some Linux distros strip out this module's functionality involving pip, | |
|
245 | so we have to look for the ensurepip module, which these distros strip out | |
|
246 | completely. | |
|
247 | On Python 2, we use the 3rd party virtualenv module, if available. | |
|
248 | ||
|
250 | 249 | $ cd $TESTTMP |
|
250 | $ unset PYTHONPATH | |
|
251 | ||
|
252 | #if py3 ensurepip | |
|
253 | $ "$PYTHON" -m venv installenv >> pip.log | |
|
254 | ||
|
255 | Note: we use this weird path to run pip and hg to avoid platform differences, | |
|
256 | since it's bin on most platforms but Scripts on Windows. | |
|
257 | $ ./installenv/*/pip install --no-index $TESTDIR/.. >> pip.log | |
|
258 | $ ./installenv/*/hg debuginstall || cat pip.log | |
|
259 | checking encoding (ascii)... | |
|
260 | checking Python executable (*) (glob) | |
|
261 | checking Python version (3.*) (glob) | |
|
262 | checking Python lib (*)... (glob) | |
|
263 | checking Python security support (*) (glob) | |
|
264 | checking Mercurial version (*) (glob) | |
|
265 | checking Mercurial custom build (*) (glob) | |
|
266 | checking module policy (*) (glob) | |
|
267 | checking installed modules (*/mercurial)... (glob) | |
|
268 | checking registered compression engines (*) (glob) | |
|
269 | checking available compression engines (*) (glob) | |
|
270 | checking available compression engines for wire protocol (*) (glob) | |
|
271 | checking "re2" regexp engine \((available|missing)\) (re) | |
|
272 | checking templates ($TESTTMP/installenv/*/site-packages/mercurial/templates)... (glob) | |
|
273 | checking default template ($TESTTMP/installenv/*/site-packages/mercurial/templates/map-cmdline.default) (glob) | |
|
274 | checking commit editor... (*) (glob) | |
|
275 | checking username (test) | |
|
276 | no problems detected | |
|
277 | #endif | |
|
278 | ||
|
279 | #if no-py3 virtualenv | |
|
280 | ||
|
251 | 281 | Note: --no-site-packages is deprecated, but some places have an |
|
252 | 282 | ancient virtualenv from their linux distro or similar and it's not yet |
|
253 | 283 | the default for them. |
|
254 | $ unset PYTHONPATH | |
|
284 | ||
|
255 | 285 | $ "$PYTHON" -m virtualenv --no-site-packages --never-download installenv >> pip.log |
|
256 | 286 | DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. (?) |
|
257 | 287 | DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support (?) |
|
288 | ||
|
258 | 289 | Note: we use this weird path to run pip and hg to avoid platform differences, |
|
259 | 290 | since it's bin on most platforms but Scripts on Windows. |
|
260 | 291 | $ ./installenv/*/pip install --no-index $TESTDIR/.. >> pip.log |
@@ -263,8 +294,7 b" since it's bin on most platforms but Scr" | |||
|
263 | 294 | $ ./installenv/*/hg debuginstall || cat pip.log |
|
264 | 295 | checking encoding (ascii)... |
|
265 | 296 | checking Python executable (*) (glob) |
|
266 |
checking Python version (2.*) (glob) |
|
|
267 | checking Python version (3.*) (glob) (py3 !) | |
|
297 | checking Python version (2.*) (glob) | |
|
268 | 298 | checking Python lib (*)... (glob) |
|
269 | 299 | checking Python security support (*) (glob) |
|
270 | 300 | TLS 1.2 not supported by Python install; network connections lack modern security (?) |
@@ -256,7 +256,8 b' ie. if patch.diff wrapper acts as it sho' | |||
|
256 | 256 | |
|
257 | 257 | Pull from bundle and trigger notify |
|
258 | 258 | |
|
259 | $ hg pull -u ../kw.hg | |
|
259 | $ hg pull -u ../kw.hg | \ | |
|
260 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | |
|
260 | 261 | pulling from ../kw.hg |
|
261 | 262 | requesting all changes |
|
262 | 263 | adding changesets |
@@ -354,7 +354,8 b' Test a checksum failure during the proce' | |||
|
354 | 354 | $LOCALIP - - [$ERRDATE$] HG error: localstore.download(oid, req.bodyfh) (glob) |
|
355 | 355 | $LOCALIP - - [$ERRDATE$] HG error: super(badstore, self).download(oid, src) (glob) |
|
356 | 356 | $LOCALIP - - [$ERRDATE$] HG error: _(b'corrupt remote lfs object: %s') % oid (glob) |
|
357 |
$LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c ( |
|
|
357 | $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c (no-py3 !) | |
|
358 | $LOCALIP - - [$ERRDATE$] HG error: hgext.lfs.blobstore.LfsCorruptionError: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c (py3 !) | |
|
358 | 359 | $LOCALIP - - [$ERRDATE$] HG error: (glob) |
|
359 | 360 | $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob) |
|
360 | 361 | Traceback (most recent call last): |
@@ -376,7 +377,8 b' Test a checksum failure during the proce' | |||
|
376 | 377 | $LOCALIP - - [$ERRDATE$] HG error: blob = self._read(self.vfs, oid, verify) (glob) |
|
377 | 378 | $LOCALIP - - [$ERRDATE$] HG error: blobstore._verify(oid, b'dummy content') (glob) |
|
378 | 379 | $LOCALIP - - [$ERRDATE$] HG error: hint=_(b'run hg verify'), (glob) |
|
379 |
$LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d ( |
|
|
380 | $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d (no-py3 !) | |
|
381 | $LOCALIP - - [$ERRDATE$] HG error: hgext.lfs.blobstore.LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d (py3 !) | |
|
380 | 382 | $LOCALIP - - [$ERRDATE$] HG error: (glob) |
|
381 | 383 | |
|
382 | 384 | Basic Authorization headers are returned by the Batch API, and sent back with |
@@ -2,6 +2,7 b' from __future__ import absolute_import' | |||
|
2 | 2 | |
|
3 | 3 | import unittest |
|
4 | 4 | from mercurial import error, mdiff |
|
5 | from mercurial.utils import stringutil | |
|
5 | 6 | |
|
6 | 7 | # for readability, line numbers are 0-origin |
|
7 | 8 | text1 = b''' |
@@ -228,7 +229,10 b' class blocksinrangetests(unittest.TestCa' | |||
|
228 | 229 | try: |
|
229 | 230 | mdiff.blocksinrange(self.blocks, linerange2) |
|
230 | 231 | except exctype as exc: |
|
231 | self.assertTrue('line range exceeds file size' in str(exc)) | |
|
232 | self.assertTrue( | |
|
233 | b'line range exceeds file size' | |
|
234 | in stringutil.forcebytestr(exc) | |
|
235 | ) | |
|
232 | 236 | else: |
|
233 | 237 | self.fail('%s not raised' % exctype.__name__) |
|
234 | 238 |
@@ -316,7 +316,7 b' class DifferenceMatcherTests(unittest.Te' | |||
|
316 | 316 | |
|
317 | 317 | # We're using includematcher instead of patterns because it behaves slightly |
|
318 | 318 | # better (giving narrower results) than patternmatcher. |
|
319 |
def testVisitdirIncludeInclud |
|
|
319 | def testVisitdirIncludeInclude(self): | |
|
320 | 320 | m1 = matchmod.match(b'', b'', include=[b'path:dir/subdir']) |
|
321 | 321 | m2 = matchmod.match(b'', b'', include=[b'rootfilesin:dir']) |
|
322 | 322 | dm = matchmod.differencematcher(m1, m2) |
@@ -430,7 +430,7 b' class IntersectionMatcherTests(unittest.' | |||
|
430 | 430 | |
|
431 | 431 | # We're using includematcher instead of patterns because it behaves slightly |
|
432 | 432 | # better (giving narrower results) than patternmatcher. |
|
433 |
def testVisitdirIncludeInclud |
|
|
433 | def testVisitdirIncludeInclude(self): | |
|
434 | 434 | m1 = matchmod.match(b'', b'', include=[b'path:dir/subdir']) |
|
435 | 435 | m2 = matchmod.match(b'', b'', include=[b'rootfilesin:dir']) |
|
436 | 436 | im = matchmod.intersectmatchers(m1, m2) |
@@ -644,7 +644,7 b' class UnionMatcherTests(unittest.TestCas' | |||
|
644 | 644 | |
|
645 | 645 | # We're using includematcher instead of patterns because it behaves slightly |
|
646 | 646 | # better (giving narrower results) than patternmatcher. |
|
647 |
def testVisitdirIncludeInclud |
|
|
647 | def testVisitdirIncludeInclude(self): | |
|
648 | 648 | m1 = matchmod.match(b'', b'', include=[b'path:dir/subdir']) |
|
649 | 649 | m2 = matchmod.match(b'', b'', include=[b'rootfilesin:dir']) |
|
650 | 650 | um = matchmod.unionmatcher([m1, m2]) |
@@ -39,6 +39,7 b' commit' | |||
|
39 | 39 | push |
|
40 | 40 | |
|
41 | 41 | $ hg --traceback --cwd b push ../a 2>&1 | |
|
42 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
42 | 43 | > "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' |
|
43 | 44 | pushing to ../a |
|
44 | 45 | searching for changes |
@@ -93,6 +94,7 b' unbundle with unrelated source' | |||
|
93 | 94 | unbundle with correct source |
|
94 | 95 | |
|
95 | 96 | $ hg --config notify.sources=unbundle --cwd a unbundle ../test.hg 2>&1 | |
|
97 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
96 | 98 | > "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' |
|
97 | 99 | adding changesets |
|
98 | 100 | adding manifests |
@@ -169,6 +171,7 b' merge as a different user' | |||
|
169 | 171 | push |
|
170 | 172 | |
|
171 | 173 | $ hg --traceback --cwd b --config notify.fromauthor=True push ../a 2>&1 | |
|
174 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
172 | 175 | > "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")' |
|
173 | 176 | pushing to ../a |
|
174 | 177 | searching for changes |
@@ -196,7 +196,9 b' the python call below wraps continuation' | |||
|
196 | 196 | of the very long subject line |
|
197 | 197 | pull (minimal config) |
|
198 | 198 | |
|
199 |
$ hg --traceback --cwd b --config notify.domain=example.com --config notify.messageidseed=example pull ../a | |
|
|
199 | $ hg --traceback --cwd b --config notify.domain=example.com --config notify.messageidseed=example pull ../a | \ | |
|
200 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
201 | > "$PYTHON" $TESTTMP/filter.py | |
|
200 | 202 | pulling from ../a |
|
201 | 203 | searching for changes |
|
202 | 204 | adding changesets |
@@ -255,7 +257,9 b' pull' | |||
|
255 | 257 | |
|
256 | 258 | $ hg --cwd b rollback |
|
257 | 259 | repository tip rolled back to revision 0 (undo pull) |
|
258 |
$ hg --traceback --cwd b pull ../a |
|
|
260 | $ hg --traceback --cwd b pull ../a | \ | |
|
261 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
262 | > "$PYTHON" $TESTTMP/filter.py | |
|
259 | 263 | pulling from ../a |
|
260 | 264 | searching for changes |
|
261 | 265 | adding changesets |
@@ -303,7 +307,9 b' pull' | |||
|
303 | 307 | |
|
304 | 308 | $ hg --cwd b rollback |
|
305 | 309 | repository tip rolled back to revision 0 (undo pull) |
|
306 |
$ hg --traceback --config notify.maxdiffstat=1 --cwd b pull ../a | |
|
|
310 | $ hg --traceback --config notify.maxdiffstat=1 --cwd b pull ../a | \ | |
|
311 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
312 | > "$PYTHON" $TESTTMP/filter.py | |
|
307 | 313 | pulling from ../a |
|
308 | 314 | searching for changes |
|
309 | 315 | adding changesets |
@@ -354,7 +360,9 b' test merge' | |||
|
354 | 360 | (branch merge, don't forget to commit) |
|
355 | 361 | $ hg ci -m merge -d '3 0' |
|
356 | 362 | $ cd .. |
|
357 |
$ hg --traceback --cwd b pull ../a | |
|
|
363 | $ hg --traceback --cwd b pull ../a | \ | |
|
364 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
365 | > "$PYTHON" $TESTTMP/filter.py | |
|
358 | 366 | pulling from ../a |
|
359 | 367 | searching for changes |
|
360 | 368 | adding changesets |
@@ -418,8 +426,9 b' non-ascii content and truncation of mult' | |||
|
418 | 426 | > EOF |
|
419 | 427 | $ echo a >> a/a |
|
420 | 428 | $ hg --cwd a --encoding utf-8 commit -A -d '0 0' \ |
|
421 |
> -m `"$PYTHON" -c 'pr |
|
|
429 | > -m `"$PYTHON" -c 'import sys; getattr(sys.stdout, "buffer", sys.stdout).write(b"\xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4")'` | |
|
422 | 430 | $ hg --traceback --cwd b --encoding utf-8 pull ../a | \ |
|
431 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
423 | 432 | > "$PYTHON" $TESTTMP/filter.py |
|
424 | 433 | pulling from ../a |
|
425 | 434 | searching for changes |
@@ -433,7 +442,8 b' non-ascii content and truncation of mult' | |||
|
433 | 442 | Content-Transfer-Encoding: 8bit |
|
434 | 443 | X-Test: foo |
|
435 | 444 | Date: * (glob) |
|
436 | Subject: \xc3\xa0... (esc) | |
|
445 | Subject: \xc3\xa0... (esc) (no-py3 !) | |
|
446 | Subject: =?utf-8?b?w6AuLi4=?= (py3 !) | |
|
437 | 447 | From: test@test.com |
|
438 | 448 | X-Hg-Notification: changeset 0f25f9c22b4c |
|
439 | 449 | Message-Id: <*> (glob) |
@@ -473,7 +483,7 b' long lines' | |||
|
473 | 483 | new changesets a846b5f6ebb7 |
|
474 | 484 | notify: sending 2 subscribers 1 changes |
|
475 | 485 | (run 'hg update' to get a working copy) |
|
476 | $ "$PYTHON" $TESTTMP/filter.py < b/mbox | |
|
486 | $ cat b/mbox | "$PYTHON" $TESTDIR/unwrap-message-id.py | "$PYTHON" $TESTTMP/filter.py | |
|
477 | 487 | From test@test.com ... ... .. ..:..:.. .... (re) |
|
478 | 488 | MIME-Version: 1.0 |
|
479 | 489 | Content-Type: text/plain; charset="*" (glob) |
@@ -533,7 +543,9 b' long lines' | |||
|
533 | 543 | (branches are permanent and global, did you want a bookmark?) |
|
534 | 544 | $ echo a >> a/a |
|
535 | 545 | $ hg --cwd a ci -m test -d '1 0' |
|
536 |
$ hg --traceback --cwd b pull ../a | |
|
|
546 | $ hg --traceback --cwd b pull ../a | \ | |
|
547 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
548 | > "$PYTHON" $TESTTMP/filter.py | |
|
537 | 549 | pulling from ../a |
|
538 | 550 | searching for changes |
|
539 | 551 | adding changesets |
@@ -563,7 +575,9 b' from different branch' | |||
|
563 | 575 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
564 | 576 | $ echo a >> a/a |
|
565 | 577 | $ hg --cwd a ci -m test -d '1 0' |
|
566 |
$ hg --traceback --cwd b pull ../a | |
|
|
578 | $ hg --traceback --cwd b pull ../a | \ | |
|
579 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
580 | > "$PYTHON" $TESTTMP/filter.py | |
|
567 | 581 | pulling from ../a |
|
568 | 582 | searching for changes |
|
569 | 583 | adding changesets |
@@ -592,7 +606,9 b' default template:' | |||
|
592 | 606 | $ mv "$HGRCPATH.new" $HGRCPATH |
|
593 | 607 | $ echo a >> a/a |
|
594 | 608 | $ hg --cwd a commit -m 'default template' |
|
595 |
$ hg --cwd b pull ../a -q | |
|
|
609 | $ hg --cwd b pull ../a -q | \ | |
|
610 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
611 | > "$PYTHON" $TESTTMP/filter.py | |
|
596 | 612 | MIME-Version: 1.0 |
|
597 | 613 | Content-Type: text/plain; charset="us-ascii" |
|
598 | 614 | Content-Transfer-Encoding: 7bit |
@@ -621,7 +637,9 b' with style:' | |||
|
621 | 637 | > EOF |
|
622 | 638 | $ echo a >> a/a |
|
623 | 639 | $ hg --cwd a commit -m 'with style' |
|
624 |
$ hg --cwd b pull ../a -q | |
|
|
640 | $ hg --cwd b pull ../a -q | \ | |
|
641 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
642 | > "$PYTHON" $TESTTMP/filter.py | |
|
625 | 643 | MIME-Version: 1.0 |
|
626 | 644 | Content-Type: text/plain; charset="us-ascii" |
|
627 | 645 | Content-Transfer-Encoding: 7bit |
@@ -644,7 +662,9 b' with template (overrides style):' | |||
|
644 | 662 | > EOF |
|
645 | 663 | $ echo a >> a/a |
|
646 | 664 | $ hg --cwd a commit -m 'with template' |
|
647 |
$ hg --cwd b pull ../a -q | |
|
|
665 | $ hg --cwd b pull ../a -q | \ | |
|
666 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | \ | |
|
667 | > "$PYTHON" $TESTTMP/filter.py | |
|
648 | 668 | MIME-Version: 1.0 |
|
649 | 669 | Content-Type: text/plain; charset="us-ascii" |
|
650 | 670 | Content-Transfer-Encoding: 7bit |
@@ -675,7 +695,8 b' showfunc diff' | |||
|
675 | 695 | > EOF |
|
676 | 696 | $ hg commit -Am addfunction |
|
677 | 697 | adding f1 |
|
678 | $ hg --cwd ../b pull ../a | |
|
698 | $ hg --cwd ../b pull ../a | \ | |
|
699 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | |
|
679 | 700 | pulling from ../a |
|
680 | 701 | searching for changes |
|
681 | 702 | adding changesets |
@@ -718,7 +739,8 b' showfunc diff' | |||
|
718 | 739 | > } |
|
719 | 740 | > EOF |
|
720 | 741 | $ hg commit -m changefunction |
|
721 | $ hg --cwd ../b --config notify.showfunc=True pull ../a | |
|
742 | $ hg --cwd ../b --config notify.showfunc=True pull ../a | \ | |
|
743 | > "$PYTHON" $TESTDIR/unwrap-message-id.py | |
|
722 | 744 | pulling from ../a |
|
723 | 745 | searching for changes |
|
724 | 746 | adding changesets |
@@ -445,7 +445,9 b' with a specific bundle type' | |||
|
445 | 445 | |
|
446 | 446 | utf-8 patch: |
|
447 | 447 | $ "$PYTHON" -c 'fp = open("utf", "wb"); fp.write(b"h\xC3\xB6mma!\n"); fp.close();' |
|
448 |
$ hg commit -A -d '4 0' |
|
|
448 | $ hg commit -A -d '4 0' \ | |
|
449 | > --encoding "utf-8" \ | |
|
450 | > -m `"$PYTHON" -c 'import sys; getattr(sys.stdout, "buffer", sys.stdout).write(b"\xc3\xa7a")'` | |
|
449 | 451 | adding description |
|
450 | 452 | adding utf |
|
451 | 453 | |
@@ -454,16 +456,16 b' no mime encoding for email --test:' | |||
|
454 | 456 | this patch series consists of 1 patches. |
|
455 | 457 | |
|
456 | 458 | |
|
457 |
displaying [PATCH] |
|
|
459 | displaying [PATCH] ?a ... | |
|
458 | 460 |
|
|
459 | 461 | Content-Type: text/plain; charset="iso-8859-1" |
|
460 | 462 | Content-Transfer-Encoding: quoted-printable |
|
461 |
Subject: [PATCH] |
|
|
462 | X-Mercurial-Node: 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
463 | Subject: [PATCH] ?a | |
|
464 | X-Mercurial-Node: f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
463 | 465 | X-Mercurial-Series-Index: 1 |
|
464 | 466 | X-Mercurial-Series-Total: 1 |
|
465 |
Message-Id: < |
|
|
466 |
X-Mercurial-Series-Id: < |
|
|
467 | Message-Id: <f81ef97829467e868fc4.240@test-hostname> | |
|
468 | X-Mercurial-Series-Id: <f81ef97829467e868fc4.240@test-hostname> | |
|
467 | 469 | User-Agent: Mercurial-patchbomb/* (glob) |
|
468 | 470 | Date: Thu, 01 Jan 1970 00:04:00 +0000 |
|
469 | 471 | From: quux |
@@ -474,18 +476,18 b' no mime encoding for email --test:' | |||
|
474 | 476 | # User test |
|
475 | 477 | # Date 4 0 |
|
476 | 478 | # Thu Jan 01 00:00:04 1970 +0000 |
|
477 | # Node ID 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
479 | # Node ID f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
478 | 480 | # Parent ff2c9fa2018b15fa74b33363bda9527323e2a99f |
|
479 | utf-8 content | |
|
480 | ||
|
481 |
|
|
|
481 | ?a | |
|
482 | ||
|
483 | diff -r ff2c9fa2018b -r f81ef9782946 description | |
|
482 | 484 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
483 | 485 | +++ b/description Thu Jan 01 00:00:04 1970 +0000 |
|
484 | 486 | @@ -0,0 +1,3 @@ |
|
485 | 487 | +a multiline |
|
486 | 488 | + |
|
487 | 489 | +description |
|
488 |
diff -r ff2c9fa2018b -r |
|
|
490 | diff -r ff2c9fa2018b -r f81ef9782946 utf | |
|
489 | 491 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
490 | 492 | +++ b/utf Thu Jan 01 00:00:04 1970 +0000 |
|
491 | 493 | @@ -0,0 +1,1 @@ |
@@ -497,35 +499,36 b' mime encoded mbox (base64):' | |||
|
497 | 499 | this patch series consists of 1 patches. |
|
498 | 500 | |
|
499 | 501 | |
|
500 |
sending [PATCH] |
|
|
502 | sending [PATCH] ?a ... | |
|
501 | 503 | |
|
502 | 504 |
$ |
|
503 | 505 | From quux ... ... .. ..:..:.. .... (re) |
|
504 | 506 | MIME-Version: 1.0 |
|
505 | 507 | Content-Type: text/plain; charset="utf-8" |
|
506 | 508 | Content-Transfer-Encoding: base64 |
|
507 |
Subject: [PATCH] |
|
|
508 | X-Mercurial-Node: 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
509 | Subject: [PATCH] ?a | |
|
510 | X-Mercurial-Node: f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
509 | 511 | X-Mercurial-Series-Index: 1 |
|
510 | 512 | X-Mercurial-Series-Total: 1 |
|
511 |
Message-Id: < |
|
|
512 |
X-Mercurial-Series-Id: < |
|
|
513 | Message-Id: <f81ef97829467e868fc4.240@test-hostname> | |
|
514 | X-Mercurial-Series-Id: <f81ef97829467e868fc4.240@test-hostname> | |
|
513 | 515 | User-Agent: Mercurial-patchbomb/* (glob) |
|
514 | 516 | Date: Thu, 01 Jan 1970 00:04:00 +0000 |
|
515 | From: Q <quux> | |
|
517 | From: Q <quux> (no-py3 !) | |
|
518 | From: =?iso-8859-1?q?Q?= <quux> (py3 !) | |
|
516 | 519 |
To: |
|
517 | 520 |
Cc: |
|
518 | 521 | |
|
519 | 522 | IyBIRyBjaGFuZ2VzZXQgcGF0Y2gKIyBVc2VyIHRlc3QKIyBEYXRlIDQgMAojICAgICAgVGh1IEph |
|
520 |
biAwMSAwMDowMDowNCAxOTcwICswMDAwCiMgTm9kZSBJRC |
|
|
521 |
|
|
|
522 | NTI3MzIzZTJhOTlmCnV0Zi04IGNvbnRlbnQKCmRpZmYgLXIgZmYyYzlmYTIwMThiIC1yIDkwOWEw | |
|
523 | MGUxM2U5ZCBkZXNjcmlwdGlvbgotLS0gL2Rldi9udWxsCVRodSBKYW4gMDEgMDA6MDA6MDAgMTk3 | |
|
524 | MCArMDAwMAorKysgYi9kZXNjcmlwdGlvbglUaHUgSmFuIDAxIDAwOjAwOjA0IDE5NzAgKzAwMDAK | |
|
525 | QEAgLTAsMCArMSwzIEBACithIG11bHRpbGluZQorCitkZXNjcmlwdGlvbgpkaWZmIC1yIGZmMmM5 | |
|
526 | ZmEyMDE4YiAtciA5MDlhMDBlMTNlOWQgdXRmCi0tLSAvZGV2L251bGwJVGh1IEphbiAwMSAwMDow | |
|
527 | MDowMCAxOTcwICswMDAwCisrKyBiL3V0ZglUaHUgSmFuIDAxIDAwOjAwOjA0IDE5NzAgKzAwMDAK | |
|
528 | QEAgLTAsMCArMSwxIEBACitow7ZtbWEhCg== | |
|
523 | biAwMSAwMDowMDowNCAxOTcwICswMDAwCiMgTm9kZSBJRCBmODFlZjk3ODI5NDY3ZTg2OGZjNDA1 | |
|
524 | ZmNjYmNmYTY2MjE3ZTRkM2U2CiMgUGFyZW50ICBmZjJjOWZhMjAxOGIxNWZhNzRiMzMzNjNiZGE5 | |
|
525 | NTI3MzIzZTJhOTlmCj9hCgpkaWZmIC1yIGZmMmM5ZmEyMDE4YiAtciBmODFlZjk3ODI5NDYgZGVz | |
|
526 | Y3JpcHRpb24KLS0tIC9kZXYvbnVsbAlUaHUgSmFuIDAxIDAwOjAwOjAwIDE5NzAgKzAwMDAKKysr | |
|
527 | IGIvZGVzY3JpcHRpb24JVGh1IEphbiAwMSAwMDowMDowNCAxOTcwICswMDAwCkBAIC0wLDAgKzEs | |
|
528 | MyBAQAorYSBtdWx0aWxpbmUKKworZGVzY3JpcHRpb24KZGlmZiAtciBmZjJjOWZhMjAxOGIgLXIg | |
|
529 | ZjgxZWY5NzgyOTQ2IHV0ZgotLS0gL2Rldi9udWxsCVRodSBKYW4gMDEgMDA6MDA6MDAgMTk3MCAr | |
|
530 | MDAwMAorKysgYi91dGYJVGh1IEphbiAwMSAwMDowMDowNCAxOTcwICswMDAwCkBAIC0wLDAgKzEs | |
|
531 | MSBAQAoraMO2bW1hIQo= | |
|
529 | 532 | |
|
530 | 533 | |
|
531 | 534 | >>> import base64 |
@@ -540,18 +543,18 b' mime encoded mbox (base64):' | |||
|
540 | 543 | # User test |
|
541 | 544 | # Date 4 0 |
|
542 | 545 | # Thu Jan 01 00:00:04 1970 +0000 |
|
543 | # Node ID 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
546 | # Node ID f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
544 | 547 | # Parent ff2c9fa2018b15fa74b33363bda9527323e2a99f |
|
545 | utf-8 content | |
|
546 | ||
|
547 |
diff -r ff2c9fa2018b -r |
|
|
548 | ?a | |
|
549 | ||
|
550 | diff -r ff2c9fa2018b -r f81ef9782946 description | |
|
548 | 551 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
549 | 552 | +++ b/description Thu Jan 01 00:00:04 1970 +0000 |
|
550 | 553 | @@ -0,0 +1,3 @@ |
|
551 | 554 | +a multiline |
|
552 | 555 | + |
|
553 | 556 | +description |
|
554 |
diff -r ff2c9fa2018b -r |
|
|
557 | diff -r ff2c9fa2018b -r f81ef9782946 utf | |
|
555 | 558 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
556 | 559 | +++ b/utf Thu Jan 01 00:00:04 1970 +0000 |
|
557 | 560 | @@ -0,0 +1,1 @@ |
@@ -574,11 +577,11 b' no mime encoding for email --test:' | |||
|
574 | 577 | Content-Type: text/plain; charset="us-ascii" |
|
575 | 578 | Content-Transfer-Encoding: quoted-printable |
|
576 | 579 | Subject: [PATCH] long line |
|
577 | X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
580 | X-Mercurial-Node: 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
578 | 581 | X-Mercurial-Series-Index: 1 |
|
579 | 582 | X-Mercurial-Series-Total: 1 |
|
580 |
Message-Id: < |
|
|
581 |
X-Mercurial-Series-Id: < |
|
|
583 | Message-Id: <0c7b871cb86b61a1c07e.240@test-hostname> | |
|
584 | X-Mercurial-Series-Id: <0c7b871cb86b61a1c07e.240@test-hostname> | |
|
582 | 585 | User-Agent: Mercurial-patchbomb/* (glob) |
|
583 | 586 | Date: Thu, 01 Jan 1970 00:04:00 +0000 |
|
584 | 587 | From: quux |
@@ -589,11 +592,11 b' no mime encoding for email --test:' | |||
|
589 | 592 | # User test |
|
590 | 593 | # Date 4 0 |
|
591 | 594 | # Thu Jan 01 00:00:04 1970 +0000 |
|
592 | # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
593 | # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
595 | # Node ID 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
596 | # Parent f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
594 | 597 | long line |
|
595 | 598 | |
|
596 | diff -r 909a00e13e9d -r a2ea8fc83dd8 long | |
|
599 | diff -r f81ef9782946 -r 0c7b871cb86b long | |
|
597 | 600 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
598 | 601 | +++ b/long Thu Jan 01 00:00:04 1970 +0000 |
|
599 | 602 | @@ -0,0 +1,4 @@ |
@@ -628,11 +631,11 b' mime encoded mbox (quoted-printable):' | |||
|
628 | 631 | Content-Type: text/plain; charset="us-ascii" |
|
629 | 632 | Content-Transfer-Encoding: quoted-printable |
|
630 | 633 | Subject: [PATCH] long line |
|
631 | X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
634 | X-Mercurial-Node: 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
632 | 635 | X-Mercurial-Series-Index: 1 |
|
633 | 636 | X-Mercurial-Series-Total: 1 |
|
634 |
Message-Id: < |
|
|
635 |
X-Mercurial-Series-Id: < |
|
|
637 | Message-Id: <0c7b871cb86b61a1c07e.240@test-hostname> | |
|
638 | X-Mercurial-Series-Id: <0c7b871cb86b61a1c07e.240@test-hostname> | |
|
636 | 639 | User-Agent: Mercurial-patchbomb/* (glob) |
|
637 | 640 | Date: Thu, 01 Jan 1970 00:04:00 +0000 |
|
638 | 641 | From: quux |
@@ -643,11 +646,11 b' mime encoded mbox (quoted-printable):' | |||
|
643 | 646 | # User test |
|
644 | 647 | # Date 4 0 |
|
645 | 648 | # Thu Jan 01 00:00:04 1970 +0000 |
|
646 | # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
647 | # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
649 | # Node ID 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
650 | # Parent f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
648 | 651 | long line |
|
649 | 652 | |
|
650 | diff -r 909a00e13e9d -r a2ea8fc83dd8 long | |
|
653 | diff -r f81ef9782946 -r 0c7b871cb86b long | |
|
651 | 654 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
652 | 655 | +++ b/long Thu Jan 01 00:00:04 1970 +0000 |
|
653 | 656 | @@ -0,0 +1,4 @@ |
@@ -690,11 +693,11 b' iso-8859-1 mbox:' | |||
|
690 | 693 | Content-Type: text/plain; charset="iso-8859-1" |
|
691 | 694 | Content-Transfer-Encoding: quoted-printable |
|
692 | 695 | Subject: [PATCH] isolatin 8-bit encoding |
|
693 | X-Mercurial-Node: 240fb913fc1b7ff15ddb9f33e73d82bf5277c720 | |
|
696 | X-Mercurial-Node: 4d6f44f466c96d89f2e7e865a70ff41d8b6eee37 | |
|
694 | 697 | X-Mercurial-Series-Index: 1 |
|
695 | 698 | X-Mercurial-Series-Total: 1 |
|
696 |
Message-Id: < |
|
|
697 |
X-Mercurial-Series-Id: < |
|
|
699 | Message-Id: <4d6f44f466c96d89f2e7.300@test-hostname> | |
|
700 | X-Mercurial-Series-Id: <4d6f44f466c96d89f2e7.300@test-hostname> | |
|
698 | 701 | User-Agent: Mercurial-patchbomb/* (glob) |
|
699 | 702 | Date: Thu, 01 Jan 1970 00:05:00 +0000 |
|
700 | 703 | From: quux |
@@ -705,11 +708,11 b' iso-8859-1 mbox:' | |||
|
705 | 708 | # User test |
|
706 | 709 | # Date 5 0 |
|
707 | 710 | # Thu Jan 01 00:00:05 1970 +0000 |
|
708 | # Node ID 240fb913fc1b7ff15ddb9f33e73d82bf5277c720 | |
|
709 | # Parent a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
711 | # Node ID 4d6f44f466c96d89f2e7e865a70ff41d8b6eee37 | |
|
712 | # Parent 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
710 | 713 | isolatin 8-bit encoding |
|
711 | 714 | |
|
712 |
diff -r |
|
|
715 | diff -r 0c7b871cb86b -r 4d6f44f466c9 isolatin | |
|
713 | 716 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
714 | 717 | +++ b/isolatin Thu Jan 01 00:00:05 1970 +0000 |
|
715 | 718 | @@ -0,0 +1,1 @@ |
@@ -937,11 +940,11 b' test inline for single patch (quoted-pri' | |||
|
937 | 940 | Content-Type: multipart/mixed; boundary="===*==" (glob) |
|
938 | 941 | MIME-Version: 1.0 |
|
939 | 942 | Subject: [PATCH] test |
|
940 | X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
943 | X-Mercurial-Node: 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
941 | 944 | X-Mercurial-Series-Index: 1 |
|
942 | 945 | X-Mercurial-Series-Total: 1 |
|
943 |
Message-Id: < |
|
|
944 |
X-Mercurial-Series-Id: < |
|
|
946 | Message-Id: <0c7b871cb86b61a1c07e.60@test-hostname> | |
|
947 | X-Mercurial-Series-Id: <0c7b871cb86b61a1c07e.60@test-hostname> | |
|
945 | 948 | User-Agent: Mercurial-patchbomb/* (glob) |
|
946 | 949 | Date: Thu, 01 Jan 1970 00:01:00 +0000 |
|
947 | 950 | From: quux |
@@ -958,11 +961,11 b' test inline for single patch (quoted-pri' | |||
|
958 | 961 | # User test |
|
959 | 962 | # Date 4 0 |
|
960 | 963 | # Thu Jan 01 00:00:04 1970 +0000 |
|
961 | # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
962 | # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
964 | # Node ID 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
965 | # Parent f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
963 | 966 | long line |
|
964 | 967 | |
|
965 | diff -r 909a00e13e9d -r a2ea8fc83dd8 long | |
|
968 | diff -r f81ef9782946 -r 0c7b871cb86b long | |
|
966 | 969 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
967 | 970 | +++ b/long Thu Jan 01 00:00:04 1970 +0000 |
|
968 | 971 | @@ -0,0 +1,4 @@ |
@@ -1088,10 +1091,10 b' test inline for multiple patches:' | |||
|
1088 | 1091 | Content-Type: multipart/mixed; boundary="===*==" (glob) |
|
1089 | 1092 | MIME-Version: 1.0 |
|
1090 | 1093 | Subject: [PATCH 3 of 3] long line |
|
1091 | X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
1094 | X-Mercurial-Node: 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
1092 | 1095 | X-Mercurial-Series-Index: 3 |
|
1093 | 1096 | X-Mercurial-Series-Total: 3 |
|
1094 |
Message-Id: < |
|
|
1097 | Message-Id: <0c7b871cb86b61a1c07e.63@test-hostname> | |
|
1095 | 1098 | X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@test-hostname> |
|
1096 | 1099 | In-Reply-To: <patchbomb.60@test-hostname> |
|
1097 | 1100 | References: <patchbomb.60@test-hostname> |
@@ -1111,11 +1114,11 b' test inline for multiple patches:' | |||
|
1111 | 1114 | # User test |
|
1112 | 1115 | # Date 4 0 |
|
1113 | 1116 | # Thu Jan 01 00:00:04 1970 +0000 |
|
1114 | # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
1115 | # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
1117 | # Node ID 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
1118 | # Parent f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
1116 | 1119 | long line |
|
1117 | 1120 | |
|
1118 | diff -r 909a00e13e9d -r a2ea8fc83dd8 long | |
|
1121 | diff -r f81ef9782946 -r 0c7b871cb86b long | |
|
1119 | 1122 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
1120 | 1123 | +++ b/long Thu Jan 01 00:00:04 1970 +0000 |
|
1121 | 1124 | @@ -0,0 +1,4 @@ |
@@ -1199,11 +1202,11 b' test attach for single patch (quoted-pri' | |||
|
1199 | 1202 | Content-Type: multipart/mixed; boundary="===*==" (glob) |
|
1200 | 1203 | MIME-Version: 1.0 |
|
1201 | 1204 | Subject: [PATCH] test |
|
1202 | X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
1205 | X-Mercurial-Node: 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
1203 | 1206 | X-Mercurial-Series-Index: 1 |
|
1204 | 1207 | X-Mercurial-Series-Total: 1 |
|
1205 |
Message-Id: < |
|
|
1206 |
X-Mercurial-Series-Id: < |
|
|
1208 | Message-Id: <0c7b871cb86b61a1c07e.60@test-hostname> | |
|
1209 | X-Mercurial-Series-Id: <0c7b871cb86b61a1c07e.60@test-hostname> | |
|
1207 | 1210 | User-Agent: Mercurial-patchbomb/* (glob) |
|
1208 | 1211 | Date: Thu, 01 Jan 1970 00:01:00 +0000 |
|
1209 | 1212 | From: quux |
@@ -1229,11 +1232,11 b' test attach for single patch (quoted-pri' | |||
|
1229 | 1232 | # User test |
|
1230 | 1233 | # Date 4 0 |
|
1231 | 1234 | # Thu Jan 01 00:00:04 1970 +0000 |
|
1232 | # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
1233 | # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
1235 | # Node ID 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
1236 | # Parent f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
1234 | 1237 | long line |
|
1235 | 1238 | |
|
1236 | diff -r 909a00e13e9d -r a2ea8fc83dd8 long | |
|
1239 | diff -r f81ef9782946 -r 0c7b871cb86b long | |
|
1237 | 1240 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
1238 | 1241 | +++ b/long Thu Jan 01 00:00:04 1970 +0000 |
|
1239 | 1242 | @@ -0,0 +1,4 @@ |
@@ -1438,10 +1441,10 b' test attach for multiple patches:' | |||
|
1438 | 1441 | Content-Type: multipart/mixed; boundary="===*==" (glob) |
|
1439 | 1442 | MIME-Version: 1.0 |
|
1440 | 1443 | Subject: [PATCH 3 of 3] long line |
|
1441 | X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
1444 | X-Mercurial-Node: 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
1442 | 1445 | X-Mercurial-Series-Index: 3 |
|
1443 | 1446 | X-Mercurial-Series-Total: 3 |
|
1444 |
Message-Id: < |
|
|
1447 | Message-Id: <0c7b871cb86b61a1c07e.63@test-hostname> | |
|
1445 | 1448 | X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@test-hostname> |
|
1446 | 1449 | In-Reply-To: <patchbomb.60@test-hostname> |
|
1447 | 1450 | References: <patchbomb.60@test-hostname> |
@@ -1470,11 +1473,11 b' test attach for multiple patches:' | |||
|
1470 | 1473 | # User test |
|
1471 | 1474 | # Date 4 0 |
|
1472 | 1475 | # Thu Jan 01 00:00:04 1970 +0000 |
|
1473 | # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
1474 | # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
1476 | # Node ID 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
1477 | # Parent f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
1475 | 1478 | long line |
|
1476 | 1479 | |
|
1477 | diff -r 909a00e13e9d -r a2ea8fc83dd8 long | |
|
1480 | diff -r f81ef9782946 -r 0c7b871cb86b long | |
|
1478 | 1481 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
1479 | 1482 | +++ b/long Thu Jan 01 00:00:04 1970 +0000 |
|
1480 | 1483 | @@ -0,0 +1,4 @@ |
@@ -1929,11 +1932,11 b' test inreplyto:' | |||
|
1929 | 1932 | Content-Type: text/plain; charset="us-ascii" |
|
1930 | 1933 | Content-Transfer-Encoding: 7bit |
|
1931 | 1934 | Subject: [PATCH] Added tag two, two.diff for changeset ff2c9fa2018b |
|
1932 | X-Mercurial-Node: 7aead2484924c445ad8ce2613df91f52f9e502ed | |
|
1935 | X-Mercurial-Node: 9cea7492c36bdda2c72e7dd5f35f7fc367adeb2c | |
|
1933 | 1936 | X-Mercurial-Series-Index: 1 |
|
1934 | 1937 | X-Mercurial-Series-Total: 1 |
|
1935 |
Message-Id: < |
|
|
1936 |
X-Mercurial-Series-Id: < |
|
|
1938 | Message-Id: <9cea7492c36bdda2c72e.60@test-hostname> | |
|
1939 | X-Mercurial-Series-Id: <9cea7492c36bdda2c72e.60@test-hostname> | |
|
1937 | 1940 | In-Reply-To: <baz> |
|
1938 | 1941 | References: <baz> |
|
1939 | 1942 | User-Agent: Mercurial-patchbomb/* (glob) |
@@ -1946,11 +1949,11 b' test inreplyto:' | |||
|
1946 | 1949 | # User test |
|
1947 | 1950 | # Date 0 0 |
|
1948 | 1951 | # Thu Jan 01 00:00:00 1970 +0000 |
|
1949 | # Node ID 7aead2484924c445ad8ce2613df91f52f9e502ed | |
|
1950 | # Parent 045ca29b1ea20e4940411e695e20e521f2f0f98e | |
|
1952 | # Node ID 9cea7492c36bdda2c72e7dd5f35f7fc367adeb2c | |
|
1953 | # Parent 3b775b32716d9b54291ccddf0a36ceea45449bfb | |
|
1951 | 1954 | Added tag two, two.diff for changeset ff2c9fa2018b |
|
1952 | 1955 | |
|
1953 |
diff -r |
|
|
1956 | diff -r 3b775b32716d -r 9cea7492c36b .hgtags | |
|
1954 | 1957 | --- a/.hgtags Thu Jan 01 00:00:00 1970 +0000 |
|
1955 | 1958 | +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000 |
|
1956 | 1959 | @@ -2,3 +2,5 @@ |
@@ -2397,9 +2400,12 b' test multi-address parsing:' | |||
|
2397 | 2400 | User-Agent: Mercurial-patchbomb/* (glob) |
|
2398 | 2401 | Date: Tue, 01 Jan 1980 00:01:00 +0000 |
|
2399 | 2402 | From: quux |
|
2400 | To: spam <spam>, eggs, toast | |
|
2401 | Cc: foo, bar@example.com, "A, B <>" <a@example.com> | |
|
2402 | Bcc: "Quux, A." <quux> | |
|
2403 | To: spam <spam>, eggs, toast (no-py3 !) | |
|
2404 | Cc: foo, bar@example.com, "A, B <>" <a@example.com> (no-py3 !) | |
|
2405 | Bcc: "Quux, A." <quux> (no-py3 !) | |
|
2406 | To: =?iso-8859-1?q?spam?= <spam>, eggs, toast (py3 !) | |
|
2407 | Cc: foo, bar@example.com, =?iso-8859-1?q?A=2C_B_=3C=3E?= <a@example.com> (py3 !) | |
|
2408 | Bcc: =?iso-8859-1?q?Quux=2C_A=2E?= <quux> (py3 !) | |
|
2403 | 2409 | |
|
2404 | 2410 | # HG changeset patch |
|
2405 | 2411 | # User test |
@@ -2601,17 +2607,17 b' test outgoing:' | |||
|
2601 | 2607 | | |
|
2602 | 2608 | o 9:2f9fa9b998c5 d |
|
2603 | 2609 | | |
|
2604 |
| o 8: |
|
|
2610 | | o 8:9cea7492c36b Added tag two, two.diff for changeset ff2c9fa2018b | |
|
2605 | 2611 | | | |
|
2606 |
| o 7: |
|
|
2612 | | o 7:3b775b32716d Added tag one, one.patch for changeset 97d72e5f12c7 | |
|
2607 | 2613 | | | |
|
2608 |
| o 6: |
|
|
2614 | | o 6:c41d7353114c Added tag zero, zero.foo for changeset 8580ff50825a | |
|
2609 | 2615 | | | |
|
2610 |
| o 5: |
|
|
2616 | | o 5:4d6f44f466c9 isolatin 8-bit encoding | |
|
2611 | 2617 | | | |
|
2612 |
| o 4: |
|
|
2618 | | o 4:0c7b871cb86b long line | |
|
2613 | 2619 | | | |
|
2614 | | o 3:909a00e13e9d utf-8 content | |
|
2620 | | o 3:f81ef9782946 \xe7a (esc) | |
|
2615 | 2621 | | | |
|
2616 | 2622 | | o 2:ff2c9fa2018b c |
|
2617 | 2623 | |/ |
@@ -2673,15 +2679,16 b' test outgoing:' | |||
|
2673 | 2679 | @@ -0,0 +1,1 @@ |
|
2674 | 2680 | +c |
|
2675 | 2681 | |
|
2676 |
displaying [PATCH 2 of 6] |
|
|
2682 | displaying [PATCH 2 of 6] \xe7a ... (esc) | |
|
2677 | 2683 | MIME-Version: 1.0 |
|
2678 | 2684 | Content-Type: text/plain; charset="iso-8859-1" |
|
2679 | 2685 | Content-Transfer-Encoding: quoted-printable |
|
2680 |
Subject: [PATCH 2 of 6] |
|
|
2681 | X-Mercurial-Node: 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
2686 | Subject: [PATCH 2 of 6] \xe7a (esc) (no-py3 !) | |
|
2687 | Subject: =?utf-8?b?W1BBVENIIDIgb2YgNl0gw6dh?= (py3 !) | |
|
2688 | X-Mercurial-Node: f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
2682 | 2689 | X-Mercurial-Series-Index: 2 |
|
2683 | 2690 | X-Mercurial-Series-Total: 6 |
|
2684 |
Message-Id: < |
|
|
2691 | Message-Id: <f81ef97829467e868fc4.315532862@test-hostname> | |
|
2685 | 2692 | X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.315532861@test-hostname> |
|
2686 | 2693 | In-Reply-To: <patchbomb.315532860@test-hostname> |
|
2687 | 2694 | References: <patchbomb.315532860@test-hostname> |
@@ -2694,18 +2701,18 b' test outgoing:' | |||
|
2694 | 2701 | # User test |
|
2695 | 2702 | # Date 4 0 |
|
2696 | 2703 | # Thu Jan 01 00:00:04 1970 +0000 |
|
2697 | # Node ID 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
2704 | # Node ID f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
2698 | 2705 | # Parent ff2c9fa2018b15fa74b33363bda9527323e2a99f |
|
2699 | utf-8 content | |
|
2700 | ||
|
2701 |
diff -r ff2c9fa2018b -r |
|
|
2706 | =E7a | |
|
2707 | ||
|
2708 | diff -r ff2c9fa2018b -r f81ef9782946 description | |
|
2702 | 2709 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
2703 | 2710 | +++ b/description Thu Jan 01 00:00:04 1970 +0000 |
|
2704 | 2711 | @@ -0,0 +1,3 @@ |
|
2705 | 2712 | +a multiline |
|
2706 | 2713 | + |
|
2707 | 2714 | +description |
|
2708 |
diff -r ff2c9fa2018b -r |
|
|
2715 | diff -r ff2c9fa2018b -r f81ef9782946 utf | |
|
2709 | 2716 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
2710 | 2717 | +++ b/utf Thu Jan 01 00:00:04 1970 +0000 |
|
2711 | 2718 | @@ -0,0 +1,1 @@ |
@@ -2716,10 +2723,10 b' test outgoing:' | |||
|
2716 | 2723 | Content-Type: text/plain; charset="us-ascii" |
|
2717 | 2724 | Content-Transfer-Encoding: quoted-printable |
|
2718 | 2725 | Subject: [PATCH 3 of 6] long line |
|
2719 | X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
2726 | X-Mercurial-Node: 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
2720 | 2727 | X-Mercurial-Series-Index: 3 |
|
2721 | 2728 | X-Mercurial-Series-Total: 6 |
|
2722 |
Message-Id: < |
|
|
2729 | Message-Id: <0c7b871cb86b61a1c07e.315532863@test-hostname> | |
|
2723 | 2730 | X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.315532861@test-hostname> |
|
2724 | 2731 | In-Reply-To: <patchbomb.315532860@test-hostname> |
|
2725 | 2732 | References: <patchbomb.315532860@test-hostname> |
@@ -2732,11 +2739,11 b' test outgoing:' | |||
|
2732 | 2739 | # User test |
|
2733 | 2740 | # Date 4 0 |
|
2734 | 2741 | # Thu Jan 01 00:00:04 1970 +0000 |
|
2735 | # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
2736 | # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f | |
|
2742 | # Node ID 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
2743 | # Parent f81ef97829467e868fc405fccbcfa66217e4d3e6 | |
|
2737 | 2744 | long line |
|
2738 | 2745 | |
|
2739 | diff -r 909a00e13e9d -r a2ea8fc83dd8 long | |
|
2746 | diff -r f81ef9782946 -r 0c7b871cb86b long | |
|
2740 | 2747 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
2741 | 2748 | +++ b/long Thu Jan 01 00:00:04 1970 +0000 |
|
2742 | 2749 | @@ -0,0 +1,4 @@ |
@@ -2763,10 +2770,10 b' test outgoing:' | |||
|
2763 | 2770 | Content-Type: text/plain; charset="iso-8859-1" |
|
2764 | 2771 | Content-Transfer-Encoding: quoted-printable |
|
2765 | 2772 | Subject: [PATCH 4 of 6] isolatin 8-bit encoding |
|
2766 | X-Mercurial-Node: 240fb913fc1b7ff15ddb9f33e73d82bf5277c720 | |
|
2773 | X-Mercurial-Node: 4d6f44f466c96d89f2e7e865a70ff41d8b6eee37 | |
|
2767 | 2774 | X-Mercurial-Series-Index: 4 |
|
2768 | 2775 | X-Mercurial-Series-Total: 6 |
|
2769 |
Message-Id: < |
|
|
2776 | Message-Id: <4d6f44f466c96d89f2e7.315532864@test-hostname> | |
|
2770 | 2777 | X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.315532861@test-hostname> |
|
2771 | 2778 | In-Reply-To: <patchbomb.315532860@test-hostname> |
|
2772 | 2779 | References: <patchbomb.315532860@test-hostname> |
@@ -2779,11 +2786,11 b' test outgoing:' | |||
|
2779 | 2786 | # User test |
|
2780 | 2787 | # Date 5 0 |
|
2781 | 2788 | # Thu Jan 01 00:00:05 1970 +0000 |
|
2782 | # Node ID 240fb913fc1b7ff15ddb9f33e73d82bf5277c720 | |
|
2783 | # Parent a2ea8fc83dd8b93cfd86ac97b28287204ab806e1 | |
|
2789 | # Node ID 4d6f44f466c96d89f2e7e865a70ff41d8b6eee37 | |
|
2790 | # Parent 0c7b871cb86b61a1c07e244393603c361e4a178d | |
|
2784 | 2791 | isolatin 8-bit encoding |
|
2785 | 2792 | |
|
2786 |
diff -r |
|
|
2793 | diff -r 0c7b871cb86b -r 4d6f44f466c9 isolatin | |
|
2787 | 2794 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
2788 | 2795 | +++ b/isolatin Thu Jan 01 00:00:05 1970 +0000 |
|
2789 | 2796 | @@ -0,0 +1,1 @@ |
@@ -2794,10 +2801,10 b' test outgoing:' | |||
|
2794 | 2801 | Content-Type: text/plain; charset="us-ascii" |
|
2795 | 2802 | Content-Transfer-Encoding: 7bit |
|
2796 | 2803 | Subject: [PATCH 5 of 6] Added tag zero, zero.foo for changeset 8580ff50825a |
|
2797 | X-Mercurial-Node: 5d5ef15dfe5e7bd3a4ee154b5fff76c7945ec433 | |
|
2804 | X-Mercurial-Node: c41d7353114ccb07a50a822ad5ddf47051c88ec2 | |
|
2798 | 2805 | X-Mercurial-Series-Index: 5 |
|
2799 | 2806 | X-Mercurial-Series-Total: 6 |
|
2800 |
Message-Id: < |
|
|
2807 | Message-Id: <c41d7353114ccb07a50a.315532865@test-hostname> | |
|
2801 | 2808 | X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.315532861@test-hostname> |
|
2802 | 2809 | In-Reply-To: <patchbomb.315532860@test-hostname> |
|
2803 | 2810 | References: <patchbomb.315532860@test-hostname> |
@@ -2810,11 +2817,11 b' test outgoing:' | |||
|
2810 | 2817 | # User test |
|
2811 | 2818 | # Date 0 0 |
|
2812 | 2819 | # Thu Jan 01 00:00:00 1970 +0000 |
|
2813 | # Node ID 5d5ef15dfe5e7bd3a4ee154b5fff76c7945ec433 | |
|
2814 | # Parent 240fb913fc1b7ff15ddb9f33e73d82bf5277c720 | |
|
2820 | # Node ID c41d7353114ccb07a50a822ad5ddf47051c88ec2 | |
|
2821 | # Parent 4d6f44f466c96d89f2e7e865a70ff41d8b6eee37 | |
|
2815 | 2822 | Added tag zero, zero.foo for changeset 8580ff50825a |
|
2816 | 2823 | |
|
2817 | diff -r 240fb913fc1b -r 5d5ef15dfe5e .hgtags | |
|
2824 | diff -r 4d6f44f466c9 -r c41d7353114c .hgtags | |
|
2818 | 2825 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
2819 | 2826 | +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000 |
|
2820 | 2827 | @@ -0,0 +1,2 @@ |
@@ -85,7 +85,7 b' Known exception should be caught, but pr' | |||
|
85 | 85 | $ hg --config "extensions.t=$abspath" --config 'worker.numcpus=8' \ |
|
86 | 86 | > test 100000.0 abort --traceback 2>&1 | egrep '(SystemExit|Abort)' |
|
87 | 87 | raise error.Abort(b'known exception') |
|
88 |
mercurial.error.Abort: |
|
|
88 | mercurial.error.Abort: known exception (py3 !) | |
|
89 | 89 | Abort: known exception (no-py3 !) |
|
90 | 90 | SystemExit: 255 |
|
91 | 91 |
|
1 | NO CONTENT: file was removed | |
This diff has been collapsed as it changes many lines, (4094 lines changed) Show them Hide them |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now