aboutsummaryrefslogtreecommitdiff
path: root/src/nix/flake.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-05-29 17:25:41 +0200
committerEelco Dolstra <edolstra@gmail.com>2019-05-29 17:25:41 +0200
commite0aaf05f4fde3096a86c6481ada64aae53bfce93 (patch)
treeb7e9f57a97b631fb0c67b196851ec718cc6552b5 /src/nix/flake.cc
parentde00ed15d3fd70ffd897d660fc337029ab50a0bf (diff)
Add 'nix flake check' command
This evaluates all the 'provides' of a flake and builds the 'check' attributes.
Diffstat (limited to 'src/nix/flake.cc')
-rw-r--r--src/nix/flake.cc93
1 files changed, 91 insertions, 2 deletions
diff --git a/src/nix/flake.cc b/src/nix/flake.cc
index c2781531d..f0231e263 100644
--- a/src/nix/flake.cc
+++ b/src/nix/flake.cc
@@ -3,7 +3,10 @@
#include "shared.hh"
#include "progress-bar.hh"
#include "eval.hh"
+#include "eval-inline.hh"
#include "primops/flake.hh"
+#include "get-drvs.hh"
+#include "store-api.hh"
#include <nlohmann/json.hpp>
#include <queue>
@@ -208,8 +211,6 @@ struct CmdFlakeInfo : FlakeCommand, MixJSON
return "list info about a given flake";
}
- CmdFlakeInfo () { }
-
void run(nix::ref<nix::Store> store) override
{
auto flake = getFlake();
@@ -221,6 +222,93 @@ struct CmdFlakeInfo : FlakeCommand, MixJSON
}
};
+static void enumerateProvides(EvalState & state, Value & vFlake,
+ std::function<void(const std::string & name, Value & vProvide)> callback)
+{
+ state.forceAttrs(vFlake);
+
+ auto vProvides = (*vFlake.attrs->get(state.symbols.create("provides")))->value;
+
+ state.forceAttrs(*vProvides);
+
+ for (auto & attr : *vProvides->attrs)
+ callback(attr.name, *attr.value);
+}
+
+struct CmdFlakeCheck : FlakeCommand, MixJSON
+{
+ bool build = true;
+
+ CmdFlakeCheck()
+ {
+ mkFlag()
+ .longName("no-build")
+ .description("do not build checks")
+ .set(&build, false);
+ }
+
+ std::string name() override
+ {
+ return "check";
+ }
+
+ std::string description() override
+ {
+ return "check whether the flake evaluates and run its tests";
+ }
+
+ void run(nix::ref<nix::Store> store) override
+ {
+ auto state = getEvalState();
+ auto flake = resolveFlake();
+
+ PathSet drvPaths;
+
+ {
+ Activity act(*logger, lvlInfo, actUnknown, "evaluating flake");
+
+ auto vFlake = state->allocValue();
+ flake::callFlake(*state, flake, *vFlake);
+
+ enumerateProvides(*state,
+ *vFlake,
+ [&](const std::string & name, Value & vProvide) {
+ Activity act(*logger, lvlChatty, actUnknown,
+ fmt("checking flake output '%s'", name));
+
+ try {
+ state->forceValue(vProvide);
+
+ if (name == "checks") {
+ state->forceAttrs(vProvide);
+ for (auto & aCheck : *vProvide.attrs) {
+ try {
+ auto drvInfo = getDerivation(*state, *aCheck.value, false);
+ if (!drvInfo)
+ throw Error("flake output 'check.%s' is not a derivation", aCheck.name);
+ drvPaths.insert(drvInfo->queryDrvPath());
+ // FIXME: check meta attributes?
+ } catch (Error & e) {
+ e.addPrefix(fmt("while checking flake check '" ANSI_BOLD "%s" ANSI_NORMAL "':\n", aCheck.name));
+ throw;
+ }
+ }
+ }
+
+ } catch (Error & e) {
+ e.addPrefix(fmt("while checking flake output '" ANSI_BOLD "%s" ANSI_NORMAL "':\n", name));
+ throw;
+ }
+ });
+ }
+
+ if (build) {
+ Activity act(*logger, lvlInfo, actUnknown, "running flake checks");
+ store->buildPaths(drvPaths);
+ }
+ }
+};
+
struct CmdFlakeAdd : MixEvalArgs, Command
{
FlakeUri alias;
@@ -387,6 +475,7 @@ struct CmdFlake : virtual MultiCommand, virtual Command
: MultiCommand({make_ref<CmdFlakeList>()
, make_ref<CmdFlakeUpdate>()
, make_ref<CmdFlakeInfo>()
+ , make_ref<CmdFlakeCheck>()
, make_ref<CmdFlakeDeps>()
, make_ref<CmdFlakeAdd>()
, make_ref<CmdFlakeRemove>()