Skip to content

Commit 03cbc6c

Browse files
authored
Make compression_level configurable for .tar.gz (#888)
1 parent 5047485 commit 03cbc6c

File tree

5 files changed

+49
-5
lines changed

5 files changed

+49
-5
lines changed

pkg/private/tar/build_tar.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ class TarFile(object):
4242
class DebError(Exception):
4343
pass
4444

45-
def __init__(self, output, directory, compression, compressor, create_parents, allow_dups_from_deps, default_mtime):
45+
def __init__(self, output, directory, compression, compressor, create_parents,
46+
allow_dups_from_deps, default_mtime, compression_level):
4647
# Directory prefix on all output paths
4748
d = directory.strip('/')
4849
self.directory = (d + '/') if d else None
@@ -52,6 +53,7 @@ def __init__(self, output, directory, compression, compressor, create_parents, a
5253
self.default_mtime = default_mtime
5354
self.create_parents = create_parents
5455
self.allow_dups_from_deps = allow_dups_from_deps
56+
self.compression_level = compression_level
5557

5658
def __enter__(self):
5759
self.tarfile = tar_writer.TarFileWriter(
@@ -60,7 +62,8 @@ def __enter__(self):
6062
self.compressor,
6163
self.create_parents,
6264
self.allow_dups_from_deps,
63-
default_mtime=self.default_mtime)
65+
default_mtime=self.default_mtime,
66+
compression_level=self.compression_level)
6467
return self
6568

6669
def __exit__(self, t, v, traceback):
@@ -397,6 +400,9 @@ def main():
397400
parser.add_argument('--allow_dups_from_deps',
398401
action='store_true',
399402
help='')
403+
parser.add_argument(
404+
'--compression_level', default=-1,
405+
help='Specify the numeric compress level in gzip mode; may be 0-9 or -1 (default to 6).')
400406
options = parser.parse_args()
401407

402408
# Parse modes arguments
@@ -440,6 +446,10 @@ def main():
440446
if options.stamp_from:
441447
default_mtime = build_info.get_timestamp(options.stamp_from)
442448

449+
compression_level = -1
450+
if options.compression_level:
451+
compression_level = int(options.compression_level)
452+
443453
# Add objects to the tar file
444454
with TarFile(
445455
options.output,
@@ -448,7 +458,8 @@ def main():
448458
compressor = options.compressor,
449459
default_mtime=default_mtime,
450460
create_parents=options.create_parents,
451-
allow_dups_from_deps=options.allow_dups_from_deps) as output:
461+
allow_dups_from_deps=options.allow_dups_from_deps,
462+
compression_level = compression_level) as output:
452463

453464
def file_attributes(filename):
454465
if filename.startswith('/'):

pkg/private/tar/tar.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ def _pkg_tar_impl(ctx):
114114
"--owner_names",
115115
"%s=%s" % (_quote(key), ctx.attr.ownernames[key]),
116116
)
117+
if ctx.attr.compression_level:
118+
args.add("--compression_level", ctx.attr.compression_level)
117119

118120
# Now we begin processing the files.
119121
path_mapper = None
@@ -272,6 +274,10 @@ pkg_tar_impl = rule(
272274
),
273275
"create_parents": attr.bool(default = True),
274276
"allow_duplicates_from_deps": attr.bool(default = False),
277+
"compression_level": attr.int(
278+
doc = """Specify the numeric compression level in gzip mode; may be 0-9 or -1 (default to 6).""",
279+
default = -1,
280+
),
275281

276282
# Common attributes
277283
"out": attr.output(mandatory = True),

pkg/private/tar/tar_writer.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ def __init__(self,
4949
create_parents=False,
5050
allow_dups_from_deps=True,
5151
default_mtime=None,
52-
preserve_tar_mtimes=True):
52+
preserve_tar_mtimes=True,
53+
compression_level=-1):
5354
"""TarFileWriter wraps tarfile.open().
5455
5556
Args:
@@ -86,10 +87,11 @@ def __init__(self,
8687
else:
8788
mode = 'w:'
8889
if compression in ['tgz', 'gz']:
90+
compression_level = min(compression_level, 9) if compression_level >= 0 else 6
8991
# The Tarfile class doesn't allow us to specify gzip's mtime attribute.
9092
# Instead, we manually reimplement gzopen from tarfile.py and set mtime.
9193
self.fileobj = gzip.GzipFile(
92-
filename=name, mode='w', compresslevel=6, mtime=self.default_mtime)
94+
filename=name, mode='w', compresslevel=compression_level, mtime=self.default_mtime)
9395
self.compressor_proc = None
9496
if self.compressor_cmd:
9597
mode = 'w|'

tests/tar/BUILD

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,10 @@ py_test(
477477
":test-tar-strip_prefix-substring.tar",
478478
":test-tar-tree-artifact",
479479
":test-tar-tree-artifact-noroot",
480+
":test-tar-compression_level--1",
481+
":test-tar-compression_level-3",
482+
":test-tar-compression_level-6",
483+
":test-tar-compression_level-9",
480484
":test-tree-input-with-strip-prefix",
481485
":test_tar_leading_dotslash",
482486
":test_tar_package_dir_substitution.tar",
@@ -756,3 +760,12 @@ verify_archive_test(
756760
],
757761
target = ":program_with_dir_runfiles_tar",
758762
)
763+
764+
[pkg_tar(
765+
name = "test-tar-compression_level-%s" % compression_level,
766+
compression_level = compression_level,
767+
deps = [
768+
"//tests:testdata/tar_test.tar",
769+
],
770+
extension = "tgz",
771+
) for compression_level in [-1, 3, 6, 9]]

tests/tar/pkg_tar_test.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414
"""Testing for pkg_tar."""
1515

16+
import os
1617
import tarfile
1718
import unittest
1819

@@ -293,6 +294,17 @@ def test_externally_defined_duplicate_structure(self):
293294
]
294295
self.assertTarFileContent('test-respect-externally-defined-duplicates.tar', content)
295296

297+
def test_compression_level(self):
298+
sizes = [
299+
('test-tar-compression_level--1.tgz', 179),
300+
('test-tar-compression_level-3.tgz', 230),
301+
('test-tar-compression_level-6.tgz', 178),
302+
('test-tar-compression_level-9.tgz', 167),
303+
]
304+
for file_name, expected_size in sizes:
305+
file_path = runfiles.Create().Rlocation('rules_pkg/tests/tar/' + file_name)
306+
file_size = os.stat(file_path).st_size
307+
self.assertEqual(file_size, expected_size, 'size error for ' + file_name)
296308

297309
if __name__ == '__main__':
298310
unittest.main()

0 commit comments

Comments
 (0)