fix: store already-compressed pack members

Every member was deflated, archives and PNGs included. On the 2026-10-20
RetroArch pack the .zip, .7z, .chd, .png, .ogg and .pk4 members are 2.1 GB
that took 28 s to deflate again for 9.6 MB saved (0.45 %), and about 16 GB
for 72 MB across all packs. Those formats are now stored. The choice reads
the member name only, so a pack stays byte-reproducible.
This commit is contained in:
Abdessamad Derraz committed 2026-10-21 05:10:00 +02:00
1 parent ae874534e2
commit f7d561e42f
2 files changed
+54 -2

No files matched your search

+18 -2
View File
@@ -105,6 +105,22 @@ DEFAULT_BIOS_DIR = "bios"
# Formats that are already compressed: deflating them again took 28 s of the
# RetroArch build for 2.1 GB of members and saved 9.6 MB (0.45 %), 16 GB and
# about 72 MB across all packs. Measured per extension on the 2026-10-20
# packs; .pk3 (3 %), .jpg (6 %), .avi (44 %) and .jar (60 %) still shrink
# and stay deflated. Chosen by name alone, so a pack stays a function of its
# inputs.
_STORED_EXTENSIONS = frozenset({".7z", ".chd", ".ogg", ".pk4", ".png", ".zip"})
def _member_compression(arcname: str) -> int:
"""ZIP_STORED for a member whose format is already compressed."""
if os.path.splitext(arcname)[1].lower() in _STORED_EXTENSIONS:
return zipfile.ZIP_STORED
return zipfile.ZIP_DEFLATED
def _add_pack_member(zf: zipfile.ZipFile, source_path: str, arcname: str) -> None:
"""Add a file to the pack with metadata that does not depend on the build.
@@ -117,7 +133,7 @@ def _add_pack_member(zf: zipfile.ZipFile, source_path: str, arcname: str) -> Non
because some members are firmware images of several hundred megabytes.
"""
info = zipfile.ZipInfo(filename=arcname, date_time=_FIXED_DATE_TIME)
info.compress_type = zipfile.ZIP_DEFLATED
info.compress_type = _member_compression(arcname)
# The executable bit is the one permission worth carrying: the RetroDECK
# pack ships the two Voxatron engine binaries, and a user who extracts
# them at 644 cannot run them. Git records the bit, so reading it from
@@ -1218,7 +1234,7 @@ def _extract_zip_to_archive(
member = zipfile.ZipInfo(
filename=target_path, date_time=_FIXED_DATE_TIME
)
member.compress_type = zipfile.ZIP_DEFLATED
member.compress_type = _member_compression(target_path)
member.external_attr = 0o100644 << 16
target_zf.writestr(member, data)
+36
View File
@@ -413,5 +413,41 @@ class ManifestInjectionIsAtomic(unittest.TestCase):
)
class PackMemberCompression(unittest.TestCase):
"""A pack deflated every member, archives and PNGs included: 16 GB of
already-compressed data deflated again on each full build for 0.18 % of
the packs' size."""
def _pack(self, tmp: Path, name: str) -> Path:
from scripts.generate_pack import _add_pack_member
source = tmp / "member"
source.write_bytes(b"\x00" * 4096)
pack = tmp / name
with zipfile.ZipFile(pack, "w", zipfile.ZIP_DEFLATED) as zf:
for arcname in ("bios/a.zip", "bios/b.PNG", "bios/c.bin", "bios/d.pk3"):
_add_pack_member(zf, str(source), arcname)
return pack
def test_compressed_formats_are_stored_and_the_rest_deflated(self):
with tempfile.TemporaryDirectory() as tmp:
pack = self._pack(Path(tmp), "pack.zip")
with zipfile.ZipFile(pack) as zf:
kinds = {i.filename: i.compress_type for i in zf.infolist()}
self.assertEqual(kinds, {
"bios/a.zip": zipfile.ZIP_STORED,
"bios/b.PNG": zipfile.ZIP_STORED,
"bios/c.bin": zipfile.ZIP_DEFLATED,
"bios/d.pk3": zipfile.ZIP_DEFLATED,
})
def test_the_pack_stays_byte_reproducible(self):
with tempfile.TemporaryDirectory() as tmp:
first = self._pack(Path(tmp), "one.zip").read_bytes()
time.sleep(1.1)
second = self._pack(Path(tmp), "two.zip").read_bytes()
self.assertEqual(hashlib.sha256(first).hexdigest(), hashlib.sha256(second).hexdigest())
if __name__ == "__main__":
unittest.main()