1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

cp: accept shortcuts for stringly-enum arguments

This commit is contained in:
Ben Wiederhake 2024-04-01 06:00:15 +02:00
parent bfc7411dec
commit d4546ced26
3 changed files with 88 additions and 63 deletions

View file

@ -37,8 +37,8 @@ use uucore::{backup_control, update_control};
// requires these enum.
pub use uucore::{backup_control::BackupMode, update_control::UpdateMode};
use uucore::{
format_usage, help_about, help_section, help_usage, prompt_yes, show_error, show_warning,
util_name,
format_usage, help_about, help_section, help_usage, prompt_yes,
shortcut_value_parser::ShortcutValueParser, show_error, show_warning, util_name,
};
use crate::copydir::copy_directory;
@ -396,22 +396,14 @@ static PRESERVABLE_ATTRIBUTES: &[&str] = &[
"ownership",
"timestamps",
"context",
"link",
"links",
"xattr",
"all",
];
#[cfg(not(unix))]
static PRESERVABLE_ATTRIBUTES: &[&str] = &[
"mode",
"timestamps",
"context",
"link",
"links",
"xattr",
"all",
];
static PRESERVABLE_ATTRIBUTES: &[&str] =
&["mode", "timestamps", "context", "links", "xattr", "all"];
pub fn uu_app() -> Command {
const MODE_ARGS: &[&str] = &[
@ -543,7 +535,7 @@ pub fn uu_app() -> Command {
.overrides_with_all(MODE_ARGS)
.require_equals(true)
.default_missing_value("always")
.value_parser(["auto", "always", "never"])
.value_parser(ShortcutValueParser::new(["auto", "always", "never"]))
.num_args(0..=1)
.help("control clone/CoW copies. See below"),
)
@ -559,9 +551,7 @@ pub fn uu_app() -> Command {
.long(options::PRESERVE)
.action(ArgAction::Append)
.use_value_delimiter(true)
.value_parser(clap::builder::PossibleValuesParser::new(
PRESERVABLE_ATTRIBUTES,
))
.value_parser(ShortcutValueParser::new(PRESERVABLE_ATTRIBUTES))
.num_args(0..)
.require_equals(true)
.value_name("ATTR_LIST")
@ -655,7 +645,7 @@ pub fn uu_app() -> Command {
Arg::new(options::SPARSE)
.long(options::SPARSE)
.value_name("WHEN")
.value_parser(["never", "auto", "always"])
.value_parser(ShortcutValueParser::new(["never", "auto", "always"]))
.help("control creation of sparse files. See below"),
)
// TODO: implement the following args

View file

@ -61,6 +61,7 @@ pub enum UpdateMode {
}
pub mod arguments {
use crate::shortcut_value_parser::ShortcutValueParser;
use clap::ArgAction;
pub static OPT_UPDATE: &str = "update";
@ -71,7 +72,7 @@ pub mod arguments {
clap::Arg::new(OPT_UPDATE)
.long("update")
.help("move only when the SOURCE file is newer than the destination file or when the destination file is missing")
.value_parser(["none", "all", "older"])
.value_parser(ShortcutValueParser::new(["none", "all", "older"]))
.num_args(0..=1)
.default_missing_value("older")
.require_equals(true)

View file

@ -2,7 +2,7 @@
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore (flags) reflink (fs) tmpfs (linux) rlimit Rlim NOFILE clob btrfs ROOTDIR USERDIR procfs outfile uufs xattrs
// spell-checker:ignore (flags) reflink (fs) tmpfs (linux) rlimit Rlim NOFILE clob btrfs neve ROOTDIR USERDIR procfs outfile uufs xattrs
use crate::common::util::TestScenario;
#[cfg(not(windows))]
@ -286,16 +286,18 @@ fn test_cp_arg_update_interactive_error() {
#[test]
fn test_cp_arg_update_none() {
for argument in ["--update=none", "--update=non", "--update=n"] {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.arg(TEST_HELLO_WORLD_SOURCE)
.arg(TEST_HOW_ARE_YOU_SOURCE)
.arg("--update=none")
.arg(argument)
.succeeds()
.no_stderr()
.no_stdout();
assert_eq!(at.read(TEST_HOW_ARE_YOU_SOURCE), "How are you?\n");
}
}
#[test]
@ -1402,6 +1404,7 @@ fn test_cp_preserve_no_args_before_opts() {
#[test]
fn test_cp_preserve_all() {
for argument in ["--preserve=all", "--preserve=al"] {
let (at, mut ucmd) = at_and_ucmd!();
let src_file = "a";
let dst_file = "b";
@ -1413,10 +1416,7 @@ fn test_cp_preserve_all() {
// TODO: create a destination that does not allow copying of xattr and context
// Copy
ucmd.arg(src_file)
.arg(dst_file)
.arg("--preserve=all")
.succeeds();
ucmd.arg(src_file).arg(dst_file).arg(argument).succeeds();
#[cfg(all(unix, not(target_os = "freebsd")))]
{
@ -1426,6 +1426,7 @@ fn test_cp_preserve_all() {
let metadata_dst = at.metadata(dst_file);
assert_metadata_eq!(metadata_src, metadata_dst);
}
}
}
#[test]
@ -1472,6 +1473,35 @@ fn test_cp_preserve_all_context_fails_on_non_selinux() {
.fails();
}
#[test]
fn test_cp_preserve_link_parses() {
// TODO: Also check whether --preserve=link did the right thing!
for argument in [
"--preserve=links",
"--preserve=link",
"--preserve=li",
"--preserve=l",
] {
new_ucmd!()
.arg(argument)
.arg(TEST_COPY_FROM_FOLDER_FILE)
.arg(TEST_HELLO_WORLD_DEST)
.succeeds()
.no_output();
}
}
#[test]
fn test_cp_preserve_invalid_rejected() {
new_ucmd!()
.arg("--preserve=invalid-value")
.arg(TEST_COPY_FROM_FOLDER_FILE)
.arg(TEST_HELLO_WORLD_DEST)
.fails()
.code_is(1)
.no_stdout();
}
#[test]
#[cfg(target_os = "android")]
#[cfg(disabled_until_fixed)] // FIXME: the test looks to .succeed on android
@ -2196,14 +2226,16 @@ fn test_cp_reflink_none() {
#[test]
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))]
fn test_cp_reflink_never() {
for argument in ["--reflink=never", "--reflink=neve", "--reflink=n"] {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.arg("--reflink=never")
ucmd.arg(argument)
.arg(TEST_HELLO_WORLD_SOURCE)
.arg(TEST_EXISTING_FILE)
.succeeds();
// Check the content of the destination file
assert_eq!(at.read(TEST_EXISTING_FILE), "Hello, World!\n");
}
}
#[test]
@ -2286,6 +2318,7 @@ fn test_cp_sparse_never_empty() {
#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn test_cp_sparse_always_empty() {
for argument in ["--sparse=always", "--sparse=alway", "--sparse=al"] {
let (at, mut ucmd) = at_and_ucmd!();
const BUFFER_SIZE: usize = 4096 * 4;
@ -2294,11 +2327,12 @@ fn test_cp_sparse_always_empty() {
at.make_file("src_file1");
at.write_bytes("src_file1", &buf);
ucmd.args(&["--sparse=always", "src_file1", "dst_file_sparse"])
ucmd.args(&[argument, "src_file1", "dst_file_sparse"])
.succeeds();
assert_eq!(at.read_bytes("dst_file_sparse"), buf);
assert_eq!(at.metadata("dst_file_sparse").blocks(), 0);
}
}
#[cfg(any(target_os = "linux", target_os = "android"))]