Skip to content

Commit cb66a0e

Browse files
committed
fix: namespace-aware dependency lookup + bump to 0.0.10
The dependency pipeline (read_xpkg_lua, install_path, resolve_semver, try_merge_semver) previously used raw package-name strings and inferred namespace from filename/directory patterns via ad-hoc fallback logic. This meant the caller's declared namespace was never propagated — a dep declared under [dependencies] (default "mcpp" namespace) could silently resolve to a "compat" package through filename guessing. Fix: add namespace-aware overloads that accept structured (ns, shortName) as the primary API surface. All call sites in cli.cppm and resolver.cppm now pass DependencySpec.namespace_ and DependencySpec.shortName through the entire pipeline. Compat changes (compat.cppm): - xpkg_lua_candidates(ns, shortName): generates candidate filenames with canonical form first, fallback forms annotated for removal in 1.0.0 - install_dir_candidates(ns, shortName, indexName): same for install dirs Legacy string-based overloads are preserved as thin wrappers that infer namespace via resolve_package_name() — marked COMPAT, remove in 1.0.0. Also bumps version to 0.0.10 (not released yet).
1 parent cbc7b4f commit cb66a0e

6 files changed

Lines changed: 235 additions & 103 deletions

File tree

mcpp.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mcpp"
3-
version = "0.0.9"
3+
version = "0.0.10"
44
description = "Modern C++ build & package management tool"
55
license = "Apache-2.0"
66
authors = ["mcpp-community"]

