rename nushell's cp command to cp-old making coreutils the default cp (#10678)

# Description

This PR renames nushell's `cp` command to `cp-old` to make room for
`ucp` to be renamed to `cp`, making the coreutils version of `cp` the
default for nushell. After some period of time, we should remove
`cp-old` entirely.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
This commit is contained in:
Darren Schroeder 2023-10-10 18:13:28 -05:00 committed by GitHub
parent c81fa397b6
commit 0ba81f1d51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 60 additions and 71 deletions

33
Cargo.lock generated
View File

@ -1021,7 +1021,7 @@ version = "3.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf"
dependencies = [ dependencies = [
"nix 0.27.1", "nix",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -2546,17 +2546,6 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]]
name = "nix"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
dependencies = [
"bitflags 1.3.2",
"cfg-if",
"libc",
]
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.27.1" version = "0.27.1"
@ -2639,7 +2628,7 @@ dependencies = [
"log", "log",
"miette", "miette",
"mimalloc", "mimalloc",
"nix 0.27.1", "nix",
"nu-ansi-term", "nu-ansi-term",
"nu-cli", "nu-cli",
"nu-cmd-base", "nu-cmd-base",
@ -2837,7 +2826,7 @@ dependencies = [
"mime_guess", "mime_guess",
"mockito", "mockito",
"native-tls", "native-tls",
"nix 0.27.1", "nix",
"notify-debouncer-full", "notify-debouncer-full",
"nu-ansi-term", "nu-ansi-term",
"nu-cmd-base", "nu-cmd-base",
@ -3034,7 +3023,7 @@ dependencies = [
"libproc", "libproc",
"log", "log",
"mach2", "mach2",
"nix 0.27.1", "nix",
"ntapi", "ntapi",
"once_cell", "once_cell",
"procfs", "procfs",
@ -5618,8 +5607,7 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]] [[package]]
name = "uu_cp" name = "uu_cp"
version = "0.0.21" version = "0.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/uutils/coreutils.git?branch=main#f3f82c14af6789ec7238a40ea120462e574f4973"
checksum = "6ce78537083be579c77dadfcced04e163a905ff51f3f83d11dcdaf252ea771c5"
dependencies = [ dependencies = [
"clap", "clap",
"filetime", "filetime",
@ -5634,14 +5622,13 @@ dependencies = [
[[package]] [[package]]
name = "uucore" name = "uucore"
version = "0.0.21" version = "0.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/uutils/coreutils.git?branch=main#f3f82c14af6789ec7238a40ea120462e574f4973"
checksum = "4bea3522caab8af3fe1de1f27d9691e4ea159efe4d86d4e176306792163936a6"
dependencies = [ dependencies = [
"clap", "clap",
"dunce", "dunce",
"glob", "glob",
"libc", "libc",
"nix 0.26.4", "nix",
"once_cell", "once_cell",
"os_display", "os_display",
"uucore_procs", "uucore_procs",
@ -5654,8 +5641,7 @@ dependencies = [
[[package]] [[package]]
name = "uucore_procs" name = "uucore_procs"
version = "0.0.21" version = "0.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/uutils/coreutils.git?branch=main#f3f82c14af6789ec7238a40ea120462e574f4973"
checksum = "0847828ba11d397cc7b5c3b2b6397f367db71ffb94e0f42cb7e7b1fb3691d556"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -5665,8 +5651,7 @@ dependencies = [
[[package]] [[package]]
name = "uuhelp_parser" name = "uuhelp_parser"
version = "0.0.21" version = "0.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/uutils/coreutils.git?branch=main#f3f82c14af6789ec7238a40ea120462e574f4973"
checksum = "37db35583cf0ad896592892034f281ef0906c893b3b6d901acf3918357f28199"
[[package]] [[package]]
name = "uuid" name = "uuid"

View File

@ -166,6 +166,7 @@ bench = false
[patch.crates-io] [patch.crates-io]
reedline = { git = "https://github.com/nushell/reedline.git", branch = "main" } reedline = { git = "https://github.com/nushell/reedline.git", branch = "main" }
# nu-ansi-term = {git = "https://github.com/nushell/nu-ansi-term.git", branch = "main"} # nu-ansi-term = {git = "https://github.com/nushell/nu-ansi-term.git", branch = "main"}
uu_cp = { git = "https://github.com/uutils/coreutils.git", branch = "main" }
# Criterion benchmarking setup # Criterion benchmarking setup
# Run all benchmarks with `cargo bench` # Run all benchmarks with `cargo bench`

View File

@ -31,11 +31,11 @@ pub struct Cp;
impl Command for Cp { impl Command for Cp {
fn name(&self) -> &str { fn name(&self) -> &str {
"cp" "cp-old"
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
"Copy files." "Old nushell version of Copy files."
} }
fn search_terms(&self) -> Vec<&str> { fn search_terms(&self) -> Vec<&str> {
@ -43,7 +43,7 @@ impl Command for Cp {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("cp") Signature::build("cp-old")
.input_output_types(vec![(Type::Nothing, Type::Nothing)]) .input_output_types(vec![(Type::Nothing, Type::Nothing)])
.required("source", SyntaxShape::GlobPattern, "the place to copy from") .required("source", SyntaxShape::GlobPattern, "the place to copy from")
.required("destination", SyntaxShape::Filepath, "the place to copy to") .required("destination", SyntaxShape::Filepath, "the place to copy to")

View File

@ -27,7 +27,7 @@ pub struct UCp;
impl Command for UCp { impl Command for UCp {
fn name(&self) -> &str { fn name(&self) -> &str {
"ucp" "cp"
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {
@ -39,7 +39,7 @@ impl Command for UCp {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("ucp") Signature::build("cp")
.input_output_types(vec![(Type::Nothing, Type::Nothing)]) .input_output_types(vec![(Type::Nothing, Type::Nothing)])
.switch("recursive", "copy directories recursively", Some('r')) .switch("recursive", "copy directories recursively", Some('r'))
.switch("verbose", "explicitly state what is being done", Some('v')) .switch("verbose", "explicitly state what is being done", Some('v'))
@ -63,22 +63,22 @@ impl Command for UCp {
vec![ vec![
Example { Example {
description: "Copy myfile to dir_b", description: "Copy myfile to dir_b",
example: "ucp myfile dir_b", example: "cp myfile dir_b",
result: None, result: None,
}, },
Example { Example {
description: "Recursively copy dir_a to dir_b", description: "Recursively copy dir_a to dir_b",
example: "ucp -r dir_a dir_b", example: "cp -r dir_a dir_b",
result: None, result: None,
}, },
Example { Example {
description: "Recursively copy dir_a to dir_b, and print the feedbacks", description: "Recursively copy dir_a to dir_b, and print the feedbacks",
example: "ucp -r -v dir_a dir_b", example: "cp -r -v dir_a dir_b",
result: None, result: None,
}, },
Example { Example {
description: "Move many files into a directory", description: "Move many files into a directory",
example: "ucp *.txt dir_a", example: "cp *.txt dir_a",
result: None, result: None,
}, },
] ]

View File

@ -373,6 +373,7 @@ fn copy_file_and_dir_from_two_parents_up_using_multiple_dots_to_current_dir_recu
}) })
} }
#[ignore = "duplicate test with slight differences in ucp"]
#[test] #[test]
fn copy_to_non_existing_dir() { fn copy_to_non_existing_dir() {
copy_to_non_existing_dir_impl(false); copy_to_non_existing_dir_impl(false);
@ -395,6 +396,7 @@ fn copy_to_non_existing_dir_impl(progress: bool) {
}); });
} }
#[ignore = "duplicate test with slight differences in ucp"]
#[test] #[test]
fn copy_dir_contains_symlink_ignored() { fn copy_dir_contains_symlink_ignored() {
copy_dir_contains_symlink_ignored_impl(false); copy_dir_contains_symlink_ignored_impl(false);
@ -488,6 +490,7 @@ fn copy_dir_symlink_file_body_not_changed_impl(progress: bool) {
}); });
} }
#[ignore = "duplicate test with slight differences in ucp"]
#[test] #[test]
fn copy_identical_file() { fn copy_identical_file() {
copy_identical_file_impl(false); copy_identical_file_impl(false);
@ -530,6 +533,7 @@ fn copy_ignores_ansi_impl(progress: bool) {
}); });
} }
#[ignore = "duplicate test with ucp with slight differences"]
#[test] #[test]
fn copy_file_not_exists_dst() { fn copy_file_not_exists_dst() {
copy_file_not_exists_dst_impl(false); copy_file_not_exists_dst_impl(false);
@ -573,13 +577,12 @@ fn copy_file_with_read_permission_impl(progress: bool) {
"cp {} valid.txt invalid_prem.txt", "cp {} valid.txt invalid_prem.txt",
progress_flag, progress_flag,
); );
assert!(
actual.err.contains("invalid_prem.txt") assert!(actual.err.contains("invalid_prem.txt") && actual.err.contains("denied"));
&& actual.err.contains("copying to destination")
);
}); });
} }
#[ignore = "not implemented with ucp"]
#[test] #[test]
fn copy_file_with_update_flag() { fn copy_file_with_update_flag() {
copy_file_with_update_flag_impl(false); copy_file_with_update_flag_impl(false);

View File

@ -33,7 +33,7 @@ fn copies_a_file_impl(progress: bool) {
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {} `{}` ucp_test_1/sample.ini", "cp {} `{}` ucp_test_1/sample.ini",
progress_flag, progress_flag,
test_file.display() test_file.display()
); );
@ -61,7 +61,7 @@ fn copies_the_file_inside_directory_if_path_to_copy_is_directory_impl(progress:
let first_hash = get_file_hash(dirs.formats().join("../formats/sample.ini").display()); let first_hash = get_file_hash(dirs.formats().join("../formats/sample.ini").display());
nu!( nu!(
cwd: dirs.formats(), cwd: dirs.formats(),
"ucp {} ../formats/sample.ini {}", "cp {} ../formats/sample.ini {}",
progress_flag, progress_flag,
expected_file.dir() expected_file.dir()
); );
@ -86,7 +86,7 @@ fn error_if_attempting_to_copy_a_directory_to_another_directory_impl(progress: b
let progress_flag = if progress { "-p" } else { "" }; let progress_flag = if progress { "-p" } else { "" };
let actual = nu!( let actual = nu!(
cwd: dirs.formats(), cwd: dirs.formats(),
"ucp {} ../formats {}", "cp {} ../formats {}",
progress_flag, progress_flag,
dirs.test().display() dirs.test().display()
); );
@ -124,7 +124,7 @@ fn copies_the_directory_inside_directory_if_path_to_copy_is_directory_and_with_r
nu!( nu!(
cwd: dirs.test(), cwd: dirs.test(),
"ucp {} originals expected -r", "cp {} originals expected -r",
progress_flag progress_flag
); );
@ -174,7 +174,7 @@ fn deep_copies_with_recursive_flag_impl(progress: bool) {
nu!( nu!(
cwd: dirs.test(), cwd: dirs.test(),
"ucp {} originals expected --recursive", "cp {} originals expected --recursive",
progress_flag progress_flag
); );
@ -213,7 +213,7 @@ fn copies_using_path_with_wildcard_impl(progress: bool) {
nu!( nu!(
cwd: dirs.formats(), cwd: dirs.formats(),
"ucp {} -r ../formats/* {}", "cp {} -r ../formats/* {}",
progress_flag, progress_flag,
dirs.test().display() dirs.test().display()
); );
@ -258,7 +258,7 @@ fn copies_using_a_glob_impl(progress: bool) {
nu!( nu!(
cwd: dirs.formats(), cwd: dirs.formats(),
"ucp {} -r * {}", "cp {} -r * {}",
progress_flag, progress_flag,
dirs.test().display() dirs.test().display()
); );
@ -298,14 +298,14 @@ fn copies_same_file_twice_impl(progress: bool) {
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {} `{}` ucp_test_8/sample.ini", "cp {} `{}` ucp_test_8/sample.ini",
progress_flag, progress_flag,
dirs.formats().join("sample.ini").display() dirs.formats().join("sample.ini").display()
); );
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {} `{}` ucp_test_8/sample.ini", "cp {} `{}` ucp_test_8/sample.ini",
progress_flag, progress_flag,
dirs.formats().join("sample.ini").display() dirs.formats().join("sample.ini").display()
); );
@ -370,7 +370,7 @@ fn copy_file_and_dir_from_two_parents_up_using_multiple_dots_to_current_dir_recu
nu!( nu!(
cwd: dirs.test().join("foo/bar"), cwd: dirs.test().join("foo/bar"),
"ucp {} -r .../hello* .", "cp {} -r .../hello* .",
progress_flag progress_flag
); );
@ -394,7 +394,7 @@ fn copy_to_non_existing_dir_impl(progress: bool) {
let actual = nu!( let actual = nu!(
cwd: sandbox.cwd(), cwd: sandbox.cwd(),
"ucp {} empty_file ~/not_a_dir{}", "cp {} empty_file ~/not_a_dir{}",
progress_flag, progress_flag,
PATH_SEPARATOR, PATH_SEPARATOR,
); );
@ -512,7 +512,7 @@ fn copy_identical_file_impl(progress: bool) {
let actual = nu!( let actual = nu!(
cwd: dirs.test(), cwd: dirs.test(),
"ucp {} same.txt same.txt", "cp {} same.txt same.txt",
progress_flag, progress_flag,
); );
// assert!(actual.err.contains("Copy aborted")); // assert!(actual.err.contains("Copy aborted"));
@ -568,7 +568,7 @@ fn copy_file_not_exists_dst_impl(progress: bool) {
let actual = nu!( let actual = nu!(
cwd: sandbox.cwd(), cwd: sandbox.cwd(),
"ucp {} valid.txt ~/invalid_dir/invalid_dir1", "cp {} valid.txt ~/invalid_dir/invalid_dir1",
progress_flag, progress_flag,
); );
assert!( assert!(
@ -597,7 +597,7 @@ fn copy_file_with_read_permission_impl(progress: bool) {
let actual = nu!( let actual = nu!(
cwd: sandbox.cwd(), cwd: sandbox.cwd(),
"ucp {} valid.txt invalid_prem.txt", "cp {} valid.txt invalid_prem.txt",
progress_flag, progress_flag,
); );
assert!(actual.err.contains("invalid_prem.txt") && actual.err.contains("denied")); assert!(actual.err.contains("invalid_prem.txt") && actual.err.contains("denied"));
@ -629,7 +629,7 @@ fn test_cp_cp() {
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {} ucp_test_19/{}", "cp {} ucp_test_19/{}",
src.display(), src.display(),
TEST_HELLO_WORLD_DEST TEST_HELLO_WORLD_DEST
); );
@ -654,7 +654,7 @@ fn test_cp_existing_target() {
// Copy existing file to destination, so that it exists for the test // Copy existing file to destination, so that it exists for the test
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {} ucp_test_20/{}", "cp {} ucp_test_20/{}",
existing.display(), existing.display(),
TEST_EXISTING_FILE TEST_EXISTING_FILE
); );
@ -665,7 +665,7 @@ fn test_cp_existing_target() {
// Now for the test // Now for the test
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {} ucp_test_20/{}", "cp {} ucp_test_20/{}",
src.display(), src.display(),
TEST_EXISTING_FILE TEST_EXISTING_FILE
); );
@ -694,7 +694,7 @@ fn test_cp_multiple_files() {
// Start test // Start test
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {} {} ucp_test_21/{}", "cp {} {} ucp_test_21/{}",
src1.display(), src1.display(),
src2.display(), src2.display(),
TEST_COPY_TO_FOLDER TEST_COPY_TO_FOLDER
@ -727,7 +727,7 @@ fn test_cp_recurse() {
// Start test // Start test
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp -r {} ucp_test_22/{}", "cp -r {} ucp_test_22/{}",
TEST_COPY_FROM_FOLDER, TEST_COPY_FROM_FOLDER,
TEST_COPY_TO_FOLDER_NEW, TEST_COPY_TO_FOLDER_NEW,
); );
@ -747,7 +747,7 @@ fn test_cp_with_dirs() {
// Start test // Start test
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {} ucp_test_23/{}", "cp {} ucp_test_23/{}",
src.display(), src.display(),
TEST_COPY_TO_FOLDER, TEST_COPY_TO_FOLDER,
); );
@ -760,7 +760,7 @@ fn test_cp_with_dirs() {
let src2_hash = get_file_hash(src2.display()); let src2_hash = get_file_hash(src2.display());
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {} ucp_test_23/{}", "cp {} ucp_test_23/{}",
src2.display(), src2.display(),
TEST_HELLO_WORLD_DEST, TEST_HELLO_WORLD_DEST,
); );
@ -778,7 +778,7 @@ fn test_cp_arg_force() {
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {} --force ucp_test_24/{}", "cp {} --force ucp_test_24/{}",
src.display(), src.display(),
"invalid_prem.txt" "invalid_prem.txt"
); );
@ -794,7 +794,7 @@ fn test_cp_directory_to_itself_disallowed() {
sandbox.mkdir("d"); sandbox.mkdir("d");
let actual = nu!( let actual = nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp -r ucp_test_25/{} ucp_test_25/{}", "cp -r ucp_test_25/{} ucp_test_25/{}",
"d", "d",
"d" "d"
); );
@ -812,7 +812,7 @@ fn test_cp_nested_directory_to_itself_disallowed() {
sandbox.mkdir("a/b/c"); sandbox.mkdir("a/b/c");
let actual = nu!( let actual = nu!(
cwd: dirs.test(), cwd: dirs.test(),
"ucp -r {} {}", "cp -r {} {}",
"a/b", "a/b",
"a/b/c" "a/b/c"
); );
@ -829,7 +829,7 @@ fn test_cp_same_file_force() {
sandbox.with_files(vec![EmptyFile("f")]); sandbox.with_files(vec![EmptyFile("f")]);
let actual = nu!( let actual = nu!(
cwd: dirs.test(), cwd: dirs.test(),
"ucp --force {} {}", "cp --force {} {}",
"f", "f",
"f" "f"
); );
@ -847,7 +847,7 @@ fn test_cp_arg_no_clobber() {
let actual = nu!( let actual = nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {} {} --no-clobber", "cp {} {} --no-clobber",
src.display(), src.display(),
target.display() target.display()
); );
@ -867,7 +867,7 @@ fn test_cp_arg_no_clobber_twice() {
]); ]);
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp --no-clobber ucp_test_29/{} ucp_test_29/{}", "cp --no-clobber ucp_test_29/{} ucp_test_29/{}",
"source.txt", "source.txt",
"dest.txt" "dest.txt"
); );
@ -875,7 +875,7 @@ fn test_cp_arg_no_clobber_twice() {
nu!( nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp --no-clobber ucp_test_29/{} ucp_test_29/{}", "cp --no-clobber ucp_test_29/{} ucp_test_29/{}",
"source_with_body.txt", "source_with_body.txt",
"dest.txt" "dest.txt"
); );
@ -891,7 +891,7 @@ fn test_cp_debug_default() {
let actual = nu!( let actual = nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp --debug {} ucp_test_30/{}", "cp --debug {} ucp_test_30/{}",
src.display(), src.display(),
TEST_HELLO_WORLD_DEST TEST_HELLO_WORLD_DEST
); );
@ -926,7 +926,7 @@ fn test_cp_verbose_default() {
let actual = nu!( let actual = nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp --verbose {} {}", "cp --verbose {} {}",
src.display(), src.display(),
TEST_HELLO_WORLD_DEST TEST_HELLO_WORLD_DEST
); );
@ -947,7 +947,7 @@ fn test_cp_only_source_no_dest() {
let src = dirs.fixtures.join("cp").join(TEST_HELLO_WORLD_SOURCE); let src = dirs.fixtures.join("cp").join(TEST_HELLO_WORLD_SOURCE);
let actual = nu!( let actual = nu!(
cwd: dirs.root(), cwd: dirs.root(),
"ucp {}", "cp {}",
src.display(), src.display(),
); );
assert!(actual assert!(actual
@ -963,7 +963,7 @@ fn test_cp_with_vars() {
sandbox.with_files(vec![EmptyFile("input")]); sandbox.with_files(vec![EmptyFile("input")]);
nu!( nu!(
cwd: dirs.test(), cwd: dirs.test(),
"let src = 'input'; let dst = 'target'; ucp $src $dst", "let src = 'input'; let dst = 'target'; cp $src $dst",
); );
assert!(dirs.test().join("target").exists()); assert!(dirs.test().join("target").exists());
}); });