Merge pull request #5048 from tweag/flox-eval-store

--eval-store and faster closure copying
This commit is contained in:
Eelco Dolstra 2021-07-27 12:20:32 +02:00 committed by GitHub
commit c000cec27f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 473 additions and 204 deletions

View file

@ -270,7 +270,7 @@ connected:
{ {
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri)); Activity act(*logger, lvlTalkative, actUnknown, fmt("copying dependencies to '%s'", storeUri));
copyPaths(store, ref<Store>(sshStore), store->parseStorePathSet(inputs), NoRepair, NoCheckSigs, substitute); copyPaths(*store, *sshStore, store->parseStorePathSet(inputs), NoRepair, NoCheckSigs, substitute);
} }
uploadLock = -1; uploadLock = -1;
@ -321,7 +321,7 @@ connected:
if (auto localStore = store.dynamic_pointer_cast<LocalStore>()) if (auto localStore = store.dynamic_pointer_cast<LocalStore>())
for (auto & path : missingPaths) for (auto & path : missingPaths)
localStore->locksHeld.insert(store->printStorePath(path)); /* FIXME: ugly */ localStore->locksHeld.insert(store->printStorePath(path)); /* FIXME: ugly */
copyPaths(ref<Store>(sshStore), store, missingPaths, NoRepair, NoCheckSigs, NoSubstitute); copyPaths(*sshStore, *store, missingPaths, NoRepair, NoCheckSigs, NoSubstitute);
} }
// XXX: Should be done as part of `copyPaths` // XXX: Should be done as part of `copyPaths`
for (auto & realisation : missingRealisations) { for (auto & realisation : missingRealisations) {

View file

@ -54,6 +54,30 @@ void StoreCommand::run()
run(getStore()); run(getStore());
} }
EvalCommand::EvalCommand()
{
}
EvalCommand::~EvalCommand()
{
if (evalState)
evalState->printStats();
}
ref<Store> EvalCommand::getEvalStore()
{
if (!evalStore)
evalStore = evalStoreUrl ? openStore(*evalStoreUrl) : getStore();
return ref<Store>(evalStore);
}
ref<EvalState> EvalCommand::getEvalState()
{
if (!evalState)
evalState = std::make_shared<EvalState>(searchPath, getEvalStore(), getStore());
return ref<EvalState>(evalState);
}
BuiltPathsCommand::BuiltPathsCommand(bool recursive) BuiltPathsCommand::BuiltPathsCommand(bool recursive)
: recursive(recursive) : recursive(recursive)
{ {
@ -91,7 +115,7 @@ void BuiltPathsCommand::run(ref<Store> store)
for (auto & p : store->queryAllValidPaths()) for (auto & p : store->queryAllValidPaths())
paths.push_back(BuiltPath::Opaque{p}); paths.push_back(BuiltPath::Opaque{p});
} else { } else {
paths = toBuiltPaths(store, realiseMode, operateOn, installables); paths = toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables);
if (recursive) { if (recursive) {
// XXX: This only computes the store path closure, ignoring // XXX: This only computes the store path closure, ignoring
// intermediate realisations // intermediate realisations

View file

@ -45,11 +45,18 @@ private:
struct EvalCommand : virtual StoreCommand, MixEvalArgs struct EvalCommand : virtual StoreCommand, MixEvalArgs
{ {
ref<EvalState> getEvalState(); EvalCommand();
std::shared_ptr<EvalState> evalState;
~EvalCommand(); ~EvalCommand();
ref<Store> getEvalStore();
ref<EvalState> getEvalState();
private:
std::shared_ptr<Store> evalStore;
std::shared_ptr<EvalState> evalState;
}; };
struct MixFlakeOptions : virtual Args, EvalCommand struct MixFlakeOptions : virtual Args, EvalCommand
@ -216,15 +223,21 @@ static RegisterCommand registerCommand2(std::vector<std::string> && name)
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); }); return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
} }
BuiltPaths build(ref<Store> store, Realise mode, BuiltPaths build(ref<Store> evalStore, ref<Store> store, Realise mode,
std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode = bmNormal); std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode = bmNormal);
std::set<StorePath> toStorePaths(ref<Store> store, std::set<StorePath> toStorePaths(
Realise mode, OperateOn operateOn, ref<Store> evalStore,
ref<Store> store,
Realise mode,
OperateOn operateOn,
std::vector<std::shared_ptr<Installable>> installables); std::vector<std::shared_ptr<Installable>> installables);
StorePath toStorePath(ref<Store> store, StorePath toStorePath(
Realise mode, OperateOn operateOn, ref<Store> evalStore,
ref<Store> store,
Realise mode,
OperateOn operateOn,
std::shared_ptr<Installable> installable); std::shared_ptr<Installable> installable);
std::set<StorePath> toDerivations(ref<Store> store, std::set<StorePath> toDerivations(ref<Store> store,
@ -232,6 +245,7 @@ std::set<StorePath> toDerivations(ref<Store> store,
bool useDeriver = false); bool useDeriver = false);
BuiltPaths toBuiltPaths( BuiltPaths toBuiltPaths(
ref<Store> evalStore,
ref<Store> store, ref<Store> store,
Realise mode, Realise mode,
OperateOn operateOn, OperateOn operateOn,

View file

@ -289,19 +289,6 @@ void completeFlakeRefWithFragment(
completeFlakeRef(evalState->store, prefix); completeFlakeRef(evalState->store, prefix);
} }
ref<EvalState> EvalCommand::getEvalState()
{
if (!evalState)
evalState = std::make_shared<EvalState>(searchPath, getStore());
return ref<EvalState>(evalState);
}
EvalCommand::~EvalCommand()
{
if (evalState)
evalState->printStats();
}
void completeFlakeRef(ref<Store> store, std::string_view prefix) void completeFlakeRef(ref<Store> store, std::string_view prefix)
{ {
if (prefix == "") if (prefix == "")
@ -391,6 +378,7 @@ DerivedPaths InstallableValue::toDerivedPaths()
DerivedPaths res; DerivedPaths res;
std::map<StorePath, std::set<std::string>> drvsToOutputs; std::map<StorePath, std::set<std::string>> drvsToOutputs;
RealisedPath::Set drvsToCopy;
// Group by derivation, helps with .all in particular // Group by derivation, helps with .all in particular
for (auto & drv : toDerivations()) { for (auto & drv : toDerivations()) {
@ -398,6 +386,7 @@ DerivedPaths InstallableValue::toDerivedPaths()
if (outputName == "") if (outputName == "")
throw Error("derivation '%s' lacks an 'outputName' attribute", state->store->printStorePath(drv.drvPath)); throw Error("derivation '%s' lacks an 'outputName' attribute", state->store->printStorePath(drv.drvPath));
drvsToOutputs[drv.drvPath].insert(outputName); drvsToOutputs[drv.drvPath].insert(outputName);
drvsToCopy.insert(drv.drvPath);
} }
for (auto & i : drvsToOutputs) for (auto & i : drvsToOutputs)
@ -712,7 +701,7 @@ std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
return installables.front(); return installables.front();
} }
BuiltPaths getBuiltPaths(ref<Store> store, DerivedPaths hopefullyBuiltPaths) BuiltPaths getBuiltPaths(ref<Store> evalStore, ref<Store> store, const DerivedPaths & hopefullyBuiltPaths)
{ {
BuiltPaths res; BuiltPaths res;
for (auto & b : hopefullyBuiltPaths) for (auto & b : hopefullyBuiltPaths)
@ -723,14 +712,13 @@ BuiltPaths getBuiltPaths(ref<Store> store, DerivedPaths hopefullyBuiltPaths)
}, },
[&](DerivedPath::Built bfd) { [&](DerivedPath::Built bfd) {
OutputPathMap outputs; OutputPathMap outputs;
auto drv = store->readDerivation(bfd.drvPath); auto drv = evalStore->readDerivation(bfd.drvPath);
auto outputHashes = staticOutputHashes(*store, drv); auto outputHashes = staticOutputHashes(*evalStore, drv); // FIXME: expensive
auto drvOutputs = drv.outputsAndOptPaths(*store); auto drvOutputs = drv.outputsAndOptPaths(*store);
for (auto & output : bfd.outputs) { for (auto & output : bfd.outputs) {
if (!outputHashes.count(output)) if (!outputHashes.count(output))
throw Error( throw Error(
"the derivation '%s' doesn't have an output " "the derivation '%s' doesn't have an output named '%s'",
"named '%s'",
store->printStorePath(bfd.drvPath), output); store->printStorePath(bfd.drvPath), output);
if (settings.isExperimentalFeatureEnabled( if (settings.isExperimentalFeatureEnabled(
"ca-derivations")) { "ca-derivations")) {
@ -762,7 +750,7 @@ BuiltPaths getBuiltPaths(ref<Store> store, DerivedPaths hopefullyBuiltPaths)
return res; return res;
} }
BuiltPaths build(ref<Store> store, Realise mode, BuiltPaths build(ref<Store> evalStore, ref<Store> store, Realise mode,
std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode) std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode)
{ {
if (mode == Realise::Nothing) if (mode == Realise::Nothing)
@ -778,20 +766,21 @@ BuiltPaths build(ref<Store> store, Realise mode,
if (mode == Realise::Nothing) if (mode == Realise::Nothing)
printMissing(store, pathsToBuild, lvlError); printMissing(store, pathsToBuild, lvlError);
else if (mode == Realise::Outputs) else if (mode == Realise::Outputs)
store->buildPaths(pathsToBuild, bMode); store->buildPaths(pathsToBuild, bMode, evalStore);
return getBuiltPaths(store, pathsToBuild); return getBuiltPaths(evalStore, store, pathsToBuild);
} }
BuiltPaths toBuiltPaths( BuiltPaths toBuiltPaths(
ref<Store> evalStore,
ref<Store> store, ref<Store> store,
Realise mode, Realise mode,
OperateOn operateOn, OperateOn operateOn,
std::vector<std::shared_ptr<Installable>> installables) std::vector<std::shared_ptr<Installable>> installables)
{ {
if (operateOn == OperateOn::Output) { if (operateOn == OperateOn::Output)
return build(store, mode, installables); return build(evalStore, store, mode, installables);
} else { else {
if (mode == Realise::Nothing) if (mode == Realise::Nothing)
settings.readOnlyMode = true; settings.readOnlyMode = true;
@ -802,23 +791,27 @@ BuiltPaths toBuiltPaths(
} }
} }
StorePathSet toStorePaths(ref<Store> store, StorePathSet toStorePaths(
ref<Store> evalStore,
ref<Store> store,
Realise mode, OperateOn operateOn, Realise mode, OperateOn operateOn,
std::vector<std::shared_ptr<Installable>> installables) std::vector<std::shared_ptr<Installable>> installables)
{ {
StorePathSet outPaths; StorePathSet outPaths;
for (auto & path : toBuiltPaths(store, mode, operateOn, installables)) { for (auto & path : toBuiltPaths(evalStore, store, mode, operateOn, installables)) {
auto thisOutPaths = path.outPaths(); auto thisOutPaths = path.outPaths();
outPaths.insert(thisOutPaths.begin(), thisOutPaths.end()); outPaths.insert(thisOutPaths.begin(), thisOutPaths.end());
} }
return outPaths; return outPaths;
} }
StorePath toStorePath(ref<Store> store, StorePath toStorePath(
ref<Store> evalStore,
ref<Store> store,
Realise mode, OperateOn operateOn, Realise mode, OperateOn operateOn,
std::shared_ptr<Installable> installable) std::shared_ptr<Installable> installable)
{ {
auto paths = toStorePaths(store, mode, operateOn, {installable}); auto paths = toStorePaths(evalStore, store, mode, operateOn, {installable});
if (paths.size() != 1) if (paths.size() != 1)
throw Error("argument '%s' should evaluate to one store path", installable->what()); throw Error("argument '%s' should evaluate to one store path", installable->what());

View file

@ -26,7 +26,7 @@ struct App
struct UnresolvedApp struct UnresolvedApp
{ {
App unresolved; App unresolved;
App resolve(ref<Store>); App resolve(ref<Store> evalStore, ref<Store> store);
}; };
struct Installable struct Installable

View file

@ -61,6 +61,14 @@ MixEvalArgs::MixEvalArgs()
fetchers::overrideRegistry(from.input, to.input, extraAttrs); fetchers::overrideRegistry(from.input, to.input, extraAttrs);
}} }}
}); });
addFlag({
.longName = "eval-store",
.description = "The Nix store to use for evaluations.",
.category = category,
.labels = {"store-url"},
.handler = {&evalStoreUrl},
});
} }
Bindings * MixEvalArgs::getAutoArgs(EvalState & state) Bindings * MixEvalArgs::getAutoArgs(EvalState & state)

View file

@ -16,8 +16,9 @@ struct MixEvalArgs : virtual Args
Strings searchPath; Strings searchPath;
private: std::optional<std::string> evalStoreUrl;
private:
std::map<std::string, std::string> autoArgs; std::map<std::string, std::string> autoArgs;
}; };

View file

@ -378,7 +378,10 @@ static Strings parseNixPath(const string & s)
} }
EvalState::EvalState(const Strings & _searchPath, ref<Store> store) EvalState::EvalState(
const Strings & _searchPath,
ref<Store> store,
std::shared_ptr<Store> buildStore)
: sWith(symbols.create("<with>")) : sWith(symbols.create("<with>"))
, sOutPath(symbols.create("outPath")) , sOutPath(symbols.create("outPath"))
, sDrvPath(symbols.create("drvPath")) , sDrvPath(symbols.create("drvPath"))
@ -411,6 +414,7 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
, sEpsilon(symbols.create("")) , sEpsilon(symbols.create(""))
, repair(NoRepair) , repair(NoRepair)
, store(store) , store(store)
, buildStore(buildStore ? buildStore : store)
, regexCache(makeRegexCache()) , regexCache(makeRegexCache())
, baseEnv(allocEnv(128)) , baseEnv(allocEnv(128))
, staticBaseEnv(false, 0) , staticBaseEnv(false, 0)

View file

@ -94,8 +94,12 @@ public:
Value vEmptySet; Value vEmptySet;
/* Store used to materialise .drv files. */
const ref<Store> store; const ref<Store> store;
/* Store used to build stuff. */
const ref<Store> buildStore;
private: private:
SrcToStore srcToStore; SrcToStore srcToStore;
@ -128,7 +132,10 @@ private:
public: public:
EvalState(const Strings & _searchPath, ref<Store> store); EvalState(
const Strings & _searchPath,
ref<Store> store,
std::shared_ptr<Store> buildStore = nullptr);
~EvalState(); ~EvalState();
void addToSearchPath(const string & s); void addToSearchPath(const string & s);

View file

