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