From fbb64b9c5c046dc1f66802e5ab2f362d24c2c9e0 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 22 Mar 2022 23:08:47 +0100 Subject: [PATCH] mkdir: gnu compat: add support of mkdir -p foo/. --- src/uu/mkdir/src/mkdir.rs | 16 ++++++++++++---- tests/by-util/test_mkdir.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/uu/mkdir/src/mkdir.rs b/src/uu/mkdir/src/mkdir.rs index ed487bb58..35078d296 100644 --- a/src/uu/mkdir/src/mkdir.rs +++ b/src/uu/mkdir/src/mkdir.rs @@ -11,7 +11,7 @@ extern crate uucore; use clap::{crate_version, Arg, ArgMatches, Command, OsValues}; -use std::path::Path; +use std::path::{Path, PathBuf}; use uucore::display::Quotable; #[cfg(not(windows))] use uucore::error::FromIo; @@ -143,8 +143,17 @@ pub fn uu_app<'a>() -> Command<'a> { */ fn exec(dirs: OsValues, recursive: bool, mode: u32, verbose: bool) -> UResult<()> { for dir in dirs { - let path = Path::new(dir); - show_if_err!(mkdir(path, recursive, mode, verbose)); + // Special case to match GNU's behavior: + // mkdir -p foo/. should work and just create foo/ + // std::fs::create_dir("foo/."); fails in pure Rust + let path = if recursive && dir.to_string_lossy().ends_with("/.") { + // Do a simple dance to strip the "/." + Path::new(dir).components().collect::() + } else { + // Normal case + PathBuf::from(dir) + }; + show_if_err!(mkdir(path.as_path(), recursive, mode, verbose)); } Ok(()) } @@ -190,7 +199,6 @@ fn create_dir(path: &Path, recursive: bool, verbose: bool) -> UResult<()> { } } } - match std::fs::create_dir(path) { Ok(()) => { if verbose { diff --git a/tests/by-util/test_mkdir.rs b/tests/by-util/test_mkdir.rs index 011c7b25a..675ca6bea 100644 --- a/tests/by-util/test_mkdir.rs +++ b/tests/by-util/test_mkdir.rs @@ -11,6 +11,8 @@ 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"; +static TEST_DIR10: &str = "mkdir_test10/."; +static TEST_DIR11: &str = "mkdir_test11/.."; #[test] fn test_mkdir_mkdir() { @@ -123,3 +125,29 @@ fn test_recursive_reporting() { .stdout_contains("created directory 'mkdir_test9/../mkdir_test9_1'") .stdout_contains("created directory 'mkdir_test9/../mkdir_test9_1/../mkdir_test9_2'"); } + +#[test] +fn test_mkdir_trailing_dot() { + let scene2 = TestScenario::new("ls"); + new_ucmd!() + .arg("-p") + .arg("-v") + .arg("mkdir_test10-2") + .succeeds(); + + new_ucmd!() + .arg("-p") + .arg("-v") + .arg(TEST_DIR10) + .succeeds() + .stdout_contains("created directory 'mkdir_test10'"); + + new_ucmd!() + .arg("-p") + .arg("-v") + .arg(TEST_DIR11) + .succeeds() + .stdout_contains("created directory 'mkdir_test11'"); + let result = scene2.cmd("ls").arg("-al").run(); + println!("ls dest {}", result.stdout_str()); +}