Support compression_level when using xz (#988)

* Support compression_level when using xz. Fixes: #987
diff --git a/pkg/private/tar/tar_writer.py b/pkg/private/tar/tar_writer.py
index b81f6db..0dc33f6 100644
--- a/pkg/private/tar/tar_writer.py
+++ b/pkg/private/tar/tar_writer.py
@@ -84,16 +84,19 @@
 
     self.fileobj = None
     self.compressor_cmd = (compressor or '').strip()
+    extra_tar_args = {}
     if self.compressor_cmd:
       # Some custom command has been specified: no need for further
       # configuration, we're just going to use it.
       pass
     # Support xz compression through xz... until we can use Py3
     elif compression in ['xz', 'lzma']:
+      compression_level = min(compression_level, 9) if compression_level >= 0 else 6
       if HAS_LZMA:
         mode = 'w:xz'
+        extra_tar_args['preset'] = compression_level
       else:
-        self.compressor_cmd = 'xz -F {} -'.format(compression)
+        self.compressor_cmd = 'xz -F {} -{} -'.format(compression, compression_level)
     elif compression in ['bzip2', 'bz2']:
       mode = 'w:bz2'
     else:
@@ -114,7 +117,7 @@
     self.name = name
 
     self.tar = tarfile.open(name=name, mode=mode, fileobj=self.fileobj,
-                            format=tarfile.GNU_FORMAT)
+                            format=tarfile.GNU_FORMAT, **extra_tar_args)
     self.existing_members = {}
     self.create_parents = create_parents
     self.allow_dups_from_deps = allow_dups_from_deps
diff --git a/tests/tar/BUILD b/tests/tar/BUILD
index dec1006..4362e46 100644
--- a/tests/tar/BUILD
+++ b/tests/tar/BUILD
@@ -486,6 +486,10 @@
         ":test-tar-strip_prefix-substring.tar",
         ":test-tar-tree-artifact",
         ":test-tar-tree-artifact-noroot",
+        ":test-tar-xz-compression_level--1",
+        ":test-tar-xz-compression_level-3",
+        ":test-tar-xz-compression_level-6",
+        ":test-tar-xz-compression_level-9",
         ":test-tree-input-with-strip-prefix",
         ":test_tar_leading_dotslash",
         ":test_tar_package_dir_substitution.tar",
@@ -807,6 +811,20 @@
 ]]
 
 [pkg_tar(
+    name = "test-tar-xz-compression_level-%s" % compression_level,
+    compression_level = compression_level,
+    extension = "tar.xz",
+    deps = [
+        "//tests:testdata/tar_xz_test.tar",
+    ],
+) for compression_level in [
+    -1,
+    3,
+    6,
+    9,
+]]
+
+[pkg_tar(
     name = "test-tar-preserve_mode-%s" % state,
     srcs = [
         "//tests:testdata/hello.txt",  # rw- r-- r--
diff --git a/tests/tar/pkg_tar_test.py b/tests/tar/pkg_tar_test.py
index c3ba4f2..7923ab6 100644
--- a/tests/tar/pkg_tar_test.py
+++ b/tests/tar/pkg_tar_test.py
@@ -295,13 +295,17 @@
     self.assertTarFileContent('test-respect-externally-defined-duplicates.tar', content)
 
   def test_compression_level(self):
-    sizes = [
+    cases = [
       ('test-tar-compression_level--1.tgz', 179),
       ('test-tar-compression_level-3.tgz', 230),
       ('test-tar-compression_level-6.tgz', 178),
       ('test-tar-compression_level-9.tgz', 167),
+      ('test-tar-xz-compression_level--1.tar.xz', 67216),
+      ('test-tar-xz-compression_level-3.tar.xz', 67264),
+      ('test-tar-xz-compression_level-6.tar.xz', 67216),
+      ('test-tar-xz-compression_level-9.tar.xz', 67156),
     ]
-    for file_name, expected_size in sizes:
+    for file_name, expected_size in cases:
       file_path = runfiles.Create().Rlocation('rules_pkg/tests/tar/' + file_name)
       file_size = os.stat(file_path).st_size
       self.assertEqual(file_size, expected_size, 'size error for ' + file_name)
diff --git a/tests/testdata/tar_xz_test.tar b/tests/testdata/tar_xz_test.tar
new file mode 100644
index 0000000..692c672
--- /dev/null
+++ b/tests/testdata/tar_xz_test.tar
Binary files differ