Skip to content

Commit

Permalink
pkg_tar: load attributes for TreeArtifacts
Browse files Browse the repository at this point in the history
This change teaches pkg_tar to reinvoke file_attributes for each
individual file in a TreeArtifact; this function is used to load the
attributes passed via pkg_tar arguments (like `mode`). Before this
change, there's no way to set individual attributes for files in a
TreeArtifact.

This attempts to maintain the previous behavior of intermediate dirs
being 0o775, unless a custom mode is passed to override it.
  • Loading branch information
novas0x2a committed Nov 28, 2023
1 parent 4b1d677 commit eb6ba24
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 18 deletions.
62 changes: 45 additions & 17 deletions pkg/private/tar/build_tar.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def add_deb(self, deb):
self.add_tar(tmpfile[1])
os.remove(tmpfile[1])

def add_tree(self, tree_top, destpath, mode=None, ids=None, names=None):
def add_tree(self, tree_top, destpath, file_attributes, mode=None, ids=None, names=None):
"""Add a tree artifact to the tar file.
Args:
Expand Down Expand Up @@ -273,31 +273,59 @@ def add_tree(self, tree_top, destpath, mode=None, ids=None, names=None):
to_write[dest_dir + file] = content_path

for path in sorted(to_write.keys()):
if file_attributes:
attrs = file_attributes(path, with_default_mode=False)
use_ids = attrs.get("ids")
use_names = attrs.get("names")
# in this case, use_mode will be None and mode (as passed into this
# function) will be the default_mode.
use_mode = attrs.get("mode")
else:
use_ids = ids
use_names = names
use_mode = mode

content_path = to_write[path]
if not content_path:
# This is an intermediate directory. Bazel has no API to specify modes
# for this, so the least surprising thing we can do is make it the
# canonical rwxr-xr-x
# canonical rwxr-xr-x unless we've gotten a custom override
if use_mode is None:
if mode is not None:
use_mode = 0o755
else:
# mode is intended as a default file mode, which means it
# probably won't have +x for a directory; set +rx on every
# piece that also has +r
use_mode = mode
if use_mode & 0o400:
use_mode |= 0o100
if use_mode & 0o040:
use_mode |= 0o010
if use_mode & 0o004:
use_mode |= 0o004

self.add_empty_file(
path,
mode=0o755,
ids=ids,
names=names,
mode=use_mode,
ids=use_ids,
names=use_names,
kind=tarfile.DIRTYPE)
else:
# If mode is unspecified, derive the mode from the file's mode.
if mode is None:
f_mode = 0o755 if os.access(content_path, os.X_OK) else 0o644
else:
f_mode = mode
if use_mode is None:
use_mode = mode
if use_mode is None:
use_mode = 0o755 if os.access(content_path, os.X_OK) else 0o644

self.tarfile.add_file(
path,
file_content=content_path,
mode=f_mode,
uid=ids[0],
gid=ids[1],
uname=names[0],
gname=names[1])
mode=use_mode,
uid=use_ids[0],
gid=use_ids[1],
uname=use_names[0],
gname=use_names[1])

def add_manifest_entry(self, entry, file_attributes):
# Use the pkg_tar mode/owner remapping as a fallback
Expand Down Expand Up @@ -325,7 +353,7 @@ def add_manifest_entry(self, entry, file_attributes):
elif entry.type == manifest.ENTRY_IS_DIR:
self.add_empty_dir(self.normalize_path(entry.dest), **attrs)
elif entry.type == manifest.ENTRY_IS_TREE:
self.add_tree(entry.src, entry.dest, **attrs)
self.add_tree(entry.src, entry.dest, file_attributes, **attrs)
elif entry.type == manifest.ENTRY_IS_EMPTY_FILE:
self.add_empty_file(self.normalize_path(entry.dest), **attrs)
else:
Expand Down Expand Up @@ -434,11 +462,11 @@ def main():
compressor = options.compressor,
default_mtime=default_mtime) as output:

def file_attributes(filename):
def file_attributes(filename, with_default_mode=True):
if filename.startswith('/'):
filename = filename[1:]
return {
'mode': mode_map.get(filename, default_mode),
'mode': mode_map.get(filename, default_mode if with_default_mode else None),
'ids': ids_map.get(filename, default_ids),
'names': names_map.get(filename, default_ownername),
}
Expand Down
6 changes: 6 additions & 0 deletions tests/tar/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ pkg_tar(
":generate_tree",
"//tests:loremipsum_txt",
],
modes = {
"a_tree/generate_tree/b/c": "0777",
},
package_dir = "a_tree",
)

Expand All @@ -318,6 +321,9 @@ pkg_tar(
":tree_noroot",
"//tests:loremipsum_txt",
],
modes = {
"a_tree/b/c": "0777",
},
package_dir = "a_tree",
)

Expand Down
2 changes: 1 addition & 1 deletion tests/tar/pkg_tar_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def test_tar_with_tree_artifact(self):
{'name': 'a_tree/generate_tree/a/b', 'isdir': True, 'mode': 0o755},
{'name': 'a_tree/generate_tree/a/b/c'},
{'name': 'a_tree/generate_tree/b', 'isdir': True, 'mode': 0o755},
{'name': 'a_tree/generate_tree/b/c', 'isdir': True, 'mode': 0o755},
{'name': 'a_tree/generate_tree/b/c', 'isdir': True, 'mode': 0o777},
{'name': 'a_tree/generate_tree/b/c/d'},
{'name': 'a_tree/generate_tree/b/d'},
{'name': 'a_tree/generate_tree/b/e'},
Expand Down

0 comments on commit eb6ba24

Please sign in to comment.