comm: implement and test correct handling of repeated --output-delimiter

This commit is contained in:
Ben Wiederhake 2024-03-23 20:52:58 +01:00
parent 1fa0b032e5
commit 801edbbcb4
2 changed files with 72 additions and 8 deletions

View file

@ -9,7 +9,7 @@ use std::cmp::Ordering;
use std::fs::File;
use std::io::{self, stdin, BufRead, BufReader, Stdin};
use std::path::Path;
use uucore::error::{FromIo, UResult};
use uucore::error::{FromIo, UResult, USimpleError};
use uucore::line_ending::LineEnding;
use uucore::{format_usage, help_about, help_usage};
@ -61,12 +61,7 @@ impl LineReader {
}
}
fn comm(a: &mut LineReader, b: &mut LineReader, opts: &ArgMatches) {
let delim = match opts.get_one::<String>(options::DELIMITER).unwrap().as_str() {
"" => "\0",
delim => delim,
};
fn comm(a: &mut LineReader, b: &mut LineReader, delim: &str, opts: &ArgMatches) {
let width_col_1 = usize::from(!opts.get_flag(options::COLUMN_1));
let width_col_2 = usize::from(!opts.get_flag(options::COLUMN_2));
@ -152,7 +147,28 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let mut f1 = open_file(filename1, line_ending).map_err_context(|| filename1.to_string())?;
let mut f2 = open_file(filename2, line_ending).map_err_context(|| filename2.to_string())?;
comm(&mut f1, &mut f2, &matches);
// Due to default_value(), there must be at least one value here, thus unwrap() must not panic.
let all_delimiters = matches
.get_many::<String>(options::DELIMITER)
.unwrap()
.map(String::from)
.collect::<Vec<_>>();
for delim in &all_delimiters[1..] {
// Note that this check is very different from ".conflicts_with_self(true).action(ArgAction::Set)",
// as this accepts duplicate *identical* arguments.
if delim != &all_delimiters[0] {
// Note: This intentionally deviate from the GNU error message by inserting the word "conflicting".
return Err(USimpleError::new(
1,
"comm: multiple conflicting output delimiters specified",
));
}
}
let delim = match &*all_delimiters[0] {
"" => "\0",
delim => delim,
};
comm(&mut f1, &mut f2, delim, &matches);
Ok(())
}
@ -187,6 +203,7 @@ pub fn uu_app() -> Command {
.value_name("STR")
.default_value(options::DELIMITER_DEFAULT)
.allow_hyphen_values(true)
.action(ArgAction::Append)
.hide_default_value(true),
)
.arg(

View file

@ -107,6 +107,53 @@ fn output_delimiter_hyphen_help() {
.stdout_only_fixture("ab_delimiter_hyphen_help.expected");
}
#[test]
fn output_delimiter_multiple_identical() {
new_ucmd!()
.args(&[
"--output-delimiter=word",
"--output-delimiter=word",
"a",
"b",
])
.succeeds()
.stdout_only_fixture("ab_delimiter_word.expected");
}
#[test]
fn output_delimiter_multiple_different() {
new_ucmd!()
.args(&[
"--output-delimiter=word",
"--output-delimiter=other",
"a",
"b",
])
.fails()
.no_stdout()
.stderr_contains("multiple")
.stderr_contains("output")
.stderr_contains("delimiters");
}
#[test]
#[ignore = "This is too weird; deviate intentionally."]
fn output_delimiter_multiple_different_prevents_help() {
new_ucmd!()
.args(&[
"--output-delimiter=word",
"--output-delimiter=other",
"--help",
"a",
"b",
])
.fails()
.no_stdout()
.stderr_contains("multiple")
.stderr_contains("output")
.stderr_contains("delimiters");
}
#[test]
fn output_delimiter_nul() {
new_ucmd!()