mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-11 00:36:20 +02:00
8d9f7048cd
In particular, this now works: $ nix path-info --eval-store auto --store https://cache.nixos.org nixpkgs#hello Previously this would fail as it would try to upload the hello .drv to cache.nixos.org. Now the .drv is instantiated in the local store, and then we check for the existence of the outputs in cache.nixos.org.
122 lines
3.5 KiB
C++
122 lines
3.5 KiB
C++
#include "installables.hh"
|
|
#include "store-api.hh"
|
|
#include "eval-inline.hh"
|
|
#include "eval-cache.hh"
|
|
#include "names.hh"
|
|
#include "command.hh"
|
|
|
|
namespace nix {
|
|
|
|
struct InstallableDerivedPath : Installable
|
|
{
|
|
ref<Store> store;
|
|
const DerivedPath derivedPath;
|
|
|
|
InstallableDerivedPath(ref<Store> store, const DerivedPath & derivedPath)
|
|
: store(store)
|
|
, derivedPath(derivedPath)
|
|
{
|
|
}
|
|
|
|
|
|
std::string what() override { return derivedPath.to_string(*store); }
|
|
|
|
DerivedPaths toDerivedPaths() override
|
|
{
|
|
return {derivedPath};
|
|
}
|
|
|
|
std::optional<StorePath> getStorePath() override
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Return the rewrites that are needed to resolve a string whose context is
|
|
* included in `dependencies`
|
|
*/
|
|
StringPairs resolveRewrites(Store & store, const BuiltPaths dependencies)
|
|
{
|
|
StringPairs res;
|
|
for (auto & dep : dependencies)
|
|
if (auto drvDep = std::get_if<BuiltPathBuilt>(&dep))
|
|
for (auto & [ outputName, outputPath ] : drvDep->outputs)
|
|
res.emplace(
|
|
downstreamPlaceholder(store, drvDep->drvPath, outputName),
|
|
store.printStorePath(outputPath)
|
|
);
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Resolve the given string assuming the given context
|
|
*/
|
|
std::string resolveString(Store & store, const std::string & toResolve, const BuiltPaths dependencies)
|
|
{
|
|
auto rewrites = resolveRewrites(store, dependencies);
|
|
return rewriteStrings(toResolve, rewrites);
|
|
}
|
|
|
|
UnresolvedApp Installable::toApp(EvalState & state)
|
|
{
|
|
auto [cursor, attrPath] = getCursor(state);
|
|
|
|
auto type = cursor->getAttr("type")->getString();
|
|
|
|
if (type == "app") {
|
|
auto [program, context] = cursor->getAttr("program")->getStringWithContext();
|
|
|
|
|
|
std::vector<StorePathWithOutputs> context2;
|
|
for (auto & [path, name] : context)
|
|
context2.push_back({state.store->parseStorePath(path), {name}});
|
|
|
|
return UnresolvedApp{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();
|
|
auto aMeta = cursor->maybeGetAttr("meta");
|
|
auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr;
|
|
auto mainProgram =
|
|
aMainProgram
|
|
? aMainProgram->getString()
|
|
: DrvName(name).name;
|
|
auto program = outPath + "/bin/" + mainProgram;
|
|
return UnresolvedApp { App {
|
|
.context = { { drvPath, {outputName} } },
|
|
.program = program,
|
|
}};
|
|
}
|
|
|
|
else
|
|
throw Error("attribute '%s' has unsupported type '%s'", attrPath, type);
|
|
}
|
|
|
|
// FIXME: move to libcmd
|
|
App UnresolvedApp::resolve(ref<Store> evalStore, 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(evalStore, 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;
|
|
}
|
|
|
|
}
|