aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/local-store.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/local-store.cc')
-rw-r--r--src/libstore/local-store.cc398
1 files changed, 232 insertions, 166 deletions
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index b26167aca..44a3cd170 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -7,6 +7,7 @@
#include "nar-info.hh"
#include "references.hh"
#include "callback.hh"
+#include "topo-sort.hh"
#include <iostream>
#include <algorithm>
@@ -41,9 +42,68 @@
namespace nix {
+struct LocalStore::State::Stmts {
+ /* Some precompiled SQLite statements. */
+ SQLiteStmt RegisterValidPath;
+ SQLiteStmt UpdatePathInfo;
+ SQLiteStmt AddReference;
+ SQLiteStmt QueryPathInfo;
+ SQLiteStmt QueryReferences;
+ SQLiteStmt QueryReferrers;
+ SQLiteStmt InvalidatePath;
+ SQLiteStmt AddDerivationOutput;
+ SQLiteStmt RegisterRealisedOutput;
+ SQLiteStmt QueryValidDerivers;
+ SQLiteStmt QueryDerivationOutputs;
+ SQLiteStmt QueryRealisedOutput;
+ SQLiteStmt QueryAllRealisedOutputs;
+ SQLiteStmt QueryPathFromHashPart;
+ SQLiteStmt QueryValidPaths;
+};
+
+int getSchema(Path schemaPath)
+{
+ int curSchema = 0;
+ if (pathExists(schemaPath)) {
+ string s = readFile(schemaPath);
+ auto n = string2Int<int>(s);
+ if (!n)
+ throw Error("'%1%' is corrupt", schemaPath);
+ curSchema = *n;
+ }
+ return curSchema;
+}
+
+void migrateCASchema(SQLite& db, Path schemaPath, AutoCloseFD& lockFd)
+{
+ const int nixCASchemaVersion = 1;
+ int curCASchema = getSchema(schemaPath);
+ if (curCASchema != nixCASchemaVersion) {
+ if (curCASchema > nixCASchemaVersion) {
+ throw Error("current Nix store ca-schema is version %1%, but I only support %2%",
+ curCASchema, nixCASchemaVersion);
+ }
+
+ if (!lockFile(lockFd.get(), ltWrite, false)) {
+ printInfo("waiting for exclusive access to the Nix store for ca drvs...");
+ lockFile(lockFd.get(), ltWrite, true);
+ }
+
+ if (curCASchema == 0) {
+ static const char schema[] =
+ #include "ca-specific-schema.sql.gen.hh"
+ ;
+ db.exec(schema);
+ }
+ writeFile(schemaPath, fmt("%d", nixCASchemaVersion));
+ lockFile(lockFd.get(), ltRead, true);
+ }
+}
LocalStore::LocalStore(const Params & params)
: StoreConfig(params)
+ , LocalFSStoreConfig(params)
+ , LocalStoreConfig(params)
, Store(params)
, LocalFSStore(params)
, realStoreDir_{this, false, rootDir != "" ? rootDir + "/nix/store" : storeDir, "real",
@@ -59,6 +119,7 @@ LocalStore::LocalStore(const Params & params)
, locksHeld(tokenizeString<PathSet>(getEnv("NIX_HELD_LOCKS").value_or("")))
{
auto state(_state.lock());
+ state->stmts = std::make_unique<State::Stmts>();
/* Create missing state directories if they don't already exist. */
createDirs(realStoreDir);
@@ -89,12 +150,7 @@ LocalStore::LocalStore(const Params & params)
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
if (!gr)
- logError({
- .name = "'build-users-group' not found",
- .hint = hintfmt(
- "warning: the group '%1%' specified in 'build-users-group' does not exist",
- settings.buildUsersGroup)
- });
+ printError("warning: the group '%1%' specified in 'build-users-group' does not exist", settings.buildUsersGroup);
else {
struct stat st;
if (stat(realStoreDir.c_str(), &st))
@@ -221,32 +277,58 @@ LocalStore::LocalStore(const Params & params)
else openDB(*state, false);
+ if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
+ migrateCASchema(state->db, dbDir + "/ca-schema", globalLock);
+ }
+
/* Prepare SQL statements. */
- state->stmtRegisterValidPath.create(state->db,
+ state->stmts->RegisterValidPath.create(state->db,
"insert into ValidPaths (path, hash, registrationTime, deriver, narSize, ultimate, sigs, ca) values (?, ?, ?, ?, ?, ?, ?, ?);");
- state->stmtUpdatePathInfo.create(state->db,
+ state->stmts->UpdatePathInfo.create(state->db,
"update ValidPaths set narSize = ?, hash = ?, ultimate = ?, sigs = ?, ca = ? where path = ?;");
- state->stmtAddReference.create(state->db,
+ state->stmts->AddReference.create(state->db,
"insert or replace into Refs (referrer, reference) values (?, ?);");
- state->stmtQueryPathInfo.create(state->db,
+ state->stmts->QueryPathInfo.create(state->db,
"select id, hash, registrationTime, deriver, narSize, ultimate, sigs, ca from ValidPaths where path = ?;");
- state->stmtQueryReferences.create(state->db,
+ state->stmts->QueryReferences.create(state->db,
"select path from Refs join ValidPaths on reference = id where referrer = ?;");
- state->stmtQueryReferrers.create(state->db,
+ state->stmts->QueryReferrers.create(state->db,
"select path from Refs join ValidPaths on referrer = id where reference = (select id from ValidPaths where path = ?);");
- state->stmtInvalidatePath.create(state->db,
+ state->stmts->InvalidatePath.create(state->db,
"delete from ValidPaths where path = ?;");
- state->stmtAddDerivationOutput.create(state->db,
+ state->stmts->AddDerivationOutput.create(state->db,
"insert or replace into DerivationOutputs (drv, id, path) values (?, ?, ?);");
- state->stmtQueryValidDerivers.create(state->db,
+ state->stmts->QueryValidDerivers.create(state->db,
"select v.id, v.path from DerivationOutputs d join ValidPaths v on d.drv = v.id where d.path = ?;");
- state->stmtQueryDerivationOutputs.create(state->db,
+ state->stmts->QueryDerivationOutputs.create(state->db,
"select id, path from DerivationOutputs where drv = ?;");
// Use "path >= ?" with limit 1 rather than "path like '?%'" to
// ensure efficient lookup.
- state->stmtQueryPathFromHashPart.create(state->db,
+ state->stmts->QueryPathFromHashPart.create(state->db,
"select path from ValidPaths where path >= ? limit 1;");
- state->stmtQueryValidPaths.create(state->db, "select path from ValidPaths");
+ state->stmts->QueryValidPaths.create(state->db, "select path from ValidPaths");
+ if (settings.isExperimentalFeatureEnabled("ca-derivations")) {
+ state->stmts->RegisterRealisedOutput.create(state->db,
+ R"(
+ insert or replace into Realisations (drvPath, outputName, outputPath)
+ values (?, ?, (select id from ValidPaths where path = ?))
+ ;
+ )");
+ state->stmts->QueryRealisedOutput.create(state->db,
+ R"(
+ select Output.path from Realisations
+ inner join ValidPaths as Output on Output.id = Realisations.outputPath
+ where drvPath = ? and outputName = ?
+ ;
+ )");
+ state->stmts->QueryAllRealisedOutputs.create(state->db,
+ R"(
+ select outputName, Output.path from Realisations
+ inner join ValidPaths as Output on Output.id = Realisations.outputPath
+ where drvPath = ?
+ ;
+ )");
+ }
}
@@ -284,16 +366,7 @@ std::string LocalStore::getUri()
int LocalStore::getSchema()
-{
- int curSchema = 0;
- if (pathExists(schemaPath)) {
- string s = readFile(schemaPath);
- if (!string2Int(s, curSchema))
- throw Error("'%1%' is corrupt", schemaPath);
- }
- return curSchema;
-}
-
+{ return nix::getSchema(schemaPath); }
void LocalStore::openDB(State & state, bool create)
{
@@ -573,21 +646,29 @@ void LocalStore::checkDerivationOutputs(const StorePath & drvPath, const Derivat
[&](DerivationOutputCAFloating _) {
/* Nothing to check */
},
+ [&](DerivationOutputDeferred) {
+ },
}, i.second.output);
}
}
-void LocalStore::linkDeriverToPath(const StorePath & deriver, const string & outputName, const StorePath & output)
+void LocalStore::registerDrvOutput(const Realisation & info)
{
auto state(_state.lock());
- return linkDeriverToPath(*state, queryValidPathId(*state, deriver), outputName, output);
+ retrySQLite<void>([&]() {
+ state->stmts->RegisterRealisedOutput.use()
+ (info.id.strHash())
+ (info.id.outputName)
+ (printStorePath(info.outPath))
+ .exec();
+ });
}
-void LocalStore::linkDeriverToPath(State & state, uint64_t deriver, const string & outputName, const StorePath & output)
+void LocalStore::cacheDrvOutputMapping(State & state, const uint64_t deriver, const string & outputName, const StorePath & output)
{
retrySQLite<void>([&]() {
- state.stmtAddDerivationOutput.use()
+ state.stmts->AddDerivationOutput.use()
(deriver)
(outputName)
(printStorePath(output))
@@ -604,7 +685,7 @@ uint64_t LocalStore::addValidPath(State & state,
throw Error("cannot add path '%s' to the Nix store because it claims to be content-addressed but isn't",
printStorePath(info.path));
- state.stmtRegisterValidPath.use()
+ state.stmts->RegisterValidPath.use()
(printStorePath(info.path))
(info.narHash.to_string(Base16, true))
(info.registrationTime == 0 ? time(0) : info.registrationTime)
@@ -621,7 +702,7 @@ uint64_t LocalStore::addValidPath(State & state,
efficiently query whether a path is an output of some
derivation. */
if (info.path.isDerivation()) {
- auto drv = readDerivation(info.path);
+ auto drv = readInvalidDerivation(info.path);
/* Verify that the output paths in the derivation are correct
(i.e., follow the scheme for computing output paths from
@@ -634,7 +715,7 @@ uint64_t LocalStore::addValidPath(State & state,
/* Floating CA derivations have indeterminate output paths until
they are built, so don't register anything in that case */
if (i.second.second)
- linkDeriverToPath(state, id, i.first, *i.second.second);
+ cacheDrvOutputMapping(state, id, i.first, *i.second.second);
}
}
@@ -652,63 +733,67 @@ void LocalStore::queryPathInfoUncached(const StorePath & path,
Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept
{
try {
- callback(retrySQLite<std::shared_ptr<ValidPathInfo>>([&]() {
+ callback(retrySQLite<std::shared_ptr<const ValidPathInfo>>([&]() {
auto state(_state.lock());
+ return queryPathInfoInternal(*state, path);
+ }));
- /* Get the path info. */
- auto useQueryPathInfo(state->stmtQueryPathInfo.use()(printStorePath(path)));
+ } catch (...) { callback.rethrow(); }
+}
- if (!useQueryPathInfo.next())
- return std::shared_ptr<ValidPathInfo>();
- auto id = useQueryPathInfo.getInt(0);
+std::shared_ptr<const ValidPathInfo> LocalStore::queryPathInfoInternal(State & state, const StorePath & path)
+{
+ /* Get the path info. */
+ auto useQueryPathInfo(state.stmts->QueryPathInfo.use()(printStorePath(path)));
- auto narHash = Hash::dummy;
- try {
- narHash = Hash::parseAnyPrefixed(useQueryPathInfo.getStr(1));
- } catch (BadHash & e) {
- throw Error("invalid-path entry for '%s': %s", printStorePath(path), e.what());
- }
+ if (!useQueryPathInfo.next())
+ return std::shared_ptr<ValidPathInfo>();
- auto info = std::make_shared<ValidPathInfo>(path, narHash);
+ auto id = useQueryPathInfo.getInt(0);
- info->id = id;
+ auto narHash = Hash::dummy;
+ try {
+ narHash = Hash::parseAnyPrefixed(useQueryPathInfo.getStr(1));
+ } catch (BadHash & e) {
+ throw Error("invalid-path entry for '%s': %s", printStorePath(path), e.what());
+ }
- info->registrationTime = useQueryPathInfo.getInt(2);
+ auto info = std::make_shared<ValidPathInfo>(path, narHash);
- auto s = (const char *) sqlite3_column_text(state->stmtQueryPathInfo, 3);
- if (s) info->deriver = parseStorePath(s);
+ info->id = id;
- /* Note that narSize = NULL yields 0. */
- info->narSize = useQueryPathInfo.getInt(4);
+ info->registrationTime = useQueryPathInfo.getInt(2);
- info->ultimate = useQueryPathInfo.getInt(5) == 1;
+ auto s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 3);
+ if (s) info->deriver = parseStorePath(s);
- s = (const char *) sqlite3_column_text(state->stmtQueryPathInfo, 6);
- if (s) info->sigs = tokenizeString<StringSet>(s, " ");
+ /* Note that narSize = NULL yields 0. */
+ info->narSize = useQueryPathInfo.getInt(4);
- s = (const char *) sqlite3_column_text(state->stmtQueryPathInfo, 7);
- if (s) info->ca = parseContentAddressOpt(s);
+ info->ultimate = useQueryPathInfo.getInt(5) == 1;
- /* Get the references. */
- auto useQueryReferences(state->stmtQueryReferences.use()(info->id));
+ s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 6);
+ if (s) info->sigs = tokenizeString<StringSet>(s, " ");
- while (useQueryReferences.next()) {
- info->insertReferencePossiblyToSelf(
- parseStorePath(useQueryReferences.getStr(0)));
- }
+ s = (const char *) sqlite3_column_text(state.stmts->QueryPathInfo, 7);
+ if (s) info->ca = parseContentAddressOpt(s);
- return info;
- }));
+ /* Get the references. */
+ auto useQueryReferences(state.stmts->QueryReferences.use()(info->id));
- } catch (...) { callback.rethrow(); }
+ while (useQueryReferences.next())
+ info->insertReferencePossiblyToSelf(
+ parseStorePath(useQueryReferences.getStr(0)));
+
+ return info;
}
/* Update path info in the database. */
void LocalStore::updatePathInfo(State & state, const ValidPathInfo & info)
{
- state.stmtUpdatePathInfo.use()
+ state.stmts->UpdatePathInfo.use()
(info.narSize, info.narSize != 0)
(info.narHash.to_string(Base16, true))
(info.ultimate ? 1 : 0, info.ultimate)
@@ -721,7 +806,7 @@ void LocalStore::updatePathInfo(State & state, const ValidPathInfo & info)
uint64_t LocalStore::queryValidPathId(State & state, const StorePath & path)
{
- auto use(state.stmtQueryPathInfo.use()(printStorePath(path)));
+ auto use(state.stmts->QueryPathInfo.use()(printStorePath(path)));
if (!use.next())
throw InvalidPath("path '%s' is not valid", printStorePath(path));
return use.getInt(0);
@@ -730,7 +815,7 @@ uint64_t LocalStore::queryValidPathId(State & state, const StorePath & path)
bool LocalStore::isValidPath_(State & state, const StorePath & path)
{
- return state.stmtQueryPathInfo.use()(printStorePath(path)).next();
+ return state.stmts->QueryPathInfo.use()(printStorePath(path)).next();
}
@@ -756,7 +841,7 @@ StorePathSet LocalStore::queryAllValidPaths()
{
return retrySQLite<StorePathSet>([&]() {
auto state(_state.lock());
- auto use(state->stmtQueryValidPaths.use());
+ auto use(state->stmts->QueryValidPaths.use());
StorePathSet res;
while (use.next()) res.insert(parseStorePath(use.getStr(0)));
return res;
@@ -766,7 +851,7 @@ StorePathSet LocalStore::queryAllValidPaths()
void LocalStore::queryReferrers(State & state, const StorePath & path, StorePathSet & referrers)
{
- auto useQueryReferrers(state.stmtQueryReferrers.use()(printStorePath(path)));
+ auto useQueryReferrers(state.stmts->QueryReferrers.use()(printStorePath(path)));
while (useQueryReferrers.next())
referrers.insert(parseStorePath(useQueryReferrers.getStr(0)));
@@ -787,7 +872,7 @@ StorePathSet LocalStore::queryValidDerivers(const StorePath & path)
return retrySQLite<StorePathSet>([&]() {
auto state(_state.lock());
- auto useQueryValidDerivers(state->stmtQueryValidDerivers.use()(printStorePath(path)));
+ auto useQueryValidDerivers(state->stmts->QueryValidDerivers.use()(printStorePath(path)));
StorePathSet derivers;
while (useQueryValidDerivers.next())
@@ -798,69 +883,38 @@ StorePathSet LocalStore::queryValidDerivers(const StorePath & path)
}
-std::map<std::string, std::optional<StorePath>> LocalStore::queryPartialDerivationOutputMap(const StorePath & path_)
+std::map<std::string, std::optional<StorePath>>
+LocalStore::queryPartialDerivationOutputMap(const StorePath & path_)
{
auto path = path_;
- std::map<std::string, std::optional<StorePath>> outputs;
- Derivation drv = readDerivation(path);
- for (auto & [outName, _] : drv.outputs) {
- outputs.insert_or_assign(outName, std::nullopt);
- }
- bool haveCached = false;
- {
- auto resolutions = drvPathResolutions.lock();
- auto resolvedPathOptIter = resolutions->find(path);
- if (resolvedPathOptIter != resolutions->end()) {
- auto & [_, resolvedPathOpt] = *resolvedPathOptIter;
- if (resolvedPathOpt)
- path = *resolvedPathOpt;
- haveCached = true;
- }
- }
- /* can't just use else-if instead of `!haveCached` because we need to unlock
- `drvPathResolutions` before it is locked in `Derivation::resolve`. */
- if (!haveCached && drv.type() == DerivationType::CAFloating) {
- /* Try resolve drv and use that path instead. */
- auto attempt = drv.tryResolve(*this);
- if (!attempt)
- /* If we cannot resolve the derivation, we cannot have any path
- assigned so we return the map of all std::nullopts. */
- return outputs;
- /* Just compute store path */
- auto pathResolved = writeDerivation(*this, *std::move(attempt), NoRepair, true);
- /* Store in memo table. */
- /* FIXME: memo logic should not be local-store specific, should have
- wrapper-method instead. */
- drvPathResolutions.lock()->insert_or_assign(path, pathResolved);
- path = std::move(pathResolved);
- }
- return retrySQLite<std::map<std::string, std::optional<StorePath>>>([&]() {
+ auto outputs = retrySQLite<std::map<std::string, std::optional<StorePath>>>([&]() {
auto state(_state.lock());
-
+ std::map<std::string, std::optional<StorePath>> outputs;
uint64_t drvId;
- try {
- drvId = queryValidPathId(*state, path);
- } catch (InvalidPath &) {
- /* FIXME? if the derivation doesn't exist, we cannot have a mapping
- for it. */
- return outputs;
- }
-
- auto useQueryDerivationOutputs {
- state->stmtQueryDerivationOutputs.use()
- (drvId)
- };
-
- while (useQueryDerivationOutputs.next())
+ drvId = queryValidPathId(*state, path);
+ auto use(state->stmts->QueryDerivationOutputs.use()(drvId));
+ while (use.next())
outputs.insert_or_assign(
- useQueryDerivationOutputs.getStr(0),
- parseStorePath(useQueryDerivationOutputs.getStr(1))
- );
+ use.getStr(0), parseStorePath(use.getStr(1)));
return outputs;
});
-}
+ if (!settings.isExperimentalFeatureEnabled("ca-derivations"))
+ return outputs;
+
+ auto drv = readInvalidDerivation(path);
+ auto drvHashes = staticOutputHashes(*this, drv);
+ for (auto& [outputName, hash] : drvHashes) {
+ auto realisation = queryRealisation(DrvOutput{hash, outputName});
+ if (realisation)
+ outputs.insert_or_assign(outputName, realisation->outPath);
+ else
+ outputs.insert({outputName, std::nullopt});
+ }
+
+ return outputs;
+}
std::optional<StorePath> LocalStore::queryPathFromHashPart(const std::string & hashPart)
{
@@ -871,11 +925,11 @@ std::optional<StorePath> LocalStore::queryPathFromHashPart(const std::string & h
return retrySQLite<std::optional<StorePath>>([&]() -> std::optional<StorePath> {
auto state(_state.lock());
- auto useQueryPathFromHashPart(state->stmtQueryPathFromHashPart.use()(prefix));
+ auto useQueryPathFromHashPart(state->stmts->QueryPathFromHashPart.use()(prefix));
if (!useQueryPathFromHashPart.next()) return {};
- const char * s = (const char *) sqlite3_column_text(state->stmtQueryPathFromHashPart, 0);
+ const char * s = (const char *) sqlite3_column_text(state->stmts->QueryPathFromHashPart, 0);
if (s && prefix.compare(0, prefix.size(), s, prefix.size()) == 0)
return parseStorePath(s);
return {};
@@ -964,9 +1018,7 @@ void LocalStore::querySubstitutablePathInfos(const StorePathCAMap & paths, Subst
void LocalStore::registerValidPath(const ValidPathInfo & info)
{
- ValidPathInfos infos;
- infos.push_back(info);
- registerValidPaths(infos);
+ registerValidPaths({{info.path, info}});
}
@@ -984,7 +1036,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
SQLiteTxn txn(state->db);
StorePathSet paths;
- for (auto & i : infos) {
+ for (auto & [_, i] : infos) {
assert(i.narHash.type == htSHA256);
if (isValidPath_(*state, i.path))
updatePathInfo(*state, i);
@@ -993,26 +1045,37 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
paths.insert(i.path);
}
- for (auto & i : infos) {
+ for (auto & [_, i] : infos) {
auto referrer = queryValidPathId(*state, i.path);
for (auto & j : i.referencesPossiblyToSelf())
- state->stmtAddReference.use()(referrer)(queryValidPathId(*state, j)).exec();
+ state->stmts->AddReference.use()(referrer)(queryValidPathId(*state, j)).exec();
}
/* Check that the derivation outputs are correct. We can't do
this in addValidPath() above, because the references might
not be valid yet. */
- for (auto & i : infos)
+ for (auto & [_, i] : infos)
if (i.path.isDerivation()) {
// FIXME: inefficient; we already loaded the derivation in addValidPath().
- checkDerivationOutputs(i.path, readDerivation(i.path));
+ checkDerivationOutputs(i.path,
+ readInvalidDerivation(i.path));
}
/* Do a topological sort of the paths. This will throw an
error if a cycle is detected and roll back the
transaction. Cycles can only occur when a derivation
has multiple outputs. */
- topoSortPaths(paths);
+ topoSort(paths,
+ {[&](const StorePath & path) {
+ auto i = infos.find(path);
+ return i == infos.end() ? StorePathSet() : i->second.references;
+ }},
+ {[&](const StorePath & path, const StorePath & parent) {
+ return BuildError(
+ "cycle detected in the references of '%s' from '%s'",
+ printStorePath(path),
+ printStorePath(parent));
+ }});
txn.commit();
});
@@ -1025,7 +1088,7 @@ void LocalStore::invalidatePath(State & state, const StorePath & path)
{
debug("invalidating path '%s'", printStorePath(path));
- state.stmtInvalidatePath.use()(printStorePath(path)).exec();
+ state.stmts->InvalidatePath.use()(printStorePath(path)).exec();
/* Note that the foreign key constraints on the Refs table take
care of deleting the references entries for `path'. */
@@ -1036,7 +1099,6 @@ void LocalStore::invalidatePath(State & state, const StorePath & path)
}
}
-
const PublicKeys & LocalStore::getPublicKeys()
{
auto state(_state.lock());
@@ -1045,11 +1107,15 @@ const PublicKeys & LocalStore::getPublicKeys()
return *state->publicKeys;
}
+bool LocalStore::pathInfoIsTrusted(const ValidPathInfo & info)
+{
+ return requireSigs && !info.checkSignatures(*this, getPublicKeys());
+}
void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
RepairFlag repair, CheckSigsFlag checkSigs)
{
- if (requireSigs && checkSigs && !info.checkSignatures(*this, getPublicKeys()))
+ if (checkSigs && pathInfoIsTrusted(info))
throw Error("cannot add path '%s' because it lacks a valid signature", printStorePath(info.path));
addTempRoot(info.path);
@@ -1089,11 +1155,11 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
auto hashResult = hashSink->finish();
if (hashResult.first != info.narHash)
- throw Error("hash mismatch importing path '%s';\n wanted: %s\n got: %s",
+ throw Error("hash mismatch importing path '%s';\n specified: %s\n got: %s",
printStorePath(info.path), info.narHash.to_string(Base32, true), hashResult.first.to_string(Base32, true));
if (hashResult.second != info.narSize)
- throw Error("size mismatch importing path '%s';\n wanted: %s\n got: %s",
+ throw Error("size mismatch importing path '%s';\n specified: %s\n got: %s",
printStorePath(info.path), info.narSize, hashResult.second);
autoGC();
@@ -1137,7 +1203,7 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, const string & name,
dump.resize(oldSize + want);
auto got = 0;
try {
- got = source.read((uint8_t *) dump.data() + oldSize, want);
+ got = source.read(dump.data() + oldSize, want);
} catch (EndOfFile &) {
inMemory = true;
break;
@@ -1353,12 +1419,8 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
Path linkPath = linksDir + "/" + link.name;
string hash = hashPath(htSHA256, linkPath).first.to_string(Base32, false);
if (hash != link.name) {
- logError({
- .name = "Invalid hash",
- .hint = hintfmt(
- "link '%s' was modified! expected hash '%s', got '%s'",
- linkPath, link.name, hash)
- });
+ printError("link '%s' was modified! expected hash '%s', got '%s'",
+ linkPath, link.name, hash);
if (repair) {
if (unlink(linkPath.c_str()) == 0)
printInfo("removed link '%s'", linkPath);
@@ -1391,11 +1453,8 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
auto current = hashSink->finish();
if (info->narHash != nullHash && info->narHash != current.first) {
- logError({
- .name = "Invalid hash - path modified",
- .hint = hintfmt("path '%s' was modified! expected hash '%s', got '%s'",
- printStorePath(i), info->narHash.to_string(Base32, true), current.first.to_string(Base32, true))
- });
+ printError("path '%s' was modified! expected hash '%s', got '%s'",
+ printStorePath(i), info->narHash.to_string(Base32, true), current.first.to_string(Base32, true));
if (repair) repairPath(i); else errors = true;
} else {
@@ -1446,10 +1505,7 @@ void LocalStore::verifyPath(const Path & pathS, const StringSet & store,
if (!done.insert(pathS).second) return;
if (!isStorePath(pathS)) {
- logError({
- .name = "Nix path not found",
- .hint = hintfmt("path '%s' is not in the Nix store", pathS)
- });
+ printError("path '%s' is not in the Nix store", pathS);
return;
}
@@ -1472,10 +1528,7 @@ void LocalStore::verifyPath(const Path & pathS, const StringSet & store,
auto state(_state.lock());
invalidatePath(*state, path);
} else {
- logError({
- .name = "Missing path with referrers",
- .hint = hintfmt("path '%s' disappeared, but it still has valid referrers!", pathS)
- });
+ printError("path '%s' disappeared, but it still has valid referrers!", pathS);
if (repair)
try {
repairPath(path);
@@ -1565,7 +1618,7 @@ void LocalStore::addSignatures(const StorePath & storePath, const StringSet & si
SQLiteTxn txn(state->db);
- auto info = std::const_pointer_cast<ValidPathInfo>(std::shared_ptr<const ValidPathInfo>(queryPathInfo(storePath)));
+ auto info = std::const_pointer_cast<ValidPathInfo>(queryPathInfoInternal(*state, storePath));
info->sigs.insert(sigs.begin(), sigs.end());
@@ -1603,5 +1656,18 @@ void LocalStore::createUser(const std::string & userName, uid_t userId)
}
}
-
+std::optional<const Realisation> LocalStore::queryRealisation(
+ const DrvOutput& id) {
+ typedef std::optional<const Realisation> Ret;
+ return retrySQLite<Ret>([&]() -> Ret {
+ auto state(_state.lock());
+ auto use(state->stmts->QueryRealisedOutput.use()(id.strHash())(
+ id.outputName));
+ if (!use.next())
+ return std::nullopt;
+ auto outputPath = parseStorePath(use.getStr(0));
+ return Ret{
+ Realisation{.id = id, .outPath = outputPath}};
+ });
}
+} // namespace nix