Show More
@@ -11,6 +11,8 b' import os' | |||||
11 | import pathlib |
|
11 | import pathlib | |
12 | import re |
|
12 | import re | |
13 | import subprocess |
|
13 | import subprocess | |
|
14 | import tempfile | |||
|
15 | import xml.dom.minidom | |||
14 |
|
16 | |||
15 | from .downloads import ( |
|
17 | from .downloads import ( | |
16 | download_entry, |
|
18 | download_entry, | |
@@ -128,6 +130,52 b' def make_post_build_signing_fn(name, sub' | |||||
128 | return post_build_sign |
|
130 | return post_build_sign | |
129 |
|
131 | |||
130 |
|
132 | |||
|
133 | LIBRARIES_XML = ''' | |||
|
134 | <?xml version="1.0" encoding="utf-8"?> | |||
|
135 | <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> | |||
|
136 | ||||
|
137 | <?include {wix_dir}/guids.wxi ?> | |||
|
138 | <?include {wix_dir}/defines.wxi ?> | |||
|
139 | ||||
|
140 | <Fragment> | |||
|
141 | <DirectoryRef Id="INSTALLDIR" FileSource="$(var.SourceDir)"> | |||
|
142 | <Directory Id="libdir" Name="lib" FileSource="$(var.SourceDir)/lib"> | |||
|
143 | <Component Id="libOutput" Guid="$(var.lib.guid)" Win64='$(var.IsX64)'> | |||
|
144 | </Component> | |||
|
145 | </Directory> | |||
|
146 | </DirectoryRef> | |||
|
147 | </Fragment> | |||
|
148 | </Wix> | |||
|
149 | '''.lstrip() | |||
|
150 | ||||
|
151 | ||||
|
152 | def make_libraries_xml(wix_dir: pathlib.Path, dist_dir: pathlib.Path): | |||
|
153 | """Make XML data for library components WXS.""" | |||
|
154 | # We can't use ElementTree because it doesn't handle the | |||
|
155 | # <?include ?> directives. | |||
|
156 | doc = xml.dom.minidom.parseString( | |||
|
157 | LIBRARIES_XML.format(wix_dir=str(wix_dir))) | |||
|
158 | ||||
|
159 | component = doc.getElementsByTagName('Component')[0] | |||
|
160 | ||||
|
161 | f = doc.createElement('File') | |||
|
162 | f.setAttribute('Name', 'library.zip') | |||
|
163 | f.setAttribute('KeyPath', 'yes') | |||
|
164 | component.appendChild(f) | |||
|
165 | ||||
|
166 | lib_dir = dist_dir / 'lib' | |||
|
167 | ||||
|
168 | for p in sorted(lib_dir.iterdir()): | |||
|
169 | if not p.name.endswith(('.dll', '.pyd')): | |||
|
170 | continue | |||
|
171 | ||||
|
172 | f = doc.createElement('File') | |||
|
173 | f.setAttribute('Name', p.name) | |||
|
174 | component.appendChild(f) | |||
|
175 | ||||
|
176 | return doc.toprettyxml() | |||
|
177 | ||||
|
178 | ||||
131 | def build_installer(source_dir: pathlib.Path, python_exe: pathlib.Path, |
|
179 | def build_installer(source_dir: pathlib.Path, python_exe: pathlib.Path, | |
132 | msi_name='mercurial', version=None, post_build_fn=None): |
|
180 | msi_name='mercurial', version=None, post_build_fn=None): | |
133 | """Build a WiX MSI installer. |
|
181 | """Build a WiX MSI installer. | |
@@ -181,6 +229,17 b' def build_installer(source_dir: pathlib.' | |||||
181 | wxs_source_dir = source_dir / rel_path |
|
229 | wxs_source_dir = source_dir / rel_path | |
182 | run_candle(wix_path, build_dir, wxs, wxs_source_dir, defines=defines) |
|
230 | run_candle(wix_path, build_dir, wxs, wxs_source_dir, defines=defines) | |
183 |
|
231 | |||
|
232 | # candle.exe doesn't like when we have an open handle on the file. | |||
|
233 | # So use TemporaryDirectory() instead of NamedTemporaryFile(). | |||
|
234 | with tempfile.TemporaryDirectory() as td: | |||
|
235 | td = pathlib.Path(td) | |||
|
236 | ||||
|
237 | tf = td / 'library.wxs' | |||
|
238 | with tf.open('w') as fh: | |||
|
239 | fh.write(make_libraries_xml(wix_dir, dist_dir)) | |||
|
240 | ||||
|
241 | run_candle(wix_path, build_dir, tf, dist_dir, defines=defines) | |||
|
242 | ||||
184 | source = wix_dir / 'mercurial.wxs' |
|
243 | source = wix_dir / 'mercurial.wxs' | |
185 | defines['Version'] = version |
|
244 | defines['Version'] = version | |
186 | defines['Comments'] = 'Installs Mercurial version %s' % version |
|
245 | defines['Comments'] = 'Installs Mercurial version %s' % version | |
@@ -204,7 +263,10 b' def build_installer(source_dir: pathlib.' | |||||
204 | assert source.endswith('.wxs') |
|
263 | assert source.endswith('.wxs') | |
205 | args.append(str(build_dir / ('%s.wixobj' % source[:-4]))) |
|
264 | args.append(str(build_dir / ('%s.wixobj' % source[:-4]))) | |
206 |
|
265 | |||
207 | args.append(str(build_dir / 'mercurial.wixobj')) |
|
266 | args.extend([ | |
|
267 | str(build_dir / 'library.wixobj'), | |||
|
268 | str(build_dir / 'mercurial.wixobj'), | |||
|
269 | ]) | |||
208 |
|
270 | |||
209 | subprocess.run(args, cwd=str(source_dir), check=True) |
|
271 | subprocess.run(args, cwd=str(source_dir), check=True) | |
210 |
|
272 |
@@ -9,35 +9,6 b'' | |||||
9 | <Component Id="distOutput" Guid="$(var.dist.guid)" Win64='$(var.IsX64)'> |
|
9 | <Component Id="distOutput" Guid="$(var.dist.guid)" Win64='$(var.IsX64)'> | |
10 | <File Name="python27.dll" KeyPath="yes" /> |
|
10 | <File Name="python27.dll" KeyPath="yes" /> | |
11 | </Component> |
|
11 | </Component> | |
12 | <Directory Id="libdir" Name="lib" FileSource="$(var.SourceDir)/lib"> |
|
|||
13 | <Component Id="libOutput" Guid="$(var.lib.guid)" Win64='$(var.IsX64)'> |
|
|||
14 | <File Name="library.zip" KeyPath="yes" /> |
|
|||
15 | <File Name="mercurial.cext.base85.pyd" /> |
|
|||
16 | <File Name="mercurial.cext.bdiff.pyd" /> |
|
|||
17 | <File Name="mercurial.cext.mpatch.pyd" /> |
|
|||
18 | <File Name="mercurial.cext.osutil.pyd" /> |
|
|||
19 | <File Name="mercurial.cext.parsers.pyd" /> |
|
|||
20 | <File Name="mercurial.thirdparty.zope.interface._zope_interface_coptimizations.pyd" /> |
|
|||
21 | <File Name="mercurial.zstd.pyd" /> |
|
|||
22 | <File Name="hgext.fsmonitor.pywatchman.bser.pyd" /> |
|
|||
23 | <File Name="pyexpat.pyd" /> |
|
|||
24 | <File Name="bz2.pyd" /> |
|
|||
25 | <File Name="select.pyd" /> |
|
|||
26 | <File Name="sqlite3.dll" /> |
|
|||
27 | <File Name="tcl85.dll" /> |
|
|||
28 | <File Name="tk85.dll" /> |
|
|||
29 | <File Name="unicodedata.pyd" /> |
|
|||
30 | <File Name="_ctypes.pyd" /> |
|
|||
31 | <File Name="_elementtree.pyd" /> |
|
|||
32 | <File Name="_testcapi.pyd" /> |
|
|||
33 | <File Name="_hashlib.pyd" /> |
|
|||
34 | <File Name="_multiprocessing.pyd" /> |
|
|||
35 | <File Name="_socket.pyd" /> |
|
|||
36 | <File Name="_sqlite3.pyd" /> |
|
|||
37 | <File Name="_ssl.pyd" /> |
|
|||
38 | <File Name="_tkinter.pyd" /> |
|
|||
39 | </Component> |
|
|||
40 | </Directory> |
|
|||
41 | </DirectoryRef> |
|
12 | </DirectoryRef> | |
42 | </Fragment> |
|
13 | </Fragment> | |
43 |
|
14 |
General Comments 0
You need to be logged in to leave comments.
Login now