about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/build.cc5
-rw-r--r--src/libstore/store.cc51
-rw-r--r--src/libstore/store.hh14
-rw-r--r--src/nix-store/main.cc17
4 files changed, 74 insertions, 13 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 881f2dac8899..64443d41a785 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -1140,7 +1140,8 @@ void DerivationGoal::computeClosure()
     {
         registerValidPath(txn, i->second.path,
             contentHashes[i->second.path],
-            allReferences[i->second.path]);
+            allReferences[i->second.path],
+            drvPath);
     }
     txn.commit();
 
@@ -1501,7 +1502,7 @@ void SubstitutionGoal::finished()
 
     Transaction txn;
     createStoreTransaction(txn);
-    registerValidPath(txn, storePath, contentHash, references);
+    registerValidPath(txn, storePath, contentHash, references, "");
     txn.commit();
 
     outputLock->setDeletion(true);
diff --git a/src/libstore/store.cc b/src/libstore/store.cc
index b915fce243a8..a3e98f69691d 100644
--- a/src/libstore/store.cc
+++ b/src/libstore/store.cc
@@ -56,6 +56,13 @@ static TableId dbReferers = 0;
 */
 static TableId dbSubstitutes = 0;
 
+/* dbDerivers :: Path -> [Path]
+
+   This table lists the derivation used to build a path.  There can
+   only be multiple such paths for fixed-output derivations (i.e.,
+   derivations specifying an expected hash). */
+static TableId dbDerivers = 0;
+
 
 bool Substitute::operator == (const Substitute & sub)
 {
@@ -78,6 +85,7 @@ void openDB()
     dbReferences = nixDB.openTable("references");
     dbReferers = nixDB.openTable("referers");
     dbSubstitutes = nixDB.openTable("substitutes");
+    dbDerivers = nixDB.openTable("derivers");
 }
 
 
@@ -318,6 +326,30 @@ void queryReferers(const Path & storePath, PathSet & referers)
 }
 
 
+void setDeriver(const Transaction & txn, const Path & storePath,
+    const Path & deriver)
+{
+    assertStorePath(storePath);
+    if (deriver == "") return;
+    assertStorePath(deriver);
+    if (!isRealisablePath(txn, storePath))
+        throw Error(format("path `%1%' is not valid") % storePath);
+    nixDB.setString(txn, dbDerivers, storePath, deriver);
+}
+
+
+Path queryDeriver(const Transaction & txn, const Path & storePath)
+{
+    if (!isRealisablePath(noTxn, storePath))
+        throw Error(format("path `%1%' is not valid") % storePath);
+    Path deriver;
+    if (nixDB.queryString(txn, dbDerivers, storePath, deriver))
+        return deriver;
+    else
+        return "";
+}
+
+
 static Substitutes readSubstitutes(const Transaction & txn,
     const Path & srcPath)
 {
@@ -406,7 +438,8 @@ void clearSubstitutes()
 
 
 void registerValidPath(const Transaction & txn,
-    const Path & _path, const Hash & hash, const PathSet & references)
+    const Path & _path, const Hash & hash, const PathSet & references,
+    const Path & deriver)
 {
     Path path(canonPath(_path));
     assertStorePath(path);
@@ -423,6 +456,8 @@ void registerValidPath(const Transaction & txn,
         if (!isValidPathTxn(txn, *i))
             throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid")
                 % path % *i);
+
+    setDeriver(txn, path, deriver);
 }
 
 
@@ -433,11 +468,13 @@ static void invalidatePath(const Path & path, Transaction & txn)
     debug(format("unregistering path `%1%'") % path);
 
     /* Clear the `references' entry for this path, as well as the
-       inverse `referers' entries; but only if there are no
-       substitutes for this path.  This maintains the cleanup
-       invariant. */
-    if (querySubstitutes(txn, path).size() == 0)
+       inverse `referers' entries, and the `derivers' entry; but only
+       if there are no substitutes for this path.  This maintains the
+       cleanup invariant. */
+    if (querySubstitutes(txn, path).size() == 0) {
         setReferences(txn, path, PathSet());
+        nixDB.delPair(txn, dbDerivers, path);
+    }
     
     nixDB.delPair(txn, dbValidPaths, path);
 }
@@ -498,7 +535,7 @@ Path addToStore(const Path & _srcPath)
             canonicalisePathMetaData(dstPath);
             
             Transaction txn(nixDB);
