From e0b8c7c2a906fd1be2e7c7f20db64a10d22d62ce Mon Sep 17 00:00:00 2001 From: Mike Lundy Date: Mon, 27 Nov 2023 15:40:49 -0800 Subject: [PATCH] pkg_tar: load attributes for TreeArtifacts 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. NOTE: This is actually a breaking change, because previously all intermediate directories were automatically 0o755, and now they will obey the global defaults. --- pkg/private/tar/build_tar.py | 39 +++++++++++++++++++++++------------- tests/tar/pkg_tar_test.py | 8 ++++---- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/pkg/private/tar/build_tar.py b/pkg/private/tar/build_tar.py index 08a3a06a..2f192afb 100644 --- a/pkg/private/tar/build_tar.py +++ b/pkg/private/tar/build_tar.py @@ -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: @@ -273,31 +273,42 @@ 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) + use_ids = attrs.get("ids") + use_names = attrs.get("names") + 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 + if use_mode is None: + use_mode = 0o755 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 = 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 @@ -325,7 +336,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: diff --git a/tests/tar/pkg_tar_test.py b/tests/tar/pkg_tar_test.py index 3bf1254b..db04e263 100644 --- a/tests/tar/pkg_tar_test.py +++ b/tests/tar/pkg_tar_test.py @@ -222,12 +222,12 @@ def test_tar_with_tree_artifact(self): content = [ {'name': 'a_tree', 'isdir': True}, {'name': 'a_tree/generate_tree', 'isdir': True, 'mode': 0o755}, - {'name': 'a_tree/generate_tree/a', 'isdir': True, 'mode': 0o755}, + {'name': 'a_tree/generate_tree/a', 'isdir': True, 'mode': 0o555}, {'name': 'a_tree/generate_tree/a/a'}, - {'name': 'a_tree/generate_tree/a/b', 'isdir': True, 'mode': 0o755}, + {'name': 'a_tree/generate_tree/a/b', 'isdir': True, 'mode': 0o555}, {'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', 'isdir': True, 'mode': 0o555}, + {'name': 'a_tree/generate_tree/b/c', 'isdir': True, 'mode': 0o555}, {'name': 'a_tree/generate_tree/b/c/d'}, {'name': 'a_tree/generate_tree/b/d'}, {'name': 'a_tree/generate_tree/b/e'},