From 2754a07eadfa3fe263f83830c701748bbd4c0420 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 20 Dec 2012 18:41:44 +0100 Subject: [PATCH] nix-store -q --roots: Respect the gc-keep-outputs/gc-keep-derivations settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/libstore/local-store.hh | 4 --- src/libstore/misc.cc | 52 +++++++++++++++++++++++---------- src/libstore/misc.hh | 4 +-- src/libstore/remote-store.cc | 10 +++++++ src/libstore/remote-store.hh | 2 ++ src/libstore/store-api.hh | 6 ++++ src/libstore/worker-protocol.hh | 3 +- src/nix-daemon/nix-daemon.cc | 3 ++ src/nix-store/nix-store.cc | 3 +- 9 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index bb5a9143ce..82ca791a3f 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -111,10 +111,6 @@ public: 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 queryDerivationOutputs(const Path & path); diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 899e4764c1..74ff26b9cc 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -15,27 +15,47 @@ Derivation derivationFromPath(StoreAPI & store, const Path & drvPath) } -void computeFSClosure(StoreAPI & store, const Path & storePath, - PathSet & paths, bool flipDirection, bool includeOutputs) +void computeFSClosure(StoreAPI & store, const Path & path, + PathSet & paths, bool flipDirection, bool includeOutputs, bool includeDerivers) { - if (paths.find(storePath) != paths.end()) return; - paths.insert(storePath); + if (paths.find(path) != paths.end()) return; + paths.insert(path); - PathSet references; - if (flipDirection) - store.queryReferrers(storePath, references); - else - store.queryReferences(storePath, references); + PathSet edges; - if (includeOutputs && isDerivation(storePath)) { - PathSet outputs = store.queryDerivationOutputs(storePath); - foreach (PathSet::iterator, i, outputs) - if (store.isValidPath(*i)) - computeFSClosure(store, *i, paths, flipDirection, true); + if (flipDirection) { + store.queryReferrers(path, edges); + + if (includeOutputs) { + 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) - computeFSClosure(store, *i, paths, flipDirection, includeOutputs); + foreach (PathSet::iterator, i, edges) + computeFSClosure(store, *i, paths, flipDirection, includeOutputs, includeDerivers); } diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh index fe0bbdd799..b4bd9ed8a4 100644 --- a/src/libstore/misc.hh +++ b/src/libstore/misc.hh @@ -17,9 +17,9 @@ Derivation derivationFromPath(StoreAPI & store, const Path & drvPath); `storePath' is returned; that is, the closures under the `referrers' relation instead of the `references' relation is returned. */ -void computeFSClosure(StoreAPI & store, const Path & storePath, +void computeFSClosure(StoreAPI & store, const Path & path, 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 given derivation. */ diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index c97c5fbf04..8f33b7e5cd 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -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(from); +} + + PathSet RemoteStore::queryDerivationOutputs(const Path & path) { openConnection(); diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 47c822969f..14253b92cd 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -40,6 +40,8 @@ public: Path queryDeriver(const Path & path); + PathSet queryValidDerivers(const Path & path); + PathSet queryDerivationOutputs(const Path & path); StringSet queryDerivationOutputNames(const Path & path); diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index cbbacc12c9..053bece7a3 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -133,6 +133,12 @@ public: no deriver has been set. */ 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'. */ virtual PathSet queryDerivationOutputs(const Path & path) = 0; diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index 7e4c3ec5fb..46035f4577 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -6,7 +6,7 @@ namespace nix { #define WORKER_MAGIC_1 0x6e697863 #define WORKER_MAGIC_2 0x6478696f -#define PROTOCOL_VERSION 0x10c +#define PROTOCOL_VERSION 0x10d #define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00) #define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff) @@ -42,6 +42,7 @@ typedef enum { wopQuerySubstitutablePathInfos = 30, wopQueryValidPaths = 31, wopQuerySubstitutablePaths = 32, + wopQueryValidDerivers = 33, } WorkerOp; diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc index 9b3c5bda19..35e5c546e9 100644 --- a/src/nix-daemon/nix-daemon.cc +++ b/src/nix-daemon/nix-daemon.cc @@ -334,6 +334,7 @@ static void performOp(unsigned int clientVersion, case wopQueryReferences: case wopQueryReferrers: + case wopQueryValidDerivers: case wopQueryDerivationOutputs: { Path path = readStorePath(from); startWork(); @@ -342,6 +343,8 @@ static void performOp(unsigned int clientVersion, store->queryReferences(path, paths); else if (op == wopQueryReferrers) store->queryReferrers(path, paths); + else if (op == wopQueryValidDerivers) + paths = store->queryValidDerivers(path); else paths = store->queryDerivationOutputs(path); stopWork(); writeStrings(paths, to); diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index c0da37d251..af4f264a67 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -404,7 +404,8 @@ static void opQuery(Strings opFlags, Strings opArgs) foreach (Strings::iterator, i, opArgs) { PathSet paths = maybeUseOutputs(followLinksToStorePath(*i), useOutput, forceRealise); foreach (PathSet::iterator, j, paths) - computeFSClosure(*store, *j, referrers, true); + computeFSClosure(*store, *j, referrers, true, + settings.gcKeepOutputs, settings.gcKeepDerivations); } Roots roots = store->findRoots(); foreach (Roots::iterator, i, roots)