summaryrefslogtreecommitdiff
path: root/pkg/private/zip/build_zip.py
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/private/zip/build_zip.py')
-rw-r--r--pkg/private/zip/build_zip.py52
1 files changed, 41 insertions, 11 deletions
diff --git a/pkg/private/zip/build_zip.py b/pkg/private/zip/build_zip.py
index 64c4206..5a191b7 100644
--- a/pkg/private/zip/build_zip.py
+++ b/pkg/private/zip/build_zip.py
@@ -15,7 +15,9 @@
import argparse
import datetime
+import logging
import os
+import sys
import zipfile
from pkg.private import build_info
@@ -24,9 +26,10 @@ from pkg.private import manifest
ZIP_EPOCH = 315532800
# Unix dir bit and Windows dir bit. Magic from zip spec
-UNIX_DIR_BIT = 0o40000
-MSDOS_DIR_BIT = 0x10
+UNIX_FILE_BIT = 0o100000
UNIX_SYMLINK_BIT = 0o120000
+UNIX_DIR_BIT = 0o040000
+MSDOS_DIR_BIT = 0x10
def _create_argument_parser():
"""Creates the command line arg parser."""
@@ -46,6 +49,12 @@ def _create_argument_parser():
parser.add_argument(
'-m', '--mode',
help='The file system mode to use for files added into the zip.')
+ parser.add_argument(
+ '-c', '--compression_type',
+ help='The compression type to use')
+ parser.add_argument(
+ '-l', '--compression_level',
+ help='The compression level to use')
parser.add_argument('--manifest',
help='manifest of contents to add to the layer.',
required=True)
@@ -71,7 +80,7 @@ def parse_date(ts):
class ZipWriter(object):
- def __init__(self, output_path: str, time_stamp: int, default_mode: int):
+ def __init__(self, output_path: str, time_stamp: int, default_mode: int, compression_type: str, compression_level: int):
"""Create a writer.
You must close() after use or use in a 'with' statement.
@@ -84,7 +93,15 @@ class ZipWriter(object):
self.output_path = output_path
self.time_stamp = time_stamp
self.default_mode = default_mode
- self.zip_file = zipfile.ZipFile(self.output_path, mode='w')
+ compressions = {
+ "deflated": zipfile.ZIP_DEFLATED,
+ "lzma": zipfile.ZIP_LZMA,
+ "bzip2": zipfile.ZIP_BZIP2,
+ "stored": zipfile.ZIP_STORED
+ }
+ self.compression_type = compressions[compression_type]
+ self.compression_level = compression_level
+ self.zip_file = zipfile.ZipFile(self.output_path, mode='w', compression=self.compression_type)
def __enter__(self):
return self
@@ -96,6 +113,15 @@ class ZipWriter(object):
self.zip_file.close()
self.zip_file = None
+ def writestr(self, entry_info, content: str, compresslevel: int):
+ if sys.version_info >= (3, 7):
+ self.zip_file.writestr(entry_info, content, compresslevel=compresslevel)
+ else:
+ # Python 3.6 and lower don't support compresslevel
+ self.zip_file.writestr(entry_info, content)
+ if compresslevel != 6:
+ logging.warn("Custom compresslevel is not supported with python < 3.7")
+
def make_zipinfo(self, path: str, mode: str):
"""Create a Zipinfo.
@@ -134,17 +160,18 @@ class ZipWriter(object):
user = entry.user
group = entry.group
- # Use the pkg_tar mode/owner remaping as a fallback
+ # Use the pkg_tar mode/owner remapping as a fallback
dst_path = dest.strip('/')
if entry_type == manifest.ENTRY_IS_DIR and not dst_path.endswith('/'):
dst_path += '/'
entry_info = self.make_zipinfo(path=dst_path, mode=mode)
if entry_type == manifest.ENTRY_IS_FILE:
- entry_info.compress_type = zipfile.ZIP_DEFLATED
+ entry_info.compress_type = self.compression_type
# Using utf-8 for the file names is for python <3.7 compatibility.
+ entry_info.external_attr |= UNIX_FILE_BIT << 16
with open(src.encode('utf-8'), 'rb') as src_content:
- self.zip_file.writestr(entry_info, src_content.read())
+ self.writestr(entry_info, src_content.read(), compresslevel=self.compression_level)
elif entry_type == manifest.ENTRY_IS_DIR:
entry_info.compress_type = zipfile.ZIP_STORED
# Set directory bits
@@ -158,7 +185,7 @@ class ZipWriter(object):
elif entry_type == manifest.ENTRY_IS_TREE:
self.add_tree(src, dst_path, mode)
elif entry_type == manifest.ENTRY_IS_EMPTY_FILE:
- entry_info.compress_type = zipfile.ZIP_DEFLATED
+ entry_info.compress_type = zipfile.ZIP_STORED
self.zip_file.writestr(entry_info, '')
else:
raise Exception('Unknown type for manifest entry:', entry)
@@ -213,9 +240,9 @@ class ZipWriter(object):
else:
f_mode = mode
entry_info = self.make_zipinfo(path=path, mode=f_mode)
- entry_info.compress_type = zipfile.ZIP_DEFLATED
+ entry_info.compress_type = self.compression_type
with open(content_path, 'rb') as src:
- self.zip_file.writestr(entry_info, src.read())
+ self.writestr(entry_info, src.read(), compresslevel=self.compression_level)
else:
# Implicitly created directory
dir_path = path
@@ -251,6 +278,8 @@ def _load_manifest(prefix, manifest_path):
mode = "0o755",
user = None,
group = None,
+ uid = None,
+ gid = None,
origin = "parent directory of {}".format(manifest_map[dest].origin),
)
@@ -264,10 +293,11 @@ def main(args):
default_mode = None
if args.mode:
default_mode = int(args.mode, 8)
+ compression_level = int(args.compression_level)
manifest = _load_manifest(args.directory, args.manifest)
with ZipWriter(
- args.output, time_stamp=ts, default_mode=default_mode) as zip_out:
+ args.output, time_stamp=ts, default_mode=default_mode, compression_type=args.compression_type, compression_level=compression_level) as zip_out:
for entry in manifest:
zip_out.add_manifest_entry(entry)