Bug 1485228 - Add support for repackage msi r=mhowell

Differential Revision: https://phabricator.services.mozilla.com/D9331

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kim Moir 2018-11-07 17:45:46 +00:00
Родитель 6ab329c54f
Коммит db3477911d
3 изменённых файлов: 230 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<!-- The version field only supports MSI version numbers, which cannot include
letters, and therefore cannot represent our version numbers. Set it to all
zeros to show it isn't valid, and add the real version to the Name. -->
<Product Name="$(var.BrandFullName) $(var.Version) $(var.Architecture) $(var.AB_CD)"
Manufacturer="$(var.Vendor)" Language="0" Codepage="1252"
Version="0.0.0.0" Id="1294a4c5-9977-480f-9497-c0ea1e630130"
UpgradeCode="3118ab4c-b433-4fbb-b9fa-8f9ca4b5c103" >
<Package Id="*" InstallerVersion="200" Compressed="yes"
Platform="$(var.Architecture)" />
<!-- We need a CAB to avoid failing an ICE, even though we have no payload. -->
<Media Id="1" Cabinet="setup.cab" EmbedCab="yes" />
<!-- We need a component and feature, or msiexec will refuse to load us. -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="TempFolder">
<Component Id="EmptyComponent" Guid="55a76b76-7496-4b47-a7a6-c5fbdd5e51a4">
<CreateFolder />
</Component>
</Directory>
</Directory>
<!-- Setting the feature to level 0 marks it hidden, so it can't be installed.
That prevents getting this MSI registered as an installed product,
because it has no features of its own to install. -->
<Feature Id="EmptyFeature" Level="0">
<ComponentRef Id="EmptyComponent" />
</Feature>
<!-- Embed the installer we want to run directly into the MSI database. -->
<Binary Id="WrappedExe" SourceFile="$(var.ExeSourcePath)" />
<!-- User-configurable properties. One of these corresponds to each documented
command-line parameter. Properties cannot be present without a value,
so use a conspicuous and difficult to mistake string for the parameters
that have no real default values. -->
<Property Id="INSTALL_DIRECTORY_PATH" Value="__DEFAULT__" />
<Property Id="INSTALL_DIRECTORY_NAME" Value="__DEFAULT__" />
<Property Id="TASKBAR_SHORTCUT" Value="true" />
<Property Id="DESKTOP_SHORTCUT" Value="true" />
<Property Id="START_MENU_SHORTCUT" Value="true" />
<Property Id="INSTALL_MAINTENANCE_SERVICE" Value="true" />
<Property Id="REMOVE_DISTRIBUTION_DIR" Value="true" />
<Property Id="PREVENT_REBOOT_REQUIRED" Value="false" />
<Property Id="OPTIONAL_EXTENSIONS" Value="true" />
<Property Id="EXTRACT_DIR" Value="__DEFAULT__" />
<!-- Always include all of the boolean options on the command line, so we don't
have to conditionally decide when to include each one of them. For the
directory settings though, we can't put them on the command line with the
default values those properties have, so we need a separate action for
each possible configuration of those settings, and conditions to select
the right action to use based on which properties are configured.
WiX throws warning LGHT1076 complaining that these command strings are
too long, but they actually work just fine, the warning is spurious. -->
<CustomAction Id="RunInstallNoDir" Return="check" Execute="deferred"
HideTarget="no" Impersonate="no" BinaryKey="WrappedExe"
ExeCommand="/S /TaskbarShortcut=[TASKBAR_SHORTCUT] /DesktopShortcut=[DESKTOP_SHORTCUT] /StartMenuShortcut=[START_MENU_SHORTCUT] /MaintenanceService=[INSTALL_MAINTENANCE_SERVICE] /RemoveDistributionDir=[REMOTE_DISTRIBUTION_DIR] /PreventRebootRequired=[PREVENT_REBOOT_REQUIRED] /OptionalExtensions=[OPTIONAL_EXTENSIONS] /LaunchedFromMSI" />
<CustomAction Id="RunInstallDirPath" Return="check" Execute="deferred"
HideTarget="no" Impersonate="no" BinaryKey="WrappedExe"
ExeCommand="/S /InstallDirectoryPath=[INSTALL_DIRECTORY_PATH] /TaskbarShortcut=[TASKBAR_SHORTCUT] /DesktopShortcut=[DESKTOP_SHORTCUT] /StartMenuShortcut=[START_MENU_SHORTCUT] /MaintenanceService=[INSTALL_MAINTENANCE_SERVICE] /RemoveDistributionDir=[REMOTE_DISTRIBUTION_DIR] /PreventRebootRequired=[PREVENT_REBOOT_REQUIRED] /OptionalExtensions=[OPTIONAL_EXTENSIONS] /LaunchedFromMSI" />
<CustomAction Id="RunInstallDirName" Return="check" Execute="deferred"
HideTarget="no" Impersonate="no" BinaryKey="WrappedExe"
ExeCommand="/S /InstallDirectoryName=[INSTALL_DIRECTORY_NAME] /TaskbarShortcut=[TASKBAR_SHORTCUT] /DesktopShortcut=[DESKTOP_SHORTCUT] /StartMenuShortcut=[START_MENU_SHORTCUT] /MaintenanceService=[INSTALL_MAINTENANCE_SERVICE] /RemoveDistributionDir=[REMOTE_DISTRIBUTION_DIR] /PreventRebootRequired=[PREVENT_REBOOT_REQUIRED] /OptionalExtensions=[OPTIONAL_EXTENSIONS] /LaunchedFromMSI" />
<CustomAction Id="RunExtractOnly" Return="check" Execute="deferred"
HideTarget="no" Impersonate="no" BinaryKey="WrappedExe"
ExeCommand="/S /ExtractDir=[EXTRACT_DIR]" />
<!-- When we run the custom actions is kind of arbitrary; this sequencing gets
us the least confusing message showing in the MSI progress dialog while
the installer runs. Our actions don't need to be sequenced relative
to one another because only one will ever run. -->
<InstallExecuteSequence>
<Custom Action="RunInstallNoDir" After="ProcessComponents">
<![CDATA[
(INSTALL_DIRECTORY_PATH = "__DEFAULT__") AND
(INSTALL_DIRECTORY_NAME = "__DEFAULT__") AND
(EXTRACT_DIR = "__DEFAULT__")
]]>
</Custom>
<Custom Action="RunInstallDirPath" After="ProcessComponents">
<![CDATA[
(INSTALL_DIRECTORY_PATH <> "__DEFAULT__") AND
(INSTALL_DIRECTORY_NAME = "__DEFAULT__") AND
(EXTRACT_DIR = "__DEFAULT__")
]]>
</Custom>
<Custom Action="RunInstallDirName" After="ProcessComponents">
<![CDATA[
(INSTALL_DIRECTORY_NAME <> "__DEFAULT__") AND
(EXTRACT_DIR = "__DEFAULT__")
]]>
</Custom>
<Custom Action="RunExtractOnly" After="ProcessComponents">
<![CDATA[
EXTRACT_DIR <> "__DEFAULT__"
]]>
</Custom>
</InstallExecuteSequence>
</Product>
</Wix>

Просмотреть файл

@ -2981,6 +2981,38 @@ class Repackage(MachCommandBase):
sfx_stub=sfx_stub,
)
@SubCommand('repackage', 'msi',
description='Repackage into a MSI')
@CommandArgument('--wsx', type=str, required=True,
help='The wsx file used to build the installer')
@CommandArgument('--version', type=str, required=True,
help='The Firefox version used to create the installer')
@CommandArgument('--locale', type=str, required=True,
help='The locale of the installer')
@CommandArgument('--arch', type=str, required=True,
help='The archtecture you are building x64 or x32')
@CommandArgument('--setupexe', type=str, required=True,
help='setup.exe installer')
@CommandArgument('--candle', type=str, required=False,
help='location of candle binary')
@CommandArgument('--light', type=str, required=False,
help='location of light binary')
@CommandArgument('--output', '-o', type=str, required=True,
help='Output filename')
def repackage_msi(self, wsx, version, locale, arch, setupexe, candle, light, output):
from mozbuild.repackaging.msi import repackage_msi
repackage_msi(
topsrcdir=self.topsrcdir,
wsx=wsx,
version=version,
locale=locale,
arch=arch,
setupexe=setupexe,
candle=candle,
light=light,
output=output,
)
@SubCommand('repackage', 'mar',
description='Repackage into complete MAR file')
@CommandArgument('--input', '-i', type=str, required=True,

Просмотреть файл

@ -0,0 +1,91 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
import os
import tempfile
import shutil
import mozpack.path as mozpath
import sys
import subprocess
from xml.dom import minidom
from mozbuild.util import ensureParentDir
def update_wsx(wfile, pvalues):
parsed = minidom.parse(wfile)
# construct a dictinary for the pre-processing options
# iterate over that list and add them to the wsx xml doc
for k,v in pvalues.items():
entry = parsed.createProcessingInstruction('define', k + ' = "' + v + '"')
root = parsed.firstChild
parsed.insertBefore(entry, root)
# write out xml to new wfile
new_w_file = wfile + ".new"
fh = open(new_w_file, "wb")
parsed.writexml(fh)
fh.close()
shutil.move(new_w_file, wfile)
return wfile
def repackage_msi(topsrcdir, wsx, version, locale, arch, setupexe, candle, light, output):
if sys.platform != 'win32':
raise Exception("repackage msi only works on windows")
if not os.path.isdir(topsrcdir):
raise Exception("%s does not exist." % topsrcdir)
if not os.path.isfile(wsx):
raise Exception("%s does not exist." % wsx)
if version is None:
raise Exception("version name must be provided.")
if locale is None:
raise Exception("locale name must be provided.")
if arch is None or arch not in ['x86','x64']:
raise Exception("arch name must be provided and either x86 or x64.")
if not os.path.isfile(setupexe):
raise Exception("%s does not exist." % setupexe)
if candle is not None and not os.path.isfile(candle):
raise Exception("%s does not exist." % candle)
if light is not None and not os.path.isfile(light):
raise Exception("%s does not exist." % light)
wsx = mozpath.realpath(wsx)
setupexe = mozpath.realpath(setupexe)
output = mozpath.realpath(output)
ensureParentDir(output)
if sys.platform == 'win32':
tmpdir = tempfile.mkdtemp()
old_cwd = os.getcwd()
try:
wsx_file = os.path.split(wsx)[1]
shutil.copy(wsx, tmpdir)
temp_wsx_file = os.path.join(tmpdir, wsx_file)
temp_wsx_file = mozpath.realpath(temp_wsx_file)
pre_values = {'Vendor': 'Mozilla',
'BrandFullName': 'Mozilla Firefox',
'Version': version,
'AB_CD': locale,
'Architecture': arch,
'ExeSourcePath': setupexe}
# update wsx file with inputs from
newfile = update_wsx(temp_wsx_file, pre_values)
wix_object_file = os.path.join(tmpdir, 'installer.wixobj')
env = os.environ.copy()
if candle is None:
candle = 'candle.exe'
cmd = [candle, '-out', wix_object_file, newfile]
subprocess.check_call(cmd, env=env)
wix_installer = wix_object_file.replace(".wixobj", ".msi")
if light is None:
light = 'light.exe'
light_cmd = [light, "-cultures:neutral", "-sw1076", "-sw1079",
'-out', wix_installer, wix_object_file]
subprocess.check_call(light_cmd, env=env)
os.remove(wix_object_file)
#mv file to output dir
shutil.move(wix_installer, output)
finally:
os.chdir(old_cwd)
shutil.rmtree(tmpdir)