Bug 1260241 - Pre: Add compress option to Jarrer.add. r?glandium
This required handling Deflater instances with different compression
options in JarWriter, which in turn required exposing the uncompressed
data in Deflater.
MozReview-Commit-ID: FWXeBOi9FTY
--- a/python/mozbuild/mozpack/copier.py
+++ b/python/mozbuild/mozpack/copier.py
@@ -479,18 +479,24 @@ class Jarrer(FileRegistry, BaseFile):
def __init__(self, compress=True, optimize=True):
'''
Create a Jarrer instance. See mozpack.mozjar.JarWriter documentation
for details on the compress and optimize arguments.
'''
self.compress = compress
self.optimize = optimize
self._preload = []
+ self._compress_options = {} # Map path to compress boolean option.
FileRegistry.__init__(self)
+ def add(self, path, content, compress=None):
+ FileRegistry.add(self, path, content)
+ if compress is not None:
+ self._compress_options[path] = compress
+
def copy(self, dest, skip_if_older=True):
'''
Pack all registered files in the given destination jar. The given
destination jar may be a path to jar file, or a Dest instance for
a jar file.
If the destination jar file exists, its (compressed) contents are used
instead of the registered BaseFile instances when appropriate.
'''
@@ -535,22 +541,26 @@ class Jarrer(FileRegistry, BaseFile):
except Exception:
old_jar = []
old_contents = dict([(f.filename, f) for f in old_jar])
with JarWriter(fileobj=dest, compress=self.compress,
optimize=self.optimize) as jar:
for path, file in self:
+ compress = self._compress_options.get(path, None)
+ if compress is None:
+ compress = self.compress
+
if path in old_contents:
- deflater = DeflaterDest(old_contents[path], self.compress)
+ deflater = DeflaterDest(old_contents[path], compress)
else:
- deflater = DeflaterDest(compress=self.compress)
+ deflater = DeflaterDest(compress=compress)
file.copy(deflater, skip_if_older)
- jar.add(path, deflater.deflater, mode=file.mode)
+ jar.add(path, deflater.deflater, mode=file.mode, compress=compress)
if self._preload:
jar.preload(self._preload)
def open(self):
raise RuntimeError('unsupported')
def preload(self, paths):
'''
--- a/python/mozbuild/mozpack/mozjar.py
+++ b/python/mozbuild/mozpack/mozjar.py
@@ -594,16 +594,19 @@ class JarWriter(object):
compress = self._compress
if (isinstance(data, JarFileReader) and data.compressed == compress) \
or (isinstance(data, Deflater) and data.compress == compress):
deflater = data
else:
deflater = Deflater(compress, compress_level=self._compress_level)
if isinstance(data, basestring):
deflater.write(data)
+ elif isinstance(data, Deflater):
+ # A Deflator, but with a different compression option.
+ deflater.write(data.uncompressed_data)
elif hasattr(data, 'read'):
if hasattr(data, 'seek'):
data.seek(0)
deflater.write(data.read())
else:
raise JarWriterError("Don't know how to handle %s" %
type(data))
# Fill a central directory entry for this new member.
@@ -751,16 +754,23 @@ class Deflater(object):
Return the compressed data, if the data should be compressed (real
compressed size smaller than the uncompressed size), or the
uncompressed data otherwise.
'''
if self.compressed:
return self._deflated.getvalue()
return self._data.getvalue()
+ @property
+ def uncompressed_data(self):
+ '''
+ Return the uncompressed data.
+ '''
+ return self._data.getvalue()
+
class JarLog(dict):
'''
Helper to read the file Gecko generates when setting MOZ_JAR_LOG_FILE.
The jar log is then available as a dict with the jar path as key (see
canonicalize for more details on the key value), and the corresponding
access log as a list value. Only the first access to a given member of
a jar is stored.
--- a/python/mozbuild/mozpack/test/test_copier.py
+++ b/python/mozbuild/mozpack/test/test_copier.py
@@ -504,10 +504,26 @@ class TestJarrer(unittest.TestCase):
copier.copy(dest)
dest.seek(0)
jar = JarReader(fileobj=dest)
self.assertEqual([f.filename for f in jar], preloaded +
[p for p in copier.paths() if not p in preloaded])
self.assertEqual(jar.last_preloaded, preloaded[-1])
+
+ def test_jarrer_compress(self):
+ copier = Jarrer()
+ copier.add('foo/bar', GeneratedFile('ffffff'))
+ copier.add('foo/qux', GeneratedFile('ffffff'), compress=False)
+
+ dest = MockDest()
+ copier.copy(dest)
+ self.check_jar(dest, copier)
+
+ dest.seek(0)
+ jar = JarReader(fileobj=dest)
+ self.assertTrue(jar['foo/bar'].compressed)
+ self.assertFalse(jar['foo/qux'].compressed)
+
+
if __name__ == '__main__':
mozunit.main()