aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/gc.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-06-02 15:08:18 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-06-02 16:02:48 +0200
commit4494000e04122f24558e1436e66d20d89028b4bd (patch)
tree4d8bb49449aa6f8611a05c96bc9d7342430232f2 /src/libstore/gc.cc
parent064816ab98e7a230b6e9f4071353f5172e70cf03 (diff)
LocalStore: Allow the physical and logical store directories to differ
This is primarily to subsume the functionality of the copy-from-other-stores substituter. For example, in the NixOS installer, we can now do (assuming we're in the target chroot, and the Nix store of the installation CD is bind-mounted on /tmp/nix): $ nix-build ... --option substituters 'local?state=/tmp/nix/var&real=/tmp/nix/store' However, unlike copy-from-other-stores, this also allows write access to such a store. One application might be fetching substitutes for /nix/store in a situation where the user doesn't have sufficient privileges to create /nix, e.g.: $ NIX_REMOTE="local?state=/home/alice/nix/var&real=/home/alice/nix/store" nix-build ...
Diffstat (limited to 'src/libstore/gc.cc')
-rw-r--r--src/libstore/gc.cc39
1 files changed, 20 insertions, 19 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index e5be048d8..77d13bbdc 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -370,7 +370,6 @@ struct LocalStore::GCState
bool gcKeepDerivations;
unsigned long long bytesInvalidated;
bool moveToTrash = true;
- Path trashDir;
bool shouldDelete;
GCState(GCResults & results_) : results(results_), bytesInvalidated(0) { }
};
@@ -407,10 +406,12 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
invalidatePathChecked(path);
}
+ Path realPath = realStoreDir + "/" + baseNameOf(path);
+
struct stat st;
- if (lstat(path.c_str(), &st)) {
+ if (lstat(realPath.c_str(), &st)) {
if (errno == ENOENT) return;
- throw SysError(format("getting status of %1%") % path);
+ throw SysError(format("getting status of %1%") % realPath);
}
printMsg(lvlInfo, format("deleting ‘%1%’") % path);
@@ -427,20 +428,20 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
// if the path was not valid, need to determine the actual
// size.
try {
- if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
- throw SysError(format("making ‘%1%’ writable") % path);
- Path tmp = state.trashDir + "/" + baseNameOf(path);
- if (rename(path.c_str(), tmp.c_str()))
- throw SysError(format("unable to rename ‘%1%’ to ‘%2%’") % path % tmp);
+ if (chmod(realPath.c_str(), st.st_mode | S_IWUSR) == -1)
+ throw SysError(format("making ‘%1%’ writable") % realPath);
+ Path tmp = trashDir + "/" + baseNameOf(path);
+ if (rename(realPath.c_str(), tmp.c_str()))
+ throw SysError(format("unable to rename ‘%1%’ to ‘%2%’") % realPath % tmp);
state.bytesInvalidated += size;
} catch (SysError & e) {
if (e.errNo == ENOSPC) {
- printMsg(lvlInfo, format("note: can't create move ‘%1%’: %2%") % path % e.msg());
- deleteGarbage(state, path);
+ printMsg(lvlInfo, format("note: can't create move ‘%1%’: %2%") % realPath % e.msg());
+ deleteGarbage(state, realPath);
}
}
} else
- deleteGarbage(state, path);
+ deleteGarbage(state, realPath);
if (state.results.bytesFreed + state.bytesInvalidated > state.options.maxFreed) {
printMsg(lvlInfo, format("deleted or invalidated more than %1% bytes; stopping") % state.options.maxFreed);
@@ -508,7 +509,8 @@ void LocalStore::tryToDelete(GCState & state, const Path & path)
{
checkInterrupt();
- if (path == linksDir || path == state.trashDir) return;
+ auto realPath = realStoreDir + "/" + baseNameOf(path);
+ if (realPath == linksDir || realPath == trashDir) return;
Activity act(*logger, lvlDebug, format("considering whether to delete ‘%1%’") % path);
@@ -590,7 +592,6 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
{
GCState state(results);
state.options = options;
- state.trashDir = storeDir + "/trash";
state.gcKeepOutputs = settings.gcKeepOutputs;
state.gcKeepDerivations = settings.gcKeepDerivations;
@@ -639,9 +640,9 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
that is not reachable from `roots' is garbage. */
if (state.shouldDelete) {
- if (pathExists(state.trashDir)) deleteGarbage(state, state.trashDir);
+ if (pathExists(trashDir)) deleteGarbage(state, trashDir);
try {
- createDirs(state.trashDir);
+ createDirs(trashDir);
} catch (SysError & e) {
if (e.errNo == ENOSPC) {
printMsg(lvlInfo, format("note: can't create trash directory: %1%") % e.msg());
@@ -671,8 +672,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
try {
- AutoCloseDir dir = opendir(storeDir.c_str());
- if (!dir) throw SysError(format("opening directory ‘%1%’") % storeDir);
+ AutoCloseDir dir = opendir(realStoreDir.c_str());
+ if (!dir) throw SysError(format("opening directory ‘%1%’") % realStoreDir);
/* Read the store and immediately delete all paths that
aren't valid. When using --max-freed etc., deleting
@@ -725,8 +726,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
fds.clear();
/* Delete the trash directory. */
- printMsg(lvlInfo, format("deleting ‘%1%’") % state.trashDir);
- deleteGarbage(state, state.trashDir);
+ printMsg(lvlInfo, format("deleting ‘%1%’") % trashDir);
+ deleteGarbage(state, trashDir);
/* Clean up the links directory. */
if (options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific) {