@@ -218,7 +218,7 @@ def add_deb(self, deb):
218
218
self .add_tar (tmpfile [1 ])
219
219
os .remove (tmpfile [1 ])
220
220
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 ):
222
222
"""Add a tree artifact to the tar file.
223
223
224
224
Args:
@@ -273,31 +273,59 @@ def add_tree(self, tree_top, destpath, mode=None, ids=None, names=None):
273
273
to_write [dest_dir + file ] = content_path
274
274
275
275
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
+
276
288
content_path = to_write [path ]
277
289
if not content_path :
278
290
# This is an intermediate directory. Bazel has no API to specify modes
279
291
# 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
+
281
308
self .add_empty_file (
282
309
path ,
283
- mode = 0o755 ,
284
- ids = ids ,
285
- names = names ,
310
+ mode = use_mode ,
311
+ ids = use_ids ,
312
+ names = use_names ,
286
313
kind = tarfile .DIRTYPE )
287
314
else :
288
315
# 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
+
293
321
self .tarfile .add_file (
294
322
path ,
295
323
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 ])
301
329
302
330
def add_manifest_entry (self , entry , file_attributes ):
303
331
# Use the pkg_tar mode/owner remapping as a fallback
@@ -325,7 +353,7 @@ def add_manifest_entry(self, entry, file_attributes):
325
353
elif entry .type == manifest .ENTRY_IS_DIR :
326
354
self .add_empty_dir (self .normalize_path (entry .dest ), ** attrs )
327
355
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 )
329
357
elif entry .type == manifest .ENTRY_IS_EMPTY_FILE :
330
358
self .add_empty_file (self .normalize_path (entry .dest ), ** attrs )
331
359
else :
@@ -434,11 +462,11 @@ def main():
434
462
compressor = options .compressor ,
435
463
default_mtime = default_mtime ) as output :
436
464
437
- def file_attributes (filename ):
465
+ def file_attributes (filename , with_default_mode = True ):
438
466
if filename .startswith ('/' ):
439
467
filename = filename [1 :]
440
468
return {
441
- 'mode' : mode_map .get (filename , default_mode ),
469
+ 'mode' : mode_map .get (filename , default_mode if with_default_mode else None ),
442
470
'ids' : ids_map .get (filename , default_ids ),
443
471
'names' : names_map .get (filename , default_ownername ),
444
472
}
0 commit comments