#!/usr/bin/env bash # Empacota o You're the OS! do fredygames.com: You're the OS! 1.11.2+ (GPL-3.0-or-later), de Pier-Luc # Brault, a partir do tarball do commit 20ff9e4 de plbrault/youre-the-os, como no "pipenv run web build" # do autor (pygbag 0.9.2, o empacotador do pygame-ce para a web), com tres diferencas: --no_opt (os # PNG entram como estao, sem o pngquant com perdas que o pygbag usa quando o acha instalado), o modelo # da pagina vem de um arquivo conferido + o nosso patch (em vez de baixado do CDN na hora) e o src.apk # (um zip) e reempacotado em ordem fixa e com datas fixas. Este script e o patch ao lado dele sao parte # do codigo-fonte publicado junto do jogo ("the scripts used to control compilation" da GPL). # # src/FredGames.Web/Content/games/youre-the-os/engine/build.sh # # O jogo e Python: o pygbag so junta src/ num src.apk e gera o index.html a partir do modelo. O runtime # (CPython 3.12 em WebAssembly, o pygame-ce, o pythons.js) e o do pygbag 0.9, que o bundle.yaml copia # do repositorio pygame-web/archives num commit fixo para a pasta pgw/ do bundle. # # pygbag-template-fredygames.patch (sobre o default.tmpl do pygbag 0.9, o mesmo do CDN): # - o endereco do runtime vira absoluto a partir da propria pagina (pgw/0.9/), porque o vtx.js # importa o xterm.js a partir dele; # - fetch() e XMLHttpRequest para https://pygame-web.github.io/archives/ (o indice de pacotes e o # wheel do pygame-ce, que o runtime pede pelo endereco original) vao para pgw/ da mesma pasta; # - uma Content-Security-Policy que recusa qualquer conexao a outra origem; # - sem o do pythonrc.py, que nao existe no CDN (404 tambem no original). # - fundo preto em volta do jogo (o modelo usa cinza). # # Python: o do sistema (/usr/bin/python3); o pygbag e Python puro, sem dependencias, e roda direto do # wheel conferido. Dois builds seguidos dao os mesmos bytes. # # Saida: artifacts/build/youre-the-os-20ff9e4/web/ (index.html, src.apk, favicon.png), que o # bundle.yaml do jogo confere arquivo por arquivo. set -euo pipefail COMMIT=20ff9e4a78b5447b3f7d55c82d4c7e664a374aaf SHA256=4503fc023217fafab1dc9e2e58058afca53008502bd7c853b75e6b7619af06a7 PYGBAG=0.9.2 PYGBAG_URL=https://files.pythonhosted.org/packages/3a/19/6c4b2a515651849138cef43d878eba9a4f8e39113499a99e7c3d97890c5e/pygbag-0.9.2-py3-none-any.whl PYGBAG_SHA256=3a60a80cc28ed21e3d5d98c08a5d8f857911e38e411b6e590ba640158e8656c1 ARCHIVES=5ab484fcee674a99492cceb7bf3340239da63d7a TEMPLATE_SHA256=ec6f47b92ad985c9ee079ca32583c0ed68538c6d8f9042a6b6bdc13a45bf8524 here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" root="$(git -C "$here" rev-parse --show-toplevel 2>/dev/null || pwd)" out="$root/artifacts/build/youre-the-os-${COMMIT:0:7}" cache="$root/artifacts/build/cache" mkdir -p "$cache" fetch() { if [ ! -f "$cache/$2" ]; then curl -fsSL --retry 4 "$1" -o "$cache/$2.partial" && mv "$cache/$2.partial" "$cache/$2" fi echo "$3 $cache/$2" | shasum -a 256 -c - } fetch "https://github.com/plbrault/youre-the-os/archive/$COMMIT.tar.gz" "youre-the-os-${COMMIT:0:7}.tar.gz" "$SHA256" fetch "$PYGBAG_URL" "pygbag-$PYGBAG-py3-none-any.whl" "$PYGBAG_SHA256" fetch "https://raw.githubusercontent.com/pygame-web/archives/$ARCHIVES/0.9/default.tmpl" \ "pygbag-0.9-default-${ARCHIVES:0:7}.tmpl" "$TEMPLATE_SHA256" rm -rf "$out" mkdir -p "$out/tree" "$out/pygbag" "$out/web" tar -xzf "$cache/youre-the-os-${COMMIT:0:7}.tar.gz" -C "$out/tree" --strip-components 1 /usr/bin/unzip -q "$cache/pygbag-$PYGBAG-py3-none-any.whl" -d "$out/pygbag" mkdir -p "$out/template" cp "$cache/pygbag-0.9-default-${ARCHIVES:0:7}.tmpl" "$out/template/default.tmpl" patch -d "$out/template" -p1 --quiet < "$here/pygbag-template-fredygames.patch" export TZ=UTC LC_ALL=C PYTHONDONTWRITEBYTECODE=1 PYTHONPATH="$out/pygbag" # Os mesmos argumentos do run-web.py do autor ("pipenv run web build"), mais --no_opt, --cdn e # --template. Roda na raiz do jogo, onde fica o favicon.png que o pygbag copia. cd "$out/tree" /usr/bin/python3 -m pygbag --app_name youre_the_os --ume_block 0 --title "You're the OS!" \ --build --no_opt --cdn pgw/0.9/ --template "$out/template/default.tmpl" src > "$out/pygbag.log" # src.apk: o mesmo conteudo, em ordem alfabetica e com data fixa (o pygbag segue a ordem do disco e a # data de cada arquivo). /usr/bin/python3 - "$out/tree/src/build/web/src.apk" "$out/web/src.apk" <<'PY' import sys, zipfile src, dst = sys.argv[1:] with zipfile.ZipFile(src) as zin, zipfile.ZipFile(dst, "w") as zout: for name in sorted(zin.namelist()): info = zipfile.ZipInfo(name, date_time=(1980, 1, 1, 0, 0, 0)) info.compress_type = zipfile.ZIP_DEFLATED info.external_attr = 0o644 << 16 info.create_system = 3 zout.writestr(info, zin.read(name), compress_type=zipfile.ZIP_DEFLATED, compresslevel=9) PY cp "$out/tree/src/build/web/index.html" "$out/tree/src/build/web/favicon.png" "$out/web/" echo "You're the OS! (${COMMIT:0:7}) em $out/web:" (cd "$out/web" && for f in index.html src.apk favicon.png; do echo "$(shasum -a 256 "$f" | cut -d' ' -f1) $f"; done)