mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 11:07:44 +00:00
cp: manages target with trailing '/'
This commit is contained in:
parent
cb27b9c9c3
commit
aabf5fa577
4 changed files with 40 additions and 4 deletions
|
@ -17,7 +17,9 @@ use std::path::{Path, PathBuf, StripPrefixError};
|
|||
use indicatif::ProgressBar;
|
||||
use uucore::display::Quotable;
|
||||
use uucore::error::UIoError;
|
||||
use uucore::fs::{canonicalize, FileInformation, MissingHandling, ResolveMode};
|
||||
use uucore::fs::{
|
||||
canonicalize, path_ends_with_terminator, FileInformation, MissingHandling, ResolveMode,
|
||||
};
|
||||
use uucore::show;
|
||||
use uucore::show_error;
|
||||
use uucore::uio_error;
|
||||
|
@ -170,7 +172,14 @@ impl Entry {
|
|||
let mut descendant =
|
||||
get_local_to_root_parent(&source_absolute, context.root_parent.as_deref())?;
|
||||
if no_target_dir {
|
||||
descendant = descendant.strip_prefix(context.root)?.to_path_buf();
|
||||
let source_is_dir: bool = direntry.path().is_dir();
|
||||
if path_ends_with_terminator(context.target) && source_is_dir {
|
||||
if let Err(e) = std::fs::create_dir_all(context.target) {
|
||||
eprintln!("Failed to create directory: {}", e);
|
||||
}
|
||||
} else {
|
||||
descendant = descendant.strip_prefix(context.root)?.to_path_buf();
|
||||
}
|
||||
}
|
||||
|
||||
let local_to_target = context.target.join(descendant);
|
||||
|
|
|
@ -32,8 +32,8 @@ use platform::copy_on_write;
|
|||
use uucore::display::Quotable;
|
||||
use uucore::error::{set_exit_code, UClapError, UError, UResult, UUsageError};
|
||||
use uucore::fs::{
|
||||
are_hardlinks_to_same_file, canonicalize, is_symlink_loop, paths_refer_to_same_file,
|
||||
FileInformation, MissingHandling, ResolveMode,
|
||||
are_hardlinks_to_same_file, canonicalize, is_symlink_loop, path_ends_with_terminator,
|
||||
paths_refer_to_same_file, FileInformation, MissingHandling, ResolveMode,
|
||||
};
|
||||
use uucore::{backup_control, update_control};
|
||||
// These are exposed for projects (e.g. nushell) that want to create an `Options` value, which
|
||||
|
@ -1994,6 +1994,10 @@ fn copy_helper(
|
|||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
|
||||
if path_ends_with_terminator(dest) && !dest.is_dir() {
|
||||
return Err(Error::NotADirectory(dest.to_path_buf()));
|
||||
}
|
||||
|
||||
if source.as_os_str() == "/dev/null" {
|
||||
/* workaround a limitation of fs::copy
|
||||
* https://github.com/rust-lang/rust/issues/79390
|
||||
|
|
|
@ -3681,3 +3681,23 @@ fn test_cp_seen_file() {
|
|||
assert!(at.plus("c").join("f").exists());
|
||||
assert!(at.plus("c").join("f.~1~").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cp_path_ends_with_terminator() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
let at = &ts.fixtures;
|
||||
at.mkdir("a");
|
||||
ts.ucmd().arg("-r").arg("-T").arg("a").arg("e/").succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cp_no_such() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
let at = &ts.fixtures;
|
||||
at.touch("b");
|
||||
ts.ucmd()
|
||||
.arg("b")
|
||||
.arg("no-such/")
|
||||
.fails()
|
||||
.stderr_is("cp: 'no-such/' is not a directory\n");
|
||||
}
|
||||
|
|
|
@ -206,6 +206,9 @@ sed -i "s|cp: target directory 'symlink': Permission denied|cp: 'symlink' is not
|
|||
# to transform an ERROR into FAIL
|
||||
sed -i 's|xargs mkdir )|xargs mkdir -p )|' tests/cp/link-heap.sh
|
||||
|
||||
# Our message is a bit better
|
||||
sed -i "s|cannot create regular file 'no-such/': Not a directory|'no-such/' is not a directory|" tests/mv/trailing-slash.sh
|
||||
|
||||
sed -i 's|cp |/usr/bin/cp |' tests/mv/hard-2.sh
|
||||
sed -i 's|paste |/usr/bin/paste |' tests/od/od-endian.sh
|
||||
sed -i 's|timeout |'"${SYSTEM_TIMEOUT}"' |' tests/tail/follow-stdin.sh
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue