feat(xpkg): auto-stamp install_dir for wrapper packages#10
Merged
Sunrisepeak merged 1 commit intomainfrom May 2, 2026
Merged
Conversation
Wrapper packages (linux-headers, etc.) leave install_dir empty because the real payload lives elsewhere — subos sysroot via config(), or a sub-dependency. Without anything in install_dir, xlings's catalog probe (`is_directory && !is_empty`) flags them as not-installed on every dependent install, looping forever. Today this is worked-around per-package: linux-headers/glibc each remember to drop a manual stamp in their install hook. New wrapper packages still hit the bug until the author finds and reproduces the idiom. Move it to the framework: run_hook(Install) auto-writes `.xim-installed` (key=value INI: schema/name/version/platform) when: 1. The Install hook returned success (don't stamp failures), AND 2. install_dir is empty (don't stomp on hook-laid content). Existing packages that already write their own stamp continue to work unchanged: their hook populates install_dir first, the auto-stamp's `is_empty` check sees non-empty, no double-write. Format compatibility is irrelevant because the file is a marker — content isn't load-bearing for the catalog probe. This is the framework-side fix for the wrapper-package idempotency issue. Bug #1 surface (UI re-listing linux-headers on every `xlings install gcc`) is already worked around in xim-pkgindex via manual stamps; this PR makes the framework no longer require that workaround for new wrapper packages. Tests: 26/26 ExecutorTest pass (4 new auto-stamp cases): - WritesStampWhenInstallDirEmpty - SkipsWhenInstallDirNonEmpty - SkipsWhenInstallHookFailed - NotWrittenForNonInstallHooks Decision NOT to add a catalog xvm fallback (originally proposed): the install_dir non-empty check should remain the single source of truth. If a stamp goes missing for any reason (manual cleanup, fs corruption), we want the catalog to truthfully report "not installed" so xlings re-runs the install, regenerating the stamp. Adding xvm DB as a secondary signal would mask such bugs.
2 tasks
Sunrisepeak
added a commit
to openxlings/xlings
that referenced
this pull request
May 2, 2026
…#256) * feat(deps): bump mcpplibs-xpkg 0.0.34 → 0.0.35 (auto-stamp framework) Picks up libxpkg's auto-stamp executor framework: after a successful install hook returns and install_dir is non-empty, the executor writes a `.xim-installed` stamp file (INI key=value: schema, name, version, platform) into install_dir if the dir is empty. This unblocks thin delegator packages — those whose actual payload lives in a separately-installed dep (e.g. linux-headers wraps scode:linux-headers, fromsource:* aliases) — from xlings's "installed: yes/no" probe. Without a stamp, the probe checks install_dir for content; an empty install_dir reports "no" → every dependent install re-triggers the wrapper's install hook + config hook unnecessarily. No version bump in this PR (deferring 0.4.13 release until other in-flight work lands). The 0.0.35 → 0.4.x consumption path is just an internal xrepo dependency bump; existing xlings 0.4.12 binaries are unaffected. libxpkg PR: openxlings/libxpkg#10 (merged) libxpkg tag: v0.0.35 mcpplibs-index: mcpplibs/mcpplibs-index@20e7543 * fixup: bump 0.0.35 → 0.0.36 + add explicit apply_install_stamp_if_empty call PR #256's first push (0.0.35) regressed E2E-02 because libxpkg's auto-stamp ran inside run_hook, writing .xim-installed before xlings's stage_extracted_payload_ fallback could probe "is install_dir empty?". patchelf's tarball has no top-level dir, so its install hook silently no-ops; without the fallback, install_dir ended up containing only the stamp file → "patchelf binary not found after self install". libxpkg PR #12 / v0.0.36 moved auto-stamp into a separate apply_install_stamp_if_empty(ctx) method that consumers call after their full install pipeline. This commit: 1. Bumps add_requires 0.0.35 → 0.0.36 (carries the API split) 2. Adds the explicit apply_install_stamp_if_empty call in installer.cppm right after stage_extracted_payload_ + normalize_file_install_, so: hook → stage extracted payload → normalize → stamp The stamp now sees the FINAL install_dir state and only fires for genuinely-empty wrapper packages (linux-headers etc.). Local E2E verified: `xlings self install` populates xim-x-patchelf/0.18.0/bin/patchelf correctly. libxpkg PR: openxlings/libxpkg#12 (merged, v0.0.36)
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
Make wrapper-package idempotency a framework concern instead of a per-package idiom. After the Install hook returns success and
install_diris empty, auto-write a.xim-installedmarker so xlings's catalog probe (is_directory && !is_empty) doesn't keep flagging the package as not-installed and re-triggering the hook on every dependent install.Context
xim-pkgindex's
linux-headers.luaandglibc.luaalready work around this in their install hooks by writing the marker manually:That's good for known wrapper packages but every new wrapper-shape package hits the bug until the author finds and reproduces the idiom. Move it to the framework once.
Stamp file
Format: key=value INI. Grep / cat / read all friendly.
schema = 1reserves room to add fields later.Behavior contract
.xim-installedCompatibility with existing manual stamps
Existing wrapper packages (linux-headers / glibc) that already write their own stamp continue to work. Their install hook populates install_dir first; the auto-stamp's
is_emptygate sees non-empty, so no double-write or format conflict.Stamp file format differs (manual = single-line version string; auto = key=value INI) but the file is a marker — content isn't load-bearing for the catalog probe. Future tooling that wants to parse it should handle both formats.
Decision NOT made: catalog xvm fallback
Originally proposed adding a "catalog falls back to
xvm::has_versionwhen install_dir is empty" as a belt-and-suspenders. Rejected on review:Self-healing via re-install > silent fallback.
Test plan
ExecutorTest: 26/26 pass (4 new auto-stamp cases):
AutoStamp_WritesStampWhenInstallDirEmpty— wrapper case, stamp content fields verifiedAutoStamp_SkipsWhenInstallDirNonEmpty— hook populated install_dir → no double-writeAutoStamp_SkipsWhenInstallHookFailed— failures don't leave a stampAutoStamp_NotWrittenForNonInstallHooks— Config/Uninstall hooks don't triggerLoaderTest 11/11, ModelTest 5/5, IndexTest 18/18 also still pass.
Cross-repo follow-up
After merge + v0.0.34 tag + mcpplibs-index 0.0.34 entry: a separate xlings PR will bump
add_requires("mcpplibs-xpkg 0.0.33")→"0.0.34". xlings has zero code changes — sameexecutor.run_hook(HookType::Install, ctx)call point now picks up the new auto-stamp behavior transparently.