Skip to content

Commit 8ccc45c

Browse files
authored
mkdir: recursive reporting of created directories in verbose mode (#3217)
1 parent 19af432 commit 8ccc45c

File tree

2 files changed

+63
-18
lines changed

2 files changed

+63
-18
lines changed

src/uu/mkdir/src/mkdir.rs

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
extern crate uucore;
1212

1313
use clap::{crate_version, App, AppSettings, Arg, ArgMatches, OsValues};
14-
use std::fs;
1514
use std::path::Path;
1615
use uucore::display::Quotable;
17-
use uucore::error::{FromIo, UResult, USimpleError};
16+
#[cfg(not(windows))]
17+
use uucore::error::FromIo;
18+
use uucore::error::{UResult, USimpleError};
1819
#[cfg(not(windows))]
1920
use uucore::mode;
2021
use uucore::{format_usage, InvalidEncodingHandling};
@@ -149,22 +150,7 @@ fn exec(dirs: OsValues, recursive: bool, mode: u32, verbose: bool) -> UResult<()
149150
}
150151

151152
fn mkdir(path: &Path, recursive: bool, mode: u32, verbose: bool) -> UResult<()> {
152-
let create_dir = if recursive {
153-
fs::create_dir_all
154-
} else {
155-
fs::create_dir
156-
};
157-
158-
create_dir(path).map_err_context(|| format!("cannot create directory {}", path.quote()))?;
159-
160-
if verbose {
161-
println!(
162-
"{}: created directory {}",
163-
uucore::util_name(),
164-
path.quote()
165-
);
166-
}
167-
153+
create_dir(path, recursive, verbose)?;
168154
chmod(path, mode)
169155
}
170156

@@ -184,3 +170,39 @@ fn chmod(_path: &Path, _mode: u32) -> UResult<()> {
184170
// chmod on Windows only sets the readonly flag, which isn't even honored on directories
185171
Ok(())
186172
}
173+
174+
fn create_dir(path: &Path, recursive: bool, verbose: bool) -> UResult<()> {
175+
if path.exists() && !recursive {
176+
return Err(USimpleError::new(
177+
1,
178+
format!("{}: File exists", path.display()),
179+
));
180+
}
181+
if path == Path::new("") {
182+
return Ok(());
183+
}
184+
185+
if recursive {
186+
match path.parent() {
187+
Some(p) => create_dir(p, recursive, verbose)?,
188+
None => {
189+
USimpleError::new(1, "failed to create whole tree");
190+
}
191+
}
192+
}
193+
194+
match std::fs::create_dir(path) {
195+
Ok(()) => {
196+
if verbose {
197+
println!(
198+
"{}: created directory {}",
199+
uucore::util_name(),
200+
path.quote()
201+
);
202+
}
203+
Ok(())
204+
}
205+
Err(_) if path.is_dir() => Ok(()),
206+
Err(e) => Err(e.into()),
207+
}
208+
}

tests/by-util/test_mkdir.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ static TEST_DIR4: &str = "mkdir_test4/mkdir_test4_1";
99
static TEST_DIR5: &str = "mkdir_test5/mkdir_test5_1";
1010
static TEST_DIR6: &str = "mkdir_test6";
1111
static TEST_FILE7: &str = "mkdir_test7";
12+
static TEST_DIR8: &str = "mkdir_test8/mkdir_test8_1/mkdir_test8_2";
13+
static TEST_DIR9: &str = "mkdir_test9/../mkdir_test9_1/../mkdir_test9_2";
1214

1315
#[test]
1416
fn test_mkdir_mkdir() {
@@ -100,3 +102,24 @@ fn test_multi_symbolic() {
100102
let perms = at.metadata(TEST_DIR1).permissions().mode();
101103
assert_eq!(perms, 0o40750);
102104
}
105+
106+
#[test]
107+
fn test_recursive_reporting() {
108+
new_ucmd!()
109+
.arg("-p")
110+
.arg("-v")
111+
.arg(TEST_DIR8)
112+
.succeeds()
113+
.stdout_contains("created directory 'mkdir_test8'")
114+
.stdout_contains("created directory 'mkdir_test8/mkdir_test8_1'")
115+
.stdout_contains("created directory 'mkdir_test8/mkdir_test8_1/mkdir_test8_2'");
116+
new_ucmd!().arg("-v").arg(TEST_DIR8).fails().no_stdout();
117+
new_ucmd!()
118+
.arg("-p")
119+
.arg("-v")
120+
.arg(TEST_DIR9)
121+
.succeeds()
122+
.stdout_contains("created directory 'mkdir_test9'")
123+
.stdout_contains("created directory 'mkdir_test9/../mkdir_test9_1'")
124+
.stdout_contains("created directory 'mkdir_test9/../mkdir_test9_1/../mkdir_test9_2'");
125+
}

0 commit comments

Comments
 (0)