|
#!/usr/bin/env python3 |
|
|
|
# create-channel-switch-mar.py |
|
# |
|
# for channel switching, replacing channel-prefs.js and/or update-settings.ini |
|
|
|
import logging |
|
from os import path, makedirs, getcwd, chdir |
|
from shutil import rmtree |
|
import subprocess |
|
import tempfile |
|
|
|
|
|
CHANNEL_PREFS = "default/pref/channel-prefs.js" |
|
CHANNEL_PREFS_CONTENT = """\ |
|
/* 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/. */ |
|
|
|
pref("app.update.channel", "%s"); |
|
""" |
|
UPDATE_SETTINGS = "update-settings.ini" |
|
UPDATE_SETTINGS_CONTENT = """\ |
|
; If you modify this file updates may fail. |
|
; Do not modify this file. |
|
|
|
[Settings] |
|
ACCEPTED_MAR_CHANNEL_IDS=%s |
|
""" |
|
|
|
|
|
def compress(str): |
|
return subprocess.check_output(["xz"], input=str.encode("ascii")) |
|
|
|
|
|
def setup_newfiles(channel=None, accepted_mar_channel_ids=None): |
|
files = [] |
|
if channel is not None: |
|
makedirs(path.dirname(CHANNEL_PREFS)) |
|
makedirs("Contents/Resources/" + path.dirname(CHANNEL_PREFS)) |
|
channel_prefs = compress(CHANNEL_PREFS_CONTENT % channel) |
|
logging.info("Writing %s", CHANNEL_PREFS) |
|
with open(CHANNEL_PREFS, "wb") as f: |
|
f.write(channel_prefs) |
|
with open("Contents/Resources/" + CHANNEL_PREFS, "wb") as f: |
|
f.write(channel_prefs) |
|
files += [CHANNEL_PREFS, "Contents/Resources/" + CHANNEL_PREFS] |
|
if accepted_mar_channel_ids is not None: |
|
makedirs("Contents/Resources/" + path.dirname(UPDATE_SETTINGS)) |
|
update_settings = compress( |
|
UPDATE_SETTINGS_CONTENT % ",".join(accepted_mar_channel_ids) |
|
) |
|
logging.info("Writing %s", UPDATE_SETTINGS) |
|
with open(UPDATE_SETTINGS, "wb") as f: |
|
f.write(update_settings) |
|
with open("Contents/Resources/" + UPDATE_SETTINGS, "wb") as f: |
|
f.write(update_settings) |
|
files += [UPDATE_SETTINGS, "Contents/Resources/" + UPDATE_SETTINGS] |
|
return files |
|
|
|
|
|
def write_manifest(files): |
|
manifest = 'type "partial"\n' |
|
for filename in files: |
|
manifest += 'add-if "%s" "%s"\n' % (filename, filename) |
|
logging.info("Writing manifest") |
|
with open("updatev3.manifest", "wb") as f: |
|
f.write(compress(manifest)) |
|
files.append("updatev3.manifest") |
|
|
|
|
|
def pack_mar(tmpdir, output, version, channel, files): |
|
logging.info("Packing mar file") |
|
subprocess.check_call( |
|
["mar", "-C", tmpdir, "-c", output, "-V", version, "-H", channel] + files |
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
import argparse |
|
|
|
parser = argparse.ArgumentParser() |
|
# contents |
|
parser.add_argument("-c", "--channel", help="update channel to switch to") |
|
parser.add_argument( |
|
"-i", "--accepted-channel-id", nargs="+", help="accepted mar channel id" |
|
) |
|
# metadata |
|
parser.add_argument( |
|
"-V", "--version", required=True, help="version number to use for the mar file" |
|
) |
|
parser.add_argument( |
|
"-m", |
|
"--mar-channel-id", |
|
required=True, |
|
help="channel id to use for the mar file", |
|
) |
|
|
|
parser.add_argument("-o", "--output", required=True, help="output file name") |
|
parser.add_argument("-v", "--verbose", action="store_true", help="verbose messages") |
|
|
|
args = parser.parse_args() |
|
|
|
log_level = logging.INFO |
|
if args.verbose: |
|
log_level = logging.DEBUG |
|
logging.basicConfig( |
|
level=log_level, format="%(asctime)s - %(levelname)s: %(message)s" |
|
) |
|
log = logging.getLogger() |
|
|
|
tmpdir = tempfile.mkdtemp() |
|
logging.info("Working directory: %s", tmpdir) |
|
|
|
cwd = getcwd() |
|
chdir(tmpdir) |
|
files = setup_newfiles(args.channel, args.accepted_channel_id) |
|
write_manifest(files) |
|
chdir(cwd) |
|
pack_mar(tmpdir, args.output, args.version, args.mar_channel_id, files) |
|
rmtree(tmpdir) |
|
|
|
log.info("All done.") |