-            registerValidPath(txn, dstPath, h, PathSet());
+            registerValidPath(txn, dstPath, h, PathSet(), "");
             txn.commit();
         }
 
@@ -534,7 +571,7 @@ Path addTextToStore(const string & suffix, const string & s,
             
             Transaction txn(nixDB);
             registerValidPath(txn, dstPath,
-                hashPath(htSHA256, dstPath), references);
+                hashPath(htSHA256, dstPath), references, "");
             txn.commit();
         }
 
diff --git a/src/libstore/store.hh b/src/libstore/store.hh
index 3a0b7a7131a2..95c738ed1bcc 100644
--- a/src/libstore/store.hh
+++ b/src/libstore/store.hh
@@ -57,7 +57,8 @@ void clearSubstitutes();
    of the file system contents of the path.  The hash must be a
    SHA-256 hash. */
 void registerValidPath(const Transaction & txn,
-    const Path & path, const Hash & hash, const PathSet & references);
+    const Path & path, const Hash & hash, const PathSet & references,
+    const Path & deriver);
 
 /* Throw an exception if `path' is not directly in the Nix store. */
 void assertStorePath(const Path & path);
@@ -77,7 +78,8 @@ void canonicalisePathMetaData(const Path & path);
 /* Checks whether a path is valid. */ 
 bool isValidPath(const Path & path);
 
-/* Sets the set of outgoing FS references for a store path. */
+/* Sets the set of outgoing FS references for a store path.  Use with
+   care! */
 void setReferences(const Transaction & txn, const Path & storePath,
     const PathSet & references);
 
@@ -89,6 +91,14 @@ void queryReferences(const Path & storePath, PathSet & references);
    result is not cleared. */
 void queryReferers(const Path & storePath, PathSet & referers);
 
+/* Sets the deriver of a store path.  Use with care! */
+void setDeriver(const Transaction & txn, const Path & storePath,
+    const Path & deriver);
+
+/* Query the deriver of a store path.  Return the empty string if no
+   deriver has been set. */
+Path queryDeriver(const Transaction & txn, const Path & storePath);
+
 /* Constructs a unique store path name. */
 Path makeStorePath(const string & type,
     const Hash & hash, const string & suffix);
diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc
index d473475b821a..4b8d2cf3f75c 100644
--- a/src/nix-store/main.cc
+++ b/src/nix-store/main.cc
@@ -162,7 +162,7 @@ static void printPathSet(const PathSet & paths)
 static void opQuery(Strings opFlags, Strings opArgs)
 {
     enum { qOutputs, qRequisites, qReferences, qReferers,
-           qReferersClosure, qGraph } query = qOutputs;
+           qReferersClosure, qDeriver, qGraph } query = qOutputs;
     bool useOutput = false;
     bool includeOutputs = false;
     bool forceRealise = false;
@@ -174,6 +174,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
         else if (*i == "--references") query = qReferences;
         else if (*i == "--referers") query = qReferers;
         else if (*i == "--referers-closure") query = qReferersClosure;
+        else if (*i == "--deriver" || *i == "-d") query = qDeriver;
         else if (*i == "--graph") query = qGraph;
         else if (*i == "--use-output" || *i == "-u") useOutput = true;
         else if (*i == "--force-realise" || *i == "-f") forceRealise = true;
@@ -214,6 +215,18 @@ static void opQuery(Strings opFlags, Strings opArgs)
             break;
         }
 
+        case qDeriver:
+            for (Strings::iterator i = opArgs.begin();
+                 i != opArgs.end(); i++)
+            {
+                *i = followSymlinks(*i);
+                Path deriver = queryDeriver(noTxn, *i);
+                cout << format("%1%\n") %
+                    (deriver == "" ? "unknown-deriver" : deriver);
+            }
+            break;
+                
+
 #if 0            
         case qGraph: {
             PathSet roots;
@@ -288,7 +301,7 @@ static void opValidPath(Strings opFlags, Strings opArgs)
     createStoreTransaction(txn);
     for (Strings::iterator i = opArgs.begin();
          i != opArgs.end(); ++i)
-        registerValidPath(txn, *i, hashPath(htSHA256, *i), PathSet());
+        registerValidPath(txn, *i, hashPath(htSHA256, *i), PathSet(), "");
     txn.commit();
 }