Skip to content

Commit 6a20bcb

Browse files
authored
Merge pull request #10141 from RenjiSann/revert-checksum-clap
Revert recent checksum CLI changes
2 parents 8041772 + b1edc49 commit 6a20bcb

6 files changed

Lines changed: 110 additions & 62 deletions

File tree

src/uu/cksum/src/cksum.rs

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
use clap::builder::ValueParser;
99
use clap::{Arg, ArgAction, Command};
10-
use std::ffi::OsString;
10+
use std::ffi::{OsStr, OsString};
1111
use uucore::checksum::compute::{
1212
ChecksumComputeOptions, figure_out_output_format, perform_checksum_computation,
1313
};
@@ -73,6 +73,42 @@ mod options {
7373
/// Returns a pair of boolean. The first one indicates if we should use tagged
7474
/// output format, the second one indicates if we should use the binary flag in
7575
/// the untagged case.
76+
fn handle_tag_text_binary_flags<S: AsRef<OsStr>>(
77+
args: impl Iterator<Item = S>,
78+
) -> UResult<(bool, bool)> {
79+
let mut tag = true;
80+
let mut binary = false;
81+
let mut text = false;
82+
83+
// --binary, --tag and --untagged are tight together: none of them
84+
// conflicts with each other but --tag will reset "binary" and "text" and
85+
// set "tag".
86+
87+
for arg in args {
88+
let arg = arg.as_ref();
89+
if arg == "-b" || arg == "--binary" {
90+
text = false;
91+
binary = true;
92+
} else if arg == "--text" {
93+
text = true;
94+
binary = false;
95+
} else if arg == "--tag" {
96+
tag = true;
97+
binary = false;
98+
text = false;
99+
} else if arg == "--untagged" {
100+
tag = false;
101+
}
102+
}
103+
104+
// Specifying --text without ever mentioning --untagged fails.
105+
if text && tag {
106+
return Err(ChecksumError::TextWithoutUntagged.into());
107+
}
108+
109+
Ok((tag, binary))
110+
}
111+
76112
/// Sanitize the `--length` argument depending on `--algorithm` and `--length`.
77113
fn maybe_sanitize_length(
78114
algo_cli: Option<AlgoKind>,
@@ -103,11 +139,19 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
103139

104140
let check = matches.get_flag(options::CHECK);
105141

106-
let ignore_missing = matches.get_flag(options::IGNORE_MISSING);
107-
let warn = matches.get_flag(options::WARN);
108-
let quiet = matches.get_flag(options::QUIET);
109-
let strict = matches.get_flag(options::STRICT);
110-
let status = matches.get_flag(options::STATUS);
142+
let check_flag = |flag| match (check, matches.get_flag(flag)) {
143+
(_, false) => Ok(false),
144+
(true, true) => Ok(true),
145+
(false, true) => Err(ChecksumError::CheckOnlyFlag(flag.into())),
146+
};
147+
148+
// Each of the following flags are only expected in --check mode.
149+
// If we encounter them otherwise, end with an error.
150+
let ignore_missing = check_flag(options::IGNORE_MISSING)?;
151+
let warn = check_flag(options::WARN)?;
152+
let quiet = check_flag(options::QUIET)?;
153+
let strict = check_flag(options::STRICT)?;
154+
let status = check_flag(options::STATUS)?;
111155

112156
let algo_cli = matches
113157
.get_one::<String>(options::ALGORITHM)
@@ -132,6 +176,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
132176
return Err(ChecksumError::AlgorithmNotSupportedWithCheck.into());
133177
}
134178

179+
let text_flag = matches.get_flag(options::TEXT);
180+
let binary_flag = matches.get_flag(options::BINARY);
181+
let tag = matches.get_flag(options::TAG);
182+
183+
if tag || binary_flag || text_flag {
184+
return Err(ChecksumError::BinaryTextConflict.into());
185+
}
186+
135187
// Execute the checksum validation based on the presence of files or the use of stdin
136188

137189
let verbose = ChecksumVerbose::new(status, quiet, warn);
@@ -154,8 +206,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
154206
// Set the default algorithm to CRC when not '--check'ing.
155207
let algo_kind = algo_cli.unwrap_or(AlgoKind::Crc);
156208

157-
let tag = !matches.get_flag(options::UNTAGGED); // Making TAG default at clap blocks --untagged
158-
let binary = matches.get_flag(options::BINARY);
209+
let (tag, binary) = handle_tag_text_binary_flags(std::env::args_os())?;
159210

160211
let algo = SizedAlgoKind::from_unsized(algo_kind, length)?;
161212
let line_ending = LineEnding::from_zero_flag(matches.get_flag(options::ZERO));
@@ -214,9 +265,7 @@ pub fn uu_app() -> Command {
214265
.long(options::TAG)
215266
.help(translate!("cksum-help-tag"))
216267
.action(ArgAction::SetTrue)
217-
.overrides_with(options::UNTAGGED)
218-
.overrides_with(options::BINARY)
219-
.overrides_with(options::TEXT),
268+
.overrides_with(options::UNTAGGED),
220269
)
221270
.arg(
222271
Arg::new(options::LENGTH)
@@ -235,17 +284,13 @@ pub fn uu_app() -> Command {
235284
Arg::new(options::STRICT)
236285
.long(options::STRICT)
237286
.help(translate!("cksum-help-strict"))
238-
.action(ArgAction::SetTrue)
239-
.requires(options::CHECK),
287+
.action(ArgAction::SetTrue),
240288
)
241289
.arg(
242290
Arg::new(options::CHECK)
243291
.short('c')
244292
.long(options::CHECK)
245293
.help(translate!("cksum-help-check"))
246-
.conflicts_with(options::TAG)
247-
.conflicts_with(options::BINARY)
248-
.conflicts_with(options::TEXT)
249294
.action(ArgAction::SetTrue),
250295
)
251296
.arg(
@@ -263,8 +308,7 @@ pub fn uu_app() -> Command {
263308
.short('t')
264309
.hide(true)
265310
.overrides_with(options::BINARY)
266-
.action(ArgAction::SetTrue)
267-
.requires(options::UNTAGGED),
311+
.action(ArgAction::SetTrue),
268312
)
269313
.arg(
270314
Arg::new(options::BINARY)
@@ -280,31 +324,27 @@ pub fn uu_app() -> Command {
280324
.long("warn")
281325
.help(translate!("cksum-help-warn"))
282326
.action(ArgAction::SetTrue)
283-
.overrides_with_all([options::STATUS, options::QUIET])
284-
.requires(options::CHECK),
327+
.overrides_with_all([options::STATUS, options::QUIET]),
285328
)
286329
.arg(
287330
Arg::new(options::STATUS)
288331
.long("status")
289332
.help(translate!("cksum-help-status"))
290333
.action(ArgAction::SetTrue)
291-
.overrides_with_all([options::WARN, options::QUIET])
292-
.requires(options::CHECK),
334+
.overrides_with_all([options::WARN, options::QUIET]),
293335
)
294336
.arg(
295337
Arg::new(options::QUIET)
296338
.long(options::QUIET)
297339
.help(translate!("cksum-help-quiet"))
298340
.action(ArgAction::SetTrue)
299-
.overrides_with_all([options::WARN, options::STATUS])
300-
.requires(options::CHECK),
341+
.overrides_with_all([options::WARN, options::STATUS]),
301342
)
302343
.arg(
303344
Arg::new(options::IGNORE_MISSING)
304345
.long(options::IGNORE_MISSING)
305346
.help(translate!("cksum-help-ignore-missing"))
306-
.action(ArgAction::SetTrue)
307-
.requires(options::CHECK),
347+
.action(ArgAction::SetTrue),
308348
)
309349
.arg(
310350
Arg::new(options::ZERO)

src/uu/hashsum/src/hashsum.rs

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,19 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
157157
};
158158
let check = matches.get_flag("check");
159159

160-
let ignore_missing = matches.get_flag("ignore-missing");
161-
let warn = matches.get_flag("warn");
162-
let quiet = matches.get_flag("quiet");
163-
let strict = matches.get_flag("strict");
164-
let status = matches.get_flag("status");
160+
let check_flag = |flag| match (check, matches.get_flag(flag)) {
161+
(_, false) => Ok(false),
162+
(true, true) => Ok(true),
163+
(false, true) => Err(ChecksumError::CheckOnlyFlag(flag.into())),
164+
};
165+
166+
// Each of the following flags are only expected in --check mode.
167+
// If we encounter them otherwise, end with an error.
168+
let ignore_missing = check_flag("ignore-missing")?;
169+
let warn = check_flag("warn")?;
170+
let quiet = check_flag("quiet")?;
171+
let strict = check_flag("strict")?;
172+
let status = check_flag("status")?;
165173

166174
// clap provides the default value -. So we unwrap() safety.
167175
let files = matches
@@ -170,7 +178,18 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
170178
.map(|s| s.as_os_str());
171179

172180
if check {
173-
// No reason to allow --check with --binary/--text on Cygwin. It want to be same with Linux and --text was broken for a long time.
181+
// on Windows, allow --binary/--text to be used with --check
182+
// and keep the behavior of defaulting to binary
183+
#[cfg(not(windows))]
184+
{
185+
let text_flag = matches.get_flag("text");
186+
let binary_flag = matches.get_flag("binary");
187+
188+
if binary_flag || text_flag {
189+
return Err(ChecksumError::BinaryTextConflict.into());
190+
}
191+
}
192+
174193
let verbose = ChecksumVerbose::new(status, quiet, warn);
175194

176195
let opts = ChecksumValidateOptions {
@@ -220,10 +239,6 @@ mod options {
220239
}
221240

222241
pub fn uu_app_common() -> Command {
223-
// --text --arg-deps-check should be error by Arg::new(options::CHECK)...conflicts_with(options::TEXT)
224-
// https://github.com/clap-rs/clap/issues/4520 ?
225-
// Let --{warn,strict,quiet,status,ignore-missing} reject --text and remove them later.
226-
// Bad error message, but not a lie...
227242
Command::new(uucore::util_name())
228243
.version(uucore::crate_version!())
229244
.help_template(uucore::localized_help_template(uucore::util_name()))
@@ -253,9 +268,7 @@ pub fn uu_app_common() -> Command {
253268
.long("check")
254269
.help(translate!("hashsum-help-check"))
255270
.action(ArgAction::SetTrue)
256-
.conflicts_with(options::BINARY)
257-
.conflicts_with(options::TEXT)
258-
.conflicts_with(options::TAG),
271+
.conflicts_with("tag"),
259272
)
260273
.arg(
261274
Arg::new(options::TAG)
@@ -287,45 +300,35 @@ pub fn uu_app_common() -> Command {
287300
.long(options::QUIET)
288301
.help(translate!("hashsum-help-quiet"))
289302
.action(ArgAction::SetTrue)
290-
.overrides_with_all([options::STATUS, options::WARN])
291-
.conflicts_with("text")
292-
.requires(options::CHECK),
303+
.overrides_with_all([options::STATUS, options::WARN]),
293304
)
294305
.arg(
295306
Arg::new(options::STATUS)
296307
.short('s')
297308
.long("status")
298309
.help(translate!("hashsum-help-status"))
299310
.action(ArgAction::SetTrue)
300-
.overrides_with_all([options::QUIET, options::WARN])
301-
.conflicts_with("text")
302-
.requires(options::CHECK),
311+
.overrides_with_all([options::QUIET, options::WARN]),
303312
)
304313
.arg(
305314
Arg::new(options::STRICT)
306315
.long("strict")
307316
.help(translate!("hashsum-help-strict"))
308-
.action(ArgAction::SetTrue)
309-
.conflicts_with("text")
310-
.requires(options::CHECK),
317+
.action(ArgAction::SetTrue),
311318
)
312319
.arg(
313320
Arg::new("ignore-missing")
314321
.long("ignore-missing")
315322
.help(translate!("hashsum-help-ignore-missing"))
316-
.action(ArgAction::SetTrue)
317-
.conflicts_with("text")
318-
.requires(options::CHECK),
323+
.action(ArgAction::SetTrue),
319324
)
320325
.arg(
321326
Arg::new(options::WARN)
322327
.short('w')
323328
.long("warn")
324329
.help(translate!("hashsum-help-warn"))
325330
.action(ArgAction::SetTrue)
326-
.overrides_with_all([options::QUIET, options::STATUS])
327-
.conflicts_with("text")
328-
.requires(options::CHECK),
331+
.overrides_with_all([options::QUIET, options::STATUS]),
329332
)
330333
.arg(
331334
Arg::new("zero")

src/uucore/src/lib/features/checksum/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,9 @@ pub enum ChecksumError {
374374
#[error("the --raw option is not supported with multiple files")]
375375
RawMultipleFiles,
376376

377+
#[error("the --{0} option is meaningful only when verifying checksums")]
378+
CheckOnlyFlag(String),
379+
377380
// --length sanitization errors
378381
#[error("--length required for {}", .0.quote())]
379382
LengthRequired(String),
@@ -390,6 +393,8 @@ pub enum ChecksumError {
390393
#[error("--length is only supported with --algorithm blake2b, sha2, or sha3")]
391394
LengthOnlyForBlake2bSha2Sha3,
392395

396+
#[error("the --binary and --text options are meaningless when verifying checksums")]
397+
BinaryTextConflict,
393398
#[error("--text mode is only supported with --untagged")]
394399
TextWithoutUntagged,
395400
#[error("--check is not supported with --algorithm={{bsd,sysv,crc,crc32b}}")]

tests/by-util/test_cksum.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,7 @@ mod output_format {
10661066
.args(&["-a", "md5"])
10671067
.arg(at.subdir.join("f"))
10681068
.fails_with_code(1)
1069-
.stderr_contains("the following required arguments were not provided"); //clap does not change the meaning
1069+
.stderr_contains("--text mode is only supported with --untagged");
10701070
}
10711071

10721072
#[test]
@@ -1216,7 +1216,7 @@ fn test_conflicting_options() {
12161216
.fails_with_code(1)
12171217
.no_stdout()
12181218
.stderr_contains(
1219-
"cannot be used with", //clap generated error
1219+
"cksum: the --binary and --text options are meaningless when verifying checksums",
12201220
);
12211221

12221222
scene
@@ -1228,7 +1228,7 @@ fn test_conflicting_options() {
12281228
.fails_with_code(1)
12291229
.no_stdout()
12301230
.stderr_contains(
1231-
"cannot be used with", //clap generated error
1231+
"cksum: the --binary and --text options are meaningless when verifying checksums",
12321232
);
12331233
}
12341234

tests/by-util/test_hashsum.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ fn test_check_md5_ignore_missing() {
268268
.arg("--ignore-missing")
269269
.arg(at.subdir.join("testf.sha1"))
270270
.fails()
271-
.stderr_contains("the following required arguments were not provided"); //clap generated error
271+
.stderr_contains("the --ignore-missing option is meaningful only when verifying checksums");
272272
}
273273

274274
#[test]
@@ -1021,13 +1021,13 @@ fn test_check_quiet() {
10211021
.arg("--quiet")
10221022
.arg(at.subdir.join("in.md5"))
10231023
.fails()
1024-
.stderr_contains("the following required arguments were not provided"); //clap generated error
1024+
.stderr_contains("md5sum: the --quiet option is meaningful only when verifying checksums");
10251025
scene
10261026
.ccmd("md5sum")
10271027
.arg("--strict")
10281028
.arg(at.subdir.join("in.md5"))
10291029
.fails()
1030-
.stderr_contains("the following required arguments were not provided"); //clap generated error
1030+
.stderr_contains("md5sum: the --strict option is meaningful only when verifying checksums");
10311031
}
10321032

10331033
#[test]

util/build-gnu.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,9 @@ echo "n_stat1 = \$n_stat1"\n\
320320
echo "n_stat2 = \$n_stat2"\n\
321321
test \$n_stat1 -ge \$n_stat2 \\' tests/ls/stat-free-color.sh
322322

323-
# clap changes the error message. Check exit code only.
323+
# no need to replicate this output with hashsum
324324
"${SED}" -i -e "s|Try 'md5sum --help' for more information.\\\n||" tests/cksum/md5sum.pl
325-
"${SED}" -i '/check-ignore-missing-4/,/EXIT/c \ ['\''check-ignore-missing-4'\'', '\''--ignore-missing'\'', {IN=> {f=> '\'''\''}}, {ERR_SUBST=>"s/.*//s"}, {EXIT=> 1}],' tests/cksum/md5sum.pl
325+
326326
# Our ls command always outputs ANSI color codes prepended with a zero. However,
327327
# in the case of GNU, it seems inconsistent. Nevertheless, it looks like it
328328
# doesn't matter whether we prepend a zero or not.

0 commit comments

Comments
 (0)