about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-09-10T13·58+0200
committerEelco Dolstra <edolstra@gmail.com>2017-09-10T20·40+0200
commitad228d84e56aeb1b5f77ae3bd3f8272f00782a8c (patch)
tree00e47bf7501c2c95e3790ac4a28e2abb27051c74
parent3ed8290e5331011609de462bda67857837998583 (diff)
nix build: Only download the requested derivation outputs
Also some refactoring.
-rw-r--r--src/nix/build.cc2
-rw-r--r--src/nix/command.cc4
-rw-r--r--src/nix/command.hh21
-rw-r--r--src/nix/installables.cc41
-rw-r--r--src/nix/run.cc2
5 files changed, 52 insertions, 18 deletions
diff --git a/src/nix/build.cc b/src/nix/build.cc
index 42b3e42c69e1..915a066497b4 100644
--- a/src/nix/build.cc
+++ b/src/nix/build.cc
@@ -51,7 +51,7 @@ struct CmdBuild : MixDryRun, InstallablesCommand
 
     void run(ref<Store> store) override
     {
-        auto buildables = toBuildables(store, dryRun ? DryRun : Build);
+        auto buildables = toBuildables(store, dryRun ? DryRun : Build, installables);
 
         for (size_t i = 0; i < buildables.size(); ++i) {
             auto & b(buildables[i]);
diff --git a/src/nix/command.cc b/src/nix/command.cc
index 058a7548c893..f69c56896567 100644
--- a/src/nix/command.cc
+++ b/src/nix/command.cc
@@ -118,7 +118,7 @@ void StorePathsCommand::run(ref<Store> store)
     }
 
     else {
-        for (auto & p : toStorePaths(store, NoBuild))
+        for (auto & p : toStorePaths(store, NoBuild, installables))
             storePaths.push_back(p);
 
         if (recursive) {
@@ -134,7 +134,7 @@ void StorePathsCommand::run(ref<Store> store)
 
 void StorePathCommand::run(ref<Store> store)
 {
-    auto storePaths = toStorePaths(store, NoBuild);
+    auto storePaths = toStorePaths(store, NoBuild, installables);
 
     if (storePaths.size() != 1)
         throw UsageError("this command requires exactly one store path");
diff --git a/src/nix/command.hh b/src/nix/command.hh
index b052c42b1de7..182b01ef92e3 100644
--- a/src/nix/command.hh
+++ b/src/nix/command.hh
@@ -93,6 +93,8 @@ private:
     Value * vSourceExpr = 0;
 };
 
+enum RealiseMode { Build, NoBuild, DryRun };
+
 /* A command that operates on a list of "installables", which can be
    store paths, attribute paths, Nix expressions, etc. */
 struct InstallablesCommand : virtual Args, SourceExprCommand
@@ -104,12 +106,6 @@ struct InstallablesCommand : virtual Args, SourceExprCommand
         expectArgs("installables", &_installables);
     }
 
-    enum RealiseMode { Build, NoBuild, DryRun };
-
-    Buildables toBuildables(ref<Store> store, RealiseMode mode);
-
-    PathSet toStorePaths(ref<Store> store, RealiseMode mode);
-
     void prepare() override;
 
     virtual bool useDefaultInstallables() { return true; }
@@ -198,4 +194,17 @@ struct RegisterCommand
     }
 };
 
+std::shared_ptr<Installable> parseInstallable(
+    SourceExprCommand & cmd, ref<Store> store, const std::string & installable,
+    bool useDefaultInstallables);
+
+Buildables toBuildables(ref<Store> store, RealiseMode mode,
+    std::vector<std::shared_ptr<Installable>> installables);
+
+PathSet toStorePaths(ref<Store> store, RealiseMode mode,
+    std::vector<std::shared_ptr<Installable>> installables);
+
+Path toStorePath(ref<Store> store, RealiseMode mode,
+    std::shared_ptr<Installable> installable);
+
 }
diff --git a/src/nix/installables.cc b/src/nix/installables.cc
index f3c7d3075fe8..76df05fa32d2 100644
--- a/src/nix/installables.cc
+++ b/src/nix/installables.cc
@@ -240,7 +240,17 @@ static std::vector<std::shared_ptr<Installable>> parseInstallables(
     return result;
 }
 
-Buildables InstallablesCommand::toBuildables(ref<Store> store, RealiseMode mode)
+std::shared_ptr<Installable> parseInstallable(
+    SourceExprCommand & cmd, ref<Store> store, const std::string & installable,
+    bool useDefaultInstallables)
+{
+    auto installables = parseInstallables(cmd, store, {installable}, false);
+    assert(installables.size() == 1);
+    return installables.front();
+}
+
+Buildables toBuildables(ref<Store> store, RealiseMode mode,
+    std::vector<std::shared_ptr<Installable>> installables)
 {
     if (mode != Build)
         settings.readOnlyMode = true;
@@ -251,8 +261,13 @@ Buildables InstallablesCommand::toBuildables(ref<Store> store, RealiseMode mode)
 
     for (auto & i : installables) {
         for (auto & b : i->toBuildables()) {
-            if (b.drvPath != "")
-                pathsToBuild.insert(b.drvPath);
+            if (b.drvPath != "") {
+                StringSet outputNames;
+                for (auto & output : b.outputs)
+                    outputNames.insert(output.first);
+                pathsToBuild.insert(
+                    b.drvPath + "!" + concatStringsSep(",", outputNames));
+            }
             buildables.push_back(std::move(b));
         }
     }
@@ -265,17 +280,29 @@ Buildables InstallablesCommand::toBuildables(ref<Store> store, RealiseMode mode)
     return buildables;
 }
 
-PathSet InstallablesCommand::toStorePaths(ref<Store> store, RealiseMode mode)
+PathSet toStorePaths(ref<Store> store, RealiseMode mode,
+    std::vector<std::shared_ptr<Installable>> installables)
 {
     PathSet outPaths;
 
-    for (auto & b : toBuildables(store, mode))
+    for (auto & b : toBuildables(store, mode, installables))
         for (auto & output : b.outputs)
             outPaths.insert(output.second);
 
     return outPaths;
 }
 
+Path toStorePath(ref<Store> store, RealiseMode mode,
+    std::shared_ptr<Installable> installable)
+{
+    auto paths = toStorePaths(store, mode, {installable});
+
+    if (paths.size() != 1)
+            throw Error("argument '%s' should evaluate to one store path", installable->what());
+
+    return *paths.begin();
+}
+
 void InstallablesCommand::prepare()
 {
     installables = parseInstallables(*this, getStore(), _installables, useDefaultInstallables());
@@ -283,9 +310,7 @@ void InstallablesCommand::prepare()
 
 void InstallableCommand::prepare()
 {
-    auto installables = parseInstallables(*this, getStore(), {_installable}, false);
-    assert(installables.size() == 1);
-    installable = installables.front();
+    installable = parseInstallable(*this, getStore(), _installable, false);
 }
 
 }
diff --git a/src/nix/run.cc b/src/nix/run.cc
index 31c3c1464f1c..c72ede99c1c2 100644
--- a/src/nix/run.cc
+++ b/src/nix/run.cc
@@ -90,7 +90,7 @@ struct CmdRun : InstallablesCommand
 
     void run(ref<Store> store) override
     {
-        auto outPaths = toStorePaths(store, Build);
+        auto outPaths = toStorePaths(store, Build, installables);
 
         auto accessor = store->getFSAccessor();