From 3db5db9c023f7bbf6a1f908049ddbf24bc038d2d Mon Sep 17 00:00:00 2001 From: osmarks Date: Sat, 9 Dec 2023 17:21:12 +0000 Subject: [PATCH] rewrite build system in Python --- build.py | 104 +++++++++++++++++++++++++++++++++++++++++++ build.sh | 21 --------- generate_manifest.py | 71 ----------------------------- 3 files changed, 104 insertions(+), 92 deletions(-) create mode 100755 build.py delete mode 100755 build.sh delete mode 100755 generate_manifest.py diff --git a/build.py b/build.py new file mode 100755 index 0000000..75d1df9 --- /dev/null +++ b/build.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 + +import hashlib +import json +import datetime +import shutil +import ccecc +import argparse +from pathlib import Path, PurePosixPath +import sys +import subprocess +import os + +parser = argparse.ArgumentParser(description="build potatOS") +parser.add_argument("-D", "--description", help="description of version") +parser.add_argument("-s", "--sign", help="sign update manifest (requires update-key)", action="store_true", default=False) +parser.add_argument("-m", "--minify", help="minify (production build)", action="store_true", default=False) +args = parser.parse_args() + +workdir = Path(sys.argv[0]).parent.resolve() +src = workdir / "src" +dist = workdir / "dist" +shutil.rmtree(dist) +os.makedirs(dist, exist_ok=True) +shutil.copy(src / "polychoron.lua", dist / "startup") +for x in ["xlib", "signing-key.tbl", "LICENSES", "stdlib.hvl", "bin", "potatobios.lua"]: + if (src / x).is_dir(): shutil.copytree(src / x, dist / x) + else: shutil.copy(src / x, dist / x) + +proc = subprocess.run(["npx", "luabundler", "bundle", src / "main.lua", "-p", src / "lib" / "?.lua"], capture_output=True) +proc.check_returncode() +with open(dist / "autorun.lua", "wb") as f: + f.write(proc.stdout.rstrip()) + +if args.minify: + os.chdir(workdir / "minify") + for x in ["autorun.lua", "potatobios.lua"]: + file = dist / x + subprocess.run(["lua5.1", "CommandLineMinify.lua", file, file.with_suffix(".lua.tmp"), file.with_suffix(".lua.map")]).check_returncode() + file.with_suffix(".lua.tmp").rename(file) + os.chdir(workdir) + +subprocess.run(["sed", "-i", "19iif _G.package and _G.package.loaded[package] then loadedModule = _G.package.loaded[package] end if _G.package and _G.package.preload[package] then local pkg = _G.package.preload[package](_G.package) _G.package.loaded[package] = pkg loadedModule = pkg end", dist / "autorun.lua"]).check_returncode() + +with open(dist / "autorun.lua", "a") as f: + f.write("(...)") + +counter = 0 +manifest_path = workdir / "manifest" +if manifest_path.exists(): + current = open(manifest_path).read().split("\n")[0] + counter = json.loads(current).get("build", 0) + +def hash_file(path): + file = open(path, "rb") + h = hashlib.sha256() + count = 0 + while data := file.read(65536): + h.update(data) + count += len(data) + return h.hexdigest(), count + +if args.sign: + print("Signing update") + import genkeys + k = genkeys.get_key() + pubkey = ccecc.public_key(k).hex() + open("dist/update-key.hex", "w").write(pubkey) + +files = dict() +sizes = dict() +code = Path("./dist/") +for path in code.glob("**/*"): + if not path.is_dir() and not path.parts[-1].endswith(".map"): + hexhash, count = hash_file(path) + mpath = "/".join(path.parts[1:]) + files[mpath] = hexhash + sizes[mpath] = count + +def deterministic_json_serialize(x): + return json.dumps(x, sort_keys=True, separators=(",", ":")) + +manifest_data = deterministic_json_serialize({ + "files": files, + "sizes": sizes, + "timestamp": int(datetime.datetime.now().timestamp()), + "build": counter + 1, + "description": args.description +}) + +manifest_meta = { + "hash": hashlib.sha256(manifest_data.encode("utf-8")).hexdigest() +} + +if args.sign: + manifest_meta["sig"] = ccecc.sign(k, manifest_meta["hash"].encode("utf-8")).hex() + +manifest_meta = deterministic_json_serialize(manifest_meta) + +manifest = f"{manifest_data}\n{manifest_meta}" + +open(manifest_path, "w").write(manifest) +shutil.copy(manifest_path, dist) +print(counter + 1) \ No newline at end of file diff --git a/build.sh b/build.sh deleted file mode 100755 index 57692d5..0000000 --- a/build.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -mkdir -p dist -rm -r dist/* -cp src/polychoron.lua dist/startup -cp -r src/xlib/ dist -cp -r src/signing-key.tbl dist -cp -r src/LICENSES dist -cp -r src/stdlib.hvl dist -cp -r src/bin/ dist -cp src/potatobios.lua dist/ -npx luabundler bundle src/main.lua -p "src/lib/?.lua" | perl -pe 'chomp if eof' > dist/autorun_full.lua -WORK=$(pwd) -cd ./minify -lua5.1 CommandLineMinify.lua "$WORK/dist/autorun_full.lua" "$WORK/dist/autorun.lua" "$WORK/dist/autorun.lua.map" -lua5.1 CommandLineMinify.lua "$WORK/dist/potatobios.lua" "$WORK/dist/pb_tmp.lua" "$WORK/dist/potatobios.lua.map" -mv "$WORK/dist/pb_tmp.lua" "$WORK/dist/potatobios.lua" -cd "$WORK" -rm dist/autorun_full.lua -sed -i '19iif _G.package and _G.package.loaded[package] then loadedModule = _G.package.loaded[package] end if _G.package and _G.package.preload[package] then local pkg = _G.package.preload[package](_G.package) _G.package.loaded[package] = pkg loadedModule = pkg end' dist/autorun.lua -echo -n "(...)" >> dist/autorun.lua -./generate_manifest.py "$@" \ No newline at end of file diff --git a/generate_manifest.py b/generate_manifest.py deleted file mode 100755 index 87332f3..0000000 --- a/generate_manifest.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python3 - -import hashlib -import json -import datetime -import os.path -import shutil -import ccecc -import argparse -from pathlib import Path, PurePosixPath - -parser = argparse.ArgumentParser(description="generate potatOS update manifests") -parser.add_argument("-D", "--description", help="description of version") -parser.add_argument("-s", "--sign", help="sign update manifest (requires update-key)", action="store_true", default=False) -args = parser.parse_args() - -counter = 0 -if os.path.exists("./manifest"): - current = open("manifest").read().split("\n")[0] - counter = json.loads(current).get("build", 0) - -def hash_file(path): - file = open(path, "rb") - h = hashlib.sha256() - count = 0 - while data := file.read(65536): - h.update(data) - count += len(data) - return h.hexdigest(), count - -if args.sign: - print("Signing update") - import genkeys - k = genkeys.get_key() - pubkey = ccecc.public_key(k).hex() - open("dist/update-key.hex", "w").write(pubkey) - -files = dict() -sizes = dict() -code = Path("./dist/") -for path in code.glob("**/*"): - if not path.is_dir() and not path.parts[-1].endswith(".map"): - hexhash, count = hash_file(path) - mpath = "/".join(path.parts[1:]) - files[mpath] = hexhash - sizes[mpath] = count - -def deterministic_json_serialize(x): - return json.dumps(x, sort_keys=True, separators=(",", ":")) - -manifest_data = deterministic_json_serialize({ - "files": files, - "sizes": sizes, - "timestamp": int(datetime.datetime.now().timestamp()), - "build": counter + 1, - "description": args.description -}) - -manifest_meta = { - "hash": hashlib.sha256(manifest_data.encode("utf-8")).hexdigest() -} - -if args.sign: - manifest_meta["sig"] = ccecc.sign(k, manifest_meta["hash"].encode("utf-8")).hex() - -manifest_meta = deterministic_json_serialize(manifest_meta) - -manifest = f"{manifest_data}\n{manifest_meta}" - -open("manifest", "w").write(manifest) -shutil.copy("manifest", "dist") \ No newline at end of file