aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-02-04 14:28:26 +0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-02-04 14:28:26 +0100
commitc10c61449f954702ae6d8092120321744acd82ff (patch)
tree40c161c42301acdfbfd7786638293951c5baf54d /src
parent4f7824c58ee0420c5679be6f0a9591f59edf410f (diff)
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.)
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/common-opts.cc2
-rw-r--r--src/libexpr/common-opts.hh2
-rw-r--r--src/libexpr/eval.cc3
-rw-r--r--src/libexpr/eval.hh10
-rw-r--r--src/libexpr/parser.y2
-rw-r--r--src/libexpr/primops.cc57
-rw-r--r--src/libmain/shared.cc9
-rw-r--r--src/libmain/shared.hh8
-rw-r--r--src/libstore/build.cc85
-rw-r--r--src/libstore/derivations.cc81
-rw-r--r--src/libstore/derivations.hh36
-rw-r--r--src/libstore/download.cc2
-rw-r--r--src/libstore/download.hh5
-rw-r--r--src/libstore/gc.cc49
-rw-r--r--src/libstore/local-store.cc4
-rw-r--r--src/libstore/local-store.hh4
-rw-r--r--src/libstore/misc.cc108
-rw-r--r--src/libstore/misc.hh40
-rw-r--r--src/libstore/profiles.cc4
-rw-r--r--src/libstore/profiles.hh4
-rw-r--r--src/libstore/store-api.cc13
-rw-r--r--src/libstore/store-api.hh54
-rw-r--r--src/libutil/types.hh67
-rw-r--r--src/libutil/util.hh10
-rw-r--r--src/nix-collect-garbage/nix-collect-garbage.cc2
-rw-r--r--src/nix-daemon/nix-daemon.cc89
-rw-r--r--src/nix-env/nix-env.cc42
-rw-r--r--src/nix-env/user-env.cc12
-rw-r--r--src/nix-instantiate/nix-instantiate.cc13
-rw-r--r--src/nix-prefetch-url/nix-prefetch-url.cc4
-rw-r--r--src/nix-store/dotgraph.cc4
-rw-r--r--src/nix-store/dotgraph.hh4
-rw-r--r--src/nix-store/nix-store.cc57
-rw-r--r--src/nix-store/xmlgraph.cc4
-rw-r--r--src/nix-store/xmlgraph.hh4
35 files changed, 480 insertions, 414 deletions
diff --git a/src/libexpr/common-opts.cc b/src/libexpr/common-opts.cc
index 13760490d..68ab4b5cd 100644
--- a/src/libexpr/common-opts.cc
+++ b/src/libexpr/common-opts.cc
@@ -55,7 +55,7 @@ bool parseSearchPathArg(Strings::iterator & i,
Path lookupFileArg(EvalState & state, string s)
{
if (isUri(s))
- return downloadFileCached(s, true);
+ return downloadFileCached(state.store, s, true);
else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
Path p = s.substr(1, s.size() - 2);
return state.findFile(p);
diff --git a/src/libexpr/common-opts.hh b/src/libexpr/common-opts.hh
index be0f40202..0500b0a83 100644
--- a/src/libexpr/common-opts.hh
+++ b/src/libexpr/common-opts.hh
@@ -4,6 +4,8 @@
namespace nix {
+class StoreAPI;
+
/* Some common option parsing between nix-env and nix-instantiate. */
bool parseAutoArgs(Strings::iterator & i,
const Strings::iterator & argsEnd, std::map<string, string> & res);
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 3b21c078f..702b12ee4 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -244,7 +244,7 @@ static Strings parseNixPath(const string & in)
}
-EvalState::EvalState(const Strings & _searchPath)
+EvalState::EvalState(const Strings & _searchPath, ref<StoreAPI> store)
: sWith(symbols.create("<with>"))
, sOutPath(symbols.create("outPath"))
, sDrvPath(symbols.create("drvPath"))
@@ -262,6 +262,7 @@ EvalState::EvalState(const Strings & _searchPath)
, sColumn(symbols.create("column"))
, sFunctor(symbols.create("__functor"))
, sToString(symbols.create("__toString"))
+ , store(store)
, baseEnv(allocEnv(128))
, staticBaseEnv(false, 0)
{
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 2d7b7bcdc..a4286ce1f 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -16,6 +16,7 @@
namespace nix {
+class StoreAPI;
class EvalState;
@@ -82,6 +83,8 @@ public:
Value vEmptySet;
+ const ref<StoreAPI> store;
+
private:
SrcToStore srcToStore;
@@ -97,7 +100,7 @@ private:
public:
- EvalState(const Strings & _searchPath);
+ EvalState(const Strings & _searchPath, ref<StoreAPI> store);
~EvalState();
void addToSearchPath(const string & s, bool warn = false);
@@ -240,6 +243,8 @@ public:
/* Print statistics. */
void printStats();
+ void realiseContext(const PathSet & context);
+
private:
unsigned long nrEnvs = 0;
@@ -290,7 +295,4 @@ struct InvalidPathError : EvalError
#endif
};
-/* Realise all paths in `context' */
-void realiseContext(const PathSet & context);
-
}
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index d34882f36..3e6c6d917 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -603,7 +603,7 @@ void EvalState::addToSearchPath(const string & s, bool warn)
}
if (isUri(path))
- path = downloadFileCached(path, true);
+ path = downloadFileCached(store, path, true);
path = absPath(path);
if (pathExists(path)) {
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 87ee4f68a..2371ae174 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -1,15 +1,15 @@
+#include "archive.hh"
+#include "derivations.hh"
+#include "download.hh"
+#include "eval-inline.hh"
#include "eval.hh"
-#include "misc.hh"
#include "globals.hh"
+#include "json-to-value.hh"
+#include "names.hh"
#include "store-api.hh"
#include "util.hh"
-#include "archive.hh"
-#include "value-to-xml.hh"
#include "value-to-json.hh"
-#include "json-to-value.hh"
-#include "names.hh"
-#include "eval-inline.hh"
-#include "download.hh"
+#include "value-to-xml.hh"
#include <sys/types.h>
#include <sys/stat.h>
@@ -43,7 +43,7 @@ std::pair<string, string> decodeContext(const string & s)
InvalidPathError::InvalidPathError(const Path & path) :
EvalError(format("path ‘%1%’ is not valid") % path), path(path) {}
-void realiseContext(const PathSet & context)
+void EvalState::realiseContext(const PathSet & context)
{
PathSet drvs;
for (auto & i : context) {
@@ -52,16 +52,14 @@ void realiseContext(const PathSet & context)
assert(isStorePath(ctx));
if (!store->isValidPath(ctx))
throw InvalidPathError(ctx);
- if (!decoded.second.empty() && isDerivation(ctx))
+ if (!decoded.second.empty() && nix::isDerivation(ctx))
drvs.insert(decoded.first + "!" + decoded.second);
}
if (!drvs.empty()) {
/* For performance, prefetch all substitute info. */
PathSet willBuild, willSubstitute, unknown;
unsigned long long downloadSize, narSize;
- queryMissing(*store, drvs,
- willBuild, willSubstitute, unknown, downloadSize, narSize);
-
+ store->queryMissing(drvs, willBuild, willSubstitute, unknown, downloadSize, narSize);
store->buildPaths(drvs);
}
}
@@ -75,7 +73,7 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
Path path = state.coerceToPath(pos, *args[1], context);
try {
- realiseContext(context);
+ state.realiseContext(context);
} catch (InvalidPathError & e) {
throw EvalError(format("cannot import ‘%1%’, since path ‘%2%’ is not valid, at %3%")
% path % e.path % pos);
@@ -83,7 +81,7 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
path = state.checkSourcePath(path);
- if (isStorePath(path) && store->isValidPath(path) && isDerivation(path)) {
+ if (isStorePath(path) && state.store->isValidPath(path) && isDerivation(path)) {
Derivation drv = readDerivation(path);
Value & w = *state.allocValue();
state.mkAttrs(w, 3 + drv.outputs.size());
@@ -145,7 +143,7 @@ static void prim_importNative(EvalState & state, const Pos & pos, Value * * args
Path path = state.coerceToPath(pos, *args[0], context);
try {
- realiseContext(context);
+ state.realiseContext(context);
} catch (InvalidPathError & e) {
throw EvalError(format("cannot import ‘%1%’, since path ‘%2%’ is not valid, at %3%")
% path % e.path % pos);
@@ -560,11 +558,12 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
runs. */
if (path.at(0) == '=') {
/* !!! This doesn't work if readOnlyMode is set. */
- PathSet refs; computeFSClosure(*store, string(path, 1), refs);
+ PathSet refs;
+ state.store->computeFSClosure(string(path, 1), refs);
for (auto & j : refs) {
drv.inputSrcs.insert(j);
if (isDerivation(j))
- drv.inputDrvs[j] = store->queryDerivationOutputNames(j);
+ drv.inputDrvs[j] = state.store->queryDerivationOutputNames(j);
}
}
@@ -581,7 +580,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
/* Handle derivation contexts returned by
‘builtins.storePath’. */
else if (isDerivation(path))
- drv.inputDrvs[path] = store->queryDerivationOutputNames(path);
+ drv.inputDrvs[path] = state.store->queryDerivationOutputNames(path);
/* Otherwise it's a source file. */
else
@@ -630,7 +629,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
/* Use the masked derivation expression to compute the output
path. */
- Hash h = hashDerivationModulo(*store, drv);
+ Hash h = hashDerivationModulo(*state.store, drv);
for (auto & i : drv.outputs)
if (i.second.path == "") {
@@ -641,7 +640,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
}
/* Write the resulting term into the Nix store directory. */
- Path drvPath = writeDerivation(*store, drv, drvName, state.repair);
+ Path drvPath = writeDerivation(state.store, drv, drvName, state.repair);
printMsg(lvlChatty, format("instantiated ‘%1%’ -> ‘%2%’")
% drvName % drvPath);
@@ -649,7 +648,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
/* Optimisation, but required in read-only mode! because in that
case we don't actually write store derivations, so we can't
read them later. */
- drvHashes[drvPath] = hashDerivationModulo(*store, drv);
+ drvHashes[drvPath] = hashDerivationModulo(*state.store, drv);
state.mkAttrs(v, 1 + drv.outputs.size());
mkString(*state.allocAttr(v, state.sDrvPath), drvPath, singleton<PathSet>("=" + drvPath));
@@ -695,7 +694,7 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V
throw EvalError(format("path ‘%1%’ is not in the Nix store, at %2%") % path % pos);
Path path2 = toStorePath(path);
if (!settings.readOnlyMode)
- store->ensurePath(path2);
+ state.store->ensurePath(path2);
context.insert(path2);
mkString(v, path, context);
}
@@ -745,7 +744,7 @@ static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Va
PathSet context;
Path path = state.coerceToPath(pos, *args[0], context);
try {
- realiseContext(context);
+ state.realiseContext(context);
} catch (InvalidPathError & e) {
throw EvalError(format("cannot read ‘%1%’, since path ‘%2%’ is not valid, at %3%")
% path % e.path % pos);
@@ -786,7 +785,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
string path = state.forceStringNoCtx(*args[1], pos);
try {
- realiseContext(context);
+ state.realiseContext(context);
} catch (InvalidPathError & e) {
throw EvalError(format("cannot find ‘%1%’, since path ‘%2%’ is not valid, at %3%")
% path % e.path % pos);
@@ -801,7 +800,7 @@ static void prim_readDir(EvalState & state, const Pos & pos, Value * * args, Val
PathSet ctx;
Path path = state.coerceToPath(pos, *args[0], ctx);
try {
- realiseContext(ctx);
+ state.realiseContext(ctx);
} catch (InvalidPathError & e) {
throw EvalError(format("cannot read ‘%1%’, since path ‘%2%’ is not valid, at %3%")
% path % e.path % pos);
@@ -879,13 +878,13 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
if (path.at(0) != '~')
throw EvalError(format("in ‘toFile’: the file ‘%1%’ cannot refer to derivation outputs, at %2%") % name % pos);
path = string(path, 1);
- }
+ }
refs.insert(path);
}
Path storePath = settings.readOnlyMode
? computeStorePathForText(name, contents, refs)
- : store->addTextToStore(name, contents, refs, state.repair);
+ : state.store->addTextToStore(name, contents, refs, state.repair);
/* Note: we don't need to add `context' to the context of the
result, since `storePath' itself has references to the paths
@@ -951,7 +950,7 @@ static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args
Path dstPath = settings.readOnlyMode
? computeStorePathForPath(path, true, htSHA256, filter).first
- : store->addToStore(baseNameOf(path), path, true, htSHA256, filter, state.repair);
+ : state.store->addToStore(baseNameOf(path), path, true, htSHA256, filter, state.repair);
mkString(v, dstPath, singleton<PathSet>(dstPath));
}
@@ -1678,7 +1677,7 @@ void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
} else
url = state.forceStringNoCtx(*args[0], pos);
- Path res = downloadFileCached(url, unpack);
+ Path res = downloadFileCached(state.store, url, unpack);
mkString(v, res, PathSet({res}));
}
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index 5106739c8..656d04cab 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -4,7 +4,6 @@
#include "globals.hh"
#include "store-api.hh"
#include "util.hh"
-#include "misc.hh"
#include <iostream>
#include <cctype>
@@ -47,22 +46,22 @@ void printGCWarning()
}
-void printMissing(StoreAPI & store, const PathSet & paths)
+void printMissing(ref<StoreAPI> store, const PathSet & paths)
{
unsigned long long downloadSize, narSize;
PathSet willBuild, willSubstitute, unknown;
- queryMissing(store, paths, willBuild, willSubstitute, unknown, downloadSize, narSize);
+ store->queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize, narSize);
printMissing(store, willBuild, willSubstitute, unknown, downloadSize, narSize);
}
-void printMissing(StoreAPI & store, const PathSet & willBuild,
+void printMissing(ref<StoreAPI> store, const PathSet & willBuild,
const PathSet & willSubstitute, const PathSet & unknown,
unsigned long long downloadSize, unsigned long long narSize)
{
if (!willBuild.empty()) {
printMsg(lvlInfo, format("these derivations will be built:"));
- Paths sorted = topoSortPaths(store, willBuild);
+ Paths sorted = store->topoSortPaths(willBuild);
reverse(sorted.begin(), sorted.end());
for (auto & i : sorted)
printMsg(lvlInfo, format(" %1%") % i);
diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh
index 8e756bd5e..6f826d8f6 100644
--- a/src/libmain/shared.hh
+++ b/src/libmain/shared.hh
@@ -19,8 +19,6 @@ public:
Exit(int status) : status(status) { }
};
-class StoreAPI;
-
int handleExceptions(const string & programName, std::function<void()> fun);
void initNix();
@@ -33,9 +31,11 @@ void printVersion(const string & programName);
/* Ugh. No better place to put this. */
void printGCWarning();
-void printMissing(StoreAPI & store, const PathSet & paths);
+class StoreAPI;
+
+void printMissing(ref<StoreAPI> store, const PathSet & paths);
-void printMissing(StoreAPI & store, const PathSet & willBuild,
+void printMissing(ref<StoreAPI> store, const PathSet & willBuild,
const PathSet & willSubstitute, const PathSet & unknown,
unsigned long long downloadSize, unsigned long long narSize);
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 9b9621dc1..180a558dc 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -2,7 +2,6 @@
#include "references.hh"
#include "pathlocks.hh"
-#include "misc.hh"
#include "globals.hh"
#include "local-store.hh"
#include "util.hh"
@@ -906,7 +905,7 @@ DerivationGoal::DerivationGoal(const Path & drvPath, const BasicDerivation & drv
{
this->drv = std::unique_ptr<BasicDerivation>(new BasicDerivation(drv));
state = &DerivationGoal::haveDerivation;
- name = (format("building of %1%") % showPaths(outputPaths(drv))).str();
+ name = (format("building of %1%") % showPaths(drv.outputPaths())).str();
trace("created");
/* Prevent the .chroot directory from being
@@ -1018,7 +1017,7 @@ void DerivationGoal::loadDerivation()
assert(worker.store.isValidPath(drvPath));
/* Get the derivation. */
- drv = std::unique_ptr<BasicDerivation>(new Derivation(derivationFromPath(worker.store, drvPath)));
+ drv = std::unique_ptr<BasicDerivation>(new Derivation(worker.store.derivationFromPath(drvPath)));
haveDerivation();
}
@@ -1057,7 +1056,7 @@ void DerivationGoal::haveDerivation()
/* We are first going to try to create the invalid output paths
through substitutes. If that doesn't work, we'll build
them. */
- if (settings.useSubstitutes && substitutesAllowed(*drv))
+ if (settings.useSubstitutes && drv->substitutesAllowed())
for (auto & i : invalidOutputs)
addWaitee(worker.makeSubstitutionGoal(i, buildMode == bmRepair));
@@ -1138,7 +1137,7 @@ void DerivationGoal::repairClosure()
PathSet outputClosure;
for (auto & i : drv->outputs) {
if (!wantOutput(i.first, wantedOutputs)) continue;
- computeFSClosure(worker.store, i.second.path, outputClosure);
+ worker.store.computeFSClosure(i.second.path, outputClosure);
}
/* Filter out our own outputs (which we have already checked). */
@@ -1149,11 +1148,11 @@ void DerivationGoal::repairClosure()
derivation is responsible for which path in the output
closure. */
PathSet inputClosure;
- if (useDerivation) computeFSClosure(worker.store, drvPath, inputClosure);
+ if (useDerivation) worker.store.computeFSClosure(drvPath, inputClosure);
std::map<Path, Path> outputsToDrv;
for (auto & i : inputClosure)
if (isDerivation(i)) {
- Derivation drv = derivationFromPath(worker.store, i);
+ Derivation drv = worker.store.derivationFromPath(i);
for (auto & j : drv.outputs)
outputsToDrv[j.second.path] = i;
}
@@ -1225,10 +1224,10 @@ void DerivationGoal::inputsRealised()
`i' as input paths. Only add the closures of output paths
that are specified as inputs. */
assert(worker.store.isValidPath(i.first));
- Derivation inDrv = derivationFromPath(worker.store, i.first);
+ Derivation inDrv = worker.store.derivationFromPath(i.first);
for (auto & j : i.second)
if (inDrv.outputs.find(j) != inDrv.outputs.end())
- computeFSClosure(worker.store, inDrv.outputs[j].path, inputPaths);
+ worker.store.computeFSClosure(inDrv.outputs[j].path, inputPaths);
else
throw Error(
format("derivation ‘%1%’ requires non-existent output ‘%2%’ from input derivation ‘%3%’")
@@ -1237,7 +1236,7 @@ void DerivationGoal::inputsRealised()
/* Second, the input sources. */
for (auto & i : drv->inputSrcs)
- computeFSClosure(worker.store, i, inputPaths);
+ worker.store.computeFSClosure(i, inputPaths);
debug(format("added input paths %1%") % showPaths(inputPaths));
@@ -1260,46 +1259,6 @@ void DerivationGoal::inputsRealised()
}
-static bool isBuiltin(const BasicDerivation & drv)
-{
- return string(drv.builder, 0, 8) == "builtin:";
-}
-
-
-static bool canBuildLocally(const BasicDerivation & drv)
-{
- return drv.platform == settings.thisSystem
- || isBuiltin(drv)
-#if __linux__
- || (drv.platform == "i686-linux" && settings.thisSystem == "x86_64-linux")
- || (drv.platform == "armv6l-linux" && settings.thisSystem == "armv7l-linux")
-#elif __FreeBSD__
- || (drv.platform == "i686-linux" && settings.thisSystem == "x86_64-freebsd")
- || (drv.platform == "i686-linux" && settings.thisSystem == "i686-freebsd")
-#endif
- ;
-}
-
-
-static string get(const StringPairs & map, const string & key, const string & def = "")
-{
- StringPairs::const_iterator i = map.find(key);
- return i == map.end() ? def : i->second;
-}
-
-
-bool willBuildLocally(const BasicDerivation & drv)
-{
- return get(drv.env, "preferLocalBuild") == "1" && canBuildLocally(drv);
-}
-
-
-bool substitutesAllowed(const BasicDerivation & drv)
-{
- return get(drv.env, "allowSubstitutes", "1") == "1";
-}
-
-
void DerivationGoal::tryToBuild()
{
trace("trying to build");
@@ -1322,7 +1281,7 @@ void DerivationGoal::tryToBuild()
can't acquire the lock, then continue; hopefully some other
goal can start a build, and if not, the main loop will sleep a
few seconds and then retry this goal. */
- if (!outputLocks.lockPaths(outputPaths(*drv), "", false)) {
+ if (!outputLocks.lockPaths(drv->outputPaths(), "", false)) {
worker.waitForAWhile(shared_from_this());
return;
}
@@ -1342,7 +1301,7 @@ void DerivationGoal::tryToBuild()
return;
}
- missingPaths = outputPaths(*drv);
+ missingPaths = drv->outputPaths();
if (buildMode != bmCheck)
for (auto & i : validPaths) missingPaths.erase(i);
@@ -1365,7 +1324,7 @@ void DerivationGoal::tryToBuild()
/* Don't do a remote build if the derivation has the attribute
`preferLocalBuild' set. Also, check and repair modes are only
supported for local builds. */
- bool buildLocally = buildMode != bmNormal || willBuildLocally(*drv);
+ bool buildLocally = buildMode != bmNormal || drv->willBuildLocally();
/* Is the build hook willing to accept this job? */
if (!buildLocally) {
@@ -1661,7 +1620,7 @@ HookReply DerivationGoal::tryBuildHook()
list it since the remote system *probably* already has it.) */
PathSet allInputs;
allInputs.insert(inputPaths.begin(), inputPaths.end());
- computeFSClosure(worker.store, drvPath, allInputs);
+ worker.store.computeFSClosure(drvPath, allInputs);
string s;
for (auto & i : allInputs) { s += i; s += ' '; }
@@ -1716,7 +1675,7 @@ void DerivationGoal::startBuilder()
startNest(nest, lvlInfo, f % showPaths(missingPaths) % curRound % nrRounds);
/* Right platform? */
- if (!canBuildLocally(*drv)) {
+ if (!drv->canBuildLocally()) {
if (settings.printBuildTrace)
printMsg(lvlError, format("@ unsupported-platform %1% %2%") % drvPath % drv->platform);
throw Error(
@@ -1873,14 +1832,14 @@ void DerivationGoal::startBuilder()
like passing all build-time dependencies of some path to a
derivation that builds a NixOS DVD image. */
PathSet paths, paths2;
- computeFSClosure(worker.store, storePath, paths);
+ worker.store.computeFSClosure(storePath, paths);
paths2 = paths;
for (auto & j : paths2) {
if (isDerivation(j)) {
- Derivation drv = derivationFromPath(worker.store, j);
+ Derivation drv = worker.store.derivationFromPath(j);
for (auto & k : drv.outputs)
- computeFSClosure(worker.store, k.second.path, paths);
+ worker.store.computeFSClosure(k.second.path, paths);
}
}
@@ -1944,7 +1903,7 @@ void DerivationGoal::startBuilder()
PathSet closure;
for (auto & i : dirsInChroot)
if (isInStore(i.second))
- computeFSClosure(worker.store, toStorePath(i.second), closure);
+ worker.store.computeFSClosure(toStorePath(i.second), closure);
for (auto & i : closure)
dirsInChroot[i] = i;
@@ -2212,7 +2171,7 @@ void DerivationGoal::startBuilder()
#endif
{
ProcessOptions options;
- options.allowVfork = !buildUser.enabled() && !isBuiltin(*drv);
+ options.allowVfork = !buildUser.enabled() && !drv->isBuiltin();
pid = startProcess([&]() {
runChild();
}, options);
@@ -2466,7 +2425,7 @@ void DerivationGoal::runChild()
const char *builder = "invalid";
string sandboxProfile;
- if (isBuiltin(*drv)) {
+ if (drv->isBuiltin()) {
;
#if __APPLE__
} else if (useChroot) {
@@ -2583,7 +2542,7 @@ void DerivationGoal::runChild()
writeFull(STDERR_FILENO, string("\1\n"));
/* Execute the program. This should not return. */
- if (isBuiltin(*drv)) {
+ if (drv->isBuiltin()) {
try {
logType = ltFlat;
if (drv->builder == "builtin:fetchurl")
@@ -2813,7 +2772,7 @@ void DerivationGoal::registerOutputs()
for (auto & i : references)
/* Don't call computeFSClosure on ourselves. */
if (actualPath != i)
- computeFSClosure(worker.store, i, used);
+ worker.store.computeFSClosure(i, used);
} else
used = references;
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index 7959d5bfc..da1747da0 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -2,7 +2,6 @@
#include "store-api.hh"
#include "globals.hh"
#include "util.hh"
-#include "misc.hh"
#include "worker-protocol.hh"
@@ -27,7 +26,49 @@ void DerivationOutput::parseHashInfo(bool & recursive, HashType & hashType, Hash
}
-Path writeDerivation(StoreAPI & store,
+Path BasicDerivation::findOutput(const string & id) const
+{
+ auto i = outputs.find(id);
+ if (i == outputs.end())
+ throw Error(format("derivation has no output ‘%1%’") % id);
+ return i->second.path;
+}
+
+
+bool BasicDerivation::willBuildLocally() const
+{
+ return get(env, "preferLocalBuild") == "1" && canBuildLocally();
+}
+
+
+bool BasicDerivation::substitutesAllowed() const
+{
+ return get(env, "allowSubstitutes", "1") == "1";
+}
+
+
+bool BasicDerivation::isBuiltin() const
+{
+ return string(builder, 0, 8) == "builtin:";
+}
+
+
+bool BasicDerivation::canBuildLocally() const
+{
+ return platform == settings.thisSystem
+ || isBuiltin()
+#if __linux__
+ || (platform == "i686-linux" && settings.thisSystem == "x86_64-linux")
+ || (platform == "armv6l-linux" && settings.thisSystem == "armv7l-linux")
+#elif __FreeBSD__
+ || (platform == "i686-linux" && settings.thisSystem == "x86_64-freebsd")
+ || (platform == "i686-linux" && settings.thisSystem == "i686-freebsd")
+#endif
+ ;
+}
+
+
+Path writeDerivation(ref<StoreAPI> store,
const Derivation & drv, const string & name, bool repair)
{
PathSet references;
@@ -38,10 +79,10 @@ Path writeDerivation(StoreAPI & store,
(that can be missing (of course) and should not necessarily be
held during a garbage collection). */
string suffix = name + drvExtension;
- string contents = unparseDerivation(drv);
+ string contents = drv.unparse();
return settings.readOnlyMode
? computeStorePathForText(suffix, contents, references)
- : store.addTextToStore(suffix, contents, references, repair);
+ : store->addTextToStore(suffix, contents, references, repair);
}
@@ -149,14 +190,14 @@ static void printStrings(string & res, ForwardIterator i, ForwardIterator j)
}
-string unparseDerivation(const Derivation & drv)
+string Derivation::unparse() const
{
string s;
s.reserve(65536);
s += "Derive([";
bool first = true;
- for (auto & i : drv.outputs) {
+ for (auto & i : outputs) {
if (first) first = false; else s += ',';
s += '('; printString(s, i.first);
s += ','; printString(s, i.second.path);
@@ -167,7 +208,7 @@ string unparseDerivation(const Derivation & drv)
s += "],[";
first = true;
- for (auto & i : drv.inputDrvs) {
+ for (auto & i : inputDrvs) {
if (first) first = false; else s += ',';
s += '('; printString(s, i.first);
s += ','; printStrings(s, i.second.begin(), i.second.end());
@@ -175,15 +216,15 @@ string unparseDerivation(const Derivation & drv)
}
s += "],";
- printStrings(s, drv.inputSrcs.begin(), drv.inputSrcs.end());
+ printStrings(s, inputSrcs.begin(), inputSrcs.end());
- s += ','; printString(s, drv.platform);
- s += ','; printString(s, drv.builder);
- s += ','; printStrings(s, drv.args.begin(), drv.args.end());
+ s += ','; printString(s, platform);
+ s += ','; printString(s, builder);
+ s += ','; printStrings(s, args.begin(), args.end());
s += ",[";
first = true;
- for (auto & i : drv.env) {
+ for (auto & i : env) {
if (first) first = false; else s += ',';
s += '('; printString(s, i.first);
s += ','; printString(s, i.second);
@@ -202,11 +243,11 @@ bool isDerivation(const string & fileName)
}
-bool isFixedOutputDrv(const Derivation & drv)
+bool BasicDerivation::isFixedOutput() const
{
- return drv.outputs.size() == 1 &&
- drv.outputs.begin()->first == "out" &&
- drv.outputs.begin()->second.hash != "";
+ return outputs.size() == 1 &&
+ outputs.begin()->first == "out" &&
+ outputs.begin()->second.hash != "";
}
@@ -236,7 +277,7 @@ DrvHashes drvHashes;
Hash hashDerivationModulo(StoreAPI & store, Derivation drv)
{
/* Return a fixed hash for fixed-output derivations. */
- if (isFixedOutputDrv(drv)) {
+ if (drv.isFixedOutput()) {
DerivationOutputs::const_iterator i = drv.outputs.begin();
return hashString(htSHA256, "fixed:out:"
+ i->second.hashAlgo + ":"
@@ -259,7 +300,7 @@ Hash hashDerivationModulo(StoreAPI & store, Derivation drv)
}
drv.inputDrvs = inputs2;
- return hashString(htSHA256, unparseDerivation(drv));
+ return hashString(htSHA256, drv.unparse());
}
@@ -286,10 +327,10 @@ bool wantOutput(const string & output, const std::set<string> & wanted)
}
-PathSet outputPaths(const BasicDerivation & drv)
+PathSet BasicDerivation::outputPaths() const
{
PathSet paths;
- for (auto & i : drv.outputs)
+ for (auto & i : outputs)
paths.insert(i.second.path);
return paths;
}
diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh
index f0842045f..4dda10b45 100644
--- a/src/libstore/derivations.hh
+++ b/src/libstore/derivations.hh
@@ -50,11 +50,33 @@ struct BasicDerivation
StringPairs env;
virtual ~BasicDerivation() { };
+
+ /* Return the path corresponding to the output identifier `id' in
+ the given derivation. */
+ Path findOutput(const string & id) const;
+
+ bool willBuildLocally() const;
+
+ bool substitutesAllowed() const;
+
+ bool isBuiltin() const;
+
+ bool canBuildLocally() const;
+
+ /* Return true iff this is a fixed-output derivation. */
+ bool isFixedOutput() const;
+
+ /* Return the output paths of a derivation. */
+ PathSet outputPaths() const;
+
};
struct Derivation : BasicDerivation
{
DerivationInputs inputDrvs; /* inputs that are sub-derivations */
+
+ /* Print a derivation. */
+ std::string unparse() const;
};
@@ -62,28 +84,22 @@ class StoreAPI;
/* Write a derivation to the Nix store, and return its path. */
-Path writeDerivation(StoreAPI & store,
+Path writeDerivation(ref<StoreAPI> store,
const Derivation & drv, const string & name, bool repair = false);
/* Read a derivation from a file. */
Derivation readDerivation(const Path & drvPath);
-/* Print a derivation. */
-string unparseDerivation(const Derivation & drv);
-
-/* Check whether a file name ends with the extensions for
+/* Check whether a file name ends with the extension for
derivations. */
bool isDerivation(const string & fileName);
-/* Return true iff this is a fixed-output derivation. */
-bool isFixedOutputDrv(const Derivation & drv);
-
Hash hashDerivationModulo(StoreAPI & store, Derivation drv);
/* Memoisation of hashDerivationModulo(). */
typedef std::map<Path, Hash> DrvHashes;
-extern DrvHashes drvHashes;
+extern DrvHashes drvHashes; // FIXME: global, not thread-safe
/* Split a string specifying a derivation and a set of outputs
(/nix/store/hash-foo!out1,out2,...) into the derivation path and
@@ -95,8 +111,6 @@ Path makeDrvPathWithOutputs(const Path & drvPath, const std::set<string> & outpu
bool wantOutput(const string & output, const std::set<string> & wanted);
-PathSet outputPaths(const BasicDerivation & drv);
-
struct Source;
struct Sink;
diff --git a/src/libstore/download.cc b/src/libstore/download.cc
index 822e9a8db..5e50c1480 100644
--- a/src/libstore/download.cc
+++ b/src/libstore/download.cc
@@ -188,7 +188,7 @@ DownloadResult downloadFile(string url, const DownloadOptions & options)
}
-Path downloadFileCached(const string & url, bool unpack)
+Path downloadFileCached(ref<StoreAPI> store, const string & url, bool unpack)
{
Path cacheDir = getEnv("XDG_CACHE_HOME", getEnv("HOME", "") + "/.cache") + "/nix/tarballs";
createDirs(cacheDir);
diff --git a/src/libstore/download.hh b/src/libstore/download.hh
index c1cb25b90..a727936d1 100644
--- a/src/libstore/download.hh
+++ b/src/libstore/download.hh
@@ -1,6 +1,7 @@
#pragma once
#include "types.hh"
+
#include <string>
namespace nix {
@@ -18,9 +19,11 @@ struct DownloadResult
string data, etag;
};
+class StoreAPI;
+
DownloadResult downloadFile(string url, const DownloadOptions & options);
-Path downloadFileCached(const string & url, bool unpack);
+Path downloadFileCached(ref<StoreAPI> store, const string & url, bool unpack);
MakeError(DownloadError, Error)
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 998a7516a..9c158c3ee 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -1,5 +1,5 @@
+#include "derivations.hh"
#include "globals.hh"
-#include "misc.hh"
#include "local-store.hh"
#include <functional>
@@ -83,7 +83,7 @@ void LocalStore::addIndirectRoot(const Path & path)
}
-Path addPermRoot(StoreAPI & store, const Path & _storePath,
+Path addPermRoot(ref<StoreAPI> store, const Path & _storePath,
const Path & _gcRoot, bool indirect, bool allowOutsideRootsDir)
{
Path storePath(canonPath(_storePath));
@@ -101,7 +101,7 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot))))
throw Error(format("cannot create symlink ‘%1%’; already exists") % gcRoot);
makeSymlink(gcRoot, storePath);
- store.addIndirectRoot(gcRoot);
+ store->addIndirectRoot(gcRoot);
}
else {
@@ -127,7 +127,7 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
check if the root is in a directory in or linked from the
gcroots directory. */
if (settings.checkRootReachability) {
- Roots roots = store.findRoots();
+ Roots roots = store->findRoots();
if (roots.find(gcRoot) == roots.end())
printMsg(lvlError,
format(
@@ -139,7 +139,7 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath,
/* Grab the global GC root, causing us to block while a GC is in
progress. This prevents the set of permanent roots from
increasing while a GC is in progress. */
- store.syncWithGC();
+ store->syncWithGC();
return gcRoot;
}
@@ -260,19 +260,16 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
}
-static void foundRoot(StoreAPI & store,
- const Path & path, const Path & target, Roots & roots)
+void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
{
- Path storePath = toStorePath(target);
- if (store.isValidPath(storePath))
- roots[path] = storePath;
- else
- printMsg(lvlInfo, format("skipping invalid root from ‘%1%’ to ‘%2%’") % path % storePath);
-}
-
+ auto foundRoot = [&](const Path & path, const Path & target) {
+ Path storePath = toStorePath(target);
+ if (isValidPath(storePath))
+ roots[path] = storePath;
+ else
+ printMsg(lvlInfo, format("skipping invalid root from ‘%1%’ to ‘%2%’") % path % storePath);
+ };
-static void findRoots(StoreAPI & store, const Path & path, unsigned char type, Roots & roots)
-{
try {
if (type == DT_UNKNOWN)
@@ -280,13 +277,13 @@ static void findRoots(StoreAPI & store, const Path & path, unsigned char type, R
if (type == DT_DIR) {
for (auto & i : readDirectory(path))
- findRoots(store, path + "/" + i.name, i.type, roots);
+ findRoots(path + "/" + i.name, i.type, roots);
}
else if (type == DT_LNK) {
Path target = readLink(path);
if (isInStore(target))
- foundRoot(store, path, target, roots);
+ foundRoot(path, target);
/* Handle indirect roots. */
else {
@@ -300,14 +297,14 @@ static void findRoots(StoreAPI & store, const Path & path, unsigned char type, R
struct stat st2 = lstat(target);
if (!S_ISLNK(st2.st_mode)) return;
Path target2 = readLink(target);
- if (isInStore(target2)) foundRoot(store, target, target2, roots);
+ if (isInStore(target2)) foundRoot(target, target2);
}
}
}
else if (type == DT_REG) {
Path storePath = settings.nixStore + "/" + baseNameOf(path);
- if (store.isValidPath(storePath))
+ if (isValidPath(storePath))
roots[path] = storePath;
}
@@ -328,16 +325,16 @@ Roots LocalStore::findRoots()
Roots roots;
/* Process direct roots in {gcroots,manifests,profiles}. */
- nix::findRoots(*this, settings.nixStateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
+ findRoots(settings.nixStateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
if (pathExists(settings.nixStateDir + "/manifests"))
- nix::findRoots(*this, settings.nixStateDir + "/manifests", DT_UNKNOWN, roots);
- nix::findRoots(*this, settings.nixStateDir + "/profiles", DT_UNKNOWN, roots);
+ findRoots(settings.nixStateDir + "/manifests", DT_UNKNOWN, roots);
+ findRoots(settings.nixStateDir + "/profiles", DT_UNKNOWN, roots);
return roots;
}
-static void addAdditionalRoots(StoreAPI & store, PathSet & roots)
+void LocalStore::findRuntimeRoots(PathSet & roots)
{
Path rootFinder = getEnv("NIX_ROOT_FINDER",
settings.nixLibexecDir + "/nix/find-runtime-roots.pl");
@@ -353,7 +350,7 @@ static void addAdditionalRoots(StoreAPI & store, PathSet & roots)
for (auto & i : paths)
if (isInStore(i)) {
Path path = toStorePath(i);
- if (roots.find(path) == roots.end() && store.isValidPath(path)) {
+ if (roots.find(path) == roots.end() && isValidPath(path)) {
debug(format("got additional root ‘%1%’") % path);
roots.insert(path);
}
@@ -628,7 +625,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
to add running programs to the set of roots (to prevent them
from being garbage collected). */
if (!options.ignoreLiveness)
- addAdditionalRoots(*this, state.roots);
+ findRuntimeRoots(state.roots);
/* Read the temporary roots. This acquires read locks on all
per-process temporary root files. So after this point no paths
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 55bd3e70e..13179459f 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -655,7 +655,7 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation &
assert(isDerivation(drvName));
drvName = string(drvName, 0, drvName.size() - drvExtension.size());
- if (isFixedOutputDrv(drv)) {
+ if (drv.isFixedOutput()) {
DerivationOutputs::const_iterator out = drv.outputs.find("out");
if (out == drv.outputs.end())
throw Error(format("derivation ‘%1%’ does not have an output named ‘out’") % drvPath);
@@ -1335,7 +1335,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
error if a cycle is detected and roll back the
transaction. Cycles can only occur when a derivation
has multiple outputs. */
- topoSortPaths(*this, paths);
+ topoSortPaths(paths);
txn.commit();
} end_retry_sqlite;
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index 5b27f9072..3ef042b61 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -303,6 +303,10 @@ private:
int openGCLock(LockType lockType);
+ void findRoots(const Path & path, unsigned char type, Roots & roots);
+
+ void findRuntimeRoots(PathSet & roots);
+
void removeUnusedLinks(const GCState & state);
void startSubstituter(const Path & substituter,
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc
index 61a976c02..032dfe658 100644
--- a/src/libstore/misc.cc
+++ b/src/libstore/misc.cc
@@ -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);
-}
-
-
-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);
+ computeFSClosure(i, paths, flipDirection, includeOutputs, includeDerivers);
}
-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)
+Paths StoreAPI::topoSortPaths(const PathSet & paths)
{
- if (parents.find(path) != parents.end())
- throw BuildError(format("cycle detected in the references of ‘%1%’") % path);
+ Paths sorted;
+ PathSet visited, parents;
- if (visited.find(path) != visited.end()) return;
- visited.insert(path);
- parents.insert(path);
+ std::function<void(const Path & path)> dfsVisit;
- PathSet references;
- if (store.isValidPath(path))
- store.queryReferences(path, references);
+ dfsVisit = [&](const Path & path) {
+ if (parents.find(path) != parents.end())
+ throw BuildError(format("cycle detected in the references of ‘%1%’") % path);
- 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);
+ if (visited.find(path) != visited.end()) return;
+ visited.insert(path);
+ parents.insert(path);
- sorted.push_front(path);
- parents.erase(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);
+ };
-Paths topoSortPaths(StoreAPI & store, const PathSet & paths)
-{
- Paths sorted;
- PathSet visited, parents;
for (auto & i : paths)
- dfsVisit(store, paths, i, visited, sorted, parents);
+ dfsVisit(i);
+
return sorted;
}
diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh
deleted file mode 100644
index 495c52875..000000000
--- a/src/libstore/misc.hh
+++ /dev/null
@@ -1,40 +0,0 @@
-#pragma once
-
-#include "derivations.hh"
-
-
-namespace nix {
-
-
-/* Read a derivation, after ensuring its existence through
- ensurePath(). */
-Derivation derivationFromPath(StoreAPI & store, const Path & drvPath);
-
-/* Place in `paths' the set of all store paths in the file system
- closure of `storePath'; that is, all paths than can be directly or
- indirectly reached from it. `paths' is not cleared. If
- `flipDirection' is true, the set of paths that can reach
- `storePath' is returned; that is, the closures under the
- `referrers' relation instead of the `references' relation is
- returned. */
-void computeFSClosure(StoreAPI & store, const Path & path,
- PathSet & paths, bool flipDirection = false,
- bool includeOutputs = false, bool includeDerivers = false);
-
-/* Return the path corresponding to the output identifier `id' in the
- given derivation. */
-Path findOutput(const Derivation & drv, string id);
-
-/* Given a set of paths that are to be built, return the set of
- derivations that will be built, and the set of output paths that
- will be substituted. */
-void queryMissing(StoreAPI & store, const PathSet & targets,
- PathSet & willBuild, PathSet & willSubstitute, PathSet & unknown,
- unsigned long long & downloadSize, unsigned long long & narSize);
-
-bool willBuildLocally(const BasicDerivation & drv);
-
-bool substitutesAllowed(const BasicDerivation & drv);
-
-
-}
diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc
index da3f7da9d..4903b12f6 100644
--- a/src/libstore/profiles.cc
+++ b/src/libstore/profiles.cc
@@ -74,7 +74,7 @@ static void makeName(const Path & profile, unsigned int num,
}
-Path createGeneration(Path profile, Path outPath)
+Path createGeneration(ref<StoreAPI> store, Path profile, Path outPath)
{
/* The new generation number should be higher than old the
previous ones. */
@@ -108,7 +108,7 @@ Path createGeneration(Path profile, Path outPath)
user environment etc. we've just built. */
Path generation;
makeName(profile, num + 1, generation);
- addPermRoot(*store, outPath, generation, false, true);
+ addPermRoot(store, outPath, generation, false, true);
return generation;
}
diff --git a/src/libstore/profiles.hh b/src/libstore/profiles.hh
index e99bbf398..37d8ec999 100644
--- a/src/libstore/profiles.hh
+++ b/src/libstore/profiles.hh
@@ -31,7 +31,9 @@ typedef list<Generation> Generations;
profile, sorted by generation number. */
Generations findGenerations(Path profile, int & curGen);
-Path createGeneration(Path profile, Path outPath);
+class StoreAPI;
+
+Path createGeneration(ref<StoreAPI> store, Path profile, Path outPath);
void deleteGeneration(const Path & profile, unsigned int gen);
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index f5035d323..98399cc48 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -284,12 +284,12 @@ string showPaths(const PathSet & paths)
}
-void exportPaths(StoreAPI & store, const Paths & paths,
+void StoreAPI::exportPaths(const Paths & paths,
bool sign, Sink & sink)
{
for (auto & i : paths) {
sink << 1;
- store.exportPath(i, sign, sink);
+ exportPath(i, sign, sink);
}
sink << 0;
}
@@ -306,10 +306,7 @@ void exportPaths(StoreAPI & store, const Paths & paths,
namespace nix {
-std::shared_ptr<StoreAPI> store;
-
-
-std::shared_ptr<StoreAPI> openStore(bool reserveSpace)
+ref<StoreAPI> openStore(bool reserveSpace)
{
enum { mDaemon, mLocal, mAuto } mode;
@@ -325,8 +322,8 @@ std::shared_ptr<StoreAPI> openStore(bool reserveSpace)
}
return mode == mDaemon
- ? (std::shared_ptr<StoreAPI>) std::make_shared<RemoteStore>()
- : std::make_shared<LocalStore>(reserveSpace);
+ ? make_ref<StoreAPI, RemoteStore>()
+ : make_ref<StoreAPI, LocalStore>(reserveSpace);
}
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 9fa137030..ce085ff55 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -132,6 +132,7 @@ struct BuildResult
struct BasicDerivation;
+struct Derivation;
class StoreAPI
@@ -214,6 +215,10 @@ public:
virtual void exportPath(const Path & path, bool sign,
Sink & sink) = 0;
+ /* Export multiple paths in the format expected by ‘nix-store
+ --import’. */
+ void exportPaths(const Paths & paths, bool sign, Sink & sink);
+
/* Import a sequence of NAR dumps created by exportPaths() into
the Nix store. */
virtual Paths importPaths(bool requireSignature, Source & source) = 0;
@@ -298,6 +303,35 @@ public:
/* Check the integrity of the Nix store. Returns true if errors
remain. */
virtual bool verifyStore(bool checkContents, bool repair) = 0;
+
+ /* Utility functions. */
+
+ /* Read a derivation, after ensuring its existence through
+ ensurePath(). */
+ Derivation derivationFromPath(const Path & drvPath);
+
+ /* Place in `paths' the set of all store paths in the file system
+ closure of `storePath'; that is, all paths than can be directly
+ or indirectly reached from it. `paths' is not cleared. If
+ `flipDirection' is true, the set of paths that can reach
+ `storePath' is returned; that is, the closures under the
+ `referrers' relation instead of the `references' relation is
+ returned. */
+ void computeFSClosure(const Path & path,
+ PathSet & paths, bool flipDirection = false,
+ bool includeOutputs = false, bool includeDerivers = false);
+
+ /* Given a set of paths that are to be built, return the set of
+ derivations that will be built, and the set of output paths
+ that will be substituted. */
+ void queryMissing(const PathSet & targets,
+ PathSet & willBuild, PathSet & willSubstitute, PathSet & unknown,
+ unsigned long long & downloadSize, unsigned long long & narSize);
+
+ /* Sort a set of paths topologically under the references
+ relation. If p refers to q, then p preceeds q in this list. */
+ Paths topoSortPaths(const PathSet & paths);
+
};
@@ -373,23 +407,13 @@ void removeTempRoots();
/* Register a permanent GC root. */
-Path addPermRoot(StoreAPI & store, const Path & storePath,
+Path addPermRoot(ref<StoreAPI> store, const Path & storePath,
const Path & gcRoot, bool indirect, bool allowOutsideRootsDir = false);
-/* Sort a set of paths topologically under the references relation.
- If p refers to q, then p preceeds q in this list. */
-Paths topoSortPaths(StoreAPI & store, const PathSet & paths);
-
-
-/* For now, there is a single global store API object, but we'll
- purify that in the future. */
-extern std::shared_ptr<StoreAPI> store;
-
-
/* Factory method: open the Nix database, either through the local or
remote implementation. */
-std::shared_ptr<StoreAPI> openStore(bool reserveSpace = true);
+ref<StoreAPI> openStore(bool reserveSpace = true);
/* Display a set of paths in human-readable form (i.e., between quotes
@@ -401,12 +425,6 @@ ValidPathInfo decodeValidPathInfo(std::istream & str,
bool hashGiven = false);
-/* Export multiple paths in the format expected by ‘nix-store
- --import’. */
-void exportPaths(StoreAPI & store, const Paths & paths,
- bool sign, Sink & sink);
-
-
MakeError(SubstError, Error)
MakeError(BuildError, Error) /* denotes a permanent build failure */
diff --git a/src/libutil/types.hh b/src/libutil/types.hh
index 160884ee1..23eb52512 100644
--- a/src/libutil/types.hh
+++ b/src/libutil/types.hh
@@ -5,6 +5,7 @@
#include <string>
#include <list>
#include <set>
+#include <memory>
#include <boost/format.hpp>
@@ -96,4 +97,70 @@ typedef enum {
} Verbosity;
+/* A simple non-nullable reference-counted pointer. Actually a wrapper
+ around std::shared_ptr that prevents non-null constructions. */
+template<typename T>
+class ref
+{
+private:
+
+ std::shared_ptr<T> p;
+
+public:
+
+ ref<T>(const ref<T> & r)
+ : p(r.p)
+ { }
+
+ explicit ref<T>(const std::shared_ptr<T> & p)
+ : p(p)
+ {
+ if (!p)
+ throw std::invalid_argument("null pointer cast to ref");
+ }
+
+ T* operator ->() const
+ {
+ return &*p;
+ }
+
+ T& operator *() const
+ {
+ return *p;
+ }
+
+ operator std::shared_ptr<T> ()
+ {
+ return p;
+ }
+
+private:
+
+ template<typename T2, typename... Args>
+ friend ref<T2>
+ make_ref(Args&&... args);
+
+ template<typename T2, typename T3, typename... Args>
+ friend ref<T2>
+ make_ref(Args&&... args);
+
+};
+
+template<typename T, typename... Args>
+inline ref<T>
+make_ref(Args&&... args)
+{
+ auto p = std::make_shared<T>(std::forward<Args>(args)...);
+ return ref<T>(p);
+}
+
+template<typename T, typename T2, typename... Args>
+inline ref<T>
+make_ref(Args&&... args)
+{
+ auto p = std::make_shared<T2>(std::forward<Args>(args)...);
+ return ref<T>(p);
+}
+
+
}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index a889ef2f1..b714cdc64 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -413,4 +413,14 @@ string base64Encode(const string & s);
string base64Decode(const string & s);
+/* Get a value for the specified key from an associate container, or a
+ default value if the key doesn't exist. */
+template <class T>
+string get(const T & map, const string & key, const string & def = "")
+{
+ auto i = map.find(key);
+ return i == map.end() ? def : i->second;
+}
+
+
}
diff --git a/src/nix-collect-garbage/nix-collect-garbage.cc b/src/nix-collect-garbage/nix-collect-garbage.cc
index 5a72cb712..b9ccafb75 100644
--- a/src/nix-collect-garbage/nix-collect-garbage.cc
+++ b/src/nix-collect-garbage/nix-collect-garbage.cc
@@ -82,7 +82,7 @@ int main(int argc, char * * argv)
// Run the actual garbage collector.
if (!dryRun) {
- store = openStore(false);
+ auto store = openStore(false);
options.action = GCOptions::gcDeleteDead;
GCResults results;
PrintFreed freed(true, results);
diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc
index c5e11afa1..aa20aa67d 100644
--- a/src/nix-daemon/nix-daemon.cc
+++ b/src/nix-daemon/nix-daemon.cc
@@ -149,7 +149,7 @@ struct SavingSourceAdapter : Source
};
-static void performOp(bool trusted, unsigned int clientVersion,
+static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVersion,
Source & from, Sink & to, unsigned int op)
{
switch (op) {
@@ -278,8 +278,7 @@ static void performOp(bool trusted, unsigned int clientVersion,
startWork();
if (!savedRegular.regular) throw Error("regular file expected");
- Path path = dynamic_cast<LocalStore *>(store.get())
- ->addToStoreFromDump(recursive ? savedNAR.s : savedRegular.s, baseName, recursive, hashAlgo);
+ Path path = store->addToStoreFromDump(recursive ? savedNAR.s : savedRegular.s, baseName, recursive, hashAlgo);
stopWork();
to << path;
@@ -583,56 +582,56 @@ static void processConnection(bool trusted)
#endif
/* Open the store. */
- store = std::shared_ptr<StoreAPI>(new LocalStore(reserveSpace));
+ auto store = make_ref<LocalStore>(reserveSpace);
stopWork();
to.flush();
- } catch (Error & e) {
- stopWork(false, e.msg(), GET_PROTOCOL_MINOR(clientVersion) >= 8 ? 1 : 0);
- to.flush();
- return;
- }
+ /* Process client requests. */
+ unsigned int opCount = 0;
+
+ while (true) {
+ WorkerOp op;
+ try {
+ op = (WorkerOp) readInt(from);
+ } catch (Interrupted & e) {
+ break;
+ } catch (EndOfFile & e) {
+ break;
+ }
- /* Process client requests. */
- unsigned int opCount = 0;
+ opCount++;
+
+ try {
+ performOp(store, trusted, clientVersion, from, to, op);
+ } catch (Error & e) {
+ /* If we're not in a state where we can send replies, then
+ something went wrong processing the input of the
+ client. This can happen especially if I/O errors occur
+ during addTextToStore() / importPath(). If that
+ happens, just send the error message and exit. */
+ bool errorAllowed = canSendStderr;
+ stopWork(false, e.msg(), GET_PROTOCOL_MINOR(clientVersion) >= 8 ? e.status : 0);
+ if (!errorAllowed) throw;
+ } catch (std::bad_alloc & e) {
+ stopWork(false, "Nix daemon out of memory", GET_PROTOCOL_MINOR(clientVersion) >= 8 ? 1 : 0);
+ throw;
+ }
- while (true) {
- WorkerOp op;
- try {
- op = (WorkerOp) readInt(from);
- } catch (Interrupted & e) {
- break;
- } catch (EndOfFile & e) {
- break;
- }
+ to.flush();
- opCount++;
+ assert(!canSendStderr);
+ };
- try {
- performOp(trusted, clientVersion, from, to, op);
- } catch (Error & e) {
- /* If we're not in a state where we can send replies, then
- something went wrong processing the input of the
- client. This can happen especially if I/O errors occur
- during addTextToStore() / importPath(). If that
- happens, just send the error message and exit. */
- bool errorAllowed = canSendStderr;
- stopWork(false, e.msg(), GET_PROTOCOL_MINOR(clientVersion) >= 8 ? e.status : 0);
- if (!errorAllowed) throw;
- } catch (std::bad_alloc & e) {
- stopWork(false, "Nix daemon out of memory", GET_PROTOCOL_MINOR(clientVersion) >= 8 ? 1 : 0);
- throw;
- }
+ canSendStderr = false;
+ _isInterrupted = false;
+ printMsg(lvlDebug, format("%1% operations") % opCount);
+ } catch (Error & e) {
+ stopWork(false, e.msg(), GET_PROTOCOL_MINOR(clientVersion) >= 8 ? 1 : 0);
to.flush();
-
- assert(!canSendStderr);
- };
-
- canSendStderr = false;
- _isInterrupted = false;
- printMsg(lvlDebug, format("%1% operations") % opCount);
+ return;
+ }
}
@@ -787,10 +786,6 @@ static void daemonLoop(char * * argv)
while (1) {
try {
- /* Important: the server process *cannot* open the SQLite
- database, because it doesn't like forks very much. */
- assert(!store);
-
/* Accept a connection. */
struct sockaddr_un remoteAddr;
socklen_t remoteAddrLen = sizeof(remoteAddr);
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 02a9f25a7..12e19d4af 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -1,17 +1,17 @@
-#include "profiles.hh"
-#include "names.hh"
-#include "globals.hh"
-#include "misc.hh"
-#include "shared.hh"
-#include "eval.hh"
-#include "get-drvs.hh"
#include "attr-path.hh"
#include "common-opts.hh"
-#include "xml-writer.hh"
+#include "derivations.hh"
+#include "eval.hh"
+#include "get-drvs.hh"
+#include "globals.hh"
+#include "names.hh"
+#include "profiles.hh"
+#include "shared.hh"
#include "store-api.hh"
#include "user-env.hh"
#include "util.hh"
#include "value-to-json.hh"
+#include "xml-writer.hh"
#include <cerrno>
#include <ctime>
@@ -223,8 +223,8 @@ static int comparePriorities(EvalState & state, DrvInfo & drv1, DrvInfo & drv2)
static bool isPrebuilt(EvalState & state, DrvInfo & elem)
{
Path path = elem.queryOutPath();
- if (store->isValidPath(path)) return true;
- PathSet ps = store->querySubstitutablePaths(singleton<PathSet>(path));
+ if (state.store->isValidPath(path)) return true;
+ PathSet ps = state.store->querySubstitutablePaths(singleton<PathSet>(path));
return ps.find(path) != ps.end();
}
@@ -398,7 +398,7 @@ static void queryInstSources(EvalState & state,
if (isDerivation(path)) {
elem.setDrvPath(path);
- elem.setOutPath(findOutput(derivationFromPath(*store, path), "out"));
+ elem.setOutPath(state.store->derivationFromPath(path).findOutput("out"));
if (name.size() >= drvExtension.size() &&
string(name, name.size() - drvExtension.size()) == drvExtension)
name = string(name, 0, name.size() - drvExtension.size());
@@ -445,7 +445,7 @@ static void printMissing(EvalState & state, DrvInfos & elems)
targets.insert(i.queryOutPath());
}
- printMissing(*store, targets);
+ printMissing(state.store, targets);
}
@@ -711,18 +711,18 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
if (drv.queryDrvPath() != "") {
PathSet paths = singleton<PathSet>(drv.queryDrvPath());
- printMissing(*store, paths);
+ printMissing(globals.state->store, paths);
if (globals.dryRun) return;
- store->buildPaths(paths, globals.state->repair ? bmRepair : bmNormal);
+ globals.state->store->buildPaths(paths, globals.state->repair ? bmRepair : bmNormal);
}
else {
- printMissing(*store, singleton<PathSet>(drv.queryOutPath()));
+ printMissing(globals.state->store, singleton<PathSet>(drv.queryOutPath()));
if (globals.dryRun) return;
- store->ensurePath(drv.queryOutPath());
+ globals.state->store->ensurePath(drv.queryOutPath());
}
debug(format("switching to new user environment"));
- Path generation = createGeneration(globals.profile, drv.queryOutPath());
+ Path generation = createGeneration(globals.state->store, globals.profile, drv.queryOutPath());
switchLink(globals.profile, generation);
}
@@ -973,8 +973,8 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
printMsg(lvlTalkative, format("skipping derivation named ‘%1%’ which gives an assertion failure") % i.name);
i.setFailed();
}
- validPaths = store->queryValidPaths(paths);
- substitutablePaths = store->querySubstitutablePaths(paths);
+ validPaths = globals.state->store->queryValidPaths(paths);
+ substitutablePaths = globals.state->store->querySubstitutablePaths(paths);
}
@@ -1394,9 +1394,9 @@ int main(int argc, char * * argv)
if (!op) throw UsageError("no operation specified");
- store = openStore();
+ auto store = openStore();
- globals.state = std::shared_ptr<EvalState>(new EvalState(searchPath));
+ globals.state = std::shared_ptr<EvalState>(new EvalState(searchPath, store));
globals.state->repair = repair;
if (file != "")
diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc
index 9a20b9433..4e0e28c11 100644
--- a/src/nix-env/user-env.cc
+++ b/src/nix-env/user-env.cc
@@ -38,7 +38,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
drvsToBuild.insert(i.queryDrvPath());
debug(format("building user environment dependencies"));
- store->buildPaths(drvsToBuild, state.repair ? bmRepair : bmNormal);
+ state.store->buildPaths(drvsToBuild, state.repair ? bmRepair : bmNormal);
/* Construct the whole top level derivation. */
PathSet references;
@@ -76,8 +76,8 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* This is only necessary when installing store paths, e.g.,
`nix-env -i /nix/store/abcd...-foo'. */
- store->addTempRoot(j.second);
- store->ensurePath(j.second);
+ state.store->addTempRoot(j.second);
+ state.store->ensurePath(j.second);
references.insert(j.second);
}
@@ -100,7 +100,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* Also write a copy of the list of user environment elements to
the store; we need it for future modifications of the
environment. */
- Path manifestFile = store->addTextToStore("env-manifest.nix",
+ Path manifestFile = state.store->addTextToStore("env-manifest.nix",
(format("%1%") % manifest).str(), references);
/* Get the environment builder expression. */
@@ -128,7 +128,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* Realise the resulting store expression. */
debug("building user environment");
- store->buildPaths(singleton<PathSet>(topLevelDrv), state.repair ? bmRepair : bmNormal);
+ state.store->buildPaths(singleton<PathSet>(topLevelDrv), state.repair ? bmRepair : bmNormal);
/* Switch the current user environment to the output path. */
PathLocks lock;
@@ -141,7 +141,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
}
debug(format("switching to new user environment"));
- Path generation = createGeneration(profile, topLevelOut);
+ Path generation = createGeneration(state.store, profile, topLevelOut);
switchLink(profile, generation);
return true;
diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc
index 13a145a3b..a20c5ce63 100644
--- a/src/nix-instantiate/nix-instantiate.cc
+++ b/src/nix-instantiate/nix-instantiate.cc
@@ -9,7 +9,6 @@
#include "util.hh"
#include "store-api.hh"
#include "common-opts.hh"
-#include "misc.hh"
#include <map>
#include <iostream>
@@ -33,7 +32,7 @@ static bool indirectRoot = false;
enum OutputKind { okPlain, okXML, okJSON };
-void processExpr(EvalState & state, const Strings & attrPaths,
+void processExpr(ref<StoreAPI> store, EvalState & state, const Strings & attrPaths,
bool parseOnly, bool strict, Bindings & autoArgs,
bool evalOnly, OutputKind output, bool location, Expr * e)
{
@@ -80,7 +79,7 @@ void processExpr(EvalState & state, const Strings & attrPaths,
else {
Path rootName = gcRoot;
if (++rootNr > 1) rootName += "-" + std::to_string(rootNr);
- drvPath = addPermRoot(*store, drvPath, rootName, indirectRoot);
+ drvPath = addPermRoot(store, drvPath, rootName, indirectRoot);
}
std::cout << format("%1%%2%\n") % drvPath % (outputName != "out" ? "!" + outputName : "");
}
@@ -158,9 +157,9 @@ int main(int argc, char * * argv)
if (evalOnly && !wantsReadWrite)
settings.readOnlyMode = true;
- store = openStore();
+ auto store = openStore();
- EvalState state(searchPath);
+ EvalState state(searchPath, store);
state.repair = repair;
Bindings & autoArgs(*evalAutoArgs(state, autoArgs_));
@@ -178,7 +177,7 @@ int main(int argc, char * * argv)
if (readStdin) {
Expr * e = parseStdin(state);
- processExpr(state, attrPaths, parseOnly, strict, autoArgs,
+ processExpr(store, state, attrPaths, parseOnly, strict, autoArgs,
evalOnly, outputKind, xmlOutputSourceLocation, e);
} else if (files.empty() && !fromArgs)
files.push_back("./default.nix");
@@ -187,7 +186,7 @@ int main(int argc, char * * argv)
Expr * e = fromArgs
? state.parseExprFromString(i, absPath("."))
: state.parseExprFromFile(resolveExprPath(lookupFileArg(state, i)));
- processExpr(state, attrPaths, parseOnly, strict, autoArgs,
+ processExpr(store, state, attrPaths, parseOnly, strict, autoArgs,
evalOnly, outputKind, xmlOutputSourceLocation, e);
}
diff --git a/src/nix-prefetch-url/nix-prefetch-url.cc b/src/nix-prefetch-url/nix-prefetch-url.cc
index 73a2845e0..c0c05a60b 100644
--- a/src/nix-prefetch-url/nix-prefetch-url.cc
+++ b/src/nix-prefetch-url/nix-prefetch-url.cc
@@ -91,8 +91,8 @@ int main(int argc, char * * argv)
if (args.size() > 2)
throw UsageError("too many arguments");
- store = openStore();
- EvalState state(searchPath);
+ auto store = openStore();
+ EvalState state(searchPath, store);
Bindings & autoArgs(*evalAutoArgs(state, autoArgs_));
diff --git a/src/nix-store/dotgraph.cc b/src/nix-store/dotgraph.cc
index af4cd48e7..326c668e0 100644
--- a/src/nix-store/dotgraph.cc
+++ b/src/nix-store/dotgraph.cc
@@ -94,7 +94,7 @@ void printClosure(const Path & nePath, const StoreExpr & fs)
#endif
-void printDotGraph(const PathSet & roots)
+void printDotGraph(StoreAPI & store, const PathSet & roots)
{
PathSet workList(roots);
PathSet doneSet;
@@ -111,7 +111,7 @@ void printDotGraph(const PathSet & roots)
cout << makeNode(path, symbolicName(path), "#ff0000");
PathSet references;
- store->queryReferences(path, references);
+ store.queryReferences(path, references);
for (PathSet::iterator i = references.begin();
i != references.end(); ++i)
diff --git a/src/nix-store/dotgraph.hh b/src/nix-store/dotgraph.hh
index 68410d841..d3b37642c 100644
--- a/src/nix-store/dotgraph.hh
+++ b/src/nix-store/dotgraph.hh
@@ -4,6 +4,8 @@
namespace nix {
-void printDotGraph(const PathSet & roots);
+class StoreAPI;
+
+void printDotGraph(StoreAPI & store, const PathSet & roots);
}
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index df6afd979..d5242492e 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -1,14 +1,14 @@
-#include "globals.hh"
-#include "misc.hh"
#include "archive.hh"
-#include "shared.hh"
+#include "derivations.hh"
#include "dotgraph.hh"
-#include "xmlgraph.hh"
+#include "globals.hh"
#include "local-store.hh"
-#include "util.hh"
+#include "monitor-fd.hh"
#include "serve-protocol.hh"
+#include "shared.hh"
+#include "util.hh"
#include "worker-protocol.hh"
-#include "monitor-fd.hh"
+#include "xmlgraph.hh"
#include <iostream>
#include <algorithm>
@@ -37,6 +37,7 @@ static Path gcRoot;
static int rootNr = 0;
static bool indirectRoot = false;
static bool noOutput = false;
+static std::shared_ptr<StoreAPI> store;
LocalStore & ensureLocalStore()
@@ -65,7 +66,7 @@ static PathSet realisePath(Path path, bool build = true)
if (isDerivation(p.first)) {
if (build) store->buildPaths(singleton<PathSet>(path));
- Derivation drv = derivationFromPath(*store, p.first);
+ Derivation drv = store->derivationFromPath(p.first);
rootNr++;
if (p.second.empty())
@@ -83,7 +84,7 @@ static PathSet realisePath(Path path, bool build = true)
Path rootName = gcRoot;
if (rootNr > 1) rootName += "-" + std::to_string(rootNr);
if (i->first != "out") rootName += "-" + i->first;
- outPath = addPermRoot(*store, outPath, rootName, indirectRoot);
+ outPath = addPermRoot(ref<StoreAPI>(store), outPath, rootName, indirectRoot);
}
outputs.insert(outPath);
}
@@ -99,7 +100,7 @@ static PathSet realisePath(Path path, bool build = true)
Path rootName = gcRoot;
rootNr++;
if (rootNr > 1) rootName += "-" + std::to_string(rootNr);
- path = addPermRoot(*store, path, rootName, indirectRoot);
+ path = addPermRoot(ref<StoreAPI>(store), path, rootName, indirectRoot);
}
return singleton<PathSet>(path);
}
@@ -129,7 +130,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
unsigned long long downloadSize, narSize;
PathSet willBuild, willSubstitute, unknown;
- queryMissing(*store, PathSet(paths.begin(), paths.end()),
+ store->queryMissing(PathSet(paths.begin(), paths.end()),
willBuild, willSubstitute, unknown, downloadSize, narSize);
if (ignoreUnknown) {
@@ -141,7 +142,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
}
if (settings.get("print-missing", true))
- printMissing(*store, willBuild, willSubstitute, unknown, downloadSize, narSize);
+ printMissing(ref<StoreAPI>(store), willBuild, willSubstitute, unknown, downloadSize, narSize);
if (dryRun) return;
@@ -216,7 +217,7 @@ static PathSet maybeUseOutputs(const Path & storePath, bool useOutput, bool forc
{
if (forceRealise) realisePath(storePath);
if (useOutput && isDerivation(storePath)) {
- Derivation drv = derivationFromPath(*store, storePath);
+ Derivation drv = store->derivationFromPath(storePath);
PathSet outputs;
for (auto & i : drv.outputs)
outputs.insert(i.second.path);
@@ -253,7 +254,7 @@ static void printTree(const Path & 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. */
- Paths sorted = topoSortPaths(*store, references);
+ Paths sorted = store->topoSortPaths(references);
reverse(sorted.begin(), sorted.end());
for (auto i = sorted.begin(); i != sorted.end(); ++i) {
@@ -318,7 +319,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (auto & i : opArgs) {
i = followLinksToStorePath(i);
if (forceRealise) realisePath(i);
- Derivation drv = derivationFromPath(*store, i);
+ Derivation drv = store->derivationFromPath(i);
for (auto & j : drv.outputs)
cout << format("%1%\n") % j.second.path;
}
@@ -333,13 +334,13 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (auto & i : opArgs) {
PathSet ps = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
for (auto & j : ps) {
- if (query == qRequisites) computeFSClosure(*store, j, paths, false, includeOutputs);
+ if (query == qRequisites) store->computeFSClosure(j, paths, false, includeOutputs);
else if (query == qReferences) store->queryReferences(j, paths);
else if (query == qReferrers) store->queryReferrers(j, paths);
- else if (query == qReferrersClosure) computeFSClosure(*store, j, paths, true);
+ else if (query == qReferrersClosure) store->computeFSClosure(j, paths, true);
}
}
- Paths sorted = topoSortPaths(*store, paths);
+ Paths sorted = store->topoSortPaths(paths);
for (Paths::reverse_iterator i = sorted.rbegin();
i != sorted.rend(); ++i)
cout << format("%s\n") % *i;
@@ -357,7 +358,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qBinding:
for (auto & i : opArgs) {
Path path = useDeriver(followLinksToStorePath(i));
- Derivation drv = derivationFromPath(*store, path);
+ Derivation drv = store->derivationFromPath(path);
StringPairs::iterator j = drv.env.find(bindingName);
if (j == drv.env.end())
throw Error(format("derivation ‘%1%’ has no environment binding named ‘%2%’")
@@ -394,7 +395,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
roots.insert(paths.begin(), paths.end());
}
- printDotGraph(roots);
+ printDotGraph(*store, roots);
break;
}
@@ -404,7 +405,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
roots.insert(paths.begin(), paths.end());
}
- printXmlGraph(roots);
+ printXmlGraph(*store, roots);
break;
}
@@ -419,7 +420,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
for (auto & i : opArgs) {
PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
for (auto & j : paths)
- computeFSClosure(*store, j, referrers, true,
+ store->computeFSClosure(j, referrers, true,
settings.gcKeepOutputs, settings.gcKeepDerivations);
}
Roots roots = store->findRoots();
@@ -450,7 +451,7 @@ static void opPrintEnv(Strings opFlags, Strings opArgs)
if (opArgs.size() != 1) throw UsageError("‘--print-env’ requires one derivation store path");
Path drvPath = opArgs.front();
- Derivation drv = derivationFromPath(*store, drvPath);
+ Derivation drv = store->derivationFromPath(drvPath);
/* Print each environment variable in the derivation in a format
that can be sourced by the shell. */
@@ -715,9 +716,9 @@ static void opExport(Strings opFlags, Strings opArgs)
else throw UsageError(format("unknown flag ‘%1%’") % i);
FdSink sink(STDOUT_FILENO);
- Paths sorted = topoSortPaths(*store, PathSet(opArgs.begin(), opArgs.end()));
+ Paths sorted = store->topoSortPaths(PathSet(opArgs.begin(), opArgs.end()));
reverse(sorted.begin(), sorted.end());
- exportPaths(*store, sorted, sign, sink);
+ store->exportPaths(sorted, sign, sink);
}
@@ -896,7 +897,7 @@ static void opServe(Strings opFlags, Strings opArgs)
if (!isDerivation(path)) paths2.insert(path);
unsigned long long downloadSize, narSize;
PathSet willBuild, willSubstitute, unknown;
- queryMissing(*store, PathSet(paths2.begin(), paths2.end()),
+ store->queryMissing(PathSet(paths2.begin(), paths2.end()),
willBuild, willSubstitute, unknown, downloadSize, narSize);
/* FIXME: should use ensurePath(), but it only
does one path at a time. */
@@ -941,9 +942,9 @@ static void opServe(Strings opFlags, Strings opArgs)
case cmdExportPaths: {
bool sign = readInt(in);
- Paths sorted = topoSortPaths(*store, readStorePaths<PathSet>(in));
+ Paths sorted = store->topoSortPaths(readStorePaths<PathSet>(in));
reverse(sorted.begin(), sorted.end());
- exportPaths(*store, sorted, sign, out);
+ store->exportPaths(sorted, sign, out);
break;
}
@@ -988,7 +989,7 @@ static void opServe(Strings opFlags, Strings opArgs)
PathSet paths = readStorePaths<PathSet>(in);
PathSet closure;
for (auto & i : paths)
- computeFSClosure(*store, i, closure, false, includeOutputs);
+ store->computeFSClosure(i, closure, false, includeOutputs);
out << closure;
break;
}
diff --git a/src/nix-store/xmlgraph.cc b/src/nix-store/xmlgraph.cc
index 98ab9e626..f88266bbb 100644
--- a/src/nix-store/xmlgraph.cc
+++ b/src/nix-store/xmlgraph.cc
@@ -33,7 +33,7 @@ static string makeNode(const string & id)
}
-void printXmlGraph(const PathSet & roots)
+void printXmlGraph(StoreAPI & store, const PathSet & roots)
{
PathSet workList(roots);
PathSet doneSet;
@@ -51,7 +51,7 @@ void printXmlGraph(const PathSet & roots)
cout << makeNode(path);
PathSet references;
- store->queryReferences(path, references);
+ store.queryReferences(path, references);
for (PathSet::iterator i = references.begin();
i != references.end(); ++i)
diff --git a/src/nix-store/xmlgraph.hh b/src/nix-store/xmlgraph.hh
index c2216c5a4..6d6d12a06 100644
--- a/src/nix-store/xmlgraph.hh
+++ b/src/nix-store/xmlgraph.hh
@@ -4,6 +4,8 @@
namespace nix {
-void printXmlGraph(const PathSet & roots);
+class StoreAPI;
+
+void printXmlGraph(StoreAPI & store, const PathSet & roots);
}