forked from nushell/nushell
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A `mkdir` command, which uses `uu_mkdir` as backend. close nushell#10515.
- Loading branch information
1 parent
b5e6986
commit 505c982
Showing
7 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
use nu_engine::env::current_dir; | ||
use nu_engine::CallExt; | ||
use nu_protocol::ast::Call; | ||
use nu_protocol::engine::{Command, EngineState, Stack}; | ||
use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type}; | ||
|
||
use uu_mkdir::mkdir; | ||
|
||
#[derive(Clone)] | ||
pub struct UMkdir; | ||
|
||
const IS_RECURSIVE: bool = true; | ||
// This is the same default as Rust's std uses: | ||
// https://doc.rust-lang.org/nightly/std/os/unix/fs/trait.DirBuilderExt.html#tymethod.mode | ||
const DEFAULT_MODE: u32 = 0o777; | ||
|
||
impl Command for UMkdir { | ||
fn name(&self) -> &str { | ||
"umkdir" | ||
} | ||
|
||
fn usage(&self) -> &str { | ||
"Create directories, with intermediary directories if required using uutils/coreutils mkdir." | ||
} | ||
|
||
fn search_terms(&self) -> Vec<&str> { | ||
vec!["directory", "folder", "create", "make_dirs", "coreutils"] | ||
} | ||
|
||
fn signature(&self) -> Signature { | ||
Signature::build("umkdir") | ||
.input_output_types(vec![(Type::Nothing, Type::Nothing)]) | ||
.rest( | ||
"rest", | ||
SyntaxShape::Directory, | ||
"the name(s) of the path(s) to create", | ||
) | ||
.switch( | ||
"verbose", | ||
"print a message for each created directory.", | ||
Some('v'), | ||
) | ||
.category(Category::FileSystem) | ||
} | ||
|
||
fn run( | ||
&self, | ||
engine_state: &EngineState, | ||
stack: &mut Stack, | ||
call: &Call, | ||
_input: PipelineData, | ||
) -> Result<PipelineData, ShellError> { | ||
let path = current_dir(engine_state, stack)?; | ||
let mut directories = call | ||
.rest::<String>(engine_state, stack, 0)? | ||
.into_iter() | ||
.map(|dir| path.join(dir)) | ||
.peekable(); | ||
|
||
let is_verbose = call.has_flag("verbose"); | ||
|
||
if directories.peek().is_none() { | ||
return Err(ShellError::MissingParameter { | ||
param_name: "requires directory paths".to_string(), | ||
span: call.head, | ||
}); | ||
} | ||
|
||
for dir in directories { | ||
if let Err(error) = mkdir(&dir, IS_RECURSIVE, DEFAULT_MODE, is_verbose) { | ||
return Err(ShellError::GenericError( | ||
format!("{}", error), | ||
format!("{}", error), | ||
None, | ||
None, | ||
Vec::new(), | ||
)); | ||
} | ||
} | ||
|
||
Ok(PipelineData::empty()) | ||
} | ||
|
||
fn examples(&self) -> Vec<Example> { | ||
vec![ | ||
Example { | ||
description: "Make a directory named foo", | ||
example: "umkdir foo", | ||
result: None, | ||
}, | ||
Example { | ||
description: "Make multiple directories and show the paths created", | ||
example: "umkdir -v foo/bar foo2", | ||
result: None, | ||
}, | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -105,6 +105,7 @@ mod touch; | |
mod transpose; | ||
mod try_; | ||
mod ucp; | ||
mod umkdir; | ||
mod uniq; | ||
mod uniq_by; | ||
mod update; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
use nu_test_support::fs::files_exist_at; | ||
use nu_test_support::playground::Playground; | ||
use nu_test_support::{nu, pipeline}; | ||
use std::path::Path; | ||
|
||
#[test] | ||
fn creates_directory() { | ||
Playground::setup("umkdir_test_1", |dirs, _| { | ||
nu!( | ||
cwd: dirs.test(), | ||
"umkdir my_new_directory" | ||
); | ||
|
||
let expected = dirs.test().join("my_new_directory"); | ||
|
||
assert!(expected.exists()); | ||
}) | ||
} | ||
|
||
#[test] | ||
fn accepts_and_creates_directories() { | ||
Playground::setup("umkdir_test_2", |dirs, _| { | ||
nu!( | ||
cwd: dirs.test(), | ||
"umkdir dir_1 dir_2 dir_3" | ||
); | ||
|
||
assert!(files_exist_at( | ||
vec![Path::new("dir_1"), Path::new("dir_2"), Path::new("dir_3")], | ||
dirs.test() | ||
)); | ||
}) | ||
} | ||
|
||
#[test] | ||
fn creates_intermediary_directories() { | ||
Playground::setup("umkdir_test_3", |dirs, _| { | ||
nu!( | ||
cwd: dirs.test(), | ||
"umkdir some_folder/another/deeper_one" | ||
); | ||
|
||
let expected = dirs.test().join("some_folder/another/deeper_one"); | ||
|
||
assert!(expected.exists()); | ||
}) | ||
} | ||
|
||
#[test] | ||
fn create_directory_two_parents_up_using_multiple_dots() { | ||
Playground::setup("umkdir_test_4", |dirs, sandbox| { | ||
sandbox.within("foo").mkdir("bar"); | ||
|
||
nu!( | ||
cwd: dirs.test().join("foo/bar"), | ||
"umkdir .../boo" | ||
); | ||
|
||
let expected = dirs.test().join("boo"); | ||
|
||
assert!(expected.exists()); | ||
}) | ||
} | ||
|
||
#[test] | ||
fn print_created_paths() { | ||
Playground::setup("umkdir_test_2", |dirs, _| { | ||
let actual = nu!( | ||
cwd: dirs.test(), | ||
pipeline("umkdir -v dir_1 dir_2 dir_3") | ||
); | ||
|
||
assert!(files_exist_at( | ||
vec![Path::new("dir_1"), Path::new("dir_2"), Path::new("dir_3")], | ||
dirs.test() | ||
)); | ||
|
||
assert!(actual.out.contains("dir_1")); | ||
assert!(actual.out.contains("dir_2")); | ||
assert!(actual.out.contains("dir_3")); | ||
}) | ||
} | ||
|
||
#[test] | ||
fn creates_directory_three_dots() { | ||
Playground::setup("umkdir_test_1", |dirs, _| { | ||
nu!( | ||
cwd: dirs.test(), | ||
"umkdir test..." | ||
); | ||
|
||
let expected = dirs.test().join("test..."); | ||
|
||
assert!(expected.exists()); | ||
}) | ||
} | ||
|
||
#[test] | ||
fn creates_directory_four_dots() { | ||
Playground::setup("umkdir_test_1", |dirs, _| { | ||
nu!( | ||
cwd: dirs.test(), | ||
"umkdir test...." | ||
); | ||
|
||
let expected = dirs.test().join("test...."); | ||
|
||
assert!(expected.exists()); | ||
}) | ||
} | ||
|
||
#[test] | ||
fn creates_directory_three_dots_quotation_marks() { | ||
Playground::setup("umkdir_test_1", |dirs, _| { | ||
nu!( | ||
cwd: dirs.test(), | ||
"umkdir 'test...'" | ||
); | ||
|
||
let expected = dirs.test().join("test..."); | ||
|
||
assert!(expected.exists()); | ||
}) | ||
} |