From dcc37c236c66ba463bd61fec23d046485d8a412f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 1 Feb 2005 12:36:25 +0000 Subject: * 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. --- src/nix-store/help.txt | 2 ++ src/nix-store/main.cc | 46 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) (limited to 'src/nix-store') diff --git a/src/nix-store/help.txt b/src/nix-store/help.txt index 35d5423cd8d2..5a5050e47b68 100644 --- a/src/nix-store/help.txt +++ b/src/nix-store/help.txt @@ -42,3 +42,5 @@ Options: --verbose / -v: verbose operation (may be repeated) --keep-failed / -K: keep temporary directories of failed builds + + --add-root: add garbage collector roots for the result diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc index 810fe94b65eb..c1fedaf48cc1 100644 --- a/src/nix-store/main.cc +++ b/src/nix-store/main.cc @@ -1,5 +1,9 @@ #include +#include +#include +#include + #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 -- cgit 1.4.1