Skip to content

Add legacy +POS/-POS handling in sort to pass GNU sort-field-limit test#9501

Merged
cakebaker merged 7 commits into
uutils:mainfrom
karanabe:test/fix-sort-field-limit
Dec 15, 2025
Merged

Add legacy +POS/-POS handling in sort to pass GNU sort-field-limit test#9501
cakebaker merged 7 commits into
uutils:mainfrom
karanabe:test/fix-sort-field-limit

Conversation

@karanabe

Copy link
Copy Markdown
Contributor

This change translates GNU’s legacy +POS1 [-POS2] sort key syntax into -k form before clap parsing, gating it by _POSIX2_VERSION to match GNU behavior, and adds by-util tests to ensure acceptance/rejection behavior matches GNU and that the sort-field-limit compatibility test passes.

#9127

Support GNU’s obsolescent +POS1 [-POS2] syntax by translating it to -k
before clap parses args, gated by _POSIX2_VERSION. Adds tests for accept
and reject cases to ensure sort-field-limit GNU test passes.
@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

Congrats! The gnu test tests/sort/sort-field-limit is no longer failing!

Comment thread tests/by-util/test_sort.rs Outdated
Comment thread tests/by-util/test_sort.rs Outdated
@karanabe karanabe requested a review from cakebaker December 1, 2025 17:00
@github-actions

github-actions Bot commented Dec 1, 2025

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/tail/overlay-headers (fails in this run but passes in the 'main' branch)
Congrats! The gnu test tests/sort/sort-field-limit is no longer failing!

Comment thread src/uu/sort/src/sort.rs Outdated
Comment on lines +1112 to +1116
let mut idx = 0;
let bytes = spec.as_bytes();
while idx < bytes.len() && bytes[idx].is_ascii_digit() {
idx += 1;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think a functional approach is cleaner. Something like:

Suggested change
let mut idx = 0;
let bytes = spec.as_bytes();
while idx < bytes.len() && bytes[idx].is_ascii_digit() {
idx += 1;
}
let idx = spec.chars().take_while(|c| c.is_ascii_digit()).count();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was fixed in this commit. 3b52b5d

Comment thread src/uu/sort/src/sort.rs Outdated
Comment on lines +1126 to +1130
let mut char_idx = 0;
let stripped_bytes = stripped.as_bytes();
while char_idx < stripped_bytes.len() && stripped_bytes[char_idx].is_ascii_digit() {
char_idx += 1;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same here.

Suggested change
let mut char_idx = 0;
let stripped_bytes = stripped.as_bytes();
while char_idx < stripped_bytes.len() && stripped_bytes[char_idx].is_ascii_digit() {
char_idx += 1;
}
let char_idx = stripped.chars().take_while(|c| c.is_ascii_digit()).count();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was fixed in this commit. 3b52b5d

Comment thread src/uu/sort/src/sort.rs Outdated
#[derive(Debug, Clone)]
struct LegacyKeyPart {
field: usize,
char: usize,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The name char is a bit unlucky.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was fixed in this commit. 3b52b5d

Comment thread src/uu/sort/src/sort.rs Outdated
to.field.saturating_add(1)
};

let mut end_part = end_field.to_string();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What's the reason for introducing end_part? Couldn't you reorder things a bit and push directly to keydef?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was fixed in this commit. bf7a8ab

Comment thread src/uu/sort/src/sort.rs Outdated
}
}

fn parse_legacy_part(spec: &str, default_char: usize) -> Option<LegacyKeyPart> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is the default_char param necessary? It's 0 in both places this function is called.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was fixed in this commit. 3b52b5d

Comment thread src/uu/sort/src/sort.rs Outdated
Comment on lines +1214 to +1218
if stripped
.as_bytes()
.first()
.is_some_and(|c| c.is_ascii_digit())
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think you can simplify it with starts_with:

Suggested change
if stripped
.as_bytes()
.first()
.is_some_and(|c| c.is_ascii_digit())
{
if stripped.starts_with(|c: char| c.is_ascii_digit()) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was fixed in this commit. e477de9

@codspeed-hq

codspeed-hq Bot commented Dec 14, 2025

Copy link
Copy Markdown

CodSpeed Performance Report

Merging #9501 will degrade performances by 4.51%

Comparing karanabe:test/fix-sort-field-limit (a10c06e) with main (64203e3)

Summary

⚡ 1 improvement
❌ 2 regressions
✅ 124 untouched
⏩ 6 skipped1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Benchmark BASE HEAD Change
sort_ascii_c_locale 21.6 ms 22.6 ms -4.51%
sort_numeric 24 ms 23.5 ms +2.04%
tsort_input_parsing_heavy[5000] 82.1 ms 83.8 ms -2.04%

Footnotes

  1. 6 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

Skipping an intermittent issue tests/tail/overlay-headers (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/sort/sort-field-limit is no longer failing!

@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

Skipping an intermittent issue tests/tail/overlay-headers (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/sort/sort-field-limit is no longer failing!

@karanabe karanabe requested a review from cakebaker December 14, 2025 11:48
@karanabe

Copy link
Copy Markdown
Contributor Author

@cakebaker Thanks for the review! I've addressed all the comments.
Regarding the test failure, test_tail::test_retry6 stdout does not seem to be related to this change and appears to be failing elsewhere as well.
Could you please take another look?

@cakebaker cakebaker merged commit 06d843f into uutils:main Dec 15, 2025
125 of 127 checks passed
@cakebaker

Copy link
Copy Markdown
Contributor

Congrats! The gnu test tests/sort/sort-field-limit is no longer failing!

Kudos, thanks!

@karanabe karanabe deleted the test/fix-sort-field-limit branch January 17, 2026 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants