mirror of
https://github.com/nushell/nushell.git
synced 2025-06-30 22:50:14 +02:00
ls, rm, cp, open, touch, mkdir: Don't expand tilde if input path is quoted string or a variable. (#12232)
# Description Fixes: #11887 Fixes: #11626 This pr unify the tilde expand behavior over several filesystem relative commands. It follows the same rule with glob expansion: | command | result | | ----------- | ------ | | ls ~/aaa | expand tilde | ls "~/aaa" | don't expand tilde | let f = "~/aaa"; ls $f | don't expand tilde, if you want to: use `ls ($f \| path expand)` | let f: glob = "~/aaa"; ls $f | expand tilde, they don't expand on `mkdir`, `touch` comamnd. Actually I'm not sure for 4th item, currently it's expanding is just because it followes the same rule with glob expansion. ### About the change It changes `expand_path_with` to accept a new argument called `expand_tilde`, if it's true, expand it, if not, just keep it as `~` itself. # User-Facing Changes After this change, `ls "~/aaa"` won't expand tilde. # Tests + Formatting Done
This commit is contained in:
@ -711,3 +711,25 @@ fn list_empty_string() {
|
||||
assert!(actual.err.contains("does not exist"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_with_tilde() {
|
||||
Playground::setup("ls_tilde", |dirs, sandbox| {
|
||||
sandbox
|
||||
.within("~tilde")
|
||||
.with_files(vec![EmptyFile("f1.txt"), EmptyFile("f2.txt")]);
|
||||
|
||||
let actual = nu!(cwd: dirs.test(), "ls '~tilde'");
|
||||
assert!(actual.out.contains("f1.txt"));
|
||||
assert!(actual.out.contains("f2.txt"));
|
||||
assert!(actual.out.contains("~tilde"));
|
||||
let actual = nu!(cwd: dirs.test(), "ls ~tilde");
|
||||
assert!(actual.err.contains("does not exist"));
|
||||
|
||||
// pass variable
|
||||
let actual = nu!(cwd: dirs.test(), "let f = '~tilde'; ls $f");
|
||||
assert!(actual.out.contains("f1.txt"));
|
||||
assert!(actual.out.contains("f2.txt"));
|
||||
assert!(actual.out.contains("~tilde"));
|
||||
})
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use nu_test_support::fs::{files_exist_at, Stub::EmptyFile, Stub::FileWithContent
|
||||
use nu_test_support::nu;
|
||||
use nu_test_support::playground::Playground;
|
||||
use rstest::rstest;
|
||||
use std::path::Path;
|
||||
|
||||
#[test]
|
||||
fn moves_a_file() {
|
||||
@ -656,3 +657,33 @@ fn test_cp_inside_glob_metachars_dir() {
|
||||
assert!(files_exist_at(vec!["test_file.txt"], dirs.test()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mv_with_tilde() {
|
||||
Playground::setup("mv_tilde", |dirs, sandbox| {
|
||||
sandbox.within("~tilde").with_files(vec![
|
||||
EmptyFile("f1.txt"),
|
||||
EmptyFile("f2.txt"),
|
||||
EmptyFile("f3.txt"),
|
||||
]);
|
||||
sandbox.within("~tilde2");
|
||||
|
||||
// mv file
|
||||
let actual = nu!(cwd: dirs.test(), "mv '~tilde/f1.txt' ./");
|
||||
assert!(actual.err.is_empty());
|
||||
assert!(!files_exist_at(
|
||||
vec![Path::new("f1.txt")],
|
||||
dirs.test().join("~tilde")
|
||||
));
|
||||
assert!(files_exist_at(vec![Path::new("f1.txt")], dirs.test()));
|
||||
|
||||
// pass variable
|
||||
let actual = nu!(cwd: dirs.test(), "let f = '~tilde/f2.txt'; mv $f ./");
|
||||
assert!(actual.err.is_empty());
|
||||
assert!(!files_exist_at(
|
||||
vec![Path::new("f2.txt")],
|
||||
dirs.test().join("~tilde")
|
||||
));
|
||||
assert!(files_exist_at(vec![Path::new("f1.txt")], dirs.test()));
|
||||
})
|
||||
}
|
||||
|
@ -538,3 +538,34 @@ fn force_rm_suppress_error() {
|
||||
assert!(actual.err.is_empty());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rm_with_tilde() {
|
||||
Playground::setup("rm_tilde", |dirs, sandbox| {
|
||||
sandbox.within("~tilde").with_files(vec![
|
||||
EmptyFile("f1.txt"),
|
||||
EmptyFile("f2.txt"),
|
||||
EmptyFile("f3.txt"),
|
||||
]);
|
||||
|
||||
let actual = nu!(cwd: dirs.test(), "rm '~tilde/f1.txt'");
|
||||
assert!(actual.err.is_empty());
|
||||
assert!(!files_exist_at(
|
||||
vec![Path::new("f1.txt")],
|
||||
dirs.test().join("~tilde")
|
||||
));
|
||||
|
||||
// pass variable
|
||||
let actual = nu!(cwd: dirs.test(), "let f = '~tilde/f2.txt'; rm $f");
|
||||
assert!(actual.err.is_empty());
|
||||
assert!(!files_exist_at(
|
||||
vec![Path::new("f2.txt")],
|
||||
dirs.test().join("~tilde")
|
||||
));
|
||||
|
||||
// remove directory
|
||||
let actual = nu!(cwd: dirs.test(), "let f = '~tilde'; rm -r $f");
|
||||
assert!(actual.err.is_empty());
|
||||
assert!(!files_exist_at(vec![Path::new("~tilde")], dirs.test()));
|
||||
})
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
use chrono::{DateTime, Local};
|
||||
use nu_test_support::fs::Stub;
|
||||
use nu_test_support::fs::{files_exist_at, Stub};
|
||||
use nu_test_support::nu;
|
||||
use nu_test_support::playground::Playground;
|
||||
use std::path::Path;
|
||||
|
||||
// Use 1 instead of 0 because 0 has a special meaning in Windows
|
||||
const TIME_ONE: filetime::FileTime = filetime::FileTime::from_unix_time(1, 0);
|
||||
@ -487,3 +488,17 @@ fn change_dir_atime_to_reference() {
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_a_file_with_tilde() {
|
||||
Playground::setup("touch with tilde", |dirs, _| {
|
||||
let actual = nu!(cwd: dirs.test(), "touch '~tilde'");
|
||||
assert!(actual.err.is_empty());
|
||||
assert!(files_exist_at(vec![Path::new("~tilde")], dirs.test()));
|
||||
|
||||
// pass variable
|
||||
let actual = nu!(cwd: dirs.test(), "let f = '~tilde2'; touch $f");
|
||||
assert!(actual.err.is_empty());
|
||||
assert!(files_exist_at(vec![Path::new("~tilde2")], dirs.test()));
|
||||
})
|
||||
}
|
||||
|
@ -1174,6 +1174,42 @@ fn test_cp_to_customized_home_directory() {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cp_with_tilde() {
|
||||
Playground::setup("cp_tilde", |dirs, sandbox| {
|
||||
sandbox.within("~tilde").with_files(vec![
|
||||
EmptyFile("f1.txt"),
|
||||
EmptyFile("f2.txt"),
|
||||
EmptyFile("f3.txt"),
|
||||
]);
|
||||
sandbox.within("~tilde2");
|
||||
// cp directory
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(),
|
||||
"let f = '~tilde'; cp -r $f '~tilde2'; ls '~tilde2/~tilde' | length"
|
||||
);
|
||||
assert_eq!(actual.out, "3");
|
||||
|
||||
// cp file
|
||||
let actual = nu!(cwd: dirs.test(), "cp '~tilde/f1.txt' ./");
|
||||
assert!(actual.err.is_empty());
|
||||
assert!(files_exist_at(
|
||||
vec![Path::new("f1.txt")],
|
||||
dirs.test().join("~tilde")
|
||||
));
|
||||
assert!(files_exist_at(vec![Path::new("f1.txt")], dirs.test()));
|
||||
|
||||
// pass variable
|
||||
let actual = nu!(cwd: dirs.test(), "let f = '~tilde/f2.txt'; cp $f ./");
|
||||
assert!(actual.err.is_empty());
|
||||
assert!(files_exist_at(
|
||||
vec![Path::new("f2.txt")],
|
||||
dirs.test().join("~tilde")
|
||||
));
|
||||
assert!(files_exist_at(vec![Path::new("f1.txt")], dirs.test()));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn copy_file_with_update_flag() {
|
||||
copy_file_with_update_flag_impl(false);
|
||||
|
@ -145,3 +145,17 @@ fn mkdir_umask_permission() {
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mkdir_with_tilde() {
|
||||
Playground::setup("mkdir with tilde", |dirs, _| {
|
||||
let actual = nu!(cwd: dirs.test(), "mkdir '~tilde'");
|
||||
assert!(actual.err.is_empty());
|
||||
assert!(files_exist_at(vec![Path::new("~tilde")], dirs.test()));
|
||||
|
||||
// pass variable
|
||||
let actual = nu!(cwd: dirs.test(), "let f = '~tilde2'; mkdir $f");
|
||||
assert!(actual.err.is_empty());
|
||||
assert!(files_exist_at(vec![Path::new("~tilde2")], dirs.test()));
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user