Skip to content

Commit eb6ba24

Browse files
committed
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. This attempts to maintain the previous behavior of intermediate dirs being 0o775, unless a custom mode is passed to override it.
1 parent 4b1d677 commit eb6ba24

File tree

3 files changed

+52
-18
lines changed

3 files changed

+52
-18
lines changed

pkg/private/tar/build_tar.py

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def add_deb(self, deb):
218218
self.add_tar(tmpfile[1])
219219
os.remove(tmpfile[1])
220220

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

275275
for path in sorted(to_write.keys()):
276+
if file_attributes:
277+
attrs = file_attributes(path, with_default_mode=False)
278+
use_ids = attrs.get("ids")
279+
use_names = attrs.get("names")
280+
# in this case, use_mode will be None and mode (as passed into this
281+
# function) will be the default_mode.
282+
use_mode = attrs.get("mode")
283+
else:
284+
use_ids = ids
285+
use_names = names
286+
use_mode = mode
287+
276288
content_path = to_write[path]
277289
if not content_path:
278290
# This is an intermediate directory. Bazel has no API to specify modes
279291
# for this, so the least surprising thing we can do is make it the
280-
# canonical rwxr-xr-x
292+
# canonical rwxr-xr-x unless we've gotten a custom override
293+
if use_mode is None:
294+
if mode is not None:
295+
use_mode = 0o755
296+
else:
297+
# mode is intended as a default file mode, which means it
298+
# probably won't have +x for a directory; set +rx on every
299+
# piece that also has +r
300+
use_mode = mode
301+
if use_mode & 0o400:
302+
use_mode |= 0o100
303+
if use_mode & 0o040:
304+
use_mode |= 0o010
305+
if use_mode & 0o004:
306+
use_mode |= 0o004
307+
281308
self.add_empty_file(
282309
path,
283-
mode=0o755,
284-
ids=ids,
285-
names=names,
310+
mode=use_mode,
311+
ids=use_ids,
312+
names=use_names,
286313
kind=tarfile.DIRTYPE)
287314
else:
288315
# If mode is unspecified, derive the mode from the file's mode.
289-
if mode is None:
290-
f_mode = 0o755 if os.access(content_path, os.X_OK) else 0o644
291-
else:
292-
f_mode = mode
316+
if use_mode is None:
317+
use_mode = mode
318+
if use_mode is None:
319+
use_mode = 0o755 if os.access(content_path, os.X_OK) else 0o644
320+
293321
self.tarfile.add_file(
294322
path,
295323
file_content=content_path,
296-
mode=f_mode,
297-
uid=ids[0],
298-
gid=ids[1],
299-
uname=names[0],
300-
gname=names[1])
324+
mode=use_mode,
325+
uid=use_ids[0],
326+
gid=use_ids[1],
327+
uname=use_names[0],
328+
gname=use_names[1])
301329

302330
def add_manifest_entry(self, entry, file_attributes):
303331
# Use the pkg_tar mode/owner remapping as a fallback
@@ -325,7 +353,7 @@ def add_manifest_entry(self, entry, file_attributes):
325353
elif entry.type == manifest.ENTRY_IS_DIR:
326354
self.add_empty_dir(self.normalize_path(entry.dest), **attrs)
327355
elif entry.type == manifest.ENTRY_IS_TREE:
328-
self.add_tree(entry.src, entry.dest, **attrs)
356+
self.add_tree(entry.src, entry.dest, file_attributes, **attrs)
329357
elif entry.type == manifest.ENTRY_IS_EMPTY_FILE:
330358
self.add_empty_file(self.normalize_path(entry.dest), **attrs)
331359
else:
@@ -434,11 +462,11 @@ def main():
434462
compressor = options.compressor,
435463
default_mtime=default_mtime) as output:
436464

437-
def file_attributes(filename):
465+
def file_attributes(filename, with_default_mode=True):
438466
if filename.startswith('/'):
439467
filename = filename[1:]
440468
return {
441-
'mode': mode_map.get(filename, default_mode),
469+
'mode': mode_map.get(filename, default_mode if with_default_mode else None),
442470
'ids': ids_map.get(filename, default_ids),
443471
'names': names_map.get(filename, default_ownername),
444472
}

tests/tar/BUILD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,9 @@ pkg_tar(
301301
":generate_tree",
302302
"//tests:loremipsum_txt",
303303
],
304+
modes = {
305+
"a_tree/generate_tree/b/c": "0777",
306+
},
304307
package_dir = "a_tree",
305308
)
306309

@@ -318,6 +321,9 @@ pkg_tar(
318321
":tree_noroot",
319322
"//tests:loremipsum_txt",
320323
],
324+
modes = {
325+
"a_tree/b/c": "0777",
326+
},
321327
package_dir = "a_tree",
322328
)
323329

tests/tar/pkg_tar_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ def test_tar_with_tree_artifact(self):
227227
{'name': 'a_tree/generate_tree/a/b', 'isdir': True, 'mode': 0o755},
228228
{'name': 'a_tree/generate_tree/a/b/c'},
229229
{'name': 'a_tree/generate_tree/b', 'isdir': True, 'mode': 0o755},
230-
{'name': 'a_tree/generate_tree/b/c', 'isdir': True, 'mode': 0o755},
230+
{'name': 'a_tree/generate_tree/b/c', 'isdir': True, 'mode': 0o777},
231231
{'name': 'a_tree/generate_tree/b/c/d'},
232232
{'name': 'a_tree/generate_tree/b/d'},
233233
{'name': 'a_tree/generate_tree/b/e'},

0 commit comments

Comments
 (0)