feat(cli): support link: and file: specs in aube add#487
Conversation
Greptile SummaryThis PR extends Confidence Score: 5/5Safe to merge — only P2 style findings, core routing logic is correct and well-tested. No P0 or P1 issues found. The two findings are a dead unreachable guard in No files require special attention. Important Files Changed
Reviews (3): Last reviewed commit: "feat(cli): support link: and file: specs..." | Re-trigger Greptile |
Benchmark changesVersions:
Public ratios: warm installs vs Bun 7x -> 9x; warm installs vs pnpm 11x -> 13x.
aba32ba vs 5f05906 | aube/bun/pnpm | 3 scenarios | 3 runs | 500mbit/50ms | generated by Codex. |
The "scrub from all four dep sections, insert into the right one" shape was triplicated across the registry path, `apply_workspace_spec_to_manifest`, and `apply_local_spec_to_manifest`. Extract `upsert_manifest_dep` next to the apply_* helpers so the asymmetric peer-section logic lives in one place. No behavior change. Addresses Cursor low-severity review on PR #487. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Extracted |
Adds a non-packument branch in `parse_pkg_spec` for `file:` and `link:` local-path specs (mirroring the workspace-spec fork). The verbatim spec is written to `package.json` and the resolver's existing local branch dispatches the install — `aube add file:./pkg` no longer 404s on the registry packument fetch. Manifest key is derived from the path basename when no alias is given (`file:./packages/foo` -> `foo`, `file:./bundle.tgz` -> `bundle`). Pass an alias when the upstream `package.json` `name` differs: `aube add my-pkg@file:./packages/foo`. Sibling to PR #483 (git specs). Closes the local-path-spec followup that #483's review surfaced. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
af6a6d0 to
aba32ba
Compare
|
Rebased onto current main (post-#475 / #483) and addressed all three Greptile P2s in the squashed-and-replayed commit:
The Cursor "triplicated scrub-and-insert" low-severity is mostly addressed: Validation: cargo build/clippy/fmt clean, Written with Claude. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit aba32ba. Configure here.
| return None; | ||
| } | ||
| Some((&spec[..alias_end], &spec[alias_end + 1..])) | ||
| } |
There was a problem hiding this comment.
Missing colon check in split_scoped_alias misroutes protocol specs
Low Severity
split_scoped_alias does not reject aliases containing :, unlike split_protocol_alias which guards against protocol prefixes with alias.contains(':'). This means a spec like @jsr:@std/file@link:./pkg gets split into alias @jsr:@std/file and rest link:./pkg, causing is_local_path_spec to match and route it as a local spec — instead of falling through to the @jsr: parsing path where it belongs. Adding a contains(':') check on &spec[..alias_end] would align with the sibling function's logic.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit aba32ba. Configure here.
| let alias_end = slash + 1 + at_in_after; | ||
| if alias_end == 0 { | ||
| return None; | ||
| } |
There was a problem hiding this comment.
Dead alias_end == 0 guard is unreachable code
Low Severity
The alias_end == 0 check in split_scoped_alias can never be true. Since the spec starts with @, slash (from spec.find('/')) is always ≥ 1, and at_in_after is always ≥ 0, so alias_end = slash + 1 + at_in_after is always ≥ 2. This dead branch provides false reassurance that an edge case is handled.
Reviewed by Cursor Bugbot for commit aba32ba. Configure here.
`aube add /path/to/lib` (and `./lib`, `../lib`, `~/lib`, `C:/projects/lib`) used to fall through to the registry path and surface a confusing HTTP 405 from npmjs. The recently-merged `file:` / `link:` support (#487) only handled the prefixed forms. Match pnpm's `parseBareSpecifier`: detect path-shaped specs at parse time and route them through the existing local-path machinery. Bare paths default to `link:` for directories and `file:` for tarballs (pnpm parity); `~/` is expanded eagerly because the resolver has no tilde handling. The drive-letter check requires `/` or `\` after the colon so a single-character npm alias like `a:1.0.0` isn't reclassified as a Windows path. Closes discussions/497. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`aube add /path/to/lib` (and `./lib`, `../lib`, `~/lib`, `C:/projects/lib`) used to fall through to the registry path and surface a confusing HTTP 405 from npmjs. The recently-merged `file:` / `link:` support (#487) only handled the prefixed forms. Match pnpm's `parseBareSpecifier`: detect path-shaped specs at parse time and route them through the existing local-path machinery. Bare paths default to `link:` for directories and `file:` for tarballs (pnpm parity); `~/` is expanded eagerly because the resolver has no tilde handling. The drive-letter check requires `/` or `\` after the colon so a single-character npm alias like `a:1.0.0` isn't reclassified as a Windows path. Closes discussions/497. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`aube add /path/to/lib` (and `./lib`, `../lib`, `~/lib`, `C:/projects/lib`) used to fall through to the registry path and surface a confusing HTTP 405 from npmjs. The recently-merged `file:` / `link:` support (#487) only handled the prefixed forms. Match pnpm's `parseBareSpecifier`: detect path-shaped specs at parse time and route them through the existing local-path machinery. Bare paths default to `link:` for directories and `file:` for tarballs (pnpm parity); `~/` is expanded eagerly because the resolver has no tilde handling. The drive-letter check requires `/` or `\` after the colon so a single-character npm alias like `a:1.0.0` isn't reclassified as a Windows path. Closes discussions/497. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`aube add /path/to/lib` (and `./lib`, `../lib`, `~/lib`, `C:/projects/lib`) used to fall through to the registry path and surface a confusing HTTP 405 from npmjs. The recently-merged `file:` / `link:` support (#487) only handled the prefixed forms. Match pnpm's `parseBareSpecifier`: detect path-shaped specs at parse time and route them through the existing local-path machinery. Bare paths default to `link:` for directories and `file:` for tarballs (pnpm parity); `~/` is expanded eagerly because the resolver has no tilde handling. The drive-letter check requires `/` or `\` after the colon so a single-character npm alias like `a:1.0.0` isn't reclassified as a Windows path. Closes discussions/497. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>


Summary
file:/link:local-path specs (file:./pkg,link:../sibling,file:./bundle.tgz). Sits alongside the workspace-spec fork; mirrors the structural shape of feat(cli): support git specs in aube add #483 (git specs).my-alias@file:./pkg), otherwise the basename of the path (with.tgz/.tar.gzstripped). Verbatim spec is written intopackage.jsonand the resolver's existing local branch (is_non_registry_specifier) dispatches the install on next pass.aube add file:./pkgno longer 404s on the registry.Sibling to PR #483 (git specs). Closes the local-path-spec followup that #483's review surfaced. The new branch is parallel to the git-spec branch in
parse_pkg_spec— when #483 lands the two branches sit side-by-side without nesting.Test plan
cargo build --workspacecargo test --workspace— 9 new unit tests incommands::add::testscoverfile:/link:relative + absolute, tarball-basename derivation, alias forms, scoped/git non-collisions, and the barefile:+ alias edge casecargo clippy --all-targets -- -D warnings— cleancargo fmt --checkmise run test:bats test/add.bats— 28 tests pass (3 new offline tests forfile:/link:/ aliasedfile:)mise run test:bats test/local_deps.bats— regression check, 10 tests passmise run test:bats test/pnpm_install_misc.bats— regression check, 30 tests passNote
Medium Risk
Extends
aube addparsing/routing to treatfile:/link:(and scoped/aliased variants) as non-registry deps, which could impact how ambiguous specs are classified and when registry packument fetches are skipped.Overview
aube addnow supportsfile:andlink:local-path dependencies by routing them through the same non-registry flow as git specs: skip packument fetch/catalog logic and write the verbatim spec intopackage.jsonfor the resolver to handle.This introduces local-spec parsing with basename-based manifest key derivation (including stripping
.tgz/.tar.gz/.tar), supports alias and@scope/alias@<spec>forms for both git and local specs, updates the packument-fetch skip guards accordingly, and adds unit + bats coverage for the new behaviors.Reviewed by Cursor Bugbot for commit aba32ba. Bugbot is set up for automated code reviews on this repo. Configure here.