1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

tr: generate an error if the input is a directory (#6855)

* tr: generate an error if the input is a directory

tested by tests/misc/read-errors

* tr: improve the test

* tr: take the commentinto account
This commit is contained in:
Sylvestre Ledru 2024-11-30 10:38:46 +01:00 committed by GitHub
parent 37fb0a02f8
commit 2ad3c45230
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 31 additions and 12 deletions

View file

@ -23,7 +23,7 @@ use std::{
io::{BufRead, Write}, io::{BufRead, Write},
ops::Not, ops::Not,
}; };
use uucore::error::UError; use uucore::error::{UError, UResult, USimpleError};
use uucore::show_warning; use uucore::show_warning;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -608,7 +608,7 @@ impl SymbolTranslator for SqueezeOperation {
} }
} }
pub fn translate_input<T, R, W>(input: &mut R, output: &mut W, mut translator: T) pub fn translate_input<T, R, W>(input: &mut R, output: &mut W, mut translator: T) -> UResult<()>
where where
T: SymbolTranslator, T: SymbolTranslator,
R: BufRead, R: BufRead,
@ -616,15 +616,25 @@ where
{ {
let mut buf = Vec::new(); let mut buf = Vec::new();
let mut output_buf = Vec::new(); let mut output_buf = Vec::new();
while let Ok(length) = input.read_until(b'\n', &mut buf) { while let Ok(length) = input.read_until(b'\n', &mut buf) {
if length == 0 { if length == 0 {
break; break; // EOF reached
} else {
let filtered = buf.iter().filter_map(|c| translator.translate(*c));
output_buf.extend(filtered);
output.write_all(&output_buf).unwrap();
} }
let filtered = buf.iter().filter_map(|&c| translator.translate(c));
output_buf.extend(filtered);
if let Err(e) = output.write_all(&output_buf) {
return Err(USimpleError::new(
1,
format!("{}: write error: {}", uucore::util_name(), e),
));
}
buf.clear(); buf.clear();
output_buf.clear(); output_buf.clear();
} }
Ok(())
} }

View file

@ -132,24 +132,24 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let delete_op = DeleteOperation::new(set1); let delete_op = DeleteOperation::new(set1);
let squeeze_op = SqueezeOperation::new(set2); let squeeze_op = SqueezeOperation::new(set2);
let op = delete_op.chain(squeeze_op); let op = delete_op.chain(squeeze_op);
translate_input(&mut locked_stdin, &mut buffered_stdout, op); translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
} else { } else {
let op = DeleteOperation::new(set1); let op = DeleteOperation::new(set1);
translate_input(&mut locked_stdin, &mut buffered_stdout, op); translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
} }
} else if squeeze_flag { } else if squeeze_flag {
if sets_len < 2 { if sets_len < 2 {
let op = SqueezeOperation::new(set1); let op = SqueezeOperation::new(set1);
translate_input(&mut locked_stdin, &mut buffered_stdout, op); translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
} else { } else {
let translate_op = TranslateOperation::new(set1, set2.clone())?; let translate_op = TranslateOperation::new(set1, set2.clone())?;
let squeeze_op = SqueezeOperation::new(set2); let squeeze_op = SqueezeOperation::new(set2);
let op = translate_op.chain(squeeze_op); let op = translate_op.chain(squeeze_op);
translate_input(&mut locked_stdin, &mut buffered_stdout, op); translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
} }
} else { } else {
let op = TranslateOperation::new(set1, set2)?; let op = TranslateOperation::new(set1, set2)?;
translate_input(&mut locked_stdin, &mut buffered_stdout, op); translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
} }
Ok(()) Ok(())
} }

View file

@ -13,6 +13,15 @@ fn test_invalid_arg() {
new_ucmd!().arg("--definitely-invalid").fails().code_is(1); new_ucmd!().arg("--definitely-invalid").fails().code_is(1);
} }
#[test]
fn test_invalid_input() {
new_ucmd!()
.args(&["1", "1", "<", "."])
.fails()
.code_is(1)
.stderr_contains("tr: extra operand '<'");
}
#[test] #[test]
fn test_to_upper() { fn test_to_upper() {
new_ucmd!() new_ucmd!()