зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
6ab329c54f
Коммит
db3477911d
|
@ -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)
|
Загрузка…
Ссылка в новой задаче