forked from lix-project/lix
863dcff6c5
representation of closures as ATerms in the Nix store. Instead, the file system pointer graph is now stored in the Nix database. This has many advantages: - It greatly simplifies the implementation (we can drop the notion of `successors', and so on). - It makes registering roots for the garbage collector much easier. Instead of specifying the closure expression as a root, you can simply specify the store path that must be retained as a root. This could not be done previously, since there was no way to find the closure store expression containing a given store path. - Better traceability: it is now possible to query what paths are referenced by a path, and what paths refer to a path.
101 lines
2.6 KiB
C++
101 lines
2.6 KiB
C++
#include "normalise.hh"
|
|
#include "globals.hh"
|
|
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
|
|
#if 0
|
|
void followLivePaths(Path nePath, PathSet & live)
|
|
{
|
|
/* Just to be sure, canonicalise the path. It is important to do
|
|
this here and in findDeadPath() to ensure that a live path is
|
|
not mistaken for a dead path due to some non-canonical
|
|
representation. */
|
|
nePath = canonPath(nePath);
|
|
|
|
if (live.find(nePath) != live.end()) return;
|
|
live.insert(nePath);
|
|
|
|
startNest(nest, lvlDebug, format("following `%1%'") % nePath);
|
|
assertStorePath(nePath);
|
|
|
|
if (isValidPath(nePath)) {
|
|
|
|
/* !!! should make sure that no substitutes are used */
|
|
StoreExpr ne = storeExprFromPath(nePath);
|
|
|
|
/* !!! painfully similar to requisitesWorker() */
|
|
if (ne.type == StoreExpr::neClosure)
|
|
for (ClosureElems::iterator i = ne.closure.elems.begin();
|
|
i != ne.closure.elems.end(); ++i)
|
|
{
|
|
Path p = canonPath(i->first);
|
|
if (live.find(p) == live.end()) {
|
|
debug(format("found live `%1%'") % p);
|
|
assertStorePath(p);
|
|
live.insert(p);
|
|
}
|
|
}
|
|
|
|
else if (ne.type == StoreExpr::neDerivation)
|
|
for (PathSet::iterator i = ne.derivation.inputs.begin();
|
|
i != ne.derivation.inputs.end(); ++i)
|
|
followLivePaths(*i, live);
|
|
|
|
else abort();
|
|
|
|
}
|
|
|
|
Path nfPath;
|
|
if (querySuccessor(nePath, nfPath))
|
|
followLivePaths(nfPath, live);
|
|
}
|
|
|
|
|
|
PathSet findLivePaths(const Paths & roots)
|
|
{
|
|
PathSet live;
|
|
|
|
startNest(nest, lvlDebug, "finding live paths");
|
|
|
|
for (Paths::const_iterator i = roots.begin(); i != roots.end(); ++i)
|
|
followLivePaths(*i, live);
|
|
|
|
return live;
|
|
}
|
|
|
|
|
|
PathSet findDeadPaths(const PathSet & live, time_t minAge)
|
|
{
|
|
PathSet dead;
|
|
|
|
startNest(nest, lvlDebug, "finding dead paths");
|
|
|
|
time_t now = time(0);
|
|
|
|
Strings storeNames = readDirectory(nixStore);
|
|
|
|
for (Strings::iterator i = storeNames.begin(); i != storeNames.end(); ++i) {
|
|
Path p = canonPath(nixStore + "/" + *i);
|
|
|
|
if (minAge > 0) {
|
|
struct stat st;
|
|
if (lstat(p.c_str(), &st) != 0)
|
|
throw SysError(format("obtaining information about `%1%'") % p);
|
|
if (st.st_atime + minAge >= now) continue;
|
|
}
|
|
|
|
if (live.find(p) == live.end()) {
|
|
debug(format("dead path `%1%'") % p);
|
|
dead.insert(p);
|
|
} else
|
|
debug(format("live path `%1%'") % p);
|
|
}
|
|
|
|
return dead;
|
|
}
|
|
#endif
|