mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
Merge pull request #1305 from rivy/fix.mv
fix "`mv` fails transfers between dirs"
This commit is contained in:
commit
8d15f36977
3 changed files with 56 additions and 8 deletions
40
src/mv/mv.rs
40
src/mv/mv.rs
|
@ -257,7 +257,10 @@ fn exec(files: &[PathBuf], b: Behaviour) -> i32 {
|
||||||
|
|
||||||
return match rename(source, target, &b) {
|
return match rename(source, target, &b) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
show_error!("{}", e);
|
show_error!(
|
||||||
|
"cannot move ‘{}’ to ‘{}’: {}",
|
||||||
|
source.display(), target.display(), e
|
||||||
|
);
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
_ => 0,
|
_ => 0,
|
||||||
|
@ -265,6 +268,12 @@ fn exec(files: &[PathBuf], b: Behaviour) -> i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
return move_files_into_dir(&[source.clone()], target, &b);
|
return move_files_into_dir(&[source.clone()], target, &b);
|
||||||
|
} else if target.exists() && source.is_dir() {
|
||||||
|
show_error!(
|
||||||
|
"cannot overwrite non-directory ‘{}’ with directory ‘{}’",
|
||||||
|
target.display(), source.display()
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = rename(source, target, &b) {
|
if let Err(e) = rename(source, target, &b) {
|
||||||
|
@ -297,7 +306,7 @@ fn move_files_into_dir(files: &[PathBuf], target_dir: &PathBuf, b: &Behaviour) -
|
||||||
|
|
||||||
let mut all_successful = true;
|
let mut all_successful = true;
|
||||||
for sourcepath in files.iter() {
|
for sourcepath in files.iter() {
|
||||||
let targetpath = match sourcepath.as_os_str().to_str() {
|
let targetpath = match sourcepath.file_name() {
|
||||||
Some(name) => target_dir.join(name),
|
Some(name) => target_dir.join(name),
|
||||||
None => {
|
None => {
|
||||||
show_error!(
|
show_error!(
|
||||||
|
@ -349,18 +358,30 @@ fn rename(from: &PathBuf, to: &PathBuf, b: &Behaviour) -> Result<()> {
|
||||||
BackupMode::ExistingBackup => Some(existing_backup_path(to, &b.suffix)),
|
BackupMode::ExistingBackup => Some(existing_backup_path(to, &b.suffix)),
|
||||||
};
|
};
|
||||||
if let Some(ref p) = backup_path {
|
if let Some(ref p) = backup_path {
|
||||||
try!(fs::rename(to, p));
|
fs::rename(to, p)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.update {
|
if b.update {
|
||||||
if try!(try!(fs::metadata(from)).modified()) <= try!(try!(fs::metadata(to)).modified())
|
if fs::metadata(from)?.modified()? <= fs::metadata(to)?.modified()?
|
||||||
{
|
{
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(fs::rename(from, to));
|
// "to" may no longer exist if it was backed up
|
||||||
|
if to.exists() && to.is_dir() {
|
||||||
|
// normalize behavior between *nix and windows
|
||||||
|
if from.is_dir() {
|
||||||
|
if is_empty_dir(to) {
|
||||||
|
fs::remove_dir(to)?
|
||||||
|
} else {
|
||||||
|
return Err(std::io::Error::new(std::io::ErrorKind::Other, "Directory not empty"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::rename(from, to)?;
|
||||||
|
|
||||||
if b.verbose {
|
if b.verbose {
|
||||||
print!("‘{}’ -> ‘{}’", from.display(), to.display());
|
print!("‘{}’ -> ‘{}’", from.display(), to.display());
|
||||||
|
@ -405,3 +426,12 @@ fn existing_backup_path(path: &PathBuf, suffix: &str) -> PathBuf {
|
||||||
simple_backup_path(path, suffix)
|
simple_backup_path(path, suffix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_empty_dir(path: &PathBuf) -> bool {
|
||||||
|
match fs::read_dir(path) {
|
||||||
|
Ok(contents) => {
|
||||||
|
return contents.peekable().peek().is_none();
|
||||||
|
},
|
||||||
|
Err(_e) => { return false; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -44,6 +44,25 @@ fn test_mv_move_file_into_dir() {
|
||||||
assert!(at.file_exists(&format!("{}/{}", dir, file)));
|
assert!(at.file_exists(&format!("{}/{}", dir, file)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mv_move_file_between_dirs() {
|
||||||
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
let dir1 = "test_mv_move_file_between_dirs_dir1";
|
||||||
|
let dir2 = "test_mv_move_file_between_dirs_dir2";
|
||||||
|
let file = "test_mv_move_file_between_dirs_file";
|
||||||
|
|
||||||
|
at.mkdir(dir1);
|
||||||
|
at.mkdir(dir2);
|
||||||
|
at.touch(&format!("{}/{}", dir1, file));
|
||||||
|
|
||||||
|
assert!(at.file_exists(&format!("{}/{}", dir1, file)));
|
||||||
|
|
||||||
|
ucmd.arg(&format!("{}/{}", dir1, file)).arg(dir2).succeeds().no_stderr();
|
||||||
|
|
||||||
|
assert!(!at.file_exists(&format!("{}/{}", dir1, file)));
|
||||||
|
assert!(at.file_exists(&format!("{}/{}", dir2, file)));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mv_strip_slashes() {
|
fn test_mv_strip_slashes() {
|
||||||
let scene = TestScenario::new(util_name!());
|
let scene = TestScenario::new(util_name!());
|
||||||
|
@ -368,8 +387,7 @@ fn test_mv_errors() {
|
||||||
// $ mv -T -t a b
|
// $ mv -T -t a b
|
||||||
// mv: cannot combine --target-directory (-t) and --no-target-directory (-T)
|
// mv: cannot combine --target-directory (-t) and --no-target-directory (-T)
|
||||||
scene.ucmd().arg("-T").arg("-t").arg(dir).arg(file_a).arg(file_b).fails()
|
scene.ucmd().arg("-T").arg("-t").arg(dir).arg(file_a).arg(file_b).fails()
|
||||||
.stderr_is("mv: error: cannot combine --target-directory (-t) and --no-target-directory \
|
.stderr_is("mv: error: cannot combine --target-directory (-t) and --no-target-directory (-T)\n");
|
||||||
(-T)\n");
|
|
||||||
|
|
||||||
// $ at.touch file && at.mkdir dir
|
// $ at.touch file && at.mkdir dir
|
||||||
// $ mv -T file dir
|
// $ mv -T file dir
|
||||||
|
|
|
@ -23,7 +23,6 @@ unix_only! {
|
||||||
"chown", test_chown;
|
"chown", test_chown;
|
||||||
"chgrp", test_chgrp;
|
"chgrp", test_chgrp;
|
||||||
"install", test_install;
|
"install", test_install;
|
||||||
"mv", test_mv;
|
|
||||||
"pathchk", test_pathchk;
|
"pathchk", test_pathchk;
|
||||||
"pinky", test_pinky;
|
"pinky", test_pinky;
|
||||||
"stdbuf", test_stdbuf;
|
"stdbuf", test_stdbuf;
|
||||||
|
@ -68,6 +67,7 @@ generic! {
|
||||||
"ls", test_ls;
|
"ls", test_ls;
|
||||||
"mkdir", test_mkdir;
|
"mkdir", test_mkdir;
|
||||||
"mktemp", test_mktemp;
|
"mktemp", test_mktemp;
|
||||||
|
"mv", test_mv;
|
||||||
"numfmt", test_numfmt;
|
"numfmt", test_numfmt;
|
||||||
"nl", test_nl;
|
"nl", test_nl;
|
||||||
"od", test_od;
|
"od", test_od;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue