nix-store -q --roots: Respect the gc-keep-outputs/gc-keep-derivations settings

So if a path is not garbage solely because it's reachable from a root
due to the gc-keep-outputs or gc-keep-derivations settings, ‘nix-store
-q --roots’ now shows that root.
This commit is contained in:
Eelco Dolstra 2012-12-20 18:41:44 +01:00
parent 06f62defe6
commit 2754a07ead
9 changed files with 63 additions and 24 deletions

View File

@ -111,10 +111,6 @@ public:
Path queryDeriver(const Path & path); Path queryDeriver(const Path & path);
/* Return all currently valid derivations that have `path' as an
output. (Note that the result of `queryDeriver()' is the
derivation that was actually used to produce `path', which may
not exist anymore.) */
PathSet queryValidDerivers(const Path & path); PathSet queryValidDerivers(const Path & path);
PathSet queryDerivationOutputs(const Path & path); PathSet queryDerivationOutputs(const Path & path);

View File

@ -15,27 +15,47 @@ Derivation derivationFromPath(StoreAPI & store, const Path & drvPath)
} }
void computeFSClosure(StoreAPI & store, const Path & storePath, void computeFSClosure(StoreAPI & store, const Path & path,
PathSet & paths, bool flipDirection, bool includeOutputs) PathSet & paths, bool flipDirection, bool includeOutputs, bool includeDerivers)
{ {
if (paths.find(storePath) != paths.end()) return; if (paths.find(path) != paths.end()) return;
paths.insert(storePath); paths.insert(path);
PathSet references; PathSet edges;
if (flipDirection)
store.queryReferrers(storePath, references);
else
store.queryReferences(storePath, references);
if (includeOutputs && isDerivation(storePath)) { if (flipDirection) {
PathSet outputs = store.queryDerivationOutputs(storePath); store.queryReferrers(path, edges);
foreach (PathSet::iterator, i, outputs)
if (store.isValidPath(*i)) if (includeOutputs) {
computeFSClosure(store, *i, paths, flipDirection, true); PathSet derivers = store.queryValidDerivers(path);
foreach (PathSet::iterator, i, derivers)
edges.insert(*i);
}
if (includeDerivers && isDerivation(path)) {
PathSet outputs = store.queryDerivationOutputs(path);
foreach (PathSet::iterator, i, outputs)
if (store.isValidPath(*i) && store.queryDeriver(*i) == path)
edges.insert(*i);
}
} else {
store.queryReferences(path, edges);
if (includeOutputs && isDerivation(path)) {
PathSet outputs = store.queryDerivationOutputs(path);
foreach (PathSet::iterator, i, outputs)
if (store.isValidPath(*i)) edges.insert(*i);
}
if (includeDerivers) {
Path deriver = store.queryDeriver(path);
if (store.isValidPath(deriver)) edges.insert(deriver);
}
} }
foreach (PathSet::iterator, i, references) foreach (PathSet::iterator, i, edges)
computeFSClosure(store, *i, paths, flipDirection, includeOutputs); computeFSClosure(store, *i, paths, flipDirection, includeOutputs, includeDerivers);
} }

View File

@ -17,9 +17,9 @@ Derivation derivationFromPath(StoreAPI & store, const Path & drvPath);
`storePath' is returned; that is, the closures under the `storePath' is returned; that is, the closures under the
`referrers' relation instead of the `references' relation is `referrers' relation instead of the `references' relation is
returned. */ returned. */
void computeFSClosure(StoreAPI & store, const Path & storePath, void computeFSClosure(StoreAPI & store, const Path & path,
PathSet & paths, bool flipDirection = false, PathSet & paths, bool flipDirection = false,
bool includeOutputs = false); bool includeOutputs = false, bool includeDerivers = false);
/* Return the path corresponding to the output identifier `id' in the /* Return the path corresponding to the output identifier `id' in the
given derivation. */ given derivation. */

View File

@ -334,6 +334,16 @@ Path RemoteStore::queryDeriver(const Path & path)
} }
PathSet RemoteStore::queryValidDerivers(const Path & path)
{
openConnection();
writeInt(wopQueryValidDerivers, to);
writeString(path, to);
processStderr();
return readStorePaths<PathSet>(from);
}
PathSet RemoteStore::queryDerivationOutputs(const Path & path) PathSet RemoteStore::queryDerivationOutputs(const Path & path)
{ {
openConnection(); openConnection();

View File

@ -40,6 +40,8 @@ public:
Path queryDeriver(const Path & path); Path queryDeriver(const Path & path);
PathSet queryValidDerivers(const Path & path);
PathSet queryDerivationOutputs(const Path & path); PathSet queryDerivationOutputs(const Path & path);
StringSet queryDerivationOutputNames(const Path & path); StringSet queryDerivationOutputNames(const Path & path);

View File

@ -133,6 +133,12 @@ public:
no deriver has been set. */ no deriver has been set. */
virtual Path queryDeriver(const Path & path) = 0; virtual Path queryDeriver(const Path & path) = 0;
/* Return all currently valid derivations that have `path' as an
output. (Note that the result of `queryDeriver()' is the
derivation that was actually used to produce `path', which may
not exist anymore.) */
virtual PathSet queryValidDerivers(const Path & path) = 0;
/* Query the outputs of the derivation denoted by `path'. */ /* Query the outputs of the derivation denoted by `path'. */
virtual PathSet queryDerivationOutputs(const Path & path) = 0; virtual PathSet queryDerivationOutputs(const Path & path) = 0;

View File

@ -6,7 +6,7 @@ namespace nix {
#define WORKER_MAGIC_1 0x6e697863 #define WORKER_MAGIC_1 0x6e697863
#define WORKER_MAGIC_2 0x6478696f #define WORKER_MAGIC_2 0x6478696f
#define PROTOCOL_VERSION 0x10c #define PROTOCOL_VERSION 0x10d
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00) #define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff) #define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
@ -42,6 +42,7 @@ typedef enum {
wopQuerySubstitutablePathInfos = 30, wopQuerySubstitutablePathInfos = 30,
wopQueryValidPaths = 31, wopQueryValidPaths = 31,
wopQuerySubstitutablePaths = 32, wopQuerySubstitutablePaths = 32,
wopQueryValidDerivers = 33,
} WorkerOp; } WorkerOp;

View File

@ -334,6 +334,7 @@ static void performOp(unsigned int clientVersion,
case wopQueryReferences: case wopQueryReferences:
case wopQueryReferrers: case wopQueryReferrers:
case wopQueryValidDerivers:
case wopQueryDerivationOutputs: { case wopQueryDerivationOutputs: {
Path path = readStorePath(from); Path path = readStorePath(from);
startWork(); startWork();
@ -342,6 +343,8 @@ static void performOp(unsigned int clientVersion,
store->queryReferences(path, paths); store->queryReferences(path, paths);
else if (op == wopQueryReferrers) else if (op == wopQueryReferrers)
store->queryReferrers(path, paths); store->queryReferrers(path, paths);
else if (op == wopQueryValidDerivers)
paths = store->queryValidDerivers(path);
else paths = store->queryDerivationOutputs(path); else paths = store->queryDerivationOutputs(path);
stopWork(); stopWork();
writeStrings(paths, to); writeStrings(paths, to);

View File

@ -404,7 +404,8 @@ static void opQuery(Strings opFlags, Strings opArgs)
foreach (Strings::iterator, i, opArgs) { foreach (Strings::iterator, i, opArgs) {
PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise); PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise);
foreach (PathSet::iterator, j, paths) foreach (PathSet::iterator, j, paths)
computeFSClosure(*store, *j, referrers, true); computeFSClosure(*store, *j, referrers, true,
settings.gcKeepOutputs, settings.gcKeepDerivations);
} }
Roots roots = store->findRoots(); Roots roots = store->findRoots();
foreach (Roots::iterator, i, roots) foreach (Roots::iterator, i, roots)