diff --git a/src/uu/mkdir/src/mkdir.rs b/src/uu/mkdir/src/mkdir.rs index b225bb300..14b1ebaf5 100644 --- a/src/uu/mkdir/src/mkdir.rs +++ b/src/uu/mkdir/src/mkdir.rs @@ -11,10 +11,11 @@ extern crate uucore; use clap::{crate_version, App, AppSettings, Arg, ArgMatches, OsValues}; -use std::fs; use std::path::Path; use uucore::display::Quotable; -use uucore::error::{FromIo, UResult, USimpleError}; +#[cfg(not(windows))] +use uucore::error::FromIo; +use uucore::error::{UResult, USimpleError}; #[cfg(not(windows))] use uucore::mode; use uucore::{format_usage, InvalidEncodingHandling}; @@ -149,22 +150,7 @@ fn exec(dirs: OsValues, recursive: bool, mode: u32, verbose: bool) -> UResult<() } fn mkdir(path: &Path, recursive: bool, mode: u32, verbose: bool) -> UResult<()> { - let create_dir = if recursive { - fs::create_dir_all - } else { - fs::create_dir - }; - - create_dir(path).map_err_context(|| format!("cannot create directory {}", path.quote()))?; - - if verbose { - println!( - "{}: created directory {}", - uucore::util_name(), - path.quote() - ); - } - + create_dir(path, recursive, verbose)?; chmod(path, mode) } @@ -184,3 +170,39 @@ fn chmod(_path: &Path, _mode: u32) -> UResult<()> { // chmod on Windows only sets the readonly flag, which isn't even honored on directories Ok(()) } + +fn create_dir(path: &Path, recursive: bool, verbose: bool) -> UResult<()> { + if path.exists() && !recursive { + return Err(USimpleError::new( + 1, + format!("{}: File exists", path.display()), + )); + } + if path == Path::new("") { + return Ok(()); + } + + if recursive { + match path.parent() { + Some(p) => create_dir(p, recursive, verbose)?, + None => { + USimpleError::new(1, "failed to create whole tree"); + } + } + } + + match std::fs::create_dir(path) { + Ok(()) => { + if verbose { + println!( + "{}: created directory {}", + uucore::util_name(), + path.quote() + ); + } + Ok(()) + } + Err(_) if path.is_dir() => Ok(()), + Err(e) => Err(e.into()), + } +} diff --git a/tests/by-util/test_mkdir.rs b/tests/by-util/test_mkdir.rs index e1038003b..011c7b25a 100644 --- a/tests/by-util/test_mkdir.rs +++ b/tests/by-util/test_mkdir.rs @@ -9,6 +9,8 @@ static TEST_DIR4: &str = "mkdir_test4/mkdir_test4_1"; static TEST_DIR5: &str = "mkdir_test5/mkdir_test5_1"; static TEST_DIR6: &str = "mkdir_test6"; static TEST_FILE7: &str = "mkdir_test7"; +static TEST_DIR8: &str = "mkdir_test8/mkdir_test8_1/mkdir_test8_2"; +static TEST_DIR9: &str = "mkdir_test9/../mkdir_test9_1/../mkdir_test9_2"; #[test] fn test_mkdir_mkdir() { @@ -100,3 +102,24 @@ fn test_multi_symbolic() { let perms = at.metadata(TEST_DIR1).permissions().mode(); assert_eq!(perms, 0o40750); } + +#[test] +fn test_recursive_reporting() { + new_ucmd!() + .arg("-p") + .arg("-v") + .arg(TEST_DIR8) + .succeeds() + .stdout_contains("created directory 'mkdir_test8'") + .stdout_contains("created directory 'mkdir_test8/mkdir_test8_1'") + .stdout_contains("created directory 'mkdir_test8/mkdir_test8_1/mkdir_test8_2'"); + new_ucmd!().arg("-v").arg(TEST_DIR8).fails().no_stdout(); + new_ucmd!() + .arg("-p") + .arg("-v") + .arg(TEST_DIR9) + .succeeds() + .stdout_contains("created directory 'mkdir_test9'") + .stdout_contains("created directory 'mkdir_test9/../mkdir_test9_1'") + .stdout_contains("created directory 'mkdir_test9/../mkdir_test9_1/../mkdir_test9_2'"); +}