@@ -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 }
0 commit comments