From afcf93b3e39ee6fb13b67d1a63d83ea4a9fa6226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 25 Oct 2024 03:17:17 +0200 Subject: [PATCH] feat(checksum): extract file processing into a separate function --- src/uucore/src/lib/features/checksum.rs | 210 ++++++++++++++---------- 1 file changed, 122 insertions(+), 88 deletions(-) diff --git a/src/uucore/src/lib/features/checksum.rs b/src/uucore/src/lib/features/checksum.rs index a29fe0767..818190533 100644 --- a/src/uucore/src/lib/features/checksum.rs +++ b/src/uucore/src/lib/features/checksum.rs @@ -92,6 +92,25 @@ impl From for LineCheckError { } } +#[allow(clippy::enum_variant_names)] +enum FileCheckError { + UError(Box), + NonCriticalError, + CriticalError, +} + +impl From> for FileCheckError { + fn from(value: Box) -> Self { + Self::UError(value) + } +} + +impl From for FileCheckError { + fn from(value: ChecksumError) -> Self { + Self::UError(Box::new(value)) + } +} + /// This struct regroups CLI flags. #[derive(Debug, Default, Clone, Copy)] pub struct ChecksumOptions { @@ -656,6 +675,104 @@ fn process_checksum_line( Ok(()) } +fn process_checksum_file( + filename_input: &OsStr, + cli_algo_name: Option<&str>, + cli_algo_length: Option, + opts: ChecksumOptions, +) -> Result<(), FileCheckError> { + let mut correct_format = 0; + let mut properly_formatted = false; + let mut res = ChecksumResult::default(); + let input_is_stdin = filename_input == OsStr::new("-"); + + let file: Box = if input_is_stdin { + // Use stdin if "-" is specified + Box::new(stdin()) + } else { + match get_input_file(filename_input) { + Ok(f) => f, + Err(e) => { + // Could not read the file, show the error and continue to the next file + show_error!("{e}"); + set_exit_code(1); + return Err(FileCheckError::NonCriticalError); + } + } + }; + + let reader = BufReader::new(file); + let lines = read_os_string_lines(reader).collect::>(); + + let Some((chosen_regex, is_algo_based_format)) = determine_regex(&lines) else { + let e = ChecksumError::NoProperlyFormattedChecksumLinesFound { + filename: get_filename_for_output(filename_input, input_is_stdin), + }; + show_error!("{e}"); + set_exit_code(1); + return Err(FileCheckError::NonCriticalError); + }; + + for (i, line) in lines.iter().enumerate() { + match process_checksum_line( + filename_input, + line, + i, + &chosen_regex, + is_algo_based_format, + &mut res, + cli_algo_name, + cli_algo_length, + &mut properly_formatted, + &mut correct_format, + opts, + ) { + Ok(_) => (), + Err(LineCheckError::UError(e)) => return Err(e.into()), + }; + } + + // not a single line correctly formatted found + // return an error + if !properly_formatted { + if !opts.status { + return Err(ChecksumError::NoProperlyFormattedChecksumLinesFound { + filename: get_filename_for_output(filename_input, input_is_stdin), + } + .into()); + } + set_exit_code(1); + return Err(FileCheckError::CriticalError); + } + + // if any incorrectly formatted line, show it + cksum_output(&res, opts.status); + + if opts.ignore_missing && correct_format == 0 { + // we have only bad format + // and we had ignore-missing + eprintln!( + "{}: {}: no file was verified", + util_name(), + filename_input.maybe_quote(), + ); + set_exit_code(1); + } + + // strict means that we should have an exit code. + if opts.strict && res.bad_format > 0 { + set_exit_code(1); + } + + // if we have any failed checksum verification, we set an exit code + // except if we have ignore_missing + if (res.failed_cksum > 0 || res.failed_open_file > 0) && !opts.ignore_missing { + set_exit_code(1); + } + + Ok(()) +} + /*** * Do the checksum validation (can be strict or not) */ @@ -670,94 +787,11 @@ where { // if cksum has several input files, it will print the result for each file for filename_input in files { - let mut correct_format = 0; - let mut properly_formatted = false; - let mut res = ChecksumResult::default(); - let input_is_stdin = filename_input == OsStr::new("-"); - - let file: Box = if input_is_stdin { - // Use stdin if "-" is specified - Box::new(stdin()) - } else { - match get_input_file(filename_input) { - Ok(f) => f, - Err(e) => { - // Could not read the file, show the error and continue to the next file - show_error!("{e}"); - set_exit_code(1); - continue; - } - } - }; - - let reader = BufReader::new(file); - let lines = read_os_string_lines(reader).collect::>(); - - let Some((chosen_regex, is_algo_based_format)) = determine_regex(&lines) else { - let e = ChecksumError::NoProperlyFormattedChecksumLinesFound { - filename: get_filename_for_output(filename_input, input_is_stdin), - }; - show_error!("{e}"); - set_exit_code(1); - continue; - }; - - for (i, line) in lines.iter().enumerate() { - match process_checksum_line( - filename_input, - line, - i, - &chosen_regex, - is_algo_based_format, - &mut res, - algo_name_input, - length_input, - &mut properly_formatted, - &mut correct_format, - opts, - ) { - Ok(_) => (), - Err(LineCheckError::UError(e)) => return Err(e), - }; - } - - // not a single line correctly formatted found - // return an error - if !properly_formatted { - if !opts.status { - return Err(ChecksumError::NoProperlyFormattedChecksumLinesFound { - filename: get_filename_for_output(filename_input, input_is_stdin), - } - .into()); - } - set_exit_code(1); - - return Ok(()); - } - - // if any incorrectly formatted line, show it - cksum_output(&res, opts.status); - - if opts.ignore_missing && correct_format == 0 { - // we have only bad format - // and we had ignore-missing - eprintln!( - "{}: {}: no file was verified", - util_name(), - filename_input.maybe_quote(), - ); - set_exit_code(1); - } - - // strict means that we should have an exit code. - if opts.strict && res.bad_format > 0 { - set_exit_code(1); - } - - // if we have any failed checksum verification, we set an exit code - // except if we have ignore_missing - if (res.failed_cksum > 0 || res.failed_open_file > 0) && !opts.ignore_missing { - set_exit_code(1); + use FileCheckError::*; + match process_checksum_file(filename_input, algo_name_input, length_input, opts) { + Err(UError(e)) => return Err(e), + Err(CriticalError) => break, + Err(NonCriticalError) | Ok(_) => continue, } }