Skip to content

Commit 76df3f5

Browse files
authored
cp: improve code clarity and remove redundant filesystem checks (#10790)
1 parent eccd157 commit 76df3f5

2 files changed

Lines changed: 27 additions & 12 deletions

File tree

src/uu/cp/src/copydir.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ use crate::{
3131
copy_file,
3232
};
3333

34+
/// Represents a directory that needs permission fixup after copying its contents.
35+
struct DirNeedingPermissions {
36+
/// Absolute path to the source directory
37+
source: PathBuf,
38+
/// Path to the destination directory
39+
dest: PathBuf,
40+
/// Whether this directory was freshly created by the copy operation
41+
was_created: bool,
42+
}
43+
3444
/// Ensure a Windows path starts with a `\\?`.
3545
#[cfg(target_os = "windows")]
3646
fn adjust_canonicalization(p: &Path) -> Cow<'_, Path> {
@@ -237,7 +247,12 @@ impl Entry {
237247

238248
#[allow(clippy::too_many_arguments)]
239249
/// Copy a single entry during a directory traversal.
240-
/// Returns a bool value indicating whether this function created a directory or not
250+
///
251+
/// # Returns
252+
///
253+
/// Returns `Ok(true)` if this function created a new directory, `Ok(false)` otherwise.
254+
/// This information is used to determine whether default directory permissions should
255+
/// be preserved during attribute copying.
241256
fn copy_direntry(
242257
progress_bar: Option<&ProgressBar>,
243258
entry: &Entry,
@@ -422,7 +437,7 @@ pub(crate) fn copy_directory(
422437
let mut last_iter: Option<DirEntry> = None;
423438

424439
// Keep track of all directories we've created that need permission fixes
425-
let mut dirs_needing_permissions: Vec<(PathBuf, PathBuf, bool)> = Vec::new();
440+
let mut dirs_needing_permissions: Vec<DirNeedingPermissions> = Vec::new();
426441

427442
// Traverse the contents of the directory, copying each one.
428443
for direntry_result in WalkDir::new(root)
@@ -481,11 +496,11 @@ pub(crate) fn copy_directory(
481496
continue;
482497
}
483498
// Add this directory to our list for permission fixing later
484-
dirs_needing_permissions.push((
485-
entry.source_absolute.clone(),
486-
entry.local_to_target.clone(),
487-
created,
488-
));
499+
dirs_needing_permissions.push(DirNeedingPermissions {
500+
source: entry.source_absolute.clone(),
501+
dest: entry.local_to_target.clone(),
502+
was_created: created,
503+
});
489504

490505
// If true, last_iter is not a parent of this iter.
491506
// The means we just exited a directory.
@@ -534,8 +549,8 @@ pub(crate) fn copy_directory(
534549

535550
// Fix permissions for all directories we created
536551
// This ensures that even sibling directories get their permissions fixed
537-
for (source_path, dest_path, created) in dirs_needing_permissions {
538-
copy_attributes(&source_path, &dest_path, &options.attributes, created)?;
552+
for dir in dirs_needing_permissions {
553+
copy_attributes(&dir.source, &dir.dest, &options.attributes, dir.was_created)?;
539554
}
540555

541556
// Also fix permissions for parent directories,

src/uu/cp/src/cp.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,16 +1717,16 @@ pub(crate) fn copy_attributes(
17171717
source: &Path,
17181718
dest: &Path,
17191719
attributes: &Attributes,
1720-
created: bool,
1720+
dest_is_freshly_created_dir: bool,
17211721
) -> CopyResult<()> {
17221722
let context = &*format!("{} -> {}", source.quote(), dest.quote());
17231723
let source_metadata =
17241724
fs::symlink_metadata(source).map_err(|e| CpError::IoErrContext(e, context.to_owned()))?;
17251725

1726-
let is_explicit = matches!(attributes.mode, Preserve::No { explicit: true });
1726+
let mode_explicitly_disabled = matches!(attributes.mode, Preserve::No { explicit: true });
17271727

17281728
// preserve is true by default if the destination is created by us and it's a directory
1729-
let mode = if !is_explicit && dest.is_dir() && created {
1729+
let mode = if !mode_explicitly_disabled && dest_is_freshly_created_dir {
17301730
Preserve::Yes { required: false }
17311731
} else {
17321732
attributes.mode

0 commit comments

Comments
 (0)