mkdir can take multiple directories or multiple directory hierachies and wil create them as required.

This commit is contained in:
Andrés N. Robalino 2019-08-21 07:07:37 -05:00
parent 23ef76a86b
commit 8b79b28971
2 changed files with 60 additions and 24 deletions

View File

@ -1,20 +1,25 @@
use crate::commands::command::RunnablePerItemContext;
use crate::errors::ShellError; use crate::errors::ShellError;
use crate::parser::hir::SyntaxType;
use crate::parser::registry::{CommandRegistry, Signature}; use crate::parser::registry::{CommandRegistry, Signature};
use crate::prelude::*; use crate::prelude::*;
use std::path::{Path, PathBuf}; use std::path::PathBuf;
pub struct Mkdir; pub struct Mkdir;
#[derive(Deserialize)]
struct MkdirArgs {
rest: Vec<Tagged<PathBuf>>,
}
impl PerItemCommand for Mkdir { impl PerItemCommand for Mkdir {
fn run( fn run(
&self, &self,
call_info: &CallInfo, call_info: &CallInfo,
registry: &CommandRegistry, _registry: &CommandRegistry,
shell_manager: &ShellManager, shell_manager: &ShellManager,
input: Tagged<Value>, _input: Tagged<Value>,
) -> Result<VecDeque<ReturnValue>, ShellError> { ) -> Result<VecDeque<ReturnValue>, ShellError> {
mkdir(call_info, registry, shell_manager, input) call_info.process(shell_manager, mkdir)?.run()
} }
fn name(&self) -> &str { fn name(&self) -> &str {
@ -22,29 +27,46 @@ impl PerItemCommand for Mkdir {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("mkdir").named("file", SyntaxType::Any) Signature::build("mkdir").rest()
} }
} }
pub fn mkdir( fn mkdir(
call_info: &CallInfo, MkdirArgs { rest: directories }: MkdirArgs,
_registry: &CommandRegistry, RunnablePerItemContext {
shell_manager: &ShellManager, name,
_input: Tagged<Value>, shell_manager,
..
}: &RunnablePerItemContext,
) -> Result<VecDeque<ReturnValue>, ShellError> { ) -> Result<VecDeque<ReturnValue>, ShellError> {
let mut full_path = PathBuf::from(shell_manager.path()); let full_path = PathBuf::from(shell_manager.path());
match &call_info.args.nth(0) { if directories.len() == 0 {
Some(Tagged { item: value, .. }) => full_path.push(Path::new(&value.as_string()?)), return Err(ShellError::labeled_error(
_ => {} "mkdir requires directory paths",
"needs parameter",
name,
));
} }
match std::fs::create_dir_all(full_path) { for dir in directories.iter() {
Err(reason) => Err(ShellError::labeled_error( let create_at = {
reason.to_string(), let mut loc = full_path.clone();
reason.to_string(), loc.push(&dir.item);
call_info.args.nth(0).unwrap().span(), loc
)), };
Ok(_) => Ok(VecDeque::new()),
match std::fs::create_dir_all(create_at) {
Err(reason) => {
return Err(ShellError::labeled_error(
reason.to_string(),
reason.to_string(),
dir.span(),
))
}
Ok(_) => {}
}
} }
Ok(VecDeque::new())
} }

View File

@ -2,7 +2,7 @@ mod helpers;
use h::{in_directory as cwd, Playground}; use h::{in_directory as cwd, Playground};
use helpers as h; use helpers as h;
use std::path::PathBuf; use std::path::{Path, PathBuf};
#[test] #[test]
fn creates_directory() { fn creates_directory() {
@ -19,11 +19,25 @@ fn creates_directory() {
} }
#[test] #[test]
fn creates_intermediary_directories() { fn accepts_and_creates_directories() {
let sandbox = Playground::setup_for("mkdir_test_2").test_dir_name(); let sandbox = Playground::setup_for("mkdir_test_2").test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox); let full_path = format!("{}/{}", Playground::root(), sandbox);
nu!(_output, cwd(&full_path), "mkdir dir_1 dir_2 dir_3");
assert!(h::files_exist_at(
vec![Path::new("dir_1"), Path::new("dir_2"), Path::new("dir_3")],
PathBuf::from(&full_path)
));
}
#[test]
fn creates_intermediary_directories() {
let sandbox = Playground::setup_for("mkdir_test_3").test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox);
nu!( nu!(
_output, _output,
cwd(&full_path), cwd(&full_path),