#!/usr/bin/env python3 import json import os import sys from datetime import datetime from collections import OrderedDict from pathlib import Path from subprocess import check_call as run from zipfile import (ZipFile, ZipInfo, ZIP_DEFLATED, ZIP_STORED) FILES = [ "manifest.json", "_locales/**/*", "bundles/*", "style/*", "uikit/css/*", "windows/*.html", "Readme.*", "LICENSE.*", ] RELEASE_ID = "{DDC359D1-844A-42a7-9AA1-88A850A938A8}" UNCOMPRESSABLE = set((".png", ".jpg", ".zip", ".woff2")) LICENSED = set((".css", ".html", ".js", "*.ts")) IGNORED = set((".DS_Store", "Thumbs.db")) PERM_IGNORED_FX = set(("downloads.shelf", "webRequest", "webRequestBlocking")) PERM_IGNORED_CHROME = set(("menus", "sessions")) SCRIPTS = [ "yarn build:regexps", "yarn build:bundles", ] def check_licenses(): for file in Path().glob("**/*"): if "node_modules" in str(file): continue if not file.suffix in LICENSED: continue with file.open("rb") as fp: if not b"License:" in fp.read(): raise Exception(f"No license in {file}") def files(): p = Path("") for pattern in FILES: for file in sorted(p.glob(pattern)): if file.name in IGNORED or not file.is_file(): continue yield file def build(out, manifest): with ZipFile(out, "w", compression=ZIP_DEFLATED, allowZip64=False, compresslevel=2) as zp: for file in files(): if str(file) == "manifest.json": buf = manifest else: with file.open("rb") as fp: buf = fp.read() if file.suffix in LICENSED and not b"License:" in buf: raise Exception(f"No license in {file}") zinfo = ZipInfo(str(file), date_time=(2019, 1, 1, 0, 0, 0)) if file.suffix in UNCOMPRESSABLE: zp.writestr(zinfo, buf, compress_type=ZIP_STORED) else: zp.writestr(zinfo, buf, compress_type=ZIP_DEFLATED, compresslevel=2) print(file) def build_firefox(args): now = datetime.now().strftime("%Y%m%d%H%M%S") with open("manifest.json") as manip: infos = json.load(manip, object_pairs_hook=OrderedDict) version = infos.get("version") if args.mode == "nightly": version = infos["version"] = f"{version}.{now}" version = infos.get("version") if args.mode != "release": infos["version_name"] = f"{version}-{args.mode}" infos["browser_specific_settings"]["gecko"]["id"] = f"{args.mode}@downthemall.org" infos["short_name"] = infos.get("name") infos["name"] = f"{infos.get('name')} {args.mode}" else: infos["browser_specific_settings"]["gecko"]["id"] = RELEASE_ID infos["permissions"] = [p for p in infos.get("permissions") if not p in PERM_IGNORED_FX] out = Path("web-ext-artifacts") / f"dta-{version}-{args.mode}-fx.zip" if not out.parent.exists(): out.parent.mkdir() if out.exists(): out.unlink() print("Output", out) build(out, json.dumps(infos, indent=2).encode("utf-8")) def build_chrome(args): now = datetime.now().strftime("%Y%m%d%H%M%S") with open("manifest.json") as manip: infos = json.load(manip, object_pairs_hook=OrderedDict) version = infos.get("version") if args.mode == "nightly": version = infos["version"] = f"{version}.{now}" version = infos.get("version") del infos["browser_specific_settings"] if args.mode != "release": infos["version_name"] = f"{version}-{args.mode}" infos["short_name"] = infos.get("name") infos["name"] = f"{infos.get('name')} {args.mode}" infos["permissions"] = [p for p in infos.get("permissions") if not p in PERM_IGNORED_CHROME] out = Path("web-ext-artifacts") / f"dta-{version}-{args.mode}-crx.zip" if not out.parent.exists(): out.parent.mkdir() if out.exists(): out.unlink() print("Output", out) build(out, json.dumps(infos, indent=2).encode("utf-8")) def main(): from argparse import ArgumentParser args = ArgumentParser() args.add_argument("--mode", type=str, default="dev", choices=["dev", "beta", "release", "nightly"]) args = args.parse_args(sys.argv[1:]) check_licenses() for script in SCRIPTS: if os.name == "nt": run(script.split(" "), shell=True) else: run([script], shell=True) build_firefox(args) build_chrome(args) print("DONE.") if __name__ == "__main__": main()