cp: reduce memory usage for cp -al by skipping unnecessary tracking (#9805)

Co-authored-by: Sylvestre Ledru <sylvestre@debian.org>
This commit is contained in:
Chris Dryden
2026-01-09 21:03:09 +01:00
committed by GitHub
co-authored by Sylvestre Ledru
parent b5a49f33b5
commit 27fd41125b
2 changed files with 22 additions and 6 deletions
+11 -1
View File
@@ -27,7 +27,8 @@ use uucore::uio_error;
use walkdir::{DirEntry, WalkDir};
use crate::{
CopyResult, CpError, Options, aligned_ancestors, context_for, copy_attributes, copy_file,
CopyMode, CopyResult, CpError, Options, aligned_ancestors, context_for, copy_attributes,
copy_file,
};
/// Ensure a Windows path starts with a `\\?`.
@@ -468,6 +469,15 @@ pub(crate) fn copy_directory(
let is_dir_for_permissions =
entry_is_dir_no_follow || (options.dereference && direntry_path.is_dir());
if is_dir_for_permissions {
// For --link mode, copy attributes immediately to avoid O(n) memory
if options.copy_mode == CopyMode::Link {
copy_attributes(
&entry.source_absolute,
&entry.local_to_target,
&options.attributes,
)?;
continue;
}
// Add this directory to our list for permission fixing later
dirs_needing_permissions
.push((entry.source_absolute.clone(), entry.local_to_target.clone()));
+11 -5
View File
@@ -2448,7 +2448,9 @@ fn copy_file(
return Err(translate!("cp-error-cannot-change-attribute", "dest" => dest.quote()).into());
}
if options.preserve_hard_links() {
// When using --link mode, hard link structure is automatically preserved
// because we link to source files (which share inodes).
if options.preserve_hard_links() && options.copy_mode != CopyMode::Link {
// if we encounter a matching device/inode pair in the source tree
// we can arrange to create a hard link between the corresponding names
// in the destination tree.
@@ -2565,10 +2567,14 @@ fn copy_file(
}
}
copied_files.insert(
FileInformation::from_path(source, options.dereference(source_in_command_line))?,
dest.to_path_buf(),
);
// Skip tracking copied files when using --link mode since hard link
// structure is automatically preserved
if options.copy_mode != CopyMode::Link {
copied_files.insert(
FileInformation::from_path(source, options.dereference(source_in_command_line))?,
dest.to_path_buf(),
);
}
if let Some(progress_bar) = progress_bar {
progress_bar.inc(source_metadata.len());