From 026335fff03adba5cfafca9f11dfe6231f70afea Mon Sep 17 00:00:00 2001 From: mengsuenyan <49850817+mengsuenyan@users.noreply.github.com> Date: Thu, 13 Jul 2023 00:12:59 +0800 Subject: [PATCH] Fix `cp -u`/`mv -u` when the `dst` doesn't exist (#9662) Fixes #9655 --- crates/nu-command/src/filesystem/cp.rs | 2 +- crates/nu-command/src/filesystem/mv.rs | 2 +- crates/nu-command/src/filesystem/util.rs | 12 +++++++----- crates/nu-command/tests/commands/cp.rs | 4 ++++ crates/nu-command/tests/commands/move_/mv.rs | 5 +++++ 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/crates/nu-command/src/filesystem/cp.rs b/crates/nu-command/src/filesystem/cp.rs index e3ad7dc589..20c05474bd 100644 --- a/crates/nu-command/src/filesystem/cp.rs +++ b/crates/nu-command/src/filesystem/cp.rs @@ -184,7 +184,7 @@ impl Command for Cp { canonicalize_with(dst.as_path(), ¤t_dir_path).unwrap_or(dst); // ignore when source file is not newer than target file - if update_mode && super::util::is_older(&src, &dst) { + if update_mode && super::util::is_older(&src, &dst).unwrap_or(false) { continue; } diff --git a/crates/nu-command/src/filesystem/mv.rs b/crates/nu-command/src/filesystem/mv.rs index 3e93c935d2..b8b63c987c 100644 --- a/crates/nu-command/src/filesystem/mv.rs +++ b/crates/nu-command/src/filesystem/mv.rs @@ -313,7 +313,7 @@ fn move_file( } } - if update_mode && super::util::is_older(&from, &to) { + if update_mode && super::util::is_older(&from, &to).unwrap_or(false) { Ok(false) } else { match move_item(&from, from_span, &to) { diff --git a/crates/nu-command/src/filesystem/util.rs b/crates/nu-command/src/filesystem/util.rs index 4c22094efd..ef95953c04 100644 --- a/crates/nu-command/src/filesystem/util.rs +++ b/crates/nu-command/src/filesystem/util.rs @@ -133,9 +133,11 @@ fn get_interactive_confirmation(prompt: String) -> Result> } } -pub fn is_older(src: &Path, dst: &Path) -> bool { - if !dst.exists() { - return true; +/// Return `Some(true)` if the last change time of the `src` old than the `dst`, +/// otherwisie return `Some(false)`. Return `None` if the `src` or `dst` doesn't exist. +pub fn is_older(src: &Path, dst: &Path) -> Option { + if !dst.exists() || !src.exists() { + return None; } #[cfg(unix)] { @@ -146,7 +148,7 @@ pub fn is_older(src: &Path, dst: &Path) -> bool { let dst_ctime = std::fs::metadata(dst) .map(|m| m.ctime()) .unwrap_or(i64::MAX); - src_ctime <= dst_ctime + Some(src_ctime <= dst_ctime) } #[cfg(windows)] { @@ -157,7 +159,7 @@ pub fn is_older(src: &Path, dst: &Path) -> bool { let dst_ctime = std::fs::metadata(dst) .map(|m| m.last_write_time()) .unwrap_or(u64::MAX); - src_ctime <= dst_ctime + Some(src_ctime <= dst_ctime) } } diff --git a/crates/nu-command/tests/commands/cp.rs b/crates/nu-command/tests/commands/cp.rs index e249210f98..d1229e727b 100644 --- a/crates/nu-command/tests/commands/cp.rs +++ b/crates/nu-command/tests/commands/cp.rs @@ -607,5 +607,9 @@ fn copy_file_with_update_flag_impl(progress: bool) { sandbox.with_files(vec![FileWithContent("newest_valid.txt", "newest_body")]); let actual = nu!(cwd: sandbox.cwd(), "cp {} -u newest_valid.txt valid.txt; open valid.txt", progress_flag); assert_eq!(actual.out, "newest_body"); + + // when destination doesn't exist + let actual = nu!(cwd: sandbox.cwd(), "cp {} -u newest_valid.txt des_missing.txt; open des_missing.txt", progress_flag); + assert_eq!(actual.out, "newest_body"); }); } diff --git a/crates/nu-command/tests/commands/move_/mv.rs b/crates/nu-command/tests/commands/move_/mv.rs index 9552b3bff2..bac5d25023 100644 --- a/crates/nu-command/tests/commands/move_/mv.rs +++ b/crates/nu-command/tests/commands/move_/mv.rs @@ -484,5 +484,10 @@ fn mv_with_update_flag() { sandbox.with_files(vec![FileWithContent("newest_valid.txt", "newest_body")]); let actual = nu!(cwd: sandbox.cwd(), "mv -uf newest_valid.txt valid.txt; open valid.txt"); assert_eq!(actual.out, "newest_body"); + + // when destination doesn't exist + sandbox.with_files(vec![FileWithContent("newest_valid.txt", "newest_body")]); + let actual = nu!(cwd: sandbox.cwd(), "mv -uf newest_valid.txt des_missing.txt; open des_missing.txt"); + assert_eq!(actual.out, "newest_body"); }); }