Skip to content

Fix lockfile entry parsing for modern bun.lock shapes - #101

Open
typedrat wants to merge 2 commits into
nix-community:masterfrom
synapdeck:typedrat/lockfile-entry-shapes
Open

Fix lockfile entry parsing for modern bun.lock shapes#101
typedrat wants to merge 2 commits into
nix-community:masterfrom
synapdeck:typedrat/lockfile-entry-shapes

Conversation

@typedrat

@typedrat typedrat commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Trying to run bun2nix against opencode's lockfile (~3,200 packages, the reproduction from #77) turned up a batch of parsing failures at generation time. The common thread is that the deserializer dispatched entries on tuple arity, and bun doesn't keep entry kinds and arities in one-to-one correspondence anymore:

  • github entries can carry an integrity hash, making them arity 4 — they land in the npm parser
  • vendored tarball entries can carry inline metadata, making them arity 3 — their bare relative paths match neither the http nor github: prefix, so they land in the git parser and fail with MissingGitRef

The first commit dispatches on the identifier's resolution instead (github:, git+, http(s)://, npm for bare versions at arity 4, file paths otherwise), reusing the drain_package_specifier helper that landed with the #76 fix to pull the resolution out of the identifier. That fix already disambiguates arity-3 entries by prefix, but arity-4 github entries (ones carrying an integrity hash) still reach the npm parser, and bare vendored tarball paths (vendor/pkg-1.0.0.tgz, no file:/./ prefix) still fail with MissingFileSpecifier — both are covered by the resolution-based dispatch here.

The second commit fixes where those vendored paths point. A "<workspace-name>/<pkg>" entry records its path relative to that workspace's directory, but bun.nix paths resolve from the project root — so a tarball vendored under packages/app rendered as ./vendor/pkg.tgz (doesn't exist) and a sibling workspace's ../app/vendor/pkg.tgz escaped the root entirely. Package building is factored out of convert_lockfile_to_nix_expression into a build_packages function that rewrites those paths against the owning workspace's directory, with lexical ./.. normalization.

With both fixes, bun2nix parses opencode's full lockfile (workspaces, catalogs, patched deps, a github dep, vendored tarballs, pkg.pr.new tarballs) cleanly.

Tests cover each dispatch route, prefix stripping, and the nested-path rewrite (the identifier split itself is covered by drain_package_specifier's existing doctests). Existing git-deps / tarball-deps / workspace flake checks still pass.

This is the first of three PRs from getting the full opencode workspace building offline; it stands alone and doesn't depend on the other two.

typedrat added 2 commits July 25, 2026 17:51
bun does not keep entry kinds and tuple arities in one-to-one
correspondence: github entries can carry an integrity hash (arity 4) and
remote or vendored tarball entries can carry inline metadata (arity 3), so
dispatching on arity misroutes both — a github dep lands in the npm parser
and a pkg.pr.new tarball lands in the git parser, failing with
MissingGitRef.

Dispatch on the identifier's resolution instead (github:/git+/http(s)://,
npm for bare versions at arity 4, file paths otherwise). The identifier is
split at the '@' that ends the package name — the second '@' for scoped
names — which also fixes resolutions that contain '@' themselves, like
https://pkg.pr.new/@scope/pkg@sha tarball URLs. Vendored tarball paths with
no file:/./ prefix (e.g. "vendor/pkg-1.0.0.tgz") are now accepted as file
packages.
A "<workspace-name>/<pkg>" lockfile entry records its file-dependency path
relative to that workspace's directory, but bun.nix paths resolve from the
project root — so a vendored tarball under packages/app rendered as
./vendor/pkg.tgz (missing) and a sibling workspace's ../app/vendor/pkg.tgz
escaped the root entirely.

Factor package building out of convert_lockfile_to_nix_expression into
build_packages, and rewrite CopyToStore paths for entries nested under a
workspace (longest workspace-name prefix wins) with lexical ././..
normalization.
@typedrat
typedrat force-pushed the typedrat/lockfile-entry-shapes branch from 483198a to aab1304 Compare July 26, 2026 00:55
Aurelian-Shuttleworth added a commit to Shuttleworth-Tech/opencode that referenced this pull request Jul 29, 2026
Adds .#opencode-bun2nix, a side-by-side packaging derivation that vendors deps from bun.lock via bun2nix (per-tarball fetchurl) instead of the node_modules FOD. Existing .#opencode / nix/node_modules.nix / nix/hashes.json and all CI are untouched.

- flake.nix: bun2nix input pinned to nix-community/bun2nix#101 (aab1304). master/2.1.2 cannot parse this repo's github dependency (ghostty-web) — anomalyco#101 fixes modern bun.lock entry shapes (github deps carrying an integrity hash). Repoint to a release tag once anomalyco#101 merges.
- nix/opencode-bun2nix.nix: mirrors opencode.nix with bun2nix.hook + fetchBunDeps (offline install, hoisted linker, --ignore-scripts parity via dontRunLifecycleScripts).
- opencode-deps.nix: generated via 'bun2nix -o opencode-deps.nix'.

Verified: nix build .#opencode-bun2nix produces opencode 1.18.8 (build smoke test + versionCheckHook pass).
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