From 73c2ae43f08ca35cbb8f86ec7c2efc15ad8686b9 Mon Sep 17 00:00:00 2001 From: Antoine Eiche Date: Sat, 29 Sep 2018 09:42:11 +0200 Subject: [PATCH 1/2] Add --graphml option to the nix-store --query command This prints the references graph of the store paths in the graphML format [1]. The graphML format is supported by several graph tools such as the Python Networkx library or the Apache Thinkerpop project. [1] http://graphml.graphdrawing.org --- doc/manual/command-ref/nix-store.xml | 12 ++++ src/nix-store/graphml.cc | 90 ++++++++++++++++++++++++++++ src/nix-store/graphml.hh | 11 ++++ src/nix-store/nix-store.cc | 14 ++++- 4 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/nix-store/graphml.cc create mode 100644 src/nix-store/graphml.hh diff --git a/doc/manual/command-ref/nix-store.xml b/doc/manual/command-ref/nix-store.xml index c827d85b3..41a04f265 100644 --- a/doc/manual/command-ref/nix-store.xml +++ b/doc/manual/command-ref/nix-store.xml @@ -679,6 +679,18 @@ query is applied to the target of the symlink. + + + Prints the references graph of the store paths + paths in the GraphML file format. + This can be used to visualise dependency graphs. To obtain a + build-time dependency graph, apply this to a store derivation. To + obtain a runtime dependency graph, apply it to an output + path. + + + name name diff --git a/src/nix-store/graphml.cc b/src/nix-store/graphml.cc new file mode 100644 index 000000000..670fbe227 --- /dev/null +++ b/src/nix-store/graphml.cc @@ -0,0 +1,90 @@ +#include "graphml.hh" +#include "util.hh" +#include "store-api.hh" +#include "derivations.hh" + +#include + + +using std::cout; + +namespace nix { + + +static inline const string & xmlQuote(const string & s) +{ + // Luckily, store paths shouldn't contain any character that needs to be + // quoted. + return s; +} + + +static string symbolicName(const string & path) +{ + string p = baseNameOf(path); + return string(p, p.find('-') + 1); +} + + +static string makeEdge(const string & src, const string & dst) +{ + return fmt(" \n", + xmlQuote(src), xmlQuote(dst)); +} + + +static string makeNode(const ValidPathInfo & info) +{ + return fmt( + " \n" + " %2%\n" + " %3%\n" + " %4%\n" + " \n", + info.path, + info.narSize, + symbolicName(info.path), + (isDerivation(info.path) ? "derivation" : "output-path")); +} + + +void printGraphML(ref store, const PathSet & roots) +{ + PathSet workList(roots); + PathSet doneSet; + std::pair ret; + + cout << "\n" + << "\n" + << "" + << "" + << "" + << "\n"; + + while (!workList.empty()) { + Path path = *(workList.begin()); + workList.erase(path); + + ret = doneSet.insert(path); + if (ret.second == false) continue; + + ValidPathInfo info = *(store->queryPathInfo(path)); + cout << makeNode(info); + + for (auto & p : store->queryPathInfo(path)->references) { + if (p != path) { + workList.insert(p); + cout << makeEdge(path, p); + } + } + + } + + cout << "\n"; + cout << "\n"; +} + + +} diff --git a/src/nix-store/graphml.hh b/src/nix-store/graphml.hh new file mode 100644 index 000000000..b78df1e49 --- /dev/null +++ b/src/nix-store/graphml.hh @@ -0,0 +1,11 @@ +#pragma once + +#include "types.hh" + +namespace nix { + +class Store; + +void printGraphML(ref store, const PathSet & roots); + +} diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index fe68f681a..4051fdbe1 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -9,6 +9,7 @@ #include "util.hh" #include "worker-protocol.hh" #include "xmlgraph.hh" +#include "graphml.hh" #include #include @@ -273,7 +274,7 @@ static void opQuery(Strings opFlags, Strings opArgs) enum QueryType { qDefault, qOutputs, qRequisites, qReferences, qReferrers , qReferrersClosure, qDeriver, qBinding, qHash, qSize - , qTree, qGraph, qXml, qResolve, qRoots }; + , qTree, qGraph, qXml, qGraphML, qResolve, qRoots }; QueryType query = qDefault; bool useOutput = false; bool includeOutputs = false; @@ -300,6 +301,7 @@ static void opQuery(Strings opFlags, Strings opArgs) else if (i == "--tree") query = qTree; else if (i == "--graph") query = qGraph; else if (i == "--xml") query = qXml; + else if (i == "--graphml") query = qGraphML; else if (i == "--resolve") query = qResolve; else if (i == "--roots") query = qRoots; else if (i == "--use-output" || i == "-u") useOutput = true; @@ -413,6 +415,16 @@ static void opQuery(Strings opFlags, Strings opArgs) break; } + case qGraphML: { + PathSet roots; + for (auto & i : opArgs) { + PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise); + roots.insert(paths.begin(), paths.end()); + } + printGraphML(ref(store), roots); + break; + } + case qResolve: { for (auto & i : opArgs) cout << format("%1%\n") % store->followLinksToStorePath(i); From d506342aa2b6945899988878b7c58de683cb573a Mon Sep 17 00:00:00 2001 From: Antoine Eiche Date: Sat, 20 Oct 2018 09:48:53 +0200 Subject: [PATCH 2/2] Remove the `--xml` query command option The `--graphml` option can be used instead. --- src/nix-store/nix-store.cc | 14 +------- src/nix-store/xmlgraph.cc | 66 -------------------------------------- src/nix-store/xmlgraph.hh | 11 ------- 3 files changed, 1 insertion(+), 90 deletions(-) delete mode 100644 src/nix-store/xmlgraph.cc delete mode 100644 src/nix-store/xmlgraph.hh diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 4051fdbe1..e245bd643 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -8,7 +8,6 @@ #include "shared.hh" #include "util.hh" #include "worker-protocol.hh" -#include "xmlgraph.hh" #include "graphml.hh" #include @@ -274,7 +273,7 @@ static void opQuery(Strings opFlags, Strings opArgs) enum QueryType { qDefault, qOutputs, qRequisites, qReferences, qReferrers , qReferrersClosure, qDeriver, qBinding, qHash, qSize - , qTree, qGraph, qXml, qGraphML, qResolve, qRoots }; + , qTree, qGraph, qGraphML, qResolve, qRoots }; QueryType query = qDefault; bool useOutput = false; bool includeOutputs = false; @@ -300,7 +299,6 @@ static void opQuery(Strings opFlags, Strings opArgs) else if (i == "--size") query = qSize; else if (i == "--tree") query = qTree; else if (i == "--graph") query = qGraph; - else if (i == "--xml") query = qXml; else if (i == "--graphml") query = qGraphML; else if (i == "--resolve") query = qResolve; else if (i == "--roots") query = qRoots; @@ -405,16 +403,6 @@ static void opQuery(Strings opFlags, Strings opArgs) break; } - case qXml: { - PathSet roots; - for (auto & i : opArgs) { - PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise); - roots.insert(paths.begin(), paths.end()); - } - printXmlGraph(ref(store), roots); - break; - } - case qGraphML: { PathSet roots; for (auto & i : opArgs) { diff --git a/src/nix-store/xmlgraph.cc b/src/nix-store/xmlgraph.cc deleted file mode 100644 index 0f7be7f7a..000000000 --- a/src/nix-store/xmlgraph.cc +++ /dev/null @@ -1,66 +0,0 @@ -#include "xmlgraph.hh" -#include "util.hh" -#include "store-api.hh" - -#include - - -using std::cout; - -namespace nix { - - -static inline const string & xmlQuote(const string & s) -{ - // Luckily, store paths shouldn't contain any character that needs to be - // quoted. - return s; -} - - -static string makeEdge(const string & src, const string & dst) -{ - format f = format(" \n") - % xmlQuote(src) % xmlQuote(dst); - return f.str(); -} - - -static string makeNode(const string & id) -{ - format f = format(" \n") % xmlQuote(id); - return f.str(); -} - - -void printXmlGraph(ref store, const PathSet & roots) -{ - PathSet workList(roots); - PathSet doneSet; - - cout << "\n" - << "\n"; - - while (!workList.empty()) { - Path path = *(workList.begin()); - workList.erase(path); - - if (doneSet.find(path) != doneSet.end()) continue; - doneSet.insert(path); - - cout << makeNode(path); - - for (auto & p : store->queryPathInfo(path)->references) { - if (p != path) { - workList.insert(p); - cout << makeEdge(p, path); - } - } - - } - - cout << "\n"; -} - - -} diff --git a/src/nix-store/xmlgraph.hh b/src/nix-store/xmlgraph.hh deleted file mode 100644 index a6e7d4e28..000000000 --- a/src/nix-store/xmlgraph.hh +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "types.hh" - -namespace nix { - -class Store; - -void printXmlGraph(ref store, const PathSet & roots); - -}