rust/hgcli/pyoxidizer.bzl
changeset 47216 603efb3845ba
parent 47215 3380848c6e04
child 47217 c8001d9c26f5
--- a/rust/hgcli/pyoxidizer.bzl	Thu May 06 16:16:21 2021 -0700
+++ b/rust/hgcli/pyoxidizer.bzl	Thu May 06 16:03:43 2021 -0700
@@ -1,5 +1,20 @@
+# The following variables can be passed in as parameters:
+#
+# VERSION
+#   Version string of program being produced.
+#
+# MSI_NAME
+#   Root name of MSI installer.
+#
+# EXTRA_MSI_FEATURES
+#   ; delimited string of extra features to advertise in the built MSA.
+
 ROOT = CWD + "/../.."
 
+VERSION = VARS.get("VERSION", "5.8")
+MSI_NAME = VARS.get("MSI_NAME", "mercurial")
+EXTRA_MSI_FEATURES = VARS.get("EXTRA_MSI_FEATURES")
+
 IS_WINDOWS = "windows" in BUILD_TARGET_TRIPLE
 
 # Code to run in Python interpreter.
@@ -80,8 +95,144 @@
 
     return m
 
+
+# This adjusts the InstallManifest produced from exe generation to provide
+# additional files found in a Windows install layout.
+def make_windows_install_layout(manifest):
+    # Copy various files to new install locations. This can go away once
+    # we're using the importlib resource reader.
+    RECURSIVE_COPIES = {
+        "lib/mercurial/locale/": "locale/",
+        "lib/mercurial/templates/": "templates/",
+    }
+    for (search, replace) in RECURSIVE_COPIES.items():
+        for path in manifest.paths():
+            if path.startswith(search):
+                new_path = path.replace(search, replace)
+                print("copy %s to %s" % (path, new_path))
+                file = manifest.get_file(path)
+                manifest.add_file(file, path = new_path)
+
+    # Similar to above, but with filename pattern matching.
+    # lib/mercurial/helptext/**/*.txt -> helptext/
+    # lib/mercurial/defaultrc/*.rc -> defaultrc/
+    for path in manifest.paths():
+        if path.startswith("lib/mercurial/helptext/") and path.endswith(".txt"):
+            new_path = path[len("lib/mercurial/"):]
+        elif path.startswith("lib/mercurial/defaultrc/") and path.endswith(".rc"):
+            new_path = path[len("lib/mercurial/"):]
+        else:
+            continue
+
+        print("copying %s to %s" % (path, new_path))
+        manifest.add_file(manifest.get_file(path), path = new_path)
+
+    # We also install a handful of additional files.
+    EXTRA_CONTRIB_FILES = [
+        "bash_completion",
+        "hgweb.fcgi",
+        "hgweb.wsgi",
+        "logo-droplets.svg",
+        "mercurial.el",
+        "mq.el",
+        "tcsh_completion",
+        "tcsh_completion_build.sh",
+        "xml.rnc",
+        "zsh_completion",
+    ]
+
+    for f in EXTRA_CONTRIB_FILES:
+        manifest.add_file(FileContent(path = ROOT + "/contrib/" + f), directory = "contrib")
+
+    # Individual files with full source to destination path mapping.
+    EXTRA_FILES = {
+        "contrib/hgk": "contrib/hgk.tcl",
+        "contrib/win32/postinstall.txt": "ReleaseNotes.txt",
+        "contrib/win32/ReadMe.html": "ReadMe.html",
+        "doc/style.css": "doc/style.css",
+        "COPYING": "Copying.txt",
+    }
+
+    for source, dest in EXTRA_FILES.items():
+        print("adding extra file %s" % dest)
+        manifest.add_file(FileContent(path = ROOT + "/" + source), path = dest)
+
+    # And finally some wildcard matches.
+    manifest.add_manifest(glob(
+        include = [ROOT + "/contrib/vim/*"],
+        strip_prefix = ROOT + "/"
+    ))
+    manifest.add_manifest(glob(
+        include = [ROOT + "/doc/*.html"],
+        strip_prefix = ROOT + "/"
+    ))
+
+    # But we don't ship hg-ssh on Windows, so exclude its documentation.
+    manifest.remove("doc/hg-ssh.8.html")
+
+    return manifest
+
+
+def make_msi(manifest):
+    manifest = make_windows_install_layout(manifest)
+
+    if "x86_64" in BUILD_TARGET_TRIPLE:
+        platform = "x64"
+    else:
+        platform = "x86"
+
+    manifest.add_file(
+        FileContent(path = ROOT + "/contrib/packaging/wix/COPYING.rtf"),
+        path = "COPYING.rtf",
+    )
+    manifest.remove("Copying.txt")
+    manifest.add_file(
+        FileContent(path = ROOT + "/contrib/win32/mercurial.ini"),
+        path = "defaultrc/mercurial.rc",
+    )
+    manifest.add_file(
+        FileContent(filename = "editor.rc", content = "[ui]\neditor = notepad\n"),
+        path = "defaultrc/editor.rc",
+    )
+
+    wix = WiXInstaller("hg", "%s-%s.msi" % (MSI_NAME, VERSION))
+
+    # Materialize files in the manifest to the install layout.
+    wix.add_install_files(manifest)
+
+    # From mercurial.wxs.
+    wix.install_files_root_directory_id = "INSTALLDIR"
+
+    # Pull in our custom .wxs files.
+    defines = {
+        "PyOxidizer": "1",
+        "Platform": platform,
+        "Version": VERSION,
+        "Comments": "Installs Mercurial version %s" % VERSION,
+        "PythonVersion": "3",
+        "MercurialHasLib": "1",
+    }
+
+    if EXTRA_MSI_FEATURES:
+        defines["MercurialExtraFeatures"] = EXTRA_MSI_FEATURES
+
+    wix.add_wxs_file(
+        ROOT + "/contrib/packaging/wix/mercurial.wxs",
+        preprocessor_parameters=defines,
+    )
+
+    # Our .wxs references to other files. Pull those into the build environment.
+    for f in ("defines.wxi", "guids.wxi", "COPYING.rtf"):
+        wix.add_build_file(f, ROOT + "/contrib/packaging/wix/" + f)
+
+    wix.add_build_file("mercurial.ico", ROOT + "/contrib/win32/mercurial.ico")
+
+    return wix
+
+
 register_target("distribution", make_distribution)
 register_target("exe", make_exe, depends = ["distribution"])
 register_target("app", make_manifest, depends = ["distribution", "exe"], default = True)
+register_target("msi", make_msi, depends = ["app"])
 
 resolve_targets()