summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Stringwell <stringwell@gmail.com>2024-03-21 15:04:19 +0100
committerGitHub <noreply@github.com>2024-03-21 10:04:19 -0400
commita0eb69a1f33109cea208fe64dcef390c74e6be53 (patch)
tree934c8b4f6ba3a37801f458f6182c8c3e71695ff7
parent20100ce9827e886f9107cbd2758c18e90af07e69 (diff)
downloadbazelbuild-rules_pkg-a0eb69a1f33109cea208fe64dcef390c74e6be53.tar.gz
Add support for no parent directory inference (#832) (#834)
Add feature as described in #832. RELNOTES: Automatic creation of parent directory specifications for paths with depth can be prevented in `pkg_tar` archives by setting `create_parents=False`.
-rwxr-xr-xdocs/latest.md3
-rw-r--r--pkg/private/tar/build_tar.py11
-rw-r--r--pkg/private/tar/tar.bzl4
-rw-r--r--pkg/private/tar/tar_writer.py22
-rw-r--r--tests/tar/tar_writer_test.py19
5 files changed, 44 insertions, 15 deletions
diff --git a/docs/latest.md b/docs/latest.md
index eea6982..c0c9822 100755
--- a/docs/latest.md
+++ b/docs/latest.md
@@ -287,7 +287,7 @@ pkg_tar(<a href="#pkg_tar-name">name</a>, <a href="#pkg_tar-allow_duplicates_wit
<a href="#pkg_tar-empty_dirs">empty_dirs</a>, <a href="#pkg_tar-empty_files">empty_files</a>, <a href="#pkg_tar-extension">extension</a>, <a href="#pkg_tar-files">files</a>, <a href="#pkg_tar-include_runfiles">include_runfiles</a>, <a href="#pkg_tar-mode">mode</a>, <a href="#pkg_tar-modes">modes</a>, <a href="#pkg_tar-mtime">mtime</a>, <a href="#pkg_tar-out">out</a>,
<a href="#pkg_tar-owner">owner</a>, <a href="#pkg_tar-ownername">ownername</a>, <a href="#pkg_tar-ownernames">ownernames</a>, <a href="#pkg_tar-owners">owners</a>, <a href="#pkg_tar-package_dir">package_dir</a>, <a href="#pkg_tar-package_dir_file">package_dir_file</a>, <a href="#pkg_tar-package_file_name">package_file_name</a>,
<a href="#pkg_tar-package_variables">package_variables</a>, <a href="#pkg_tar-portable_mtime">portable_mtime</a>, <a href="#pkg_tar-private_stamp_detect">private_stamp_detect</a>, <a href="#pkg_tar-remap_paths">remap_paths</a>, <a href="#pkg_tar-srcs">srcs</a>, <a href="#pkg_tar-stamp">stamp</a>,
- <a href="#pkg_tar-strip_prefix">strip_prefix</a>, <a href="#pkg_tar-symlinks">symlinks</a>)
+ <a href="#pkg_tar-strip_prefix">strip_prefix</a>, <a href="#pkg_tar-symlinks">symlinks</a>, <a href="#pkg_tar-create_parents">symlinks</a>)
</pre>
@@ -326,6 +326,7 @@ pkg_tar(<a href="#pkg_tar-name">name</a>, <a href="#pkg_tar-allow_duplicates_wit
| <a id="pkg_tar-stamp"></a>stamp | Enable file time stamping. Possible values: <li>stamp = 1: Use the time of the build as the modification time of each file in the archive. <li>stamp = 0: Use an "epoch" time for the modification time of each file. This gives good build result caching. <li>stamp = -1: Control the chosen modification time using the --[no]stamp flag. <div class="since"><i>Since 0.5.0</i></div> | Integer | optional | 0 |
| <a id="pkg_tar-strip_prefix"></a>strip_prefix | (note: Use strip_prefix = "." to strip path to the package but preserve relative paths of sub directories beneath the package.) | String | optional | "" |
| <a id="pkg_tar-symlinks"></a>symlinks | - | <a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a> | optional | {} |
+| <a id="pkg_tar-create_parents"></a>create_parents | Implicitly create parent directories with default permissions for file paths where parent directories are not specified. | Boolean | optional | True |
diff --git a/pkg/private/tar/build_tar.py b/pkg/private/tar/build_tar.py
index f4b9f0d..81ad03f 100644
--- a/pkg/private/tar/build_tar.py
+++ b/pkg/private/tar/build_tar.py
@@ -42,7 +42,7 @@ class TarFile(object):
class DebError(Exception):
pass
- def __init__(self, output, directory, compression, compressor, default_mtime):
+ def __init__(self, output, directory, compression, compressor, create_parents, default_mtime):
# Directory prefix on all output paths
d = directory.strip('/')
self.directory = (d + '/') if d else None
@@ -50,12 +50,14 @@ class TarFile(object):
self.compression = compression
self.compressor = compressor
self.default_mtime = default_mtime
+ self.create_parents = create_parents
def __enter__(self):
self.tarfile = tar_writer.TarFileWriter(
self.output,
self.compression,
self.compressor,
+ self.create_parents,
default_mtime=self.default_mtime)
return self
@@ -383,6 +385,10 @@ def main():
'path/to/file=root.root.')
parser.add_argument('--stamp_from', default='',
help='File to find BUILD_STAMP in')
+ parser.add_argument('--create_parents',
+ action='store_true',
+ help='Automatically creates parent directories implied by a'
+ ' prefix if they do not exist')
options = parser.parse_args()
# Parse modes arguments
@@ -432,7 +438,8 @@ def main():
directory = helpers.GetFlagValue(options.directory),
compression = options.compression,
compressor = options.compressor,
- default_mtime=default_mtime) as output:
+ default_mtime=default_mtime,
+ create_parents=options.create_parents) as output:
def file_attributes(filename):
if filename.startswith('/'):
diff --git a/pkg/private/tar/tar.bzl b/pkg/private/tar/tar.bzl
index 963cb5a..8bea9fb 100644
--- a/pkg/private/tar/tar.bzl
+++ b/pkg/private/tar/tar.bzl
@@ -173,6 +173,9 @@ def _pkg_tar_impl(ctx):
args.set_param_file_format("flag_per_line")
args.use_param_file("@%s", use_always = False)
+ if ctx.attr.create_parents:
+ args.add("--create_parents")
+
inputs = depset(
direct = ctx.files.deps + files,
transitive = mapping_context.file_deps,
@@ -264,6 +267,7 @@ pkg_tar_impl = rule(
"compressor_args": attr.string(
doc = """Arg list for `compressor`.""",
),
+ "create_parents": attr.bool(default = True),
# Common attributes
"out": attr.output(mandatory = True),
diff --git a/pkg/private/tar/tar_writer.py b/pkg/private/tar/tar_writer.py
index 325db76..957ce45 100644
--- a/pkg/private/tar/tar_writer.py
+++ b/pkg/private/tar/tar_writer.py
@@ -46,6 +46,7 @@ class TarFileWriter(object):
name,
compression='',
compressor='',
+ create_parents=False,
default_mtime=None,
preserve_tar_mtimes=True):
"""TarFileWriter wraps tarfile.open().
@@ -106,6 +107,7 @@ class TarFileWriter(object):
# we can adjust that here based on the setting of root_dirctory.
self.directories.add('/')
self.directories.add('./')
+ self.create_parents = create_parents
def __enter__(self):
return self
@@ -219,7 +221,8 @@ class TarFileWriter(object):
mtime = self.default_mtime
# Make directories up the file
- self.add_parents(name, mtime=mtime, mode=0o755, uid=uid, gid=gid, uname=uname, gname=gname)
+ if self.create_parents:
+ self.add_parents(name, mtime=mtime, mode=0o755, uid=uid, gid=gid, uname=uname, gname=gname)
tarinfo = tarfile.TarInfo(name)
tarinfo.mtime = mtime
@@ -291,14 +294,15 @@ class TarFileWriter(object):
if prefix:
in_name = os.path.normpath(prefix + in_name).replace(os.path.sep, '/')
tarinfo.name = in_name
- self.add_parents(
- path=tarinfo.name,
- mtime=tarinfo.mtime,
- mode=0o755,
- uid=tarinfo.uid,
- gid=tarinfo.gid,
- uname=tarinfo.uname,
- gname=tarinfo.gname)
+ if self.create_parents:
+ self.add_parents(
+ path=tarinfo.name,
+ mtime=tarinfo.mtime,
+ mode=0o755,
+ uid=tarinfo.uid,
+ gid=tarinfo.gid,
+ uname=tarinfo.uname,
+ gname=tarinfo.gname)
if prefix is not None:
# Relocate internal hardlinks as well to avoid breaking them.
diff --git a/tests/tar/tar_writer_test.py b/tests/tar/tar_writer_test.py
index ad31b0c..8503d31 100644
--- a/tests/tar/tar_writer_test.py
+++ b/tests/tar/tar_writer_test.py
@@ -138,7 +138,7 @@ class TarFileWriterTest(unittest.TestCase):
{"name": "foo/a", "data": b"a"},
{"name": "foo/ab", "data": b"ab"},
]
- with tar_writer.TarFileWriter(self.tempfile) as f:
+ with tar_writer.TarFileWriter(self.tempfile, create_parents=True) as f:
datafile = self.data_files.Rlocation(
"rules_pkg/tests/testdata/tar_test.tar")
f.add_tar(datafile, name_filter=lambda n: n != "./b", prefix="foo")
@@ -176,7 +176,7 @@ class TarFileWriterTest(unittest.TestCase):
self.assertEqual(output_file.mtime, 0)
def testAddingDirectoriesForFile(self):
- with tar_writer.TarFileWriter(self.tempfile) as f:
+ with tar_writer.TarFileWriter(self.tempfile, create_parents=True) as f:
f.add_file("d/f")
content = [
{"name": "d", "mode": 0o755},
@@ -185,7 +185,7 @@ class TarFileWriterTest(unittest.TestCase):
self.assertTarFileContent(self.tempfile, content)
def testAddingDirectoriesForFileManually(self):
- with tar_writer.TarFileWriter(self.tempfile) as f:
+ with tar_writer.TarFileWriter(self.tempfile, create_parents=True) as f:
f.add_file("d", tarfile.DIRTYPE)
f.add_file("d/f")
@@ -210,6 +210,19 @@ class TarFileWriterTest(unittest.TestCase):
]
self.assertTarFileContent(self.tempfile, content)
+ def testAddingOnlySpecifiedFiles(self):
+ with tar_writer.TarFileWriter(self.tempfile) as f:
+ f.add_file("a", tarfile.DIRTYPE)
+ f.add_file("a/b", tarfile.DIRTYPE)
+ f.add_file("a/b/", tarfile.DIRTYPE)
+ f.add_file("a/b/c/f")
+ content = [
+ {"name": "a", "mode": 0o755},
+ {"name": "a/b", "mode": 0o755},
+ {"name": "a/b/c/f"},
+ ]
+ self.assertTarFileContent(self.tempfile, content)
+
def testPackageDirAttribute(self):
"""Tests package_dir of pkg_tar."""
package_dir = self.data_files.Rlocation(