aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-06-18 16:15:40 +0200
committerGitHub <noreply@github.com>2019-06-18 16:15:40 +0200
commiteb18aedccbc0d01b6a5cc720ce1befd0b316aebf (patch)
tree1bb0b5d9c3ebdcf9cb0802b1e93a5e085bd20832
parentd4a48b12fafea6a35054cd5d4f014551e8e4e352 (diff)
parent556f33422d0a064ef100fe232f60b42b34bf40e2 (diff)
Merge pull request #2951 from NixOS/app-improvements
App / check improvements
-rw-r--r--src/libexpr/primops.cc14
-rw-r--r--src/nix/command.hh14
-rw-r--r--src/nix/flake.cc39
-rw-r--r--src/nix/installables.cc50
-rw-r--r--src/nix/run.cc13
5 files changed, 92 insertions, 38 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index a9a1a1e35..10ce1abf5 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -51,21 +51,20 @@ void EvalState::realiseContext(const PathSet & context)
PathSet drvs;
for (auto & i : context) {
- std::pair<string, string> decoded = decodeContext(i);
- Path ctx = decoded.first;
+ auto [ctx, outputName] = decodeContext(i);
assert(store->isStorePath(ctx));
if (!store->isValidPath(ctx))
throw InvalidPathError(ctx);
- if (!decoded.second.empty() && nix::isDerivation(ctx)) {
- drvs.insert(decoded.first + "!" + decoded.second);
+ if (!outputName.empty() && nix::isDerivation(ctx)) {
+ drvs.insert(ctx + "!" + outputName);
/* Add the output of this derivation to the allowed
paths. */
if (allowedPaths) {
- auto drv = store->derivationFromPath(decoded.first);
- DerivationOutputs::iterator i = drv.outputs.find(decoded.second);
+ auto drv = store->derivationFromPath(ctx);
+ DerivationOutputs::iterator i = drv.outputs.find(outputName);
if (i == drv.outputs.end())
- throw Error("derivation '%s' does not have an output named '%s'", decoded.first, decoded.second);
+ throw Error("derivation '%s' does not have an output named '%s'", ctx, outputName);
allowedPaths->insert(i->second.path);
}
}
@@ -80,6 +79,7 @@ void EvalState::realiseContext(const PathSet & context)
PathSet willBuild, willSubstitute, unknown;
unsigned long long downloadSize, narSize;
store->queryMissing(drvs, willBuild, willSubstitute, unknown, downloadSize, narSize);
+
store->buildPaths(drvs);
}
diff --git a/src/nix/command.hh b/src/nix/command.hh
index 659b724c3..0ffbe46f5 100644
--- a/src/nix/command.hh
+++ b/src/nix/command.hh
@@ -43,6 +43,8 @@ struct App
PathSet context;
Path program;
// FIXME: add args, sandbox settings, metadata, ...
+
+ App(EvalState & state, Value & vApp);
};
struct Installable
@@ -102,6 +104,18 @@ struct SourceExprCommand : virtual Args, EvalCommand, MixFlakeOptions
{
return {"defaultPackage"};
}
+
+ virtual Strings getDefaultFlakeAttrPathPrefixes()
+ {
+ return {
+ // As a convenience, look for the attribute in
+ // 'outputs.packages'.
+ "packages.",
+ // As a temporary hack until Nixpkgs is properly converted
+ // to provide a clean 'packages' set, look in 'legacyPackages'.
+ "legacyPackages."
+ };
+ }
};
enum RealiseMode { Build, NoBuild, DryRun };
diff --git a/src/nix/flake.cc b/src/nix/flake.cc
index f1406becc..6fc56827f 100644
--- a/src/nix/flake.cc
+++ b/src/nix/flake.cc
@@ -7,6 +7,7 @@
#include "flake/flake.hh"
#include "get-drvs.hh"
#include "store-api.hh"
+#include "derivations.hh"
#include <nlohmann/json.hpp>
#include <queue>
@@ -226,8 +227,8 @@ struct CmdFlakeInfo : FlakeCommand, MixJSON
if (json) {
auto json = flakeToJson(flake);
-#if 0
auto state = getEvalState();
+ auto flake = resolveFlake();
auto vFlake = state->allocValue();
flake::callFlake(*state, flake, *vFlake);
@@ -249,7 +250,6 @@ struct CmdFlakeInfo : FlakeCommand, MixJSON
});
json["outputs"] = std::move(outputs);
-#endif
std::cout << json.dump() << std::endl;
} else
@@ -294,13 +294,27 @@ struct CmdFlakeCheck : FlakeCommand, MixJSON
// FIXME: check meta attributes
return drvInfo->queryDrvPath();
} catch (Error & e) {
- e.addPrefix(fmt("while checking flake output attribute '" ANSI_BOLD "%s" ANSI_NORMAL "':\n", attrPath));
+ e.addPrefix(fmt("while checking the derivation '" ANSI_BOLD "%s" ANSI_NORMAL "':\n", attrPath));
throw;
}
};
PathSet drvPaths;
+ auto checkApp = [&](const std::string & attrPath, Value & v) {
+ try {
+ auto app = App(*state, v);
+ for (auto & i : app.context) {
+ auto [drvPath, outputName] = decodeContext(i);
+ if (!outputName.empty() && nix::isDerivation(drvPath))
+ drvPaths.insert(drvPath + "!" + outputName);
+ }
+ } catch (Error & e) {
+ e.addPrefix(fmt("while checking the app definition '" ANSI_BOLD "%s" ANSI_NORMAL "':\n", attrPath));
+ throw;
+ }
+ };
+
{
Activity act(*logger, lvlInfo, actUnknown, "evaluating flake");
@@ -330,9 +344,26 @@ struct CmdFlakeCheck : FlakeCommand, MixJSON
name + "." + (std::string) aCheck.name, *aCheck.value);
}
+ else if (name == "apps") {
+ state->forceAttrs(vProvide);
+ for (auto & aCheck : *vProvide.attrs)
+ checkApp(
+ name + "." + (std::string) aCheck.name, *aCheck.value);
+ }
+
else if (name == "defaultPackage" || name == "devShell")
checkDerivation(name, vProvide);
+ else if (name == "defaultApp")
+ checkApp(name, vProvide);
+
+ else if (name == "legacyPackages")
+ // FIXME: do getDerivations?
+ ;
+
+ else
+ warn("unknown flake output '%s'", name);
+
} catch (Error & e) {
e.addPrefix(fmt("while checking flake output '" ANSI_BOLD "%s" ANSI_NORMAL "':\n", name));
throw;
@@ -340,7 +371,7 @@ struct CmdFlakeCheck : FlakeCommand, MixJSON
});
}
- if (build) {
+ if (build && !drvPaths.empty()) {
Activity act(*logger, lvlInfo, actUnknown, "running flake checks");
store->buildPaths(drvPaths);
}
diff --git a/src/nix/installables.cc b/src/nix/installables.cc
index 1c7debf4e..feaf57f0c 100644
--- a/src/nix/installables.cc
+++ b/src/nix/installables.cc
@@ -69,26 +69,25 @@ Buildable Installable::toBuildable()
return std::move(buildables[0]);
}
-App Installable::toApp(EvalState & state)
+App::App(EvalState & state, Value & vApp)
{
- auto v = toValue(state);
-
- state.forceAttrs(*v);
+ state.forceAttrs(vApp);
- auto aType = v->attrs->need(state.sType);
+ auto aType = vApp.attrs->need(state.sType);
if (state.forceStringNoCtx(*aType.value, *aType.pos) != "app")
throw Error("value does not have type 'app', at %s", *aType.pos);
- App app;
-
- auto aProgram = v->attrs->need(state.symbols.create("program"));
- app.program = state.forceString(*aProgram.value, app.context, *aProgram.pos);
+ auto aProgram = vApp.attrs->need(state.symbols.create("program"));
+ program = state.forceString(*aProgram.value, context, *aProgram.pos);
// FIXME: check that 'program' is in the closure of 'context'.
- if (!state.store->isInStore(app.program))
- throw Error("app program '%s' is not in the Nix store", app.program);
+ if (!state.store->isInStore(program))
+ throw Error("app program '%s' is not in the Nix store", program);
+}
- return app;
+App Installable::toApp(EvalState & state)
+{
+ return App(state, *toValue(state));
}
struct InstallableStorePath : Installable
@@ -257,14 +256,16 @@ struct InstallableFlake : InstallableValue
{
FlakeRef flakeRef;
Strings attrPaths;
- bool searchPackages = false;
+ 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)
- : InstallableValue(cmd), flakeRef(flakeRef), attrPaths{attrPath}, searchPackages(true)
+ 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(); }
@@ -273,15 +274,8 @@ struct InstallableFlake : InstallableValue
{
std::vector<std::string> res;
- if (searchPackages) {
- // As a convenience, look for the attribute in
- // 'outputs.packages'.
- res.push_back("packages." + *attrPaths.begin());
-
- // As a temporary hack until Nixpkgs is properly converted
- // to provide a clean 'packages' set, look in 'legacyPackages'.
- res.push_back("legacyPackages." + *attrPaths.begin());
- }
+ for (auto & prefix : prefixes)
+ res.push_back(prefix + *attrPaths.begin());
for (auto & s : attrPaths)
res.push_back(s);
@@ -421,7 +415,11 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
else if ((colon = s.rfind(':')) != std::string::npos) {
auto flakeRef = std::string(s, 0, colon);
auto attrPath = std::string(s, colon + 1);
- result.push_back(std::make_shared<InstallableFlake>(*this, FlakeRef(flakeRef, true), attrPath));
+ result.push_back(std::make_shared<InstallableFlake>(
+ *this,
+ FlakeRef(flakeRef, true),
+ attrPath,
+ getDefaultFlakeAttrPathPrefixes()));
}
else if (s.find('/') != std::string::npos || s == ".") {
@@ -437,7 +435,7 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
}
else
- result.push_back(std::make_shared<InstallableFlake>(*this, FlakeRef("nixpkgs"), s));
+ throw Error("unsupported argument '%s'", s);
}
}
diff --git a/src/nix/run.cc b/src/nix/run.cc
index 00a682832..d30851d47 100644
--- a/src/nix/run.cc
+++ b/src/nix/run.cc
@@ -196,8 +196,11 @@ static RegisterCommand r1(make_ref<CmdRun>());
struct CmdApp : InstallableCommand, RunCommon
{
+ std::vector<std::string> args;
+
CmdApp()
{
+ expectArgs("args", &args);
}
std::string name() override
@@ -225,6 +228,11 @@ struct CmdApp : InstallableCommand, RunCommon
return {"defaultApp"};
}
+ Strings getDefaultFlakeAttrPathPrefixes() override
+ {
+ return {"apps."};
+ }
+
void run(ref<Store> store) override
{
auto state = getEvalState();
@@ -233,7 +241,10 @@ struct CmdApp : InstallableCommand, RunCommon
state->realiseContext(app.context);
- runProgram(store, app.program, {app.program});
+ Strings allArgs{app.program};
+ for (auto & i : args) allArgs.push_back(i);
+
+ runProgram(store, app.program, allArgs);
}
};