@@ -38,6 +38,18 @@ struct IndexRepo {
3838 std::string url;
3939};
4040
41+ // Canonical mcpplibs index coordinates. The index repository moved from the
42+ // mcpp-community org to the mcpplibs org (#267) — the legacy URL only works
43+ // through GitHub's repo redirect, which breaks silently if the old name is
44+ // ever re-taken. The artifact base is the release mirror consumed by
45+ // xlings >= 0.4.68 per-repo artifact sync (#269); older xlings ignores it.
46+ inline constexpr std::string_view kMcpplibsIndexUrl =
47+ " https://github.com/mcpplibs/mcpp-index.git" ;
48+ inline constexpr std::string_view kMcpplibsIndexUrlLegacy =
49+ " https://github.com/mcpp-community/mcpp-index.git" ;
50+ inline constexpr std::string_view kMcpplibsIndexArtifact =
51+ " https://github.com/xlings-res/mcpp-index" ;
52+
4153struct GlobalConfig {
4254 // Resolved paths
4355 std::filesystem::path mcppHome; // ~/.mcpp/
@@ -251,6 +263,12 @@ std::expected<GlobalConfig, ConfigError> load_or_init(
251263// Pretty-print resolved config for `mcpp env` command.
252264void print_env (const GlobalConfig& cfg);
253265
266+ // Normalize legacy index naming in a loaded config (exported for tests):
267+ // org migration mcpp-community/mcpp-index -> mcpplibs/mcpp-index, index name
268+ // mcpp-index -> mcpplibs, then name+url dedup. Order matters: URL first, so
269+ // old-config name entries still match and legacy/default entries fold.
270+ void canonicalize_legacy_index_names (GlobalConfig& cfg);
271+
254272// M5.5: persist [toolchain].default to config.toml.
255273std::expected<void , ConfigError>
256274write_default_toolchain (const GlobalConfig& cfg, std::string_view spec);
@@ -357,7 +375,7 @@ home = ""
357375default = "mcpplibs"
358376
359377[index.repos."mcpplibs"]
360- url = "https://github.com/mcpp-community /mcpp-index.git"
378+ url = "https://github.com/mcpplibs /mcpp-index.git"
361379# xlings auto-adds xim / awesome / scode / d2x as defaults.
362380
363381[cache]
@@ -396,25 +414,8 @@ bool write_default_xlings_json(const std::filesystem::path& path,
396414}
397415
398416// Migration helpers delegated to mcpp.fallback.config_migration.
399-
400- void canonicalize_legacy_index_names (GlobalConfig& cfg) {
401- if (cfg.defaultIndex == " mcpp-index" )
402- cfg.defaultIndex = " mcpplibs" ;
403-
404- std::vector<IndexRepo> normalized;
405- for (auto r : cfg.indexRepos ) {
406- if (r.name == " mcpp-index"
407- && r.url == " https://github.com/mcpp-community/mcpp-index.git" ) {
408- r.name = " mcpplibs" ;
409- }
410- bool duplicate = std::any_of (normalized.begin (), normalized.end (),
411- [&](const IndexRepo& existing) {
412- return existing.name == r.name && existing.url == r.url ;
413- });
414- if (!duplicate) normalized.push_back (std::move (r));
415- }
416- cfg.indexRepos = std::move (normalized);
417- }
417+ // canonicalize_legacy_index_names is exported (declared above, defined after
418+ // this helper namespace) so its ordering rules stay under unit test.
418419
419420// Xlings binary acquisition delegated to mcpp.fallback.xlings_binary.
420421
@@ -454,6 +455,29 @@ void ensure_sandbox_patchelf(const GlobalConfig& cfg, bool quiet,
454455
455456} // namespace
456457
458+ void canonicalize_legacy_index_names (GlobalConfig& cfg) {
459+ if (cfg.defaultIndex == " mcpp-index" )
460+ cfg.defaultIndex = " mcpplibs" ;
461+
462+ std::vector<IndexRepo> normalized;
463+ for (auto r : cfg.indexRepos ) {
464+ // ① Org migration first — later steps (name match, dedup) key on the
465+ // canonical URL, so legacy entries fold instead of surviving as dupes.
466+ if (r.url == kMcpplibsIndexUrlLegacy )
467+ r.url = std::string (kMcpplibsIndexUrl );
468+ // ② Legacy index name. The URL condition keeps a user's unrelated
469+ // repo that happens to be named "mcpp-index" untouched.
470+ if (r.name == " mcpp-index" && r.url == kMcpplibsIndexUrl )
471+ r.name = " mcpplibs" ;
472+ bool duplicate = std::any_of (normalized.begin (), normalized.end (),
473+ [&](const IndexRepo& existing) {
474+ return existing.name == r.name && existing.url == r.url ;
475+ });
476+ if (!duplicate) normalized.push_back (std::move (r));
477+ }
478+ cfg.indexRepos = std::move (normalized);
479+ }
480+
457481std::expected<GlobalConfig, ConfigError> load_or_init (
458482 bool quiet,
459483 BootstrapProgressCallback onBootstrapProgress,
@@ -572,7 +596,7 @@ std::expected<GlobalConfig, ConfigError> load_or_init(
572596 for (auto & r : cfg.indexRepos ) if (r.name == name) return ;
573597 cfg.indexRepos .push_back ({ std::string (name), std::string (url) });
574598 };
575- add_default (" mcpplibs" , " https://github.com/mcpp-community/mcpp-index.git " );
599+ add_default (" mcpplibs" , kMcpplibsIndexUrl );
576600 canonicalize_legacy_index_names (cfg);
577601
578602 // 5. Seed registry/.xlings.json if missing; migrate legacy cached
0 commit comments