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`.
This commit is contained in:
Erik Stringwell 2024-03-21 15:04:19 +01:00 committed by GitHub
parent 20100ce982
commit a0eb69a1f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 44 additions and 15 deletions

View File

@ -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 |

View File

@ -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('/'):

View File

@ -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),

View File

@ -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.

View File

@ -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(