Skip to content

chore: normalize xpkg identity layout, enforce it in lint, pin CI to mcpp 0.0.105#117

Closed
Sunrisepeak wants to merge 1 commit into
mainfrom
chore/normalize-xpkg-identity-and-mcpp-0.0.105
Closed

chore: normalize xpkg identity layout, enforce it in lint, pin CI to mcpp 0.0.105#117
Sunrisepeak wants to merge 1 commit into
mainfrom
chore/normalize-xpkg-identity-and-mcpp-0.0.105

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

TL;DR

The index was already clean on identity — all 49 descriptors declare a fully-qualified name with an atomic short segment, so mcpp#278's split form appears nowhere here. No namespace or name value changes in this PR.

What was not pinned was the layer below: where a descriptor lives. That gap had let two real defects in.

Normalization

Change Why
pkgs/c/capi.lua.lua deleted Byte-identical duplicate (same md5) of pkgs/m/mcpplibs.capi.lua.lua — same identity (mcpplibs.capi, lua). Whichever the directory scan reached first won; edits to the other were dead code nobody would notice.
pkgs/t/tensorvia-cpu.luapkgs/a/aimol.tensorvia-cpu.lua Canonical path for identity (aimol, tensorvia-cpu). Off-canonical names still resolve, but only through a COMPAT filename fallback mcpp schedules for removal in 1.0.0.

Lint now enforces all three identity rules

Rule 1 — name == <namespace>.<short> (existing, kept).

Rule 2 — short is a SINGLE atomic segment; depth belongs in namespace. (new)

namespace = "mcpplibs.capi",  name = "mcpplibs.capi.lua"   -- ✅ (mcpplibs.capi, lua)
namespace = "mcpplibs",       name = "mcpplibs.capi.lua"   -- ❌ short = "capi.lua"

Both survive mcpp's normalizer, because it splits the FQN on its last dot — so the second silently resolves to (mcpplibs.capi, lua), a namespace the descriptor never declared. After this rule the declared namespace and the canonical one are always the same string.

Rule 3 — descriptor sits at the canonical path for its identity. (new, tests/check_package_filename.lua) — this is the check that found both defects above.

(mcpplibs, cmdline)       → pkgs/c/cmdline.lua
(compat,   zlib)          → pkgs/c/compat.zlib.lua
(aimol,    tensorvia-cpu) → pkgs/a/aimol.tensorvia-cpu.lua
(mcpplibs.capi, lua)      → pkgs/m/mcpplibs.capi.lua.lua

The filename is not part of identity (mcpp resolves identity-first and re-verifies every hit against the file's own package.{namespace,name}), so this is about two other things: keeping a package on mcpp's first filename probe, and making duplicate descriptors for one identity impossible to add unnoticed.

Zero-namespace packages are untouched

imgui / ffmpeg / opencv keep namespace = "" — their bare name is the FQN, which is a deliberate, legal form. Consumers keep writing imgui = "0.0.3"; xlings key and store dir unchanged. Rule 2 still guards them: a dotted name with no declared namespace would resolve into a namespace written down nowhere.

CI → mcpp 0.0.105

env.MCPP_VERSION and all three matrix entries bumped 0.0.102 → 0.0.105, where mcpp xpkg parse enforces Rule 1 itself (INV-NAME, mcpp-community/mcpp#278). The two lua lints therefore become an earlier, cheaper second gate rather than the only defense.

index.toml's min_mcpp/latest_mcpp deliberately stay at 0.0.102. The floor is a consumer contract; 0.0.105 carries a breaking change (bare names no longer reach third-party namespaces) and nothing in this index needs 0.0.105 grammar — so there is no reason to force every consumer forward. Rationale recorded inline in validate.yml.

Verification

Run locally against real mcpp 0.0.105:

  • All 48 descriptors pass every lint (syntax, required fields, leading-v, mirror URLs, name, filename) plus mcpp xpkg parse.
  • Three counterexamples each rejected with the exact spelling to write instead:
    • split form (ns="chriskohlhoff", name="asio")
    • non-atomic short (ns="mcpplibs", name="mcpplibs.capi.lua")
    • dotted name with no namespace (ns="", name="mcpplibs.capi.lua")
  • Both pre-normalization files are caught by Rule 3 when replayed through the new lint.
  • Neither renamed package is a workspace member, so no test-example churn.

Docs

docs/repository-and-schema.md gains a 包身份:(namespace, name) 的三条规则 section (rules + examples + why filenames are pinned even though they aren't identity), and the repo-layout / CI-behaviour / local-lint-reproduction sections are updated to match.

…mcpp 0.0.105

The index was already clean on identity: all 49 descriptors declare a
fully-qualified `name` and an atomic short segment, so mcpp#278's split
form appears nowhere here. What was NOT pinned was the layer below it —
where a descriptor lives — and that had let two real defects in.

Normalization (no identity/namespace/name value changes at all):

  * pkgs/c/capi.lua.lua deleted. It was a BYTE-IDENTICAL duplicate of
    pkgs/m/mcpplibs.capi.lua.lua — same md5, same identity
    (mcpplibs.capi, lua). Whichever the directory scan reached first won;
    edits to the other were dead code nobody would notice.
  * pkgs/t/tensorvia-cpu.lua -> pkgs/a/aimol.tensorvia-cpu.lua, the
    canonical path for identity (aimol, tensorvia-cpu). Off-canonical
    names still resolve, but only via a COMPAT filename fallback that
    mcpp schedules for removal in 1.0.0.

Lint now enforces all three identity rules mechanically:

  1. `name` == `<namespace>.<short>`  (existing check, kept)
  2. `short` is a SINGLE atomic segment — depth belongs in `namespace`.
     NEW. Both spellings of a nested package survive mcpp's normalizer
     because it splits the FQN on its LAST dot, so
     `namespace="mcpplibs", name="mcpplibs.capi.lua"` silently resolves
     to `(mcpplibs.capi, lua)` — a namespace the descriptor never
     declared. After this rule the declared and canonical namespace are
     always the same string.
  3. descriptor sits at the canonical path for its identity. NEW
     (tests/check_package_filename.lua) — this is the check that found
     both defects above.

Zero-namespace packages (imgui/ffmpeg/opencv) stay exactly as they are:
their bare `name` IS the FQN and that is a deliberate, legal form. Rule 2
still guards them — a dotted name with no declared namespace would
resolve into a namespace written down nowhere.

CI pinned to mcpp 0.0.105 (env.MCPP_VERSION + all three matrix entries),
where `mcpp xpkg parse` enforces rule 1 itself (INV-NAME, mcpp#278). The
lua lints therefore become an earlier, cheaper second gate rather than
the only one.

index.toml's min_mcpp/latest_mcpp deliberately stay at 0.0.102: the floor
is a CONSUMER contract, 0.0.105 carries a breaking change (bare names no
longer reach third-party namespaces), and nothing here needs 0.0.105
grammar — so there is no reason to force every consumer forward.

Verified locally against real mcpp 0.0.105: all 48 descriptors pass every
lint plus `mcpp xpkg parse`; the three counterexamples (split form,
non-atomic short, dotted-name-without-namespace) are each rejected with
the exact spelling to write instead.
@Sunrisepeak

Copy link
Copy Markdown
Member Author

Superseded. Its two concrete fixes landed upstream independently — the duplicate capi identity in #119, and chriskohlhoff.asio in #116. The lint/docs half was written against the 0.0.105 rule that package.name must be fully-qualified; mcpp 0.0.106 (SPEC-001) reverses that — the canonical form is the short name, with the FQN spelling kept as a compatible legacy form. Replacement PR follows once 0.0.106 ships.

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