From 32260273b736f4111a9ddfcbc152f6c5386fcbf6 Mon Sep 17 00:00:00 2001 From: Cedric Erdelen Date: Mon, 2 Feb 2026 20:29:54 +0100 Subject: [PATCH 1/2] du: Flags 'm', 'k', 'm' should be POSIX style overriden --- src/uu/du/src/du.rs | 15 ++++++++++++++ tests/by-util/test_du.rs | 42 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index d8bfd4446a1..90f865f3194 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -1281,6 +1281,11 @@ pub fn uu_app() -> Command { Arg::new(options::BYTES) .short('b') .long("bytes") + .overrides_with_all([ + options::BLOCK_SIZE_1K, + options::BLOCK_SIZE_1M, + options::BYTES, + ]) .help(translate!("du-help-bytes")) .action(ArgAction::SetTrue), ) @@ -1314,6 +1319,11 @@ pub fn uu_app() -> Command { .arg( Arg::new(options::BLOCK_SIZE_1K) .short('k') + .overrides_with_all([ + options::BLOCK_SIZE_1K, + options::BLOCK_SIZE_1M, + options::BYTES, + ]) .help(translate!("du-help-block-size-1k")) .action(ArgAction::SetTrue), ) @@ -1350,6 +1360,11 @@ pub fn uu_app() -> Command { .arg( Arg::new(options::BLOCK_SIZE_1M) .short('m') + .overrides_with_all([ + options::BLOCK_SIZE_1K, + options::BLOCK_SIZE_1M, + options::BYTES, + ]) .help(translate!("du-help-block-size-1m")) .action(ArgAction::SetTrue), ) diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index c89cd46678c..458b08cee27 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -2058,3 +2058,45 @@ fn test_du_symlinks_multiple_links_in_args() { result.stdout_contains("dir1/file"); result.stdout_does_not_contain("dir1/link"); } + +#[test] +fn test_block_size_args_override() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + let dir = "a"; + + at.mkdir(dir); + let fpath = at.plus(format!("{dir}/file")); + std::fs::File::create(&fpath) + .expect("cannot create test file") + .set_len(100_000_000) + .expect("cannot set file size"); + + let test_cases = [ + (["-sb", "-m"], "-sm"), + (["-sm", "-b"], "-sb"), + (["-sk", "-b"], "-sb"), + (["-sm", "-k"], "-sk"), + ]; + + for (overwriting_args, expected) in test_cases { + let decimal = ts + .ucmd() + .arg(dir) + .args(&overwriting_args) + .succeeds() + .stdout_move_str(); + + let binary = ts + .ucmd() + .arg(dir) + .arg(expected) + .succeeds() + .stdout_move_str(); + + assert_eq!( + decimal, binary, + "The last argument of m, k and b should overwrite" + ); + } +} From 85db938ae26461f3bf8c1ce100a179c380d2b913 Mon Sep 17 00:00:00 2001 From: cerdelen <95369756+cerdelen@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:06:09 +0100 Subject: [PATCH 2/2] du: overwriting b flag doesnt deactivate --apparent-size --- src/uu/du/src/du.rs | 57 +++++++++++++++++++++------------ tests/by-util/test_du.rs | 69 ++++++++++++++++++++++++++++++++++------ 2 files changed, 96 insertions(+), 30 deletions(-) diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index 90f865f3194..a0922ce03fc 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -959,6 +959,40 @@ fn read_files_from(file_name: &OsStr) -> Result, std::io::Error> { Ok(paths) } +fn get_block_size_arg_index_if_present(matches: &ArgMatches, flag: &str) -> Option { + if matches.get_flag(flag) { + // Indices of returns index even if flag is not present, thats why we need to if guard it + matches + .indices_of(flag) + .and_then(|mut indices| indices.next_back()) + } else { + None + } +} + +fn handle_block_size_arg_override(matches: &ArgMatches) -> Option { + let candidates = [ + ( + SizeFormat::BlockSize(1), + get_block_size_arg_index_if_present(matches, options::BYTES), + ), + ( + SizeFormat::BlockSize(1024), + get_block_size_arg_index_if_present(matches, options::BLOCK_SIZE_1K), + ), + ( + SizeFormat::BlockSize(1024 * 1024), + get_block_size_arg_index_if_present(matches, options::BLOCK_SIZE_1M), + ), + ]; + + candidates + .into_iter() + .filter(|(_, idx)| idx.is_some()) + .max_by_key(|&(_, idx)| idx.unwrap_or(0)) + .map(|(size_format, _)| size_format) +} + #[uucore::main] #[allow(clippy::cognitive_complexity)] pub fn uumain(args: impl uucore::Args) -> UResult<()> { @@ -1014,12 +1048,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { SizeFormat::HumanBinary } else if matches.get_flag(options::SI) { SizeFormat::HumanDecimal - } else if matches.get_flag(options::BYTES) { - SizeFormat::BlockSize(1) - } else if matches.get_flag(options::BLOCK_SIZE_1K) { - SizeFormat::BlockSize(1024) - } else if matches.get_flag(options::BLOCK_SIZE_1M) { - SizeFormat::BlockSize(1024 * 1024) + } else if let Some(size_format) = handle_block_size_arg_override(&matches) { + size_format } else { let block_size_str = matches.get_one::(options::BLOCK_SIZE); let block_size = read_block_size(block_size_str.map(AsRef::as_ref))?; @@ -1281,11 +1311,6 @@ pub fn uu_app() -> Command { Arg::new(options::BYTES) .short('b') .long("bytes") - .overrides_with_all([ - options::BLOCK_SIZE_1K, - options::BLOCK_SIZE_1M, - options::BYTES, - ]) .help(translate!("du-help-bytes")) .action(ArgAction::SetTrue), ) @@ -1319,11 +1344,6 @@ pub fn uu_app() -> Command { .arg( Arg::new(options::BLOCK_SIZE_1K) .short('k') - .overrides_with_all([ - options::BLOCK_SIZE_1K, - options::BLOCK_SIZE_1M, - options::BYTES, - ]) .help(translate!("du-help-block-size-1k")) .action(ArgAction::SetTrue), ) @@ -1360,11 +1380,6 @@ pub fn uu_app() -> Command { .arg( Arg::new(options::BLOCK_SIZE_1M) .short('m') - .overrides_with_all([ - options::BLOCK_SIZE_1K, - options::BLOCK_SIZE_1M, - options::BYTES, - ]) .help(translate!("du-help-block-size-1m")) .action(ArgAction::SetTrue), ) diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index 458b08cee27..2be6ef02c36 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -2063,31 +2063,36 @@ fn test_du_symlinks_multiple_links_in_args() { fn test_block_size_args_override() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; - let dir = "a"; + let dir = "override_args_dir"; at.mkdir(dir); let fpath = at.plus(format!("{dir}/file")); - std::fs::File::create(&fpath) + std::fs::File::create(fpath) + .expect("cannot create test file") + .set_len(100_000_000) + .expect("cannot set file size"); + + let fpath2 = at.plus(format!("{dir}/file_2")); + std::fs::File::create(fpath2) .expect("cannot create test file") .set_len(100_000_000) .expect("cannot set file size"); let test_cases = [ - (["-sb", "-m"], "-sm"), - (["-sm", "-b"], "-sb"), + (["-sk", "-m"], "-sm"), (["-sk", "-b"], "-sb"), (["-sm", "-k"], "-sk"), ]; - for (overwriting_args, expected) in test_cases { - let decimal = ts + for (idx, (overwriting_args, expected)) in test_cases.into_iter().enumerate() { + let overridden_args = ts .ucmd() .arg(dir) .args(&overwriting_args) .succeeds() .stdout_move_str(); - let binary = ts + let single_args = ts .ucmd() .arg(dir) .arg(expected) @@ -2095,8 +2100,54 @@ fn test_block_size_args_override() { .stdout_move_str(); assert_eq!( - decimal, binary, - "The last argument of m, k and b should overwrite" + overridden_args, single_args, + "The last argument of m, k and b should overwrite. Run: {idx}" + ); + } +} + +#[test] +fn test_block_override_b_still_has_apparent_size() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + let dir = "override_args_dir"; + + at.mkdir(dir); + let fpath = at.plus(format!("{dir}/file")); + std::fs::File::create(fpath) + .expect("cannot create test file") + .set_len(100_000_000) + .expect("cannot set file size"); + + let fpath2 = at.plus(format!("{dir}/file_2")); + std::fs::File::create(fpath2) + .expect("cannot create test file") + .set_len(100_000_000) + .expect("cannot set file size"); + + let test_cases = [ + (["-sb", "-m"], ["-sm", "--apparent-size"]), + (["-sb", "-k"], ["-sk", "--apparent-size"]), + ]; + + for (idx, (overwriting_args, expected)) in test_cases.into_iter().enumerate() { + let overridden_args = ts + .ucmd() + .arg(dir) + .args(&overwriting_args) + .succeeds() + .stdout_move_str(); + + let single_args = ts + .ucmd() + .arg(dir) + .args(&expected) + .succeeds() + .stdout_move_str(); + + assert_eq!( + overridden_args, single_args, + "Overwriting the b flag should still leave --apparent-size active. Run: {idx}" ); } }