1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-27 08:31:16 +02:00

Eliminate the "store" global variable

Also, move a few free-standing functions into StoreAPI and Derivation.

Also, introduce a non-nullable smart pointer, ref<T>, which is just a
wrapper around std::shared_ptr ensuring that the pointer is never
null. (For reference-counted values, this is better than passing a
"T&", because the latter doesn't maintain the refcount. Usually, the
caller will have a shared_ptr keeping the value alive, but that's not
always the case, e.g., when passing a reference to a std::thread via
std::bind.)
This commit is contained in:
Eelco Dolstra 2016-02-04 14:28:26 +01:00
parent 4f7824c58e
commit c10c61449f
36 changed files with 511 additions and 458 deletions

View file

@ -1,21 +1,21 @@
#include "misc.hh"
#include "store-api.hh"
#include "local-store.hh"
#include "derivations.hh"
#include "globals.hh"
#include "local-store.hh"
#include "store-api.hh"
namespace nix {
Derivation derivationFromPath(StoreAPI & store, const Path & drvPath)
Derivation StoreAPI::derivationFromPath(const Path & drvPath)
{
assertStorePath(drvPath);
store.ensurePath(drvPath);
ensurePath(drvPath);
return readDerivation(drvPath);
}
void computeFSClosure(StoreAPI & store, const Path & path,
void StoreAPI::computeFSClosure(const Path & path,
PathSet & paths, bool flipDirection, bool includeOutputs, bool includeDerivers)
{
if (paths.find(path) != paths.end()) return;
@ -24,50 +24,42 @@ void computeFSClosure(StoreAPI & store, const Path & path,
PathSet edges;
if (flipDirection) {
store.queryReferrers(path, edges);
queryReferrers(path, edges);
if (includeOutputs) {
PathSet derivers = store.queryValidDerivers(path);
PathSet derivers = queryValidDerivers(path);
for (auto & i : derivers)
edges.insert(i);
}
if (includeDerivers && isDerivation(path)) {
PathSet outputs = store.queryDerivationOutputs(path);
PathSet outputs = queryDerivationOutputs(path);
for (auto & i : outputs)
if (store.isValidPath(i) && store.queryDeriver(i) == path)
if (isValidPath(i) && queryDeriver(i) == path)
edges.insert(i);
}
} else {
store.queryReferences(path, edges);
queryReferences(path, edges);
if (includeOutputs && isDerivation(path)) {
PathSet outputs = store.queryDerivationOutputs(path);
PathSet outputs = queryDerivationOutputs(path);
for (auto & i : outputs)
if (store.isValidPath(i)) edges.insert(i);
if (isValidPath(i)) edges.insert(i);
}
if (includeDerivers) {
Path deriver = store.queryDeriver(path);
if (store.isValidPath(deriver)) edges.insert(deriver);
Path deriver = queryDeriver(path);
if (isValidPath(deriver)) edges.insert(deriver);
}
}
for (auto & i : edges)
computeFSClosure(store, i, paths, flipDirection, includeOutputs, includeDerivers);
computeFSClosure(i, paths, flipDirection, includeOutputs, includeDerivers);
}
Path findOutput(const Derivation & drv, string id)
{
for (auto & i : drv.outputs)
if (i.first == id) return i.second.path;
throw Error(format("derivation has no output %1%") % id);
}
void queryMissing(StoreAPI & store, const PathSet & targets,
void StoreAPI::queryMissing(const PathSet & targets,
PathSet & willBuild, PathSet & willSubstitute, PathSet & unknown,
unsigned long long & downloadSize, unsigned long long & narSize)
{
@ -105,27 +97,27 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
DrvPathWithOutputs i2 = parseDrvPathWithOutputs(i);
if (isDerivation(i2.first)) {
if (!store.isValidPath(i2.first)) {
if (!isValidPath(i2.first)) {
// FIXME: we could try to substitute p.
unknown.insert(i);
continue;
}
Derivation drv = derivationFromPath(store, i2.first);
Derivation drv = derivationFromPath(i2.first);
PathSet invalid;
for (auto & j : drv.outputs)
if (wantOutput(j.first, i2.second)
&& !store.isValidPath(j.second.path))
&& !isValidPath(j.second.path))
invalid.insert(j.second.path);
if (invalid.empty()) continue;
todoDrv.insert(i);
if (settings.useSubstitutes && substitutesAllowed(drv))
if (settings.useSubstitutes && drv.substitutesAllowed())
query.insert(invalid.begin(), invalid.end());
}
else {
if (store.isValidPath(i)) continue;
if (isValidPath(i)) continue;
query.insert(i);
todoNonDrv.insert(i);
}
@ -134,20 +126,20 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
todo.clear();
SubstitutablePathInfos infos;
store.querySubstitutablePathInfos(query, infos);
querySubstitutablePathInfos(query, infos);
for (auto & i : todoDrv) {
DrvPathWithOutputs i2 = parseDrvPathWithOutputs(i);
// FIXME: cache this
Derivation drv = derivationFromPath(store, i2.first);
Derivation drv = derivationFromPath(i2.first);
PathSet outputs;
bool mustBuild = false;
if (settings.useSubstitutes && substitutesAllowed(drv)) {
if (settings.useSubstitutes && drv.substitutesAllowed()) {
for (auto & j : drv.outputs) {
if (!wantOutput(j.first, i2.second)) continue;
if (!store.isValidPath(j.second.path)) {
if (!isValidPath(j.second.path)) {
if (infos.find(j.second.path) == infos.end())
mustBuild = true;
else
@ -181,38 +173,38 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
}
static void dfsVisit(StoreAPI & store, const PathSet & paths,
const Path & path, PathSet & visited, Paths & sorted,
PathSet & parents)
{
if (parents.find(path) != parents.end())
throw BuildError(format("cycle detected in the references of %1%") % path);
if (visited.find(path) != visited.end()) return;
visited.insert(path);
parents.insert(path);
PathSet references;
if (store.isValidPath(path))
store.queryReferences(path, references);
for (auto & i : references)
/* Don't traverse into paths that don't exist. That can
happen due to substitutes for non-existent paths. */
if (i != path && paths.find(i) != paths.end())
dfsVisit(store, paths, i, visited, sorted, parents);
sorted.push_front(path);
parents.erase(path);
}
Paths topoSortPaths(StoreAPI & store, const PathSet & paths)
Paths StoreAPI::topoSortPaths(const PathSet & paths)
{
Paths sorted;
PathSet visited, parents;
std::function<void(const Path & path)> dfsVisit;
dfsVisit = [&](const Path & path) {
if (parents.find(path) != parents.end())
throw BuildError(format("cycle detected in the references of %1%") % path);
if (visited.find(path) != visited.end()) return;
visited.insert(path);
parents.insert(path);
PathSet references;
if (isValidPath(path))
queryReferences(path, references);
for (auto & i : references)
/* Don't traverse into paths that don't exist. That can
happen due to substitutes for non-existent paths. */
if (i != path && paths.find(i) != paths.end())
dfsVisit(i);
sorted.push_front(path);
parents.erase(path);
};
for (auto & i : paths)
dfsVisit(store, paths, i, visited, sorted, parents);
dfsVisit(i);
return sorted;
}