##// END OF EJS Templates
packaging: move Inno Setup core logic into a module...
Gregory Szorc -
r42077:dc7827a9 default
parent child Browse files
Show More
@@ -1,204 +1,169 b''
1 #!/usr/bin/env python3
1 # inno.py - Inno Setup functionality.
2 # build.py - Inno installer build script.
3 #
2 #
4 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
5 #
4 #
6 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
8
7
9 # This script automates the building of the Inno MSI installer for Mercurial.
10
11 # no-check-code because Python 3 native.
8 # no-check-code because Python 3 native.
12
9
13 import argparse
14 import os
10 import os
15 import pathlib
11 import pathlib
16 import shutil
12 import shutil
17 import subprocess
13 import subprocess
18 import sys
19 import tempfile
14 import tempfile
20
15
16 from .downloads import (
17 download_entry,
18 )
19 from .util import (
20 extract_tar_to_directory,
21 extract_zip_to_directory,
22 find_vc_runtime_files,
23 )
24
21
25
22 PRINT_PYTHON_INFO = '''
26 PRINT_PYTHON_INFO = '''
23 import platform, sys; print("%s:%d" % (platform.architecture()[0], sys.version_info[0]))
27 import platform, sys; print("%s:%d" % (platform.architecture()[0], sys.version_info[0]))
24 '''.strip()
28 '''.strip()
25
29
26
30
27 def build(source_dir: pathlib.Path, build_dir: pathlib.Path,
31 def build(source_dir: pathlib.Path, build_dir: pathlib.Path,
28 python_exe: pathlib.Path, iscc_exe: pathlib.Path,
32 python_exe: pathlib.Path, iscc_exe: pathlib.Path,
29 version=None):
33 version=None):
30 """Build the Inno installer.
34 """Build the Inno installer.
31
35
32 Build files will be placed in ``build_dir``.
36 Build files will be placed in ``build_dir``.
33
37
34 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
38 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
35 for finding the Python 2.7 toolchain. So, we require the environment
39 for finding the Python 2.7 toolchain. So, we require the environment
36 to already be configured with an active toolchain.
40 to already be configured with an active toolchain.
37 """
41 """
38 from hgpackaging.downloads import (
42 if not iscc_exe.exists():
39 download_entry,
43 raise Exception('%s does not exist' % iscc_exe)
40 )
41 from hgpackaging.util import (
42 extract_tar_to_directory,
43 extract_zip_to_directory,
44 find_vc_runtime_files,
45 )
46
47 if not iscc.exists():
48 raise Exception('%s does not exist' % iscc)
49
44
50 if 'VCINSTALLDIR' not in os.environ:
45 if 'VCINSTALLDIR' not in os.environ:
51 raise Exception('not running from a Visual C++ build environment; '
46 raise Exception('not running from a Visual C++ build environment; '
52 'execute the "Visual C++ <version> Command Prompt" '
47 'execute the "Visual C++ <version> Command Prompt" '
53 'application shortcut or a vcsvarsall.bat file')
48 'application shortcut or a vcsvarsall.bat file')
54
49
55 # Identity x86/x64 and validate the environment matches the Python
50 # Identity x86/x64 and validate the environment matches the Python
56 # architecture.
51 # architecture.
57 vc_x64 = r'\x64' in os.environ['LIB']
52 vc_x64 = r'\x64' in os.environ['LIB']
58
53
59 res = subprocess.run(
54 res = subprocess.run(
60 [str(python_exe), '-c', PRINT_PYTHON_INFO],
55 [str(python_exe), '-c', PRINT_PYTHON_INFO],
61 capture_output=True, check=True)
56 capture_output=True, check=True)
62
57
63 py_arch, py_version = res.stdout.decode('utf-8').split(':')
58 py_arch, py_version = res.stdout.decode('utf-8').split(':')
64 py_version = int(py_version)
59 py_version = int(py_version)
65
60
66 if vc_x64:
61 if vc_x64:
67 if py_arch != '64bit':
62 if py_arch != '64bit':
68 raise Exception('architecture mismatch: Visual C++ environment '
63 raise Exception('architecture mismatch: Visual C++ environment '
69 'is configured for 64-bit but Python is 32-bit')
64 'is configured for 64-bit but Python is 32-bit')
70 else:
65 else:
71 if py_arch != '32bit':
66 if py_arch != '32bit':
72 raise Exception('architecture mismatch: Visual C++ environment '
67 raise Exception('architecture mismatch: Visual C++ environment '
73 'is configured for 32-bit but Python is 64-bit')
68 'is configured for 32-bit but Python is 64-bit')
74
69
75 if py_version != 2:
70 if py_version != 2:
76 raise Exception('Only Python 2 is currently supported')
71 raise Exception('Only Python 2 is currently supported')
77
72
78 build_dir.mkdir(exist_ok=True)
73 build_dir.mkdir(exist_ok=True)
79
74
80 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
75 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
81 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
76 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
82 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
77 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
83 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
78 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
84
79
85 venv_path = build_dir / ('venv-inno-%s' % ('x64' if vc_x64 else 'x86'))
80 venv_path = build_dir / ('venv-inno-%s' % ('x64' if vc_x64 else 'x86'))
86
81
87 gettext_root = build_dir / (
82 gettext_root = build_dir / (
88 'gettext-win-%s' % gettext_entry['version'])
83 'gettext-win-%s' % gettext_entry['version'])
89
84
90 if not gettext_root.exists():
85 if not gettext_root.exists():
91 extract_zip_to_directory(gettext_pkg, gettext_root)
86 extract_zip_to_directory(gettext_pkg, gettext_root)
92 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
87 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
93
88
94 with tempfile.TemporaryDirectory() as td:
89 with tempfile.TemporaryDirectory() as td:
95 td = pathlib.Path(td)
90 td = pathlib.Path(td)
96
91
97 # This assumes Python 2.
92 # This assumes Python 2.
98 extract_tar_to_directory(virtualenv_pkg, td)
93 extract_tar_to_directory(virtualenv_pkg, td)
99 extract_zip_to_directory(py2exe_pkg, td)
94 extract_zip_to_directory(py2exe_pkg, td)
100
95
101 virtualenv_src_path = td / ('virtualenv-%s' %
96 virtualenv_src_path = td / ('virtualenv-%s' %
102 virtualenv_entry['version'])
97 virtualenv_entry['version'])
103 py2exe_source_path = td / ('py2exe-%s' %
98 py2exe_source_path = td / ('py2exe-%s' %
104 py2exe_entry['version'])
99 py2exe_entry['version'])
105
100
106 virtualenv_py = virtualenv_src_path / 'virtualenv.py'
101 virtualenv_py = virtualenv_src_path / 'virtualenv.py'
107
102
108 if not venv_path.exists():
103 if not venv_path.exists():
109 print('creating virtualenv with dependencies')
104 print('creating virtualenv with dependencies')
110 subprocess.run(
105 subprocess.run(
111 [str(python_exe), str(virtualenv_py), str(venv_path)],
106 [str(python_exe), str(virtualenv_py), str(venv_path)],
112 check=True)
107 check=True)
113
108
114 venv_python = venv_path / 'Scripts' / 'python.exe'
109 venv_python = venv_path / 'Scripts' / 'python.exe'
115 venv_pip = venv_path / 'Scripts' / 'pip.exe'
110 venv_pip = venv_path / 'Scripts' / 'pip.exe'
116
111
117 requirements_txt = (source_dir / 'contrib' / 'packaging' /
112 requirements_txt = (source_dir / 'contrib' / 'packaging' /
118 'inno' / 'requirements.txt')
113 'inno' / 'requirements.txt')
119 subprocess.run([str(venv_pip), 'install', '-r', str(requirements_txt)],
114 subprocess.run([str(venv_pip), 'install', '-r', str(requirements_txt)],
120 check=True)
115 check=True)
121
116
122 # Force distutils to use VC++ settings from environment, which was
117 # Force distutils to use VC++ settings from environment, which was
123 # validated above.
118 # validated above.
124 env = dict(os.environ)
119 env = dict(os.environ)
125 env['DISTUTILS_USE_SDK'] = '1'
120 env['DISTUTILS_USE_SDK'] = '1'
126 env['MSSdk'] = '1'
121 env['MSSdk'] = '1'
127
122
128 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
123 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
129 if not py2exe_py_path.exists():
124 if not py2exe_py_path.exists():
130 print('building py2exe')
125 print('building py2exe')
131 subprocess.run([str(venv_python), 'setup.py', 'install'],
126 subprocess.run([str(venv_python), 'setup.py', 'install'],
132 cwd=py2exe_source_path,
127 cwd=py2exe_source_path,
133 env=env,
128 env=env,
134 check=True)
129 check=True)
135
130
136 # Register location of msgfmt and other binaries.
131 # Register location of msgfmt and other binaries.
137 env['PATH'] = '%s%s%s' % (
132 env['PATH'] = '%s%s%s' % (
138 env['PATH'], os.pathsep, str(gettext_root / 'bin'))
133 env['PATH'], os.pathsep, str(gettext_root / 'bin'))
139
134
140 print('building Mercurial')
135 print('building Mercurial')
141 subprocess.run(
136 subprocess.run(
142 [str(venv_python), 'setup.py',
137 [str(venv_python), 'setup.py',
143 'py2exe', '-b', '3' if vc_x64 else '2',
138 'py2exe', '-b', '3' if vc_x64 else '2',
144 'build_doc', '--html'],
139 'build_doc', '--html'],
145 cwd=str(source_dir),
140 cwd=str(source_dir),
146 env=env,
141 env=env,
147 check=True)
142 check=True)
148
143
149 # hg.exe depends on VC9 runtime DLLs. Copy those into place.
144 # hg.exe depends on VC9 runtime DLLs. Copy those into place.
150 for f in find_vc_runtime_files(vc_x64):
145 for f in find_vc_runtime_files(vc_x64):
151 if f.name.endswith('.manifest'):
146 if f.name.endswith('.manifest'):
152 basename = 'Microsoft.VC90.CRT.manifest'
147 basename = 'Microsoft.VC90.CRT.manifest'
153 else:
148 else:
154 basename = f.name
149 basename = f.name
155
150
156 dest_path = source_dir / 'dist' / basename
151 dest_path = source_dir / 'dist' / basename
157
152
158 print('copying %s to %s' % (f, dest_path))
153 print('copying %s to %s' % (f, dest_path))
159 shutil.copyfile(f, dest_path)
154 shutil.copyfile(f, dest_path)
160
155
161 print('creating installer')
156 print('creating installer')
162
157
163 args = [str(iscc_exe)]
158 args = [str(iscc_exe)]
164
159
165 if vc_x64:
160 if vc_x64:
166 args.append('/dARCH=x64')
161 args.append('/dARCH=x64')
167
162
168 if version:
163 if version:
169 args.append('/dVERSION=%s' % version)
164 args.append('/dVERSION=%s' % version)
170
165
171 args.append('/Odist')
166 args.append('/Odist')
172 args.append('contrib/packaging/inno/mercurial.iss')
167 args.append('contrib/packaging/inno/mercurial.iss')
173
168
174 subprocess.run(args, cwd=str(source_dir), check=True)
169 subprocess.run(args, cwd=str(source_dir), check=True)
175
176
177 if __name__ == '__main__':
178 parser = argparse.ArgumentParser()
179
180 parser.add_argument('--python',
181 required=True,
182 help='path to python.exe to use')
183 parser.add_argument('--iscc',
184 help='path to iscc.exe to use')
185 parser.add_argument('--version',
186 help='Mercurial version string to use '
187 '(detected from __version__.py if not defined')
188
189 args = parser.parse_args()
190
191 if args.iscc:
192 iscc = pathlib.Path(args.iscc)
193 else:
194 iscc = (pathlib.Path(os.environ['ProgramFiles(x86)']) / 'Inno Setup 5' /
195 'ISCC.exe')
196
197 here = pathlib.Path(os.path.abspath(os.path.dirname(__file__)))
198 source_dir = here.parent.parent.parent
199 build_dir = source_dir / 'build'
200
201 sys.path.insert(0, str(source_dir / 'contrib' / 'packaging'))
202
203 build(source_dir, build_dir, pathlib.Path(args.python), iscc,
204 version=args.version)
@@ -1,204 +1,48 b''
1 #!/usr/bin/env python3
1 #!/usr/bin/env python3
2 # build.py - Inno installer build script.
2 # build.py - Inno installer build script.
3 #
3 #
4 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
4 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 # This script automates the building of the Inno MSI installer for Mercurial.
9 # This script automates the building of the Inno MSI installer for Mercurial.
10
10
11 # no-check-code because Python 3 native.
11 # no-check-code because Python 3 native.
12
12
13 import argparse
13 import argparse
14 import os
14 import os
15 import pathlib
15 import pathlib
16 import shutil
17 import subprocess
18 import sys
16 import sys
19 import tempfile
20
21
22 PRINT_PYTHON_INFO = '''
23 import platform, sys; print("%s:%d" % (platform.architecture()[0], sys.version_info[0]))
24 '''.strip()
25
26
27 def build(source_dir: pathlib.Path, build_dir: pathlib.Path,
28 python_exe: pathlib.Path, iscc_exe: pathlib.Path,
29 version=None):
30 """Build the Inno installer.
31
32 Build files will be placed in ``build_dir``.
33
34 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
35 for finding the Python 2.7 toolchain. So, we require the environment
36 to already be configured with an active toolchain.
37 """
38 from hgpackaging.downloads import (
39 download_entry,
40 )
41 from hgpackaging.util import (
42 extract_tar_to_directory,
43 extract_zip_to_directory,
44 find_vc_runtime_files,
45 )
46
47 if not iscc.exists():
48 raise Exception('%s does not exist' % iscc)
49
50 if 'VCINSTALLDIR' not in os.environ:
51 raise Exception('not running from a Visual C++ build environment; '
52 'execute the "Visual C++ <version> Command Prompt" '
53 'application shortcut or a vcsvarsall.bat file')
54
55 # Identity x86/x64 and validate the environment matches the Python
56 # architecture.
57 vc_x64 = r'\x64' in os.environ['LIB']
58
59 res = subprocess.run(
60 [str(python_exe), '-c', PRINT_PYTHON_INFO],
61 capture_output=True, check=True)
62
63 py_arch, py_version = res.stdout.decode('utf-8').split(':')
64 py_version = int(py_version)
65
66 if vc_x64:
67 if py_arch != '64bit':
68 raise Exception('architecture mismatch: Visual C++ environment '
69 'is configured for 64-bit but Python is 32-bit')
70 else:
71 if py_arch != '32bit':
72 raise Exception('architecture mismatch: Visual C++ environment '
73 'is configured for 32-bit but Python is 64-bit')
74
75 if py_version != 2:
76 raise Exception('Only Python 2 is currently supported')
77
78 build_dir.mkdir(exist_ok=True)
79
80 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
81 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
82 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
83 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
84
85 venv_path = build_dir / ('venv-inno-%s' % ('x64' if vc_x64 else 'x86'))
86
87 gettext_root = build_dir / (
88 'gettext-win-%s' % gettext_entry['version'])
89
90 if not gettext_root.exists():
91 extract_zip_to_directory(gettext_pkg, gettext_root)
92 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
93
94 with tempfile.TemporaryDirectory() as td:
95 td = pathlib.Path(td)
96
97 # This assumes Python 2.
98 extract_tar_to_directory(virtualenv_pkg, td)
99 extract_zip_to_directory(py2exe_pkg, td)
100
101 virtualenv_src_path = td / ('virtualenv-%s' %
102 virtualenv_entry['version'])
103 py2exe_source_path = td / ('py2exe-%s' %
104 py2exe_entry['version'])
105
106 virtualenv_py = virtualenv_src_path / 'virtualenv.py'
107
108 if not venv_path.exists():
109 print('creating virtualenv with dependencies')
110 subprocess.run(
111 [str(python_exe), str(virtualenv_py), str(venv_path)],
112 check=True)
113
114 venv_python = venv_path / 'Scripts' / 'python.exe'
115 venv_pip = venv_path / 'Scripts' / 'pip.exe'
116
117 requirements_txt = (source_dir / 'contrib' / 'packaging' /
118 'inno' / 'requirements.txt')
119 subprocess.run([str(venv_pip), 'install', '-r', str(requirements_txt)],
120 check=True)
121
122 # Force distutils to use VC++ settings from environment, which was
123 # validated above.
124 env = dict(os.environ)
125 env['DISTUTILS_USE_SDK'] = '1'
126 env['MSSdk'] = '1'
127
128 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
129 if not py2exe_py_path.exists():
130 print('building py2exe')
131 subprocess.run([str(venv_python), 'setup.py', 'install'],
132 cwd=py2exe_source_path,
133 env=env,
134 check=True)
135
136 # Register location of msgfmt and other binaries.
137 env['PATH'] = '%s%s%s' % (
138 env['PATH'], os.pathsep, str(gettext_root / 'bin'))
139
140 print('building Mercurial')
141 subprocess.run(
142 [str(venv_python), 'setup.py',
143 'py2exe', '-b', '3' if vc_x64 else '2',
144 'build_doc', '--html'],
145 cwd=str(source_dir),
146 env=env,
147 check=True)
148
149 # hg.exe depends on VC9 runtime DLLs. Copy those into place.
150 for f in find_vc_runtime_files(vc_x64):
151 if f.name.endswith('.manifest'):
152 basename = 'Microsoft.VC90.CRT.manifest'
153 else:
154 basename = f.name
155
156 dest_path = source_dir / 'dist' / basename
157
158 print('copying %s to %s' % (f, dest_path))
159 shutil.copyfile(f, dest_path)
160
161 print('creating installer')
162
163 args = [str(iscc_exe)]
164
165 if vc_x64:
166 args.append('/dARCH=x64')
167
168 if version:
169 args.append('/dVERSION=%s' % version)
170
171 args.append('/Odist')
172 args.append('contrib/packaging/inno/mercurial.iss')
173
174 subprocess.run(args, cwd=str(source_dir), check=True)
175
17
176
18
177 if __name__ == '__main__':
19 if __name__ == '__main__':
178 parser = argparse.ArgumentParser()
20 parser = argparse.ArgumentParser()
179
21
180 parser.add_argument('--python',
22 parser.add_argument('--python',
181 required=True,
23 required=True,
182 help='path to python.exe to use')
24 help='path to python.exe to use')
183 parser.add_argument('--iscc',
25 parser.add_argument('--iscc',
184 help='path to iscc.exe to use')
26 help='path to iscc.exe to use')
185 parser.add_argument('--version',
27 parser.add_argument('--version',
186 help='Mercurial version string to use '
28 help='Mercurial version string to use '
187 '(detected from __version__.py if not defined')
29 '(detected from __version__.py if not defined')
188
30
189 args = parser.parse_args()
31 args = parser.parse_args()
190
32
191 if args.iscc:
33 if args.iscc:
192 iscc = pathlib.Path(args.iscc)
34 iscc = pathlib.Path(args.iscc)
193 else:
35 else:
194 iscc = (pathlib.Path(os.environ['ProgramFiles(x86)']) / 'Inno Setup 5' /
36 iscc = (pathlib.Path(os.environ['ProgramFiles(x86)']) / 'Inno Setup 5' /
195 'ISCC.exe')
37 'ISCC.exe')
196
38
197 here = pathlib.Path(os.path.abspath(os.path.dirname(__file__)))
39 here = pathlib.Path(os.path.abspath(os.path.dirname(__file__)))
198 source_dir = here.parent.parent.parent
40 source_dir = here.parent.parent.parent
199 build_dir = source_dir / 'build'
41 build_dir = source_dir / 'build'
200
42
201 sys.path.insert(0, str(source_dir / 'contrib' / 'packaging'))
43 sys.path.insert(0, str(source_dir / 'contrib' / 'packaging'))
202
44
45 from hgpackaging.inno import build
46
203 build(source_dir, build_dir, pathlib.Path(args.python), iscc,
47 build(source_dir, build_dir, pathlib.Path(args.python), iscc,
204 version=args.version)
48 version=args.version)
@@ -1,72 +1,73 b''
1 #require test-repo
1 #require test-repo
2
2
3 $ . "$TESTDIR/helpers-testrepo.sh"
3 $ . "$TESTDIR/helpers-testrepo.sh"
4 $ check_code="$TESTDIR"/../contrib/check-code.py
4 $ check_code="$TESTDIR"/../contrib/check-code.py
5 $ cd "$TESTDIR"/..
5 $ cd "$TESTDIR"/..
6
6
7 New errors are not allowed. Warnings are strongly discouraged.
7 New errors are not allowed. Warnings are strongly discouraged.
8 (The writing "no-che?k-code" is for not skipping this file when checking.)
8 (The writing "no-che?k-code" is for not skipping this file when checking.)
9
9
10 $ testrepohg locate \
10 $ testrepohg locate \
11 > -X contrib/python-zstandard \
11 > -X contrib/python-zstandard \
12 > -X hgext/fsmonitor/pywatchman \
12 > -X hgext/fsmonitor/pywatchman \
13 > -X mercurial/thirdparty \
13 > -X mercurial/thirdparty \
14 > | sed 's-\\-/-g' | "$check_code" --warnings --per-file=0 - || false
14 > | sed 's-\\-/-g' | "$check_code" --warnings --per-file=0 - || false
15 Skipping contrib/packaging/hgpackaging/downloads.py it has no-che?k-code (glob)
15 Skipping contrib/packaging/hgpackaging/downloads.py it has no-che?k-code (glob)
16 Skipping contrib/packaging/hgpackaging/inno.py it has no-che?k-code (glob)
16 Skipping contrib/packaging/hgpackaging/util.py it has no-che?k-code (glob)
17 Skipping contrib/packaging/hgpackaging/util.py it has no-che?k-code (glob)
17 Skipping contrib/packaging/inno/build.py it has no-che?k-code (glob)
18 Skipping contrib/packaging/inno/build.py it has no-che?k-code (glob)
18 Skipping i18n/polib.py it has no-che?k-code (glob)
19 Skipping i18n/polib.py it has no-che?k-code (glob)
19 Skipping mercurial/statprof.py it has no-che?k-code (glob)
20 Skipping mercurial/statprof.py it has no-che?k-code (glob)
20 Skipping tests/badserverext.py it has no-che?k-code (glob)
21 Skipping tests/badserverext.py it has no-che?k-code (glob)
21
22
22 @commands in debugcommands.py should be in alphabetical order.
23 @commands in debugcommands.py should be in alphabetical order.
23
24
24 >>> import re
25 >>> import re
25 >>> commands = []
26 >>> commands = []
26 >>> with open('mercurial/debugcommands.py', 'rb') as fh:
27 >>> with open('mercurial/debugcommands.py', 'rb') as fh:
27 ... for line in fh:
28 ... for line in fh:
28 ... m = re.match(br"^@command\('([a-z]+)", line)
29 ... m = re.match(br"^@command\('([a-z]+)", line)
29 ... if m:
30 ... if m:
30 ... commands.append(m.group(1))
31 ... commands.append(m.group(1))
31 >>> scommands = list(sorted(commands))
32 >>> scommands = list(sorted(commands))
32 >>> for i, command in enumerate(scommands):
33 >>> for i, command in enumerate(scommands):
33 ... if command != commands[i]:
34 ... if command != commands[i]:
34 ... print('commands in debugcommands.py not sorted; first differing '
35 ... print('commands in debugcommands.py not sorted; first differing '
35 ... 'command is %s; expected %s' % (commands[i], command))
36 ... 'command is %s; expected %s' % (commands[i], command))
36 ... break
37 ... break
37
38
38 Prevent adding new files in the root directory accidentally.
39 Prevent adding new files in the root directory accidentally.
39
40
40 $ testrepohg files 'glob:*'
41 $ testrepohg files 'glob:*'
41 .arcconfig
42 .arcconfig
42 .clang-format
43 .clang-format
43 .editorconfig
44 .editorconfig
44 .hgignore
45 .hgignore
45 .hgsigs
46 .hgsigs
46 .hgtags
47 .hgtags
47 .jshintrc
48 .jshintrc
48 CONTRIBUTING
49 CONTRIBUTING
49 CONTRIBUTORS
50 CONTRIBUTORS
50 COPYING
51 COPYING
51 Makefile
52 Makefile
52 README.rst
53 README.rst
53 hg
54 hg
54 hgeditor
55 hgeditor
55 hgweb.cgi
56 hgweb.cgi
56 setup.py
57 setup.py
57
58
58 Prevent adding modules which could be shadowed by ancient .so/.dylib.
59 Prevent adding modules which could be shadowed by ancient .so/.dylib.
59
60
60 $ testrepohg files \
61 $ testrepohg files \
61 > mercurial/base85.py \
62 > mercurial/base85.py \
62 > mercurial/bdiff.py \
63 > mercurial/bdiff.py \
63 > mercurial/diffhelpers.py \
64 > mercurial/diffhelpers.py \
64 > mercurial/mpatch.py \
65 > mercurial/mpatch.py \
65 > mercurial/osutil.py \
66 > mercurial/osutil.py \
66 > mercurial/parsers.py \
67 > mercurial/parsers.py \
67 > mercurial/zstd.py
68 > mercurial/zstd.py
68 [1]
69 [1]
69
70
70 Keep python3 tests sorted:
71 Keep python3 tests sorted:
71 $ sort < contrib/python3-whitelist > $TESTTMP/py3sorted
72 $ sort < contrib/python3-whitelist > $TESTTMP/py3sorted
72 $ cmp contrib/python3-whitelist $TESTTMP/py3sorted || echo 'Please sort passing tests!'
73 $ cmp contrib/python3-whitelist $TESTTMP/py3sorted || echo 'Please sort passing tests!'
General Comments 0
You need to be logged in to leave comments. Login now