src/cli.cppm

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,7 +1088,10 @@ prepare_build(bool print_fingerprint,
10881088
auto cfg = get_cfg();
10891089
if (!cfg) return std::unexpected(cfg.error());
10901090
mcpp::fetcher::Fetcher fetcher(**cfg);
1091-
auto resolved = mcpp::pm::resolve_semver(depName, s.version, fetcher);
1091+
// 0.0.10+: use structured namespace from DependencySpec.
1092+
auto resolved = mcpp::pm::resolve_semver(
1093+
s.namespace_, s.shortName.empty() ? depName : s.shortName,
1094+
s.version, fetcher);
10921095
if (!resolved) return std::unexpected(resolved.error());
10931096
mcpp::ui::info("Resolved",
10941097
std::format("{} {} → v{}", depName, s.version, *resolved));
@@ -1101,17 +1104,24 @@ prepare_build(bool print_fingerprint,
11011104
// different version is needed. Returns the dep's effective root (where
11021105
// mcpp.toml lives) and a fully loaded manifest.
11031106
using LoadedDep = std::pair<std::filesystem::path, mcpp::manifest::Manifest>;
1107+
// 0.0.10+: loadVersionDep accepts structured (ns, shortName) for
1108+
// namespace-aware lookup. depName is the map key (qualified or bare),
1109+
// kept for install() target formatting and error messages.
11041110
auto loadVersionDep = [&](const std::string& depName,
1111+
const std::string& ns,
1112+
const std::string& shortName,
11051113
const std::string& version)
11061114
-> std::expected<LoadedDep, std::string>
11071115
{
11081116
auto cfg = get_cfg();
11091117
if (!cfg) return std::unexpected(cfg.error());
11101118
mcpp::fetcher::Fetcher fetcher(**cfg);
11111119

1112-
auto installed = fetcher.install_path(depName, version);
1120+
auto installed = fetcher.install_path(ns, shortName, version);
11131121
if (!installed) {
11141122
mcpp::ui::info("Downloading", std::format("{} v{}", depName, version));
1123+
// install() target uses the map key (depName) which xlings
1124+
// knows how to resolve via its own index lookup.
11151125
std::vector<std::string> targets{ std::format("{}@{}", depName, version) };
11161126
CliInstallProgress progress;
11171127
auto r = fetcher.install(targets, &progress);
@@ -1123,13 +1133,13 @@ prepare_build(bool print_fingerprint,
11231133
if (r->error) err += ": " + r->error->message;
11241134
return std::unexpected(err);
11251135
}
1126-
installed = fetcher.install_path(depName, version);
1136+
installed = fetcher.install_path(ns, shortName, version);
11271137
if (!installed) return std::unexpected(std::format(
11281138
"package '{}@{}' install path missing after fetch", depName, version));
11291139
}
11301140
std::filesystem::path verRoot = *installed;
11311141

1132-
auto luaContent = fetcher.read_xpkg_lua(depName);
1142+
auto luaContent = fetcher.read_xpkg_lua(ns, shortName);
11331143
if (!luaContent) return std::unexpected(std::format(
11341144
"dependency '{}': index entry not found in local clone", depName));
11351145
auto field = mcpp::manifest::extract_mcpp_field(*luaContent);
@@ -1361,7 +1371,7 @@ prepare_build(bool print_fingerprint,
13611371
mcpp::fetcher::Fetcher fetcher(**cfg);
13621372

13631373
auto merged = mcpp::pm::try_merge_semver(
1364-
name,
1374+
key.ns, key.shortName,
13651375
it->second.constraint,
13661376
item.originalConstraint,
13671377
fetcher);
@@ -1397,7 +1407,7 @@ prepare_build(bool print_fingerprint,
13971407
merged.error()));
13981408
}
13991409

1400-
auto loaded = loadVersionDep(name, spec.version);
1410+
auto loaded = loadVersionDep(name, key.ns, key.shortName, spec.version);
14011411
if (!loaded) return std::unexpected(loaded.error());
14021412
auto& [secondaryRoot, secondaryManifest] = *loaded;
14031413

@@ -1511,7 +1521,7 @@ prepare_build(bool print_fingerprint,
15111521
std::format("{}{}{} {} ⨯ {} → v{}",
15121522
key.ns, key.ns.empty() ? "" : ".", key.shortName,
15131523
it->second.version, spec.version, *merged));
1514-
auto reloaded = loadVersionDep(name, *merged);
1524+
auto reloaded = loadVersionDep(name, key.ns, key.shortName, *merged);
15151525
if (!reloaded) return std::unexpected(reloaded.error());
15161526
auto& [newRoot, newManifest] = *reloaded;
15171527

@@ -1649,7 +1659,7 @@ prepare_build(bool print_fingerprint,
16491659
}
16501660
dep_manifest = std::move(*dm);
16511661
} else {
1652-
auto loaded = loadVersionDep(name, spec.version);
1662+
auto loaded = loadVersionDep(name, key.ns, key.shortName, spec.version);
16531663
if (!loaded) return std::unexpected(loaded.error());
16541664
dep_root = std::move(loaded->first);
16551665
dep_manifest = std::move(loaded->second);

src/pm/compat.cppm

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,92 @@ inline std::string xpkg_dir_name(std::string_view indexName,
103103
return std::format("{}-x-{}", indexName, qname);
104104
}
105105

106+
// ─── xpkg .lua filename candidates (namespace-aware) ────────────────
107+
//
108+
// Given a structured (namespace, shortName), return the list of candidate
109+
// filenames to search for in the index's pkgs/<letter>/ directories.
110+
//
111+
// The FIRST candidate is the canonical form; subsequent candidates are
112+
// backward-compatibility fallbacks.
113+
//
114+
// DEPRECATION SCHEDULE (fallback candidates):
115+
// Fallback candidates are slated for removal in mcpp 1.0.0.
116+
// Package indices should use the canonical filename form by then.
117+
118+
inline std::vector<std::string> xpkg_lua_candidates(std::string_view ns,
119+
std::string_view shortName)
120+
{
121+
std::vector<std::string> candidates;
122+
auto qname = qualified_name(ns, shortName);
123+
124+
// Canonical: <ns>.<shortName>.lua (e.g. "compat.mbedtls.lua",
125+
// "mcpplibs.cmdline.lua") — namespace is part of the filename.
126+
// For default namespace ("mcpp"), canonical is just "<shortName>.lua".
127+
if (ns.empty() || ns == mcpp::pm::kDefaultNamespace) {
128+
candidates.push_back(std::string(shortName) + ".lua");
129+
} else {
130+
candidates.push_back(qname + ".lua");
131+
}
132+
133+
// ── Fallback candidates (COMPAT, remove in 1.0.0) ──────────────
134+
135+
// Fallback 1: bare short name — covers mcpplibs packages whose
136+
// index files are named "<shortName>.lua" without namespace prefix.
137+
if (!ns.empty() && ns != mcpp::pm::kDefaultNamespace) {
138+
candidates.push_back(std::string(shortName) + ".lua");
139+
}
140+
141+
// Fallback 2: compat.<shortName>.lua — covers compat packages
142+
// when the caller didn't specify the "compat" namespace.
143+
if (ns.empty() || ns == mcpp::pm::kDefaultNamespace) {
144+
candidates.push_back("compat." + std::string(shortName) + ".lua");
145+
}
146+
147+
// Fallback 3: compat.<qname>.lua — covers edge cases where the
148+
// qualified name itself is used with a compat prefix.
149+
if (!ns.empty() && ns != mcpp::pm::kDefaultNamespace && ns != "compat") {
150+
candidates.push_back("compat." + qname + ".lua");
151+
candidates.push_back("compat." + std::string(shortName) + ".lua");
152+
}
153+
154+
return candidates;
155+
}
156+
157+
// ─── install_path directory candidates (namespace-aware) ─────────────
158+
//
159+
// Given a structured (namespace, shortName) and index name, return the
160+
// list of candidate directory names under <xpkgs>/ to search for.
161+
//
162+
// DEPRECATION SCHEDULE (fallback candidates):
163+
// Fallback candidates are slated for removal in mcpp 1.0.0.
164+
// By then xlings should use a consistent directory layout.
165+
166+
inline std::vector<std::string> install_dir_candidates(std::string_view ns,
167+
std::string_view shortName,
168+
std::string_view indexName)
169+
{
170+
std::vector<std::string> candidates;
171+
auto qname = qualified_name(ns, shortName);
172+
173+
// Canonical: <index>-x-<ns>.<shortName> (e.g. "mcpp-index-x-compat.mbedtls")
174+
// For default namespace: <index>-x-<shortName> (e.g. "mcpp-index-x-gtest")
175+
candidates.push_back(std::format("{}-x-{}", indexName, qname));
176+
177+
// ── Fallback candidates (COMPAT, remove in 1.0.0) ──────────────
178+
179+
// Fallback 1: namespace-prefixed dir without index
180+
// e.g. "compat-x-mbedtls" (new-style ns-aware layout)
181+
if (!ns.empty() && ns != mcpp::pm::kDefaultNamespace) {
182+
candidates.push_back(std::format("{}-x-{}", ns, shortName));
183+
}
184+
185+
// Fallback 2: index-prefixed with bare short name
186+
// e.g. "mcpp-index-x-mbedtls" (old pre-namespace layout)
187+
if (!ns.empty() && ns != mcpp::pm::kDefaultNamespace) {
188+
candidates.push_back(std::format("{}-x-{}", indexName, shortName));
189+
}
190+
191+
return candidates;
192+
}
193+
106194
} // namespace mcpp::pm::compat

0 commit comments

Comments
 (0)