Skip to content

fix(pkginfo): a bare dependency name is not the same thing as an ambiguous one (0.0.56) - #40

Merged
Sunrisepeak merged 3 commits into
mainfrom
fix/dep-install-dir-fallback
Aug 10, 2026
Merged

fix(pkginfo): a bare dependency name is not the same thing as an ambiguous one (0.0.56)#40
Sunrisepeak merged 3 commits into
mainfrom
fix/dep-install-dir-fallback

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

Fixes the dependency-resolution half of openxlings/xlings#524.

What broke

0.0.55 made explicit dependency store roots the resolver for dep_install_dir, and gated resolved_deps' bare-name branch on _is_exact_store_version as well. That precondition disambiguated nothing — the uniqueness guard was already there and already failed closed — and its only effect was to reject the unversioned query, which is the shape every recipe in xim-pkgindex writes.

Measured by replaying each published call site with and without the roots field: 6 of 7 returned nil once xlings 2026.8.10.1 began filling dependency_store_roots unconditionally.

libxpkg roots absent roots present
0.0.54 0/7 broken 0/7 broken
0.0.55 0/7 6/7
0.0.56 (before this PR) 0/7 6/7 — diagnosed correctly, only added diagnostics
this PR 0/7 0/7

gcc and meson could not install on any cold home; godot silently fell back to the host's GL; the graphics banner reported unknown.

The distinction

Ambiguity is a property of the record set, not of how specific the question was. resolved_deps is a closed table of the package's own declared deps, so "is there a second record with this bare name" is decidable here. That is what makes it different from the explicit roots, where refusing to guess is the right answer — and that part is unchanged.

Nothing is narrowed

Every query 0.0.55/0.0.56 answered is answered the same way. Collisions still fail closed (now naming both providers). An exact namespaced coordinate absent from the roots is still a definite no. A record whose payload is not on disk is still a miss. Clients with no roots field keep the scan.

The version half now matches as a range, not a literal — xlings#481 again: >=2.39 compared as a string to the resolver's chosen 2.44 is unequal, and a caller restates the range it declared, never the pick.

Tests

Four new ExecutorTest.PkgInfo_* cases, each verified to fail against the unfixed pkginfo: the bare unversioned query that is #524 itself, range-vs-pick matching, the collision naming both providers without the misleading generic advice, and the absent payload. All 14 pre-existing PkgInfo tests still pass.

Second commit fixes a diagnostic that told an undeclared-coordinate caller to omit a version it had already omitted.

Verify

xlings/.agents/tools/repro-dep-install-dir.sh          # 0.0.54 / 0.0.55 / 0.0.56
xlings/.agents/tools/repro-dep-install-dir.sh worktree # any working tree

…absent one (0.0.56)

0.0.55 made explicit dependency store roots the resolver for `dep_install_dir`
when the host supplies them. Those roots answer an EXACT, NAMESPACED coordinate
and nothing else, on purpose -- a bare `zlib` would have to pick between
`compat-x-zlib` and `other-x-zlib`, and guessing is the decoy problem the roots
exist to remove. That part was right and is unchanged.

What was wrong is that an underspecified query returned nil with no word to the
caller, and a recipe cannot tell that from "the dependency is not installed".

Measured under xlings 2026.8.10.1: `gcc.lua` and `llvm.lua` both call
`pkginfo.dep_install_dir("glibc")` -- bare and unversioned -- while both declare
`xim:glibc@>=2.39`. They know the namespace; they just did not pass it. Both got
nil and reported "glibc payload not found" on a home where glibc was installed,
and gcc could not install on Linux at all. Under 0.0.54 and earlier the roots
field did not exist, so the legacy scan ran and the same call resolved.

The query is answerable the moment the caller names the dependency the way it
declared it: `dep_install_dir("xim:glibc")` goes through `resolved_deps`, the
single source this path is built around. So nil stays, and now it explains
itself and shows the call that works.

Three tests. Two of them are the ones that matter:

  NamespacedUnversionedQueryUsesResolvedRecord   the fix recipes should adopt
  BareNameUnderExplicitRootsExplainsItself       the diagnostic, asserted by
                                                 its text, not by its absence
  ExactNamespacedCoordinateStillFailsClosed      the 0.0.55 guarantee, intact

A first attempt made the roots a preferred source with a fallback to the scan.
It fixed gcc and broke three existing tests -- ExplicitRootsRejectBareNameRequests
among them -- because the scan is exactly the guessing those tests forbid. The
tests were right; keeping them red would have traded a loud failure for a quiet
wrong answer.
…guous one

0.0.55 made explicit dependency store roots the resolver for `dep_install_dir`,
and gated the `resolved_deps` bare-name branch on `_is_exact_store_version`
as well. That precondition disambiguated NOTHING -- the uniqueness guard was
already there and already failed closed -- and its only effect was to reject
the unversioned query, which is the shape every recipe in the index writes.

Measured against the published recipes (openxlings/xlings#524), replaying each
call site with and without the roots field: 6 of 7 returned nil once xlings
2026.8.10.1 started filling `dependency_store_roots` unconditionally. gcc and
meson could not install on any cold home; godot silently fell back to the
host's GL, which is the exact mcpp#352 failure its dependency exists to
prevent. 0.0.56 diagnosed this correctly and only added diagnostics -- same
6 of 7 still nil, now loud.

The distinction that matters: ambiguity is a property of the RECORD SET, not
of how specific the question was. `resolved_deps` is a closed table of this
package's own declared deps, so "is there a second record with this bare name"
is decidable here. That is what makes it different from the explicit roots,
where refusing to guess IS the right answer -- and that part is unchanged.

So the bare branch now matches on the name and lets the uniqueness guard rule,
a collision names both providers instead of returning a bare nil, and the
version half matches as a RANGE rather than a literal. That last one is
xlings#481 again: `>=2.39` compared as a string to the resolver's chosen 2.44
is unequal, and the caller restates the range, never the pick.

Nothing is narrowed. Every query 0.0.55/0.0.56 answered is answered the same
way, collisions still fail closed, an exact namespaced coordinate absent from
the roots is still a definite no, and a record whose payload is not on disk is
still a miss with its own message. Clients with no roots field keep the scan.

`resolved_dep` gained a second return value naming why it declined, so an
ambiguous name no longer also gets "you did not name a namespace" printed
under it -- that advice points at the wrong fix when two namespaces answer.

Four tests, each verified to fail against the unfixed pkginfo: the bare
unversioned query that is #524 itself, range-vs-pick matching, the collision
naming both providers without the generic advice, and the absent payload.

Refs openxlings/xlings#524
…clared dep

A namespaced coordinate with no version and no resolver record fell into the
branch that says explicit dependency stores need an exact version, and offers
"omit the version to use the resolved dependency record instead" -- which is
what the caller already did. The real problem is that there is no record: the
coordinate is not a declared dependency of this package.

Measured while building the #524 e2e: `dep_install_dir("xim:never-declared")`
from a hook whose deps do not mention it produced advice that, followed
literally, changes nothing.

Now it names the cause and the two ways out -- declare it, or use
tool_payload_dir if the hook installed the payload itself -- and prints what
this package actually declares, so the reader can see the mismatch rather than
infer it.
@Sunrisepeak
Sunrisepeak merged commit cf46d93 into main Aug 10, 2026
1 check passed
@Sunrisepeak
Sunrisepeak deleted the fix/dep-install-dir-fallback branch August 10, 2026 03:21
FarnaHerry pushed a commit to FarnaHerry/mcpp-index that referenced this pull request Aug 10, 2026
Fixes openxlings/xlings#524: `dep_install_dir` gated on how specific the query
was rather than on whether the answer was unique, and six of the seven call
sites in xim-pkgindex returned nil once xlings 2026.8.10.1 began supplying
explicit dependency store roots -- gcc and meson could not install on any cold
home.

GLOBAL is the tag tarball; CN is a byte-identical copy on gitcode, verified by
downloading both and comparing sha256 (4d20f5d3...518e2a).

openxlings/libxpkg#40
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