refactor(builtins): migrate readlink to codegen-ported argument surface#1542
Merged
refactor(builtins): migrate readlink to codegen-ported argument surface#1542
Conversation
readlink moves from handwritten char-by-char short-flag parsing to
the bashkit-coreutils-port codegen pipeline. Replaces the manual
parser (~50 LoC of `match arg.as_str()` plus a combined-flag loop)
with `readlink_command().try_get_matches_from(...)`.
Codegen tool extension: bashkit-coreutils-port now also handles utils
that declare option keys as module-level `const OPT_FOO: &str = ...`
or `static OPT_FOO` rather than wrapping them in `mod options { }`.
The two patterns coexist in uutils (cat/tac/truncate/stat/shuf use
the mod, mktemp/realpath/readlink/od use bare consts); the tool now
emits whichever the source uses without requiring per-util branches
in the bashkit codebase.
Behaviour fixes accompanying the migration:
- `-n` / `--no-newline` now suppresses the trailing terminator on the
last operand (previously silently accepted as a no-op).
- `-z` / `--zero` switches the terminator to NUL (previously rejected
as unknown).
- Combined short flags like `-fn` now parse natively via clap; the
manual `for ch in s[1..].chars()` loop is gone.
- Unknown flags now exit with clap's exit code 2 instead of the
custom code 1; documented as a clap-vs-GNU divergence in the spec
test (`### bash_diff`), matching cat / tac / truncate / shuf.
Tests:
- `crates/bashkit/tests/spec_cases/bash/readlink.test.sh` covers
`-f`/`-m`/`-e`, combined short flags, long form, and unknown-flag
rejection.
- `generated_args_headers_match_pinned_uutils_revision` continues
to pass against the existing pin (39364b6).
Spec: implementation-status.md adds the new test row.
Part of #1532.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
bashkit | ac8daf3 | Commit Preview URL Branch Preview URL |
May 05 2026, 11:15 PM |
`test_readlink_invalid_option` previously asserted exit 1 with stderr containing "invalid option" — the GNU/handwritten convention. After the codegen migration, clap exits 2 with "unexpected argument". Additionally, -z is now a valid flag (zero-terminate output), so the test must pick a flag that is genuinely not part of the ported surface. The clap-vs-GNU exit-code divergence is already documented as a \`### bash_diff\` row in the spec test; mirror that in the unit assertion. Same fix as the prior cat/tac/truncate/shuf migrations. Part of #1532.
The previous fix used `{:?}` which trips
`no_debug_fmt_in_builtin_source`. Switch to `{}` — the asserted value
is a String for which Display reads cleanly.
chaliy
added a commit
that referenced
this pull request
May 6, 2026
Minor release `0.4.1` → `0.5.0`. Two new builtins (`shuf`, `truncate`), a coreutils-codegen pipeline that ports uutils' `uu_app()` clap definitions for `cat`/`tac`/`truncate`/`shuf`/`readlink`, and `tool_def` flag-syntax improvements. ## Highlights - **Coreutils argument surface via codegen** — Ports uutils' `uu_app()` clap definitions into bashkit so builtins share the real coreutils argument shape; `cat`, `tac`, `truncate`, `shuf`, and `readlink` now flow through this surface, with a coreutils differential testing harness to catch parity drift. Pipeline reads a single pinned uutils revision so generated builtins, the differential harness, and CI all agree on the upstream source of truth (#1529, #1535, #1536, #1537, #1538, #1542). - **Site updates** — Bashkit agent skill is now published on the site, alongside rustdoc guides and content signal declarations for discoverability. ## What's Changed * refactor(builtins): migrate readlink to codegen-ported argument surface (#1542) * chore(site): publish bashkit agent skill (#1541) * chore(site): declare content signals * docs(site): publish rustdoc guides * feat(builtins): add shuf via codegen with helper-fn inlining (#1538) * chore(builtins): pin uutils revision as single source of truth (#1537) * feat(builtins): add truncate via codegen-ported argument surface (#1536) * test(builtins): add coreutils differential testing harness (#1535) * feat(builtins): port uutils argument surfaces via codegen (POC: cat, tac) (#1529) * feat(tool_def): accept --flag key=value... syntax for object/array flags (#1528) * fix(tool_def): coerce stringified JSON for array/object flag schemas (#1527) ## Publish-readiness report Per the updated `specs/release-process.md`: - [x] `cargo fmt --check` clean - [x] `cargo clippy --all-targets --all-features -- -D warnings` clean - [x] `cargo build` clean - [x] Versions synced across `Cargo.toml`, `crates/bashkit-cli/Cargo.toml`, `crates/bashkit-js/package.json`, `package-lock.json`, `Cargo.lock` - [x] `cargo publish --dry-run -p bashkit --allow-dirty` (after CI's monty-strip): **success** - [x] `cargo publish --dry-run -p bashkit-cli`: blocked only on ordering (`bashkit 0.5.0` not yet on crates.io) — resolves at real publish time when `publish-bashkit` runs first per `publish.yml`'s `needs:` chain. - [x] New `0.5.0` > latest published versions on crates.io / PyPI / npm (`0.4.1`). ## Companion change This branch also includes `chore(specs): document publish verification and post-merge monitoring`, codifying the verify-before-tag and watch-after-merge flow that this release follows. On merge, `release.yml` will create the GitHub Release `v0.5.0` and dispatch publish workflows for crates.io, PyPI, npm, and Homebrew. **Full Changelog**: v0.4.1...v0.5.0 --- _Generated by [Claude Code](https://claude.ai/code/session_01SvuLdA8pMAmP4woG2HqxKw)_
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
readlink moves from handwritten char-by-char short-flag parsing to the
bashkit-coreutils-portcodegen pipeline. Replaces the manual parser(~50 LoC of
match arg.as_str()plus a combined-flag loop) withreadlink_command().try_get_matches_from(...).Codegen tool extension
bashkit-coreutils-portnow also handles utils that declare optionkeys as module-level
const OPT_FOO: &str = ...orstatic OPT_FOOrather than wrapping them in
mod options { ... }. The two patternscoexist in uutils —
cat/tac/truncate/stat/shufuse the mod,mktemp/realpath/readlink/oduse bare consts. The tool nowemits whichever the source uses without requiring per-util branches
in bashkit.
Behaviour fixes accompanying the migration
-n/--no-newlinenow suppresses the trailing terminator on thelast operand (previously silently accepted as a no-op).
-z/--zeroswitches the terminator to NUL (previously rejectedas unknown).
-fnnow parse natively via clap; themanual
for ch in s[1..].chars()loop is gone.custom code 1; documented as a clap-vs-GNU divergence in the spec
test (
### bash_diff), matching cat / tac / truncate / shuf.Test plan
cargo test -p bashkit --test spec_tests bash_spec_tests—includes new
readlink.test.sh(6 cases).generated_args_headers_match_pinned_uutils_revision— passesagainst the pinned rev (39364b6).
every_builtin_handles_bogus_flag_cleanly— passes.cargo clippy -p bashkit -p bashkit-coreutils-port --all-targets --all-features -- -D warnings— green.cargo fmt --check— green.Scope
Part of #1532. Five existing builtins remain on the codegen-migrationlist (
tee,mktemp,realpath,stat,od) — separate PRs astheir parser surfaces are larger.
Generated by Claude Code