Make ValidPathInfo have plain StorePathSet references like before

This change can wait for another PR.
This commit is contained in:
John Ericson 2023-01-14 16:38:43 -05:00
parent 056cc1c1b9
commit b3d91239ae
24 changed files with 109 additions and 166 deletions

View File

@ -69,7 +69,7 @@ int isValidPath(char * path)
SV * queryReferences(char * path) SV * queryReferences(char * path)
PPCODE: PPCODE:
try { try {
for (auto & i : store()->queryPathInfo(store()->parseStorePath(path))->referencesPossiblyToSelf()) for (auto & i : store()->queryPathInfo(store()->parseStorePath(path))->references)
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0))); XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0)));
} catch (Error & e) { } catch (Error & e) {
croak("%s", e.what()); croak("%s", e.what());
@ -110,7 +110,7 @@ SV * queryPathInfo(char * path, int base32)
mXPUSHi(info->registrationTime); mXPUSHi(info->registrationTime);
mXPUSHi(info->narSize); mXPUSHi(info->narSize);
AV * refs = newAV(); AV * refs = newAV();
for (auto & i : info->referencesPossiblyToSelf()) for (auto & i : info->references)
av_push(refs, newSVpv(store()->printStorePath(i).c_str(), 0)); av_push(refs, newSVpv(store()->printStorePath(i).c_str(), 0));
XPUSHs(sv_2mortal(newRV((SV *) refs))); XPUSHs(sv_2mortal(newRV((SV *) refs)));
AV * sigs = newAV(); AV * sigs = newAV();

View File

@ -1544,8 +1544,7 @@ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, V
StorePathSet refs; StorePathSet refs;
if (state.store->isInStore(path)) { if (state.store->isInStore(path)) {
try { try {
// FIXME: Are self references becoming non-self references OK? refs = state.store->queryPathInfo(state.store->toStorePath(path).first)->references;
refs = state.store->queryPathInfo(state.store->toStorePath(path).first)->referencesPossiblyToSelf();
} catch (Error &) { // FIXME: should be InvalidPathError } catch (Error &) { // FIXME: should be InvalidPathError
} }
// Re-scan references to filter down to just the ones that actually occur in the file. // Re-scan references to filter down to just the ones that actually occur in the file.
@ -1980,7 +1979,7 @@ static void addPath(
try { try {
auto [storePath, subPath] = state.store->toStorePath(path); auto [storePath, subPath] = state.store->toStorePath(path);
// FIXME: we should scanForReferences on the path before adding it // FIXME: we should scanForReferences on the path before adding it
refs = state.store->queryPathInfo(storePath)->referencesPossiblyToSelf(); refs = state.store->queryPathInfo(storePath)->references;
path = state.store->toRealPath(storePath) + subPath; path = state.store->toRealPath(storePath) + subPath;
} catch (Error &) { // FIXME: should be InvalidPathError } catch (Error &) { // FIXME: should be InvalidPathError
} }

View File

@ -180,11 +180,11 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
duration); duration);
/* Verify that all references are valid. This may do some .narinfo /* Verify that all references are valid. This may do some .narinfo
reads, but typically they'll already be cached. Note that reads, but typically they'll already be cached. */
self-references are always valid. */ for (auto & ref : info.references)
for (auto & ref : info.references.others)
try { try {
queryPathInfo(ref); if (ref != info.path)
queryPathInfo(ref);
} catch (InvalidPath &) { } catch (InvalidPath &) {
throw Error("cannot add '%s' to the binary cache because the reference '%s' is not valid", throw Error("cannot add '%s' to the binary cache because the reference '%s' is not valid",
printStorePath(info.path), printStorePath(ref)); printStorePath(info.path), printStorePath(ref));

View File

@ -2523,7 +2523,10 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
auto narHashAndSize = hashPath(htSHA256, actualPath); auto narHashAndSize = hashPath(htSHA256, actualPath);
ValidPathInfo newInfo0 { requiredFinalPath, narHashAndSize.first }; ValidPathInfo newInfo0 { requiredFinalPath, narHashAndSize.first };
newInfo0.narSize = narHashAndSize.second; newInfo0.narSize = narHashAndSize.second;
newInfo0.references = rewriteRefs(); auto refs = rewriteRefs();
newInfo0.references = std::move(refs.others);
if (refs.self)
newInfo0.references.insert(newInfo0.path);
return newInfo0; return newInfo0;
}, },
@ -2774,12 +2777,12 @@ void LocalDerivationGoal::checkOutputs(const std::map<std::string, ValidPathInfo
auto i = outputsByPath.find(worker.store.printStorePath(path)); auto i = outputsByPath.find(worker.store.printStorePath(path));
if (i != outputsByPath.end()) { if (i != outputsByPath.end()) {
closureSize += i->second.narSize; closureSize += i->second.narSize;
for (auto & ref : i->second.referencesPossiblyToSelf()) for (auto & ref : i->second.references)
pathsLeft.push(ref); pathsLeft.push(ref);
} else { } else {
auto info = worker.store.queryPathInfo(path); auto info = worker.store.queryPathInfo(path);
closureSize += info->narSize; closureSize += info->narSize;
for (auto & ref : info->referencesPossiblyToSelf()) for (auto & ref : info->references)
pathsLeft.push(ref); pathsLeft.push(ref);
} }
} }
@ -2819,7 +2822,7 @@ void LocalDerivationGoal::checkOutputs(const std::map<std::string, ValidPathInfo
auto used = recursive auto used = recursive
? getClosure(info.path).first ? getClosure(info.path).first
: info.referencesPossiblyToSelf(); : info.references;
if (recursive && checks.ignoreSelfRefs) if (recursive && checks.ignoreSelfRefs)
used.erase(info.path); used.erase(info.path);

View File

@ -165,8 +165,9 @@ void PathSubstitutionGoal::tryNext()
/* To maintain the closure invariant, we first have to realise the /* To maintain the closure invariant, we first have to realise the
paths referenced by this one. */ paths referenced by this one. */
for (auto & i : info->references.others) for (auto & i : info->references)
addWaitee(worker.makePathSubstitutionGoal(i)); if (i != storePath) /* ignore self-references */
addWaitee(worker.makePathSubstitutionGoal(i));
if (waitees.empty()) /* to prevent hang (no wake-up event) */ if (waitees.empty()) /* to prevent hang (no wake-up event) */
referencesValid(); referencesValid();
@ -187,8 +188,9 @@ void PathSubstitutionGoal::referencesValid()
return; return;
} }
for (auto & i : info->references.others) for (auto & i : info->references)
assert(worker.store.isValidPath(i)); if (i != storePath) /* ignore self-references */
assert(worker.store.isValidPath(i));
state = &PathSubstitutionGoal::tryToRun; state = &PathSubstitutionGoal::tryToRun;
worker.wakeUp(shared_from_this()); worker.wakeUp(shared_from_this());

