Last active
January 25, 2025 21:32
-
-
Save WillyJL/9e3e6fac4fdbdb3d40fccdb329fe32f1 to your computer and use it in GitHub Desktop.
Deterministic zip archiving for Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import os | |
| import pathlib | |
| import zipfile | |
| ZIP_COMPRESS_TYPE = zipfile.ZIP_DEFLATED | |
| ZIP_ARCH_EXTENSION = ".zip" | |
| def zip_sanitizer_filter(zipinfo: zipfile.ZipInfo): | |
| zipinfo.date_time = (1980, 1, 1, 0, 0, 0) # Minimum date | |
| if zipinfo.is_dir(): | |
| zipinfo.external_attr = 0o40775 << 16 # drwxrwxr-x | |
| zipinfo.external_attr |= 0x10 # MS-DOS directory flag | |
| else: | |
| zipinfo.external_attr = 0o664 << 16 # ?rw-rw-r-- | |
| zipinfo.create_system = 0 # Unix-like | |
| return zipinfo | |
| def compress_tree_ziparch( | |
| src_dir, | |
| output_name, | |
| filter=zip_sanitizer_filter, | |
| gz_level=9, | |
| ): | |
| top = pathlib.Path(src_dir) | |
| original_size = 0 | |
| with zipfile.ZipFile( | |
| file=output_name, | |
| mode="w", | |
| compression=ZIP_COMPRESS_TYPE, | |
| compresslevel=gz_level, | |
| ) as ziparch: | |
| for cur, dirs, files in os.walk(top): | |
| cur = pathlib.Path(cur) | |
| dirs.sort() | |
| files.sort() | |
| if cur != top: | |
| zipinfo = zipfile.ZipInfo.from_file(cur, cur.relative_to(top)) | |
| zipinfo.compress_size = 0 | |
| zipinfo.CRC = 0 | |
| ziparch.mkdir(filter(zipinfo)) | |
| for file in files: | |
| path = cur / file | |
| original_size += top.stat().st_size | |
| zipinfo = zipfile.ZipInfo.from_file(path, path.relative_to(top)) | |
| ziparch.writestr( | |
| filter(zipinfo), | |
| path.read_bytes(), | |
| compress_type=ZIP_COMPRESS_TYPE, | |
| compresslevel=gz_level, | |
| ) | |
| return original_size, os.stat(output_name).st_size |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Originally made for Momentum Firmware's Asset-Packs management tooling. Loosely based on tarball.py from Flipper Zero firmware, you might find that script useful too, as a parallel to this one.