summaryrefslogtreecommitdiffstats
path: root/python/mozbuild/mozbuild/repackaging/mar.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/mozbuild/mozbuild/repackaging/mar.py')
-rw-r--r--python/mozbuild/mozbuild/repackaging/mar.py93
1 files changed, 93 insertions, 0 deletions
diff --git a/python/mozbuild/mozbuild/repackaging/mar.py b/python/mozbuild/mozbuild/repackaging/mar.py
new file mode 100644
index 0000000000..f215c17238
--- /dev/null
+++ b/python/mozbuild/mozbuild/repackaging/mar.py
@@ -0,0 +1,93 @@
+# 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 shutil
+import subprocess
+import sys
+import tarfile
+import tempfile
+import zipfile
+from pathlib import Path
+
+import mozfile
+import mozpack.path as mozpath
+
+from mozbuild.repackaging.application_ini import get_application_ini_value
+from mozbuild.util import ensureParentDir
+
+_BCJ_OPTIONS = {
+ "x86": ["--x86"],
+ "x86_64": ["--x86"],
+ "aarch64": [],
+ # macOS Universal Builds
+ "macos-x86_64-aarch64": [],
+}
+
+
+def repackage_mar(topsrcdir, package, mar, output, arch=None, mar_channel_id=None):
+ if not zipfile.is_zipfile(package) and not tarfile.is_tarfile(package):
+ raise Exception("Package file %s is not a valid .zip or .tar file." % package)
+ if arch and arch not in _BCJ_OPTIONS:
+ raise Exception(
+ "Unknown architecture {}, available architectures: {}".format(
+ arch, list(_BCJ_OPTIONS.keys())
+ )
+ )
+
+ ensureParentDir(output)
+ tmpdir = tempfile.mkdtemp()
+ try:
+ if tarfile.is_tarfile(package):
+ filelist = mozfile.extract_tarball(package, tmpdir)
+ else:
+ z = zipfile.ZipFile(package)
+ z.extractall(tmpdir)
+ filelist = z.namelist()
+ z.close()
+
+ toplevel_dirs = set([mozpath.split(f)[0] for f in filelist])
+ excluded_stuff = set([" ", ".background", ".DS_Store", ".VolumeIcon.icns"])
+ toplevel_dirs = toplevel_dirs - excluded_stuff
+ # Make sure the .zip file just contains a directory like 'firefox/' at
+ # the top, and find out what it is called.
+ if len(toplevel_dirs) != 1:
+ raise Exception(
+ "Package file is expected to have a single top-level directory"
+ "(eg: 'firefox'), not: %s" % toplevel_dirs
+ )
+ ffxdir = mozpath.join(tmpdir, toplevel_dirs.pop())
+
+ make_full_update = mozpath.join(
+ topsrcdir, "tools/update-packaging/make_full_update.sh"
+ )
+
+ env = os.environ.copy()
+ env["MOZ_PRODUCT_VERSION"] = get_application_ini_value(tmpdir, "App", "Version")
+ env["MAR"] = mozpath.normpath(mar)
+ if arch:
+ env["BCJ_OPTIONS"] = " ".join(_BCJ_OPTIONS[arch])
+ if mar_channel_id:
+ env["MAR_CHANNEL_ID"] = mar_channel_id
+ # The Windows build systems have xz installed but it isn't in the path
+ # like it is on Linux and Mac OS X so just use the XZ env var so the mar
+ # generation scripts can find it.
+ xz_path = mozpath.join(topsrcdir, "xz/xz.exe")
+ if os.path.exists(xz_path):
+ env["XZ"] = mozpath.normpath(xz_path)
+
+ cmd = [make_full_update, output, ffxdir]
+ if sys.platform == "win32":
+ # make_full_update.sh is a bash script, and Windows needs to
+ # explicitly call out the shell to execute the script from Python.
+
+ mozillabuild = os.environ["MOZILLABUILD"]
+ if (Path(mozillabuild) / "msys2").exists():
+ cmd.insert(0, mozillabuild + "/msys2/usr/bin/bash.exe")
+ else:
+ cmd.insert(0, mozillabuild + "/msys/bin/bash.exe")
+ subprocess.check_call(cmd, env=env)
+
+ finally:
+ shutil.rmtree(tmpdir)