mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 19:17:43 +00:00
Merge pull request #3353 from sylvestre/install
install: support of `-d dir/.` to match GNU's
This commit is contained in:
commit
a219d9e355
4 changed files with 66 additions and 7 deletions
|
@ -20,6 +20,7 @@ use uucore::display::Quotable;
|
|||
use uucore::entries::{grp2gid, usr2uid};
|
||||
use uucore::error::{FromIo, UError, UIoError, UResult, UUsageError};
|
||||
use uucore::format_usage;
|
||||
use uucore::fs::dir_strip_dot_for_creation;
|
||||
use uucore::mode::get_umask;
|
||||
use uucore::perms::{wrap_chown, Verbosity, VerbosityLevel};
|
||||
|
||||
|
@ -395,6 +396,11 @@ fn directory(paths: &[String], b: &Behavior) -> UResult<()> {
|
|||
for path in paths.iter().map(Path::new) {
|
||||
// if the path already exist, don't try to create it again
|
||||
if !path.exists() {
|
||||
// Special case to match GNU's behavior:
|
||||
// install -d foo/. should work and just create foo/
|
||||
// std::fs::create_dir("foo/."); fails in pure Rust
|
||||
// See also mkdir.rs for another occurrence of this
|
||||
let path_to_create = dir_strip_dot_for_creation(path);
|
||||
// Differently than the primary functionality
|
||||
// (MainFunction::Standard), the directory functionality should
|
||||
// create all ancestors (or components) of a directory
|
||||
|
@ -404,15 +410,15 @@ fn directory(paths: &[String], b: &Behavior) -> UResult<()> {
|
|||
// target directory. All created ancestor directories will have
|
||||
// the default mode. Hence it is safe to use fs::create_dir_all
|
||||
// and then only modify the target's dir mode.
|
||||
if let Err(e) =
|
||||
fs::create_dir_all(path).map_err_context(|| path.maybe_quote().to_string())
|
||||
if let Err(e) = fs::create_dir_all(path_to_create.as_path())
|
||||
.map_err_context(|| path_to_create.as_path().maybe_quote().to_string())
|
||||
{
|
||||
show!(e);
|
||||
continue;
|
||||
}
|
||||
|
||||
if b.verbose {
|
||||
println!("creating directory {}", path.quote());
|
||||
println!("creating directory {}", path_to_create.quote());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,12 +12,12 @@ extern crate uucore;
|
|||
|
||||
use clap::{crate_version, Arg, ArgMatches, Command, OsValues};
|
||||
use std::path::{Path, PathBuf};
|
||||
use uucore::display::Quotable;
|
||||
#[cfg(not(windows))]
|
||||
use uucore::error::FromIo;
|
||||
use uucore::error::{UResult, USimpleError};
|
||||
#[cfg(not(windows))]
|
||||
use uucore::mode;
|
||||
use uucore::{display::Quotable, fs::dir_strip_dot_for_creation};
|
||||
use uucore::{format_usage, InvalidEncodingHandling};
|
||||
|
||||
static DEFAULT_PERM: u32 = 0o755;
|
||||
|
@ -146,9 +146,8 @@ fn exec(dirs: OsValues, recursive: bool, mode: u32, verbose: bool) -> UResult<()
|
|||
// 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::<PathBuf>()
|
||||
let path = if recursive {
|
||||
dir_strip_dot_for_creation(&PathBuf::from(dir))
|
||||
} else {
|
||||
// Normal case
|
||||
PathBuf::from(dir)
|
||||
|
|
|
@ -470,6 +470,20 @@ pub fn display_permissions_unix(mode: mode_t, display_file_type: bool) -> String
|
|||
result
|
||||
}
|
||||
|
||||
// For some programs like install or mkdir, dir/. can be provided
|
||||
// Special case to match GNU's behavior:
|
||||
// install -d foo/. should work and just create foo/
|
||||
// std::fs::create_dir("foo/."); fails in pure Rust
|
||||
// See also mkdir.rs for another occurrence of this
|
||||
pub fn dir_strip_dot_for_creation(path: &Path) -> PathBuf {
|
||||
if path.to_string_lossy().ends_with("/.") {
|
||||
// Do a simple dance to strip the "/."
|
||||
Path::new(&path).components().collect::<PathBuf>()
|
||||
} else {
|
||||
path.to_path_buf()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
||||
|
|
|
@ -1124,3 +1124,43 @@ fn test_install_missing_destination() {
|
|||
file_1
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_dir_dot() {
|
||||
// To match tests/install/d-slashdot.sh
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
scene.ucmd().arg("-d").arg("dir1/.").succeeds();
|
||||
scene.ucmd().arg("-d").arg("dir2/..").succeeds();
|
||||
// Tests that we don't have dir3/. in the output
|
||||
// but only 'dir3'
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-d")
|
||||
.arg("dir3/.")
|
||||
.arg("-v")
|
||||
.succeeds()
|
||||
.stdout_contains("creating directory 'dir3'");
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-d")
|
||||
.arg("dir4/./cal")
|
||||
.arg("-v")
|
||||
.succeeds()
|
||||
.stdout_contains("creating directory 'dir4/./cal'");
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-d")
|
||||
.arg("dir5/./cali/.")
|
||||
.arg("-v")
|
||||
.succeeds()
|
||||
.stdout_contains("creating directory 'dir5/cali'");
|
||||
|
||||
let at = &scene.fixtures;
|
||||
|
||||
assert!(at.dir_exists("dir1"));
|
||||
assert!(at.dir_exists("dir2"));
|
||||
assert!(at.dir_exists("dir3"));
|
||||
assert!(at.dir_exists("dir4/cal"));
|
||||
assert!(at.dir_exists("dir5/cali"));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue