about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/primops.cc1
-rw-r--r--src/libstore/Makefile.am3
-rw-r--r--src/libstore/build.cc1
-rw-r--r--src/libstore/build.hh17
-rw-r--r--src/libstore/gc.cc2
-rw-r--r--src/libstore/misc.cc47
-rw-r--r--src/libstore/misc.hh32
-rw-r--r--src/nix-env/main.cc38
-rw-r--r--src/nix-store/main.cc1
9 files changed, 120 insertions, 22 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 4b1aef9352ed..310bca5ae97f 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -1,6 +1,7 @@
 #include <algorithm>
 
 #include "build.hh"
+#include "misc.hh"
 #include "eval.hh"
 #include "globals.hh"
 #include "nixexpr-ast.hh"
diff --git a/src/libstore/Makefile.am b/src/libstore/Makefile.am
index 3fa941b3bd79..384f99b9ff28 100644
--- a/src/libstore/Makefile.am
+++ b/src/libstore/Makefile.am
@@ -2,7 +2,8 @@ lib_LTLIBRARIES = libstore.la
 
 libstore_la_SOURCES = \
  store.cc store.hh derivations.cc derivations.hh \
- build.cc misc.cc build.hh \
+ build.cc build.hh \
+ misc.cc misc.hh \
  globals.cc globals.hh db.cc db.hh \
  references.cc references.hh pathlocks.cc pathlocks.hh \
  gc.cc gc.hh derivations-ast.hh
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 2f6d69d3e15e..9dd12a46d6ba 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -17,6 +17,7 @@
 #include "build.hh"
 #include "references.hh"
 #include "pathlocks.hh"
+#include "misc.hh"
 #include "globals.hh"
 #include "gc.hh"
 
diff --git a/src/libstore/build.hh b/src/libstore/build.hh
index 9e3d365e989a..489a6cabc8a5 100644
--- a/src/libstore/build.hh
+++ b/src/libstore/build.hh
@@ -15,23 +15,6 @@ void buildDerivations(const PathSet & drvPaths);
    be made valid by running a substitute (if defined for the path). */
 void ensurePath(const Path & storePath);
 
-/* Read a derivation, after ensuring its existence through
-   ensurePath(). */
-Derivation derivationFromPath(const Path & drvPath);
-
-/* Place in `paths' the set of all store paths in the file system
-   closure of `storePath'; that is, all paths than can be directly or
-   indirectly reached from it.  `paths' is not cleared.  If
-   `flipDirection' is true, the set of paths that can reach
-   `storePath' is returned; that is, the closures under the
-   `referrers' relation instead of the `references' relation is
-   returned. */
-void computeFSClosure(const Path & storePath,
-    PathSet & paths, bool flipDirection = false);
-
-/* Return the path corresponding to the output identifier `id' in the
-   given derivation. */
-Path findOutput(const Derivation & drv, string id);
     
 
 #endif /* !__BUILD_H */
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 5f4f5b27ff79..c2bc5bdb1b92 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -1,6 +1,6 @@
 #include "globals.hh"
 #include "gc.hh"
-#include "build.hh"
+#include "misc.hh"
 #include "pathlocks.hh"
 
 #include <boost/shared_ptr.hpp>
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc
index 33efe8bebc98..91cf25f27187 100644
--- a/src/libstore/misc.cc
+++ b/src/libstore/misc.cc
@@ -29,10 +29,55 @@ void computeFSClosure(const Path & storePath,
 }
 
 
- Path findOutput(const Derivation & drv, string id)
+Path findOutput(const Derivation & drv, string id)
 {
     for (DerivationOutputs::const_iterator i = drv.outputs.begin();
          i != drv.outputs.end(); ++i)
         if (i->first == id) return i->second.path;
     throw Error(format("derivation has no output `%1%'") % id);
 }
+
+
+void queryMissing(const PathSet & targets,
+    PathSet & willBuild, PathSet & willSubstitute)
+{
+    PathSet todo(targets.begin(), targets.end()), done;
+
+    while (!todo.empty()) {
+        Path p = *(todo.begin());
+        todo.erase(p);
+        if (done.find(p) != done.end()) continue;
+        done.insert(p);
+
+        if (isDerivation(p)) {
+            if (!isValidPath(p)) continue;
+            Derivation drv = derivationFromPath(p);
+
+            bool mustBuild = false;
+            for (DerivationOutputs::iterator i = drv.outputs.begin();
+                 i != drv.outputs.end(); ++i)
+                if (!isValidPath(i->second.path) &&
+                    querySubstitutes(noTxn, i->second.path).size() == 0)
+                    mustBuild = true;
+
+            if (mustBuild) {
+                willBuild.insert(p);
+                todo.insert(drv.inputSrcs.begin(), drv.inputSrcs.end());
+                for (DerivationInputs::iterator i = drv.inputDrvs.begin();
+                     i != drv.inputDrvs.end(); ++i)
+                    todo.insert(i->first);
+            } else 
+                for (DerivationOutputs::iterator i = drv.outputs.begin();
+                     i != drv.outputs.end(); ++i)
+                    todo.insert(i->second.path);
+        }
+
+        else {
+            if (isValidPath(p)) continue;
+            if (querySubstitutes(noTxn, p).size() > 0)
+                willSubstitute.insert(p);
+            PathSet refs;
+            queryReferences(noTxn, p, todo);
+        }
+    }
+}
diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh
new file mode 100644
index 000000000000..f758f5bfd58e
--- /dev/null
+++ b/src/libstore/misc.hh
@@ -0,0 +1,32 @@
+#ifndef __MISC_H
+#define __MISC_H
+
+#include "derivations.hh"
+
+
+/* Read a derivation, after ensuring its existence through
+   ensurePath(). */
+Derivation derivationFromPath(const Path & drvPath);
+
+/* Place in `paths' the set of all store paths in the file system
+   closure of `storePath'; that is, all paths than can be directly or
+   indirectly reached from it.  `paths' is not cleared.  If
+   `flipDirection' is true, the set of paths that can reach
+   `storePath' is returned; that is, the closures under the
+   `referrers' relation instead of the `references' relation is
+   returned. */
+void computeFSClosure(const Path & storePath,
+    PathSet & paths, bool flipDirection = false);
+
+/* Return the path corresponding to the output identifier `id' in the
+   given derivation. */
+Path findOutput(const Derivation & drv, string id);
+
+/* Given a set of paths that are to be built, return the set of
+   derivations that will be built, and the set of output paths that
+   will be substituted. */
+void queryMissing(const PathSet & targets,
+    PathSet & willBuild, PathSet & willSubstitute);
+
+
+#endif /* !__MISC_H */
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 84c89a157ae1..8648e4f0f871 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -2,6 +2,7 @@
 #include "names.hh"
 #include "globals.hh"
 #include "build.hh"
+#include "misc.hh"
 #include "gc.hh"
 #include "shared.hh"
 #include "parser.hh"
@@ -383,6 +384,33 @@ static void queryInstSources(EvalState & state,
 }
 
 
+static void printMissing(EvalState & state, const DrvInfos & elems)
+{
+    PathSet targets, willBuild, willSubstitute;
+    for (DrvInfos::const_iterator i = elems.begin(); i != elems.end(); ++i) {
+        Path drvPath = i->queryDrvPath(state);
+        if (drvPath != "")
+            targets.insert(drvPath);
+        else
+            targets.insert(i->queryOutPath(state));
+    }
+
+    queryMissing(targets, willBuild, willSubstitute);
+
+    if (!willBuild.empty()) {
+        printMsg(lvlInfo, format("the following derivations will be built:"));
+        for (PathSet::iterator i = willBuild.begin(); i != willBuild.end(); ++i)
+            printMsg(lvlInfo, format("  %1%") % *i);
+    }
+
+    if (!willSubstitute.empty()) {
+        printMsg(lvlInfo, format("the following paths will be substituted:"));
+        for (PathSet::iterator i = willSubstitute.begin(); i != willSubstitute.end(); ++i)
+            printMsg(lvlInfo, format("  %1%") % *i);
+    }
+}
+
+
 static void installDerivations(Globals & globals,
     const Strings & args, const Path & profile)
 {
@@ -417,7 +445,10 @@ static void installDerivations(Globals & globals,
         printMsg(lvlInfo,
             format("installing `%1%'") % i->name);
         
-    if (globals.dryRun) return;
+    if (globals.dryRun) {
+        printMissing(globals.state, newElems);
+        return;
+    }
 
     createUserEnv(globals.state, allElems,
         profile, globals.keepDerivations);
@@ -500,7 +531,10 @@ static void upgradeDerivations(Globals & globals,
         } else newElems.push_back(*i);
     }
     
-    if (globals.dryRun) return;
+    if (globals.dryRun) {
+        printMissing(globals.state, newElems);
+        return;
+    }
 
     createUserEnv(globals.state, newElems,
         profile, globals.keepDerivations);
diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc
index ae386a0220a3..132516cd9396 100644
--- a/src/nix-store/main.cc
+++ b/src/nix-store/main.cc
@@ -3,6 +3,7 @@
 
 #include "globals.hh"
 #include "build.hh"
+#include "misc.hh"
 #include "gc.hh"
 #include "archive.hh"
 #include "shared.hh"