From 3d55f1eb57c04efc10a093379ea38d6c0aefa588 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 23 Nov 2009 18:16:25 +0000 Subject: [PATCH] * A command `nix-store --query --roots ' to find the garbage collector roots that point (directly or indirectly) to the given paths. --- doc/manual/nix-store.xml | 23 ++++++++++++++++++- src/nix-store/help.txt | 15 ++++++------ src/nix-store/nix-store.cc | 47 +++++++++++++++++++------------------- 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/doc/manual/nix-store.xml b/doc/manual/nix-store.xml index 562a5439a6..566c75bf3e 100644 --- a/doc/manual/nix-store.xml +++ b/doc/manual/nix-store.xml @@ -404,6 +404,7 @@ error: cannot delete path `/nix/store/zq0h41l75vlb4z45kzgjjmsjxvcv1qk7-mesa-6.4' name + @@ -586,12 +587,20 @@ query is applied to the target of the symlink. Prints the SHA-256 hash of the contents of the - store path paths. Since the hash is + store paths paths. Since the hash is stored in the Nix database, this is a fast operation. + + + Prints the garbage collector roots that point, + directly or indirectly, at the store paths + paths. + + + @@ -669,6 +678,18 @@ $ gv graph.ps +Show every garbage collector root that points to a store path +that depends on svn: + + +$ nix-store -q --roots $(which svn) +/nix/var/nix/profiles/default-81-link +/nix/var/nix/profiles/default-82-link +/nix/var/nix/profiles/per-user/eelco/profile-97-link + + + + diff --git a/src/nix-store/help.txt b/src/nix-store/help.txt index c4981168bd..7576e3ef5d 100644 --- a/src/nix-store/help.txt +++ b/src/nix-store/help.txt @@ -24,7 +24,6 @@ Operations: --import: import a path from a Nix archive, and register as valid - --init: initialise the Nix database --verify: verify Nix structures --optimise: optimise the Nix store by hard-linking identical files @@ -34,12 +33,14 @@ Operations: Query flags: --outputs: query the output paths of a Nix derivation (default) - --requisites / -R: print all paths necessary to realise a path - --references: print all paths referenced by the given path - --referrers: print all paths directly refering to the given path - --referrers-closure: print all paths (in)directly refering to the given path - --tree: print a tree showing the dependency graph of the given paths - --graph: print a dot graph rooted at given paths + --requisites / -R: print all paths necessary to realise the path + --references: print all paths referenced by the path + --referrers: print all paths directly refering to the path + --referrers-closure: print all paths (in)directly refering to the path + --tree: print a tree showing the dependency graph of the path + --graph: print a dot graph rooted at given path + --hash: print the SHA-256 hash of the contents of the path + --roots: print the garbage collector roots that point to the path Query switches (not applicable to all queries): diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index b951393092..e08908cd78 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -261,14 +261,13 @@ static void opQuery(Strings opFlags, Strings opArgs) { enum { qOutputs, qRequisites, qReferences, qReferrers , qReferrersClosure, qDeriver, qBinding, qHash - , qTree, qGraph, qResolve } query = qOutputs; + , qTree, qGraph, qResolve, qRoots } query = qOutputs; bool useOutput = false; bool includeOutputs = false; bool forceRealise = false; string bindingName; - for (Strings::iterator i = opFlags.begin(); - i != opFlags.end(); ++i) + foreach (Strings::iterator, i, opFlags) if (*i == "--outputs") query = qOutputs; else if (*i == "--requisites" || *i == "-R") query = qRequisites; else if (*i == "--references") query = qReferences; @@ -286,6 +285,7 @@ static void opQuery(Strings opFlags, Strings opArgs) else if (*i == "--tree") query = qTree; else if (*i == "--graph") query = qGraph; else if (*i == "--resolve") query = qResolve; + else if (*i == "--roots") query = qRoots; else if (*i == "--use-output" || *i == "-u") useOutput = true; else if (*i == "--force-realise" || *i == "-f") forceRealise = true; else if (*i == "--include-outputs") includeOutputs = true; @@ -294,9 +294,7 @@ static void opQuery(Strings opFlags, Strings opArgs) switch (query) { case qOutputs: { - for (Strings::iterator i = opArgs.begin(); - i != opArgs.end(); ++i) - { + foreach (Strings::iterator, i, opArgs) { *i = followLinksToStorePath(*i); if (forceRealise) realisePath(*i); Derivation drv = derivationFromPath(*i); @@ -310,9 +308,7 @@ static void opQuery(Strings opFlags, Strings opArgs) case qReferrers: case qReferrersClosure: { PathSet paths; - for (Strings::iterator i = opArgs.begin(); - i != opArgs.end(); ++i) - { + foreach (Strings::iterator, i, opArgs) { Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise); if (query == qRequisites) storePathRequisites(path, includeOutputs, paths); @@ -328,9 +324,7 @@ static void opQuery(Strings opFlags, Strings opArgs) } case qDeriver: - for (Strings::iterator i = opArgs.begin(); - i != opArgs.end(); ++i) - { + foreach (Strings::iterator, i, opArgs) { Path deriver = store->queryDeriver(followLinksToStorePath(*i)); cout << format("%1%\n") % (deriver == "" ? "unknown-deriver" : deriver); @@ -338,9 +332,7 @@ static void opQuery(Strings opFlags, Strings opArgs) break; case qBinding: - for (Strings::iterator i = opArgs.begin(); - i != opArgs.end(); ++i) - { + foreach (Strings::iterator, i, opArgs) { Path path = useDeriver(followLinksToStorePath(*i)); Derivation drv = derivationFromPath(path); StringPairs::iterator j = drv.env.find(bindingName); @@ -352,9 +344,7 @@ static void opQuery(Strings opFlags, Strings opArgs) break; case qHash: - for (Strings::iterator i = opArgs.begin(); - i != opArgs.end(); ++i) - { + foreach (Strings::iterator, i, opArgs) { Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise); Hash hash = store->queryPathHash(path); assert(hash.type == htSHA256); @@ -364,28 +354,37 @@ static void opQuery(Strings opFlags, Strings opArgs) case qTree: { PathSet done; - for (Strings::iterator i = opArgs.begin(); - i != opArgs.end(); ++i) + foreach (Strings::iterator, i, opArgs) printTree(followLinksToStorePath(*i), "", "", done); break; } case qGraph: { PathSet roots; - for (Strings::iterator i = opArgs.begin(); - i != opArgs.end(); ++i) + foreach (Strings::iterator, i, opArgs) roots.insert(maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise)); printDotGraph(roots); break; } case qResolve: { - for (Strings::iterator i = opArgs.begin(); - i != opArgs.end(); ++i) + foreach (Strings::iterator, i, opArgs) cout << format("%1%\n") % followLinksToStorePath(*i); break; } + case qRoots: { + PathSet referrers; + foreach (Strings::iterator, i, opArgs) + computeFSClosure(maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise), + referrers, true); + Roots roots = store->findRoots(); + foreach (Roots::iterator, i, roots) + if (referrers.find(i->second) != referrers.end()) + cout << format("%1%\n") % i->first; + break; + } + default: abort(); }