@@ -377,6 +377,9 @@ pub(crate) fn copy_directory(
377
377
// The directory we were in during the previous iteration
378
378
let mut last_iter: Option < DirEntry > = None ;
379
379
380
+ // Keep track of all directories we've created that need permission fixes
381
+ let mut dirs_needing_permissions: Vec < ( PathBuf , PathBuf ) > = Vec :: new ( ) ;
382
+
380
383
// Traverse the contents of the directory, copying each one.
381
384
for direntry_result in WalkDir :: new ( root)
382
385
. same_file_system ( options. one_file_system )
@@ -408,6 +411,14 @@ pub(crate) fn copy_directory(
408
411
// `./a/b/c` into `./a/`, in which case we'll need to fix the
409
412
// permissions of both `./a/b/c` and `./a/b`, in that order.)
410
413
if direntry. file_type ( ) . is_dir ( ) {
414
+ // Add this directory to our list for permission fixing later
415
+ let entry_for_tracking =
416
+ Entry :: new ( & context, direntry. path ( ) , options. no_target_dir ) ?;
417
+ dirs_needing_permissions. push ( (
418
+ entry_for_tracking. source_absolute ,
419
+ entry_for_tracking. local_to_target ,
420
+ ) ) ;
421
+
411
422
// If true, last_iter is not a parent of this iter.
412
423
// The means we just exited a directory.
413
424
let went_up = if let Some ( last_iter) = & last_iter {
@@ -452,25 +463,10 @@ pub(crate) fn copy_directory(
452
463
}
453
464
}
454
465
455
- // Handle final directory permission fixes.
456
- // This is almost the same as the permission-fixing code above,
457
- // with minor differences (commented)
458
- if let Some ( last_iter) = last_iter {
459
- let diff = last_iter. path ( ) . strip_prefix ( root) . unwrap ( ) ;
460
-
461
- // Do _not_ skip `.` this time, since we know we're done.
462
- // This is where we fix the permissions of the top-level
463
- // directory we just copied.
464
- for p in diff. ancestors ( ) {
465
- let src = root. join ( p) ;
466
- let entry = Entry :: new ( & context, & src, options. no_target_dir ) ?;
467
-
468
- copy_attributes (
469
- & entry. source_absolute ,
470
- & entry. local_to_target ,
471
- & options. attributes ,
472
- ) ?;
473
- }
466
+ // Fix permissions for all directories we created
467
+ // This ensures that even sibling directories get their permissions fixed
468
+ for ( source_path, dest_path) in dirs_needing_permissions {
469
+ copy_attributes ( & source_path, & dest_path, & options. attributes ) ?;
474
470
}
475
471
476
472
// Also fix permissions for parent directories,
0 commit comments