From a4ec6cb1da63941c9ec3e7ffcb7639fc21b858c8 Mon Sep 17 00:00:00 2001 From: regnat Date: Fri, 16 Jul 2021 11:40:56 +0200 Subject: [PATCH] Be more lenient when realisations have a conflicting dependency set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - This can legitimately happen (for example because of a non-determinism causing a build-time dependency to be kept or not as a runtime reference) - Because of older Nix versions, it can happen that we encounter a realisation with an (erroneously) empty set of dependencies, in which case we don’t want to fail, but just warn the user and try to fix it. --- src/libstore/local-store.cc | 8 ++++---- src/libstore/realisation.cc | 12 ++++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index d7c7f8e1d..747eb205e 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -342,7 +342,7 @@ LocalStore::LocalStore(const Params & params) if (settings.isExperimentalFeatureEnabled("ca-derivations")) { state->stmts->RegisterRealisedOutput.create(state->db, R"( - insert or replace into Realisations (drvPath, outputName, outputPath, signatures) + insert into Realisations (drvPath, outputName, outputPath, signatures) values (?, ?, (select id from ValidPaths where path = ?), ?) ; )"); @@ -379,7 +379,7 @@ LocalStore::LocalStore(const Params & params) R"( insert or replace into RealisationsRefs (referrer, realisationReference) values ( - ?, + (select id from Realisations where drvPath = ? and outputName = ?), (select id from Realisations where drvPath = ? and outputName = ?)); )"); } @@ -748,7 +748,6 @@ void LocalStore::registerDrvOutput(const Realisation & info) (concatStringsSep(" ", info.signatures)) .exec(); } - uint64_t myId = state->db.getLastInsertedRowId(); for (auto & [outputId, depPath] : info.dependentRealisations) { auto localRealisation = queryRealisationCore_(*state, outputId); if (!localRealisation) @@ -761,7 +760,8 @@ void LocalStore::registerDrvOutput(const Realisation & info) "match what we have locally", info.id.to_string(), outputId.to_string()); state->stmts->AddRealisationReference.use() - (myId) + (info.id.strHash()) + (info.id.outputName) (outputId.strHash()) (outputId.outputName) .exec(); diff --git a/src/libstore/realisation.cc b/src/libstore/realisation.cc index eadec594c..f871e6437 100644 --- a/src/libstore/realisation.cc +++ b/src/libstore/realisation.cc @@ -144,8 +144,16 @@ bool Realisation::isCompatibleWith(const Realisation & other) const { assert (id == other.id); if (outPath == other.outPath) { - assert(dependentRealisations == other.dependentRealisations); - return true; + if (dependentRealisations.empty() != other.dependentRealisations.empty()) { + warn( + "Encountered a realisation for '%s' with an empty set of " + "dependencies. This is likely an artifact from an older Nix. " + "I’ll try to fix the realisation if I can", + id.to_string()); + return true; + } else if (dependentRealisations == other.dependentRealisations) { + return true; + } } return false; }