Skip to content

feat(engine): --sort=name for deterministic sibling ordering - #114

Merged
helly25 merged 1 commit into
mainfrom
feat/sort-name
Jun 24, 2026
Merged

feat(engine): --sort=name for deterministic sibling ordering#114
helly25 merged 1 commit into
mainfrom
feat/sort-name

Conversation

@helly25

@helly25 helly25 commented Jun 24, 2026

Copy link
Copy Markdown
Owner

--sort=name - reproducible traversal order

Adds --sort[=name], an xff extension: order each directory's entries by name before visiting, so xff's output is reproducible and diffable instead of filesystem-readdir order (find's default - non-deterministic across filesystems/runs). --sort=none (or no flag) keeps the fast readdir order; bare --sort means --sort=name; last occurrence wins.

What

  • WalkOptions gains SortOrder { kNone, kName }; Walker::Descend sorts the ReadDir result by .path (siblings share the directory prefix, so path order == name order) when kName - covering both pre-order and -depth post-order in one place.
  • run.cc ResolveSort(globals) maps --sort/--sort=name -> kName, --sort=none -> kNone.

Test

run_test: --sort visits root, then a.txt < b.md < sub, then sub/c.txt in that exact order (ElementsAre); the unsorted default keeps UnorderedElementsAre.

bazel test //... green in both --config=clang and --config=clang --config=asan. clang-format + em-dash clean.

The parallel-traversal half of #43 remains a separate follow-up (it needs the walk threaded, deferred to keep this contained and low-risk).

Add --sort[=name], an xff extension: order each directory's entries by name before
visiting, so the walk is reproducible and diffable instead of filesystem-readdir
order (find's default, which --sort=none / absence preserves). Bare --sort means
--sort=name; last occurrence wins.

- WalkOptions gains SortOrder { kNone, kName }; Walker::Descend sorts the ReadDir
  result by path (siblings share the dir prefix, so path order is name order) when
  kName, covering both pre- and post-order.
- run.cc ResolveSort(globals) maps --sort / --sort=name -> kName, --sort=none -> kNone.

Tests: run_test (--sort visits root, a.txt < b.md < sub, sub/c.txt in that exact
order via ElementsAre; the unsorted default stays UnorderedElementsAre). Green in
both configs; clang-format + em-dash clean.

The parallel-traversal half of #43 remains a separate follow-up.
@helly25
helly25 merged commit bbcb405 into main Jun 24, 2026
5 checks passed
@helly25
helly25 deleted the feat/sort-name branch June 24, 2026 07:54
helly25 added a commit that referenced this pull request Jul 6, 2026
A per-text-file line count in the field vocabulary: {lines}, %{lines} in
-printf, and --template - wc -l style but also counting a final unterminated
line. Empty for a non-regular, unreadable, or binary file (grep/ripgrep's
NUL-byte-in-first-8KiB heuristic), so binaries render nothing rather than a
misleading count.

- xff/content: CountLines (pure, reuses the CollectLineMatches grep line
  semantics via ForEachLine) + FileLineCount (reads via mbo::file::Artefact,
  skips binary), next to the line-match logic they share.
- xff/fields: LinesField reads by path (like {hash}), gated on a regular-file
  metadata type; registered in the field table + FieldDocs (so --help=fields,
  man, and markdown list it by construction).
- Tests: CountLines/FileLineCount unit tests, LinesField render tests
  (text/no-newline/empty/binary/unreadable/non-regular), and a CLI bashtest
  driving -printf %{lines} end to end.

The aggregate side (sum + distribution across matches) is the histograms
work (#81), not part of this field.
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.

1 participant