aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--perl/lib/Nix/Store.xs12
-rw-r--r--src/libexpr/primops.cc21
-rw-r--r--src/libexpr/primops/fetchTree.cc13
-rw-r--r--src/libfetchers/fetchers.cc8
-rw-r--r--src/libfetchers/tarball.cc18
-rw-r--r--src/libstore/binary-cache-store.cc60
-rw-r--r--src/libstore/build/local-derivation-goal.cc63
-rw-r--r--src/libstore/build/substitution-goal.cc15
-rw-r--r--src/libstore/content-address.cc32
-rw-r--r--src/libstore/content-address.hh98
-rw-r--r--src/libstore/daemon.cc8
-rw-r--r--src/libstore/derivations.cc4
-rw-r--r--src/libstore/derived-path.hh1
-rw-r--r--src/libstore/export-import.cc4
-rw-r--r--src/libstore/legacy-ssh-store.cc7
-rw-r--r--src/libstore/local-store.cc53
-rw-r--r--src/libstore/make-content-addressed.cc49
-rw-r--r--src/libstore/misc.cc19
-rw-r--r--src/libstore/nar-info-disk-cache.cc2
-rw-r--r--src/libstore/nar-info.cc2
-rw-r--r--src/libstore/nar-info.hh3
-rw-r--r--src/libstore/path-info.cc91
-rw-r--r--src/libstore/path-info.hh11
-rw-r--r--src/libstore/path.hh5
-rw-r--r--src/libstore/realisation.hh3
-rw-r--r--src/libstore/remote-store.cc13
-rw-r--r--src/libstore/store-api.cc112
-rw-r--r--src/libstore/store-api.hh14
-rw-r--r--src/libutil/reference-set.hh68
-rw-r--r--src/nix-store/dotgraph.cc2
-rw-r--r--src/nix-store/graphml.cc2
-rw-r--r--src/nix-store/nix-store.cc20
-rw-r--r--src/nix/add-to-store.cc16
-rw-r--r--src/nix/prefetch.cc8
-rw-r--r--src/nix/profile.cc17
-rw-r--r--src/nix/verify.cc6
-rw-r--r--src/nix/why-depends.cc2
37 files changed, 606 insertions, 276 deletions
diff --git a/perl/lib/Nix/Store.xs b/perl/lib/Nix/Store.xs
index 54ad1680c..bdb4fa655 100644
--- a/perl/lib/Nix/Store.xs
+++ b/perl/lib/Nix/Store.xs
@@ -69,7 +69,7 @@ int isValidPath(char * path)
SV * queryReferences(char * path)
PPCODE:
try {
- for (auto & i : store()->queryPathInfo(store()->parseStorePath(path))->references)
+ for (auto & i : store()->queryPathInfo(store()->parseStorePath(path))->referencesPossiblyToSelf())
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
@@ -110,7 +110,7 @@ SV * queryPathInfo(char * path, int base32)
mXPUSHi(info->registrationTime);
mXPUSHi(info->narSize);
AV * refs = newAV();
- for (auto & i : info->references)
+ for (auto & i : info->referencesPossiblyToSelf())
av_push(refs, newSVpv(store()->printStorePath(i).c_str(), 0));
XPUSHs(sv_2mortal(newRV((SV *) refs)));
AV * sigs = newAV();
@@ -294,7 +294,13 @@ SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
try {
auto h = Hash::parseAny(hash, parseHashType(algo));
auto method = recursive ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat;
- auto path = store()->makeFixedOutputPath(method, h, name);
+ auto path = store()->makeFixedOutputPath(name, FixedOutputInfo {
+ {
+ .method = method,
+ .hash = h,
+ },
+ .references = {},
+ });
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(path).c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 9cff4b365..ae573cf4d 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -1253,7 +1253,13 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * *
auto h = newHashAllowEmpty(*outputHash, parseHashTypeOpt(outputHashAlgo));
auto method = ingestionMethod.value_or(FileIngestionMethod::Flat);
- auto outPath = state.store->makeFixedOutputPath(method, h, drvName);
+ auto outPath = state.store->makeFixedOutputPath(drvName, FixedOutputInfo {
+ {
+ .method = method,
+ .hash = h,
+ },
+ .references = {},
+ });
drv.env["out"] = state.store->printStorePath(outPath);
drv.outputs.insert_or_assign("out",
DerivationOutput::CAFixed {
@@ -1538,7 +1544,8 @@ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, V
StorePathSet refs;
if (state.store->isInStore(path)) {
try {
- refs = state.store->queryPathInfo(state.store->toStorePath(path).first)->references;
+ // FIXME: Are self references becoming non-self references OK?
+ refs = state.store->queryPathInfo(state.store->toStorePath(path).first)->referencesPossiblyToSelf();
} catch (Error &) { // FIXME: should be InvalidPathError
}
// Re-scan references to filter down to just the ones that actually occur in the file.
@@ -1973,7 +1980,7 @@ static void addPath(
try {
auto [storePath, subPath] = state.store->toStorePath(path);
// FIXME: we should scanForReferences on the path before adding it
- refs = state.store->queryPathInfo(storePath)->references;
+ refs = state.store->queryPathInfo(storePath)->referencesPossiblyToSelf();
path = state.store->toRealPath(storePath) + subPath;
} catch (Error &) { // FIXME: should be InvalidPathError
}
@@ -2007,7 +2014,13 @@ static void addPath(
std::optional<StorePath> expectedStorePath;
if (expectedHash)
- expectedStorePath = state.store->makeFixedOutputPath(method, *expectedHash, name);
+ expectedStorePath = state.store->makeFixedOutputPath(name, FixedOutputInfo {
+ {
+ .method = method,
+ .hash = *expectedHash,
+ },
+ .references = {},
+ });
if (!expectedHash || !state.store->isValidPath(*expectedStorePath)) {
StorePath dstPath = settings.readOnlyMode
diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc
index 1fb480089..560a086f0 100644
--- a/src/libexpr/primops/fetchTree.cc
+++ b/src/libexpr/primops/fetchTree.cc
@@ -228,10 +228,15 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
// early exit if pinned and already in the store
if (expectedHash && expectedHash->type == htSHA256) {
- auto expectedPath =
- unpack
- ? state.store->makeFixedOutputPath(FileIngestionMethod::Recursive, *expectedHash, name, {})
- : state.store->makeFixedOutputPath(FileIngestionMethod::Flat, *expectedHash, name, {});
+ auto expectedPath = state.store->makeFixedOutputPath(
+ name,
+ FixedOutputInfo {
+ {
+ .method = unpack ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat,
+ .hash = *expectedHash,
+ },
+ .references = {}
+ });
if (state.store->isValidPath(expectedPath)) {
state.allowAndSetStorePathString(expectedPath, v);
diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc
index c767e72e5..3936eadfe 100644
--- a/src/libfetchers/fetchers.cc
+++ b/src/libfetchers/fetchers.cc
@@ -210,7 +210,13 @@ StorePath Input::computeStorePath(Store & store) const
auto narHash = getNarHash();
if (!narHash)
throw Error("cannot compute store path for unlocked input '%s'", to_string());
- return store.makeFixedOutputPath(FileIngestionMethod::Recursive, *narHash, getName());
+ return store.makeFixedOutputPath(getName(), FixedOutputInfo {
+ {
+ .method = FileIngestionMethod::Recursive,
+ .hash = *narHash,
+ },
+ .references = {},
+ });
}
std::string Input::getType() const
diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc
index e9686262a..155b86cc4 100644
--- a/src/libfetchers/tarball.cc
+++ b/src/libfetchers/tarball.cc
@@ -71,15 +71,21 @@ DownloadFileResult downloadFile(
dumpString(res.data, sink);
auto hash = hashString(htSHA256, res.data);
ValidPathInfo info {
- store->makeFixedOutputPath(FileIngestionMethod::Flat, hash, name),
+ *store,
+ {
+ .name = name,
+ .info = FixedOutputInfo {
+ {
+ .method = FileIngestionMethod::Flat,
+ .hash = hash,
+ },
+ .references = {},
+ },
+ },
hashString(htSHA256, sink.s),
};
info.narSize = sink.s.size();
- info.ca = FixedOutputHash {
- .method = FileIngestionMethod::Flat,
- .hash = hash,
- };
- auto source = StringSource(sink.s);
+ auto source = StringSource { sink.s };
store->addToStore(info, source, NoRepair, NoCheckSigs);
storePath = std::move(info.path);
}
diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc
index 05bf0501d..087b37655 100644
--- a/src/libstore/binary-cache-store.cc
+++ b/src/libstore/binary-cache-store.cc
@@ -180,11 +180,11 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
duration);
/* Verify that all references are valid. This may do some .narinfo
- reads, but typically they'll already be cached. */
- for (auto & ref : info.references)
+ reads, but typically they'll already be cached. Note that
+ self-references are always valid. */
+ for (auto & ref : info.references.others)
try {
- if (ref != info.path)
- queryPathInfo(ref);
+ queryPathInfo(ref);
} catch (InvalidPath &) {
throw Error("cannot add '%s' to the binary cache because the reference '%s' is not valid",
printStorePath(info.path), printStorePath(ref));
@@ -306,11 +306,23 @@ StorePath BinaryCacheStore::addToStoreFromDump(Source & dump, std::string_view n
unsupported("addToStoreFromDump");
return addToStoreCommon(dump, repair, CheckSigs, [&](HashResult nar) {
ValidPathInfo info {
- makeFixedOutputPath(method, nar.first, name, references),
+ *this,
+ {
+ .name = std::string { name },
+ .info = FixedOutputInfo {
+ {
+ .method = method,
+ .hash = nar.first,
+ },
+ .references = {
+ .others = references,
+ .self = false,
+ },
+ },
+ },
nar.first,
};
info.narSize = nar.second;
- info.references = references;
return info;
})->path;
}
@@ -414,15 +426,23 @@ StorePath BinaryCacheStore::addToStore(
});
return addToStoreCommon(*source, repair, CheckSigs, [&](HashResult nar) {
ValidPathInfo info {
- makeFixedOutputPath(method, h, name, references),
+ *this,
+ {
+ .name = std::string { name },
+ .info = FixedOutputInfo {
+ {
+ .method = method,
+ .hash = h,
+ },
+ .references = {
+ .others = references,
+ .self = false,
+ },
+ },
+ },
nar.first,
};
info.narSize = nar.second;
- info.references = references;
- info.ca = FixedOutputHash {
- .method = method,
- .hash = h,
- };
return info;
})->path;
}
@@ -434,7 +454,7 @@ StorePath BinaryCacheStore::addTextToStore(
RepairFlag repair)
{
auto textHash = hashString(htSHA256, s);
- auto path = makeTextPath(name, textHash, references);
+ auto path = makeTextPath(name, TextInfo { textHash, references });
if (!repair && isValidPath(path))
return path;
@@ -443,10 +463,18 @@ StorePath BinaryCacheStore::addTextToStore(
dumpString(s, sink);
StringSource source(sink.s);
return addToStoreCommon(source, repair, CheckSigs, [&](HashResult nar) {
- ValidPathInfo info { path, nar.first };
+ ValidPathInfo info {
+ *this,
+ {
+ .name = std::string { name },
+ .info = TextInfo {
+ { .hash = textHash },
+ references,
+ },
+ },
+ nar.first,
+ };
info.narSize = nar.second;
- info.ca = TextHash { textHash };
- info.references = references;
return info;
})->path;
}
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index 9ab9b17fe..d96858fc0 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -2421,27 +2421,26 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
}
};
- auto rewriteRefs = [&]() -> std::pair<bool, StorePathSet> {
+ auto rewriteRefs = [&]() -> StoreReferences {
/* In the CA case, we need the rewritten refs to calculate the
final path, therefore we look for a *non-rewritten
self-reference, and use a bool rather try to solve the
computationally intractable fixed point. */
- std::pair<bool, StorePathSet> res {
- false,
- {},
+ StoreReferences res {
+ .self = false,
};
for (auto & r : references) {
auto name = r.name();
auto origHash = std::string { r.hashPart() };
if (r == *scratchPath) {
- res.first = true;
+ res.self = true;
} else if (auto outputRewrite = get(outputRewrites, origHash)) {
std::string newRef = *outputRewrite;
newRef += '-';
newRef += name;
- res.second.insert(StorePath { newRef });
+ res.others.insert(StorePath { newRef });
} else {
- res.second.insert(r);
+ res.others.insert(r);
}
}
return res;
@@ -2474,18 +2473,24 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
break;
}
auto got = caSink.finish().first;
- auto refs = rewriteRefs();
-
- auto finalPath = worker.store.makeFixedOutputPath(
- outputHash.method,
- got,
- outputPathName(drv->name, outputName),
- refs.second,
- refs.first);
- if (*scratchPath != finalPath) {
+ ValidPathInfo newInfo0 {
+ worker.store,
+ {
+ .name = outputPathName(drv->name, outputName),
+ .info = FixedOutputInfo {
+ {
+ .method = outputHash.method,
+ .hash = got,
+ },
+ .references = rewriteRefs(),
+ },
+ },
+ Hash::dummy,
+ };
+ if (*scratchPath != newInfo0.path) {
// Also rewrite the output path
auto source = sinkToSource([&](Sink & nextSink) {
- RewritingSink rsink2(oldHashPart, std::string(finalPath.hashPart()), nextSink);
+ RewritingSink rsink2(oldHashPart, std::string(newInfo0.path.hashPart()), nextSink);
dumpPath(actualPath, rsink2);
rsink2.flush();
});
@@ -2496,19 +2501,8 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
}
HashResult narHashAndSize = hashPath(htSHA256, actualPath);
- ValidPathInfo newInfo0 {
- finalPath,
- narHashAndSize.first,
- };
-
+ newInfo0.narHash = narHashAndSize.first;
newInfo0.narSize = narHashAndSize.second;
- newInfo0.ca = FixedOutputHash {
- .method = outputHash.method,
- .hash = got,
- };
- newInfo0.references = refs.second;
- if (refs.first)
- newInfo0.references.insert(newInfo0.path);
assert(newInfo0.ca);
return newInfo0;
@@ -2529,10 +2523,7 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
auto narHashAndSize = hashPath(htSHA256, actualPath);
ValidPathInfo newInfo0 { requiredFinalPath, narHashAndSize.first };
newInfo0.narSize = narHashAndSize.second;
- auto refs = rewriteRefs();
- newInfo0.references = refs.second;
- if (refs.first)
- newInfo0.references.insert(newInfo0.path);
+ newInfo0.references = rewriteRefs();
return newInfo0;
},
@@ -2783,12 +2774,12 @@ void LocalDerivationGoal::checkOutputs(const std::map<std::string, ValidPathInfo
auto i = outputsByPath.find(worker.store.printStorePath(path));
if (i != outputsByPath.end()) {
closureSize += i->second.narSize;
- for (auto & ref : i->second.references)
+ for (auto & ref : i->second.referencesPossiblyToSelf())
pathsLeft.push(ref);
} else {
auto info = worker.store.queryPathInfo(path);
closureSize += info->narSize;
- for (auto & ref : info->references)
+ for (auto & ref : info->referencesPossiblyToSelf())
pathsLeft.push(ref);
}
}
@@ -2828,7 +2819,7 @@ void LocalDerivationGoal::checkOutputs(const std::map<std::string, ValidPathInfo
auto used = recursive
? getClosure(info.path).first
- : info.references;
+ : info.referencesPossiblyToSelf();
if (recursive && checks.ignoreSelfRefs)
used.erase(info.path);
diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc
index 2af105b4d..36b0ea7a7 100644
--- a/src/libstore/build/substitution-goal.cc
+++ b/src/libstore/build/substitution-goal.cc
@@ -95,7 +95,10 @@ void PathSubstitutionGoal::tryNext()
subs.pop_front();
if (ca) {
- subPath = sub->makeFixedOutputPathFromCA(storePath.name(), *ca);
+ subPath = sub->makeFixedOutputPathFromCA({
+ .name = std::string { storePath.name() },
+ .info = caWithoutRefs(*ca),
+ });
if (sub->storeDir == worker.store.storeDir)
assert(subPath == storePath);
} else if (sub->storeDir != worker.store.storeDir) {
@@ -162,9 +165,8 @@ void PathSubstitutionGoal::tryNext()
/* To maintain the closure invariant, we first have to realise the
paths referenced by this one. */
- for (auto & i : info->references)
- if (i != storePath) /* ignore self-references */
- addWaitee(worker.makePathSubstitutionGoal(i));
+ for (auto & i : info->references.others)
+ addWaitee(worker.makePathSubstitutionGoal(i));
if (waitees.empty()) /* to prevent hang (no wake-up event) */
referencesValid();
@@ -185,9 +187,8 @@ void PathSubstitutionGoal::referencesValid()
return;
}
- for (auto & i : info->references)
- if (i != storePath) /* ignore self-references */
- assert(worker.store.isValidPath(i));
+ for (auto & i : info->references.others)
+ assert(worker.store.isValidPath(i));
state = &PathSubstitutionGoal::tryToRun;
worker.wakeUp(shared_from_this());
diff --git a/src/libstore/content-address.cc b/src/libstore/content-address.cc
index cf32ccdc4..3b8a773b7 100644
--- a/src/libstore/content-address.cc
+++ b/src/libstore/content-address.cc
@@ -9,16 +9,16 @@ std::string FixedOutputHash::printMethodAlgo() const
return makeFileIngestionPrefix(method) + printHashType(hash.type);
}
-std::string makeFileIngestionPrefix(const FileIngestionMethod m)
+
+std::string makeFileIngestionPrefix(FileIngestionMethod m)
{
switch (m) {
case FileIngestionMethod::Flat:
return "";
case FileIngestionMethod::Recursive:
return "r:";
- default:
- throw Error("impossible, caught both cases");
}
+ assert(false);
}
std::string makeFixedOutputCA(FileIngestionMethod method, const Hash & hash)
@@ -32,10 +32,13 @@ std::string renderContentAddress(ContentAddress ca)
{
return std::visit(overloaded {
[](TextHash & th) {
- return "text:" + th.hash.to_string(Base32, true);
+ return "text:"
+ + th.hash.to_string(Base32, true);
},
[](FixedOutputHash & fsh) {
- return makeFixedOutputCA(fsh.method, fsh.hash);
+ return "fixed:"
+ + makeFileIngestionPrefix(fsh.method)
+ + fsh.hash.to_string(Base32, true);
}
}, ca);
}
@@ -144,7 +147,24 @@ Hash getContentAddressHash(const ContentAddress & ca)
},
[](const FixedOutputHash & fsh) {
return fsh.hash;
- }
+ },
+ }, ca);
+}
+
+ContentAddressWithReferences caWithoutRefs(const ContentAddress & ca) {
+ return std::visit(overloaded {
+ [&](const TextHash & h) -> ContentAddressWithReferences {
+ return TextInfo {
+ h,
+ .references = {},
+ };
+ },
+ [&](const FixedOutputHash & h) -> ContentAddressWithReferences {
+ return FixedOutputInfo {
+ h,
+ .references = {},
+ };
+ },
}, ca);
}
diff --git a/src/libstore/content-address.hh b/src/libstore/content-address.hh
index f6a6f5140..f8a4d5370 100644
--- a/src/libstore/content-address.hh
+++ b/src/libstore/content-address.hh
@@ -2,16 +2,57 @@
#include <variant>
#include "hash.hh"
+#include "path.hh"
+#include "comparator.hh"
+#include "reference-set.hh"
namespace nix {
+/*
+ * Content addressing method
+ */
+
+/* We only have one way to hash text with references, so this is a single-value
+ type, mainly useful with std::variant.
+*/
+struct TextHashMethod : std::monostate { };
+
enum struct FileIngestionMethod : uint8_t {
Flat = false,
Recursive = true
};
+struct FixedOutputHashMethod {
+ FileIngestionMethod fileIngestionMethod;
+ HashType hashType;
+};
+
+/* Compute the prefix to the hash algorithm which indicates how the files were
+ ingested. */
+std::string makeFileIngestionPrefix(FileIngestionMethod m);
+
+
+/* Just the type of a content address. Combine with the hash itself, and we
+ have a `ContentAddress` as defined below. Combine that, in turn, with info
+ on references, and we have `ContentAddressWithReferences`, as defined
+ further below. */
+typedef std::variant<
+ TextHashMethod,
+ FixedOutputHashMethod
+> ContentAddressMethod;
+
+ContentAddressMethod parseContentAddressMethod(std::string_view rawCaMethod);
+
+std::string renderContentAddressMethod(ContentAddressMethod caMethod);
+
+/*
+ * Mini content address
+ */
+
struct TextHash {
Hash hash;
+
+ GENERATE_CMP(TextHash, me->hash);
};
/// Pair of a hash, and how the file system was ingested
@@ -19,6 +60,8 @@ struct FixedOutputHash {
FileIngestionMethod method;
Hash hash;
std::string printMethodAlgo() const;
+
+ GENERATE_CMP(FixedOutputHash, me->method, me->hash);
};
/*
@@ -37,14 +80,6 @@ typedef std::variant<
FixedOutputHash // for path computed by makeFixedOutputPath
> ContentAddress;
-/* Compute the prefix to the hash algorithm which indicates how the files were
- ingested. */
-std::string makeFileIngestionPrefix(const FileIngestionMethod m);
-
-/* Compute the content-addressability assertion (ValidPathInfo::ca)
- for paths created by makeFixedOutputPath() / addToStore(). */
-std::string makeFixedOutputCA(FileIngestionMethod method, const Hash & hash);
-
std::string renderContentAddress(ContentAddress ca);
std::string renderContentAddress(std::optional<ContentAddress> ca);
@@ -55,23 +90,46 @@ std::optional<ContentAddress> parseContentAddressOpt(std::string_view rawCaOpt);
Hash getContentAddressHash(const ContentAddress & ca);
+
/*
- We only have one way to hash text with references, so this is single-value
- type is only useful in std::variant.
-*/
-struct TextHashMethod { };
-struct FixedOutputHashMethod {
- FileIngestionMethod fileIngestionMethod;
- HashType hashType;
+ * References set
+ */
+
+typedef References<StorePath> StoreReferences;
+
+/*
+ * Full content address
+ *
+ * See the schema for store paths in store-api.cc
+ */
+
+// This matches the additional info that we need for makeTextPath
+struct TextInfo : TextHash {
+ // References for the paths, self references disallowed
+ StorePathSet references;
+
+ GENERATE_CMP(TextInfo, *(const TextHash *)me, me->references);
+};
+
+struct FixedOutputInfo : FixedOutputHash {
+ // References for the paths
+ StoreReferences references;
+
+ GENERATE_CMP(FixedOutputInfo, *(const FixedOutputHash *)me, me->references);
};
typedef std::variant<
- TextHashMethod,
- FixedOutputHashMethod
- > ContentAddressMethod;
+ TextInfo,
+ FixedOutputInfo
+> ContentAddressWithReferences;
-ContentAddressMethod parseContentAddressMethod(std::string_view rawCaMethod);
+ContentAddressWithReferences caWithoutRefs(const ContentAddress &);
-std::string renderContentAddressMethod(ContentAddressMethod caMethod);
+struct StorePathDescriptor {
+ std::string name;
+ ContentAddressWithReferences info;
+
+ GENERATE_CMP(StorePathDescriptor, me->name, me->info);
+};
}
diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc
index 12596ba49..605f871fc 100644
--- a/src/libstore/daemon.cc
+++ b/src/libstore/daemon.cc
@@ -336,7 +336,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
logger->startWork();
StorePathSet paths;
if (op == wopQueryReferences)
- for (auto & i : store->queryPathInfo(path)->references)
+ for (auto & i : store->queryPathInfo(path)->referencesPossiblyToSelf())
paths.insert(i);
else if (op == wopQueryReferrers)
store->queryReferrers(path, paths);
@@ -758,7 +758,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
else {
to << 1
<< (i->second.deriver ? store->printStorePath(*i->second.deriver) : "");
- worker_proto::write(*store, to, i->second.references);
+ worker_proto::write(*store, to, i->second.references.possiblyToSelf(path));
to << i->second.downloadSize
<< i->second.narSize;
}
@@ -781,7 +781,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
for (auto & i : infos) {
to << store->printStorePath(i.first)
<< (i.second.deriver ? store->printStorePath(*i.second.deriver) : "");
- worker_proto::write(*store, to, i.second.references);
+ worker_proto::write(*store, to, i.second.references.possiblyToSelf(i.first));
to << i.second.downloadSize << i.second.narSize;
}
break;
@@ -863,7 +863,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
ValidPathInfo info { path, narHash };
if (deriver != "")
info.deriver = store->parseStorePath(deriver);
- info.references = worker_proto::read(*store, from, Phantom<StorePathSet> {});
+ info.setReferencesPossiblyToSelf(worker_proto::read(*store, from, Phantom<StorePathSet> {}));
from >> info.registrationTime >> info.narSize >> info.ultimate;
info.sigs = readStrings<StringSet>(from);
info.ca = parseContentAddressOpt(readString(from));
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index cf18724ef..135f5799b 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -35,8 +35,8 @@ std::optional<StorePath> DerivationOutput::path(const Store & store, std::string
StorePath DerivationOutput::CAFixed::path(const Store & store, std::string_view drvName, std::string_view outputName) const
{
return store.makeFixedOutputPath(
- hash.method, hash.hash,
- outputPathName(drvName, outputName));
+ outputPathName(drvName, outputName),
+ { hash, {} });
}
diff --git a/src/libstore/derived-path.hh b/src/libstore/derived-path.hh
index 4edff7467..5f2dfa4f1 100644
--- a/src/libstore/derived-path.hh
+++ b/src/libstore/derived-path.hh
@@ -6,6 +6,7 @@
#include "outputs-spec.hh"
#include <optional>
+#include <variant>
#include <nlohmann/json_fwd.hpp>
diff --git a/src/libstore/export-import.cc b/src/libstore/export-import.cc
index 9875da909..4adf51573 100644
--- a/src/libstore/export-import.cc
+++ b/src/libstore/export-import.cc
@@ -45,7 +45,7 @@ void Store::exportPath(const StorePath & path, Sink & sink)
teeSink
<< exportMagic
<< printStorePath(path);
- worker_proto::write(*this, teeSink, info->references);
+ worker_proto::write(*this, teeSink, info->referencesPossiblyToSelf());
teeSink
<< (info->deriver ? printStorePath(*info->deriver) : "")
<< 0;
@@ -80,7 +80,7 @@ StorePaths Store::importPaths(Source & source, CheckSigsFlag checkSigs)
ValidPathInfo info { path, narHash };
if (deriver != "")
info.deriver = parseStorePath(deriver);
- info.references = references;
+ info.setReferencesPossiblyToSelf(std::move(references));
info.narSize = saved.s.size();
// Ignore optional legacy signature.
diff --git a/src/libstore/legacy-ssh-store.cc b/src/libstore/legacy-ssh-store.cc
index e1a4e13a3..6a694f034 100644
--- a/src/libstore/legacy-ssh-store.cc
+++ b/src/libstore/legacy-ssh-store.cc
@@ -134,11 +134,10 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
/* Hash will be set below. FIXME construct ValidPathInfo at end. */
auto info = std::make_shared<ValidPathInfo>(path, Hash::dummy);
- PathSet references;
auto deriver = readString(conn->from);
if (deriver != "")
info->deriver = parseStorePath(deriver);
- info->references = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
+ info->setReferencesPossiblyToSelf(worker_proto::read(*this, conn->from, Phantom<StorePathSet> {}));
readLongLong(conn->from); // download size
info->narSize = readLongLong(conn->from);
@@ -172,7 +171,7 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
<< printStorePath(info.path)
<< (info.deriver ? printStorePath(*info.deriver) : "")
<< info.narHash.to_string(Base16, false);
- worker_proto::write(*this, conn->to, info.references);
+ worker_proto::write(*this, conn->to, info.referencesPossiblyToSelf());
conn->to
<< info.registrationTime
<< info.narSize
@@ -201,7 +200,7 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
conn->to
<< exportMagic
<< printStorePath(info.path);
- worker_proto::write(*this, conn->to, info.references);
+ worker_proto::write(*this, conn->to, info.referencesPossiblyToSelf());
conn->to
<< (info.deriver ? printStorePath(*info.deriver) : "")
<< 0
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index be21e3ca0..b32953f3f 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -738,7 +738,7 @@ void LocalStore::checkDerivationOutputs(const StorePath & drvPath, const Derivat
envHasRightPath(doia.path, i.first);
},
[&](const DerivationOutput::CAFixed & dof) {
- StorePath path = makeFixedOutputPath(dof.hash.method, dof.hash.hash, drvName);
+ StorePath path = makeFixedOutputPath(drvName, { dof.hash, {} });
envHasRightPath(path, i.first);
},
[&](const DerivationOutput::CAFloating &) {
@@ -938,7 +938,8 @@ std::shared_ptr<const ValidPathInfo> LocalStore::queryPathInfoInternal(State & s
auto useQueryReferences(state.stmts->QueryReferences.use()(info->id));
while (useQueryReferences.next())
- info->references.insert(parseStorePath(useQueryReferences.getStr(0)));
+ info->insertReferencePossiblyToSelf(
+ parseStorePath(useQueryReferences.getStr(0)));
return info;
}
@@ -1136,7 +1137,10 @@ void LocalStore::querySubstitutablePathInfos(const StorePathCAMap & paths, Subst
// Recompute store path so that we can use a different store root.
if (path.second) {
- subPath = makeFixedOutputPathFromCA(path.first.name(), *path.second);
+ subPath = makeFixedOutputPathFromCA({
+ .name = std::string { path.first.name() },
+ .info = caWithoutRefs(*path.second),
+ });
if (sub->storeDir == storeDir)
assert(subPath == path.first);
if (subPath != path.first)
@@ -1153,10 +1157,11 @@ void LocalStore::querySubstitutablePathInfos(const StorePathCAMap & paths, Subst
auto narInfo = std::dynamic_pointer_cast<const NarInfo>(
std::shared_ptr<const ValidPathInfo>(info));
infos.insert_or_assign(path.first, SubstitutablePathInfo{
- info->deriver,
- info->references,
- narInfo ? narInfo->fileSize : 0,
- info->narSize});
+ .deriver = info->deriver,
+ .references = info->references,
+ .downloadSize = narInfo ? narInfo->fileSize : 0,
+ .narSize = info->narSize,
+ });
} catch (InvalidPath &) {
} catch (SubstituterDisabled &) {
} catch (Error & e) {
@@ -1201,7 +1206,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
for (auto & [_, i] : infos) {
auto referrer = queryValidPathId(*state, i.path);
- for (auto & j : i.references)
+ for (auto & j : i.referencesPossiblyToSelf())
state->stmts->AddReference.use()(referrer)(queryValidPathId(*state, j)).exec();
}
@@ -1222,7 +1227,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
topoSort(paths,
{[&](const StorePath & path) {
auto i = infos.find(path);
- return i == infos.end() ? StorePathSet() : i->second.references;
+ return i == infos.end() ? StorePathSet() : i->second.references.others;
}},
{[&](const StorePath & path, const StorePath & parent) {
return BuildError(
@@ -1413,7 +1418,21 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, std::string_view name
auto [hash, size] = hashSink->finish();
- auto dstPath = makeFixedOutputPath(method, hash, name, references);
+ auto desc = StorePathDescriptor {
+ std::string { name },
+ FixedOutputInfo {
+ {
+ .method = method,
+ .hash = hash,
+ },
+ .references = {
+ .others = references,
+ .self = false,
+ },
+ },
+ };
+
+ auto dstPath = makeFixedOutputPathFromCA(desc);
addTempRoot(dstPath);
@@ -1433,7 +1452,7 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, std::string_view name
autoGC();
if (inMemory) {
- StringSource dumpSource { dump };
+ StringSource dumpSource { dump };
/* Restore from the NAR in memory. */
if (method == FileIngestionMethod::Recursive)
restorePath(realPath, dumpSource);
@@ -1457,10 +1476,8 @@ StorePath LocalStore::addToStoreFromDump(Source & source0, std::string_view name
optimisePath(realPath, repair);
- ValidPathInfo info { dstPath, narHash.first };
+ ValidPathInfo info { *this, std::move(desc), narHash.first };
info.narSize = narHash.second;
- info.references = references;
- info.ca = FixedOutputHash { .method = method, .hash = hash };
registerValidPath(info);
}
@@ -1477,7 +1494,10 @@ StorePath LocalStore::addTextToStore(
const StorePathSet & references, RepairFlag repair)
{
auto hash = hashString(htSHA256, s);
- auto dstPath = makeTextPath(name, hash, references);
+ auto dstPath = makeTextPath(name, TextInfo {
+ { .hash = hash },
+ references,
+ });
addTempRoot(dstPath);
@@ -1505,7 +1525,8 @@ StorePath LocalStore::addTextToStore(
ValidPathInfo info { dstPath, narHash };
info.narSize = sink.s.size();
- info.references = references;
+ // No self reference allowed with text-hashing
+ info.references.others = references;
info.ca = TextHash { .hash = hash };
registerValidPath(info);
}
diff --git a/src/libstore/make-content-addressed.cc b/src/libstore/make-content-addressed.cc
index 64d172918..5d7945eb1 100644
--- a/src/libstore/make-content-addressed.cc
+++ b/src/libstore/make-content-addressed.cc
@@ -27,18 +27,15 @@ std::map<StorePath, StorePath> makeContentAddressed(
StringMap rewrites;
- StorePathSet references;
- bool hasSelfReference = false;
- for (auto & ref : oldInfo->references) {
- if (ref == path)
- hasSelfReference = true;
- else {
- auto i = remappings.find(ref);
- auto replacement = i != remappings.end() ? i->second : ref;
- // FIXME: warn about unremapped paths?
- if (replacement != ref)
- rewrites.insert_or_assign(srcStore.printStorePath(ref), srcStore.printStorePath(replacement));
- references.insert(std::move(replacement));
+ StoreReferences refs;
+ refs.self = oldInfo->references.self;
+ for (auto & ref : oldInfo->references.others) {
+ auto i = remappings.find(ref);
+ auto replacement = i != remappings.end() ? i->second : ref;
+ // FIXME: warn about unremapped paths?
+ if (replacement != ref) {
+ rewrites.insert_or_assign(srcStore.printStorePath(ref), srcStore.printStorePath(replacement));
+ refs.others.insert(std::move(replacement));
}
}
@@ -49,24 +46,30 @@ std::map<StorePath, StorePath> makeContentAddressed(
auto narModuloHash = hashModuloSink.finish().first;
- auto dstPath = dstStore.makeFixedOutputPath(
- FileIngestionMethod::Recursive, narModuloHash, path.name(), references, hasSelfReference);
+ ValidPathInfo info {
+ dstStore,
+ StorePathDescriptor {
+ .name = std::string { path.name() },
+ .info = FixedOutputInfo {
+ {
+ .method = FileIngestionMethod::Recursive,
+ .hash = narModuloHash,
+ },
+ .references = std::move(refs),
+ },
+ },
+ Hash::dummy,
+ };
- printInfo("rewriting '%s' to '%s'", pathS, srcStore.printStorePath(dstPath));
+ printInfo("rewriting '%s' to '%s'", pathS, dstStore.printStorePath(info.path));
StringSink sink2;
- RewritingSink rsink2(oldHashPart, std::string(dstPath.hashPart()), sink2);
+ RewritingSink rsink2(oldHashPart, std::string(info.path.hashPart()), sink2);
rsink2(sink.s);
rsink2.flush();
- ValidPathInfo info { dstPath, hashString(htSHA256, sink2.s) };
- info.references = std::move(references);
- if (hasSelfReference) info.references.insert(info.path);
+ info.narHash = hashString(htSHA256, sink2.s);
info.narSize = sink.s.size();
- info.ca = FixedOutputHash {
- .method = FileIngestionMethod::Recursive,
- .hash = narModuloHash,
- };
StringSource source(sink2.s);
dstStore.addToStore(info, source);
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc
index 5758c3d93..70e97569a 100644
--- a/src/libstore/misc.cc
+++ b/src/libstore/misc.cc
@@ -21,16 +21,16 @@ void Store::computeFSClosure(const StorePathSet & startPaths,
StorePathSet res;
StorePathSet referrers;
queryReferrers(path, referrers);
- for (auto& ref : referrers)
+ for (auto & ref : referrers)
if (ref != path)
res.insert(ref);
if (includeOutputs)
- for (auto& i : queryValidDerivers(path))
+ for (auto & i : queryValidDerivers(path))
res.insert(i);
if (includeDerivers && path.isDerivation())
- for (auto& [_, maybeOutPath] : queryPartialDerivationOutputMap(path))
+ for (auto & [_, maybeOutPath] : queryPartialDerivationOutputMap(path))
if (maybeOutPath && isValidPath(*maybeOutPath))
res.insert(*maybeOutPath);
return res;
@@ -40,12 +40,11 @@ void Store::computeFSClosure(const StorePathSet & startPaths,
std::future<ref<const ValidPathInfo>> & fut) {
StorePathSet res;
auto info = fut.get();
- for (auto& ref : info->references)
- if (ref != path)
- res.insert(ref);
+ for (auto & ref : info->references.others)
+ res.insert(ref);
if (includeOutputs && path.isDerivation())
- for (auto& [_, maybeOutPath] : queryPartialDerivationOutputMap(path))
+ for (auto & [_, maybeOutPath] : queryPartialDerivationOutputMap(path))
if (maybeOutPath && isValidPath(*maybeOutPath))
res.insert(*maybeOutPath);
@@ -224,7 +223,7 @@ void Store::queryMissing(const std::vector<DerivedPath> & targets,
state->narSize += info->second.narSize;
}
- for (auto & ref : info->second.references)
+ for (auto & ref : info->second.references.others)
pool.enqueue(std::bind(doPath, DerivedPath::Opaque { ref }));
},
}, req.raw());
@@ -242,7 +241,7 @@ StorePaths Store::topoSortPaths(const StorePathSet & paths)
return topoSort(paths,
{[&](const StorePath & path) {
try {
- return queryPathInfo(path)->references;
+ return queryPathInfo(path)->references.others;
} catch (InvalidPath &) {
return StorePathSet();
}
@@ -298,7 +297,7 @@ std::map<DrvOutput, StorePath> drvOutputReferences(
auto info = store.queryPathInfo(outputPath);
- return drvOutputReferences(Realisation::closure(store, inputRealisations), info->references);
+ return drvOutputReferences(Realisation::closure(store, inputRealisations), info->referencesPossiblyToSelf());
}
OutputPathMap resolveDerivedPath(Store & store, const DerivedPath::Built & bfd, Store * evalStore_)
diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc
index 3e0689534..8d4a21daf 100644
--- a/src/libstore/nar-info-disk-cache.cc
+++ b/src/libstore/nar-info-disk-cache.cc
@@ -248,7 +248,7 @@ public:
narInfo->fileSize = queryNAR.getInt(5);
narInfo->narSize = queryNAR.getInt(7);
for (auto & r : tokenizeString<Strings>(queryNAR.getStr(8), " "))
- narInfo->references.insert(StorePath(r));
+ narInfo->insertReferencePossiblyToSelf(StorePath(r));
if (!queryNAR.isNull(9))
narInfo->deriver = StorePath(queryNAR.getStr(9));
for (auto & sig : tokenizeString<Strings>(queryNAR.getStr(10), " "))
diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc
index 071d8355e..f54e8f1fc 100644
--- a/src/libstore/nar-info.cc
+++ b/src/libstore/nar-info.cc
@@ -63,7 +63,7 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
auto refs = tokenizeString<Strings>(value, " ");
if (!references.empty()) throw corrupt();
for (auto & r : refs)
- references.insert(StorePath(r));
+ insertReferencePossiblyToSelf(StorePath(r));
}
else if (name == "Deriver") {
if (value != "unknown-deriver")
diff --git a/src/libstore/nar-info.hh b/src/libstore/nar-info.hh
index 01683ec73..f1e3aabbd 100644
--- a/src/libstore/nar-info.hh
+++ b/src/libstore/nar-info.hh
@@ -16,6 +16,9 @@ struct NarInfo : ValidPathInfo
uint64_t fileSize = 0;
NarInfo() = delete;
+ NarInfo(const Store & store, StorePathDescriptor && ca, Hash narHash)
+ : ValidPathInfo(store, std::move(ca), narHash)
+ { }
NarInfo(StorePath && path, Hash narHash) : ValidPathInfo(std::move(path), narHash) { }
NarInfo(const ValidPathInfo & info) : ValidPathInfo(info) { }
NarInfo(const Store & store, const std::string & s, const std::string & whence);
diff --git a/src/libstore/path-info.cc b/src/libstore/path-info.cc
index bd55a9d06..2972c0bbe 100644
--- a/src/libstore/path-info.cc
+++ b/src/libstore/path-info.cc
@@ -12,7 +12,7 @@ std::string ValidPathInfo::fingerprint(const Store & store) const
"1;" + store.printStorePath(path) + ";"
+ narHash.to_string(Base32, true) + ";"
+ std::to_string(narSize) + ";"
- + concatStringsSep(",", store.printStorePathSet(references));
+ + concatStringsSep(",", store.printStorePathSet(referencesPossiblyToSelf()));
}
@@ -21,25 +21,39 @@ void ValidPathInfo::sign(const Store & store, const SecretKey & secretKey)
sigs.insert(secretKey.signDetached(fingerprint(store)));
}
+std::optional<StorePathDescriptor> ValidPathInfo::fullStorePathDescriptorOpt() const
+{
+ if (! ca)
+ return std::nullopt;
+
+ return StorePathDescriptor {
+ .name = std::string { path.name() },
+ .info = std::visit(overloaded {
+ [&](const TextHash & th) -> ContentAddressWithReferences {
+ assert(!references.self);
+ return TextInfo {
+ th,
+ .references = references.others,
+ };
+ },
+ [&](const FixedOutputHash & foh) -> ContentAddressWithReferences {
+ return FixedOutputInfo {
+ foh,
+ .references = references,
+ };
+ },
+ }, *ca),
+ };
+}
bool ValidPathInfo::isContentAddressed(const Store & store) const
{
- if (! ca) return false;
+ auto fullCaOpt = fullStorePathDescriptorOpt();
- auto caPath = std::visit(overloaded {
- [&](const TextHash & th) {
- return store.makeTextPath(path.name(), th.hash, references);
- },
- [&](const FixedOutputHash & fsh) {
- auto refs = references;
- bool hasSelfReference = false;
- if (refs.count(path)) {
- hasSelfReference = true;
- refs.erase(path);
- }
- return store.makeFixedOutputPath(fsh.method, fsh.hash, path.name(), refs, hasSelfReference);
- }
- }, *ca);
+ if (! fullCaOpt)
+ return false;
+
+ auto caPath = store.makeFixedOutputPathFromCA(*fullCaOpt);
bool res = caPath == path;
@@ -71,12 +85,51 @@ bool ValidPathInfo::checkSignature(const Store & store, const PublicKeys & publi
Strings ValidPathInfo::shortRefs() const
{
Strings refs;
- for (auto & r : references)
+ for (auto & r : referencesPossiblyToSelf())
refs.push_back(std::string(r.to_string()));
return refs;
}
+ValidPathInfo::ValidPathInfo(
+ const Store & store,
+ StorePathDescriptor && info,
+ Hash narHash)
+ : path(store.makeFixedOutputPathFromCA(info))
+ , narHash(narHash)
+{
+ std::visit(overloaded {
+ [this](TextInfo && ti) {
+ this->references = {
+ .others = std::move(ti.references),
+ .self = false,
+ };
+ this->ca = std::move((TextHash &&) ti);
+ },
+ [this](FixedOutputInfo && foi) {
+ this->references = std::move(foi.references);
+ this->ca = std::move((FixedOutputHash &&) foi);
+ },
+ }, std::move(info.info));
+}
+
+
+StorePathSet ValidPathInfo::referencesPossiblyToSelf() const
+{
+ return references.possiblyToSelf(path);
+}
+
+void ValidPathInfo::insertReferencePossiblyToSelf(StorePath && ref)
+{
+ return references.insertPossiblyToSelf(path, std::move(ref));
+}
+
+void ValidPathInfo::setReferencesPossiblyToSelf(StorePathSet && refs)
+{
+ return references.setPossiblyToSelf(path, std::move(refs));
+}
+
+
ValidPathInfo ValidPathInfo::read(Source & source, const Store & store, unsigned int format)
{
return read(source, store, format, store.parseStorePath(readString(source)));
@@ -88,7 +141,7 @@ ValidPathInfo ValidPathInfo::read(Source & source, const Store & store, unsigned
auto narHash = Hash::parseAny(readString(source), htSHA256);
ValidPathInfo info(path, narHash);
if (deriver != "") info.deriver = store.parseStorePath(deriver);
- info.references = worker_proto::read(store, source, Phantom<StorePathSet> {});
+ info.setReferencesPossiblyToSelf(worker_proto::read(store, source, Phantom<StorePathSet> {}));
source >> info.registrationTime >> info.narSize;
if (format >= 16) {
source >> info.ultimate;
@@ -109,7 +162,7 @@ void ValidPathInfo::write(
sink << store.printStorePath(path);
sink << (deriver ? store.printStorePath(*deriver) : "")
<< narHash.to_string(Base16, false);
- worker_proto::write(store, sink, references);
+ worker_proto::write(store, sink, referencesPossiblyToSelf());
sink << registrationTime << narSize;
if (format >= 16) {
sink << ultimate
diff --git a/src/libstore/path-info.hh b/src/libstore/path-info.hh
index b4b54e593..9254835b7 100644
--- a/src/libstore/path-info.hh
+++ b/src/libstore/path-info.hh
@@ -17,21 +17,19 @@ class Store;
struct SubstitutablePathInfo
{
std::optional<StorePath> deriver;
- StorePathSet references;
+ StoreReferences references;
uint64_t downloadSize; /* 0 = unknown or inapplicable */
uint64_t narSize; /* 0 = unknown */
};
typedef std::map<StorePath, SubstitutablePathInfo> SubstitutablePathInfos;
-
struct ValidPathInfo
{
StorePath path;
std::optional<StorePath> deriver;
- // TODO document this
Hash narHash;
- StorePathSet references;
+ StoreReferences references;
time_t registrationTime = 0;
uint64_t narSize = 0; // 0 = unknown
uint64_t id; // internal use only
@@ -78,6 +76,8 @@ struct ValidPathInfo
void sign(const Store & store, const SecretKey & secretKey);
+ std::optional<StorePathDescriptor> fullStorePathDescriptorOpt() const;
+
/* Return true iff the path is verifiably content-addressed. */
bool isContentAddressed(const Store & store) const;
@@ -104,6 +104,9 @@ struct ValidPathInfo
ValidPathInfo(StorePath && path, Hash narHash) : path(std::move(path)), narHash(narHash) { };
ValidPathInfo(const StorePath & path, Hash narHash) : path(path), narHash(narHash) { };
+ ValidPathInfo(const Store & store,
+ StorePathDescriptor && ca, Hash narHash);
+
virtual ~ValidPathInfo() { }
static ValidPathInfo read(Source & source, const Store & store, unsigned int format);
diff --git a/src/libstore/path.hh b/src/libstore/path.hh
index 0694b4c18..7f13c11e9 100644
--- a/src/libstore/path.hh
+++ b/src/libstore/path.hh
@@ -1,6 +1,7 @@
#pragma once
-#include "content-address.hh"
+#include <string_view>
+
#include "types.hh"
namespace nix {
@@ -65,8 +66,6 @@ public:
typedef std::set<StorePath> StorePathSet;
typedef std::vector<StorePath> StorePaths;
-typedef std::map<StorePath, std::optional<ContentAddress>> StorePathCAMap;
-
/* Extension of derivations in the Nix store. */
const std::string drvExtension = ".drv";
diff --git a/src/libstore/realisation.hh b/src/libstore/realisation.hh
index 911c61909..9429c7004 100644
--- a/src/libstore/realisation.hh
+++ b/src/libstore/realisation.hh
@@ -1,5 +1,8 @@
#pragma once
+#include <variant>
+
+#include "hash.hh"
#include "path.hh"
#include <nlohmann/json_fwd.hpp>
#include "comparator.hh"
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index ff57a77ca..8ea126c65 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -402,7 +402,7 @@ void RemoteStore::querySubstitutablePathInfos(const StorePathCAMap & pathsMap, S
auto deriver = readString(conn->from);
if (deriver != "")
info.deriver = parseStorePath(deriver);
- info.references = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
+ info.references.setPossiblyToSelf(i.first, worker_proto::read(*this, conn->from, Phantom<StorePathSet> {}));
info.downloadSize = readLongLong(conn->from);
info.narSize = readLongLong(conn->from);
infos.insert_or_assign(i.first, std::move(info));
@@ -421,11 +421,12 @@ void RemoteStore::querySubstitutablePathInfos(const StorePathCAMap & pathsMap, S
conn.processStderr();
size_t count = readNum<size_t>(conn->from);
for (size_t n = 0; n < count; n++) {
- SubstitutablePathInfo & info(infos[parseStorePath(readString(conn->from))]);
+ auto path = parseStorePath(readString(conn->from));
+ SubstitutablePathInfo & info { infos[path] };
auto deriver = readString(conn->from);
if (deriver != "")
info.deriver = parseStorePath(deriver);
- info.references = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
+ info.references.setPossiblyToSelf(path, worker_proto::read(*this, conn->from, Phantom<StorePathSet> {}));
info.downloadSize = readLongLong(conn->from);
info.narSize = readLongLong(conn->from);
}
@@ -633,7 +634,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
sink
<< exportMagic
<< printStorePath(info.path);
- worker_proto::write(*this, sink, info.references);
+ worker_proto::write(*this, sink, info.referencesPossiblyToSelf());
sink
<< (info.deriver ? printStorePath(*info.deriver) : "")
<< 0 // == no legacy signature
@@ -644,7 +645,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
conn.processStderr(0, source2.get());
auto importedPaths = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
- assert(importedPaths.size() <= 1);
+ assert(importedPaths.empty() == 0); // doesn't include possible self reference
}
else {
@@ -652,7 +653,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
<< printStorePath(info.path)
<< (info.deriver ? printStorePath(*info.deriver) : "")
<< info.narHash.to_string(Base16, false);
- worker_proto::write(*this, conn->to, info.references);
+ worker_proto::write(*this, conn->to, info.referencesPossiblyToSelf());
conn->to << info.registrationTime << info.narSize
<< info.ultimate << info.sigs << renderContentAddress(info.ca)
<< repair << !checkSigs;
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index 5130409d4..9446ad132 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -7,6 +7,7 @@
#include "nar-info-disk-cache.hh"
#include "thread-pool.hh"
#include "url.hh"
+#include "references.hh"
#include "archive.hh"
#include "callback.hh"
#include "remote-store.hh"
@@ -162,63 +163,60 @@ StorePath Store::makeOutputPath(std::string_view id,
}
+/* Stuff the references (if any) into the type. This is a bit
+ hacky, but we can't put them in `s' since that would be
+ ambiguous. */
static std::string makeType(
const Store & store,
std::string && type,
- const StorePathSet & references,
- bool hasSelfReference = false)
+ const StoreReferences & references)
{
- for (auto & i : references) {
+ for (auto & i : references.others) {
type += ":";
type += store.printStorePath(i);
}
- if (hasSelfReference) type += ":self";
+ if (references.self) type += ":self";
return std::move(type);
}
-StorePath Store::makeFixedOutputPath(
- FileIngestionMethod method,
- const Hash & hash,
- std::string_view name,
- const StorePathSet & references,
- bool hasSelfReference) const
+StorePath Store::makeFixedOutputPath(std::string_view name, const FixedOutputInfo & info) const
{
- if (hash.type == htSHA256 && method == FileIngestionMethod::Recursive) {
- return makeStorePath(makeType(*this, "source", references, hasSelfReference), hash, name);
+ if (info.hash.type == htSHA256 && info.method == FileIngestionMethod::Recursive) {
+ return makeStorePath(makeType(*this, "source", info.references), info.hash, name);
} else {
- assert(references.empty());
+ assert(info.references.size() == 0);
return makeStorePath("output:out",
hashString(htSHA256,
"fixed:out:"
- + makeFileIngestionPrefix(method)
- + hash.to_string(Base16, true) + ":"),
+ + makeFileIngestionPrefix(info.method)
+ + info.hash.to_string(Base16, true) + ":"),
name);
}
}
-StorePath Store::makeFixedOutputPathFromCA(std::string_view name, ContentAddress ca,
- const StorePathSet & references, bool hasSelfReference) const
+
+StorePath Store::makeTextPath(std::string_view name, const TextInfo & info) const
+{
+ assert(info.hash.type == htSHA256);
+ return makeStorePath(
+ makeType(*this, "text", StoreReferences { info.references }),
+ info.hash,
+ name);
+}
+
+
+StorePath Store::makeFixedOutputPathFromCA(const StorePathDescriptor & desc) const
{
// New template
return std::visit(overloaded {
- [&](const TextHash & th) {
- return makeTextPath(name, th.hash, references);
+ [&](const TextInfo & ti) {
+ return makeTextPath(desc.name, ti);
},
- [&](const FixedOutputHash & fsh) {
- return makeFixedOutputPath(fsh.method, fsh.hash, name, references, hasSelfReference);
+ [&](const FixedOutputInfo & foi) {
+ return makeFixedOutputPath(desc.name, foi);
}
- }, ca);
-}
-
-StorePath Store::makeTextPath(std::string_view name, const Hash & hash,
- const StorePathSet & references) const
-{
- assert(hash.type == htSHA256);
- /* Stuff the references (if any) into the type. This is a bit
- hacky, but we can't put them in `s' since that would be
- ambiguous. */
- return makeStorePath(makeType(*this, "text", references), hash, name);
+ }, desc.info);
}
@@ -228,7 +226,14 @@ std::pair<StorePath, Hash> Store::computeStorePathForPath(std::string_view name,
Hash h = method == FileIngestionMethod::Recursive
? hashPath(hashAlgo, srcPath, filter).first
: hashFile(hashAlgo, srcPath);
- return std::make_pair(makeFixedOutputPath(method, h, name), h);
+ FixedOutputInfo caInfo {
+ {
+ .method = method,
+ .hash = h,
+ },
+ .references = {},
+ };
+ return std::make_pair(makeFixedOutputPath(name, caInfo), h);
}
@@ -237,7 +242,10 @@ StorePath Store::computeStorePathForText(
std::string_view s,
const StorePathSet & references) const
{
- return makeTextPath(name, hashString(htSHA256, s), references);
+ return makeTextPath(name, TextInfo {
+ { .hash = hashString(htSHA256, s) },
+ references,
+ });
}
@@ -302,7 +310,7 @@ void Store::addMultipleToStore(
bytesExpected += info.narSize;
act.setExpected(actCopyPath, bytesExpected);
- return info.references;
+ return info.references.others;
},
[&](const StorePath & path) {
@@ -425,11 +433,20 @@ ValidPathInfo Store::addToStoreSlow(std::string_view name, const Path & srcPath,
throw Error("hash mismatch for '%s'", srcPath);
ValidPathInfo info {
- makeFixedOutputPath(method, hash, name),
+ *this,
+ StorePathDescriptor {
+ std::string { name },
+ FixedOutputInfo {
+ {
+ .method = method,
+ .hash = hash,
+ },
+ .references = {},
+ },
+ },
narHash,
};
info.narSize = narSize;
- info.ca = FixedOutputHash { .method = method, .hash = hash };
if (!isValidPath(info.path)) {
auto source = sinkToSource([&](Sink & scratchpadSink) {
@@ -742,13 +759,13 @@ StorePathSet Store::queryValidPaths(const StorePathSet & paths, SubstituteFlag m
std::condition_variable wakeup;
ThreadPool pool;
- auto doQuery = [&](const Path & path) {
+ auto doQuery = [&](const StorePath & path) {
checkInterrupt();
- queryPathInfo(parseStorePath(path), {[path, this, &state_, &wakeup](std::future<ref<const ValidPathInfo>> fut) {
+ queryPathInfo(path, {[path, this, &state_, &wakeup](std::future<ref<const ValidPathInfo>> fut) {
auto state(state_.lock());
try {
auto info = fut.get();
- state->valid.insert(parseStorePath(path));
+ state->valid.insert(path);
} catch (InvalidPath &) {
} catch (...) {
state->exc = std::current_exception();
@@ -760,7 +777,7 @@ StorePathSet Store::queryValidPaths(const StorePathSet & paths, SubstituteFlag m
};
for (auto & path : paths)
- pool.enqueue(std::bind(doQuery, printStorePath(path))); // FIXME
+ pool.enqueue(std::bind(doQuery, path));
pool.process();
@@ -798,7 +815,7 @@ std::string Store::makeValidityRegistration(const StorePathSet & paths,
s += (format("%1%\n") % info->references.size()).str();
- for (auto & j : info->references)
+ for (auto & j : info->referencesPossiblyToSelf())
s += printStorePath(j) + "\n";
}
@@ -860,7 +877,7 @@ json Store::pathInfoToJSON(const StorePathSet & storePaths,
{
auto& jsonRefs = (jsonPath["references"] = json::array());
- for (auto & ref : info->references)
+ for (auto & ref : info->referencesPossiblyToSelf())
jsonRefs.emplace_back(printStorePath(ref));
}
@@ -976,7 +993,8 @@ void copyStorePath(
// recompute store path on the chance dstStore does it differently
if (info->ca && info->references.empty()) {
auto info2 = make_ref<ValidPathInfo>(*info);
- info2->path = dstStore.makeFixedOutputPathFromCA(info->path.name(), *info->ca);
+ info2->path = dstStore.makeFixedOutputPathFromCA(
+ info->fullStorePathDescriptorOpt().value());
if (dstStore.storeDir == srcStore.storeDir)
assert(info->path == info2->path);
info = info2;
@@ -1088,7 +1106,8 @@ std::map<StorePath, StorePath> copyPaths(
auto storePathForSrc = currentPathInfo.path;
auto storePathForDst = storePathForSrc;
if (currentPathInfo.ca && currentPathInfo.references.empty()) {
- storePathForDst = dstStore.makeFixedOutputPathFromCA(storePathForSrc.name(), *currentPathInfo.ca);
+ storePathForDst = dstStore.makeFixedOutputPathFromCA(
+ currentPathInfo.fullStorePathDescriptorOpt().value());
if (dstStore.storeDir == srcStore.storeDir)
assert(storePathForDst == storePathForSrc);
if (storePathForDst != storePathForSrc)
@@ -1186,7 +1205,7 @@ std::optional<ValidPathInfo> decodeValidPathInfo(const Store & store, std::istre
if (!n) throw Error("number expected");
while ((*n)--) {
getline(str, s);
- info.references.insert(store.parseStorePath(s));
+ info.insertReferencePossiblyToSelf(store.parseStorePath(s));
}
if (!str || str.eof()) throw Error("missing input");
return std::optional<ValidPathInfo>(std::move(info));
@@ -1209,7 +1228,6 @@ std::string showPaths(const PathSet & paths)
return concatStringsSep(", ", quoteStrings(paths));
}
-
Derivation Store::derivationFromPath(const StorePath & drvPath)
{
ensurePath(drvPath);
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 9eab4b4e5..d77aea338 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -87,6 +87,8 @@ enum BuildMode { bmNormal, bmRepair, bmCheck };
struct BuildResult;
+typedef std::map<StorePath, std::optional<ContentAddress>> StorePathCAMap;
+
struct StoreConfig : public Config
{
using Config::Config;
@@ -210,17 +212,11 @@ public:
StorePath makeOutputPath(std::string_view id,
const Hash & hash, std::string_view name) const;
- StorePath makeFixedOutputPath(FileIngestionMethod method,
- const Hash & hash, std::string_view name,
- const StorePathSet & references = {},
- bool hasSelfReference = false) const;
+ StorePath makeFixedOutputPath(std::string_view name, const FixedOutputInfo & info) const;
- StorePath makeTextPath(std::string_view name, const Hash & hash,
- const StorePathSet & references = {}) const;
+ StorePath makeTextPath(std::string_view name, const TextInfo & info) const;
- StorePath makeFixedOutputPathFromCA(std::string_view name, ContentAddress ca,
- const StorePathSet & references = {},
- bool hasSelfReference = false) const;
+ StorePath makeFixedOutputPathFromCA(const StorePathDescriptor & info) const;
/* This is the preparatory part of addToStore(); it computes the
store path to which srcPath is to be copied. Returns the store
diff --git a/src/libutil/reference-set.hh b/src/libutil/reference-set.hh
new file mode 100644
index 000000000..ac4a9994e
--- /dev/null
+++ b/src/libutil/reference-set.hh
@@ -0,0 +1,68 @@
+#pragma once
+
+#include "comparator.hh"
+
+#include <set>
+
+namespace nix {
+
+template<typename Ref>
+struct References
+{
+ std::set<Ref> others;
+ bool self = false;
+
+ bool empty() const;
+ size_t size() const;
+
+ /* Functions to view references + self as one set, mainly for
+ compatibility's sake. */
+ std::set<Ref> possiblyToSelf(const Ref & self) const;
+ void insertPossiblyToSelf(const Ref & self, Ref && ref);
+ void setPossiblyToSelf(const Ref & self, std::set<Ref> && refs);
+
+ GENERATE_CMP(References<Ref>, me->others, me->self);
+};
+
+template<typename Ref>
+bool References<Ref>::empty() const
+{
+ return !self && others.empty();
+}
+
+template<typename Ref>
+size_t References<Ref>::size() const
+{
+ return (self ? 1 : 0) + others.size();
+}
+
+template<typename Ref>
+std::set<Ref> References<Ref>::possiblyToSelf(const Ref & selfRef) const
+{
+ std::set<Ref> refs { others };
+ if (self)
+ refs.insert(selfRef);
+ return refs;
+}
+
+template<typename Ref>
+void References<Ref>::insertPossiblyToSelf(const Ref & selfRef, Ref && ref)
+{
+ if (ref == selfRef)
+ self = true;
+ else
+ others.insert(std::move(ref));
+}
+
+template<typename Ref>
+void References<Ref>::setPossiblyToSelf(const Ref & selfRef, std::set<Ref> && refs)
+{
+ if (refs.count(selfRef)) {
+ self = true;
+ refs.erase(selfRef);
+ }
+
+ others = refs;
+}
+
+}
diff --git a/src/nix-store/dotgraph.cc b/src/nix-store/dotgraph.cc
index 577cadceb..36d774dca 100644
--- a/src/nix-store/dotgraph.cc
+++ b/src/nix-store/dotgraph.cc
@@ -56,7 +56,7 @@ void printDotGraph(ref<Store> store, StorePathSet && roots)
cout << makeNode(std::string(path.to_string()), path.name(), "#ff0000");
- for (auto & p : store->queryPathInfo(path)->references) {
+ for (auto & p : store->queryPathInfo(path)->referencesPossiblyToSelf()) {
if (p != path) {
workList.insert(p);
cout << makeEdge(std::string(p.to_string()), std::string(path.to_string()));
diff --git a/src/nix-store/graphml.cc b/src/nix-store/graphml.cc
index 425d61e53..d2eebca7a 100644
--- a/src/nix-store/graphml.cc
+++ b/src/nix-store/graphml.cc
@@ -71,7 +71,7 @@ void printGraphML(ref<Store> store, StorePathSet && roots)
auto info = store->queryPathInfo(path);
cout << makeNode(*info);
- for (auto & p : info->references) {
+ for (auto & p : info->referencesPossiblyToSelf()) {
if (p != path) {
workList.insert(p);
cout << makeEdge(path.to_string(), p.to_string());
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index 3bbefedbe..5cb5aa53a 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -201,10 +201,10 @@ static void opAddFixed(Strings opFlags, Strings opArgs)
/* Hack to support caching in `nix-prefetch-url'. */
static void opPrintFixedPath(Strings opFlags, Strings opArgs)
{
- auto recursive = FileIngestionMethod::Flat;
+ auto method = FileIngestionMethod::Flat;
for (auto i : opFlags)
- if (i == "--recursive") recursive = FileIngestionMethod::Recursive;
+ if (i == "--recursive") method = FileIngestionMethod::Recursive;
else throw UsageError("unknown flag '%1%'", i);
if (opArgs.size() != 3)
@@ -215,7 +215,13 @@ static void opPrintFixedPath(Strings opFlags, Strings opArgs)
std::string hash = *i++;
std::string name = *i++;
- cout << fmt("%s\n", store->printStorePath(store->makeFixedOutputPath(recursive, Hash::parseAny(hash, hashAlgo), name)));
+ cout << fmt("%s\n", store->printStorePath(store->makeFixedOutputPath(name, FixedOutputInfo {
+ {
+ .method = method,
+ .hash = Hash::parseAny(hash, hashAlgo),
+ },
+ .references = {},
+ })));
}
@@ -257,7 +263,7 @@ static void printTree(const StorePath & path,
closure(B). That is, if derivation A is an (possibly indirect)
input of B, then A is printed first. This has the effect of
flattening the tree, preventing deeply nested structures. */
- auto sorted = store->topoSortPaths(info->references);
+ auto sorted = store->topoSortPaths(info->referencesPossiblyToSelf());
reverse(sorted.begin(), sorted.end());
for (const auto &[n, i] : enumerate(sorted)) {
@@ -338,7 +344,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (auto & j : ps) {
if (query == qRequisites) store->computeFSClosure(j, paths, false, includeOutputs);
else if (query == qReferences) {
- for (auto & p : store->queryPathInfo(j)->references)
+ for (auto & p : store->queryPathInfo(j)->referencesPossiblyToSelf())
paths.insert(p);
}
else if (query == qReferrers) {
@@ -861,7 +867,7 @@ static void opServe(Strings opFlags, Strings opArgs)
auto info = store->queryPathInfo(i);
out << store->printStorePath(info->path)
<< (info->deriver ? store->printStorePath(*info->deriver) : "");
- worker_proto::write(*store, out, info->references);
+ worker_proto::write(*store, out, info->referencesPossiblyToSelf());
// !!! Maybe we want compression?
out << info->narSize // downloadSize
<< info->narSize;
@@ -958,7 +964,7 @@ static void opServe(Strings opFlags, Strings opArgs)
};
if (deriver != "")
info.deriver = store->parseStorePath(deriver);
- info.references = worker_proto::read(*store, in, Phantom<StorePathSet> {});
+ info.setReferencesPossiblyToSelf(worker_proto::read(*store, in, Phantom<StorePathSet> {}));
in >> info.registrationTime >> info.narSize >> info.ultimate;
info.sigs = readStrings<StringSet>(in);
info.ca = parseContentAddressOpt(readString(in));
diff --git a/src/nix/add-to-store.cc b/src/nix/add-to-store.cc
index 5168413d2..0b58818c3 100644
--- a/src/nix/add-to-store.cc
+++ b/src/nix/add-to-store.cc
@@ -42,14 +42,20 @@ struct CmdAddToStore : MixDryRun, StoreCommand
}
ValidPathInfo info {
- store->makeFixedOutputPath(ingestionMethod, hash, *namePart),
+ *store,
+ StorePathDescriptor {
+ .name = *namePart,
+ .info = FixedOutputInfo {
+ {
+ .method = std::move(ingestionMethod),
+ .hash = std::move(hash),
+ },
+ .references = {},
+ },
+ },
narHash,
};
info.narSize = sink.s.size();
- info.ca = std::optional { FixedOutputHash {
- .method = ingestionMethod,
- .hash = hash,
- } };
if (!dryRun) {
auto source = StringSource(sink.s);
diff --git a/src/nix/prefetch.cc b/src/nix/prefetch.cc
index fc3823406..df9933d29 100644
--- a/src/nix/prefetch.cc
+++ b/src/nix/prefetch.cc
@@ -67,7 +67,13 @@ std::tuple<StorePath, Hash> prefetchFile(
the store. */
if (expectedHash) {
hashType = expectedHash->type;
- storePath = store->makeFixedOutputPath(ingestionMethod, *expectedHash, *name);
+ storePath = store->makeFixedOutputPath(*name, FixedOutputInfo {
+ {
+ .method = ingestionMethod,
+ .hash = *expectedHash,
+ },
+ .references = {},
+ });
if (store->isValidPath(*storePath))
hash = expectedHash;
else
diff --git a/src/nix/profile.cc b/src/nix/profile.cc
index 32364e720..aac8e5c81 100644
--- a/src/nix/profile.cc
+++ b/src/nix/profile.cc
@@ -199,12 +199,23 @@ struct ProfileManifest
auto narHash = hashString(htSHA256, sink.s);
ValidPathInfo info {
- store->makeFixedOutputPath(FileIngestionMethod::Recursive, narHash, "profile", references),
+ *store,
+ StorePathDescriptor {
+ "profile",
+ FixedOutputInfo {
+ {
+ .method = FileIngestionMethod::Recursive,
+ .hash = narHash,
+ },
+ .references = {
+ .others = std::move(references),
+ .self = false,
+ },
+ },
+ },
narHash,
};
- info.references = std::move(references);
info.narSize = sink.s.size();
- info.ca = FixedOutputHash { .method = FileIngestionMethod::Recursive, .hash = info.narHash };
StringSource source(sink.s);
store->addToStore(info, source);
diff --git a/src/nix/verify.cc b/src/nix/verify.cc
index efa2434dc..0b306cc11 100644
--- a/src/nix/verify.cc
+++ b/src/nix/verify.cc
@@ -81,14 +81,14 @@ struct CmdVerify : StorePathsCommand
ThreadPool pool;
- auto doPath = [&](const Path & storePath) {
+ auto doPath = [&](const StorePath & storePath) {
try {
checkInterrupt();
MaintainCount<std::atomic<size_t>> mcActive(active);
update();
- auto info = store->queryPathInfo(store->parseStorePath(storePath));
+ auto info = store->queryPathInfo(storePath);
// Note: info->path can be different from storePath
// for binary cache stores when using --all (since we
@@ -173,7 +173,7 @@ struct CmdVerify : StorePathsCommand
};
for (auto & storePath : storePaths)
- pool.enqueue(std::bind(doPath, store->printStorePath(storePath)));
+ pool.enqueue(std::bind(doPath, storePath));
pool.process();
diff --git a/src/nix/why-depends.cc b/src/nix/why-depends.cc
index 76125e5e4..33cd13600 100644
--- a/src/nix/why-depends.cc
+++ b/src/nix/why-depends.cc
@@ -136,7 +136,7 @@ struct CmdWhyDepends : SourceExprCommand
for (auto & path : closure)
graph.emplace(path, Node {
.path = path,
- .refs = store->queryPathInfo(path)->references,
+ .refs = store->queryPathInfo(path)->references.others,
.dist = path == dependencyPath ? 0 : inf
});