@@ -377,6 +377,9 @@ pub(crate) fn copy_directory(
377377 // The directory we were in during the previous iteration
378378 let mut last_iter: Option < DirEntry > = None ;
379379
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+
380383 // Traverse the contents of the directory, copying each one.
381384 for direntry_result in WalkDir :: new ( root)
382385 . same_file_system ( options. one_file_system )
@@ -408,6 +411,14 @@ pub(crate) fn copy_directory(
408411 // `./a/b/c` into `./a/`, in which case we'll need to fix the
409412 // permissions of both `./a/b/c` and `./a/b`, in that order.)
410413 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+
411422 // If true, last_iter is not a parent of this iter.
412423 // The means we just exited a directory.
413424 let went_up = if let Some ( last_iter) = & last_iter {
@@ -452,25 +463,10 @@ pub(crate) fn copy_directory(
452463 }
453464 }
454465
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 ) ?;
474470 }
475471
476472 // Also fix permissions for parent directories,
0 commit comments