Skip to content

Commit 6f07bf1

Browse files
authored
Merge pull request #6112 from BenWiederhake/dev-comm-all-args
comm: Handle duplicated flags and output-delimiter correctly
2 parents c97cb30 + 5803d3b commit 6f07bf1

File tree

4 files changed

+104
-8
lines changed

4 files changed

+104
-8
lines changed

src/uu/comm/src/comm.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::cmp::Ordering;
99
use std::fs::File;
1010
use std::io::{self, stdin, BufRead, BufReader, Stdin};
1111
use std::path::Path;
12-
use uucore::error::{FromIo, UResult};
12+
use uucore::error::{FromIo, UResult, USimpleError};
1313
use uucore::line_ending::LineEnding;
1414
use uucore::{format_usage, help_about, help_usage};
1515

@@ -61,12 +61,7 @@ impl LineReader {
6161
}
6262
}
6363

64-
fn comm(a: &mut LineReader, b: &mut LineReader, opts: &ArgMatches) {
65-
let delim = match opts.get_one::<String>(options::DELIMITER).unwrap().as_str() {
66-
"" => "\0",
67-
delim => delim,
68-
};
69-
64+
fn comm(a: &mut LineReader, b: &mut LineReader, delim: &str, opts: &ArgMatches) {
7065
let width_col_1 = usize::from(!opts.get_flag(options::COLUMN_1));
7166
let width_col_2 = usize::from(!opts.get_flag(options::COLUMN_2));
7267

@@ -152,7 +147,28 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
152147
let mut f1 = open_file(filename1, line_ending).map_err_context(|| filename1.to_string())?;
153148
let mut f2 = open_file(filename2, line_ending).map_err_context(|| filename2.to_string())?;
154149

155-
comm(&mut f1, &mut f2, &matches);
150+
// Due to default_value(), there must be at least one value here, thus unwrap() must not panic.
151+
let all_delimiters = matches
152+
.get_many::<String>(options::DELIMITER)
153+
.unwrap()
154+
.map(String::from)
155+
.collect::<Vec<_>>();
156+
for delim in &all_delimiters[1..] {
157+
// Note that this check is very different from ".conflicts_with_self(true).action(ArgAction::Set)",
158+
// as this accepts duplicate *identical* arguments.
159+
if delim != &all_delimiters[0] {
160+
// Note: This intentionally deviate from the GNU error message by inserting the word "conflicting".
161+
return Err(USimpleError::new(
162+
1,
163+
"multiple conflicting output delimiters specified",
164+
));
165+
}
166+
}
167+
let delim = match &*all_delimiters[0] {
168+
"" => "\0",
169+
delim => delim,
170+
};
171+
comm(&mut f1, &mut f2, delim, &matches);
156172
Ok(())
157173
}
158174

@@ -162,6 +178,7 @@ pub fn uu_app() -> Command {
162178
.about(ABOUT)
163179
.override_usage(format_usage(USAGE))
164180
.infer_long_args(true)
181+
.args_override_self(true)
165182
.arg(
166183
Arg::new(options::COLUMN_1)
167184
.short('1')
@@ -186,6 +203,8 @@ pub fn uu_app() -> Command {
186203
.help("separate columns with STR")
187204
.value_name("STR")
188205
.default_value(options::DELIMITER_DEFAULT)
206+
.allow_hyphen_values(true)
207+
.action(ArgAction::Append)
189208
.hide_default_value(true),
190209
)
191210
.arg(

tests/by-util/test_comm.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ fn total_with_suppressed_regular_output() {
7575
.stdout_is_fixture("ab_total_suppressed_regular_output.expected");
7676
}
7777

78+
#[test]
79+
fn repeated_flags() {
80+
new_ucmd!()
81+
.args(&["--total", "-123123", "--total", "a", "b"])
82+
.succeeds()
83+
.stdout_is_fixture("ab_total_suppressed_regular_output.expected");
84+
}
85+
7886
#[test]
7987
fn total_with_output_delimiter() {
8088
new_ucmd!()
@@ -91,6 +99,69 @@ fn output_delimiter() {
9199
.stdout_only_fixture("ab_delimiter_word.expected");
92100
}
93101

102+
#[test]
103+
fn output_delimiter_hyphen_one() {
104+
new_ucmd!()
105+
.args(&["--output-delimiter", "-1", "a", "b"])
106+
.succeeds()
107+
.stdout_only_fixture("ab_delimiter_hyphen_one.expected");
108+
}
109+
110+
#[test]
111+
fn output_delimiter_hyphen_help() {
112+
new_ucmd!()
113+
.args(&["--output-delimiter", "--help", "a", "b"])
114+
.succeeds()
115+
.stdout_only_fixture("ab_delimiter_hyphen_help.expected");
116+
}
117+
118+
#[test]
119+
fn output_delimiter_multiple_identical() {
120+
new_ucmd!()
121+
.args(&[
122+
"--output-delimiter=word",
123+
"--output-delimiter=word",
124+
"a",
125+
"b",
126+
])
127+
.succeeds()
128+
.stdout_only_fixture("ab_delimiter_word.expected");
129+
}
130+
131+
#[test]
132+
fn output_delimiter_multiple_different() {
133+
new_ucmd!()
134+
.args(&[
135+
"--output-delimiter=word",
136+
"--output-delimiter=other",
137+
"a",
138+
"b",
139+
])
140+
.fails()
141+
.no_stdout()
142+
.stderr_contains("multiple")
143+
.stderr_contains("output")
144+
.stderr_contains("delimiters");
145+
}
146+
147+
#[test]
148+
#[ignore = "This is too weird; deviate intentionally."]
149+
fn output_delimiter_multiple_different_prevents_help() {
150+
new_ucmd!()
151+
.args(&[
152+
"--output-delimiter=word",
153+
"--output-delimiter=other",
154+
"--help",
155+
"a",
156+
"b",
157+
])
158+
.fails()
159+
.no_stdout()
160+
.stderr_contains("multiple")
161+
.stderr_contains("output")
162+
.stderr_contains("delimiters");
163+
}
164+
94165
#[test]
95166
fn output_delimiter_nul() {
96167
new_ucmd!()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
a
2+
--helpb
3+
--help--helpz
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
a
2+
-1b
3+
-1-1z

0 commit comments

Comments
 (0)