From 19db7a91d3e2ffe7ec69f48dd8e5d042857de7de Mon Sep 17 00:00:00 2001 From: cerdelen Date: Wed, 26 Mar 2025 15:43:11 +0100 Subject: [PATCH 1/3] Fixes #7558 Added check to only insert addition double hyphen if at start of arguments to correctly prepend addition hyphens for clap as well as additional test case --- src/uu/echo/src/echo.rs | 6 ++--- tests/by-util/test_echo.rs | 54 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/uu/echo/src/echo.rs b/src/uu/echo/src/echo.rs index c8d31a72945..d4a623c631b 100644 --- a/src/uu/echo/src/echo.rs +++ b/src/uu/echo/src/echo.rs @@ -27,12 +27,10 @@ mod options { // follows. In order to use '--' as a value, we have to inject an additional '--' fn handle_double_hyphens(args: impl uucore::Args) -> impl uucore::Args { let mut result = Vec::new(); - let mut is_first_double_hyphen = true; - for arg in args { - if arg == "--" && is_first_double_hyphen { + for (i, arg) in args.enumerate() { + if arg == "--" && i == 1 { result.push(OsString::from("--")); - is_first_double_hyphen = false; } result.push(arg); } diff --git a/tests/by-util/test_echo.rs b/tests/by-util/test_echo.rs index d4430d05655..db495b0d682 100644 --- a/tests/by-util/test_echo.rs +++ b/tests/by-util/test_echo.rs @@ -242,6 +242,37 @@ fn test_hyphen_values_between() { .stdout_is("dumdum dum dum dum -e dum\n"); } +#[test] +fn test_double_hyphens_at_start() { + new_ucmd!().arg("--").succeeds().stdout_only("--\n"); + new_ucmd!() + .arg("--") + .arg("--") + .succeeds() + .stdout_only("-- --\n"); + + new_ucmd!() + .arg("--") + .arg("a") + .succeeds() + .stdout_only("-- a\n"); + + new_ucmd!() + .arg("--") + .arg("a") + .arg("b") + .succeeds() + .stdout_only("-- a b\n"); + + new_ucmd!() + .arg("--") + .arg("a") + .arg("b") + .arg("--") + .succeeds() + .stdout_only("-- a b --\n"); +} + #[test] fn test_double_hyphens() { new_ucmd!().arg("--").succeeds().stdout_only("--\n"); @@ -250,6 +281,29 @@ fn test_double_hyphens() { .arg("--") .succeeds() .stdout_only("-- --\n"); + + new_ucmd!() + .arg("a") + .arg("--") + .arg("b") + .succeeds() + .stdout_only("a -- b\n"); + + new_ucmd!() + .arg("a") + .arg("--") + .arg("b") + .arg("--") + .succeeds() + .stdout_only("a -- b --\n"); + + new_ucmd!() + .arg("a") + .arg("b") + .arg("--") + .arg("--") + .succeeds() + .stdout_only("a b -- --\n"); } #[test] From b0df222d8bce6aee9edc7989d1519c5cb662644b Mon Sep 17 00:00:00 2001 From: cerdelen Date: Wed, 26 Mar 2025 19:42:27 +0100 Subject: [PATCH 2/3] additional comment --- src/uu/echo/src/echo.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/uu/echo/src/echo.rs b/src/uu/echo/src/echo.rs index d4a623c631b..612ad7e3934 100644 --- a/src/uu/echo/src/echo.rs +++ b/src/uu/echo/src/echo.rs @@ -29,7 +29,8 @@ fn handle_double_hyphens(args: impl uucore::Args) -> impl uucore::Args { let mut result = Vec::new(); for (i, arg) in args.enumerate() { - if arg == "--" && i == 1 { + // check for argument at index 1 which is the first argument to echo (0 being "echo") + if i == 1 && arg == "--" { result.push(OsString::from("--")); } result.push(arg); From a8d6780a40687337f83bb72a6424a733495f7941 Mon Sep 17 00:00:00 2001 From: cerdelen Date: Thu, 27 Mar 2025 09:26:22 +0100 Subject: [PATCH 3/3] fixes issue where flags precedes "--" as arguments --- src/uu/echo/src/echo.rs | 27 +++++++++++++++++----- tests/by-util/test_echo.rs | 47 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/uu/echo/src/echo.rs b/src/uu/echo/src/echo.rs index 612ad7e3934..7ce2fa9ad95 100644 --- a/src/uu/echo/src/echo.rs +++ b/src/uu/echo/src/echo.rs @@ -23,17 +23,32 @@ mod options { pub const DISABLE_BACKSLASH_ESCAPE: &str = "disable_backslash_escape"; } +fn is_echo_flag(arg: &OsString) -> bool { + matches!(arg.to_str(), Some("-e" | "-E" | "-n")) +} + // A workaround because clap interprets the first '--' as a marker that a value // follows. In order to use '--' as a value, we have to inject an additional '--' fn handle_double_hyphens(args: impl uucore::Args) -> impl uucore::Args { let mut result = Vec::new(); - - for (i, arg) in args.enumerate() { - // check for argument at index 1 which is the first argument to echo (0 being "echo") - if i == 1 && arg == "--" { - result.push(OsString::from("--")); + let mut is_first_argument = true; + let mut args_iter = args.into_iter(); + + if let Some(first_val) = args_iter.next() { + // the first argument ('echo') gets pushed before we start with the checks for flags/'--' + result.push(first_val); + // We need to skip any possible Flag arguments until we find the first argument to echo that + // is not a flag. If the first argument is double hyphen we inject an additional '--' + // otherwise we switch is_first_argument boolean to skip the checks for any further arguments + for arg in args_iter { + if is_first_argument && !is_echo_flag(&arg) { + is_first_argument = false; + if arg == "--" { + result.push(OsString::from("--")); + } + } + result.push(arg); } - result.push(arg); } result.into_iter() diff --git a/tests/by-util/test_echo.rs b/tests/by-util/test_echo.rs index db495b0d682..9e2f686aff1 100644 --- a/tests/by-util/test_echo.rs +++ b/tests/by-util/test_echo.rs @@ -273,6 +273,53 @@ fn test_double_hyphens_at_start() { .stdout_only("-- a b --\n"); } +#[test] +fn test_double_hyphens_after_flags() { + new_ucmd!() + .arg("-e") + .arg("--") + .succeeds() + .stdout_only("--\n"); + + new_ucmd!() + .arg("-n") + .arg("-e") + .arg("--") + .arg("foo\n") + .succeeds() + .stdout_only("-- foo\n"); + + new_ucmd!() + .arg("-e") + .arg("--") + .arg("--") + .succeeds() + .stdout_only("-- --\n"); + + new_ucmd!() + .arg("-e") + .arg("--") + .arg("a") + .arg("--") + .succeeds() + .stdout_only("-- a --\n"); + + new_ucmd!() + .arg("-n") + .arg("--") + .arg("a") + .succeeds() + .stdout_only("-- a"); + + new_ucmd!() + .arg("-n") + .arg("--") + .arg("a") + .arg("--") + .succeeds() + .stdout_only("-- a --"); +} + #[test] fn test_double_hyphens() { new_ucmd!().arg("--").succeeds().stdout_only("--\n");