mirror of
https://github.com/NixOS/nix.git
synced 2025-11-21 09:49:36 +01: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:
parent
4f7824c58e
commit
c10c61449f
36 changed files with 511 additions and 458 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue