From fdc9da034fd7e0cb9c5275209d991ed6ca38f1cc Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 14 Jul 2017 17:10:13 +0200 Subject: [PATCH] Avoid a call to derivationFromPath() This doesn't work in read-only mode, ensuring that operations like nix path-info --store https://cache.nixos.org -S nixpkgs.hello (asking for the closure size of nixpkgs.hello in cache.nixos.org) work when nixpkgs.hello doesn't exist in the local store. --- src/nix/command.hh | 5 ++++- src/nix/installables.cc | 49 +++++++++++++++++++---------------------- src/nix/log.cc | 3 ++- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/nix/command.hh b/src/nix/command.hh index eb736ce3a..ae7709b5d 100644 --- a/src/nix/command.hh +++ b/src/nix/command.hh @@ -44,11 +44,14 @@ private: std::shared_ptr _store; }; +struct Whence { std::string outputName; Path drvPath; }; +typedef std::map Buildables; + struct Installable { virtual std::string what() = 0; - virtual PathSet toBuildable() + virtual Buildables toBuildable() { throw Error("argument ā€˜%sā€™ cannot be built", what()); } diff --git a/src/nix/installables.cc b/src/nix/installables.cc index f0d5d547c..7fad8fe41 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -67,9 +67,9 @@ struct InstallableStoreDrv : Installable std::string what() override { return storePath; } - PathSet toBuildable() override + Buildables toBuildable() override { - return {storePath}; + return {{storePath, {}}}; } }; @@ -81,9 +81,9 @@ struct InstallableStorePath : Installable std::string what() override { return storePath; } - PathSet toBuildable() override + Buildables toBuildable() override { - return {storePath}; + return {{storePath, {}}}; } }; @@ -97,7 +97,7 @@ struct InstallableExpr : Installable std::string what() override { return text; } - PathSet toBuildable() override + Buildables toBuildable() override { auto state = installables.getEvalState(); @@ -110,10 +110,11 @@ struct InstallableExpr : Installable DrvInfos drvs; getDerivations(*state, *v, "", autoArgs, drvs, false); - PathSet res; + Buildables res; - for (auto & i : drvs) - res.insert(i.queryDrvPath()); + for (auto & drv : drvs) + for (auto & output : drv.queryOutputs()) + res.emplace(output.second, Whence{output.first, drv.queryDrvPath()}); return res; } @@ -137,7 +138,7 @@ struct InstallableAttrPath : Installable std::string what() override { return attrPath; } - PathSet toBuildable() override + Buildables toBuildable() override { auto state = installables.getEvalState(); @@ -150,10 +151,11 @@ struct InstallableAttrPath : Installable DrvInfos drvs; getDerivations(*state, *v, "", autoArgs, drvs, false); - PathSet res; + Buildables res; - for (auto & i : drvs) - res.insert(i.queryDrvPath()); + for (auto & drv : drvs) + for (auto & output : drv.queryOutputs()) + res.emplace(output.second, Whence{output.first, drv.queryDrvPath()}); return res; } @@ -216,27 +218,22 @@ std::vector> InstallablesCommand::parseInstallables PathSet InstallablesCommand::toStorePaths(ref store, ToStorePathsMode mode) { - PathSet buildables; + if (mode != DryRun) + settings.readOnlyMode = true; - for (auto & i : installables) { - auto b = i->toBuildable(); - buildables.insert(b.begin(), b.end()); - } + PathSet outPaths, buildables; + + for (auto & i : installables) + for (auto & b : i->toBuildable()) { + outPaths.insert(b.first); + buildables.insert(b.second.drvPath != "" ? b.second.drvPath : b.first); + } if (mode == DryRun) printMissing(store, buildables); else if (mode == Build) store->buildPaths(buildables); - PathSet outPaths; - for (auto & path : buildables) - if (isDerivation(path)) { - Derivation drv = store->derivationFromPath(path); - for (auto & output : drv.outputs) - outPaths.insert(output.second.path); - } else - outPaths.insert(path); - return outPaths; } diff --git a/src/nix/log.cc b/src/nix/log.cc index ed610261d..62ae6b8fa 100644 --- a/src/nix/log.cc +++ b/src/nix/log.cc @@ -28,7 +28,8 @@ struct CmdLog : InstallablesCommand subs.push_front(store); for (auto & inst : installables) { - for (auto & path : inst->toBuildable()) { + for (auto & b : inst->toBuildable()) { + auto path = b.second.drvPath != "" ? b.second.drvPath : b.first; bool found = false; for (auto & sub : subs) { auto log = sub->getBuildLog(path);