Patchwork D6139: wix: autogenerate wxs file for library files

login
register
mail settings
Submitter phabricator
Date March 16, 2019, 3:12 a.m.
Message ID <46cf311162da6bae7edb5714d35d6bd3@localhost.localdomain>
Download mbox | patch
Permalink /patch/39280/
State Not Applicable
Headers show

Comments

phabricator - March 16, 2019, 3:12 a.m.
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG131d0b7c3940: wix: autogenerate wxs file for library files (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6139?vs=14502&id=14518

REVISION DETAIL
  https://phab.mercurial-scm.org/D6139

AFFECTED FILES
  contrib/packaging/hgpackaging/wix.py
  contrib/packaging/wix/dist.wxs

CHANGE DETAILS




To: indygreg, #hg-reviewers
Cc: mjpieters, mercurial-devel

Patch

diff --git a/contrib/packaging/wix/dist.wxs b/contrib/packaging/wix/dist.wxs
--- a/contrib/packaging/wix/dist.wxs
+++ b/contrib/packaging/wix/dist.wxs
@@ -9,35 +9,6 @@ 
       <Component Id="distOutput" Guid="$(var.dist.guid)" Win64='$(var.IsX64)'>
         <File Name="python27.dll" KeyPath="yes" />
       </Component>
-      <Directory Id="libdir" Name="lib" FileSource="$(var.SourceDir)/lib">
-        <Component Id="libOutput" Guid="$(var.lib.guid)" Win64='$(var.IsX64)'>
-          <File Name="library.zip" KeyPath="yes" />
-          <File Name="mercurial.cext.base85.pyd" />
-          <File Name="mercurial.cext.bdiff.pyd" />
-          <File Name="mercurial.cext.mpatch.pyd" />
-          <File Name="mercurial.cext.osutil.pyd" />
-          <File Name="mercurial.cext.parsers.pyd" />
-          <File Name="mercurial.thirdparty.zope.interface._zope_interface_coptimizations.pyd" />
-          <File Name="mercurial.zstd.pyd" />
-          <File Name="hgext.fsmonitor.pywatchman.bser.pyd" />
-          <File Name="pyexpat.pyd" />
-          <File Name="bz2.pyd" />
-          <File Name="select.pyd" />
-          <File Name="sqlite3.dll" />
-          <File Name="tcl85.dll" />
-          <File Name="tk85.dll" />
-          <File Name="unicodedata.pyd" />
-          <File Name="_ctypes.pyd" />
-          <File Name="_elementtree.pyd" />
-          <File Name="_testcapi.pyd" />
-          <File Name="_hashlib.pyd" />
-          <File Name="_multiprocessing.pyd" />
-          <File Name="_socket.pyd" />
-          <File Name="_sqlite3.pyd" />
-          <File Name="_ssl.pyd" />
-          <File Name="_tkinter.pyd" />
-        </Component>
-      </Directory>
     </DirectoryRef>
   </Fragment>
 
diff --git a/contrib/packaging/hgpackaging/wix.py b/contrib/packaging/hgpackaging/wix.py
--- a/contrib/packaging/hgpackaging/wix.py
+++ b/contrib/packaging/hgpackaging/wix.py
@@ -11,6 +11,8 @@ 
 import pathlib
 import re
 import subprocess
+import tempfile
+import xml.dom.minidom
 
 from .downloads import (
     download_entry,
@@ -128,6 +130,52 @@ 
     return post_build_sign
 
 
+LIBRARIES_XML = '''
+<?xml version="1.0" encoding="utf-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
+
+  <?include {wix_dir}/guids.wxi ?>
+  <?include {wix_dir}/defines.wxi ?>
+
+  <Fragment>
+    <DirectoryRef Id="INSTALLDIR" FileSource="$(var.SourceDir)">
+      <Directory Id="libdir" Name="lib" FileSource="$(var.SourceDir)/lib">
+        <Component Id="libOutput" Guid="$(var.lib.guid)" Win64='$(var.IsX64)'>
+        </Component>
+      </Directory>
+    </DirectoryRef>
+  </Fragment>
+</Wix>
+'''.lstrip()
+
+
+def make_libraries_xml(wix_dir: pathlib.Path, dist_dir: pathlib.Path):
+    """Make XML data for library components WXS."""
+    # We can't use ElementTree because it doesn't handle the
+    # <?include ?> directives.
+    doc = xml.dom.minidom.parseString(
+        LIBRARIES_XML.format(wix_dir=str(wix_dir)))
+
+    component = doc.getElementsByTagName('Component')[0]
+
+    f = doc.createElement('File')
+    f.setAttribute('Name', 'library.zip')
+    f.setAttribute('KeyPath', 'yes')
+    component.appendChild(f)
+
+    lib_dir = dist_dir / 'lib'
+
+    for p in sorted(lib_dir.iterdir()):
+        if not p.name.endswith(('.dll', '.pyd')):
+            continue
+
+        f = doc.createElement('File')
+        f.setAttribute('Name', p.name)
+        component.appendChild(f)
+
+    return doc.toprettyxml()
+
+
 def build_installer(source_dir: pathlib.Path, python_exe: pathlib.Path,
                     msi_name='mercurial', version=None, post_build_fn=None):
     """Build a WiX MSI installer.
@@ -181,6 +229,17 @@ 
         wxs_source_dir = source_dir / rel_path
         run_candle(wix_path, build_dir, wxs, wxs_source_dir, defines=defines)
 
+    # candle.exe doesn't like when we have an open handle on the file.
+    # So use TemporaryDirectory() instead of NamedTemporaryFile().
+    with tempfile.TemporaryDirectory() as td:
+        td = pathlib.Path(td)
+
+        tf = td / 'library.wxs'
+        with tf.open('w') as fh:
+            fh.write(make_libraries_xml(wix_dir, dist_dir))
+
+        run_candle(wix_path, build_dir, tf, dist_dir, defines=defines)
+
     source = wix_dir / 'mercurial.wxs'
     defines['Version'] = version
     defines['Comments'] = 'Installs Mercurial version %s' % version
@@ -204,7 +263,10 @@ 
         assert source.endswith('.wxs')
         args.append(str(build_dir / ('%s.wixobj' % source[:-4])))
 
-    args.append(str(build_dir / 'mercurial.wixobj'))
+    args.extend([
+        str(build_dir / 'library.wixobj'),
+        str(build_dir / 'mercurial.wixobj'),
+    ])
 
     subprocess.run(args, cwd=str(source_dir), check=True)