aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nix/command.hh49
-rw-r--r--src/nix/installables.cc237
-rw-r--r--src/nix/installables.hh97
3 files changed, 205 insertions, 178 deletions
diff --git a/src/nix/command.hh b/src/nix/command.hh
index 92f606bbe..802dd9828 100644
--- a/src/nix/command.hh
+++ b/src/nix/command.hh
@@ -1,15 +1,15 @@
#pragma once
+#include "installables.hh"
#include "args.hh"
#include "common-eval-args.hh"
+
#include <optional>
namespace nix {
extern std::string programPath;
-struct Value;
-class Bindings;
class EvalState;
class Store;
@@ -30,51 +30,6 @@ private:
std::shared_ptr<Store> _store;
};
-struct Buildable
-{
- Path drvPath; // may be empty
- std::map<std::string, Path> outputs;
-};
-
-typedef std::vector<Buildable> Buildables;
-
-struct App
-{
- PathSet context;
- Path program;
- // FIXME: add args, sandbox settings, metadata, ...
-
- App(EvalState & state, Value & vApp);
-};
-
-struct Installable
-{
- virtual ~Installable() { }
-
- virtual std::string what() = 0;
-
- virtual Buildables toBuildables()
- {
- throw Error("argument '%s' cannot be built", what());
- }
-
- Buildable toBuildable();
-
- App toApp(EvalState & state);
-
- virtual Value * toValue(EvalState & state)
- {
- throw Error("argument '%s' cannot be evaluated", what());
- }
-
- /* Return a value only if this installable is a store path or a
- symlink to it. */
- virtual std::optional<Path> getStorePath()
- {
- return {};
- }
-};
-
struct EvalCommand : virtual StoreCommand, MixEvalArgs
{
ref<EvalState> getEvalState();
diff --git a/src/nix/installables.cc b/src/nix/installables.cc
index 5611a84ae..93509955a 100644
--- a/src/nix/installables.cc
+++ b/src/nix/installables.cc
@@ -1,3 +1,4 @@
+#include "installables.hh"
#include "command.hh"
#include "attr-path.hh"
#include "common-eval-args.hh"
@@ -111,65 +112,58 @@ struct InstallableStorePath : Installable
}
};
-struct InstallableValue : Installable
+std::vector<flake::EvalCache::Derivation> InstallableValue::toDerivations()
{
- SourceExprCommand & cmd;
+ auto state = cmd.getEvalState();
- InstallableValue(SourceExprCommand & cmd) : cmd(cmd) { }
+ auto v = toValue(*state);
- virtual std::vector<flake::EvalCache::Derivation> toDerivations()
- {
- auto state = cmd.getEvalState();
-
- auto v = toValue(*state);
-
- Bindings & autoArgs = *cmd.getAutoArgs(*state);
+ Bindings & autoArgs = *cmd.getAutoArgs(*state);
- DrvInfos drvInfos;
- getDerivations(*state, *v, "", autoArgs, drvInfos, false);
+ DrvInfos drvInfos;
+ getDerivations(*state, *v, "", autoArgs, drvInfos, false);
- std::vector<flake::EvalCache::Derivation> res;
- for (auto & drvInfo : drvInfos) {
- res.push_back({
- drvInfo.queryDrvPath(),
- drvInfo.queryOutPath(),
- drvInfo.queryOutputName()
- });
- }
-
- return res;
+ std::vector<flake::EvalCache::Derivation> res;
+ for (auto & drvInfo : drvInfos) {
+ res.push_back({
+ drvInfo.queryDrvPath(),
+ drvInfo.queryOutPath(),
+ drvInfo.queryOutputName()
+ });
}
- Buildables toBuildables() override
- {
- Buildables res;
+ return res;
+}
- PathSet drvPaths;
+Buildables InstallableValue::toBuildables()
+{
+ Buildables res;
- for (auto & drv : toDerivations()) {
- Buildable b{drv.drvPath};
- drvPaths.insert(b.drvPath);
+ PathSet drvPaths;
- auto outputName = drv.outputName;
- if (outputName == "")
- throw Error("derivation '%s' lacks an 'outputName' attribute", b.drvPath);
+ for (auto & drv : toDerivations()) {
+ Buildable b{drv.drvPath};
+ drvPaths.insert(b.drvPath);
- b.outputs.emplace(outputName, drv.outPath);
+ auto outputName = drv.outputName;
+ if (outputName == "")
+ throw Error("derivation '%s' lacks an 'outputName' attribute", b.drvPath);
- res.push_back(std::move(b));
- }
+ b.outputs.emplace(outputName, drv.outPath);
- // Hack to recognize .all: if all drvs have the same drvPath,
- // merge the buildables.
- if (drvPaths.size() == 1) {
- Buildable b{*drvPaths.begin()};
- for (auto & b2 : res)
- b.outputs.insert(b2.outputs.begin(), b2.outputs.end());
- return {b};
- } else
- return res;
+ res.push_back(std::move(b));
}
-};
+
+ // Hack to recognize .all: if all drvs have the same drvPath,
+ // merge the buildables.
+ if (drvPaths.size() == 1) {
+ Buildable b{*drvPaths.begin()};
+ for (auto & b2 : res)
+ b.outputs.insert(b2.outputs.begin(), b2.outputs.end());
+ return {b};
+ } else
+ return res;
+}
struct InstallableExpr : InstallableValue
{
@@ -254,123 +248,104 @@ void makeFlakeClosureGCRoot(Store & store,
store.addIndirectRoot(symlink);
}
-struct InstallableFlake : InstallableValue
+std::vector<std::string> InstallableFlake::getActualAttrPaths()
{
- FlakeRef flakeRef;
- Strings attrPaths;
- Strings prefixes;
-
- InstallableFlake(SourceExprCommand & cmd, FlakeRef && flakeRef, Strings attrPaths)
- : InstallableValue(cmd), flakeRef(flakeRef), attrPaths(std::move(attrPaths))
- { }
+ std::vector<std::string> res;
- InstallableFlake(SourceExprCommand & cmd, FlakeRef && flakeRef,
- std::string attrPath, Strings && prefixes)
- : InstallableValue(cmd), flakeRef(flakeRef), attrPaths{attrPath},
- prefixes(prefixes)
- { }
-
- std::string what() override { return flakeRef.to_string() + ":" + *attrPaths.begin(); }
-
- std::vector<std::string> getActualAttrPaths()
- {
- std::vector<std::string> res;
-
- for (auto & prefix : prefixes)
- res.push_back(prefix + *attrPaths.begin());
+ for (auto & prefix : prefixes)
+ res.push_back(prefix + *attrPaths.begin());
- for (auto & s : attrPaths)
- res.push_back(s);
+ for (auto & s : attrPaths)
+ res.push_back(s);
- return res;
- }
+ return res;
+}
- Value * getFlakeOutputs(EvalState & state, const flake::ResolvedFlake & resFlake)
- {
- auto vFlake = state.allocValue();
+Value * InstallableFlake::getFlakeOutputs(EvalState & state, const flake::ResolvedFlake & resFlake)
+{
+ auto vFlake = state.allocValue();
- callFlake(state, resFlake, *vFlake);
+ callFlake(state, resFlake, *vFlake);
- makeFlakeClosureGCRoot(*state.store, flakeRef, resFlake);
+ makeFlakeClosureGCRoot(*state.store, flakeRef, resFlake);
- auto aOutputs = vFlake->attrs->get(state.symbols.create("outputs"));
- assert(aOutputs);
+ auto aOutputs = vFlake->attrs->get(state.symbols.create("outputs"));
+ assert(aOutputs);
- state.forceValue(*(*aOutputs)->value);
+ state.forceValue(*(*aOutputs)->value);
- return (*aOutputs)->value;
- }
+ return (*aOutputs)->value;
+}
- std::vector<flake::EvalCache::Derivation> toDerivations() override
- {
- auto state = cmd.getEvalState();
+std::vector<flake::EvalCache::Derivation> InstallableFlake::toDerivations()
+{
+ auto state = cmd.getEvalState();
- auto resFlake = resolveFlake(*state, flakeRef, cmd.getLockFileMode());
+ auto resFlake = resolveFlake(*state, flakeRef, cmd.getLockFileMode());
- Value * vOutputs = nullptr;
+ Value * vOutputs = nullptr;
- auto emptyArgs = state->allocBindings(0);
+ auto emptyArgs = state->allocBindings(0);
- auto & evalCache = flake::EvalCache::singleton();
+ auto & evalCache = flake::EvalCache::singleton();
- auto fingerprint = resFlake.getFingerprint();
+ auto fingerprint = resFlake.getFingerprint();
- for (auto & attrPath : getActualAttrPaths()) {
- auto drv = evalCache.getDerivation(fingerprint, attrPath);
- if (drv) {
- if (state->store->isValidPath(drv->drvPath))
- return {*drv};
- }
+ for (auto & attrPath : getActualAttrPaths()) {
+ auto drv = evalCache.getDerivation(fingerprint, attrPath);
+ if (drv) {
+ if (state->store->isValidPath(drv->drvPath))
+ return {*drv};
+ }
- if (!vOutputs)
- vOutputs = getFlakeOutputs(*state, resFlake);
+ if (!vOutputs)
+ vOutputs = getFlakeOutputs(*state, resFlake);
- try {
- auto * v = findAlongAttrPath(*state, attrPath, *emptyArgs, *vOutputs);
- state->forceValue(*v);
+ try {
+ auto * v = findAlongAttrPath(*state, attrPath, *emptyArgs, *vOutputs);
+ state->forceValue(*v);
- auto drvInfo = getDerivation(*state, *v, false);
- if (!drvInfo)
- throw Error("flake output attribute '%s' is not a derivation", attrPath);
+ auto drvInfo = getDerivation(*state, *v, false);
+ if (!drvInfo)
+ throw Error("flake output attribute '%s' is not a derivation", attrPath);
- auto drv = flake::EvalCache::Derivation{
- drvInfo->queryDrvPath(),
- drvInfo->queryOutPath(),
- drvInfo->queryOutputName()
- };
+ auto drv = flake::EvalCache::Derivation{
+ drvInfo->queryDrvPath(),
+ drvInfo->queryOutPath(),
+ drvInfo->queryOutputName()
+ };
- evalCache.addDerivation(fingerprint, attrPath, drv);
+ evalCache.addDerivation(fingerprint, attrPath, drv);
- return {drv};
- } catch (AttrPathNotFound & e) {
- }
+ return {drv};
+ } catch (AttrPathNotFound & e) {
}
-
- throw Error("flake '%s' does not provide attribute %s",
- flakeRef, concatStringsSep(", ", quoteStrings(attrPaths)));
}
- Value * toValue(EvalState & state) override
- {
- auto resFlake = resolveFlake(state, flakeRef, cmd.getLockFileMode());
+ throw Error("flake '%s' does not provide attribute %s",
+ flakeRef, concatStringsSep(", ", quoteStrings(attrPaths)));
+}
- auto vOutputs = getFlakeOutputs(state, resFlake);
+Value * InstallableFlake::toValue(EvalState & state)
+{
+ auto resFlake = resolveFlake(state, flakeRef, cmd.getLockFileMode());
- auto emptyArgs = state.allocBindings(0);
+ auto vOutputs = getFlakeOutputs(state, resFlake);
- for (auto & attrPath : getActualAttrPaths()) {
- try {
- auto * v = findAlongAttrPath(state, attrPath, *emptyArgs, *vOutputs);
- state.forceValue(*v);
- return v;
- } catch (AttrPathNotFound & e) {
- }
- }
+ auto emptyArgs = state.allocBindings(0);
- throw Error("flake '%s' does not provide attribute %s",
- flakeRef, concatStringsSep(", ", quoteStrings(attrPaths)));
+ for (auto & attrPath : getActualAttrPaths()) {
+ try {
+ auto * v = findAlongAttrPath(state, attrPath, *emptyArgs, *vOutputs);
+ state.forceValue(*v);
+ return v;
+ } catch (AttrPathNotFound & e) {
+ }
}
-};
+
+ throw Error("flake '%s' does not provide attribute %s",
+ flakeRef, concatStringsSep(", ", quoteStrings(attrPaths)));
+}
// FIXME: extend
std::string attrRegex = R"([A-Za-z_][A-Za-z0-9-_+]*)";
diff --git a/src/nix/installables.hh b/src/nix/installables.hh
new file mode 100644
index 000000000..020a61a2b
--- /dev/null
+++ b/src/nix/installables.hh
@@ -0,0 +1,97 @@
+#pragma once
+
+#include "util.hh"
+#include "flake/eval-cache.hh"
+
+#include <optional>
+
+namespace nix {
+
+struct Value;
+class EvalState;
+class SourceExprCommand;
+
+struct Buildable
+{
+ Path drvPath; // may be empty
+ std::map<std::string, Path> outputs;
+};
+
+typedef std::vector<Buildable> Buildables;
+
+struct App
+{
+ PathSet context;
+ Path program;
+ // FIXME: add args, sandbox settings, metadata, ...
+
+ App(EvalState & state, Value & vApp);
+};
+
+struct Installable
+{
+ virtual ~Installable() { }
+
+ virtual std::string what() = 0;
+
+ virtual Buildables toBuildables()
+ {
+ throw Error("argument '%s' cannot be built", what());
+ }
+
+ Buildable toBuildable();
+
+ App toApp(EvalState & state);
+
+ virtual Value * toValue(EvalState & state)
+ {
+ throw Error("argument '%s' cannot be evaluated", what());
+ }
+
+ /* Return a value only if this installable is a store path or a
+ symlink to it. */
+ virtual std::optional<Path> getStorePath()
+ {
+ return {};
+ }
+};
+
+struct InstallableValue : Installable
+{
+ SourceExprCommand & cmd;
+
+ InstallableValue(SourceExprCommand & cmd) : cmd(cmd) { }
+
+ virtual std::vector<flake::EvalCache::Derivation> toDerivations();
+
+ Buildables toBuildables() override;
+};
+
+struct InstallableFlake : InstallableValue
+{
+ FlakeRef flakeRef;
+ Strings attrPaths;
+ Strings prefixes;
+
+ InstallableFlake(SourceExprCommand & cmd, FlakeRef && flakeRef, Strings attrPaths)
+ : InstallableValue(cmd), flakeRef(flakeRef), attrPaths(std::move(attrPaths))
+ { }
+
+ InstallableFlake(SourceExprCommand & cmd, FlakeRef && flakeRef,
+ std::string attrPath, Strings && prefixes)
+ : InstallableValue(cmd), flakeRef(flakeRef), attrPaths{attrPath},
+ prefixes(prefixes)
+ { }
+
+ std::string what() override { return flakeRef.to_string() + ":" + *attrPaths.begin(); }
+
+ std::vector<std::string> getActualAttrPaths();
+
+ Value * getFlakeOutputs(EvalState & state, const flake::ResolvedFlake & resFlake);
+
+ std::vector<flake::EvalCache::Derivation> toDerivations() override;
+
+ Value * toValue(EvalState & state) override;
+};
+
+}