Skip to content

Commit 6df8620

Browse files
committed
date: handle unknown options gracefully
1 parent 055ba74 commit 6df8620

File tree

4 files changed

+49
-2
lines changed

4 files changed

+49
-2
lines changed

src/uu/date/locales/en-US.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,4 @@ date-error-date-overflow = date overflow '{$date}'
104104
date-error-setting-date-not-supported-macos = setting the date is not supported by macOS
105105
date-error-setting-date-not-supported-redox = setting the date is not supported by Redox
106106
date-error-cannot-set-date = cannot set date
107+
date-error-extra-operand = extra operand '{$operand}'

src/uu/date/locales/fr-FR.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,4 @@ date-error-date-overflow = débordement de date '{$date}'
9999
date-error-setting-date-not-supported-macos = la définition de la date n'est pas prise en charge par macOS
100100
date-error-setting-date-not-supported-redox = la définition de la date n'est pas prise en charge par Redox
101101
date-error-cannot-set-date = impossible de définir la date
102+
date-error-extra-operand = opérande supplémentaire '{$operand}'

src/uu/date/src/date.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,28 @@ fn parse_military_timezone_with_offset(s: &str) -> Option<i32> {
169169
#[uucore::main]
170170
#[allow(clippy::cognitive_complexity)]
171171
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
172-
let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?;
172+
let args: Vec<std::ffi::OsString> = args.collect();
173+
let matches = match uu_app().try_get_matches_from(&args) {
174+
Ok(matches) => matches,
175+
Err(e) => {
176+
match e.kind() {
177+
clap::error::ErrorKind::DisplayHelp | clap::error::ErrorKind::DisplayVersion => {
178+
return Err(e.into());
179+
}
180+
_ => {
181+
// Convert unknown options to be treated as invalid date format
182+
// This ensures consistent exit status 1 instead of clap's exit status 77
183+
if let Some(arg) = args.get(1) {
184+
return Err(USimpleError::new(
185+
1,
186+
translate!("date-error-invalid-date", "date" => arg.to_string_lossy()),
187+
));
188+
}
189+
return Err(USimpleError::new(1, e.to_string()));
190+
}
191+
}
192+
}
193+
};
173194

174195
// Check for extra operands (multiple positional arguments)
175196
if let Some(formats) = matches.get_many::<String>(OPT_FORMAT) {
@@ -526,7 +547,7 @@ pub fn uu_app() -> Command {
526547
.help(translate!("date-help-universal"))
527548
.action(ArgAction::SetTrue),
528549
)
529-
.arg(Arg::new(OPT_FORMAT).num_args(0..))
550+
.arg(Arg::new(OPT_FORMAT).num_args(0..).trailing_var_arg(true))
530551
}
531552

532553
/// Return the appropriate format string for the given settings.

tests/by-util/test_date.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,30 @@ fn test_extra_operands() {
3232
.stderr_contains("extra operand 'extra'");
3333
}
3434

35+
#[test]
36+
fn test_invalid_long_option() {
37+
new_ucmd!()
38+
.arg("--fB")
39+
.fails_with_code(1)
40+
.stderr_contains("invalid date '--fB'");
41+
}
42+
43+
#[test]
44+
fn test_invalid_short_option() {
45+
new_ucmd!()
46+
.arg("-w")
47+
.fails_with_code(1)
48+
.stderr_contains("invalid date '-w'");
49+
}
50+
51+
#[test]
52+
fn test_single_dash_as_date() {
53+
new_ucmd!()
54+
.arg("-")
55+
.fails_with_code(1)
56+
.stderr_contains("invalid date");
57+
}
58+
3559
#[test]
3660
fn test_date_email() {
3761
for param in ["--rfc-email", "--rfc-e", "-R", "--rfc-2822", "--rfc-822"] {

0 commit comments

Comments
 (0)