about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/local-store.hh4
-rw-r--r--src/libstore/misc.cc54
-rw-r--r--src/libstore/misc.hh4
-rw-r--r--src/libstore/remote-store.cc10
-rw-r--r--src/libstore/remote-store.hh2
-rw-r--r--src/libstore/store-api.hh6
-rw-r--r--src/libstore/worker-protocol.hh3
-rw-r--r--src/nix-daemon/nix-daemon.cc3
-rw-r--r--src/nix-store/nix-store.cc3
9 files changed, 64 insertions, 25 deletions
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index bb5a9143ceef..82ca791a3fb2 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -111,10 +111,6 @@ public:
 
     Path queryDeriver(const Path & path);
 
-    /* Return all currently valid derivations that have `path' as an
-       output.  (Note that the result of `queryDeriver()' is the
-       derivation that was actually used to produce `path', which may
-       not exist anymore.) */
     PathSet queryValidDerivers(const Path & path);
 
     PathSet queryDerivationOutputs(const Path & path);
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc
index 899e4764c1d6..74ff26b9cc5c 100644
--- a/src/libstore/misc.cc
+++ b/src/libstore/misc.cc
@@ -15,27 +15,47 @@ Derivation derivationFromPath(StoreAPI & store, const Path & drvPath)
 }
 
 
-void computeFSClosure(StoreAPI & store, const Path & storePath,
-    PathSet & paths, bool flipDirection, bool includeOutputs)
+void computeFSClosure(StoreAPI & store, const Path & path,
+    PathSet & paths, bool flipDirection, bool includeOutputs, bool includeDerivers)
 {
-    if (paths.find(storePath) != paths.end()) return;
-    paths.insert(storePath);
+    if (paths.find(path) != paths.end()) return;
+    paths.insert(path);
 
-    PathSet references;
-    if (flipDirection)
-        store.queryReferrers(storePath, references);
-    else
-        store.queryReferences(storePath, references);
-
-    if (includeOutputs && isDerivation(storePath)) {
-        PathSet outputs = store.queryDerivationOutputs(storePath);
-        foreach (PathSet::iterator, i, outputs)
-            if (store.isValidPath(*i))
-                computeFSClosure(store, *i, paths, flipDirection, true);
+    PathSet edges;
+
+    if (flipDirection) {
+        store.queryReferrers(path, edges);
+
+        if (includeOutputs) {
+            PathSet derivers = store.queryValidDerivers(path);
+            foreach (PathSet::iterator, i, derivers)
+                edges.insert(*i);
+        }
+
+        if (includeDerivers && isDerivation(path)) {
+            PathSet outputs = store.queryDerivationOutputs(path);
+            foreach (PathSet::iterator, i, outputs)
+                if (store.isValidPath(*i) && store.queryDeriver(*i) == path)
+                    edges.insert(*i);
+        }
+
+    } else {
+        store.queryReferences(path, edges);
+
+        if (includeOutputs && isDerivation(path)) {
+            PathSet outputs = store.queryDerivationOutputs(path);
+            foreach (PathSet::iterator, i, outputs)
+                if (store.isValidPath(*i)) edges.insert(*i);
+        }
+
+        if (includeDerivers) {
+            Path deriver = store.queryDeriver(path);
+            if (store.isValidPath(deriver)) edges.insert(deriver);
+        }
     }
 
-    foreach (PathSet::iterator, i, references)
-        computeFSClosure(store, *i, paths, flipDirection, includeOutputs);
+    foreach (PathSet::iterator, i, edges)
+        computeFSClosure(store, *i, paths, flipDirection, includeOutputs, includeDerivers);
 }
 
 
diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh
index fe0bbdd799d7..b4bd9ed8a49f 100644
--- a/src/libstore/misc.hh
+++ b/src/libstore/misc.hh
@@ -17,9 +17,9 @@ Derivation derivationFromPath(StoreAPI & store, const Path & drvPath);
    `storePath' is returned; that is, the closures under the
    `referrers' relation instead of the `references' relation is
    returned. */
-void computeFSClosure(StoreAPI & store, const Path & storePath,
+void computeFSClosure(StoreAPI & store, const Path & path,
     PathSet & paths, bool flipDirection = false,
-    bool includeOutputs = false);
+    bool includeOutputs = false, bool includeDerivers = false);
 
 /* Return the path corresponding to the output identifier `id' in the
    given derivation. */
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index c97c5fbf044e..8f33b7e5cd46 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -334,6 +334,16 @@ Path RemoteStore::queryDeriver(const Path & path)
 }
 
 
