diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index a199dc84adf..a7e84468d0f 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -1289,6 +1289,7 @@ pub fn uu_app() -> Command { .long(options::ALL) .help(translate!("du-help-all")) .conflicts_with(options::SUMMARIZE) + .overrides_with(options::ALL) .action(ArgAction::SetTrue), ) .arg( @@ -1296,68 +1297,78 @@ pub fn uu_app() -> Command { .short('A') .long(options::APPARENT_SIZE) .help(translate!("du-help-apparent-size")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::APPARENT_SIZE), ) .arg( Arg::new(options::BLOCK_SIZE) .short('B') .long(options::BLOCK_SIZE) .value_name("SIZE") - .help(translate!("du-help-block-size")), + .help(translate!("du-help-block-size")) + .overrides_with(options::BLOCK_SIZE), ) .arg( Arg::new(options::BYTES) .short('b') .long("bytes") .help(translate!("du-help-bytes")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::BYTES), ) .arg( Arg::new(options::TOTAL) .long("total") .short('c') .help(translate!("du-help-total")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::TOTAL), ) .arg( Arg::new(options::MAX_DEPTH) .short('d') .long("max-depth") .value_name("N") - .help(translate!("du-help-max-depth")), + .help(translate!("du-help-max-depth")) + .overrides_with(options::MAX_DEPTH), ) .arg( Arg::new(options::HUMAN_READABLE) .long("human-readable") .short('h') .help(translate!("du-help-human-readable")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::HUMAN_READABLE), ) .arg( Arg::new(options::INODES) .long(options::INODES) .help(translate!("du-help-inodes")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::INODES), ) .arg( Arg::new(options::BLOCK_SIZE_1K) .short('k') .help(translate!("du-help-block-size-1k")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::BLOCK_SIZE_1K), ) .arg( Arg::new(options::COUNT_LINKS) .short('l') .long("count-links") .help(translate!("du-help-count-links")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::COUNT_LINKS), ) .arg( Arg::new(options::DEREFERENCE) .short('L') .long(options::DEREFERENCE) .help(translate!("du-help-dereference")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::DEREFERENCE), ) .arg( Arg::new(options::DEREFERENCE_ARGS) @@ -1365,7 +1376,8 @@ pub fn uu_app() -> Command { .visible_short_alias('H') .long(options::DEREFERENCE_ARGS) .help(translate!("du-help-dereference-args")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::DEREFERENCE_ARGS), ) .arg( Arg::new(options::NO_DEREFERENCE) @@ -1373,47 +1385,54 @@ pub fn uu_app() -> Command { .long(options::NO_DEREFERENCE) .help(translate!("du-help-no-dereference")) .overrides_with(options::DEREFERENCE) + .overrides_with(options::NO_DEREFERENCE) .action(ArgAction::SetTrue), ) .arg( Arg::new(options::BLOCK_SIZE_1M) .short('m') .help(translate!("du-help-block-size-1m")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::BLOCK_SIZE_1M), ) .arg( Arg::new(options::NULL) .short('0') .long("null") .help(translate!("du-help-null")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::NULL), ) .arg( Arg::new(options::SEPARATE_DIRS) .short('S') .long("separate-dirs") .help(translate!("du-help-separate-dirs")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::SEPARATE_DIRS), ) .arg( Arg::new(options::SUMMARIZE) .short('s') .long("summarize") .help(translate!("du-help-summarize")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::SUMMARIZE), ) .arg( Arg::new(options::SI) .long(options::SI) .help(translate!("du-help-si")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::SI), ) .arg( Arg::new(options::ONE_FILE_SYSTEM) .short('x') .long(options::ONE_FILE_SYSTEM) .help(translate!("du-help-one-file-system")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::ONE_FILE_SYSTEM), ) .arg( Arg::new(options::THRESHOLD) @@ -1422,14 +1441,16 @@ pub fn uu_app() -> Command { .value_name("SIZE") .num_args(1) .allow_hyphen_values(true) - .help(translate!("du-help-threshold")), + .help(translate!("du-help-threshold")) + .overrides_with(options::THRESHOLD), ) .arg( Arg::new(options::VERBOSE) .short('v') .long("verbose") .help(translate!("du-help-verbose")) - .action(ArgAction::SetTrue), + .action(ArgAction::SetTrue) + .overrides_with(options::VERBOSE), ) .arg( Arg::new(options::EXCLUDE) @@ -1467,13 +1488,15 @@ pub fn uu_app() -> Command { PossibleValue::new("ctime").alias("status"), PossibleValue::new("creation").alias("birth"), ])) - .help(translate!("du-help-time")), + .help(translate!("du-help-time")) + .overrides_with(options::TIME), ) .arg( Arg::new(options::TIME_STYLE) .long(options::TIME_STYLE) .value_name("STYLE") - .help(translate!("du-help-time-style")), + .help(translate!("du-help-time-style")) + .overrides_with(options::TIME_STYLE), ) .arg( Arg::new(options::FILE) diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index 5aa8d904ea5..0adb1662703 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -2276,3 +2276,220 @@ fn test_overriding_block_size_arg_with_invalid_value_still_errors() { .fails_with_code(1) .stderr_contains("invalid --block-size argument 'abc'"); } + +#[test] +fn test_du_repeated_h() { + new_ucmd!().args(&["-s", "-h", "-h"]).succeeds(); +} + +#[test] +fn test_du_repeated_a() { + new_ucmd!().args(&["-a", "-a"]).succeeds(); +} + +#[test] +fn test_du_repeated_apparent_size() { + new_ucmd!() + .args(&["-s", "-A", "-A"]) + .succeeds() + .stdout_only("6\t.\n"); +} + +#[test] +fn test_du_repeated_block_size() { + new_ucmd!() + .args(&["-s", "-B", "100", "-B", "100"]) + .succeeds(); +} + +#[test] +fn test_du_repeated_b() { + new_ucmd!() + .args(&["-s", "-b", "-b"]) + .succeeds() + .stdout_only("5148\t.\n"); +} + +#[test] +fn test_du_repeated_c() { + new_ucmd!().args(&["-s", "-c", "-c"]).succeeds(); +} + +#[test] +fn test_du_repeated_d() { + new_ucmd!().args(&["-d", "2", "-d", "2"]).succeeds(); +} + +#[test] +fn test_du_repeated_inodes() { + new_ucmd!() + .args(&["-s", "--inodes", "--inodes"]) + .succeeds() + .stdout_only("11\t.\n"); +} + +#[test] +fn test_du_repeated_k() { + new_ucmd!().args(&["-s", "-k", "-k"]).succeeds(); +} + +#[test] +fn test_du_repeated_l() { + new_ucmd!().args(&["-s", "-l", "-l"]).succeeds(); +} + +#[test] +fn test_du_repeated_dereference() { + new_ucmd!().args(&["-s", "-L", "-L"]).succeeds(); +} + +#[test] +fn test_du_repeated_dereference_args() { + new_ucmd!().args(&["-s", "-D", "-D"]).succeeds(); +} + +#[test] +fn test_du_repeated_no_dereference() { + new_ucmd!().args(&["-s", "-P", "-P"]).succeeds(); +} + +#[test] +fn test_du_repeated_m() { + new_ucmd!() + .args(&["-s", "-m", "-m"]) + .succeeds() + .stdout_only("1\t.\n"); +} + +#[test] +fn test_du_repeated_0() { + new_ucmd!().args(&["-s", "-0", "-0"]).succeeds(); +} + +#[test] +fn test_du_repeated_separate_dirs() { + new_ucmd!().args(&["-s", "-S", "-S"]).succeeds(); +} + +#[test] +fn test_du_repeated_s() { + new_ucmd!().args(&["-s", "-s"]).succeeds(); +} + +#[test] +fn test_du_repeated_si() { + new_ucmd!().args(&["-s", "--si", "--si"]).succeeds(); +} + +#[test] +fn test_du_repeated_x() { + new_ucmd!().args(&["-s", "-x", "-x"]).succeeds(); +} + +#[test] +fn test_du_repeated_t() { + new_ucmd!() + .args(&["-s", "-t", "100", "-t", "100"]) + .succeeds(); +} + +#[test] +fn test_du_repeated_v() { + new_ucmd!().args(&["-s", "-v", "-v"]).succeeds(); +} + +#[test] +fn test_du_repeated_files0_from() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + + // Set up the data for use with command 'du' and argument '--files0-from'. + // File 'somefile' has to contain a list of NUL-terminated directory and + // file names. + at.mkdir("dir"); + at.write("dir/file2", "xyz"); + at.write("./somefile", "dir\0"); + + ts.ucmd() + .args(&[ + "-s", + "--files0-from", + "somefile", + "--files0-from", + "somefile", + ]) + .succeeds(); +} + +#[test] +#[cfg(feature = "touch")] +fn test_du_repeated_time() { + let ts = TestScenario::new(util_name!()); + + // du --time formats the timestamp according to the local timezone. We set the TZ + // environment variable to UTC in the commands below to ensure consistent outputs + // and test results regardless of the timezone of the machine this test runs in. + + ts.ccmd("touch") + .env("TZ", "UTC") + .arg("-a") + .arg("-t") + .arg("201505150000") + .arg("date_test") + .succeeds(); + + ts.ccmd("touch") + .env("TZ", "UTC") + .arg("-m") + .arg("-t") + .arg("201606160000") + .arg("date_test") + .succeeds(); + + let result = ts + .ucmd() + .env("TZ", "UTC") + .arg("--time") + .arg("date_test") + .arg("--time") + .arg("date_test") + .succeeds(); + result.stdout_only("0\t2016-06-16 00:00\tdate_test\n"); +} + +#[test] +#[cfg(feature = "touch")] +fn test_du_repeated_time_style() { + let ts = TestScenario::new(util_name!()); + + // du --time formats the timestamp according to the local timezone. We set the TZ + // environment variable to UTC in the commands below to ensure consistent outputs + // and test results regardless of the timezone of the machine this test runs in. + + ts.ccmd("touch") + .env("TZ", "UTC") + .arg("-a") + .arg("-t") + .arg("201505150000") + .arg("date_test") + .succeeds(); + + ts.ccmd("touch") + .env("TZ", "UTC") + .arg("-m") + .arg("-t") + .arg("201606160000") + .arg("date_test") + .succeeds(); + + // full-iso + let result = ts + .ucmd() + .env("TZ", "UTC") + .arg("--time") + .arg("--time-style=full-iso") + .arg("--time-style=full-iso") + .arg("date_test") + .succeeds(); + result.stdout_only("0\t2016-06-16 00:00:00.000000000 +0000\tdate_test\n"); +}