From 6e280becbee47cb3554fcd192285a3d65a774527 Mon Sep 17 00:00:00 2001 From: Amadey Vorontsov Date: Sun, 10 May 2026 15:49:44 +0000 Subject: [PATCH] [M5+] cargoxx add evicts stale auto-discovered overlay rows --- src/cli/cmd_add.cpp | 14 ++++++++++++++ src/linkdb/linkdb.cppm | 13 +++++++++++++ src/linkdb/overlay.cpp | 30 ++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/src/cli/cmd_add.cpp b/src/cli/cmd_add.cpp index 80bbf60..98a8da2 100644 --- a/src/cli/cmd_add.cpp +++ b/src/cli/cmd_add.cpp @@ -139,6 +139,20 @@ auto cmd_add(const fs::path& project_root, const std::string& name, const auto effective_overlay = overlay_path.value_or(linkdb::default_overlay_path()); + // Drop any auto-discovered overlay rows for this package before + // resolving — they may have been written by an older cargoxx whose + // scanner produced a different recipe (e.g. picked the wrong + // CMake config in a multi-config tree). Manual recipes survive. + { + auto db = linkdb::Database::open(effective_overlay); + if (!db) { + return std::unexpected(db.error()); + } + if (auto r = db->evict_auto_recipes(name); !r) { + return std::unexpected(r.error()); + } + } + auto known = recipe_already_known(name, effective_version, components, effective_overlay); if (!known) { diff --git a/src/linkdb/linkdb.cppm b/src/linkdb/linkdb.cppm index 7f50555..2e6687c 100644 --- a/src/linkdb/linkdb.cppm +++ b/src/linkdb/linkdb.cppm @@ -104,6 +104,13 @@ auto overlay_set_libcxx_override(OverlayState& state, const std::string& package const std::string& source, bool value) -> cargoxx::util::Result; +// Drops every overlay row for `package` whose source is not "manual". +// Used by `cargoxx add` to invalidate stale auto-discovered recipes +// when the resolver/scanner logic has changed under the user — they +// should never have to know `~/.cache/cargoxx/linkdb.sqlite` exists. +auto overlay_evict_auto(OverlayState& state, const std::string& package) + -> cargoxx::util::Result; + auto overlay_query(OverlayState& state, const std::string& package) -> cargoxx::util::Result>; @@ -144,6 +151,12 @@ class Database { const std::string& source, bool value) -> util::Result; + // Evict every non-manual overlay row for `package`. Called by + // `cargoxx add` so users never have to manually drop stale + // auto-discovered recipes when cargoxx's resolver/scanner logic + // changes. + auto evict_auto_recipes(const std::string& package) -> util::Result; + private: Database() = default; std::map> curated_; diff --git a/src/linkdb/overlay.cpp b/src/linkdb/overlay.cpp index 3d17338..e50732b 100644 --- a/src/linkdb/overlay.cpp +++ b/src/linkdb/overlay.cpp @@ -241,6 +241,28 @@ auto overlay_delete_recipe(OverlayState& state, const std::string& package, return {}; } +auto overlay_evict_auto(OverlayState& state, const std::string& package) + -> util::Result { + // `manual` rows are user-curated via `cargoxx linkdb add`; everything + // else (`nix-probe`, `conan`, `vcpkg`, …) was synthesized by the + // resolver from the current cargoxx logic and is safe to drop — + // the next add will re-discover with the latest scanner. + constexpr const char* SQL = + "DELETE FROM recipes WHERE package = ? AND source != 'manual'"; + sqlite3* db = state.handle(); + sqlite3_stmt* stmt = nullptr; + if (sqlite3_prepare_v2(db, SQL, -1, &stmt, nullptr) != SQLITE_OK) { + return std::unexpected(sqlite_error(db, "prepare evict")); + } + sqlite3_bind_text(stmt, 1, package.c_str(), -1, SQLITE_TRANSIENT); + auto rc = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if (rc != SQLITE_DONE) { + return std::unexpected(sqlite_error(db, "step evict")); + } + return {}; +} + auto overlay_query(OverlayState& state, const std::string& package) -> util::Result> { constexpr const char* SQL = @@ -380,6 +402,14 @@ auto Database::abort_provisional(const std::string& package, return detail::overlay_delete_recipe(*overlay_, package, version_range, source); } +auto Database::evict_auto_recipes(const std::string& package) + -> util::Result { + if (auto ok = require_overlay(overlay_); !ok) { + return std::unexpected(ok.error()); + } + return detail::overlay_evict_auto(*overlay_, package); +} + auto Database::set_libcxx_override(const std::string& package, const std::string& version_range, const std::string& source, bool value)