feat: search 结果与 add 建议显示包的可用版本(默认最新 3 个,--all-versions 全量) - #488
Conversation
`mcpp search` 的命中行追加描述符 per-OS 版本表的并集:semver 降序、按键去重, 默认显示最新 3 个并以 ", ..." 标记截断,--all-versions 显示全部;描述符不可读 或未发布版本的包保持原两列输出——富化是尽力而为的展示,不是新的失败路径。 `mcpp add` 未命中时的跨命名空间建议从裸 FQN 升级为带版本: compat.eui-neo (0.5.6, 0.5.5, 0.5.3)。数据是白捡的:did-you-mean 扫描本就要 打开每个候选 .lua 读身份(mcpp-community#278),版本只是同一段文本的再一次遍历。build 失败 路径的同款提示同步升级,两条路径不说两套话。 实现: - manifest 新增 merge_xpkg_versions_desc:per-OS 键列表的并集视图。排序用 version_req 的 SemVer 解析;不可解析的键保留原文排在最后(mcpp-community#363 的教训: 任意的索引键无法从解析形态复原);等值异写("1.0"/"1.0.0")保持首见序。 - mcpp-community#278 的扫描由 scan_fqns_with_short_name 改为 scan_short_name_matches, 携带 fqn + versions;三条约束不变(只在已失败路径调用、结果只进错误文本/ 展示、空结果不是错误),版本列表受同一纪律约束——描述存在性,不做解析输入。 - cross_namespace_matches 更名 cross_namespace_suggestions 返回富记录; prepare.cppm 与 commands.cppm 两个调用点同步渲染。 - Fetcher 新增 versions_for_hit:search 命中的 ns:name → 描述符 → 版本并集; 无 ns 前缀或读不到描述符时返回空。 - search_packages 增加 --all-versions;cli 注册选项。 测试:merge 排序 8 例(含预发布/四段/不可解析键)、扫描携带版本 3 例、 versions_for_hit 3 例;e2e 162 断言 build 与 add 两侧建议都带版本 (acme.widget (1.0.0) / compat.gadget (2.0.0)),且被拒的 add 不写 manifest。 Closes mcpp-community#487 Refs mcpp-community#324
Carries wellwei's #487 work onto current main. The CHANGELOG entry moves into [Unreleased]; it was filed under a [2026.8.22.1] section that no longer exists. The version display is one function now. #488 grew two joins of the same list -- `ShortNameMatch::versions_label` and a file-local `join_versions` in index_management -- and only the first appended the `, ...` truncation marker. So `mcpp search` cut the list to three and said nothing about it, against a description that promises the marker and a package (mcpplibs:imgui) that has six. Both callers now render through `manifest::join_versions_desc`, with the count policy as one `kVersionsShown`, and a unit test pins the marker for the truncated and exact-fit cases -- neither was covered. `all_xpkg_versions_desc` replaces two copies of "read every OS table, then merge" that each spelled the platform axis as a literal `{"linux", "macosx", "windows"}`. The axis already exists once, as `platform::xpkg_platforms`; a fourth OS should not need a sweep for the call sites that knew three. `merge_xpkg_versions_desc` parses each key once beside the key instead of on every comparison -- the comparator runs O(n log n) times and the parse was its whole cost. The optional-adapting lambda goes with it: the comparator only ever used `operator bool` and `operator*`, which `std::expected` already provides. Ordering is unchanged, `stable_sort` included, so `1.0` and `1.0.0` still hold first-seen order. `search_packages`'s defaulted `allVersions` is dropped; its one caller passes the flag explicitly. Co-authored-by: wellwei <ywellwei@qq.com>
|
Reviewed and carried forward as #573, with a The design holds and went in as written: the scan #278 already pays for on a failed lookup is reused rather than a new index built, and both constraint comments are explicit that the version list is display-only and never a resolution input. One behavioural gap, and one consolidation:
The platform axis existed already.
Thanks — the reasoning in the constraint comments is what made this quick to review. |
…, and docs/21 (#565, #487) Two contributor PRs, each reviewed and amended, plus the docs chapter both of them needed and neither had a place for. `mcpp clean --stale` (#568, closes #565) removes the fingerprint directories under target/ that no recorded build still uses, so reclaiming disk no longer costs a full rebuild. "Current" is what target/.build_cache already records rather than a second authority; with no record the command refuses instead of guessing, and an unrecorded directory written within --older-than is kept. `mcpp search` and the `mcpp add` did-you-mean now show what a package publishes (#488, closes #487), merged across the descriptor's per-OS tables and sorted semver-descending. The scan is the one #278 already pays for on a failed lookup; its result reaches error text and display only, never resolution. Three defects were found in review and fixed here. `mcpp clean --older-than 3d` set neither --stale nor --dry-run, so it reached clean_project and deleted every triple and profile under target/ -- silently, and precisely the outcome --stale exists to avoid. `--older-than -1s`, a typo for `1s`, parsed to a negative window that keeps nothing, disabling the freshness guard without a word. And 609's closing assertion -- the one that catches clean --stale destroying live build state -- used GNU `stat -c` in a test that declares no capabilities, so on macOS BSD stat rejected it, the `| sort` swallowed the status for want of pipefail, and two empty strings compared equal while the test printed OK. `mcpp search` also truncated its version list to three without the `, ...` marker its own description promised, because the feature grew two joins of the same list and only one appended it. Both callers now render through a single manifest::join_versions_desc with one kVersionsShown, and a unit test pins the truncated and exact-fit cases; neither had been covered. Simplifications: clean_stale keeps one map<triple, set<fingerprint>> where it kept a set of pairs and a parallel set of triples; all_xpkg_versions_desc replaces two copies of "read every OS table, then merge" that each spelled the platform axis as a literal, when platform::xpkg_platforms already defines it once; and merge_xpkg_versions_desc parses each key once beside the key rather than on every comparison, ordering unchanged. docs/21 documents the commands whose name does not announce their situation -- search, why, index status, xpkg parse had no entry under docs/ at all. Every transcript in it is real output from this branch, and two claims were weakened after failing that check: cache list is not ordered by last use, and the cost of rebuilding a std BMI is the implementation's stated rationale, not a measurement. Closes #565. Closes #487. Supersedes #568 and #488. Co-authored-by: Cloud_Yun <yunfeng66645@gmail.com> Co-authored-by: wellwei <ywellwei@qq.com>
|
Merged as 090c016 — the squash carries |
Summary
Closes #487,补上 #324 遗留的「建议不带版本」半边。
mcpp search <keyword>:命中行追加该包描述符 per-OS 版本表的并集——semver 降序、按键去重,默认显示最新 3 个并以, ...标记截断;--all-versions显示全部。描述符不可读或未发布任何版本的包保持原两列输出,富化是尽力而为的展示,不是新的失败路径。mcpp add ns.name@ver未命中时:跨命名空间建议从裸 FQN 升级为带版本:数据是白捡的:did-you-mean 扫描本就要打开每个候选
.lua读身份(#278),版本只是同一段文本的再一次遍历。build 失败路径的同款提示同步升级,两条路径不说两套话。warn_unpublished_version的 warn-not-fail 策略不动。实现
manifest::merge_xpkg_versions_desc:per-OS 键列表的并集视图。排序用version_req的 SemVer 解析;不可解析的键保留原文排在最后(版本模型:精确键能表达上游的一切,范围表达不了 —— 且 lock 记的是范围本身 #363 的教训:任意的索引键无法从解析形态复原);等值异写(1.0/1.0.0)保持首见序。scan_fqns_with_short_name改为scan_short_name_matches,携带 fqn + versions。三条约束不变(只在已失败路径调用、结果只进错误文本/展示、空结果不是错误),版本列表受同一纪律约束——描述存在性,不做解析输入。cross_namespace_matches更名cross_namespace_suggestions返回富记录;prepare.cppm与commands.cppm两个调用点同步渲染。Fetcher::versions_for_hit:search 命中的ns:name→ 描述符 → 版本并集;无 ns 前缀或读不到描述符返回空。Test plan
versions_for_hit3 例)tests/e2e/162_bare_name_namespace_scope.sh扩展并全绿:build 路径断言acme.widget (1.0.0)、add 路径断言compat.gadget (2.0.0),且被拒的 add 不写 manifest12_add_command.sh、93_xpkg_parse.shmcpp search imgui [--all-versions]与mcpp add mcpplibs.eui-neo@1.0.0输出符合上述契约