Skip to content

refactor uu_ls so that crate users can call the ls without having to print everything to stdout#9851

Merged
cakebaker merged 15 commits into
uutils:mainfrom
fdncred:refactor_uu_ls_for_others
Apr 17, 2026
Merged

refactor uu_ls so that crate users can call the ls without having to print everything to stdout#9851
cakebaker merged 15 commits into
uutils:mainfrom
fdncred:refactor_uu_ls_for_others

Conversation

@fdncred
Copy link
Copy Markdown
Contributor

@fdncred fdncred commented Dec 26, 2025

I was wanting to use uu_ls in nushell and found out that I couldn't because some of the internals weren't exposed in a way such that crate callers could really use it. So, I was wondering if something like this PR would be something worth considering?

It refactors the code in such a way so that crate callers could call uu_ls and get structured data back instead of everything printing to stdout. It does this without a breaking change by implementing a type of visitor pattern through the LsOutput trait.

I created a TextOutput struct that impelments the LsOutput trait so now the list() function now looks like this:

   pub fn list(locs: Vec<&Path>, config: &Config) -> UResult<()> {
       let mut output = TextOutput::new(config);
       list_with_output(locs, config, &mut output)
   }

All of this allows crate callers like nushell to now do something like this:

use std::ffi::OsString;
use std::path::Path;
use uu_ls::{CollectorOutput, Config, list_with_output, uu_app};

fn main() -> Result<(), String> {
    let matches = uu_app()
        .try_get_matches_from(vec![OsString::from("ls")])
        .map_err(|err| err.to_string())?;

    let config = Config::from(&matches).map_err(|err| err.to_string())?;
    let mut output = CollectorOutput::new();

    list_with_output(vec![Path::new(".")], &config, &mut output).map_err(|err| err.to_string())?;

    for entry in output.entries() {
        // Convert to Nushell Value with full type information
        let name = entry.display_name.to_string_lossy();
        let size = entry.size().unwrap_or(0);
        let is_dir = entry.is_dir();
        // ...
        println!("name: {name}\nsize: {size}\ndir: {is_dir}\nentry: {entry:?}");
    }

    Ok(())
}

One last note, I know I didn't discuss this with anyone so it won't hurt my feelings if this PR isn't accepted. I'm open to whatever. I was just trying to figure out a way to reuse more of the excellent coreutils code. Thanks for such a great repo!!!

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Note: The gnu test tests/pr/pr-tests was skipped on 'main' but is now failing.

@sylvestre
Copy link
Copy Markdown
Contributor

sorry, it needs to be rebased

@sylvestre
Copy link
Copy Markdown
Contributor

Sorry, could you please rebase it? Sorry again

@fdncred fdncred force-pushed the refactor_uu_ls_for_others branch from 59813c6 to a2e601e Compare April 9, 2026 16:32
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 9, 2026

GNU testsuite comparison:

