diff options
Diffstat (limited to 'src/libstore')
-rw-r--r-- | src/libstore/gc.cc | 27 | ||||
-rw-r--r-- | src/libstore/gc.hh | 5 |
2 files changed, 22 insertions, 10 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index cb808b6d1b68..c02f59f2cca6 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -303,8 +303,8 @@ static Paths topoSort(const PathSet & paths) } -void collectGarbage(GCAction action, PathSet & result, - unsigned long long & bytesFreed) +void collectGarbage(GCAction action, const PathSet & pathsToDelete, + PathSet & result, unsigned long long & bytesFreed) { result.clear(); bytesFreed = 0; @@ -398,17 +398,26 @@ void collectGarbage(GCAction action, PathSet & result, /* Read the Nix store directory to find all currently existing paths. */ - Paths storePaths = readDirectory(nixStore); - PathSet storePaths2; - for (Paths::iterator i = storePaths.begin(); i != storePaths.end(); ++i) - storePaths2.insert(canonPath(nixStore + "/" + *i)); + PathSet storePathSet; + if (action != gcDeleteSpecific) { + Paths entries = readDirectory(nixStore); + for (Paths::iterator i = entries.begin(); i != entries.end(); ++i) + storePathSet.insert(canonPath(nixStore + "/" + *i)); + } else { + for (PathSet::iterator i = pathsToDelete.begin(); + i != pathsToDelete.end(); ++i) + { + assertStorePath(*i); + storePathSet.insert(*i); + } + } /* Topologically sort them under the `referrers' relation. That is, a < b iff a is in referrers(b). This gives us the order in which things can be deleted safely. */ /* !!! when we have multiple output paths per derivation, this will not work anymore because we get cycles. */ - storePaths = topoSort(storePaths2); + Paths storePaths = topoSort(storePathSet); /* Try to delete store paths in the topologically sorted order. */ for (Paths::iterator i = storePaths.begin(); i != storePaths.end(); ++i) { @@ -416,6 +425,8 @@ void collectGarbage(GCAction action, PathSet & result, debug(format("considering deletion of `%1%'") % *i); if (livePaths.find(*i) != livePaths.end()) { + if (action == gcDeleteSpecific) + throw Error(format("cannot delete path `%1%' since it is still alive") % *i); debug(format("live path `%1%'") % *i); continue; } @@ -430,7 +441,7 @@ void collectGarbage(GCAction action, PathSet & result, AutoCloseFD fdLock; - if (action == gcDeleteDead) { + if (action == gcDeleteDead || action == gcDeleteSpecific) { /* Only delete a lock file if we can acquire a write lock on it. That means that it's either stale, or the diff --git a/src/libstore/gc.hh b/src/libstore/gc.hh index eb1858729037..b05d88f93088 100644 --- a/src/libstore/gc.hh +++ b/src/libstore/gc.hh @@ -10,6 +10,7 @@ typedef enum { gcReturnLive, gcReturnDead, gcDeleteDead, + gcDeleteSpecific, } GCAction; /* If `action' is set to `gcReturnRoots', find and return the set of @@ -19,8 +20,8 @@ typedef enum { closure of) the roots. If `action' is `gcReturnDead', return the set of paths not reachable from the roots. If `action' is `gcDeleteDead', actually delete the latter set. */ -void collectGarbage(GCAction action, PathSet & result, - unsigned long long & bytesFreed); +void collectGarbage(GCAction action, const PathSet & pathsToDelete, + PathSet & result, unsigned long long & bytesFreed); /* Register a temporary GC root. This root will automatically disappear when this process exits. WARNING: this function should |