mirror of
https://github.com/nushell/nushell.git
synced 2024-11-28 19:33:47 +01:00
# Description This fixes #12391. nushell/nushell@87c5f6e455 accidentally introduced a bug where the path was not being properly expanded according to the cwd. This makes both 'touch' and 'mkdir' use globs just like the rest of the commands to preserve tilde behavior while still expanding the paths properly. This doesn't actually expand the globs. Should it? # User-Facing Changes - Restore behavior of `mkdir`, `touch` - Help text now says they can take globs, but they won't actually expand them, maybe this should be changed # Tests + Formatting Regression tests added. # After Submitting This is severe enough and should be included in the point release.
This commit is contained in:
parent
25b90744b7
commit
51aa66fef7
@ -1,8 +1,12 @@
|
|||||||
use filetime::FileTime;
|
use filetime::FileTime;
|
||||||
use nu_engine::command_prelude::*;
|
use nu_engine::{command_prelude::*, current_dir};
|
||||||
|
use nu_path::expand_path_with;
|
||||||
|
use nu_protocol::NuGlob;
|
||||||
|
|
||||||
use std::{fs::OpenOptions, path::Path, time::SystemTime};
|
use std::{fs::OpenOptions, path::Path, time::SystemTime};
|
||||||
|
|
||||||
|
use super::util::get_rest_for_glob_pattern;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Touch;
|
pub struct Touch;
|
||||||
|
|
||||||
@ -18,7 +22,11 @@ impl Command for Touch {
|
|||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("touch")
|
Signature::build("touch")
|
||||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||||
.rest("files", SyntaxShape::Filepath, "The file(s) to create.")
|
.rest(
|
||||||
|
"files",
|
||||||
|
SyntaxShape::OneOf(vec![SyntaxShape::GlobPattern, SyntaxShape::Filepath]),
|
||||||
|
"The file(s) to create."
|
||||||
|
)
|
||||||
.named(
|
.named(
|
||||||
"reference",
|
"reference",
|
||||||
SyntaxShape::String,
|
SyntaxShape::String,
|
||||||
@ -58,7 +66,7 @@ impl Command for Touch {
|
|||||||
let mut change_atime: bool = call.has_flag(engine_state, stack, "access")?;
|
let mut change_atime: bool = call.has_flag(engine_state, stack, "access")?;
|
||||||
let reference: Option<Spanned<String>> = call.get_flag(engine_state, stack, "reference")?;
|
let reference: Option<Spanned<String>> = call.get_flag(engine_state, stack, "reference")?;
|
||||||
let no_create: bool = call.has_flag(engine_state, stack, "no-create")?;
|
let no_create: bool = call.has_flag(engine_state, stack, "no-create")?;
|
||||||
let files: Vec<String> = call.rest(engine_state, stack, 0)?;
|
let files: Vec<Spanned<NuGlob>> = get_rest_for_glob_pattern(engine_state, stack, call, 0)?;
|
||||||
|
|
||||||
if files.is_empty() {
|
if files.is_empty() {
|
||||||
return Err(ShellError::MissingParameter {
|
return Err(ShellError::MissingParameter {
|
||||||
@ -105,8 +113,10 @@ impl Command for Touch {
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index, item) in files.into_iter().enumerate() {
|
let cwd = current_dir(engine_state, stack)?;
|
||||||
let path = Path::new(&item);
|
|
||||||
|
for (index, glob) in files.into_iter().enumerate() {
|
||||||
|
let path = expand_path_with(glob.item.as_ref(), &cwd, glob.item.is_expand());
|
||||||
|
|
||||||
// If --no-create is passed and the file/dir does not exist there's nothing to do
|
// If --no-create is passed and the file/dir does not exist there's nothing to do
|
||||||
if no_create && !path.exists() {
|
if no_create && !path.exists() {
|
||||||
@ -119,7 +129,7 @@ impl Command for Touch {
|
|||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.truncate(false)
|
.truncate(false)
|
||||||
.open(path)
|
.open(&path)
|
||||||
{
|
{
|
||||||
return Err(ShellError::CreateNotPossible {
|
return Err(ShellError::CreateNotPossible {
|
||||||
msg: format!("Failed to create file: {err}"),
|
msg: format!("Failed to create file: {err}"),
|
||||||
@ -132,7 +142,7 @@ impl Command for Touch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if change_mtime {
|
if change_mtime {
|
||||||
if let Err(err) = filetime::set_file_mtime(&item, FileTime::from_system_time(mtime))
|
if let Err(err) = filetime::set_file_mtime(&path, FileTime::from_system_time(mtime))
|
||||||
{
|
{
|
||||||
return Err(ShellError::ChangeModifiedTimeNotPossible {
|
return Err(ShellError::ChangeModifiedTimeNotPossible {
|
||||||
msg: format!("Failed to change the modified time: {err}"),
|
msg: format!("Failed to change the modified time: {err}"),
|
||||||
@ -145,7 +155,7 @@ impl Command for Touch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if change_atime {
|
if change_atime {
|
||||||
if let Err(err) = filetime::set_file_atime(&item, FileTime::from_system_time(atime))
|
if let Err(err) = filetime::set_file_atime(&path, FileTime::from_system_time(atime))
|
||||||
{
|
{
|
||||||
return Err(ShellError::ChangeAccessTimeNotPossible {
|
return Err(ShellError::ChangeAccessTimeNotPossible {
|
||||||
msg: format!("Failed to change the access time: {err}"),
|
msg: format!("Failed to change the access time: {err}"),
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::{command_prelude::*, current_dir};
|
||||||
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use uu_mkdir::mkdir;
|
use uu_mkdir::mkdir;
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
use uucore::mode;
|
use uucore::mode;
|
||||||
|
|
||||||
|
use super::util::get_rest_for_glob_pattern;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct UMkdir;
|
pub struct UMkdir;
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ impl Command for UMkdir {
|
|||||||
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
.input_output_types(vec![(Type::Nothing, Type::Nothing)])
|
||||||
.rest(
|
.rest(
|
||||||
"rest",
|
"rest",
|
||||||
SyntaxShape::Directory,
|
SyntaxShape::OneOf(vec![SyntaxShape::GlobPattern, SyntaxShape::Directory]),
|
||||||
"The name(s) of the path(s) to create.",
|
"The name(s) of the path(s) to create.",
|
||||||
)
|
)
|
||||||
.switch(
|
.switch(
|
||||||
@ -57,10 +58,10 @@ impl Command for UMkdir {
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let mut directories = call
|
let cwd = current_dir(engine_state, stack)?;
|
||||||
.rest::<String>(engine_state, stack, 0)?
|
let mut directories = get_rest_for_glob_pattern(engine_state, stack, call, 0)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(PathBuf::from)
|
.map(|dir| nu_path::expand_path_with(dir.item.as_ref(), &cwd, dir.item.is_expand()))
|
||||||
.peekable();
|
.peekable();
|
||||||
|
|
||||||
let is_verbose = call.has_flag(engine_state, stack, "verbose")?;
|
let is_verbose = call.has_flag(engine_state, stack, "verbose")?;
|
||||||
|
@ -502,3 +502,16 @@ fn create_a_file_with_tilde() {
|
|||||||
assert!(files_exist_at(vec![Path::new("~tilde2")], dirs.test()));
|
assert!(files_exist_at(vec![Path::new("~tilde2")], dirs.test()));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn respects_cwd() {
|
||||||
|
Playground::setup("touch_respects_cwd", |dirs, _sandbox| {
|
||||||
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"mkdir 'dir'; cd 'dir'; touch 'i_will_be_created.txt'"
|
||||||
|
);
|
||||||
|
|
||||||
|
let path = dirs.test().join("dir/i_will_be_created.txt");
|
||||||
|
assert!(path.exists());
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -123,6 +123,20 @@ fn creates_directory_three_dots_quotation_marks() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn respects_cwd() {
|
||||||
|
Playground::setup("mkdir_respects_cwd", |dirs, _| {
|
||||||
|
nu!(
|
||||||
|
cwd: dirs.test(),
|
||||||
|
"mkdir 'some_folder'; cd 'some_folder'; mkdir 'another/deeper_one'"
|
||||||
|
);
|
||||||
|
|
||||||
|
let expected = dirs.test().join("some_folder/another/deeper_one");
|
||||||
|
|
||||||
|
assert!(expected.exists());
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
#[test]
|
#[test]
|
||||||
fn mkdir_umask_permission() {
|
fn mkdir_umask_permission() {
|
||||||
|
Loading…
Reference in New Issue
Block a user