##// END OF EJS Templates
packaging: consolidate CLI functionality into packaging.py...
Gregory Szorc -
r43913:081a77df default
parent child Browse files
Show More
@@ -0,0 +1,153 b''
1 # cli.py - Command line interface for automation
2 #
3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
4 #
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
7
8 # no-check-code because Python 3 native.
9
10 import argparse
11 import os
12 import pathlib
13
14 from . import (
15 inno,
16 wix,
17 )
18
19 HERE = pathlib.Path(os.path.abspath(os.path.dirname(__file__)))
20 SOURCE_DIR = HERE.parent.parent.parent
21
22
23 def build_inno(python=None, iscc=None, version=None):
24 if not os.path.isabs(python):
25 raise Exception("--python arg must be an absolute path")
26
27 if iscc:
28 iscc = pathlib.Path(iscc)
29 else:
30 iscc = (
31 pathlib.Path(os.environ["ProgramFiles(x86)"])
32 / "Inno Setup 5"
33 / "ISCC.exe"
34 )
35
36 build_dir = SOURCE_DIR / "build"
37
38 inno.build(
39 SOURCE_DIR, build_dir, pathlib.Path(python), iscc, version=version,
40 )
41
42
43 def build_wix(
44 name=None,
45 python=None,
46 version=None,
47 sign_sn=None,
48 sign_cert=None,
49 sign_password=None,
50 sign_timestamp_url=None,
51 extra_packages_script=None,
52 extra_wxs=None,
53 extra_features=None,
54 ):
55 fn = wix.build_installer
56 kwargs = {
57 "source_dir": SOURCE_DIR,
58 "python_exe": pathlib.Path(python),
59 "version": version,
60 }
61
62 if not os.path.isabs(python):
63 raise Exception("--python arg must be an absolute path")
64
65 if extra_packages_script:
66 kwargs["extra_packages_script"] = extra_packages_script
67 if extra_wxs:
68 kwargs["extra_wxs"] = dict(
69 thing.split("=") for thing in extra_wxs.split(",")
70 )
71 if extra_features:
72 kwargs["extra_features"] = extra_features.split(",")
73
74 if sign_sn or sign_cert:
75 fn = wix.build_signed_installer
76 kwargs["name"] = name
77 kwargs["subject_name"] = sign_sn
78 kwargs["cert_path"] = sign_cert
79 kwargs["cert_password"] = sign_password
80 kwargs["timestamp_url"] = sign_timestamp_url
81
82 fn(**kwargs)
83
84
85 def get_parser():
86 parser = argparse.ArgumentParser()
87
88 subparsers = parser.add_subparsers()
89
90 sp = subparsers.add_parser("inno", help="Build Inno Setup installer")
91 sp.add_argument("--python", required=True, help="path to python.exe to use")
92 sp.add_argument("--iscc", help="path to iscc.exe to use")
93 sp.add_argument(
94 "--version",
95 help="Mercurial version string to use "
96 "(detected from __version__.py if not defined",
97 )
98 sp.set_defaults(func=build_inno)
99
100 sp = subparsers.add_parser(
101 "wix", help="Build Windows installer with WiX Toolset"
102 )
103 sp.add_argument("--name", help="Application name", default="Mercurial")
104 sp.add_argument(
105 "--python", help="Path to Python executable to use", required=True
106 )
107 sp.add_argument(
108 "--sign-sn",
109 help="Subject name (or fragment thereof) of certificate "
110 "to use for signing",
111 )
112 sp.add_argument(
113 "--sign-cert", help="Path to certificate to use for signing"
114 )
115 sp.add_argument("--sign-password", help="Password for signing certificate")
116 sp.add_argument(
117 "--sign-timestamp-url",
118 help="URL of timestamp server to use for signing",
119 )
120 sp.add_argument("--version", help="Version string to use")
121 sp.add_argument(
122 "--extra-packages-script",
123 help=(
124 "Script to execute to include extra packages in " "py2exe binary."
125 ),
126 )
127 sp.add_argument(
128 "--extra-wxs", help="CSV of path_to_wxs_file=working_dir_for_wxs_file"
129 )
130 sp.add_argument(
131 "--extra-features",
132 help=(
133 "CSV of extra feature names to include "
134 "in the installer from the extra wxs files"
135 ),
136 )
137 sp.set_defaults(func=build_wix)
138
139 return parser
140
141
142 def main():
143 parser = get_parser()
144 args = parser.parse_args()
145
146 if not hasattr(args, "func"):
147 parser.print_help()
148 return
149
150 kwargs = dict(vars(args))
151 del kwargs["func"]
152
153 args.func(**kwargs)
@@ -0,0 +1,74 b''
1 #!/usr/bin/env python3
2 #
3 # packaging.py - Mercurial packaging functionality
4 #
5 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
6 #
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
9
10 import os
11 import pathlib
12 import subprocess
13 import sys
14 import venv
15
16
17 HERE = pathlib.Path(os.path.abspath(__file__)).parent
18 REQUIREMENTS_TXT = HERE / "requirements.txt"
19 SOURCE_DIR = HERE.parent.parent
20 VENV = SOURCE_DIR / "build" / "venv-packaging"
21
22
23 def bootstrap():
24 venv_created = not VENV.exists()
25
26 VENV.parent.mkdir(exist_ok=True)
27
28 venv.create(VENV, with_pip=True)
29
30 if os.name == "nt":
31 venv_bin = VENV / "Scripts"
32 pip = venv_bin / "pip.exe"
33 python = venv_bin / "python.exe"
34 else:
35 venv_bin = VENV / "bin"
36 pip = venv_bin / "pip"
37 python = venv_bin / "python"
38
39 args = [
40 str(pip),
41 "install",
42 "-r",
43 str(REQUIREMENTS_TXT),
44 "--disable-pip-version-check",
45 ]
46
47 if not venv_created:
48 args.append("-q")
49
50 subprocess.run(args, check=True)
51
52 os.environ["HGPACKAGING_BOOTSTRAPPED"] = "1"
53 os.environ["PATH"] = "%s%s%s" % (venv_bin, os.pathsep, os.environ["PATH"])
54
55 subprocess.run([str(python), __file__] + sys.argv[1:], check=True)
56
57
58 def run():
59 import hgpackaging.cli as cli
60
61 # Need to strip off main Python executable.
62 cli.main()
63
64
65 if __name__ == "__main__":
66 try:
67 if "HGPACKAGING_BOOTSTRAPPED" not in os.environ:
68 bootstrap()
69 else:
70 run()
71 except subprocess.CalledProcessError as e:
72 sys.exit(e.returncode)
73 except KeyboardInterrupt:
74 sys.exit(1)
@@ -0,0 +1,39 b''
1 #
2 # This file is autogenerated by pip-compile
3 # To update, run:
4 #
5 # pip-compile --generate-hashes --output-file=contrib/packaging/requirements.txt contrib/packaging/requirements.txt.in
6 #
7 jinja2==2.10.3 \
8 --hash=sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f \
9 --hash=sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de
10 markupsafe==1.1.1 \
11 --hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \
12 --hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \
13 --hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \
14 --hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \
15 --hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \
16 --hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b \
17 --hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \
18 --hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \
19 --hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \
20 --hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \
21 --hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \
22 --hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \
23 --hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \
24 --hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \
25 --hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \
26 --hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \
27 --hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \
28 --hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \
29 --hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \
30 --hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \
31 --hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \
32 --hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \
33 --hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \
34 --hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \
35 --hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \
36 --hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \
37 --hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \
38 --hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \
39 # via jinja2
@@ -0,0 +1,1 b''
1 jinja2
@@ -71,7 +71,7 b' Write-Output "updated Mercurial working '
71 BUILD_INNO = r'''
71 BUILD_INNO = r'''
72 Set-Location C:\hgdev\src
72 Set-Location C:\hgdev\src
73 $python = "C:\hgdev\python27-{arch}\python.exe"
73 $python = "C:\hgdev\python27-{arch}\python.exe"
74 C:\hgdev\python37-x64\python.exe contrib\packaging\inno\build.py --python $python
74 C:\hgdev\python37-x64\python.exe contrib\packaging\packaging.py inno --python $python
75 if ($LASTEXITCODE -ne 0) {{
75 if ($LASTEXITCODE -ne 0) {{
76 throw "process exited non-0: $LASTEXITCODE"
76 throw "process exited non-0: $LASTEXITCODE"
77 }}
77 }}
@@ -88,7 +88,7 b' if ($LASTEXITCODE -ne 0) {{'
88 BUILD_WIX = r'''
88 BUILD_WIX = r'''
89 Set-Location C:\hgdev\src
89 Set-Location C:\hgdev\src
90 $python = "C:\hgdev\python27-{arch}\python.exe"
90 $python = "C:\hgdev\python27-{arch}\python.exe"
91 C:\hgdev\python37-x64\python.exe contrib\packaging\wix\build.py --python $python {extra_args}
91 C:\hgdev\python37-x64\python.exe contrib\packaging\packaging.py wix --python $python {extra_args}
92 if ($LASTEXITCODE -ne 0) {{
92 if ($LASTEXITCODE -ne 0) {{
93 throw "process exited non-0: $LASTEXITCODE"
93 throw "process exited non-0: $LASTEXITCODE"
94 }}
94 }}
@@ -11,12 +11,12 b' The following system dependencies must b'
11 * Inno Setup (http://jrsoftware.org/isdl.php) version 5.4 or newer.
11 * Inno Setup (http://jrsoftware.org/isdl.php) version 5.4 or newer.
12 Be sure to install the optional Inno Setup Preprocessor feature,
12 Be sure to install the optional Inno Setup Preprocessor feature,
13 which is required.
13 which is required.
14 * Python 3.5+ (to run the ``build.py`` script)
14 * Python 3.5+ (to run the ``packaging.py`` script)
15
15
16 Building
16 Building
17 ========
17 ========
18
18
19 The ``build.py`` script automates the process of producing an
19 The ``packaging.py`` script automates the process of producing an
20 Inno installer. It manages fetching and configuring the
20 Inno installer. It manages fetching and configuring the
21 non-system dependencies (such as py2exe, gettext, and various
21 non-system dependencies (such as py2exe, gettext, and various
22 Python packages).
22 Python packages).
@@ -31,11 +31,11 b' either ``Visual C++ 2008 32-bit Command '
31 From the prompt, change to the Mercurial source directory. e.g.
31 From the prompt, change to the Mercurial source directory. e.g.
32 ``cd c:\src\hg``.
32 ``cd c:\src\hg``.
33
33
34 Next, invoke ``build.py`` to produce an Inno installer. You will
34 Next, invoke ``packaging.py`` to produce an Inno installer. You will
35 need to supply the path to the Python interpreter to use.::
35 need to supply the path to the Python interpreter to use.::
36
36
37 $ python3.exe contrib\packaging\inno\build.py \
37 $ python3.exe contrib\packaging\packaging.py \
38 --python c:\python27\python.exe
38 inno --python c:\python27\python.exe
39
39
40 .. note::
40 .. note::
41
41
@@ -49,13 +49,13 b' configured into the ``build`` sub-direct'
49 and an installer placed in the ``dist`` sub-directory. The final
49 and an installer placed in the ``dist`` sub-directory. The final
50 line of output should print the name of the generated installer.
50 line of output should print the name of the generated installer.
51
51
52 Additional options may be configured. Run ``build.py --help`` to
52 Additional options may be configured. Run
53 see a list of program flags.
53 ``packaging.py inno --help`` to see a list of program flags.
54
54
55 MinGW
55 MinGW
56 =====
56 =====
57
57
58 It is theoretically possible to generate an installer that uses
58 It is theoretically possible to generate an installer that uses
59 MinGW. This isn't well tested and ``build.py`` and may properly
59 MinGW. This isn't well tested and ``packaging.py`` and may properly
60 support it. See old versions of this file in version control for
60 support it. See old versions of this file in version control for
61 potentially useful hints as to how to achieve this.
61 potentially useful hints as to how to achieve this.
@@ -18,12 +18,12 b' dependencies must be installed:'
18 * Python 2.7 (download from https://www.python.org/downloads/)
18 * Python 2.7 (download from https://www.python.org/downloads/)
19 * Microsoft Visual C++ Compiler for Python 2.7
19 * Microsoft Visual C++ Compiler for Python 2.7
20 (https://www.microsoft.com/en-us/download/details.aspx?id=44266)
20 (https://www.microsoft.com/en-us/download/details.aspx?id=44266)
21 * Python 3.5+ (to run the ``build.py`` script)
21 * Python 3.5+ (to run the ``packaging.py`` script)
22
22
23 Building
23 Building
24 ========
24 ========
25
25
26 The ``build.py`` script automates the process of producing an MSI
26 The ``packaging.py`` script automates the process of producing an MSI
27 installer. It manages fetching and configuring non-system dependencies
27 installer. It manages fetching and configuring non-system dependencies
28 (such as py2exe, gettext, and various Python packages).
28 (such as py2exe, gettext, and various Python packages).
29
29
@@ -37,11 +37,11 b' launch either ``Visual C++ 2008 32-bit C'
37 From the prompt, change to the Mercurial source directory. e.g.
37 From the prompt, change to the Mercurial source directory. e.g.
38 ``cd c:\src\hg``.
38 ``cd c:\src\hg``.
39
39
40 Next, invoke ``build.py`` to produce an MSI installer. You will need
40 Next, invoke ``packaging.py`` to produce an MSI installer. You will need
41 to supply the path to the Python interpreter to use.::
41 to supply the path to the Python interpreter to use.::
42
42
43 $ python3 contrib\packaging\wix\build.py \
43 $ python3 contrib\packaging\packaging.py \
44 --python c:\python27\python.exe
44 wix --python c:\python27\python.exe
45
45
46 .. note::
46 .. note::
47
47
@@ -54,8 +54,8 b' configured into the ``build`` sub-direct'
54 and an installer placed in the ``dist`` sub-directory. The final line
54 and an installer placed in the ``dist`` sub-directory. The final line
55 of output should print the name of the generated installer.
55 of output should print the name of the generated installer.
56
56
57 Additional options may be configured. Run ``build.py --help`` to see
57 Additional options may be configured. Run ``packaging.py wix --help`` to
58 a list of program flags.
58 see a list of program flags.
59
59
60 Relationship to TortoiseHG
60 Relationship to TortoiseHG
61 ==========================
61 ==========================
@@ -21,13 +21,12 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/packaging/hgpackaging/cli.py it has no-che?k-code (glob)
24 Skipping contrib/packaging/hgpackaging/downloads.py it has no-che?k-code (glob)
25 Skipping contrib/packaging/hgpackaging/downloads.py it has no-che?k-code (glob)
25 Skipping contrib/packaging/hgpackaging/inno.py it has no-che?k-code (glob)
26 Skipping contrib/packaging/hgpackaging/inno.py it has no-che?k-code (glob)
26 Skipping contrib/packaging/hgpackaging/py2exe.py it has no-che?k-code (glob)
27 Skipping contrib/packaging/hgpackaging/py2exe.py it has no-che?k-code (glob)
27 Skipping contrib/packaging/hgpackaging/util.py it has no-che?k-code (glob)
28 Skipping contrib/packaging/hgpackaging/util.py it has no-che?k-code (glob)
28 Skipping contrib/packaging/hgpackaging/wix.py it has no-che?k-code (glob)
29 Skipping contrib/packaging/hgpackaging/wix.py it has no-che?k-code (glob)
29 Skipping contrib/packaging/inno/build.py it has no-che?k-code (glob)
30 Skipping contrib/packaging/wix/build.py it has no-che?k-code (glob)
31 Skipping i18n/polib.py it has no-che?k-code (glob)
30 Skipping i18n/polib.py it has no-che?k-code (glob)
32 Skipping mercurial/statprof.py it has no-che?k-code (glob)
31 Skipping mercurial/statprof.py it has no-che?k-code (glob)
33 Skipping tests/badserverext.py it has no-che?k-code (glob)
32 Skipping tests/badserverext.py it has no-che?k-code (glob)
@@ -8,6 +8,7 b''
8 > -X contrib/automation/ \
8 > -X contrib/automation/ \
9 > -X contrib/packaging/hgpackaging/ \
9 > -X contrib/packaging/hgpackaging/ \
10 > -X contrib/packaging/inno/ \
10 > -X contrib/packaging/inno/ \
11 > -X contrib/packaging/packaging.py \
11 > -X contrib/packaging/wix/ \
12 > -X contrib/packaging/wix/ \
12 > -X hgdemandimport/demandimportpy2.py \
13 > -X hgdemandimport/demandimportpy2.py \
13 > -X mercurial/thirdparty/cbor \
14 > -X mercurial/thirdparty/cbor \
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