From 78e785d3bf6add04beedefe859cc2ec7ef8b8bc9 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Thu, 9 Jul 2026 15:20:21 +0800 Subject: [PATCH 1/2] fix(config): don't inject official global xim index into project scope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Project-local mode (a project with a custom `[indices]`, e.g. a local path index) force-added the official `xim` index into the project's `.xlings.json` `index_repos` (ensure_project_index_dir), intending to make `xim:*` deps resolvable in project mode. But xlings scopes by which group a repo lands in: packages from project `index_repos` are `PackageScope::Project`. So every `xim` GLOBAL tool (cmake/glibc/gcc/make/binutils/…) resolved project-scoped and installed into the project store instead of the shared registry. That broke ELF loader resolution for build-dep tools — a build-dep `xim:cmake`'s interpreter was patched to an unmaterialized project-store glibc → `cannot execute`. Any compat package running a glibc-dynamic build-dep tool in install() (e.g. a source-built CMake OpenCV) failed under `mcpp test`, universally (fresh MCPP_HOME too). global IS the default: `xim` (and its dynamically-discovered sub-indexes) are xlings global-default indices. `xim:*` resolves at global scope via the global index_repos + the registry-local xim clone, and stays visible to the project via additive. Only user-declared local custom indices are project-scoped. Remove the xim injection and the project-data-dir xim exposure; not a hardcoded allowlist — just don't inject an index the user didn't declare. Verified: opencv workspace member closes (cmake now installs to the global registry, project store holds only the local package); mcpp self-test 30/30; mcpp-index full workspace green. Design + analysis: .agents/docs/2026-07-09-project-index-scope-global-infra-fix.md Bumps 0.0.86 → 0.0.87. Claude-Session: https://claude.ai/code/session_01Y3KE7MAE8yV7BG35eXy7FV --- ...09-project-index-scope-global-infra-fix.md | 93 +++++++++++++++++++ CHANGELOG.md | 20 ++++ mcpp.toml | 2 +- src/config.cppm | 50 ++++------ src/toolchain/fingerprint.cppm | 2 +- tests/unit/test_config.cpp | 27 +++++- 6 files changed, 156 insertions(+), 38 deletions(-) create mode 100644 .agents/docs/2026-07-09-project-index-scope-global-infra-fix.md diff --git a/.agents/docs/2026-07-09-project-index-scope-global-infra-fix.md b/.agents/docs/2026-07-09-project-index-scope-global-infra-fix.md new file mode 100644 index 00000000..42f82e9d --- /dev/null +++ b/.agents/docs/2026-07-09-project-index-scope-global-infra-fix.md @@ -0,0 +1,93 @@ +# 项目本地模式下的索引作用域:别把默认全局的官方索引(xim)注入项目组(架构分析 + 修复设计) + +**日期**: 2026-07-09 +**范围**: `src/config.cppm`(`ensure_project_index_dir`)、`src/pm/index_spec.cppm`、`src/build/prepare.cppm` +**性质**: mcpp 侧架构缺陷分析与修复设计。这是 OpenCV 收录时 `mcpp test` 沙箱里 `cmake` 不可执行故障的**唯一正解所在**。 +## 文档族与职责边界(三份配套,全部根治设计、无 workaround) + +| # | 仓库 / 文档 | 角色 | 与本故障的关系 | +|---|---|---|---| +| ① | mcpp-index `2026-07-09-mcpp-builddep-loader-store-split-rootcause.md` | 根因总报告(现象/实证/归责) | 先读,了解全貌 | +| ② | **本篇** mcpp `2026-07-09-project-index-scope-global-infra-fix.md` | **本故障的唯一必需修复(根治)** | 修 ② 即可让 OpenCV 闭环 | +| ③ | openxlings/xlings `2026-07-09-scope-consistency-installed-check-and-loader-resolution.md` | xlings 侧**独立**健壮性缺口(根治) | 不由本故障触发、与 ② 互不依赖 | + +**职责边界**:OpenCV/cmake 故障的**必需且唯一**修复是 ②(本篇)。③ 是一个**独立**的 additive loader 解析缺口(合法"项目消费者+全局 provider"场景),**不是本故障的必要条件**;两者可各自独立落地。**三份均采用根治设计,不提供也不采用任何 workaround。** + +--- + +## 0. 结论(TL;DR) + +- **缺陷**:mcpp 在项目本地模式下,把**官方全局基础设施索引 `xim`** 强注册为**项目作用域** index repo(`config.cppm:684-697`)。因 xlings 把"项目 index_repos 里的包"一律判 `PackageScope::Project`,导致 `xim` 的**全局工具**(cmake/glibc/gcc/make/binutils)被整体错误地"项目化"、装进项目 store —— 而它们本应装进全局 registry。由此引出 loader 不落项目 store、cmake interpreter 悬空、不可执行的连锁。 +- **根**:**xlings 的作用域默认就是全局** —— 一个 repo 只有落进"项目组"(项目 `.xlings.json` 的 `index_repos` / 项目 discovered sub-index)才是 Project,其余(全局 repos、全局发现的 sub-index)恒 Global(`catalog.cppm:175-224`)。`xim` 及其 sub-index 本在全局组 → 本应 Global。**是 mcpp 主动把 `xim` 塞进了项目组**(`config.cppm:684-697` 把官方 xim append 进项目 `customRepos`),把一个默认全局的索引挪成了项目作用域。 +- **多余**:xlings 原生就在全局解析 `xim`(全局 index_repos + registry 本地 clone `registry/data/xim-pkgindex/pkgs`),并经 additive 让项目可见。`xim:*` 本会 Global 解析 → 装 registry。mcpp 的注入不必要。 +- **修复原则(不硬编码)**:**global 是默认;mcpp 只把用户在 `mcpp.toml [indices]` 声明的项目本地索引放进项目组,绝不注入用户未声明的官方 `xim`。** 删掉这次注入即根治;xim 及其 sub-index 留在全局 → registry;cmake/glibc/gcc/make 同店 → interpreter 天然指 registry glibc → 可执行。**xlings 无需改动。** 不建 `is_global_infra` 白名单(违背"global 默认"、且漏 sub-index)。 + +--- + +## 1. mcpp 项目本地模式的架构(先厘清哪些是对的) + +- **触发**:工程 `mcpp.toml` 声明自定义 `[indices]`(如本地 path 索引)→ 进入项目本地模式(`make_project_xlings_env`,`config.cppm:100-105`;`prepare.cppm:1188` `useProjectEnv = idxSpec && !idxSpec->is_builtin()`)。 +- **目的(正当)**:让**用户自定义索引**的包**项目作用域隔离**(不污染全局、可复现)。这本身没问题。 +- **工具链走全局(正确)**:默认工具链 `gcc@16.1.0`(含 glibc)经 `make_xlings_env`(无 projectDir)装进 **registry**(`prepare.cppm:805-810`),global 作用域、共享。**对。** +- **一次调用挂双 store**:项目模式命令前缀同时设 `XLINGS_HOME=registry` + `XLINGS_PROJECT_DIR=/.mcpp`(`xlings.cppm:730-738`)。这本身也 OK —— xlings 支持 additive(project 叠加 global)。 + +→ 问题**不在**"用了项目本地模式",而在**把哪些索引归入了项目作用域**。 + +## 2. 缺陷:把全局基础设施索引 `xim` 归进了项目作用域 + +`ensure_project_index_dir`(`config.cppm:662-767`)做了两件事: + +1. **`config.cppm:684-697`(致命)**:把官方 `xim` 索引(`officialIndex = cfg.xlingsHome()/data/xim-pkgindex`)以名字 `xim` **append 进项目 `customRepos`**,随后 `seed_xlings_json`(`:707`)写进项目 `.mcpp/.xlings.json` 的 `index_repos`。 + - 后果:xlings `catalog` 把 `project_index_repos()` 里的包判 `PackageScope::Project` → `storeRoot=project_data_dir/xpkgs`。→ **凡从 `xim` 解析到的包(cmake/glibc/gcc/make/binutils)全部项目化、装项目 store。** +2. **`config.cppm:745-765`(冗余)**:把 `xim` 索引 symlink/copy 进项目 data dir(`/.mcpp/.xlings/data/xim-pkgindex`)。意图注释 `:745-748`:"让 `xim:python@latest` 之类能解析,免于回退到 remote 索引更新"。 + +**根(违背"global 默认")**:xlings 的作用域默认全局——只有落进"项目组"才是 Project(`catalog.cppm:175-224`)。`config.cppm:684-697` 这段是**无条件**把官方 `xim` 注入项目 `customRepos`(不经 `is_builtin` 判定、也不是用户声明),等于**主动把一个默认全局的索引搬进项目组**。`xim` 本是 xlings 全局默认索引(`config.cppm:556-561`),连同其动态 sub-index 都应留在全局——不该被注入项目。 + +**证据(实测)**:项目 `.mcpp/.xlings.json` 的 `index_repos = [compat(本地,对), xim(官方全局,被项目化)]`;项目 store 里出现 `xim-x-cmake/gcc/glibc/make/binutils`,而 fresh registry **无 cmake**(即 cmake 只被装进了项目)。 + +## 3. 为什么"强加"既多余又有害 + +- **多余**:xlings 原生就把 `xim` auto-add 进 **globalIndexRepos_**(`config.cppm:556-561`),catalog 同时扫 project+global 两套 repo,项目模式 additive over global。registry 里已有 `xim-pkgindex` 本地 clone。→ **`xim:cmake` 本会 Global 解析 → 装 registry → 对项目可见,无需 mcpp 再把 xim 加进项目 repos。** +- **有害**:一旦项目化,全局工具装进项目 store;其 loader dep glibc 又被工具链 bootstrap 装在 registry 并记录,项目安装时被"已装"复用跳过 → 项目 store 的 glibc 空 → elfpatch 把 cmake interpreter 指向空目录 → 悬空。**故障链的起点就是这次错误的作用域归属。** + +## 4. 修复设计 + +### 设计原则:**global 是默认,项目化是显式且仅限用户声明** +xlings 的作用域已由"repo 落在哪一组"决定(`catalog.cppm:175-224`):`project_index_repos()` → Project;`global_index_repos()` / discovered 全局 sub-index(`xim-indexrepos.json`)→ Global;discovered 项目 sub-index → Project。**即"不落进项目组的一切,默认全局"。** `xim` 及其 sub-index 本在全局组/全局发现 → 天然 Global。 + +因此**不建任何硬编码"全局基础设施"白名单**(既违背"global 默认",又漏掉动态发现的 sub-index)。正确原则只有一句: + +> **mcpp 只把"用户在 `mcpp.toml [indices]` 里声明的项目本地索引"放进项目组;绝不注入用户未声明的索引(尤其官方 `xim`)。** + +### 根治方案(单一设计;不含 workaround) +1. **删除 `config.cppm:684-697`**(`ensure_project_index_dir` 里把官方 `xim` append 进项目 `customRepos` 的整段)。→ mcpp 不再把 xim 从全局组搬进项目组;xim 及其 sub-index 留在全局 → Global → registry。 +2. **收敛 `config.cppm:745-765`**(项目 data dir 的 xim 副本暴露)——它是"项目化 xim"的配套产物,删注入后不再需要。 +3. **保留 `:672` 遍历中"用户声明的本地自定义索引 → 项目组"的逻辑**(这是项目本地隔离的正当用途,不动)。 +4. **全局侧保证 `xim:*` 本地可解析(回应原动机、免 remote)**:确保全局 `xim` 条目/发现指向 **registry 的本地 clone**(`registry/data/xim-pkgindex`),使 `xim:*` 以 Global 解析、装 registry、不触发 remote fetch。原 `:745-748` 的"避免 remote 索引更新"顾虑,在全局侧被正确满足。 + +落地后:`xim` 的全部工具(cmake/glibc/gcc/make/binutils)及其 sub-index → Global → registry(同一全局 store);项目模式经 xlings additive 天然可见并复用;工具链(§1 已正确 global)与它们同店 → interpreter 天然自洽。**完整根治,不依赖任何 xlings 改动,且对 sub-index 机制天然正确(mcpp 一概不碰全局发现的 sub-index)。** + +### ❌ 不要做(明确排除的 workaround) +- **不建 `is_global_infra` 硬编码白名单**:硬编码 `{mcpplibs,xim,awesome,scode,d2x}` 违背"global 默认",且漏掉 xim 动态 sub-index —— 正解是"别注入",而非"枚举谁是全局"。 +- **不做"删注入但仍以其它方式把 xim 拉进项目"**的变体。 +- **不在 xlings 侧迁就**:不"把 glibc 物化进项目 store",不"改 elfpatch 指项目空目录"——那是坐实错误作用域(见文档 ③ 反模式)。**正解在本仓:别把默认全局的索引搬进项目组。** + +## 5. 与 xlings 的关系(职责边界) +- 修好本缺陷后:cmake/glibc/gcc/make 全 Global → registry(同一全局 store)→ cmake interpreter 天然指 registry glibc(存在)→ 可执行。**xlings 的 additive 模型本就支持此,无需任何改动。** +- xlings 侧另有一个**相互独立**的健壮性缺口(合法"项目消费者 + 全局 loader-provider"时,elfpatch 的 provider 解析口径),记录在 xlings 仓文档里,**不是本故障的必要条件、也不由本修复触发**。 + +## 6. 验证与最小复现 +- **修前(现状)**:含自定义 `[indices]` 的工程 + compat 包声明 build-dep `xim:cmake` 并在 install() 执行它 → 任意机器(含 fresh `MCPP_HOME`)`mcpp test` → `cmake: cannot execute`(项目 store 的 xim-x-glibc 只有 `.xpkg.lua`)。现成:`mcpp-index` 仓 `tests/examples/opencv` + `pkgs/c/compat.opencv.lua`。 +- **修后预期**:项目 `.xlings.json` 的 `index_repos` 只含本地 `compat`;`xim-x-cmake/glibc/gcc/make` 出现在 **registry** 而非项目 store;`cmake` 可执行;`compat.opencv` 的 `mcpp test --workspace` 三平台闭环(descriptor 与测试工程零改动)。 +- **回归点**:确认移除项目 xim 后,`xim:*` 依赖仍能解析(靠 global auto-add + registry 本地 clone),且不触发 remote 索引 fetch。 + +## 7. 影响 +- **compat.opencv**:本修复是其闭环的前置;修好后 descriptor(已是零兼容代码的 `pkginfo.build_dep` 形式)与 `tests/examples/opencv` **零改动**即通过 `mcpp test --workspace`,可进 CI 选跑、开 PR。 +- **面向未来**:确立"**global 默认、只项目化用户声明的本地索引、绝不注入官方索引**"这一不变式,避免后续任何"全局工具被项目化"的复发;对 xim 动态 sub-index 天然正确(mcpp 不碰全局发现)。 + +## 8. 改动点清单(单一根治设计,不硬编码) +- `src/config.cppm:684-697` —— **删除**把官方 `xim` append 进项目 `customRepos` 的整段(不再把默认全局的索引注入项目组)。 +- `src/config.cppm:745-765` —— 收敛项目 data dir 的 xim 副本暴露(注入删除后不再需要);由全局 `xim` 指 registry 本地 clone 满足解析(免 remote fetch)。 +- `src/config.cppm:662-682`(`ensure_project_index_dir` 遍历)—— **保持不变**:仅项目化用户在 `[indices]` 声明的本地自定义索引(项目隔离的正当用途)。 +- **不改** `is_builtin()`,**不新增** `is_global_infra` 白名单(违背"global 默认"、漏 sub-index)。 +- e2e/工作区:`mcpp test --workspace` 覆盖"含全局 build-dep 工具的 compat 包"(opencv 即样例)+ 断言 xim 工具落在 registry 而非项目 store,防回归。 diff --git a/CHANGELOG.md b/CHANGELOG.md index ba1e55bd..e7dc1692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,26 @@ > 本文件追踪 `mcpp-community/mcpp` 公开仓的版本演进。 > 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)。 +## [0.0.87] — 2026-07-09 + +### 修复 + +- **项目本地模式:不再把官方全局索引 `xim` 注入项目作用域**。此前带自定义 + `[indices]`(本地 path 索引)的工程进入项目本地模式时,`ensure_project_index_dir` + 会无条件把官方 `xim` 索引 append 进项目 `.xlings.json` 的 `index_repos` + (`config.cppm`),意在让 `xim:*` 依赖在项目模式可解析。但 xlings 按"repo 落在 + 哪一组"决定作用域——项目 `index_repos` 里的包一律 `PackageScope::Project`,于是 + `xim` 的**全局工具**(cmake/glibc/gcc/make/binutils 等)整体被错误地"项目化"、 + 装进项目 store 而非共享 registry。由此 build-dep 工具(如 `xim:cmake`)的 ELF + interpreter 被指向项目 store 里未物化的 glibc → `cannot execute`,任何在 + `install()` 里执行 glibc-动态 build-dep 工具的 compat 包(如从源码 CMake 构建的 + OpenCV)在 `mcpp test` 下必现,且与宿主历史无关(fresh `MCPP_HOME` 亦复现)。 + **修复**:移除该注入及配套的项目 data dir `xim` 副本暴露。`xim`(及其动态发现的 + sub-index)是 xlings 全局默认索引,**global 即默认作用域**——`xim:*` 经全局 + index_repos + registry 本地 clone 正常解析、装 registry,并经 additive 对项目 + 可见;只有用户在 `[indices]` 声明的本地自定义索引才项目化。设计与分析见 + `.agents/docs/2026-07-09-project-index-scope-global-infra-fix.md`。 + ## [0.0.84] — 2026-07-08 ### 修复 diff --git a/mcpp.toml b/mcpp.toml index 7ac2de10..130318bd 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,6 +1,6 @@ [package] name = "mcpp" -version = "0.0.86" +version = "0.0.87" description = "Modern C++ build & package management tool" license = "Apache-2.0" authors = ["mcpp-community"] diff --git a/src/config.cppm b/src/config.cppm index e08713c2..ee7be2a9 100644 --- a/src/config.cppm +++ b/src/config.cppm @@ -681,20 +681,18 @@ bool ensure_project_index_dir( customRepos.emplace_back(name, spec.url); } - auto officialIndex = cfg.xlingsHome() / "data" / "xim-pkgindex"; + // NOTE: the official global `xim` index is deliberately NOT injected into + // the project's customRepos here. `xim` (and its dynamically-discovered + // sub-indexes) are xlings GLOBAL-default indices — global IS the default + // scope, and a repo is only project-scoped when it lands in the project's + // index_repos. Injecting `xim` as a project repo made every `xim:*` tool + // (cmake/glibc/gcc/make/…) resolve project-scoped and install into the + // project store instead of the shared registry, which broke ELF loader + // resolution for build-dep tools (cmake interpreter dangling). `xim:*` + // resolves fine at global scope via xlings' global index_repos + the + // registry-local clone, and stays visible to the project via additive. + // See .agents/docs/2026-07-09-project-index-scope-global-infra-fix.md. std::error_code ec; - if (!customRepos.empty() && std::filesystem::exists(officialIndex / "pkgs", ec)) { - bool hasXim = false; - for (auto const& [name, _] : customRepos) { - if (name == "xim") { - hasXim = true; - break; - } - } - if (!hasXim) { - customRepos.emplace_back("xim", officialIndex.generic_string()); - } - } if (customRepos.empty() && penv.empty()) return false; // nothing to do @@ -742,27 +740,11 @@ bool ensure_project_index_dir( exposeLocalIndex(name, source, dotMcpp / "data"); } - // Project-scoped xlings installs custom-index packages in an additive - // project data dir. Expose the global official xim index there too, so - // package deps like `xim:python@latest` can resolve without falling back - // to unrelated remote index updates or system tools. - if (std::filesystem::exists(officialIndex / "pkgs", ec)) { - auto projectData = dotMcpp / ".xlings" / "data"; - auto projectOfficial = projectData / "xim-pkgindex"; - std::filesystem::create_directories(projectData, ec); - if (!std::filesystem::exists(projectOfficial, ec)) { - std::filesystem::create_directory_symlink(officialIndex, projectOfficial, ec); - if (ec) { - ec.clear(); - std::filesystem::copy( - officialIndex, - projectOfficial, - std::filesystem::copy_options::recursive - | std::filesystem::copy_options::skip_existing, - ec); - } - } - } + // (removed) The official global `xim` index is no longer exposed/copied into + // the project data dir: it is not a project-scoped repo (see the note above), + // so `xim:*` resolves at GLOBAL scope via the registry-local xim clone, not + // from a project-local copy. Only genuinely user-declared local custom + // indices are exposed project-locally (the loop above). return true; } diff --git a/src/toolchain/fingerprint.cppm b/src/toolchain/fingerprint.cppm index 79362a67..7b30e0f8 100644 --- a/src/toolchain/fingerprint.cppm +++ b/src/toolchain/fingerprint.cppm @@ -18,7 +18,7 @@ import mcpp.toolchain.detect; export namespace mcpp::toolchain { -inline constexpr std::string_view MCPP_VERSION = "0.0.86"; +inline constexpr std::string_view MCPP_VERSION = "0.0.87"; struct FingerprintInputs { Toolchain toolchain; diff --git a/tests/unit/test_config.cpp b/tests/unit/test_config.cpp index a6a9ca7a..6e07cc26 100644 --- a/tests/unit/test_config.cpp +++ b/tests/unit/test_config.cpp @@ -1,4 +1,7 @@ #include +#include +#include +#include import std; import mcpp.config; @@ -85,7 +88,14 @@ TEST(Config, ProjectIndexJsonEscapesLocalIndexPath) { std::filesystem::remove_all(project); } -TEST(Config, ProjectIndexDirExposesOfficialXimIndex) { +// The official global `xim` index must NOT be injected/exposed into the project +// scope. `xim` (and its dynamic sub-indexes) are xlings GLOBAL-default indices — +// global IS the default scope; injecting xim as a project repo made every `xim:*` +// tool (cmake/glibc/gcc/make) resolve project-scoped and install into the project +// store instead of the shared registry, breaking ELF loader resolution for +// build-dep tools. `xim:*` resolves at global scope via the registry-local clone. +// See .agents/docs/2026-07-09-project-index-scope-global-infra-fix.md. +TEST(Config, ProjectIndexDirDoesNotInjectOfficialXimIndex) { auto project = make_tempdir("mcpp-config-project-xim-index"); auto registry = make_tempdir("mcpp-config-registry"); auto official = registry / "data" / "xim-pkgindex"; @@ -109,9 +119,22 @@ TEST(Config, ProjectIndexDirExposesOfficialXimIndex) { cfg.registryDir = registry; ASSERT_TRUE(mcpp::config::ensure_project_index_dir(cfg, project, indices)); + // xim is NOT copied/exposed into the project data dir (it stays global). auto projectOfficial = project / ".mcpp" / ".xlings" / "data" / "xim-pkgindex"; - EXPECT_TRUE(std::filesystem::exists(projectOfficial / "pkgs" / "p" / "python.lua")); + EXPECT_FALSE(std::filesystem::exists(projectOfficial / "pkgs" / "p" / "python.lua")); + + // The user-declared local `compat` index IS exposed project-locally. + auto projectLocal = project / ".mcpp" / ".xlings" / "data" / "compat"; + EXPECT_TRUE(std::filesystem::exists(projectLocal / "pkgs")); + + // The seeded project .xlings.json index_repos must not contain `xim`. + auto projJson = project / ".mcpp" / ".xlings.json"; + if (std::filesystem::exists(projJson)) { + std::ifstream is(projJson); + std::stringstream ss; ss << is.rdbuf(); + EXPECT_EQ(ss.str().find("\"xim\""), std::string::npos); + } std::filesystem::remove_all(project); std::filesystem::remove_all(registry); From a9781ba37a29b13fa9b062abfd0a79dbbd5250a2 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Thu, 9 Jul 2026 15:41:45 +0800 Subject: [PATCH 2/2] test(e2e): 52 asserts xim is NOT injected into project .xlings.json (matches fix) The fake-xlings in 52_local_path_namespaced_index.sh asserted the OLD behavior (project .xlings.json must contain the official xim index). Flip it: xim is a global-default index and must NOT be injected project-scoped. Verified: e2e 52 OK. Claude-Session: https://claude.ai/code/session_01Y3KE7MAE8yV7BG35eXy7FV --- tests/e2e/52_local_path_namespaced_index.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/e2e/52_local_path_namespaced_index.sh b/tests/e2e/52_local_path_namespaced_index.sh index a71c0520..f5a9a50f 100755 --- a/tests/e2e/52_local_path_namespaced_index.sh +++ b/tests/e2e/52_local_path_namespaced_index.sh @@ -134,8 +134,12 @@ if [[ "${1:-}" == "interface" && "${2:-}" == "install_packages" ]]; then fi shift done - if ! grep -q '"name": "xim"' "${XLINGS_PROJECT_DIR:?}/.xlings.json"; then - echo "missing official xim index in project .xlings.json" >&2 + # The official global `xim` index must NOT be injected into the project's + # .xlings.json — it's a global-default index (global IS the default scope); + # injecting it project-scoped mis-scopes every xim:* tool into the project + # store. Only user-declared local custom indices belong here. + if grep -q '"name": "xim"' "${XLINGS_PROJECT_DIR:?}/.xlings.json"; then + echo "official xim index must NOT be injected into project .xlings.json" >&2 cat "${XLINGS_PROJECT_DIR:?}/.xlings.json" >&2 2>/dev/null || true exit 24 fi