+PathSet RemoteStore::queryValidDerivers(const Path & path)
+{
+    openConnection();
+    writeInt(wopQueryValidDerivers, to);
+    writeString(path, to);
+    processStderr();
+    return readStorePaths<PathSet>(from);
+}
+
+
 PathSet RemoteStore::queryDerivationOutputs(const Path & path)
 {
     openConnection();
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 47c822969f50..14253b92cd0e 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -40,6 +40,8 @@ public:
 
     Path queryDeriver(const Path & path);
     
+    PathSet queryValidDerivers(const Path & path);
+
     PathSet queryDerivationOutputs(const Path & path);
     
     StringSet queryDerivationOutputNames(const Path & path);
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index cbbacc12c92a..053bece7a3a3 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -133,6 +133,12 @@ public:
        no deriver has been set. */
     virtual Path queryDeriver(const Path & path) = 0;
 
+    /* Return all currently valid derivations that have `path' as an
+       output.  (Note that the result of `queryDeriver()' is the
+       derivation that was actually used to produce `path', which may
+       not exist anymore.) */
+    virtual PathSet queryValidDerivers(const Path & path) = 0;
+
     /* Query the outputs of the derivation denoted by `path'. */
     virtual PathSet queryDerivationOutputs(const Path & path) = 0;
 
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index 7e4c3ec5fbde..46035f4577e3 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -6,7 +6,7 @@ namespace nix {
 #define WORKER_MAGIC_1 0x6e697863
 #define WORKER_MAGIC_2 0x6478696f
 
-#define PROTOCOL_VERSION 0x10c
+#define PROTOCOL_VERSION 0x10d
 #define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
 #define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
 
@@ -42,6 +42,7 @@ typedef enum {
     wopQuerySubstitutablePathInfos = 30,
     wopQueryValidPaths = 31,
     wopQuerySubstitutablePaths = 32,
+    wopQueryValidDerivers = 33,
 } WorkerOp;
 
 
diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc
index 9b3c5bda1983..35e5c546e97c 100644
--- a/src/nix-daemon/nix-daemon.cc
+++ b/src/nix-daemon/nix-daemon.cc
@@ -334,6 +334,7 @@ static void performOp(unsigned int clientVersion,
 
     case wopQueryReferences:
     case wopQueryReferrers:
+    case wopQueryValidDerivers:
     case wopQueryDerivationOutputs: {
         Path path = readStorePath(from);
         startWork();
@@ -342,6 +343,8 @@ static void performOp(unsigned int clientVersion,
             store->queryReferences(path, paths);
         else if (op == wopQueryReferrers)
             store->queryReferrers(path, paths);
+        else if (op == wopQueryValidDerivers)
+            paths = store->queryValidDerivers(path);
         else paths = store->queryDerivationOutputs(path);
         stopWork();
         writeStrings(paths, to);
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index c0da37d251da..af4f264a67e6 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -404,7 +404,8 @@ static void opQuery(Strings opFlags, Strings opArgs)
             foreach (Strings::iterator, i, opArgs) {
                 PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
                 foreach (PathSet::iterator, j, paths)
-                    computeFSClosure(*store, *j, referrers, true);
+                    computeFSClosure(*store, *j, referrers, true,
+                        settings.gcKeepOutputs, settings.gcKeepDerivations);
             }
             Roots roots = store->findRoots();
             foreach (Roots::iterator, i, roots)