mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-23 06:26:15 +02:00
nix run: Use packages/legacyPackages as fallback if there is no app definition
'nix run' will try to run $out/bin/<name>, where <name> 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
This commit is contained in:
parent
50f13b06fb
commit
26cf0c674f
4 changed files with 50 additions and 25 deletions
|
@ -1,28 +1,46 @@
|
||||||
#include "installables.hh"
|
#include "installables.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "eval-inline.hh"
|
#include "eval-inline.hh"
|
||||||
|
#include "eval-cache.hh"
|
||||||
|
#include "names.hh"
|
||||||
|
|
||||||
namespace nix {
|
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)
|
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<StorePathWithOutputs> 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,11 +243,14 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
|
|
||||||
auto checkApp = [&](const std::string & attrPath, Value & v, const Pos & pos) {
|
auto checkApp = [&](const std::string & attrPath, Value & v, const Pos & pos) {
|
||||||
try {
|
try {
|
||||||
|
#if 0
|
||||||
|
// FIXME
|
||||||
auto app = App(*state, v);
|
auto app = App(*state, v);
|
||||||
for (auto & i : app.context) {
|
for (auto & i : app.context) {
|
||||||
auto [drvPathS, outputName] = decodeContext(i);
|
auto [drvPathS, outputName] = decodeContext(i);
|
||||||
store->parseStorePath(drvPathS);
|
store->parseStorePath(drvPathS);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addPrefix(fmt("while checking the app definition '" ANSI_BOLD "%s" ANSI_NORMAL "' at %s:\n", attrPath, pos));
|
e.addPrefix(fmt("while checking the app definition '" ANSI_BOLD "%s" ANSI_NORMAL "' at %s:\n", attrPath, pos));
|
||||||
throw;
|
throw;
|
||||||
|
@ -544,9 +547,9 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
|
||||||
Strings{templateName == "" ? "defaultTemplate" : templateName},
|
Strings{templateName == "" ? "defaultTemplate" : templateName},
|
||||||
Strings(attrsPathPrefixes), lockFlags);
|
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));
|
assert(store->isInStore(templateDir));
|
||||||
|
|
||||||
|
|
|
@ -24,11 +24,9 @@ typedef std::vector<Buildable> Buildables;
|
||||||
|
|
||||||
struct App
|
struct App
|
||||||
{
|
{
|
||||||
PathSet context;
|
std::vector<StorePathWithOutputs> context;
|
||||||
Path program;
|
Path program;
|
||||||
// FIXME: add args, sandbox settings, metadata, ...
|
// FIXME: add args, sandbox settings, metadata, ...
|
||||||
|
|
||||||
App(EvalState & state, Value & vApp);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Installable
|
struct Installable
|
||||||
|
|
|
@ -172,12 +172,18 @@ struct CmdRun : InstallableCommand, RunCommon
|
||||||
|
|
||||||
Strings getDefaultFlakeAttrPaths() override
|
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
|
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> store) override
|
void run(ref<Store> store) override
|
||||||
|
@ -186,7 +192,7 @@ struct CmdRun : InstallableCommand, RunCommon
|
||||||
|
|
||||||
auto app = installable->toApp(*state);
|
auto app = installable->toApp(*state);
|
||||||
|
|
||||||
state->realiseContext(app.context);
|
state->store->buildPaths(app.context);
|
||||||
|
|
||||||
Strings allArgs{app.program};
|
Strings allArgs{app.program};
|
||||||
for (auto & i : args) allArgs.push_back(i);
|
for (auto & i : args) allArgs.push_back(i);
|
||||||
|
|
Loading…
Reference in a new issue