feat: add index-aware recipe resolution with repo support

- fetch_recipe_from_repos() iterates repos by priority, channels, with
  mirror fallback — caches indexes at /cache/indexes/

- Conditional HTTP downloads (curl -z) to only re-fetch stale indexes

- build_registry and fetch-package prefer repos { } over remotes = [...]
  when both are present

- Fallback chain: local .kap → repos (index-aware) → remotes (legacy)
This commit is contained in:
2026-08-04 13:50:29 -04:00
parent 4f1ce17ec8
commit 7b0538c392
3 changed files with 267 additions and 2 deletions
+28 -2
View File
@@ -132,7 +132,26 @@ static resolve::Registry build_registry(const dsl::SystemConfig& cfg) {
}
}
// If not found locally, try remotes
// If not found locally, try repos (index-aware) first, then legacy remotes
if (!found && !cfg.repos.empty()) {
auto result = fetch::fetch_recipe_from_repos(pref.name, cfg.repos);
if (result.ok && !result.path.empty()) {
std::ifstream in(result.path);
if (in) {
std::ostringstream buf;
buf << in.rdbuf();
try {
auto pkg = dsl::parse(buf.str());
registry[pkg.name] = std::move(pkg);
found = true;
} catch (const std::exception& e) {
std::cerr << "warning: parse error in remote recipe " << pref.name << ": " << e.what() << "\n";
} catch (...) {
std::cerr << "warning: unknown parse error in remote recipe " << pref.name << "\n";
}
}
}
}
if (!found && !cfg.remotes.empty()) {
auto result = fetch::fetch_recipe(pref.name, cfg.remotes);
if (result.ok && !result.path.empty()) {
@@ -308,19 +327,26 @@ int main(int argc, char* argv[]) {
}
try {
std::vector<std::string> remotes;
std::vector<dsl::RepoDef> repos;
auto config_path = std::filesystem::path(paths::system_dir()) / "config.kap";
if (std::filesystem::exists(config_path)) {
auto cfg_src = read_file(config_path.c_str());
try {
auto cfg = dsl::parse_system_config(cfg_src);
remotes = cfg.remotes;
repos = std::move(cfg.repos);
} catch (const std::exception& e) {
std::cerr << "warning: config parse error: " << e.what() << "\n";
} catch (...) {
std::cerr << "warning: unknown config parse error\n";
}
}
auto result = fetch::fetch_recipe(file_arg, remotes);
fetch::RecipeResult result;
if (!repos.empty()) {
result = fetch::fetch_recipe_from_repos(file_arg, repos);
} else {
result = fetch::fetch_recipe(file_arg, remotes);
}
if (result.ok) {
if (result.updated) {
std::cout << "fetched " << file_arg << " " << result.version