Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/uu/sort/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ sort-open-failed = open failed: {$path}: {$error}
sort-parse-key-error = failed to parse key {$key}: {$msg}
sort-cannot-read = cannot read: {$path}: {$error}
sort-open-tmp-file-failed = failed to open temporary file: {$error}
sort-compress-prog-execution-failed = couldn't execute compress program: errno {$code}
sort-compress-prog-execution-failed = could not run compress program '{$prog}': {$error}
sort-compress-prog-terminated-abnormally = {$prog} terminated abnormally
sort-cannot-create-tmp-file = cannot create temporary file in '{$path}':
sort-file-operands-combined = extra operand '{$file}'
Expand Down
2 changes: 1 addition & 1 deletion src/uu/sort/locales/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ sort-open-failed = échec d'ouverture : {$path} : {$error}
sort-parse-key-error = échec d'analyse de la clé {$key} : {$msg}
sort-cannot-read = impossible de lire : {$path} : {$error}
sort-open-tmp-file-failed = échec d'ouverture du fichier temporaire : {$error}
sort-compress-prog-execution-failed = impossible d'exécuter le programme de compression : errno {$code}
sort-compress-prog-execution-failed = impossible d'exécuter le programme de compression '{$prog}' : {$error}
sort-compress-prog-terminated-abnormally = {$prog} s'est terminé anormalement
sort-cannot-create-tmp-file = impossible de créer un fichier temporaire dans '{$path}' :
sort-file-operands-combined = opérande supplémentaire '{$file}'
Expand Down
35 changes: 31 additions & 4 deletions src/uu/sort/src/ext_sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use std::{
};

use itertools::Itertools;
use uucore::error::UResult;
use uucore::error::{UResult, strip_errno};

use crate::Output;
use crate::chunks::RecycledChunk;
Expand Down Expand Up @@ -52,10 +52,37 @@ pub fn ext_sort(
let settings = settings.clone();
move || sorter(&recycled_receiver, &sorted_sender, &settings)
});
if settings.compress_prog.is_some() {

// Test if compression program exists and works, disable if not
let mut effective_settings = settings.clone();
if let Some(ref prog) = settings.compress_prog {
// Test the compression program by trying to spawn it
match std::process::Command::new(prog)
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.spawn()
{
Ok(mut child) => {
// Kill the test process immediately
let _ = child.kill();
}
Err(err) => {
// Print the error and disable compression
eprintln!(
"sort: could not run compress program '{}': {}",
prog,
strip_errno(&err)
);
effective_settings.compress_prog = None;
}
}
}

if effective_settings.compress_prog.is_some() {
reader_writer::<_, WriteableCompressedTmpFile>(
files,
settings,
&effective_settings,
&sorted_receiver,
recycled_sender,
output,
Expand All @@ -64,7 +91,7 @@ pub fn ext_sort(
} else {
reader_writer::<_, WriteablePlainTmpFile>(
files,
settings,
&effective_settings,
&sorted_receiver,
recycled_sender,
output,
Expand Down
6 changes: 4 additions & 2 deletions src/uu/sort/src/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,8 @@ impl WriteableTmpFile for WriteableCompressedTmpFile {
let mut child = command
.spawn()
.map_err(|err| SortError::CompressProgExecutionFailed {
code: err.raw_os_error().unwrap(),
prog: compress_prog.to_owned(),
error: err,
})?;
let child_stdin = child.stdin.take().unwrap();
Ok(Self {
Expand Down Expand Up @@ -522,7 +523,8 @@ impl ClosedTmpFile for ClosedCompressedTmpFile {
let mut child = command
.spawn()
.map_err(|err| SortError::CompressProgExecutionFailed {
code: err.raw_os_error().unwrap(),
prog: self.compress_prog.clone(),
error: err,
})?;
let child_stdout = child.stdout.take().unwrap();
Ok(CompressedTmpMergeInput {
Expand Down
4 changes: 2 additions & 2 deletions src/uu/sort/src/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ pub enum SortError {
#[error("{}", translate!("sort-open-tmp-file-failed", "error" => strip_errno(.error)))]
OpenTmpFileFailed { error: std::io::Error },

#[error("{}", translate!("sort-compress-prog-execution-failed", "code" => .code))]
CompressProgExecutionFailed { code: i32 },
#[error("{}", translate!("sort-compress-prog-execution-failed", "prog" => .prog, "error" => strip_errno(.error)))]
CompressProgExecutionFailed { prog: String, error: std::io::Error },

#[error("{}", translate!("sort-compress-prog-terminated-abnormally", "prog" => .prog.quote()))]
CompressProgTerminatedAbnormally { prog: String },
Expand Down
33 changes: 16 additions & 17 deletions tests/by-util/test_sort.rs
Copy link
Contributor

@cakebaker cakebaker Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code for Windows and non-Windows is identical, except of the expected error message, and so I would make only the expected error message platform-dependent. Another option would be to use the same error message on all platforms, so you don't have to care on which platform the test is run.

Original file line number Diff line number Diff line change
Expand Up @@ -1002,8 +1002,7 @@ fn test_compress_merge() {
#[test]
#[cfg(not(target_os = "android"))]
fn test_compress_fail() {
#[cfg(not(windows))]
new_ucmd!()
let result = new_ucmd!()
.args(&[
"ext_sort.txt",
"-n",
Expand All @@ -1012,22 +1011,22 @@ fn test_compress_fail() {
"-S",
"10",
])
.fails()
.stderr_only("sort: couldn't execute compress program: errno 2\n");
// With coverage, it fails with a different error:
// "thread 'main' panicked at 'called `Option::unwrap()` on ...
// So, don't check the output
.succeeds();

#[cfg(not(windows))]
result.stderr_contains(
"sort: could not run compress program 'nonexistent-program': No such file or directory",
);

#[cfg(windows)]
new_ucmd!()
.args(&[
"ext_sort.txt",
"-n",
"--compress-program",
"nonexistent-program",
"-S",
"10",
])
.fails();
result.stderr_contains("could not run compress program");

// Check that it still produces correct sorted output to stdout
let expected = new_ucmd!()
.args(&["ext_sort.txt", "-n"])
.succeeds()
.stdout_move_str();
assert_eq!(result.stdout_str(), expected);
}

#[test]
Expand Down
Loading