View File

@ -151,6 +151,16 @@ Hash getContentAddressHash(const ContentAddress & ca)
}, ca); }, ca);
} }
bool StoreReferences::empty() const
{
return !self && others.empty();
}
size_t StoreReferences::size() const
{
return (self ? 1 : 0) + others.size();
}
ContentAddressWithReferences caWithoutRefs(const ContentAddress & ca) { ContentAddressWithReferences caWithoutRefs(const ContentAddress & ca) {
return std::visit(overloaded { return std::visit(overloaded {
[&](const TextHash & h) -> ContentAddressWithReferences { [&](const TextHash & h) -> ContentAddressWithReferences {

View File

@ -4,7 +4,6 @@
#include "hash.hh" #include "hash.hh"
#include "path.hh" #include "path.hh"
#include "comparator.hh" #include "comparator.hh"
#include "reference-set.hh"
namespace nix { namespace nix {
@ -95,7 +94,15 @@ Hash getContentAddressHash(const ContentAddress & ca);
* References set * References set
*/ */
typedef References<StorePath> StoreReferences; struct StoreReferences {
StorePathSet others;
bool self = false;
bool empty() const;
size_t size() const;
GENERATE_CMP(StoreReferences, me->self, me->others);
};
/* /*
* Full content address * Full content address

View File

@ -336,7 +336,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
logger->startWork(); logger->startWork();
StorePathSet paths; StorePathSet paths;
if (op == wopQueryReferences) if (op == wopQueryReferences)
for (auto & i : store->queryPathInfo(path)->referencesPossiblyToSelf()) for (auto & i : store->queryPathInfo(path)->references)
paths.insert(i); paths.insert(i);
else if (op == wopQueryReferrers) else if (op == wopQueryReferrers)
store->queryReferrers(path, paths); store->queryReferrers(path, paths);
@ -758,7 +758,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
else { else {
to << 1 to << 1
<< (i->second.deriver ? store->printStorePath(*i->second.deriver) : ""); << (i->second.deriver ? store->printStorePath(*i->second.deriver) : "");
worker_proto::write(*store, to, i->second.references.possiblyToSelf(path)); worker_proto::write(*store, to, i->second.references);
to << i->second.downloadSize to << i->second.downloadSize
<< i->second.narSize; << i->second.narSize;
} }
@ -781,7 +781,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
for (auto & i : infos) { for (auto & i : infos) {
to << store->printStorePath(i.first) to << store->printStorePath(i.first)
<< (i.second.deriver ? store->printStorePath(*i.second.deriver) : ""); << (i.second.deriver ? store->printStorePath(*i.second.deriver) : "");
worker_proto::write(*store, to, i.second.references.possiblyToSelf(i.first)); worker_proto::write(*store, to, i.second.references);
to << i.second.downloadSize << i.second.narSize; to << i.second.downloadSize << i.second.narSize;
} }
break; break;
@ -863,7 +863,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
ValidPathInfo info { path, narHash }; ValidPathInfo info { path, narHash };
if (deriver != "") if (deriver != "")
info.deriver = store->parseStorePath(deriver); info.deriver = store->parseStorePath(deriver);
info.setReferencesPossiblyToSelf(worker_proto::read(*store, from, Phantom<StorePathSet> {})); info.references = worker_proto::read(*store, from, Phantom<StorePathSet> {});
from >> info.registrationTime >> info.narSize >> info.ultimate; from >> info.registrationTime >> info.narSize >> info.ultimate;
info.sigs = readStrings<StringSet>(from); info.sigs = readStrings<StringSet>(from);
info.ca = parseContentAddressOpt(readString(from)); info.ca = parseContentAddressOpt(readString(from));

View File

@ -45,7 +45,7 @@ void Store::exportPath(const StorePath & path, Sink & sink)
teeSink teeSink
<< exportMagic << exportMagic
<< printStorePath(path); << printStorePath(path);
worker_proto::write(*this, teeSink, info->referencesPossiblyToSelf()); worker_proto::write(*this, teeSink, info->references);
teeSink teeSink
<< (info->deriver ? printStorePath(*info->deriver) : "") << (info->deriver ? printStorePath(*info->deriver) : "")
<< 0; << 0;
@ -80,7 +80,7 @@ StorePaths Store::importPaths(Source & source, CheckSigsFlag checkSigs)
ValidPathInfo info { path, narHash }; ValidPathInfo info { path, narHash };
if (deriver != "") if (deriver != "")
info.deriver = parseStorePath(deriver); info.deriver = parseStorePath(deriver);
info.setReferencesPossiblyToSelf(std::move(references)); info.references = references;
info.narSize = saved.s.size(); info.narSize = saved.s.size();
// Ignore optional legacy signature. // Ignore optional legacy signature.

View File

@ -137,7 +137,7 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
auto deriver = readString(conn->from); auto deriver = readString(conn->from);
if (deriver != "") if (deriver != "")
info->deriver = parseStorePath(deriver); info->deriver = parseStorePath(deriver);
info->setReferencesPossiblyToSelf(worker_proto::read(*this, conn->from, Phantom<StorePathSet> {})); info->references = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
readLongLong(conn->from); // download size readLongLong(conn->from); // download size
info->narSize = readLongLong(conn->from); info->narSize = readLongLong(conn->from);
@ -171,7 +171,7 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
<< printStorePath(info.path) << printStorePath(info.path)
<< (info.deriver ? printStorePath(*info.deriver) : "") << (info.deriver ? printStorePath(*info.deriver) : "")
<< info.narHash.to_string(Base16, false); << info.narHash.to_string(Base16, false);
worker_proto::write(*this, conn->to, info.referencesPossiblyToSelf()); worker_proto::write(*this, conn->to, info.references);
conn->to conn->to
<< info.registrationTime << info.registrationTime
<< info.narSize << info.narSize
@ -200,7 +200,7 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
conn->to conn->to
<< exportMagic << exportMagic
<< printStorePath(info.path); << printStorePath(info.path);
worker_proto::write(*this, conn->to, info.referencesPossiblyToSelf()); worker_proto::write(*this, conn->to, info.references);
conn->to conn->to
<< (info.deriver ? printStorePath(*info.deriver) : "") << (info.deriver ? printStorePath(*info.deriver) : "")
<< 0 << 0

View File

@ -938,8 +938,7 @@ std::shared_ptr<const ValidPathInfo> LocalStore::queryPathInfoInternal(State & s
auto useQueryReferences(state.stmts->QueryReferences.use()(info->id)); auto useQueryReferences(state.stmts->QueryReferences.use()(info->id));
while (useQueryReferences.next()) while (useQueryReferences.next())
info->insertReferencePossiblyToSelf( info->references.insert(parseStorePath(useQueryReferences.getStr(0)));
parseStorePath(useQueryReferences.getStr(0)));
return info; return info;
} }
@ -1206,7 +1205,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
for (auto & [_, i] : infos) { for (auto & [_, i] : infos) {
auto referrer = queryValidPathId(*state, i.path); auto referrer = queryValidPathId(*state, i.path);
for (auto & j : i.referencesPossiblyToSelf()) for (auto & j : i.references)
state->stmts->AddReference.use()(referrer)(queryValidPathId(*state, j)).exec(); state->stmts->AddReference.use()(referrer)(queryValidPathId(*state, j)).exec();
} }
@ -1227,7 +1226,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
topoSort(paths, topoSort(paths,
{[&](const StorePath & path) { {[&](const StorePath & path) {
auto i = infos.find(path); auto i = infos.find(path);
return i == infos.end() ? StorePathSet() : i->second.references.others; return i == infos.end() ? StorePathSet() : i->second.references;
}}, }},
{[&](const StorePath & path, const StorePath & parent) { {[&](const StorePath & path, const StorePath & parent) {
return BuildError( return BuildError(
@ -1525,8 +1524,7 @@ StorePath LocalStore::addTextToStore(
ValidPathInfo info { dstPath, narHash }; ValidPathInfo info { dstPath, narHash };
info.narSize = sink.s.size(); info.narSize = sink.s.size();
// No self reference allowed with text-hashing info.references = references;
info.references.others = references;
info.ca = TextHash { .hash = hash }; info.ca = TextHash { .hash = hash };
registerValidPath(info); registerValidPath(info);
} }

View File

@ -28,8 +28,9 @@ std::map<StorePath, StorePath> makeContentAddressed(
StringMap rewrites; StringMap rewrites;
StoreReferences refs; StoreReferences refs;
refs.self = oldInfo->references.self; for (auto & ref : oldInfo->references) {
for (auto & ref : oldInfo->references.others) { if (ref == path)
refs.self = true;
auto i = remappings.find(ref); auto i = remappings.find(ref);
auto replacement = i != remappings.end() ? i->second : ref; auto replacement = i != remappings.end() ? i->second : ref;
// FIXME: warn about unremapped paths? // FIXME: warn about unremapped paths?

View File

@ -40,8 +40,9 @@ void Store::computeFSClosure(const StorePathSet & startPaths,
std::future<ref<const ValidPathInfo>> & fut) { std::future<ref<const ValidPathInfo>> & fut) {
StorePathSet res; StorePathSet res;
auto info = fut.get(); auto info = fut.get();
for (auto & ref : info->references.others) for (auto & ref : info->references)
res.insert(ref); if (ref != path)
res.insert(ref);
if (includeOutputs && path.isDerivation()) if (includeOutputs && path.isDerivation())
for (auto & [_, maybeOutPath] : queryPartialDerivationOutputMap(path)) for (auto & [_, maybeOutPath] : queryPartialDerivationOutputMap(path))
@ -223,7 +224,7 @@ void Store::queryMissing(const std::vector<DerivedPath> & targets,
state->narSize += info->second.narSize; state->narSize += info->second.narSize;
} }
for (auto & ref : info->second.references.others) for (auto & ref : info->second.references)
pool.enqueue(std::bind(doPath, DerivedPath::Opaque { ref })); pool.enqueue(std::bind(doPath, DerivedPath::Opaque { ref }));
}, },
}, req.raw()); }, req.raw());
@ -241,7 +242,7 @@ StorePaths Store::topoSortPaths(const StorePathSet & paths)
return topoSort(paths, return topoSort(paths,
{[&](const StorePath & path) { {[&](const StorePath & path) {
try { try {
return queryPathInfo(path)->references.others; return queryPathInfo(path)->references;
} catch (InvalidPath &) { } catch (InvalidPath &) {
return StorePathSet(); return StorePathSet();
} }
@ -297,7 +298,7 @@ std::map<DrvOutput, StorePath> drvOutputReferences(
auto info = store.queryPathInfo(outputPath); auto info = store.queryPathInfo(outputPath);
return drvOutputReferences(Realisation::closure(store, inputRealisations), info->referencesPossiblyToSelf()); return drvOutputReferences(Realisation::closure(store, inputRealisations), info->references);
} }
OutputPathMap resolveDerivedPath(Store & store, const DerivedPath::Built & bfd, Store * evalStore_) OutputPathMap resolveDerivedPath(Store & store, const DerivedPath::Built & bfd, Store * evalStore_)

View File

@ -248,7 +248,7 @@ public:
narInfo->fileSize = queryNAR.getInt(5); narInfo->fileSize = queryNAR.getInt(5);
narInfo->narSize = queryNAR.getInt(7); narInfo->narSize = queryNAR.getInt(7);
for (auto & r : tokenizeString<Strings>(queryNAR.getStr(8), " ")) for (auto & r : tokenizeString<Strings>(queryNAR.getStr(8), " "))
narInfo->insertReferencePossiblyToSelf(StorePath(r)); narInfo->references.insert(StorePath(r));
if (!queryNAR.isNull(9)) if (!queryNAR.isNull(9))
narInfo->deriver = StorePath(queryNAR.getStr(9)); narInfo->deriver = StorePath(queryNAR.getStr(9));
for (auto & sig : tokenizeString<Strings>(queryNAR.getStr(10), " ")) for (auto & sig : tokenizeString<Strings>(queryNAR.getStr(10), " "))

View File

@ -63,7 +63,7 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
auto refs = tokenizeString<Strings>(value, " "); auto refs = tokenizeString<Strings>(value, " ");
if (!references.empty()) throw corrupt(); if (!references.empty()) throw corrupt();
for (auto & r : refs) for (auto & r : refs)
insertReferencePossiblyToSelf(StorePath(r)); references.insert(StorePath(r));
} }
else if (name == "Deriver") { else if (name == "Deriver") {
if (value != "unknown-deriver") if (value != "unknown-deriver")

View File

@ -12,7 +12,7 @@ std::string ValidPathInfo::fingerprint(const Store & store) const
"1;" + store.printStorePath(path) + ";" "1;" + store.printStorePath(path) + ";"
+ narHash.to_string(Base32, true) + ";" + narHash.to_string(Base32, true) + ";"
+ std::to_string(narSize) + ";" + std::to_string(narSize) + ";"
+ concatStringsSep(",", store.printStorePathSet(referencesPossiblyToSelf())); + concatStringsSep(",", store.printStorePathSet(references));
} }
@ -30,16 +30,25 @@ std::optional<StorePathDescriptor> ValidPathInfo::fullStorePathDescriptorOpt() c
.name = std::string { path.name() }, .name = std::string { path.name() },
.info = std::visit(overloaded { .info = std::visit(overloaded {
[&](const TextHash & th) -> ContentAddressWithReferences { [&](const TextHash & th) -> ContentAddressWithReferences {
assert(!references.self); assert(references.count(path) == 0);
return TextInfo { return TextInfo {
th, th,
.references = references.others, .references = references,
}; };
}, },
[&](const FixedOutputHash & foh) -> ContentAddressWithReferences { [&](const FixedOutputHash & foh) -> ContentAddressWithReferences {
auto refs = references;
bool hasSelfReference = false;
if (refs.count(path)) {
hasSelfReference = true;
refs.erase(path);
}
return FixedOutputInfo { return FixedOutputInfo {
foh, foh,
.references = references, .references = {
.others = std::move(refs),
.self = hasSelfReference,
},
}; };
}, },
}, *ca), }, *ca),
@ -85,7 +94,7 @@ bool ValidPathInfo::checkSignature(const Store & store, const PublicKeys & publi
Strings ValidPathInfo::shortRefs() const Strings ValidPathInfo::shortRefs() const
{ {
Strings refs; Strings refs;
for (auto & r : referencesPossiblyToSelf()) for (auto & r : references)
refs.push_back(std::string(r.to_string())); refs.push_back(std::string(r.to_string()));
return refs; return refs;
} }
@ -100,36 +109,19 @@ ValidPathInfo::ValidPathInfo(
{ {
std::visit(overloaded { std::visit(overloaded {
[this](TextInfo && ti) { [this](TextInfo && ti) {
this->references = { this->references = std::move(ti.references);
.others = std::move(ti.references),
.self = false,
};
this->ca = std::move((TextHash &&) ti); this->ca = std::move((TextHash &&) ti);
}, },
[this](FixedOutputInfo && foi) { [this](FixedOutputInfo && foi) {
this->references = std::move(foi.references); this->references = std::move(foi.references.others);
if (foi.references.self)
this->references.insert(path);
this->ca = std::move((FixedOutputHash &&) foi); this->ca = std::move((FixedOutputHash &&) foi);
}, },
}, std::move(info.info)); }, 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) ValidPathInfo ValidPathInfo::read(Source & source, const Store & store, unsigned int format)
{ {
return read(source, store, format, store.parseStorePath(readString(source))); return read(source, store, format, store.parseStorePath(readString(source)));
@ -141,7 +133,7 @@ ValidPathInfo ValidPathInfo::read(Source & source, const Store & store, unsigned
auto narHash = Hash::parseAny(readString(source), htSHA256); auto narHash = Hash::parseAny(readString(source), htSHA256);
ValidPathInfo info(path, narHash); ValidPathInfo info(path, narHash);
if (deriver != "") info.deriver = store.parseStorePath(deriver); if (deriver != "") info.deriver = store.parseStorePath(deriver);
info.setReferencesPossiblyToSelf(worker_proto::read(store, source, Phantom<StorePathSet> {})); info.references = worker_proto::read(store, source, Phantom<StorePathSet> {});
source >> info.registrationTime >> info.narSize; source >> info.registrationTime >> info.narSize;
if (format >= 16) { if (format >= 16) {
source >> info.ultimate; source >> info.ultimate;
@ -162,7 +154,7 @@ void ValidPathInfo::write(
sink << store.printStorePath(path); sink << store.printStorePath(path);
sink << (deriver ? store.printStorePath(*deriver) : "") sink << (deriver ? store.printStorePath(*deriver) : "")
<< narHash.to_string(Base16, false); << narHash.to_string(Base16, false);
worker_proto::write(store, sink, referencesPossiblyToSelf()); worker_proto::write(store, sink, references);
sink << registrationTime << narSize; sink << registrationTime << narSize;
if (format >= 16) { if (format >= 16) {
sink << ultimate sink << ultimate

View File

@ -17,19 +17,20 @@ class Store;
struct SubstitutablePathInfo struct SubstitutablePathInfo
{ {
std::optional<StorePath> deriver; std::optional<StorePath> deriver;
StoreReferences references; StorePathSet references;
uint64_t downloadSize; /* 0 = unknown or inapplicable */ uint64_t downloadSize; /* 0 = unknown or inapplicable */
uint64_t narSize; /* 0 = unknown */ uint64_t narSize; /* 0 = unknown */
}; };
typedef std::map<StorePath, SubstitutablePathInfo> SubstitutablePathInfos; typedef std::map<StorePath, SubstitutablePathInfo> SubstitutablePathInfos;
struct ValidPathInfo struct ValidPathInfo
{ {
StorePath path; StorePath path;
std::optional<StorePath> deriver; std::optional<StorePath> deriver;
Hash narHash; Hash narHash;
StoreReferences references; StorePathSet references;
time_t registrationTime = 0; time_t registrationTime = 0;
uint64_t narSize = 0; // 0 = unknown uint64_t narSize = 0; // 0 = unknown
uint64_t id; // internal use only uint64_t id; // internal use only
@ -81,12 +82,6 @@ struct ValidPathInfo
/* Return true iff the path is verifiably content-addressed. */ /* Return true iff the path is verifiably content-addressed. */
bool isContentAddressed(const Store & store) const; bool isContentAddressed(const Store & store) const;
/* Functions to view references + hasSelfReference as one set, mainly for
compatibility's sake. */
StorePathSet referencesPossiblyToSelf() const;
void insertReferencePossiblyToSelf(StorePath && ref);
void setReferencesPossiblyToSelf(StorePathSet && refs);
static const size_t maxSigs = std::numeric_limits<size_t>::max(); static const size_t maxSigs = std::numeric_limits<size_t>::max();
/* Return the number of signatures on this .narinfo that were /* Return the number of signatures on this .narinfo that were

View File

@ -402,7 +402,7 @@ void RemoteStore::querySubstitutablePathInfos(const StorePathCAMap & pathsMap, S
auto deriver = readString(conn->from); auto deriver = readString(conn->from);
if (deriver != "") if (deriver != "")
info.deriver = parseStorePath(deriver); info.deriver = parseStorePath(deriver);
info.references.setPossiblyToSelf(i.first, worker_proto::read(*this, conn->from, Phantom<StorePathSet> {})); info.references = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
info.downloadSize = readLongLong(conn->from); info.downloadSize = readLongLong(conn->from);
info.narSize = readLongLong(conn->from); info.narSize = readLongLong(conn->from);
infos.insert_or_assign(i.first, std::move(info)); infos.insert_or_assign(i.first, std::move(info));
@ -421,12 +421,11 @@ void RemoteStore::querySubstitutablePathInfos(const StorePathCAMap & pathsMap, S
conn.processStderr(); conn.processStderr();
size_t count = readNum<size_t>(conn->from); size_t count = readNum<size_t>(conn->from);
for (size_t n = 0; n < count; n++) { for (size_t n = 0; n < count; n++) {
auto path = parseStorePath(readString(conn->from)); SubstitutablePathInfo & info(infos[parseStorePath(readString(conn->from))]);
SubstitutablePathInfo & info { infos[path] };
auto deriver = readString(conn->from); auto deriver = readString(conn->from);
if (deriver != "") if (deriver != "")
info.deriver = parseStorePath(deriver); info.deriver = parseStorePath(deriver);
info.references.setPossiblyToSelf(path, worker_proto::read(*this, conn->from, Phantom<StorePathSet> {})); info.references = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
info.downloadSize = readLongLong(conn->from); info.downloadSize = readLongLong(conn->from);
info.narSize = readLongLong(conn->from); info.narSize = readLongLong(conn->from);
} }
@ -634,7 +633,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
sink sink
<< exportMagic << exportMagic
<< printStorePath(info.path); << printStorePath(info.path);
worker_proto::write(*this, sink, info.referencesPossiblyToSelf()); worker_proto::write(*this, sink, info.references);
sink sink
<< (info.deriver ? printStorePath(*info.deriver) : "") << (info.deriver ? printStorePath(*info.deriver) : "")
<< 0 // == no legacy signature << 0 // == no legacy signature
@ -645,7 +644,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
conn.processStderr(0, source2.get()); conn.processStderr(0, source2.get());
auto importedPaths = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {}); auto importedPaths = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
assert(importedPaths.empty() == 0); // doesn't include possible self reference assert(importedPaths.size() <= 1);
} }
else { else {
@ -653,7 +652,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
<< printStorePath(info.path) << printStorePath(info.path)
<< (info.deriver ? printStorePath(*info.deriver) : "") << (info.deriver ? printStorePath(*info.deriver) : "")
<< info.narHash.to_string(Base16, false); << info.narHash.to_string(Base16, false);
worker_proto::write(*this, conn->to, info.referencesPossiblyToSelf()); worker_proto::write(*this, conn->to, info.references);
conn->to << info.registrationTime << info.narSize conn->to << info.registrationTime << info.narSize
<< info.ultimate << info.sigs << renderContentAddress(info.ca) << info.ultimate << info.sigs << renderContentAddress(info.ca)
<< repair << !checkSigs; << repair << !checkSigs;

View File

@ -200,7 +200,10 @@ StorePath Store::makeTextPath(std::string_view name, const TextInfo & info) cons
{ {
assert(info.hash.type == htSHA256); assert(info.hash.type == htSHA256);
return makeStorePath( return makeStorePath(
makeType(*this, "text", StoreReferences { info.references }), makeType(*this, "text", StoreReferences {
.others = info.references,
.self = false,
}),
info.hash, info.hash,
name); name);
} }
@ -310,7 +313,7 @@ void Store::addMultipleToStore(
bytesExpected += info.narSize; bytesExpected += info.narSize;
act.setExpected(actCopyPath, bytesExpected); act.setExpected(actCopyPath, bytesExpected);
return info.references.others; return info.references;
}, },
[&](const StorePath & path) { [&](const StorePath & path) {
@ -815,7 +818,7 @@ std::string Store::makeValidityRegistration(const StorePathSet & paths,
s += (format("%1%\n") % info->references.size()).str(); s += (format("%1%\n") % info->references.size()).str();
for (auto & j : info->referencesPossiblyToSelf()) for (auto & j : info->references)
s += printStorePath(j) + "\n"; s += printStorePath(j) + "\n";
} }
@ -877,7 +880,7 @@ json Store::pathInfoToJSON(const StorePathSet & storePaths,
{ {
auto& jsonRefs = (jsonPath["references"] = json::array()); auto& jsonRefs = (jsonPath["references"] = json::array());
for (auto & ref : info->referencesPossiblyToSelf()) for (auto & ref : info->references)
jsonRefs.emplace_back(printStorePath(ref)); jsonRefs.emplace_back(printStorePath(ref));
} }
@ -1205,7 +1208,7 @@ std::optional<ValidPathInfo> decodeValidPathInfo(const Store & store, std::istre
if (!n) throw Error("number expected"); if (!n) throw Error("number expected");
while ((*n)--) { while ((*n)--) {
getline(str, s); getline(str, s);
info.insertReferencePossiblyToSelf(store.parseStorePath(s)); info.references.insert(store.parseStorePath(s));
} }
if (!str || str.eof()) throw Error("missing input"); if (!str || str.eof()) throw Error("missing input");
return std::optional<ValidPathInfo>(std::move(info)); return std::optional<ValidPathInfo>(std::move(info));
@ -1228,6 +1231,7 @@ std::string showPaths(const PathSet & paths)
return concatStringsSep(", ", quoteStrings(paths)); return concatStringsSep(", ", quoteStrings(paths));
} }
Derivation Store::derivationFromPath(const StorePath & drvPath) Derivation Store::derivationFromPath(const StorePath & drvPath)
{ {
ensurePath(drvPath); ensurePath(drvPath);

View File

@ -1,68 +0,0 @@
#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;
}
}

View File

@ -56,7 +56,7 @@ void printDotGraph(ref<Store> store, StorePathSet && roots)
cout << makeNode(std::string(path.to_string()), path.name(), "#ff0000"); cout << makeNode(std::string(path.to_string()), path.name(), "#ff0000");
for (auto & p : store->queryPathInfo(path)->referencesPossiblyToSelf()) { for (auto & p : store->queryPathInfo(path)->references) {
if (p != path) { if (p != path) {
workList.insert(p); workList.insert(p);
cout << makeEdge(std::string(p.to_string()), std::string(path.to_string())); cout << makeEdge(std::string(p.to_string()), std::string(path.to_string()));

View File

@ -71,7 +71,7 @@ void printGraphML(ref<Store> store, StorePathSet && roots)
auto info = store->queryPathInfo(path); auto info = store->queryPathInfo(path);
cout << makeNode(*info); cout << makeNode(*info);
for (auto & p : info->referencesPossiblyToSelf()) { for (auto & p : info->references) {
if (p != path) { if (p != path) {
workList.insert(p); workList.insert(p);
cout << makeEdge(path.to_string(), p.to_string()); cout << makeEdge(path.to_string(), p.to_string());

View File

@ -263,7 +263,7 @@ static void printTree(const StorePath & path,
closure(B). That is, if derivation A is an (possibly indirect) closure(B). That is, if derivation A is an (possibly indirect)
input of B, then A is printed first. This has the effect of input of B, then A is printed first. This has the effect of
flattening the tree, preventing deeply nested structures. */ flattening the tree, preventing deeply nested structures. */
auto sorted = store->topoSortPaths(info->referencesPossiblyToSelf()); auto sorted = store->topoSortPaths(info->references);
reverse(sorted.begin(), sorted.end()); reverse(sorted.begin(), sorted.end());
for (const auto &[n, i] : enumerate(sorted)) { for (const auto &[n, i] : enumerate(sorted)) {
@ -344,7 +344,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (auto & j : ps) { for (auto & j : ps) {
if (query == qRequisites) store->computeFSClosure(j, paths, false, includeOutputs); if (query == qRequisites) store->computeFSClosure(j, paths, false, includeOutputs);
else if (query == qReferences) { else if (query == qReferences) {
for (auto & p : store->queryPathInfo(j)->referencesPossiblyToSelf()) for (auto & p : store->queryPathInfo(j)->references)
paths.insert(p); paths.insert(p);
} }
else if (query == qReferrers) { else if (query == qReferrers) {
@ -867,7 +867,7 @@ static void opServe(Strings opFlags, Strings opArgs)
auto info = store->queryPathInfo(i); auto info = store->queryPathInfo(i);
out << store->printStorePath(info->path) out << store->printStorePath(info->path)
<< (info->deriver ? store->printStorePath(*info->deriver) : ""); << (info->deriver ? store->printStorePath(*info->deriver) : "");
worker_proto::write(*store, out, info->referencesPossiblyToSelf()); worker_proto::write(*store, out, info->references);
// !!! Maybe we want compression? // !!! Maybe we want compression?
out << info->narSize // downloadSize out << info->narSize // downloadSize
<< info->narSize; << info->narSize;
@ -964,7 +964,7 @@ static void opServe(Strings opFlags, Strings opArgs)
}; };
if (deriver != "") if (deriver != "")
info.deriver = store->parseStorePath(deriver); info.deriver = store->parseStorePath(deriver);
info.setReferencesPossiblyToSelf(worker_proto::read(*store, in, Phantom<StorePathSet> {})); info.references = worker_proto::read(*store, in, Phantom<StorePathSet> {});
in >> info.registrationTime >> info.narSize >> info.ultimate; in >> info.registrationTime >> info.narSize >> info.ultimate;
info.sigs = readStrings<StringSet>(in); info.sigs = readStrings<StringSet>(in);
info.ca = parseContentAddressOpt(readString(in)); info.ca = parseContentAddressOpt(readString(in));

View File

@ -136,7 +136,7 @@ struct CmdWhyDepends : SourceExprCommand
for (auto & path : closure) for (auto & path : closure)
graph.emplace(path, Node { graph.emplace(path, Node {
.path = path, .path = path,
.refs = store->queryPathInfo(path)->references.others, .refs = store->queryPathInfo(path)->references,
.dist = path == dependencyPath ? 0 : inf .dist = path == dependencyPath ? 0 : inf
}); });