GNU test failed: tests/ls/recursive. tests/ls/recursive is passing on 'main'. Maybe you have to rebase?
Skip an intermittent issue tests/tail/inotify-dir-recreate (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tail/tail-n0f (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tty/tty-eof (fails in this run but passes in the 'main' branch)
Note: The gnu test tests/basenc/bounded-memory is now being skipped but was previously passing.
Note: The gnu test tests/printf/printf-surprise is now being skipped but was previously passing.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 9, 2026

Merging this PR will degrade performance by 10.19%

⚡ 5 improved benchmarks
❌ 4 regressed benchmarks
✅ 300 untouched benchmarks
⏩ 46 skipped benchmarks1

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

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory ls_recursive_deep_tree[(200, 2)] 143.3 KB 159.5 KB -10.19%
Memory ls_recursive_mixed_tree 133 KB 141.6 KB -6.12%
Memory ls_recursive_long_all_deep_tree[(100, 4)] 126.3 KB 133.7 KB -5.59%
Memory ls_recursive_long_all_mixed_tree 133.6 KB 142.3 KB -6.11%
Simulation ls_recursive_long_all_deep_tree[(100, 4)] 2.6 ms 2.4 ms +4.44%
Simulation ls_recursive_mixed_tree 1.3 ms 1.2 ms +5.24%
Simulation ls_recursive_long_all_mixed_tree 2.3 ms 2.3 ms +4.16%
Simulation ls_recursive_deep_tree[(200, 2)] 1.7 ms 1.5 ms +15.12%
Simulation ls_recursive_wide_tree[(10000, 1000)] 35.7 ms 32.9 ms +8.29%

Comparing fdncred:refactor_uu_ls_for_others (0f506de) with main (5daf0a5)

Open in CodSpeed

Footnotes

  1. 46 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.

@sylvestre
Copy link
Copy Markdown
Contributor

some jobs are failing and we see some quite significant regressions

Comment thread src/uu/ls/src/ls.rs Outdated

for (pos, path_data) in dirs.iter().enumerate() {
let needs_blank_line = pos != 0 || !files.is_empty();
let _needs_blank_line = pos != 0 || !files.is_empty();
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.

why _ ?

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.

oops. fixed.

@fdncred
Copy link
Copy Markdown
Contributor Author

fdncred commented Apr 10, 2026

some jobs are failing and we see some quite significant regressions

@sylvestre I tried to address these performance concerns. I'm not sure how to validate my changes other than pushing a commit.

I also changed things up a bit because one of the most important things for nushell is streaming and I forgot that when I added the CollectorOutput, which collected, duh. I removed that and replaced it with a StreamingOutput which has a batch mode as the default.

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/date/date-locale-hour (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/tty/tty-eof (passes in this run but fails in the 'main' branch)

@fdncred
Copy link
Copy Markdown
Contributor Author

fdncred commented Apr 10, 2026

@sylvestre can you start the CI so we can see if I caught everything?

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/date/resolution (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tty/tty-eof (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/tail/tail-n0f (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/csplit/csplit-heap is now being skipped but was previously passing.

@fdncred
Copy link
Copy Markdown
Contributor Author

fdncred commented Apr 11, 2026

@sylvestre hopefully this fixes the last broken test. it passes on my ubuntu vm. if we can start the ci again. i feel for y'all. so many regression tests. 🤯

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/date/date-locale-hour (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/tty/tty-eof (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/misc/write-errors was skipped on 'main' but is now failing.

@sylvestre
Copy link
Copy Markdown
Contributor

done!

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/tty/tty-eof (fails in this run but passes in the 'main' branch)
Note: The gnu test tests/pr/bounded-memory is now being skipped but was previously passing.
Note: The gnu test tests/tail/pipe-f is now being skipped but was previously passing.

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/cut/bounded-memory (fails in this run but passes in the 'main' branch)

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/pr/bounded-memory (fails in this run but passes in the 'main' branch)
Note: The gnu test tests/cut/bounded-memory is now being skipped but was previously passing.
Congrats! The gnu test tests/cut/cut-huge-range is now passing!

@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/tty/tty-eof (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/dd/no-allocate is now passing!
Congrats! The gnu test tests/printf/printf-surprise is now passing!

@sylvestre
Copy link
Copy Markdown
Contributor

the memory regressions are acceptable

@sylvestre
Copy link
Copy Markdown
Contributor

please let me known when it is ready to be reviewed

@fdncred
Copy link
Copy Markdown
Contributor Author

fdncred commented Apr 13, 2026

@sylvestre it's ready. just was trying to get that memory regression closer but i've kind of had my fill of messing with it. thanks!

@fdncred
Copy link
Copy Markdown
Contributor Author

fdncred commented Apr 15, 2026

@sylvestre any thoughts? Would like to get this landed if it's acceptible before bit rot occurs again.

Comment thread src/uu/ls/src/ls.rs
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 16, 2026

GNU testsuite comparison:

Skipping an intermittent issue tests/tail/symlink (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/expand/bounded-memory is now being skipped but was previously passing.
Note: The gnu test tests/tail/tail-n0f is now being skipped but was previously passing.
Congrats! The gnu test tests/rm/many-dir-entries-vs-OOM is now passing!
Congrats! The gnu test tests/seq/seq-epipe is now passing!

@fdncred
Copy link
Copy Markdown
Contributor Author

fdncred commented Apr 16, 2026

I don't think these CI errors are related to this PR

@sylvestre sylvestre force-pushed the refactor_uu_ls_for_others branch from 430a09b to dbed28e Compare April 17, 2026 06:00
Comment thread src/uu/ls/src/ls.rs Outdated
Comment thread src/uu/ls/src/ls.rs Outdated
Copy link
Copy Markdown
Contributor

@cakebaker cakebaker left a comment

Choose a reason for hiding this comment

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

Good work, kudos!

sylvestre and others added 2 commits April 17, 2026 11:25
Co-authored-by: Daniel Hofstetter <daniel.hofstetter@42dh.com>
Co-authored-by: Daniel Hofstetter <daniel.hofstetter@42dh.com>
@cakebaker cakebaker merged commit ceb09c7 into uutils:main Apr 17, 2026
168 of 169 checks passed
@cakebaker
Copy link
Copy Markdown
Contributor

Thanks for your PR!

@fdncred fdncred deleted the refactor_uu_ls_for_others branch April 17, 2026 12:32
sylvestre added a commit that referenced this pull request Apr 22, 2026
…11930)

* ls: restore WASI ".." metadata fallback in collect_directory_entries

The ls refactor in #9851 dropped the WASI guard added in #11633, so
`ls -al` at a preopened root once again fails with "Capabilities
insufficient" when stat'ing "..". Extract the logic into a small
`dotdot_path` helper and add a regression test covering `ls -al`.

* Update spell-checker ignore words in test_ls.rs
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.

3 participants