sync: return after checking all inputs (#10742)

* sync: return after checking all inputs

* fix missing error context

* use set_exit_code and update translation templates to show errors

* remove thiserror dependency

* fix typo

---------

Co-authored-by: Sylvestre Ledru <sylvestre@debian.org>
Co-authored-by: Chris Dryden <christopher.paul.dryden@gmail.com>
This commit is contained in:
Reuben Wong
2026-02-09 18:45:20 -08:00
committed by GitHub
co-authored by Sylvestre Ledru Chris Dryden
parent e4e95a7c74
commit 7b0e7e4cbf
4 changed files with 26 additions and 12 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ sync-help-data = sync only file data, no unneeded metadata (Linux only)
# Error messages
sync-error-data-needs-argument = --data needs at least one argument
sync-error-opening-file = error opening { $file }
sync-error-opening-file = error opening { $file }: { $err }
sync-error-no-such-file = error opening { $file }: No such file or directory
sync-error-syncing-file = error syncing { $file }
+1 -1
View File
@@ -7,7 +7,7 @@ sync-help-data = synchroniser seulement les données des fichiers, pas les méta
# Messages d'erreur
sync-error-data-needs-argument = --data nécessite au moins un argument
sync-error-opening-file = erreur lors de l'ouverture de { $file }
sync-error-opening-file = erreur lors de l'ouverture de { $file } : { $err }
sync-error-no-such-file = erreur lors de l'ouverture de { $file } : Aucun fichier ou répertoire de ce type
sync-error-syncing-file = erreur lors de la synchronisation de { $file }
+16 -10
View File
@@ -14,10 +14,9 @@ use nix::fcntl::{OFlag, open};
use nix::sys::stat::Mode;
use std::path::Path;
use uucore::display::Quotable;
#[cfg(any(target_os = "linux", target_os = "android"))]
use uucore::error::FromIo;
use uucore::error::{UResult, USimpleError};
use uucore::error::{UResult, USimpleError, get_exit_code, set_exit_code};
use uucore::format_usage;
use uucore::show_error;
use uucore::translate;
pub mod options {
@@ -235,23 +234,30 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let path = Path::new(&f);
if let Err(e) = open(path, OFlag::O_NONBLOCK, Mode::empty()) {
if e != Errno::EACCES || (e == Errno::EACCES && path.is_dir()) {
e.map_err_context(
|| translate!("sync-error-opening-file", "file" => f.quote()),
)?;
show_error!(
"{}",
translate!("sync-error-opening-file", "file" => f.quote(), "err" => e.desc())
);
set_exit_code(1);
}
}
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
{
if !Path::new(&f).exists() {
return Err(USimpleError::new(
1,
translate!("sync-error-no-such-file", "file" => f.quote()),
));
show_error!(
"{}",
translate!("sync-error-no-such-file", "file" => f.quote())
);
set_exit_code(1);
}
}
}
if get_exit_code() != 0 {
return Err(USimpleError::new(1, ""));
}
#[allow(clippy::if_same_then_else)]
if matches.get_flag(options::FILE_SYSTEM) {
#[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))]
+8
View File
@@ -168,6 +168,14 @@ fn test_sync_multiple_files() {
new_ucmd!().arg("--data").arg(&file1).arg(&file2).succeeds();
}
#[test]
fn test_sync_multiple_nonexistent_files() {
let result = new_ucmd!().arg("--data").arg("bad1").arg("bad2").fails();
result.stderr_contains("sync: error opening 'bad1': No such file or directory");
result.stderr_contains("sync: error opening 'bad2': No such file or directory");
}
#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn test_sync_data_fifo_fails_immediately() {