about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/gc.cc6
-rw-r--r--src/libstore/store.cc22
-rw-r--r--src/libstore/store.hh5
-rw-r--r--src/nix-store/main.cc43
4 files changed, 60 insertions, 16 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 6f09e9cb7852..020712368f52 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -60,7 +60,7 @@ void createSymlink(const Path & link, const Path & target, bool careful)
 
     /* Remove the old symlink. */
     if (pathExists(link)) {
-        if (careful && (!isLink(link) || !isStorePath(readLink(link))))
+        if (careful && (!isLink(link) || !isInStore(readLink(link))))
             throw Error(format("cannot create symlink `%1%'; already exists") % link);
         unlink(link.c_str());
     }
@@ -250,10 +250,10 @@ static void findRoots(const Path & path, bool recurseSymlinks,
         string target = readLink(path);
         Path target2 = absPath(target, dirOf(path));
 
-        if (isStorePath(target2)) {
+        if (isInStore(target2)) {
             debug(format("found root `%1%' in `%2%'")
                 % target2 % path);
-            roots.insert(target2);
+            roots.insert(toStorePath(target2));
         }
 
         else if (recurseSymlinks) {
diff --git a/src/libstore/store.cc b/src/libstore/store.cc
index a3e98f69691d..693a388b3e1e 100644
--- a/src/libstore/store.cc
+++ b/src/libstore/store.cc
@@ -176,12 +176,18 @@ void copyPath(const Path & src, const Path & dst)
 }
 
 
-bool isStorePath(const Path & path)
+bool isInStore(const Path & path)
 {
     return path[0] == '/'
         && path.compare(0, nixStore.size(), nixStore) == 0
         && path.size() >= nixStore.size() + 2
-        && path[nixStore.size()] == '/'
+        && path[nixStore.size()] == '/';
+}
+
+
+bool isStorePath(const Path & path)
+{
+    return isInStore(path)
         && path.find('/', nixStore.size() + 1) == Path::npos;
 }
 
@@ -193,6 +199,18 @@ void assertStorePath(const Path & path)
 }
 
 
+Path toStorePath(const Path & path)
+{
+    if (!isInStore(path))
+        throw Error(format("path `%1%' is not in the Nix store") % path);
+    unsigned int slash = path.find('/', nixStore.size() + 1);
+    if (slash == Path::npos)
+        return path;
+    else
+        return Path(path, 0, slash);
+}
+
+
 void canonicalisePathMetaData(const Path & path)
 {
     checkInterrupt();
diff --git a/src/libstore/store.hh b/src/libstore/store.hh
index 95c738ed1bcc..1f2b630e106c 100644
--- a/src/libstore/store.hh
+++ b/src/libstore/store.hh
@@ -63,8 +63,13 @@ void registerValidPath(const Transaction & txn,
 /* Throw an exception if `path' is not directly in the Nix store. */
 void assertStorePath(const Path & path);
 
+bool isInStore(const Path & path);
 bool isStorePath(const Path & path);
 
+/* Chop off the parts after the top-level store name, e.g.,
+   /nix/store/abcd-foo/bar => /nix/store/abcd-foo. */
+Path toStorePath(const Path & path);
+
 /* "Fix", or canonicalise, the meta-data of the files in a store path
    after it has been built.  In particular:
    - the last modification date on each file is set to 0 (i.e.,
diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc
index 4b8d2cf3f75c..f9bd3323f447 100644
--- a/src/nix-store/main.cc
+++ b/src/nix-store/main.cc
@@ -32,15 +32,15 @@ static Path findOutput(const Derivation & drv, string id)
 }
 
 
-static Path followSymlinks(Path & path)
+static Path fixPath(Path path)
 {
     path = absPath(path);
-    while (!isStorePath(path)) {
-        if (!isLink(path)) return path;
+    while (!isInStore(path)) {
+        if (!isLink(path)) break;
         string target = readLink(path);
         path = absPath(target, dirOf(path));
     }
-    return path;
+    return toStorePath(path);
 }
 
 
@@ -76,7 +76,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
 
     for (Strings::iterator i = opArgs.begin();
          i != opArgs.end(); i++)
-        *i = followSymlinks(*i);
+        *i = fixPath(*i);
             
     if (opArgs.size() > 1) {
         PathSet drvPaths;
@@ -162,19 +162,27 @@ static void printPathSet(const PathSet & paths)
 static void opQuery(Strings opFlags, Strings opArgs)
 {
     enum { qOutputs, qRequisites, qReferences, qReferers,
-           qReferersClosure, qDeriver, qGraph } query = qOutputs;
+           qReferersClosure, qDeriver, qBinding, qGraph } query = qOutputs;
     bool useOutput = false;
     bool includeOutputs = false;
     bool forceRealise = false;
+    string bindingName;
 
     for (Strings::iterator i = opFlags.begin();
-         i != opFlags.end(); i++)
+         i != opFlags.end(); ++i)
         if (*i == "--outputs") query = qOutputs;
         else if (*i == "--requisites" || *i == "-R") query = qRequisites;
         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 == "--binding" || *i == "-b") {
+            if (opArgs.size() == 0)
+                throw UsageError("expected binding name");
+            bindingName = opArgs.front();
+            opArgs.pop_front();
+            query = qBinding;
+        }
         else if (*i == "--graph") query = qGraph;
         else if (*i == "--use-output" || *i == "-u") useOutput = true;
         else if (*i == "--force-realise" || *i == "-f") forceRealise = true;
@@ -187,7 +195,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
             for (Strings::iterator i = opArgs.begin();
                  i != opArgs.end(); i++)
             {
-                *i = followSymlinks(*i);
+                *i = fixPath(*i);
                 if (forceRealise) realisePath(*i);
                 Derivation drv = derivationFromPath(*i);
                 cout << format("%1%\n") % findOutput(drv, "out");
@@ -203,7 +211,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
             for (Strings::iterator i = opArgs.begin();
                  i != opArgs.end(); i++)
             {
-                *i = followSymlinks(*i);
+                *i = fixPath(*i);
                 Path path = maybeUseOutput(*i, useOutput, forceRealise);
                 if (query == qRequisites)
                     storePathRequisites(path, includeOutputs, paths);
@@ -219,13 +227,26 @@ static void opQuery(Strings opFlags, Strings opArgs)
             for (Strings::iterator i = opArgs.begin();
                  i != opArgs.end(); i++)
             {
-                *i = followSymlinks(*i);
+                *i = fixPath(*i);
                 Path deriver = queryDeriver(noTxn, *i);
                 cout << format("%1%\n") %
                     (deriver == "" ? "unknown-deriver" : deriver);
             }
             break;
-                
+
+        case qBinding:
+            for (Strings::iterator i = opArgs.begin();
+                 i != opArgs.end(); i++)
+            {
+                *i = fixPath(*i);
+                Derivation drv = derivationFromPath(*i);
+                StringPairs::iterator j = drv.env.find(bindingName);
+                if (j == drv.env.end())
+                    throw Error(format("derivation `%1%' has no environment binding named `%2%'")
+                        % *i % bindingName);
+                cout << format("%1%\n") % j->second;
+            }
+            break;
 
 #if 0            
         case qGraph: {