From 5047b2fc04e531c692c2c89398e676db4f2afb2f Mon Sep 17 00:00:00 2001 From: Jay Hemnani <193022578+jayhemnani9910@users.noreply.github.com> Date: Fri, 23 Oct 2026 02:18:53 +0530 Subject: [PATCH 1/2] tar: print the tar: prefix once in error messages --- src/uu/tar/src/errors.rs | 40 +++++++++++++++++++-------------- src/uu/tar/tests/test_errors.rs | 8 +++---- tests/by-util/test_tar.rs | 10 +++++++++ 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/uu/tar/src/errors.rs b/src/uu/tar/src/errors.rs index adf771f..efbc136 100644 --- a/src/uu/tar/src/errors.rs +++ b/src/uu/tar/src/errors.rs @@ -17,63 +17,63 @@ pub enum TarError { Io(#[from] io::Error), /// Cannot read entries from archive - #[error("tar: Cannot read archive entries: {0}")] + #[error("Cannot read archive entries: {0}")] CannotReadEntries(io::Error), /// Cannot read an individual archive entry - #[error("tar: Cannot read archive entry: {0}")] + #[error("Cannot read archive entry: {0}")] CannotReadEntry(io::Error), /// Cannot read the path of an archive entry - #[error("tar: Cannot read entry path: {0}")] + #[error("Cannot read entry path: {0}")] CannotReadEntryPath(io::Error), /// Invalid archive format or unsupported compression stream - #[error("tar: {0}")] + #[error("{0}")] InvalidArchive(String), /// File or directory not found - #[error("tar: {path}: Cannot open: No such file or directory")] + #[error("{path}: Cannot open: No such file or directory")] FileNotFound { path: PathBuf }, /// Permission denied when accessing file - #[error("tar: {path}: Cannot open: Permission denied")] + #[error("{path}: Cannot open: Permission denied")] PermissionDenied { path: PathBuf }, /// Cannot create archive file - #[error("tar: Cannot create archive '{path}': {source}")] + #[error("Cannot create archive '{path}': {source}")] CannotCreateArchive { path: PathBuf, source: io::Error }, /// Cannot add a directory to the archive - #[error("tar: Cannot add directory '{path}': {source}")] + #[error("Cannot add directory '{path}': {source}")] CannotAddDirectory { path: PathBuf, source: io::Error }, /// Cannot add a file to the archive - #[error("tar: Cannot add file '{path}': {source}")] + #[error("Cannot add file '{path}': {source}")] CannotAddFile { path: PathBuf, source: io::Error }, /// Cannot extract an archive entry - #[error("tar: Cannot extract '{path}': {source}")] + #[error("Cannot extract '{path}': {source}")] CannotExtract { path: PathBuf, source: io::Error }, /// General tar operation error - #[error("tar: {0}")] + #[error("{0}")] TarOperationError(String), /// Cannot finalize the archive - #[error("tar: Cannot finalize archive: {0}")] + #[error("Cannot finalize archive: {0}")] CannotFinalizeArchive(io::Error), /// Refusing to write archive contents to terminal - #[error("tar: Refusing to write archive contents to terminal (missing -f option?)")] + #[error("Refusing to write archive contents to terminal (missing -f option?)")] RefuseWriteArchiveToTerminal, /// A member name with a `..` component, which is not extracted - #[error("tar: {path}: Member name contains '..'")] + #[error("{path}: Member name contains '..'")] MemberNameContainsDotDot { path: PathBuf }, /// Errors that were reported earlier and recovered from - #[error("tar: Exiting with failure status due to previous errors")] + #[error("Exiting with failure status due to previous errors")] PreviousErrors, } @@ -95,7 +95,7 @@ impl TarError { /// Reports an error that tar recovers from: the operation carries on, and has to /// end with [`finish_after_previous_errors`]. pub fn report_recoverable(err: &TarError) -> UResult<()> { - writeln!(io::stderr(), "{err}").map_err(TarError::Io)?; + writeln!(io::stderr(), "{}: {err}", uucore::util_name()).map_err(TarError::Io)?; Ok(()) } @@ -103,7 +103,13 @@ pub fn report_recoverable(err: &TarError) -> UResult<()> { /// GNU tar. The status is set right before returning `Ok`, which is how `tarapp` /// tells these errors apart from fatal ones. pub fn finish_after_previous_errors() -> UResult<()> { - writeln!(io::stderr(), "{}", TarError::PreviousErrors).map_err(TarError::Io)?; + writeln!( + io::stderr(), + "{}: {}", + uucore::util_name(), + TarError::PreviousErrors + ) + .map_err(TarError::Io)?; set_exit_code(2); Ok(()) } diff --git a/src/uu/tar/tests/test_errors.rs b/src/uu/tar/tests/test_errors.rs index 8bb41a0..81953a2 100644 --- a/src/uu/tar/tests/test_errors.rs +++ b/src/uu/tar/tests/test_errors.rs @@ -14,7 +14,7 @@ fn test_tar_error_display() { }; assert_eq!( err.to_string(), - "tar: test.txt: Cannot open: No such file or directory" + "test.txt: Cannot open: No such file or directory" ); let err = TarError::PermissionDenied { @@ -22,7 +22,7 @@ fn test_tar_error_display() { }; assert_eq!( err.to_string(), - "tar: /root/file: Cannot open: Permission denied" + "/root/file: Cannot open: Permission denied" ); } @@ -103,7 +103,7 @@ fn test_from_io_error_not_found() { assert!(matches!(tar_err, TarError::FileNotFound { .. })); assert_eq!( tar_err.to_string(), - "tar: myfile.txt: Cannot open: No such file or directory" + "myfile.txt: Cannot open: No such file or directory" ); } @@ -115,7 +115,7 @@ fn test_from_io_error_permission_denied() { assert!(matches!(tar_err, TarError::PermissionDenied { .. })); assert_eq!( tar_err.to_string(), - "tar: /root/secret: Cannot open: Permission denied" + "/root/secret: Cannot open: Permission denied" ); } diff --git a/tests/by-util/test_tar.rs b/tests/by-util/test_tar.rs index dd44e62..6e5061a 100644 --- a/tests/by-util/test_tar.rs +++ b/tests/by-util/test_tar.rs @@ -634,6 +634,16 @@ fn test_extract_nonexistent_archive() { .stderr_contains("nonexistent.tar"); } +#[test] +fn test_error_message_has_one_prefix() { + let result = new_ucmd!().args(&["-tf", "nonexistent.tar"]).fails(); + let first = result.stderr_str().lines().next().unwrap(); + assert_eq!( + first.split_once(": ").unwrap().1, + "nonexistent.tar: Cannot open: No such file or directory" + ); +} + #[test] fn test_extract_directory_structure() { let (at, mut ucmd) = at_and_ucmd!(); From 5586a941d6410e854f56dfa5bcffb7cab2e228a9 Mon Sep 17 00:00:00 2001 From: Jay Hemnani <193022578+jayhemnani9910@users.noreply.github.com> Date: Sun, 25 Oct 2026 13:14:14 +0530 Subject: [PATCH 2/2] tar: reuse report_recoverable, check the prefix in the nonexistent archive test --- src/uu/tar/src/errors.rs | 8 +------- tests/by-util/test_tar.rs | 13 ++----------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/src/uu/tar/src/errors.rs b/src/uu/tar/src/errors.rs index efbc136..7eb1ded 100644 --- a/src/uu/tar/src/errors.rs +++ b/src/uu/tar/src/errors.rs @@ -103,13 +103,7 @@ pub fn report_recoverable(err: &TarError) -> UResult<()> { /// GNU tar. The status is set right before returning `Ok`, which is how `tarapp` /// tells these errors apart from fatal ones. pub fn finish_after_previous_errors() -> UResult<()> { - writeln!( - io::stderr(), - "{}: {}", - uucore::util_name(), - TarError::PreviousErrors - ) - .map_err(TarError::Io)?; + report_recoverable(&TarError::PreviousErrors)?; set_exit_code(2); Ok(()) } diff --git a/tests/by-util/test_tar.rs b/tests/by-util/test_tar.rs index 6e5061a..9a95fdc 100644 --- a/tests/by-util/test_tar.rs +++ b/tests/by-util/test_tar.rs @@ -631,17 +631,8 @@ fn test_extract_nonexistent_archive() { .args(&["-xf", "nonexistent.tar"]) .fails() .code_is(2) - .stderr_contains("nonexistent.tar"); -} - -#[test] -fn test_error_message_has_one_prefix() { - let result = new_ucmd!().args(&["-tf", "nonexistent.tar"]).fails(); - let first = result.stderr_str().lines().next().unwrap(); - assert_eq!( - first.split_once(": ").unwrap().1, - "nonexistent.tar: Cannot open: No such file or directory" - ); + .stderr_contains(": nonexistent.tar: Cannot open") + .stderr_does_not_contain(": tar: "); } #[test]