Skip to content

Commit 4e1dbcd

Browse files
authored
Merge pull request #6230 from sylvestre/hash-ignore-missing
hashsum: implement the ignore-missing option
2 parents 57388a9 + f817018 commit 4e1dbcd

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

src/uu/hashsum/src/hashsum.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use std::iter;
2121
use std::num::ParseIntError;
2222
use std::path::Path;
2323
use uucore::error::USimpleError;
24-
use uucore::error::{FromIo, UError, UResult};
24+
use uucore::error::{set_exit_code, FromIo, UError, UResult};
2525
use uucore::sum::{
2626
Blake2b, Blake3, Digest, DigestWriter, Md5, Sha1, Sha224, Sha256, Sha384, Sha3_224, Sha3_256,
2727
Sha3_384, Sha3_512, Sha512, Shake128, Shake256,
@@ -46,6 +46,7 @@ struct Options {
4646
warn: bool,
4747
output_bits: usize,
4848
zero: bool,
49+
ignore_missing: bool,
4950
}
5051

5152
/// Creates a Blake2b hasher instance based on the specified length argument.
@@ -345,6 +346,12 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
345346
let strict = matches.get_flag("strict");
346347
let warn = matches.get_flag("warn") && !status;
347348
let zero = matches.get_flag("zero");
349+
let ignore_missing = matches.get_flag("ignore-missing");
350+
351+
if ignore_missing && !check {
352+
// --ignore-missing needs -c
353+
return Err(HashsumError::IgnoreNotCheck.into());
354+
}
348355

349356
let opts = Options {
350357
algoname: name,
@@ -359,6 +366,7 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
359366
strict,
360367
warn,
361368
zero,
369+
ignore_missing,
362370
};
363371

364372
match matches.get_many::<OsString>("FILE") {
@@ -431,6 +439,12 @@ pub fn uu_app_common() -> Command {
431439
.help("exit non-zero for improperly formatted checksum lines")
432440
.action(ArgAction::SetTrue),
433441
)
442+
.arg(
443+
Arg::new("ignore-missing")
444+
.long("ignore-missing")
445+
.help("don't fail or report status for missing files")
446+
.action(ArgAction::SetTrue),
447+
)
434448
.arg(
435449
Arg::new("warn")
436450
.short('w')
@@ -564,6 +578,7 @@ fn uu_app(binary_name: &str) -> Command {
564578
enum HashsumError {
565579
InvalidRegex,
566580
InvalidFormat,
581+
IgnoreNotCheck,
567582
}
568583

569584
impl Error for HashsumError {}
@@ -574,6 +589,10 @@ impl std::fmt::Display for HashsumError {
574589
match self {
575590
Self::InvalidRegex => write!(f, "invalid regular expression"),
576591
Self::InvalidFormat => Ok(()),
592+
Self::IgnoreNotCheck => write!(
593+
f,
594+
"the --ignore-missing option is meaningful only when verifying checksums"
595+
),
577596
}
578597
}
579598
}
@@ -705,13 +724,19 @@ where
705724
let (ck_filename_unescaped, prefix) = unescape_filename(&ck_filename);
706725
let f = match File::open(ck_filename_unescaped) {
707726
Err(_) => {
727+
if options.ignore_missing {
728+
// No need to show or return an error.
729+
continue;
730+
}
731+
708732
failed_open_file += 1;
709733
println!(
710734
"{}: {}: No such file or directory",
711735
uucore::util_name(),
712736
ck_filename
713737
);
714738
println!("{ck_filename}: FAILED open or read");
739+
set_exit_code(1);
715740
continue;
716741
}
717742
Ok(file) => file,

tests/by-util/test_hashsum.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,40 @@ fn test_check_sha1() {
129129
.stderr_is("");
130130
}
131131

132+
#[test]
133+
fn test_check_md5_ignore_missing() {
134+
let scene = TestScenario::new(util_name!());
135+
let at = &scene.fixtures;
136+
137+
at.write("testf", "foobar\n");
138+
at.write(
139+
"testf.sha1",
140+
"14758f1afd44c09b7992073ccf00b43d testf\n14758f1afd44c09b7992073ccf00b43d testf2\n",
141+
);
142+
scene
143+
.ccmd("md5sum")
144+
.arg("-c")
145+
.arg(at.subdir.join("testf.sha1"))
146+
.fails()
147+
.stdout_contains("testf2: FAILED open or read");
148+
149+
scene
150+
.ccmd("md5sum")
151+
.arg("-c")
152+
.arg("--ignore-missing")
153+
.arg(at.subdir.join("testf.sha1"))
154+
.succeeds()
155+
.stdout_is("testf: OK\n")
156+
.stderr_is("");
157+
158+
scene
159+
.ccmd("md5sum")
160+
.arg("--ignore-missing")
161+
.arg(at.subdir.join("testf.sha1"))
162+
.fails()
163+
.stderr_contains("the --ignore-missing option is meaningful only when verifying checksums");
164+
}
165+
132166
#[test]
133167
fn test_check_b2sum_length_option_0() {
134168
let scene = TestScenario::new(util_name!());
@@ -208,7 +242,7 @@ fn test_check_file_not_found_warning() {
208242
.ccmd("sha1sum")
209243
.arg("-c")
210244
.arg(at.subdir.join("testf.sha1"))
211-
.succeeds()
245+
.fails()
212246
.stdout_is("sha1sum: testf: No such file or directory\ntestf: FAILED open or read\n")
213247
.stderr_is("sha1sum: warning: 1 listed file could not be read\n");
214248
}

0 commit comments

Comments
 (0)