about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-07-14T15·10+0200
committerEelco Dolstra <edolstra@gmail.com>2017-07-14T16·29+0200
commitfdc9da034fd7e0cb9c5275209d991ed6ca38f1cc (patch)
tree43b8592e523540b47c9b80e1bb0c83178c408437
parent3908d3929ceb07cee5983fa647817f0e7aecbd97 (diff)
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.
-rw-r--r--src/nix/command.hh5
-rw-r--r--src/nix/installables.cc49
-rw-r--r--src/nix/log.cc3
3 files changed, 29 insertions, 28 deletions
diff --git a/src/nix/command.hh b/src/nix/command.hh
index eb736ce3a3e4..ae7709b5dc83 100644
--- a/src/nix/command.hh
+++ b/src/nix/command.hh
@@ -44,11 +44,14 @@ private:
     std::shared_ptr<Store> _store;
 };
 
+struct Whence { std::string outputName; Path drvPath; };
+typedef std::map<Path, Whence> 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 f0d5d547ca33..7fad8fe415c6 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<std::shared_ptr<Installable>> InstallablesCommand::parseInstallables
 
 PathSet InstallablesCommand::toStorePaths(ref<Store> 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 ed610261d1ca..62ae6b8facf0 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);