about summary refs log tree commit diff
path: root/src/nix-store/main.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2005-02-01T12·36+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2005-02-01T12·36+0000
commitdcc37c236c66ba463bd61fec23d046485d8a412f (patch)
treeb1a34feaf2a9a0ca0e0bad89c1671289de9e19d2 /src/nix-store/main.cc
parenta6b65fd5e107416588a6572a88518d8816abcb12 (diff)
* nix-store, nix-instantiate: added an option `--add-root' to
  immediately add the result as a permanent GC root.  This is the only
  way to prevent a race with the garbage collector.  For instance, the
  old style

    ln -s $(nix-store -r $(nix-instantiate foo.nix)) \
      /nix/var/nix/gcroots/result

  has two time windows in which the garbage collector can interfere
  (by GC'ing the derivation and the output, respectively).  On the
  other hand,

    nix-store --add-root /nix/var/nix/gcroots/result -r \
      $(nix-instantiate --add-root /nix/var/nix/gcroots/drv \
        foo.nix)

  is safe.

* nix-build: use `--add-root' to prevent GC races.

Diffstat (limited to 'src/nix-store/main.cc')
-rw-r--r--src/nix-store/main.cc46
1 files changed, 43 insertions, 3 deletions
diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc
index 810fe94b65..c1fedaf48c 100644
--- a/src/nix-store/main.cc
+++ b/src/nix-store/main.cc
@@ -1,5 +1,9 @@
 #include <iostream>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 #include "globals.hh"
 #include "build.hh"
 #include "gc.hh"
@@ -18,6 +22,10 @@ void printHelp()
 }
 
 
+static Path gcRoot;
+static int rootNr = 0;
+
+
 static Path findOutput(const Derivation & drv, string id)
 {
     for (DerivationOutputs::const_iterator i = drv.outputs.begin();
@@ -27,6 +35,22 @@ static Path findOutput(const Derivation & drv, string id)
 }
 
 
+static Path followSymlinks(Path & path)
+{
+    while (!isStorePath(path)) {
+        struct stat st;
+        if (lstat(path.c_str(), &st))
+            throw SysError(format("getting status of `%1%'") % path);
+        if (!S_ISLNK(st.st_mode)) return path;
+        string target = readLink(path);
+        path = canonPath(string(target, 0, 1) == "/"
+            ? target
+            : path + "/" + target);
+    }
+    return path;
+}
+
+
 /* Realisation the given path.  For a derivation that means build it;
    for other paths it means ensure their validity. */
 static Path realisePath(const Path & path)
@@ -35,7 +59,14 @@ static Path realisePath(const Path & path)
         PathSet paths;
         paths.insert(path);
         buildDerivations(paths);
-        return findOutput(derivationFromPath(path), "out");
+        Path outPath = findOutput(derivationFromPath(path), "out");
+        
+        if (gcRoot == "")
+            printGCWarning();
+        else
+            outPath = addPermRoot(outPath, makeRootName(gcRoot, rootNr));
+        
+        return outPath;
     } else {
         ensurePath(path);
         return path;
@@ -48,6 +79,10 @@ static void opRealise(Strings opFlags, Strings opArgs)
 {
     if (!opFlags.empty()) throw UsageError("unknown flag");
 
+    for (Strings::iterator i = opArgs.begin();
+         i != opArgs.end(); i++)
+        *i = followSymlinks(*i);
+            
     if (opArgs.size() > 1) {
         PathSet drvPaths;
         for (Strings::iterator i = opArgs.begin();
@@ -374,8 +409,8 @@ void run(Strings args)
     Strings opFlags, opArgs;
     Operation op = 0;
 
-    for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
-        string arg = *i;
+    for (Strings::iterator i = args.begin(); i != args.end(); ) {
+        string arg = *i++;
 
         Operation oldOp = op;
 
@@ -403,6 +438,11 @@ void run(Strings args)
             op = opInit;
         else if (arg == "--verify")
             op = opVerify;
+        else if (arg == "--add-root") {
+            if (i == args.end())
+                throw UsageError("`--add-root requires an argument");
+            gcRoot = *i++;
+        }
         else if (arg[0] == '-')
             opFlags.push_back(arg);
         else