@ -165,7 +165,7 @@ void DerivationGoal::getDerivation()
/* The first thing to do is to make sure that the derivation /* The first thing to do is to make sure that the derivation
exists. If it doesn't, it may be created through a exists. If it doesn't, it may be created through a
substitute. */ substitute. */
if (buildMode == bmNormal && worker.store.isValidPath(drvPath)) { if (buildMode == bmNormal && worker.evalStore.isValidPath(drvPath)) {
loadDerivation(); loadDerivation();
return; return;
} }
@ -188,12 +188,12 @@ void DerivationGoal::loadDerivation()
/* `drvPath' should already be a root, but let's be on the safe /* `drvPath' should already be a root, but let's be on the safe
side: if the user forgot to make it a root, we wouldn't want side: if the user forgot to make it a root, we wouldn't want
things being garbage collected while we're busy. */ things being garbage collected while we're busy. */
worker.store.addTempRoot(drvPath); worker.evalStore.addTempRoot(drvPath);
assert(worker.store.isValidPath(drvPath)); assert(worker.evalStore.isValidPath(drvPath));
/* Get the derivation. */ /* Get the derivation. */
drv = std::make_unique<Derivation>(worker.store.derivationFromPath(drvPath)); drv = std::make_unique<Derivation>(worker.evalStore.derivationFromPath(drvPath));
haveDerivation(); haveDerivation();
} }
@ -212,7 +212,7 @@ void DerivationGoal::haveDerivation()
if (i.second.second) if (i.second.second)
worker.store.addTempRoot(*i.second.second); worker.store.addTempRoot(*i.second.second);
auto outputHashes = staticOutputHashes(worker.store, *drv); auto outputHashes = staticOutputHashes(worker.evalStore, *drv);
for (auto & [outputName, outputHash] : outputHashes) for (auto & [outputName, outputHash] : outputHashes)
initialOutputs.insert({ initialOutputs.insert({
outputName, outputName,
@ -337,6 +337,15 @@ void DerivationGoal::gaveUpOnSubstitution()
for (auto & i : dynamic_cast<Derivation *>(drv.get())->inputDrvs) for (auto & i : dynamic_cast<Derivation *>(drv.get())->inputDrvs)
addWaitee(worker.makeDerivationGoal(i.first, i.second, buildMode == bmRepair ? bmRepair : bmNormal)); addWaitee(worker.makeDerivationGoal(i.first, i.second, buildMode == bmRepair ? bmRepair : bmNormal));
/* Copy the input sources from the eval store to the build
store. */
if (&worker.evalStore != &worker.store) {
RealisedPath::Set inputSrcs;
for (auto & i : drv->inputSrcs)
inputSrcs.insert(i);
copyClosure(worker.evalStore, worker.store, inputSrcs);
}
for (auto & i : drv->inputSrcs) { for (auto & i : drv->inputSrcs) {
if (worker.store.isValidPath(i)) continue; if (worker.store.isValidPath(i)) continue;
if (!settings.useSubstitutes) if (!settings.useSubstitutes)
@ -478,8 +487,8 @@ void DerivationGoal::inputsRealised()
/* Add the relevant output closures of the input derivation /* Add the relevant output closures of the input derivation
`i' as input paths. Only add the closures of output paths `i' as input paths. Only add the closures of output paths
that are specified as inputs. */ that are specified as inputs. */
assert(worker.store.isValidPath(drvPath)); assert(worker.evalStore.isValidPath(drvPath));
auto outputs = worker.store.queryPartialDerivationOutputMap(depDrvPath); auto outputs = worker.evalStore.queryPartialDerivationOutputMap(depDrvPath);
for (auto & j : wantedDepOutputs) { for (auto & j : wantedDepOutputs) {
if (outputs.count(j) > 0) { if (outputs.count(j) > 0) {
auto optRealizedInput = outputs.at(j); auto optRealizedInput = outputs.at(j);

View file

@ -6,9 +6,9 @@
namespace nix { namespace nix {
void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMode) void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMode, std::shared_ptr<Store> evalStore)
{ {
Worker worker(*this); Worker worker(*this, evalStore ? *evalStore : *this);
Goals goals; Goals goals;
for (auto & br : reqs) { for (auto & br : reqs) {
@ -51,7 +51,7 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod
BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,
BuildMode buildMode) BuildMode buildMode)
{ {
Worker worker(*this); Worker worker(*this, *this);
auto goal = worker.makeBasicDerivationGoal(drvPath, drv, {}, buildMode); auto goal = worker.makeBasicDerivationGoal(drvPath, drv, {}, buildMode);
BuildResult result; BuildResult result;
@ -93,7 +93,7 @@ void Store::ensurePath(const StorePath & path)
/* If the path is already valid, we're done. */ /* If the path is already valid, we're done. */
if (isValidPath(path)) return; if (isValidPath(path)) return;
Worker worker(*this); Worker worker(*this, *this);
GoalPtr goal = worker.makePathSubstitutionGoal(path); GoalPtr goal = worker.makePathSubstitutionGoal(path);
Goals goals = {goal}; Goals goals = {goal};
@ -111,7 +111,7 @@ void Store::ensurePath(const StorePath & path)
void LocalStore::repairPath(const StorePath & path) void LocalStore::repairPath(const StorePath & path)
{ {
Worker worker(*this); Worker worker(*this, *this);
GoalPtr goal = worker.makePathSubstitutionGoal(path, Repair); GoalPtr goal = worker.makePathSubstitutionGoal(path, Repair);
Goals goals = {goal}; Goals goals = {goal};

View file

@ -1254,8 +1254,10 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo
return next->queryRealisation(id); return next->queryRealisation(id);
} }
void buildPaths(const std::vector<DerivedPath> & paths, BuildMode buildMode) override void buildPaths(const std::vector<DerivedPath> & paths, BuildMode buildMode, std::shared_ptr<Store> evalStore) override
{ {
assert(!evalStore);
if (buildMode != bmNormal) throw Error("unsupported build mode"); if (buildMode != bmNormal) throw Error("unsupported build mode");
StorePathSet newPaths; StorePathSet newPaths;

View file

@ -204,7 +204,7 @@ void PathSubstitutionGoal::tryToRun()
Activity act(*logger, actSubstitute, Logger::Fields{worker.store.printStorePath(storePath), sub->getUri()}); Activity act(*logger, actSubstitute, Logger::Fields{worker.store.printStorePath(storePath), sub->getUri()});
PushActivity pact(act.id); PushActivity pact(act.id);
copyStorePath(ref<Store>(sub), ref<Store>(worker.store.shared_from_this()), copyStorePath(*sub, worker.store,
subPath ? *subPath : storePath, repair, sub->isTrusted ? NoCheckSigs : CheckSigs); subPath ? *subPath : storePath, repair, sub->isTrusted ? NoCheckSigs : CheckSigs);
promise.set_value(); promise.set_value();

View file

@ -9,11 +9,12 @@
namespace nix { namespace nix {
Worker::Worker(Store & store) Worker::Worker(Store & store, Store & evalStore)
: act(*logger, actRealise) : act(*logger, actRealise)
, actDerivations(*logger, actBuilds) , actDerivations(*logger, actBuilds)
, actSubstitutions(*logger, actCopyPaths) , actSubstitutions(*logger, actCopyPaths)
, store(store) , store(store)
, evalStore(evalStore)
{ {
/* Debugging: prevent recursive workers. */ /* Debugging: prevent recursive workers. */
nrLocalBuilds = 0; nrLocalBuilds = 0;

View file

@ -110,6 +110,7 @@ public:
bool checkMismatch; bool checkMismatch;
Store & store; Store & store;
Store & evalStore;
std::unique_ptr<HookInstance> hook; std::unique_ptr<HookInstance> hook;
@ -131,7 +132,7 @@ public:
it answers with "decline-permanently", we don't try again. */ it answers with "decline-permanently", we don't try again. */
bool tryBuildHook = true; bool tryBuildHook = true;
Worker(Store & store); Worker(Store & store, Store & evalStore);
~Worker(); ~Worker();
/* Make a goal (with caching). */ /* Make a goal (with caching). */

View file

@ -243,23 +243,6 @@ struct ClientSettings
} }
}; };
static void writeValidPathInfo(
ref<Store> store,
unsigned int clientVersion,
Sink & to,
std::shared_ptr<const ValidPathInfo> info)
{
to << (info->deriver ? store->printStorePath(*info->deriver) : "")
<< info->narHash.to_string(Base16, false);
worker_proto::write(*store, to, info->references);
to << info->registrationTime << info->narSize;
if (GET_PROTOCOL_MINOR(clientVersion) >= 16) {
to << info->ultimate
<< info->sigs
<< renderContentAddress(info->ca);
}
}
static std::vector<DerivedPath> readDerivedPaths(Store & store, unsigned int clientVersion, Source & from) static std::vector<DerivedPath> readDerivedPaths(Store & store, unsigned int clientVersion, Source & from)
{ {
std::vector<DerivedPath> reqs; std::vector<DerivedPath> reqs;
@ -422,9 +405,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
}(); }();
logger->stopWork(); logger->stopWork();
to << store->printStorePath(pathInfo->path); pathInfo->write(to, *store, GET_PROTOCOL_MINOR(clientVersion));
writeValidPathInfo(store, clientVersion, to, pathInfo);
} else { } else {
HashType hashAlgo; HashType hashAlgo;
std::string baseName; std::string baseName;
@ -471,6 +452,21 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
break; break;
} }
case wopAddMultipleToStore: {
bool repair, dontCheckSigs;
from >> repair >> dontCheckSigs;
if (!trusted && dontCheckSigs)
dontCheckSigs = false;
logger->startWork();
FramedSource source(from);
store->addMultipleToStore(source,
RepairFlag{repair},
dontCheckSigs ? NoCheckSigs : CheckSigs);
logger->stopWork();
break;
}
case wopAddTextToStore: { case wopAddTextToStore: {
string suffix = readString(from); string suffix = readString(from);
string s = readString(from); string s = readString(from);
@ -770,7 +766,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
if (info) { if (info) {
if (GET_PROTOCOL_MINOR(clientVersion) >= 17) if (GET_PROTOCOL_MINOR(clientVersion) >= 17)
to << 1; to << 1;
writeValidPathInfo(store, clientVersion, to, info); info->write(to, *store, GET_PROTOCOL_MINOR(clientVersion), false);
} else { } else {
assert(GET_PROTOCOL_MINOR(clientVersion) >= 17); assert(GET_PROTOCOL_MINOR(clientVersion) >= 17);
to << 0; to << 0;

View file

@ -43,11 +43,6 @@ struct DummyStore : public virtual DummyStoreConfig, public virtual Store
RepairFlag repair, CheckSigsFlag checkSigs) override RepairFlag repair, CheckSigsFlag checkSigs) override
{ unsupported("addToStore"); } { unsupported("addToStore"); }
StorePath addToStore(const string & name, const Path & srcPath,
FileIngestionMethod method, HashType hashAlgo,
PathFilter & filter, RepairFlag repair) override
{ unsupported("addToStore"); }
StorePath addTextToStore(const string & name, const string & s, StorePath addTextToStore(const string & name, const string & s,
const StorePathSet & references, RepairFlag repair) override const StorePathSet & references, RepairFlag repair) override
{ unsupported("addTextToStore"); } { unsupported("addTextToStore"); }

View file

@ -267,8 +267,11 @@ public:
return status; return status;
} }
void buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMode buildMode) override void buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMode buildMode, std::shared_ptr<Store> evalStore) override
{ {
if (evalStore && evalStore.get() != this)
throw Error("building on an SSH store is incompatible with '--eval-store'");
auto conn(connections->get()); auto conn(connections->get());
conn->to << cmdBuildPaths; conn->to << cmdBuildPaths;

46
src/libstore/path-info.cc Normal file
View file

@ -0,0 +1,46 @@
#include "path-info.hh"
#include "worker-protocol.hh"
namespace nix {
ValidPathInfo ValidPathInfo::read(Source & source, const Store & store, unsigned int format)
{
return read(source, store, format, store.parseStorePath(readString(source)));
}
ValidPathInfo ValidPathInfo::read(Source & source, const Store & store, unsigned int format, StorePath && path)
{
auto deriver = readString(source);
auto narHash = Hash::parseAny(readString(source), htSHA256);
ValidPathInfo info(path, narHash);
if (deriver != "") info.deriver = store.parseStorePath(deriver);
info.references = worker_proto::read(store, source, Phantom<StorePathSet> {});
source >> info.registrationTime >> info.narSize;
if (format >= 16) {
source >> info.ultimate;
info.sigs = readStrings<StringSet>(source);
info.ca = parseContentAddressOpt(readString(source));
}
return info;
}
void ValidPathInfo::write(
Sink & sink,
const Store & store,
unsigned int format,
bool includePath) const
{
if (includePath)
sink << store.printStorePath(path);
sink << (deriver ? store.printStorePath(*deriver) : "")
<< narHash.to_string(Base16, false);
worker_proto::write(store, sink, references);
sink << registrationTime << narSize;
if (format >= 16) {
sink << ultimate
<< sigs
<< renderContentAddress(ca);
}
}
}

View file

@ -105,6 +105,11 @@ struct ValidPathInfo
ValidPathInfo(const StorePath & path, Hash narHash) : path(path), narHash(narHash) { }; ValidPathInfo(const StorePath & path, Hash narHash) : path(path), narHash(narHash) { };
virtual ~ValidPathInfo() { } virtual ~ValidPathInfo() { }
static ValidPathInfo read(Source & source, const Store & store, unsigned int format);
static ValidPathInfo read(Source & source, const Store & store, unsigned int format, StorePath && path);
void write(Sink & sink, const Store & store, unsigned int format, bool includePath = true) const;
}; };
typedef std::map<StorePath, ValidPathInfo> ValidPathInfos; typedef std::map<StorePath, ValidPathInfo> ValidPathInfos;

View file

@ -386,23 +386,6 @@ void RemoteStore::querySubstitutablePathInfos(const StorePathCAMap & pathsMap, S
} }
ref<const ValidPathInfo> RemoteStore::readValidPathInfo(ConnectionHandle & conn, const StorePath & path)
{
auto deriver = readString(conn->from);
auto narHash = Hash::parseAny(readString(conn->from), htSHA256);
auto info = make_ref<ValidPathInfo>(path, narHash);
if (deriver != "") info->deriver = parseStorePath(deriver);
info->references = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
conn->from >> info->registrationTime >> info->narSize;
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 16) {
conn->from >> info->ultimate;
info->sigs = readStrings<StringSet>(conn->from);
info->ca = parseContentAddressOpt(readString(conn->from));
}
return info;
}
void RemoteStore::queryPathInfoUncached(const StorePath & path, void RemoteStore::queryPathInfoUncached(const StorePath & path,
Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept
{ {
@ -423,7 +406,8 @@ void RemoteStore::queryPathInfoUncached(const StorePath & path,
bool valid; conn->from >> valid; bool valid; conn->from >> valid;
if (!valid) throw InvalidPath("path '%s' is not valid", printStorePath(path)); if (!valid) throw InvalidPath("path '%s' is not valid", printStorePath(path));
} }
info = readValidPathInfo(conn, path); info = std::make_shared<ValidPathInfo>(
ValidPathInfo::read(conn->from, *this, GET_PROTOCOL_MINOR(conn->daemonVersion), StorePath{path}));
} }
callback(std::move(info)); callback(std::move(info));
} catch (...) { callback.rethrow(); } } catch (...) { callback.rethrow(); }
@ -525,8 +509,8 @@ ref<const ValidPathInfo> RemoteStore::addCAToStore(
}); });
} }
auto path = parseStorePath(readString(conn->from)); return make_ref<ValidPathInfo>(
return readValidPathInfo(conn, path); ValidPathInfo::read(conn->from, *this, GET_PROTOCOL_MINOR(conn->daemonVersion)));
} }
else { else {
if (repair) throw Error("repairing is not supported when building through the Nix daemon protocol < 1.25"); if (repair) throw Error("repairing is not supported when building through the Nix daemon protocol < 1.25");
@ -642,6 +626,25 @@ void RemoteStore::addToStore(const ValidPathInfo & info, Source & source,
} }
void RemoteStore::addMultipleToStore(
Source & source,
RepairFlag repair,
CheckSigsFlag checkSigs)
{
if (GET_PROTOCOL_MINOR(getConnection()->daemonVersion) >= 32) {
auto conn(getConnection());
conn->to
<< wopAddMultipleToStore
<< repair
<< !checkSigs;
conn.withFramedSink([&](Sink & sink) {
source.drainInto(sink);
});
} else
Store::addMultipleToStore(source, repair, checkSigs);
}
StorePath RemoteStore::addTextToStore(const string & name, const string & s, StorePath RemoteStore::addTextToStore(const string & name, const string & s,
const StorePathSet & references, RepairFlag repair) const StorePathSet & references, RepairFlag repair)
{ {
@ -705,8 +708,18 @@ static void writeDerivedPaths(RemoteStore & store, ConnectionHandle & conn, cons
} }
} }
void RemoteStore::buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMode buildMode) void RemoteStore::buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMode buildMode, std::shared_ptr<Store> evalStore)
{ {
if (evalStore && evalStore.get() != this) {
/* The remote doesn't have a way to access evalStore, so copy
the .drvs. */
RealisedPath::Set drvPaths2;
for (auto & i : drvPaths)
if (auto p = std::get_if<DerivedPath::Built>(&i))
drvPaths2.insert(p->drvPath);
copyClosure(*evalStore, *this, drvPaths2);
}
auto conn(getConnection()); auto conn(getConnection());
conn->to << wopBuildPaths; conn->to << wopBuildPaths;
assert(GET_PROTOCOL_MINOR(conn->daemonVersion) >= 13); assert(GET_PROTOCOL_MINOR(conn->daemonVersion) >= 13);
@ -1007,8 +1020,8 @@ void ConnectionHandle::withFramedSink(std::function<void(Sink &sink)> fun)
std::exception_ptr ex; std::exception_ptr ex;
/* Handle log messages / exceptions from the remote on a /* Handle log messages / exceptions from the remote on a separate
separate thread. */ thread. */
std::thread stderrThread([&]() std::thread stderrThread([&]()
{ {
try { try {
@ -1041,7 +1054,6 @@ void ConnectionHandle::withFramedSink(std::function<void(Sink &sink)> fun)
stderrThread.join(); stderrThread.join();
if (ex) if (ex)
std::rethrow_exception(ex); std::rethrow_exception(ex);
} }
} }

View file

@ -78,6 +78,11 @@ public:
void addToStore(const ValidPathInfo & info, Source & nar, void addToStore(const ValidPathInfo & info, Source & nar,
RepairFlag repair, CheckSigsFlag checkSigs) override; RepairFlag repair, CheckSigsFlag checkSigs) override;
void addMultipleToStore(
Source & source,
RepairFlag repair,
CheckSigsFlag checkSigs) override;
StorePath addTextToStore(const string & name, const string & s, StorePath addTextToStore(const string & name, const string & s,
const StorePathSet & references, RepairFlag repair) override; const StorePathSet & references, RepairFlag repair) override;
@ -85,7 +90,7 @@ public:
std::optional<const Realisation> queryRealisation(const DrvOutput &) override; std::optional<const Realisation> queryRealisation(const DrvOutput &) override;
void buildPaths(const std::vector<DerivedPath> & paths, BuildMode buildMode) override; void buildPaths(const std::vector<DerivedPath> & paths, BuildMode buildMode, std::shared_ptr<Store> evalStore) override;
BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,
BuildMode buildMode) override; BuildMode buildMode) override;
@ -151,8 +156,6 @@ protected:
virtual void narFromPath(const StorePath & path, Sink & sink) override; virtual void narFromPath(const StorePath & path, Sink & sink) override;
ref<const ValidPathInfo> readValidPathInfo(ConnectionHandle & conn, const StorePath & path);
private: private:
std::atomic_bool failed{false}; std::atomic_bool failed{false};

View file

@ -9,6 +9,7 @@
#include "url.hh" #include "url.hh"
#include "archive.hh" #include "archive.hh"
#include "callback.hh" #include "callback.hh"
#include "remote-store.hh"
#include <regex> #include <regex>
@ -249,6 +250,20 @@ StorePath Store::addToStore(const string & name, const Path & _srcPath,
} }
void Store::addMultipleToStore(
Source & source,
RepairFlag repair,
CheckSigsFlag checkSigs)
{
auto expected = readNum<uint64_t>(source);
for (uint64_t i = 0; i < expected; ++i) {
auto info = ValidPathInfo::read(source, *this, 16);
info.ultimate = false;
addToStore(info, source, repair, checkSigs);
}
}
/* /*
The aim of this function is to compute in one pass the correct ValidPathInfo for The aim of this function is to compute in one pass the correct ValidPathInfo for
the files that we are trying to add to the store. To accomplish that in one the files that we are trying to add to the store. To accomplish that in one
@ -770,30 +785,43 @@ const Store::Stats & Store::getStats()
} }
void copyStorePath(ref<Store> srcStore, ref<Store> dstStore, static std::string makeCopyPathMessage(
const StorePath & storePath, RepairFlag repair, CheckSigsFlag checkSigs) std::string_view srcUri,
std::string_view dstUri,
std::string_view storePath)
{ {
auto srcUri = srcStore->getUri(); return srcUri == "local" || srcUri == "daemon"
auto dstUri = dstStore->getUri(); ? fmt("copying path '%s' to '%s'", storePath, dstUri)
Activity act(*logger, lvlInfo, actCopyPath,
srcUri == "local" || srcUri == "daemon"
? fmt("copying path '%s' to '%s'", srcStore->printStorePath(storePath), dstUri)
: dstUri == "local" || dstUri == "daemon" : dstUri == "local" || dstUri == "daemon"
? fmt("copying path '%s' from '%s'", srcStore->printStorePath(storePath), srcUri) ? fmt("copying path '%s' from '%s'", storePath, srcUri)
: fmt("copying path '%s' from '%s' to '%s'", srcStore->printStorePath(storePath), srcUri, dstUri), : fmt("copying path '%s' from '%s' to '%s'", storePath, srcUri, dstUri);
{srcStore->printStorePath(storePath), srcUri, dstUri}); }
void copyStorePath(
Store & srcStore,
Store & dstStore,
const StorePath & storePath,
RepairFlag repair,
CheckSigsFlag checkSigs)
{
auto srcUri = srcStore.getUri();
auto dstUri = dstStore.getUri();
auto storePathS = srcStore.printStorePath(storePath);
Activity act(*logger, lvlInfo, actCopyPath,
makeCopyPathMessage(srcUri, dstUri, storePathS),
{storePathS, srcUri, dstUri});
PushActivity pact(act.id); PushActivity pact(act.id);
auto info = srcStore->queryPathInfo(storePath); auto info = srcStore.queryPathInfo(storePath);
uint64_t total = 0; uint64_t total = 0;
// recompute store path on the chance dstStore does it differently // recompute store path on the chance dstStore does it differently
if (info->ca && info->references.empty()) { if (info->ca && info->references.empty()) {
auto info2 = make_ref<ValidPathInfo>(*info); auto info2 = make_ref<ValidPathInfo>(*info);
info2->path = dstStore->makeFixedOutputPathFromCA(info->path.name(), *info->ca); info2->path = dstStore.makeFixedOutputPathFromCA(info->path.name(), *info->ca);
if (dstStore->storeDir == srcStore->storeDir) if (dstStore.storeDir == srcStore.storeDir)
assert(info->path == info2->path); assert(info->path == info2->path);
info = info2; info = info2;
} }
@ -810,17 +838,22 @@ void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
act.progress(total, info->narSize); act.progress(total, info->narSize);
}); });
TeeSink tee { sink, progressSink }; TeeSink tee { sink, progressSink };
srcStore->narFromPath(storePath, tee); srcStore.narFromPath(storePath, tee);
}, [&]() { }, [&]() {
throw EndOfFile("NAR for '%s' fetched from '%s' is incomplete", srcStore->printStorePath(storePath), srcStore->getUri()); throw EndOfFile("NAR for '%s' fetched from '%s' is incomplete", srcStore.printStorePath(storePath), srcStore.getUri());
}); });
dstStore->addToStore(*info, *source, repair, checkSigs); dstStore.addToStore(*info, *source, repair, checkSigs);
} }
std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStore, const RealisedPath::Set & paths, std::map<StorePath, StorePath> copyPaths(
RepairFlag repair, CheckSigsFlag checkSigs, SubstituteFlag substitute) Store & srcStore,
Store & dstStore,
const RealisedPath::Set & paths,
RepairFlag repair,
CheckSigsFlag checkSigs,
SubstituteFlag substitute)
{ {
StorePathSet storePaths; StorePathSet storePaths;
std::set<Realisation> toplevelRealisations; std::set<Realisation> toplevelRealisations;
@ -838,11 +871,11 @@ std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStor
try { try {
// Copy the realisation closure // Copy the realisation closure
processGraph<Realisation>( processGraph<Realisation>(
pool, Realisation::closure(*srcStore, toplevelRealisations), pool, Realisation::closure(srcStore, toplevelRealisations),
[&](const Realisation & current) -> std::set<Realisation> { [&](const Realisation & current) -> std::set<Realisation> {
std::set<Realisation> children; std::set<Realisation> children;
for (const auto & [drvOutput, _] : current.dependentRealisations) { for (const auto & [drvOutput, _] : current.dependentRealisations) {
auto currentChild = srcStore->queryRealisation(drvOutput); auto currentChild = srcStore.queryRealisation(drvOutput);
if (!currentChild) if (!currentChild)
throw Error( throw Error(
"incomplete realisation closure: '%s' is a " "incomplete realisation closure: '%s' is a "
@ -853,7 +886,7 @@ std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStor
return children; return children;
}, },
[&](const Realisation& current) -> void { [&](const Realisation& current) -> void {
dstStore->registerDrvOutput(current, checkSigs); dstStore.registerDrvOutput(current, checkSigs);
}); });
} catch (MissingExperimentalFeature & e) { } catch (MissingExperimentalFeature & e) {
// Don't fail if the remote doesn't support CA derivations is it might // Don't fail if the remote doesn't support CA derivations is it might
@ -868,10 +901,15 @@ std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStor
return pathsMap; return pathsMap;
} }
std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStore, const StorePathSet & storePaths, std::map<StorePath, StorePath> copyPaths(
RepairFlag repair, CheckSigsFlag checkSigs, SubstituteFlag substitute) Store & srcStore,
Store & dstStore,
const StorePathSet & storePaths,
RepairFlag repair,
CheckSigsFlag checkSigs,
SubstituteFlag substitute)
{ {
auto valid = dstStore->queryValidPaths(storePaths, substitute); auto valid = dstStore.queryValidPaths(storePaths, substitute);
StorePathSet missing; StorePathSet missing;
for (auto & path : storePaths) for (auto & path : storePaths)
@ -881,9 +919,31 @@ std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStor
for (auto & path : storePaths) for (auto & path : storePaths)
pathsMap.insert_or_assign(path, path); pathsMap.insert_or_assign(path, path);
Activity act(*logger, lvlInfo, actCopyPaths, fmt("copying %d paths", missing.size())); Activity act(*logger, lvlInfo, actCopyPaths, fmt("copying %d paths", missing.size()));
auto sorted = srcStore.topoSortPaths(missing);
std::reverse(sorted.begin(), sorted.end());
auto source = sinkToSource([&](Sink & sink) {
sink << sorted.size();
for (auto & storePath : sorted) {
auto srcUri = srcStore.getUri();
auto dstUri = dstStore.getUri();
auto storePathS = srcStore.printStorePath(storePath);
Activity act(*logger, lvlInfo, actCopyPath,
makeCopyPathMessage(srcUri, dstUri, storePathS),
{storePathS, srcUri, dstUri});
PushActivity pact(act.id);
auto info = srcStore.queryPathInfo(storePath);
info->write(sink, srcStore, 16);
srcStore.narFromPath(storePath, sink);
}
});
dstStore.addMultipleToStore(*source, repair, checkSigs);
#if 0
std::atomic<size_t> nrDone{0}; std::atomic<size_t> nrDone{0};
std::atomic<size_t> nrFailed{0}; std::atomic<size_t> nrFailed{0};
std::atomic<uint64_t> bytesExpected{0}; std::atomic<uint64_t> bytesExpected{0};
@ -899,18 +959,21 @@ std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStor
StorePathSet(missing.begin(), missing.end()), StorePathSet(missing.begin(), missing.end()),
[&](const StorePath & storePath) { [&](const StorePath & storePath) {
auto info = srcStore->queryPathInfo(storePath); auto info = srcStore.queryPathInfo(storePath);
auto storePathForDst = storePath; auto storePathForDst = storePath;
if (info->ca && info->references.empty()) { if (info->ca && info->references.empty()) {
storePathForDst = dstStore->makeFixedOutputPathFromCA(storePath.name(), *info->ca); storePathForDst = dstStore.makeFixedOutputPathFromCA(storePath.name(), *info->ca);
if (dstStore->storeDir == srcStore->storeDir) if (dstStore.storeDir == srcStore.storeDir)
assert(storePathForDst == storePath); assert(storePathForDst == storePath);
if (storePathForDst != storePath) if (storePathForDst != storePath)
debug("replaced path '%s' to '%s' for substituter '%s'", srcStore->printStorePath(storePath), dstStore->printStorePath(storePathForDst), dstStore->getUri()); debug("replaced path '%s' to '%s' for substituter '%s'",
srcStore.printStorePath(storePath),
dstStore.printStorePath(storePathForDst),
dstStore.getUri());
} }
pathsMap.insert_or_assign(storePath, storePathForDst); pathsMap.insert_or_assign(storePath, storePathForDst);
if (dstStore->isValidPath(storePath)) { if (dstStore.isValidPath(storePath)) {
nrDone++; nrDone++;
showProgress(); showProgress();
return StorePathSet(); return StorePathSet();
@ -925,19 +988,22 @@ std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStor
[&](const StorePath & storePath) { [&](const StorePath & storePath) {
checkInterrupt(); checkInterrupt();
auto info = srcStore->queryPathInfo(storePath); auto info = srcStore.queryPathInfo(storePath);
auto storePathForDst = storePath; auto storePathForDst = storePath;
if (info->ca && info->references.empty()) { if (info->ca && info->references.empty()) {
storePathForDst = dstStore->makeFixedOutputPathFromCA(storePath.name(), *info->ca); storePathForDst = dstStore.makeFixedOutputPathFromCA(storePath.name(), *info->ca);
if (dstStore->storeDir == srcStore->storeDir) if (dstStore.storeDir == srcStore.storeDir)
assert(storePathForDst == storePath); assert(storePathForDst == storePath);
if (storePathForDst != storePath) if (storePathForDst != storePath)
debug("replaced path '%s' to '%s' for substituter '%s'", srcStore->printStorePath(storePath), dstStore->printStorePath(storePathForDst), dstStore->getUri()); debug("replaced path '%s' to '%s' for substituter '%s'",
srcStore.printStorePath(storePath),
dstStore.printStorePath(storePathForDst),
dstStore.getUri());
} }
pathsMap.insert_or_assign(storePath, storePathForDst); pathsMap.insert_or_assign(storePath, storePathForDst);
if (!dstStore->isValidPath(storePathForDst)) { if (!dstStore.isValidPath(storePathForDst)) {
MaintainCount<decltype(nrRunning)> mc(nrRunning); MaintainCount<decltype(nrRunning)> mc(nrRunning);
showProgress(); showProgress();
try { try {
@ -946,7 +1012,7 @@ std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStor
nrFailed++; nrFailed++;
if (!settings.keepGoing) if (!settings.keepGoing)
throw e; throw e;
logger->log(lvlError, fmt("could not copy %s: %s", dstStore->printStorePath(storePath), e.what())); logger->log(lvlError, fmt("could not copy %s: %s", dstStore.printStorePath(storePath), e.what()));
showProgress(); showProgress();
return; return;
} }
@ -955,9 +1021,27 @@ std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStor
nrDone++; nrDone++;
showProgress(); showProgress();
}); });
#endif
return pathsMap; return pathsMap;
} }
void copyClosure(
Store & srcStore,
Store & dstStore,
const RealisedPath::Set & paths,
RepairFlag repair,
CheckSigsFlag checkSigs,
SubstituteFlag substitute)
{
if (&srcStore == &dstStore) return;
RealisedPath::Set closure;
RealisedPath::closure(srcStore, paths, closure);
copyPaths(srcStore, dstStore, closure, repair, checkSigs, substitute);
}
std::optional<ValidPathInfo> decodeValidPathInfo(const Store & store, std::istream & str, std::optional<HashResult> hashGiven) std::optional<ValidPathInfo> decodeValidPathInfo(const Store & store, std::istream & str, std::optional<HashResult> hashGiven)
{ {
std::string path; std::string path;

View file

@ -440,6 +440,12 @@ public:
virtual void addToStore(const ValidPathInfo & info, Source & narSource, virtual void addToStore(const ValidPathInfo & info, Source & narSource,
RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs) = 0; RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs) = 0;
/* Import multiple paths into the store. */
virtual void addMultipleToStore(
Source & source,
RepairFlag repair = NoRepair,
CheckSigsFlag checkSigs = CheckSigs);
/* Copy the contents of a path to the store and register the /* Copy the contents of a path to the store and register the
validity the resulting path. The resulting path is returned. validity the resulting path. The resulting path is returned.
The function object `filter' can be used to exclude files (see The function object `filter' can be used to exclude files (see
@ -497,7 +503,8 @@ public:
not derivations, substitute them. */ not derivations, substitute them. */
virtual void buildPaths( virtual void buildPaths(
const std::vector<DerivedPath> & paths, const std::vector<DerivedPath> & paths,
BuildMode buildMode = bmNormal); BuildMode buildMode = bmNormal,
std::shared_ptr<Store> evalStore = nullptr);
/* Build a single non-materialized derivation (i.e. not from an /* Build a single non-materialized derivation (i.e. not from an
on-disk .drv file). on-disk .drv file).
@ -751,8 +758,12 @@ protected:
/* Copy a path from one store to another. */ /* Copy a path from one store to another. */
void copyStorePath(ref<Store> srcStore, ref<Store> dstStore, void copyStorePath(
const StorePath & storePath, RepairFlag repair = NoRepair, CheckSigsFlag checkSigs = CheckSigs); Store & srcStore,
Store & dstStore,
const StorePath & storePath,
RepairFlag repair = NoRepair,
CheckSigsFlag checkSigs = CheckSigs);
/* Copy store paths from one store to another. The paths may be copied /* Copy store paths from one store to another. The paths may be copied
@ -761,17 +772,27 @@ void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
of store paths is not automatically closed; use copyClosure() for of store paths is not automatically closed; use copyClosure() for
that. Returns a map of what each path was copied to the dstStore that. Returns a map of what each path was copied to the dstStore
as. */ as. */
std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStore, std::map<StorePath, StorePath> copyPaths(
Store & srcStore, Store & dstStore,
const RealisedPath::Set &, const RealisedPath::Set &,
RepairFlag repair = NoRepair, RepairFlag repair = NoRepair,
CheckSigsFlag checkSigs = CheckSigs, CheckSigsFlag checkSigs = CheckSigs,
SubstituteFlag substitute = NoSubstitute); SubstituteFlag substitute = NoSubstitute);
std::map<StorePath, StorePath> copyPaths(ref<Store> srcStore, ref<Store> dstStore,
std::map<StorePath, StorePath> copyPaths(
Store & srcStore, Store & dstStore,
const StorePathSet & paths, const StorePathSet & paths,
RepairFlag repair = NoRepair, RepairFlag repair = NoRepair,
CheckSigsFlag checkSigs = CheckSigs, CheckSigsFlag checkSigs = CheckSigs,
SubstituteFlag substitute = NoSubstitute); SubstituteFlag substitute = NoSubstitute);
/* Copy the closure of `paths` from `srcStore` to `dstStore`. */
void copyClosure(
Store & srcStore, Store & dstStore,
const RealisedPath::Set & paths,
RepairFlag repair = NoRepair,
CheckSigsFlag checkSigs = CheckSigs,
SubstituteFlag substitute = NoSubstitute);
/* Remove the temporary roots file for this process. Any temporary /* Remove the temporary roots file for this process. Any temporary
root becomes garbage after this point unless it has been registered root becomes garbage after this point unless it has been registered

View file

@ -9,7 +9,7 @@ namespace nix {
#define WORKER_MAGIC_1 0x6e697863 #define WORKER_MAGIC_1 0x6e697863
#define WORKER_MAGIC_2 0x6478696f #define WORKER_MAGIC_2 0x6478696f
#define PROTOCOL_VERSION (1 << 8 | 31) #define PROTOCOL_VERSION (1 << 8 | 32)
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00) #define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff) #define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
@ -55,6 +55,7 @@ typedef enum {
wopQueryDerivationOutputMap = 41, wopQueryDerivationOutputMap = 41,
wopRegisterDrvOutput = 42, wopRegisterDrvOutput = 42,
wopQueryRealisation = 43, wopQueryRealisation = 43,
wopAddMultipleToStore = 44,
} WorkerOp; } WorkerOp;

View file

@ -250,8 +250,9 @@ static void main_nix_build(int argc, char * * argv)
throw UsageError("'-p' and '-E' are mutually exclusive"); throw UsageError("'-p' and '-E' are mutually exclusive");
auto store = openStore(); auto store = openStore();
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
auto state = std::make_unique<EvalState>(myArgs.searchPath, store); auto state = std::make_unique<EvalState>(myArgs.searchPath, evalStore, store);
state->repair = repair; state->repair = repair;
auto autoArgs = myArgs.getAutoArgs(*state); auto autoArgs = myArgs.getAutoArgs(*state);
@ -301,8 +302,8 @@ static void main_nix_build(int argc, char * * argv)
absolute = canonPath(absPath(i), true); absolute = canonPath(absPath(i), true);
} catch (Error & e) {}; } catch (Error & e) {};
auto [path, outputNames] = parsePathWithOutputs(absolute); auto [path, outputNames] = parsePathWithOutputs(absolute);
if (store->isStorePath(path) && hasSuffix(path, ".drv")) if (evalStore->isStorePath(path) && hasSuffix(path, ".drv"))
drvs.push_back(DrvInfo(*state, store, absolute)); drvs.push_back(DrvInfo(*state, evalStore, absolute));
else else
/* If we're in a #! script, interpret filenames /* If we're in a #! script, interpret filenames
relative to the script. */ relative to the script. */
@ -340,7 +341,7 @@ static void main_nix_build(int argc, char * * argv)
printMissing(ref<Store>(store), willBuild, willSubstitute, unknown, downloadSize, narSize); printMissing(ref<Store>(store), willBuild, willSubstitute, unknown, downloadSize, narSize);
if (!dryRun) if (!dryRun)
store->buildPaths(paths, buildMode); store->buildPaths(paths, buildMode, evalStore);
}; };
if (runEnv) { if (runEnv) {
@ -348,9 +349,10 @@ static void main_nix_build(int argc, char * * argv)
throw UsageError("nix-shell requires a single derivation"); throw UsageError("nix-shell requires a single derivation");
auto & drvInfo = drvs.front(); auto & drvInfo = drvs.front();
auto drv = store->derivationFromPath(store->parseStorePath(drvInfo.queryDrvPath())); auto drv = evalStore->derivationFromPath(evalStore->parseStorePath(drvInfo.queryDrvPath()));
std::vector<StorePathWithOutputs> pathsToBuild; std::vector<StorePathWithOutputs> pathsToBuild;
RealisedPath::Set pathsToCopy;
/* Figure out what bash shell to use. If $NIX_BUILD_SHELL /* Figure out what bash shell to use. If $NIX_BUILD_SHELL
is not set, then build bashInteractive from is not set, then build bashInteractive from
@ -369,7 +371,9 @@ static void main_nix_build(int argc, char * * argv)
if (!drv) if (!drv)
throw Error("the 'bashInteractive' attribute in <nixpkgs> did not evaluate to a derivation"); throw Error("the 'bashInteractive' attribute in <nixpkgs> did not evaluate to a derivation");
pathsToBuild.push_back({store->parseStorePath(drv->queryDrvPath())}); auto bashDrv = store->parseStorePath(drv->queryDrvPath());
pathsToBuild.push_back({bashDrv});
pathsToCopy.insert(bashDrv);
shell = drv->queryOutPath() + "/bin/bash"; shell = drv->queryOutPath() + "/bin/bash";
@ -384,9 +388,14 @@ static void main_nix_build(int argc, char * * argv)
for (const auto & input : drv.inputDrvs) for (const auto & input : drv.inputDrvs)
if (std::all_of(envExclude.cbegin(), envExclude.cend(), if (std::all_of(envExclude.cbegin(), envExclude.cend(),
[&](const string & exclude) { return !std::regex_search(store->printStorePath(input.first), std::regex(exclude)); })) [&](const string & exclude) { return !std::regex_search(store->printStorePath(input.first), std::regex(exclude)); }))
{
pathsToBuild.push_back({input.first, input.second}); pathsToBuild.push_back({input.first, input.second});
for (const auto & src : drv.inputSrcs) pathsToCopy.insert(input.first);
}
for (const auto & src : drv.inputSrcs) {
pathsToBuild.push_back({src}); pathsToBuild.push_back({src});
pathsToCopy.insert(src);
}
buildPaths(pathsToBuild); buildPaths(pathsToBuild);
@ -438,7 +447,7 @@ static void main_nix_build(int argc, char * * argv)
if (env.count("__json")) { if (env.count("__json")) {
StorePathSet inputs; StorePathSet inputs;
for (auto & [depDrvPath, wantedDepOutputs] : drv.inputDrvs) { for (auto & [depDrvPath, wantedDepOutputs] : drv.inputDrvs) {
auto outputs = store->queryPartialDerivationOutputMap(depDrvPath); auto outputs = evalStore->queryPartialDerivationOutputMap(depDrvPath);
for (auto & i : wantedDepOutputs) { for (auto & i : wantedDepOutputs) {
auto o = outputs.at(i); auto o = outputs.at(i);
store->computeFSClosure(*o, inputs); store->computeFSClosure(*o, inputs);
@ -531,6 +540,7 @@ static void main_nix_build(int argc, char * * argv)
std::vector<StorePathWithOutputs> pathsToBuild; std::vector<StorePathWithOutputs> pathsToBuild;
std::vector<std::pair<StorePath, std::string>> pathsToBuildOrdered; std::vector<std::pair<StorePath, std::string>> pathsToBuildOrdered;
RealisedPath::Set drvsToCopy;
std::map<StorePath, std::pair<size_t, StringSet>> drvMap; std::map<StorePath, std::pair<size_t, StringSet>> drvMap;
@ -543,14 +553,14 @@ static void main_nix_build(int argc, char * * argv)
pathsToBuild.push_back({drvPath, {outputName}}); pathsToBuild.push_back({drvPath, {outputName}});
pathsToBuildOrdered.push_back({drvPath, {outputName}}); pathsToBuildOrdered.push_back({drvPath, {outputName}});
drvsToCopy.insert(drvPath);
auto i = drvMap.find(drvPath); auto i = drvMap.find(drvPath);
if (i != drvMap.end()) if (i != drvMap.end())
i->second.second.insert(outputName); i->second.second.insert(outputName);
else { else
drvMap[drvPath] = {drvMap.size(), {outputName}}; drvMap[drvPath] = {drvMap.size(), {outputName}};
} }
}
buildPaths(pathsToBuild); buildPaths(pathsToBuild);
@ -564,7 +574,7 @@ static void main_nix_build(int argc, char * * argv)
if (counter) if (counter)
drvPrefix += fmt("-%d", counter + 1); drvPrefix += fmt("-%d", counter + 1);
auto builtOutputs = store->queryPartialDerivationOutputMap(drvPath); auto builtOutputs = evalStore->queryPartialDerivationOutputMap(drvPath);
auto maybeOutputPath = builtOutputs.at(outputName); auto maybeOutputPath = builtOutputs.at(outputName);
assert(maybeOutputPath); assert(maybeOutputPath);

View file

@ -54,10 +54,7 @@ static int main_nix_copy_closure(int argc, char ** argv)
for (auto & path : storePaths) for (auto & path : storePaths)
storePaths2.insert(from->followLinksToStorePath(path)); storePaths2.insert(from->followLinksToStorePath(path));
RealisedPath::Set closure; copyClosure(*from, *to, storePaths2, NoRepair, NoCheckSigs, useSubstitutes);
RealisedPath::closure(*from, storePaths2, closure);
copyPaths(from, to, closure, NoRepair, NoCheckSigs, useSubstitutes);
return 0; return 0;
} }

View file

@ -153,8 +153,9 @@ static int main_nix_instantiate(int argc, char * * argv)
settings.readOnlyMode = true; settings.readOnlyMode = true;
auto store = openStore(); auto store = openStore();
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
auto state = std::make_unique<EvalState>(myArgs.searchPath, store); auto state = std::make_unique<EvalState>(myArgs.searchPath, evalStore, store);
state->repair = repair; state->repair = repair;
Bindings & autoArgs = *myArgs.getAutoArgs(*state); Bindings & autoArgs = *myArgs.getAutoArgs(*state);

View file

@ -100,7 +100,8 @@ UnresolvedApp Installable::toApp(EvalState & state)
throw Error("attribute '%s' has unsupported type '%s'", attrPath, type); throw Error("attribute '%s' has unsupported type '%s'", attrPath, type);
} }
App UnresolvedApp::resolve(ref<Store> store) // FIXME: move to libcmd
App UnresolvedApp::resolve(ref<Store> evalStore, ref<Store> store)
{ {
auto res = unresolved; auto res = unresolved;
@ -110,7 +111,7 @@ App UnresolvedApp::resolve(ref<Store> store)
installableContext.push_back( installableContext.push_back(
std::make_shared<InstallableDerivedPath>(store, ctxElt.toDerivedPath())); std::make_shared<InstallableDerivedPath>(store, ctxElt.toDerivedPath()));
auto builtContext = build(store, Realise::Outputs, installableContext); auto builtContext = build(evalStore, store, Realise::Outputs, installableContext);
res.program = resolveString(*store, unresolved.program, builtContext); res.program = resolveString(*store, unresolved.program, builtContext);
if (!store->isInStore(res.program)) if (!store->isInStore(res.program))
throw Error("app program '%s' is not in the Nix store", res.program); throw Error("app program '%s' is not in the Nix store", res.program);

View file

@ -52,7 +52,10 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
void run(ref<Store> store) override void run(ref<Store> store) override
{ {
auto buildables = build(store, dryRun ? Realise::Nothing : Realise::Outputs, installables, buildMode); auto buildables = build(
getEvalStore(), store,
dryRun ? Realise::Nothing : Realise::Outputs,
installables, buildMode);
if (json) logger->cout("%s", derivedPathsWithHintsToJSON(buildables, store).dump()); if (json) logger->cout("%s", derivedPathsWithHintsToJSON(buildables, store).dump());

View file

@ -69,7 +69,7 @@ struct CmdBundle : InstallableCommand
{ {
auto evalState = getEvalState(); auto evalState = getEvalState();
auto app = installable->toApp(*evalState).resolve(store); auto app = installable->toApp(*evalState).resolve(getEvalStore(), store);
auto [bundlerFlakeRef, bundlerName] = parseFlakeRefWithFragment(bundler, absPath(".")); auto [bundlerFlakeRef, bundlerName] = parseFlakeRefWithFragment(bundler, absPath("."));
const flake::LockFlags lockFlags{ .writeLockFile = false }; const flake::LockFlags lockFlags{ .writeLockFile = false };

View file

@ -90,7 +90,7 @@ struct CmdCopy : BuiltPathsCommand
} }
copyPaths( copyPaths(
srcStore, dstStore, stuffToCopy, NoRepair, checkSigs, substitute); *srcStore, *dstStore, stuffToCopy, NoRepair, checkSigs, substitute);
} }
}; };

View file

@ -171,15 +171,15 @@ const static std::string getEnvSh =
modified derivation with the same dependencies and nearly the same modified derivation with the same dependencies and nearly the same
initial environment variables, that just writes the resulting initial environment variables, that just writes the resulting
environment to a file and exits. */ environment to a file and exits. */
StorePath getDerivationEnvironment(ref<Store> store, const StorePath & drvPath) static StorePath getDerivationEnvironment(ref<Store> store, ref<Store> evalStore, const StorePath & drvPath)
{ {
auto drv = store->derivationFromPath(drvPath); auto drv = evalStore->derivationFromPath(drvPath);
auto builder = baseNameOf(drv.builder); auto builder = baseNameOf(drv.builder);
if (builder != "bash") if (builder != "bash")
throw Error("'nix develop' only works on derivations that use 'bash' as their builder"); throw Error("'nix develop' only works on derivations that use 'bash' as their builder");
auto getEnvShPath = store->addTextToStore("get-env.sh", getEnvSh, {}); auto getEnvShPath = evalStore->addTextToStore("get-env.sh", getEnvSh, {});
drv.args = {store->printStorePath(getEnvShPath)}; drv.args = {store->printStorePath(getEnvShPath)};
@ -205,7 +205,7 @@ StorePath getDerivationEnvironment(ref<Store> store, const StorePath & drvPath)
output.second = { .output = DerivationOutputInputAddressed { .path = StorePath::dummy } }; output.second = { .output = DerivationOutputInputAddressed { .path = StorePath::dummy } };
drv.env[output.first] = ""; drv.env[output.first] = "";
} }
Hash h = std::get<0>(hashDerivationModulo(*store, drv, true)); Hash h = std::get<0>(hashDerivationModulo(*evalStore, drv, true));
for (auto & output : drv.outputs) { for (auto & output : drv.outputs) {
auto outPath = store->makeOutputPath(output.first, h, drv.name); auto outPath = store->makeOutputPath(output.first, h, drv.name);
@ -214,12 +214,12 @@ StorePath getDerivationEnvironment(ref<Store> store, const StorePath & drvPath)
} }
} }
auto shellDrvPath = writeDerivation(*store, drv); auto shellDrvPath = writeDerivation(*evalStore, drv);
/* Build the derivation. */ /* Build the derivation. */
store->buildPaths({DerivedPath::Built{shellDrvPath}}); store->buildPaths({DerivedPath::Built{shellDrvPath}}, bmNormal, evalStore);
for (auto & [_0, optPath] : store->queryPartialDerivationOutputMap(shellDrvPath)) { for (auto & [_0, optPath] : evalStore->queryPartialDerivationOutputMap(shellDrvPath)) {
assert(optPath); assert(optPath);
auto & outPath = *optPath; auto & outPath = *optPath;
assert(store->isValidPath(outPath)); assert(store->isValidPath(outPath));
@ -307,7 +307,7 @@ struct Common : InstallableCommand, MixProfile
auto dir = absPath(dir_); auto dir = absPath(dir_);
auto installable = parseInstallable(store, installable_); auto installable = parseInstallable(store, installable_);
auto builtPaths = toStorePaths( auto builtPaths = toStorePaths(
store, Realise::Nothing, OperateOn::Output, {installable}); getEvalStore(), store, Realise::Nothing, OperateOn::Output, {installable});
for (auto & path: builtPaths) { for (auto & path: builtPaths) {
auto from = store->printStorePath(path); auto from = store->printStorePath(path);
if (script.find(from) == std::string::npos) if (script.find(from) == std::string::npos)
@ -347,7 +347,7 @@ struct Common : InstallableCommand, MixProfile
auto & drvPath = *drvs.begin(); auto & drvPath = *drvs.begin();
return getDerivationEnvironment(store, drvPath); return getDerivationEnvironment(store, getEvalStore(), drvPath);
} }
} }
@ -361,7 +361,7 @@ struct Common : InstallableCommand, MixProfile
debug("reading environment file '%s'", strPath); debug("reading environment file '%s'", strPath);
return {BuildEnvironment::fromJSON(readFile(strPath)), strPath}; return {BuildEnvironment::fromJSON(readFile(store->toRealPath(shellOutPath))), strPath};
} }
}; };
@ -495,8 +495,8 @@ struct CmdDevelop : Common, MixEnvironment
Strings{"legacyPackages." + settings.thisSystem.get() + "."}, Strings{"legacyPackages." + settings.thisSystem.get() + "."},
nixpkgsLockFlags); nixpkgsLockFlags);
shell = state->store->printStorePath( shell = store->printStorePath(
toStorePath(state->store, Realise::Outputs, OperateOn::Output, bashInstallable)) + "/bin/bash"; toStorePath(getEvalStore(), store, Realise::Outputs, OperateOn::Output, bashInstallable)) + "/bin/bash";
} catch (Error &) { } catch (Error &) {
ignoreException(); ignoreException();
} }

View file

@ -131,9 +131,9 @@ struct CmdDiffClosures : SourceExprCommand
void run(ref<Store> store) override void run(ref<Store> store) override
{ {
auto before = parseInstallable(store, _before); auto before = parseInstallable(store, _before);
auto beforePath = toStorePath(store, Realise::Outputs, operateOn, before); auto beforePath = toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, before);
auto after = parseInstallable(store, _after); auto after = parseInstallable(store, _after);
auto afterPath = toStorePath(store, Realise::Outputs, operateOn, after); auto afterPath = toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, after);
printClosureDiff(store, beforePath, afterPath, ""); printClosureDiff(store, beforePath, afterPath, "");
} }
}; };

View file

@ -841,7 +841,7 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun
if (!dryRun && !dstUri.empty()) { if (!dryRun && !dstUri.empty()) {
ref<Store> dstStore = dstUri.empty() ? openStore() : openStore(dstUri); ref<Store> dstStore = dstUri.empty() ? openStore() : openStore(dstUri);
copyPaths(store, dstStore, sources); copyPaths(*store, *dstStore, sources);
} }
} }
}; };

View file

@ -253,7 +253,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
manifest.elements.emplace_back(std::move(element)); manifest.elements.emplace_back(std::move(element));
} else { } else {
auto buildables = build(store, Realise::Outputs, {installable}, bmNormal); auto buildables = build(getEvalStore(), store, Realise::Outputs, {installable}, bmNormal);
for (auto & buildable : buildables) { for (auto & buildable : buildables) {
ProfileElement element; ProfileElement element;

View file

@ -93,7 +93,7 @@ struct CmdShell : InstallablesCommand, RunCommon, MixEnvironment
void run(ref<Store> store) override void run(ref<Store> store) override
{ {
auto outPaths = toStorePaths(store, Realise::Outputs, OperateOn::Output, installables); auto outPaths = toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables);
auto accessor = store->getFSAccessor(); auto accessor = store->getFSAccessor();
@ -178,7 +178,7 @@ struct CmdRun : InstallableCommand, RunCommon
{ {
auto state = getEvalState(); auto state = getEvalState();
auto app = installable->toApp(*state).resolve(store); auto app = installable->toApp(*state).resolve(getEvalStore(), store);
Strings allArgs{app.program}; Strings allArgs{app.program};
for (auto & i : args) allArgs.push_back(i); for (auto & i : args) allArgs.push_back(i);

View file

@ -62,9 +62,9 @@ struct CmdWhyDepends : SourceExprCommand
void run(ref<Store> store) override void run(ref<Store> store) override
{ {
auto package = parseInstallable(store, _package); auto package = parseInstallable(store, _package);
auto packagePath = toStorePath(store, Realise::Outputs, operateOn, package); auto packagePath = toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, package);
auto dependency = parseInstallable(store, _dependency); auto dependency = parseInstallable(store, _dependency);
auto dependencyPath = toStorePath(store, Realise::Derivation, operateOn, dependency); auto dependencyPath = toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency);
auto dependencyPathHash = dependencyPath.hashPart(); auto dependencyPathHash = dependencyPath.hashPart();
StorePathSet closure; StorePathSet closure;

26
tests/eval-store.sh Normal file
View file

@ -0,0 +1,26 @@
source common.sh
eval_store=$TEST_ROOT/eval-store
clearStore
rm -rf "$eval_store"
nix build -f dependencies.nix --eval-store "$eval_store" -o "$TEST_ROOT/result"
[[ -e $TEST_ROOT/result/foobar ]]
(! ls $NIX_STORE_DIR/*.drv)
ls $eval_store/nix/store/*.drv
clearStore
rm -rf "$eval_store"
nix-instantiate dependencies.nix --eval-store "$eval_store"
(! ls $NIX_STORE_DIR/*.drv)
ls $eval_store/nix/store/*.drv
clearStore
rm -rf "$eval_store"
nix-build dependencies.nix --eval-store "$eval_store" -o "$TEST_ROOT/result"
[[ -e $TEST_ROOT/result/foobar ]]
(! ls $NIX_STORE_DIR/*.drv)
ls $eval_store/nix/store/*.drv

View file

@ -56,7 +56,8 @@ nix_tests = \
ca/nix-run.sh \ ca/nix-run.sh \
ca/recursive.sh \ ca/recursive.sh \
ca/concurrent-builds.sh \ ca/concurrent-builds.sh \
ca/nix-copy.sh ca/nix-copy.sh \
eval-store.sh
# parallel.sh # parallel.sh
install-tests += $(foreach x, $(nix_tests), tests/$(x)) install-tests += $(foreach x, $(nix_tests), tests/$(x))