From 26cf0c674f543ec86a5ccb7e05a4773559bb8f8a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 29 Jun 2020 19:08:50 +0200 Subject: [PATCH] nix run: Use packages/legacyPackages as fallback if there is no app definition 'nix run' will try to run $out/bin/, where is the derivation name (excluding the version). This often works well: $ nix run nixpkgs#hello Hello, world! $ nix run nix -- --version nix (Nix) 2.4pre20200626_adf2fbb $ nix run patchelf -- --version patchelf 0.11.20200623.e61654b $ nix run nixpkgs#firefox -- --version Mozilla Firefox 77.0.1 $ nix run nixpkgs#gimp -- --version GNU Image Manipulation Program version 2.10.14 though not always: $ nix run nixpkgs#git error: unable to execute '/nix/store/kp7wp760l4gryq9s36x481b2x4rfklcy-git-2.25.4/bin/git-minimal': No such file or directory --- src/nix/app.cc | 52 +++++++++++++++++++++++++++-------------- src/nix/flake.cc | 7 ++++-- src/nix/installables.hh | 4 +--- src/nix/run.cc | 12 +++++++--- 4 files changed, 50 insertions(+), 25 deletions(-) diff --git a/src/nix/app.cc b/src/nix/app.cc index 749dea02b..3935297cf 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -1,28 +1,46 @@ #include "installables.hh" #include "store-api.hh" #include "eval-inline.hh" +#include "eval-cache.hh" +#include "names.hh" namespace nix { -App::App(EvalState & state, Value & vApp) -{ - state.forceAttrs(vApp); - - 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); - - 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(program)) - throw Error("app program '%s' is not in the Nix store", program); -} - App Installable::toApp(EvalState & state) { - return App(state, *toValue(state).first); + auto [cursor, attrPath] = getCursor(state, true); + + auto type = cursor->getAttr("type")->getString(); + + if (type == "app") { + auto [program, context] = cursor->getAttr("program")->getStringWithContext(); + + if (!state.store->isInStore(program)) + throw Error("app program '%s' is not in the Nix store", program); + + std::vector context2; + for (auto & [path, name] : context) + context2.push_back({state.store->parseStorePath(path), {name}}); + + return App { + .context = std::move(context2), + .program = program, + }; + } + + else if (type == "derivation") { + auto drvPath = cursor->forceDerivation(); + auto outPath = cursor->getAttr(state.sOutPath)->getString(); + auto outputName = cursor->getAttr(state.sOutputName)->getString(); + auto name = cursor->getAttr(state.sName)->getString(); + return App { + .context = { { drvPath, {outputName} } }, + .program = outPath + "/bin/" + DrvName(name).name, + }; + } + + else + throw Error("attribute '%s' has unsupported type '%s'", attrPath, type); } } diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 17df29fdb..847985ea3 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -243,11 +243,14 @@ struct CmdFlakeCheck : FlakeCommand auto checkApp = [&](const std::string & attrPath, Value & v, const Pos & pos) { try { + #if 0 + // FIXME auto app = App(*state, v); for (auto & i : app.context) { auto [drvPathS, outputName] = decodeContext(i); store->parseStorePath(drvPathS); } + #endif } catch (Error & e) { e.addPrefix(fmt("while checking the app definition '" ANSI_BOLD "%s" ANSI_NORMAL "' at %s:\n", attrPath, pos)); throw; @@ -544,9 +547,9 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand Strings{templateName == "" ? "defaultTemplate" : templateName}, Strings(attrsPathPrefixes), lockFlags); - auto cursor = installable.getCursor(*evalState, true); + auto [cursor, attrPath] = installable.getCursor(*evalState, true); - auto templateDir = cursor.first->getAttr("path")->getString(); + auto templateDir = cursor->getAttr("path")->getString(); assert(store->isInStore(templateDir)); diff --git a/src/nix/installables.hh b/src/nix/installables.hh index 1e6623f88..eb34365d4 100644 --- a/src/nix/installables.hh +++ b/src/nix/installables.hh @@ -24,11 +24,9 @@ typedef std::vector Buildables; struct App { - PathSet context; + std::vector context; Path program; // FIXME: add args, sandbox settings, metadata, ... - - App(EvalState & state, Value & vApp); }; struct Installable diff --git a/src/nix/run.cc b/src/nix/run.cc index 204937cbc..59a6c7252 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -172,12 +172,18 @@ struct CmdRun : InstallableCommand, RunCommon Strings getDefaultFlakeAttrPaths() override { - return {"defaultApp." + settings.thisSystem.get()}; + Strings res{"defaultApp." + settings.thisSystem.get()}; + for (auto & s : SourceExprCommand::getDefaultFlakeAttrPaths()) + res.push_back(s); + return res; } Strings getDefaultFlakeAttrPathPrefixes() override { - return {"apps." + settings.thisSystem.get() + "."}; + Strings res{"apps." + settings.thisSystem.get() + ".", "packages"}; + for (auto & s : SourceExprCommand::getDefaultFlakeAttrPathPrefixes()) + res.push_back(s); + return res; } void run(ref store) override @@ -186,7 +192,7 @@ struct CmdRun : InstallableCommand, RunCommon auto app = installable->toApp(*state); - state->realiseContext(app.context); + state->store->buildPaths(app.context); Strings allArgs{app.program}; for (auto & i : args) allArgs.push_back(i);