[M5+] verify_link retries with libc++ stdenv override on link failure

This commit is contained in:
2026-05-10 15:16:47 +00:00
parent 5e691ac37b
commit 3c77431658
5 changed files with 161 additions and 14 deletions

View File

@@ -90,6 +90,25 @@ auto overlay_open(const std::filesystem::path& path)
});
}
// Add the libcxx-override column to legacy overlay files. SQLite's
// ADD COLUMN errors when the column already exists; treat that as
// success (the column is present, which is all we need).
constexpr const char* MIGRATE =
"ALTER TABLE recipes ADD COLUMN requires_libcxx_override INTEGER NOT NULL DEFAULT 0";
char* mig_err = nullptr;
if (sqlite3_exec(state->handle(), MIGRATE, nullptr, nullptr, &mig_err) != SQLITE_OK) {
if (mig_err && std::string_view{mig_err}.find("duplicate column") ==
std::string_view::npos) {
std::string msg = std::format("cannot migrate overlay schema: {}",
mig_err ? mig_err : "?");
sqlite3_free(mig_err);
return std::unexpected(util::Error{
util::ErrorCode::LinkdbCorrupt, std::move(msg), "", path, std::nullopt,
});
}
sqlite3_free(mig_err);
}
return state;
}
@@ -99,8 +118,8 @@ auto overlay_insert_manual(OverlayState& state, const std::string& package,
constexpr const char* SQL =
"INSERT OR REPLACE INTO recipes "
"(package, version_range, nixpkgs_attr, find_package, targets, components, source, "
" verified_at) "
"VALUES (?, ?, ?, ?, ?, NULL, 'manual', ?)";
" verified_at, requires_libcxx_override) "
"VALUES (?, ?, ?, ?, ?, NULL, 'manual', ?, ?)";
sqlite3* db = state.handle();
sqlite3_stmt* stmt = nullptr;
@@ -119,6 +138,7 @@ auto overlay_insert_manual(OverlayState& state, const std::string& package,
sqlite3_bind_text(stmt, 4, r.find_package.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, targets_str.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int64(stmt, 6, now);
sqlite3_bind_int(stmt, 7, r.requires_libcxx_override ? 1 : 0);
auto rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
@@ -137,8 +157,8 @@ auto overlay_insert(OverlayState& state, const std::string& package,
constexpr const char* SQL =
"INSERT OR REPLACE INTO recipes "
"(package, version_range, nixpkgs_attr, find_package, targets, components, source, "
" verified_at) "
"VALUES (?, ?, ?, ?, ?, NULL, ?, ?)";
" verified_at, requires_libcxx_override) "
"VALUES (?, ?, ?, ?, ?, NULL, ?, ?, ?)";
sqlite3* db = state.handle();
sqlite3_stmt* stmt = nullptr;
@@ -155,6 +175,7 @@ auto overlay_insert(OverlayState& state, const std::string& package,
sqlite3_bind_text(stmt, 5, targets_str.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, source.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int64(stmt, 7, verified_at);
sqlite3_bind_int(stmt, 8, r.requires_libcxx_override ? 1 : 0);
auto rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
@@ -223,7 +244,8 @@ auto overlay_delete_recipe(OverlayState& state, const std::string& package,
auto overlay_query(OverlayState& state, const std::string& package)
-> util::Result<std::vector<OverlayRow>> {
constexpr const char* SQL =
"SELECT version_range, nixpkgs_attr, find_package, targets, source, verified_at "
"SELECT version_range, nixpkgs_attr, find_package, targets, source, verified_at, "
" requires_libcxx_override "
"FROM recipes WHERE package = ?";
sqlite3* db = state.handle();
@@ -254,6 +276,7 @@ auto overlay_query(OverlayState& state, const std::string& package)
}
row.source = column_text(stmt, 4);
row.verified_at = sqlite3_column_int64(stmt, 5);
row.requires_libcxx_override = sqlite3_column_int(stmt, 6) != 0;
out.push_back(std::move(row));
}
sqlite3_finalize(stmt);
@@ -278,6 +301,30 @@ auto overlay_is_fresh(const OverlayRow& row, std::int64_t now) -> bool {
return (now - row.verified_at) < THIRTY_DAYS_SECONDS;
}
auto overlay_set_libcxx_override(OverlayState& state, const std::string& package,
const std::string& version_range,
const std::string& source, bool value)
-> util::Result<void> {
constexpr const char* SQL =
"UPDATE recipes SET requires_libcxx_override = ? "
"WHERE package = ? AND version_range = ? AND source = ?";
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 update libcxx_override"));
}
sqlite3_bind_int(stmt, 1, value ? 1 : 0);
sqlite3_bind_text(stmt, 2, package.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, version_range.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, source.c_str(), -1, SQLITE_TRANSIENT);
auto rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
if (rc != SQLITE_DONE) {
return std::unexpected(sqlite_error(db, "step update libcxx_override"));
}
return {};
}
} // namespace detail
auto Database::add_manual(const std::string& package, const std::string& version_range,
@@ -333,4 +380,15 @@ auto Database::abort_provisional(const std::string& package,
return detail::overlay_delete_recipe(*overlay_, package, version_range, source);
}
auto Database::set_libcxx_override(const std::string& package,
const std::string& version_range,
const std::string& source, bool value)
-> util::Result<void> {
if (auto ok = require_overlay(overlay_); !ok) {
return std::unexpected(ok.error());
}
return detail::overlay_set_libcxx_override(*overlay_, package, version_range,
source, value);
}
} // namespace cargoxx::linkdb