Newer
Older
NewLang / build.py
# SPDX-License-Identifier: LGPL-2.1
# Copyright 2022 Jookia <contact@jookia.org>

import pathlib
import zipfile
import subprocess
import time


def reproducible_date():
    fallback = (1980, 1, 1, 1, 1, 1)
    git_time = subprocess.run(
        ["git", "show", "-s", "--format=%ct"], capture_output=True
    )
    if git_time.returncode != 0:
        return fallback
    commit_time = int(git_time.stdout.decode("utf-8").split("\n")[0])
    t = time.gmtime(commit_time)
    return (t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)


def clean_zip(path):
    path.unlink(missing_ok=True)


def open_zip(path):
    return zipfile.ZipFile(
        path, mode="x", compression=zipfile.ZIP_DEFLATED, compresslevel=9
    )


def close_zip(zip):
    zip.close()


def find_all_src(srcpath):
    paths = srcpath.glob("**/*")
    new_paths = [srcpath]
    for p in paths:
        if "__pycache__" in p.as_posix():
            continue
        new_paths.append(p)
    return new_paths


def write_zip_entry(zip, name, data, date):
    info = zipfile.ZipInfo(filename=name, date_time=date)
    zip.writestr(info, data, compress_type=zipfile.ZIP_DEFLATED, compresslevel=9)


def write_main(zip, date):
    name = "__main__.py"
    data = "import src.main\nsrc.main.wait_main()"
    write_zip_entry(zip, name, data, date)


def write_dir(zip, path, date):
    # For some reason Python needs empty files with the names of directories ending in /
    name = path.as_posix() + "/"
    data = ""
    write_zip_entry(zip, name, data, date)


def write_file(zip, path, date):
    file = path.open()
    data = file.read()
    file.close()
    name = path.as_posix()
    write_zip_entry(zip, name, data, date)


def write_src(zip, date):
    srcs = sorted(find_all_src(pathlib.Path("src")))
    for p in srcs:
        if p.is_dir():
            write_dir(zip, p, date)
        else:
            write_file(zip, p, date)


def main():
    filename = pathlib.Path("NewLang.pyz")
    date = reproducible_date()
    clean_zip(filename)
    zip = open_zip(filename)
    write_src(zip, date)
    write_main(zip, date)
    close_zip(zip)


if __name__ == "__main__":
    main()