diff options
author | regnat <rg@regnat.ovh> | 2021-05-17 17:49:20 +0200 |
---|---|---|
committer | regnat <rg@regnat.ovh> | 2021-05-17 17:50:41 +0200 |
commit | ca96f5219489c1002499bfe2c580fdd458219144 (patch) | |
tree | d4b0f564f5a5da65900ab51babf5c85cc328d15e /src | |
parent | bd6cf25952a42afabea822141798566e0f0583b3 (diff) |
Split the parsing of an `App` and its resolving
That way things (like `nix flake check`) can evaluate the `app` outputs
without having to build anything
Diffstat (limited to 'src')
-rw-r--r-- | src/libcmd/installables.hh | 8 | ||||
-rw-r--r-- | src/nix/app.cc | 64 | ||||
-rw-r--r-- | src/nix/bundle.cc | 3 | ||||
-rw-r--r-- | src/nix/run.cc | 4 |
4 files changed, 41 insertions, 38 deletions
diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index 16bc4ae68..298fd48f8 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -23,6 +23,12 @@ struct App // FIXME: add args, sandbox settings, metadata, ... }; +struct UnresolvedApp +{ + App unresolved; + App resolve(ref<Store>); +}; + struct Installable { virtual ~Installable() { } @@ -33,7 +39,7 @@ struct Installable DerivedPath toDerivedPath(); - App toApp(EvalState & state); + UnresolvedApp toApp(EvalState & state); virtual std::pair<Value *, Pos> toValue(EvalState & state) { diff --git a/src/nix/app.cc b/src/nix/app.cc index 1e30deb34..bdc64a886 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -58,33 +58,24 @@ std::string resolveString(Store & store, const std::string & toResolve, const Bu return rewriteStrings(toResolve, rewrites); } -App Installable::toApp(EvalState & state) +UnresolvedApp Installable::toApp(EvalState & state) { auto [cursor, attrPath] = getCursor(state); auto type = cursor->getAttr("type")->getString(); - auto checkProgram = [&](const Path & program) - { - if (!state.store->isInStore(program)) - throw Error("app program '%s' is not in the Nix store", program); - }; + if (type == "app") { + auto [program, context] = cursor->getAttr("program")->getStringWithContext(); - std::vector<std::shared_ptr<Installable>> context; - std::string unresolvedProgram; + std::vector<StorePathWithOutputs> context2; + for (auto & [path, name] : context) + context2.push_back({state.store->parseStorePath(path), {name}}); - if (type == "app") { - auto [program, context_] = cursor->getAttr("program")->getStringWithContext(); - unresolvedProgram = program; - - for (auto & [path, name] : context_) - context.push_back(std::make_shared<InstallableDerivedPath>( - state.store, - DerivedPathBuilt{ - .drvPath = state.store->parseStorePath(path), - .outputs = {name}, - })); + return UnresolvedApp{App { + .context = std::move(context2), + .program = program, + }}; } else if (type == "derivation") { @@ -98,24 +89,33 @@ App Installable::toApp(EvalState & state) aMainProgram ? aMainProgram->getString() : DrvName(name).name; - unresolvedProgram = outPath + "/bin/" + mainProgram; - context = {std::make_shared<InstallableDerivedPath>( - state.store, - DerivedPathBuilt{ - .drvPath = drvPath, - .outputs = {outputName}, - })}; + auto program = outPath + "/bin/" + mainProgram; + return UnresolvedApp { App { + .context = { { drvPath, {outputName} } }, + .program = program, + }}; } else throw Error("attribute '%s' has unsupported type '%s'", attrPath, type); +} + +App UnresolvedApp::resolve(ref<Store> store) +{ + auto res = unresolved; + + std::vector<std::shared_ptr<Installable>> installableContext; + + for (auto & ctxElt : unresolved.context) + installableContext.push_back( + std::make_shared<InstallableDerivedPath>(store, ctxElt.toDerivedPath())); - auto builtContext = build(state.store, Realise::Outputs, context); - auto program = resolveString(*state.store, unresolvedProgram, builtContext); - checkProgram(program); - return App { - .program = program, - }; + auto builtContext = build(store, Realise::Outputs, installableContext); + res.program = resolveString(*store, unresolved.program, builtContext); + if (store->isInStore(res.program)) + throw Error("app program '%s' is not in the Nix store", res.program); + + return res; } } diff --git a/src/nix/bundle.cc b/src/nix/bundle.cc index 53dccc63a..88bc3d1d1 100644 --- a/src/nix/bundle.cc +++ b/src/nix/bundle.cc @@ -69,8 +69,7 @@ struct CmdBundle : InstallableCommand { auto evalState = getEvalState(); - auto app = installable->toApp(*evalState); - store->buildPaths(toDerivedPaths(app.context)); + auto app = installable->toApp(*evalState).resolve(store); auto [bundlerFlakeRef, bundlerName] = parseFlakeRefWithFragment(bundler, absPath(".")); const flake::LockFlags lockFlags{ .writeLockFile = false }; diff --git a/src/nix/run.cc b/src/nix/run.cc index b5d8ab38a..f684c5ea4 100644 --- a/src/nix/run.cc +++ b/src/nix/run.cc @@ -178,9 +178,7 @@ struct CmdRun : InstallableCommand, RunCommon { auto state = getEvalState(); - auto app = installable->toApp(*state); - - state->store->buildPaths(toDerivedPaths(app.context)); + auto app = installable->toApp(*state).resolve(store); Strings allArgs{app.program}; for (auto & i : args) allArgs.push_back(i); |