mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
refactor(mkdir): Move to clap + add a test
This commit is contained in:
parent
a3f3a050a8
commit
897bcb2e67
4 changed files with 63 additions and 42 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1748,7 +1748,7 @@ dependencies = [
|
||||||
name = "uu_mkdir"
|
name = "uu_mkdir"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"uucore 0.0.4 (git+https://github.com/uutils/uucore.git?branch=canary)",
|
"uucore 0.0.4 (git+https://github.com/uutils/uucore.git?branch=canary)",
|
||||||
"uucore_procs 0.0.4 (git+https://github.com/uutils/uucore.git?branch=canary)",
|
"uucore_procs 0.0.4 (git+https://github.com/uutils/uucore.git?branch=canary)",
|
||||||
|
|
|
@ -15,7 +15,7 @@ edition = "2018"
|
||||||
path = "src/mkdir.rs"
|
path = "src/mkdir.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
getopts = "0.2.18"
|
clap = "2.33"
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version="0.0.4", package="uucore", git="https://github.com/uutils/uucore.git", branch="canary", features=["fs", "mode"] }
|
uucore = { version="0.0.4", package="uucore", git="https://github.com/uutils/uucore.git", branch="canary", features=["fs", "mode"] }
|
||||||
uucore_procs = { version="0.0.4", package="uucore_procs", git="https://github.com/uutils/uucore.git", branch="canary" }
|
uucore_procs = { version="0.0.4", package="uucore_procs", git="https://github.com/uutils/uucore.git", branch="canary" }
|
||||||
|
|
|
@ -5,53 +5,78 @@
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * file that was distributed with this source code.
|
||||||
|
|
||||||
extern crate getopts;
|
extern crate clap;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate uucore;
|
extern crate uucore;
|
||||||
|
|
||||||
|
use clap::{App, Arg};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
static NAME: &str = "mkdir";
|
static ABOUT: &str = "Create the given DIRECTORY(ies) if they do not exist";
|
||||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
static OPT_MODE: &str = "mode";
|
||||||
|
static OPT_PARENTS: &str = "parents";
|
||||||
|
static OPT_VERBOSE: &str = "verbose";
|
||||||
|
|
||||||
|
static ARG_DIRS: &str = "dirs";
|
||||||
|
|
||||||
|
fn get_usage() -> String {
|
||||||
|
format!("{0} [OPTION]... [USER]", executable!())
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles option parsing
|
* Handles option parsing
|
||||||
*/
|
*/
|
||||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
let args = args.collect_str();
|
let usage = get_usage();
|
||||||
|
|
||||||
let mut opts = getopts::Options::new();
|
|
||||||
|
|
||||||
// Linux-specific options, not implemented
|
// Linux-specific options, not implemented
|
||||||
// opts.optflag("Z", "context", "set SELinux security context" +
|
// opts.optflag("Z", "context", "set SELinux security context" +
|
||||||
// " of each created directory to CTX"),
|
// " of each created directory to CTX"),
|
||||||
opts.optopt("m", "mode", "set file mode", "755");
|
let matches = App::new(executable!())
|
||||||
opts.optflag("p", "parents", "make parent directories as needed");
|
.version(VERSION)
|
||||||
opts.optflag("v", "verbose", "print a message for each printed directory");
|
.about(ABOUT)
|
||||||
opts.optflag("h", "help", "display this help");
|
.usage(&usage[..])
|
||||||
opts.optflag("V", "version", "display this version");
|
.arg(
|
||||||
|
Arg::with_name(OPT_MODE)
|
||||||
|
.short("m")
|
||||||
|
.long(OPT_MODE)
|
||||||
|
.help("set file mode")
|
||||||
|
.default_value("755"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(OPT_PARENTS)
|
||||||
|
.short("p")
|
||||||
|
.long(OPT_PARENTS)
|
||||||
|
.help("make parent directories as needed"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(OPT_VERBOSE)
|
||||||
|
.short("v")
|
||||||
|
.long(OPT_VERBOSE)
|
||||||
|
.help("print a message for each printed directory"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(ARG_DIRS)
|
||||||
|
.multiple(true)
|
||||||
|
.takes_value(true)
|
||||||
|
.min_values(1),
|
||||||
|
)
|
||||||
|
.get_matches_from(args);
|
||||||
|
|
||||||
let matches = match opts.parse(&args[1..]) {
|
let dirs: Vec<String> = matches
|
||||||
Ok(m) => m,
|
.values_of(ARG_DIRS)
|
||||||
Err(f) => crash!(1, "Invalid options\n{}", f),
|
.map(|v| v.map(ToString::to_string).collect())
|
||||||
};
|
.unwrap_or_default();
|
||||||
|
|
||||||
if args.len() == 1 || matches.opt_present("help") {
|
let verbose = matches.is_present(OPT_VERBOSE);
|
||||||
print_help(&opts);
|
let recursive = matches.is_present(OPT_PARENTS);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if matches.opt_present("version") {
|
|
||||||
println!("{} {}", NAME, VERSION);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
let verbose = matches.opt_present("verbose");
|
|
||||||
let recursive = matches.opt_present("parents");
|
|
||||||
|
|
||||||
// Translate a ~str in octal form to u16, default to 755
|
// Translate a ~str in octal form to u16, default to 755
|
||||||
// Not tested on Windows
|
// Not tested on Windows
|
||||||
let mode_match = matches.opts_str(&["mode".to_owned()]);
|
let mode_match = matches.value_of(OPT_MODE);
|
||||||
let mode: u16 = match mode_match {
|
let mode: u16 = match mode_match {
|
||||||
Some(m) => {
|
Some(m) => {
|
||||||
let res: Option<u16> = u16::from_str_radix(&m, 8).ok();
|
let res: Option<u16> = u16::from_str_radix(&m, 8).ok();
|
||||||
|
@ -63,23 +88,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
_ => 0o755 as u16,
|
_ => 0o755 as u16,
|
||||||
};
|
};
|
||||||
|
|
||||||
let dirs = matches.free;
|
|
||||||
if dirs.is_empty() {
|
|
||||||
crash!(1, "missing operand");
|
|
||||||
}
|
|
||||||
exec(dirs, recursive, mode, verbose)
|
exec(dirs, recursive, mode, verbose)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_help(opts: &getopts::Options) {
|
|
||||||
println!("{} {}", NAME, VERSION);
|
|
||||||
println!();
|
|
||||||
println!("Usage:");
|
|
||||||
print!(
|
|
||||||
"{}",
|
|
||||||
opts.usage("Create the given DIRECTORY(ies) if they do not exist")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the list of new directories
|
* Create the list of new directories
|
||||||
*/
|
*/
|
||||||
|
@ -120,7 +131,7 @@ fn mkdir(path: &Path, recursive: bool, mode: u16, verbose: bool) -> i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
show_info!("created directory '{}'", path.display());
|
println!("{}: created directory '{}'", executable!(), path.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(unix, target_os = "redox"))]
|
#[cfg(any(unix, target_os = "redox"))]
|
||||||
|
|
|
@ -13,6 +13,16 @@ fn test_mkdir_mkdir() {
|
||||||
new_ucmd!().arg(TEST_DIR1).succeeds();
|
new_ucmd!().arg(TEST_DIR1).succeeds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mkdir_verbose() {
|
||||||
|
let expected = "mkdir: created directory 'mkdir_test1'\n";
|
||||||
|
new_ucmd!()
|
||||||
|
.arg(TEST_DIR1)
|
||||||
|
.arg("-v")
|
||||||
|
.run()
|
||||||
|
.stdout_is(expected);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mkdir_dup_dir() {
|
fn test_mkdir_dup_dir() {
|
||||||
let scene = TestScenario::new(util_name!());
|
let scene = TestScenario::new(util_name!());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue