From bd9d865912fa9080cdbff48b81246a48a46c7781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandra=20=C3=98stermark?= Date: Thu, 20 Jul 2023 20:16:03 +0200 Subject: [PATCH] fix removing symlinks on windows (#9704) this PR should close #9624 # Description Fixes the `rm` command assuming that a symlink is a directory and trying to delete the directory as opposed to unlinking the symlink. Should probably be tested on linux before merge. Added tests for deleting symlinks --- crates/nu-command/src/filesystem/rm.rs | 12 ++++++++++-- crates/nu-command/tests/commands/rm.rs | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/crates/nu-command/src/filesystem/rm.rs b/crates/nu-command/src/filesystem/rm.rs index 41f48e92d1e7..486f6acfd5ed 100644 --- a/crates/nu-command/src/filesystem/rm.rs +++ b/crates/nu-command/src/filesystem/rm.rs @@ -393,7 +393,11 @@ fn rm( trash::delete(&f).map_err(|e: trash::Error| { Error::new(ErrorKind::Other, format!("{e:?}\nTry '--trash' flag")) }) - } else if metadata.is_file() || is_socket || is_fifo { + } else if metadata.is_file() + || is_socket + || is_fifo + || metadata.file_type().is_symlink() + { std::fs::remove_file(&f) } else { std::fs::remove_dir_all(&f) @@ -411,7 +415,11 @@ fn rm( Err(e) } else if interactive && !confirmed { Ok(()) - } else if metadata.is_file() || is_socket || is_fifo { + } else if metadata.is_file() + || is_socket + || is_fifo + || metadata.file_type().is_symlink() + { std::fs::remove_file(&f) } else { std::fs::remove_dir_all(&f) diff --git a/crates/nu-command/tests/commands/rm.rs b/crates/nu-command/tests/commands/rm.rs index 978a80325051..ac795614214c 100644 --- a/crates/nu-command/tests/commands/rm.rs +++ b/crates/nu-command/tests/commands/rm.rs @@ -352,6 +352,29 @@ fn remove_ignores_ansi() { }); } +#[test] +fn removes_symlink() { + let symlink_target = "symlink_target"; + let symlink = "symlink"; + Playground::setup("rm_test_symlink", |dirs, sandbox| { + sandbox.with_files(vec![EmptyFile(symlink_target)]); + + #[cfg(not(windows))] + std::os::unix::fs::symlink(dirs.test().join(symlink_target), dirs.test().join(symlink)) + .unwrap(); + #[cfg(windows)] + std::os::windows::fs::symlink_file( + dirs.test().join(symlink_target), + dirs.test().join(symlink), + ) + .unwrap(); + + let _ = nu!(cwd: sandbox.cwd(), "rm symlink"); + + assert!(!dirs.test().join(symlink).exists()); + }); +} + struct Cleanup<'a> { dir_to_clean: &'a PathBuf, }