Skip to content

Commit

Permalink
cp: correct --verbose --parents output for dirs
Browse files Browse the repository at this point in the history
This commit corrects the behavior of `cp -r --parents --verbose` when
the source path is a directory, so that it prints the copied ancestor
directories. For example,

    $ mkdir -p a/b/c d
    $ cp -r --verbose --parents a/b/c d
    a -> d/a
    a/b -> d/a/b
    'a/b/c' -> 'd/a/b/c'
  • Loading branch information
jfinkels committed Nov 27, 2022
1 parent 74e997d commit 9d904f6
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
21 changes: 19 additions & 2 deletions src/uu/cp/src/copydir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use uucore::uio_error;
use walkdir::{DirEntry, WalkDir};

use crate::{
copy_attributes, copy_file, copy_link, preserve_hardlinks, CopyResult, Error, Options,
TargetSlice,
aligned_ancestors, context_for, copy_attributes, copy_file, copy_link, preserve_hardlinks,
CopyResult, Error, Options, TargetSlice,
};

/// Ensure a Windows path starts with a `\\?`.
Expand Down Expand Up @@ -188,6 +188,10 @@ fn copy_direntry(
target_is_file,
} = entry;

if options.verbose {
println!("{}", context_for(&source_relative, &local_to_target));
}

// If the source is a symbolic link and the options tell us not to
// dereference the link, then copy the link object itself.
if source_absolute.is_symlink() && !options.dereference {
Expand Down Expand Up @@ -324,6 +328,19 @@ pub(crate) fn copy_directory(
if let Some(parent) = root.parent() {
let new_target = target.join(parent);
std::fs::create_dir_all(&new_target)?;

if options.verbose {
// For example, if copying file `a/b/c` and its parents
// to directory `d/`, then print
//
// a -> d/a
// a/b -> d/a/b
//
for (x, y) in aligned_ancestors(root, &target.join(root)) {
println!("{} -> {}", x.display(), y.display());
}
}

new_target
} else {
target.to_path_buf()
Expand Down
30 changes: 30 additions & 0 deletions tests/by-util/test_cp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2085,6 +2085,36 @@ fn test_cp_parents_2_link() {
assert!(at.file_exists("d/a/link/c"));
}

#[test]
fn test_cp_parents_2_dir() {
let (at, mut ucmd) = at_and_ucmd!();
at.mkdir_all("a/b/c");
at.mkdir("d");
#[cfg(not(windows))]
let expected_stdout = "a -> d/a\na/b -> d/a/b\n'a/b/c' -> 'd/a/b/c'\n";
#[cfg(windows)]
let expected_stdout = "a -> d\\a\na/b -> d\\a/b\n'a/b/c' -> 'd\\a/b\\c'\n";
ucmd.args(&["--verbose", "-r", "--parents", "a/b/c", "d"])
.succeeds()
.stdout_only(expected_stdout);
assert!(at.dir_exists("d/a/b/c"));
}

#[test]
fn test_cp_parents_2_deep_dir() {
let (at, mut ucmd) = at_and_ucmd!();
at.mkdir_all("a/b/c");
at.mkdir_all("d/e");
#[cfg(not(windows))]
let expected_stdout = "a -> d/e/a\na/b -> d/e/a/b\n'a/b/c' -> 'd/e/a/b/c'\n";
#[cfg(windows)]
let expected_stdout = "a -> d/e\\a\na/b -> d/e\\a/b\n'a/b/c' -> 'd/e\\a/b\\c'\n";
ucmd.args(&["--verbose", "-r", "--parents", "a/b/c", "d/e"])
.succeeds()
.stdout_only(expected_stdout);
assert!(at.dir_exists("d/e/a/b/c"));
}

#[test]
fn test_cp_copy_symlink_contents_recursive() {
let (at, mut ucmd) = at_and_ucmd!();
Expand Down

0 comments on commit 9d904f6

Please sign in to comment.