mirror of
https://github.com/uutils/coreutils
synced 2024-11-17 02:08:09 +00:00
Merge pull request #2097 from miDeb/sort-disable-dictionary-mode
sort: disallow certain flags with -d and -i
This commit is contained in:
commit
d7e8a03237
2 changed files with 60 additions and 9 deletions
|
@ -84,7 +84,7 @@ static THOUSANDS_SEP: char = ',';
|
||||||
static NEGATIVE: char = '-';
|
static NEGATIVE: char = '-';
|
||||||
static POSITIVE: char = '+';
|
static POSITIVE: char = '+';
|
||||||
|
|
||||||
#[derive(Eq, Ord, PartialEq, PartialOrd, Clone)]
|
#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Copy)]
|
||||||
enum SortMode {
|
enum SortMode {
|
||||||
Numeric,
|
Numeric,
|
||||||
HumanNumeric,
|
HumanNumeric,
|
||||||
|
@ -153,7 +153,7 @@ struct KeySettings {
|
||||||
impl From<&GlobalSettings> for KeySettings {
|
impl From<&GlobalSettings> for KeySettings {
|
||||||
fn from(settings: &GlobalSettings) -> Self {
|
fn from(settings: &GlobalSettings) -> Self {
|
||||||
Self {
|
Self {
|
||||||
mode: settings.mode.clone(),
|
mode: settings.mode,
|
||||||
ignore_blanks: settings.ignore_blanks,
|
ignore_blanks: settings.ignore_blanks,
|
||||||
ignore_case: settings.ignore_case,
|
ignore_case: settings.ignore_case,
|
||||||
ignore_non_printing: settings.ignore_non_printing,
|
ignore_non_printing: settings.ignore_non_printing,
|
||||||
|
@ -405,6 +405,28 @@ impl KeyPosition {
|
||||||
crash!(1, "invalid option for key: `{}`", c)
|
crash!(1, "invalid option for key: `{}`", c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// All numeric sorts and month sort conflict with dictionary_order and ignore_non_printing.
|
||||||
|
// Instad of reporting an error, let them overwrite each other.
|
||||||
|
|
||||||
|
// FIXME: This should only override if the overridden flag is a global flag.
|
||||||
|
// If conflicting flags are attached to the key, GNU sort crashes and we should probably too.
|
||||||
|
match option {
|
||||||
|
'h' | 'n' | 'g' | 'M' => {
|
||||||
|
settings.dictionary_order = false;
|
||||||
|
settings.ignore_non_printing = false;
|
||||||
|
}
|
||||||
|
'd' | 'i' => {
|
||||||
|
settings.mode = match settings.mode {
|
||||||
|
SortMode::Numeric
|
||||||
|
| SortMode::HumanNumeric
|
||||||
|
| SortMode::GeneralNumeric
|
||||||
|
| SortMode::Month => SortMode::Default,
|
||||||
|
// Only SortMode::Default and SortMode::Version work with dictionary_order and ignore_non_printing
|
||||||
|
m @ SortMode::Default | m @ SortMode::Version => m,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Strip away option characters from the original value so we can parse it later
|
// Strip away option characters from the original value so we can parse it later
|
||||||
*value_with_options = &value_with_options[..options_start];
|
*value_with_options = &value_with_options[..options_start];
|
||||||
|
@ -649,7 +671,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
Arg::with_name(OPT_DICTIONARY_ORDER)
|
Arg::with_name(OPT_DICTIONARY_ORDER)
|
||||||
.short("d")
|
.short("d")
|
||||||
.long(OPT_DICTIONARY_ORDER)
|
.long(OPT_DICTIONARY_ORDER)
|
||||||
.help("consider only blanks and alphanumeric characters"),
|
.help("consider only blanks and alphanumeric characters")
|
||||||
|
.conflicts_with_all(&[OPT_NUMERIC_SORT, OPT_GENERAL_NUMERIC_SORT, OPT_HUMAN_NUMERIC_SORT, OPT_MONTH_SORT]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(OPT_MERGE)
|
Arg::with_name(OPT_MERGE)
|
||||||
|
@ -677,9 +700,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(OPT_IGNORE_NONPRINTING)
|
Arg::with_name(OPT_IGNORE_NONPRINTING)
|
||||||
.short("-i")
|
.short("i")
|
||||||
.long(OPT_IGNORE_NONPRINTING)
|
.long(OPT_IGNORE_NONPRINTING)
|
||||||
.help("ignore nonprinting characters"),
|
.help("ignore nonprinting characters")
|
||||||
|
.conflicts_with_all(&[OPT_NUMERIC_SORT, OPT_GENERAL_NUMERIC_SORT, OPT_HUMAN_NUMERIC_SORT, OPT_MONTH_SORT]),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(OPT_IGNORE_BLANKS)
|
Arg::with_name(OPT_IGNORE_BLANKS)
|
||||||
|
|
|
@ -63,7 +63,7 @@ fn test_check_zero_terminated_success() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_random_shuffle_len() {
|
fn test_random_shuffle_len() {
|
||||||
// check whether output is the same length as the input
|
// check whether output is the same length as the input
|
||||||
const FILE: &'static str = "default_unsorted_ints.expected";
|
const FILE: &str = "default_unsorted_ints.expected";
|
||||||
let (at, _ucmd) = at_and_ucmd!();
|
let (at, _ucmd) = at_and_ucmd!();
|
||||||
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
|
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
|
||||||
let expected = at.read(FILE);
|
let expected = at.read(FILE);
|
||||||
|
@ -75,7 +75,7 @@ fn test_random_shuffle_len() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_random_shuffle_contains_all_lines() {
|
fn test_random_shuffle_contains_all_lines() {
|
||||||
// check whether lines of input are all in output
|
// check whether lines of input are all in output
|
||||||
const FILE: &'static str = "default_unsorted_ints.expected";
|
const FILE: &str = "default_unsorted_ints.expected";
|
||||||
let (at, _ucmd) = at_and_ucmd!();
|
let (at, _ucmd) = at_and_ucmd!();
|
||||||
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
|
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
|
||||||
let expected = at.read(FILE);
|
let expected = at.read(FILE);
|
||||||
|
@ -90,7 +90,7 @@ fn test_random_shuffle_two_runs_not_the_same() {
|
||||||
// check to verify that two random shuffles are not equal; this has the
|
// check to verify that two random shuffles are not equal; this has the
|
||||||
// potential to fail in the very unlikely event that the random order is the same
|
// potential to fail in the very unlikely event that the random order is the same
|
||||||
// as the starting order, or if both random sorts end up having the same order.
|
// as the starting order, or if both random sorts end up having the same order.
|
||||||
const FILE: &'static str = "default_unsorted_ints.expected";
|
const FILE: &str = "default_unsorted_ints.expected";
|
||||||
let (at, _ucmd) = at_and_ucmd!();
|
let (at, _ucmd) = at_and_ucmd!();
|
||||||
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
|
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
|
||||||
let expected = at.read(FILE);
|
let expected = at.read(FILE);
|
||||||
|
@ -105,7 +105,7 @@ fn test_random_shuffle_contains_two_runs_not_the_same() {
|
||||||
// check to verify that two random shuffles are not equal; this has the
|
// check to verify that two random shuffles are not equal; this has the
|
||||||
// potential to fail in the unlikely event that random order is the same
|
// potential to fail in the unlikely event that random order is the same
|
||||||
// as the starting order, or if both random sorts end up having the same order.
|
// as the starting order, or if both random sorts end up having the same order.
|
||||||
const FILE: &'static str = "default_unsorted_ints.expected";
|
const FILE: &str = "default_unsorted_ints.expected";
|
||||||
let (at, _ucmd) = at_and_ucmd!();
|
let (at, _ucmd) = at_and_ucmd!();
|
||||||
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
|
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
|
||||||
let expected = at.read(FILE);
|
let expected = at.read(FILE);
|
||||||
|
@ -582,6 +582,33 @@ fn test_check_silent() {
|
||||||
.stdout_is("");
|
.stdout_is("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dictionary_and_nonprinting_conflicts() {
|
||||||
|
let conflicting_args = ["n", "h", "g", "M"];
|
||||||
|
for restricted_arg in &["d", "i"] {
|
||||||
|
for conflicting_arg in &conflicting_args {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg(&format!("-{}{}", restricted_arg, conflicting_arg))
|
||||||
|
.fails();
|
||||||
|
}
|
||||||
|
for conflicting_arg in &conflicting_args {
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&[
|
||||||
|
format!("-{}", restricted_arg).as_str(),
|
||||||
|
"-k",
|
||||||
|
&format!("1,1{}", conflicting_arg),
|
||||||
|
])
|
||||||
|
.succeeds();
|
||||||
|
}
|
||||||
|
for conflicting_arg in &conflicting_args {
|
||||||
|
// FIXME: this should ideally fail.
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["-k", &format!("1{},1{}", restricted_arg, conflicting_arg)])
|
||||||
|
.succeeds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_trailing_separator() {
|
fn test_trailing_separator() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
|
|
Loading…
Reference in a new issue