Browse Source

Add 'guix graph'.

* guix/scripts/graph.scm, tests/graph.scm, tests/guix-graph.sh,
  doc/images/coreutils-bag-graph.dot, doc/images/coreutils-graph.dot: New
  files.
* Makefile.am (MODULES): Add guix/scripts/graph.scm.
  (SH_TESTS): Add tests/guix-graph.sh.
  (SCM_TESTS): Add tests/graph.scm.
* doc.am (DOT_FILES, DOT_VECTOR_GRAPHICS): New variables.
  (EXTRA_DIST): Use them.
  (dist_infoimage_DATA): Use $(DOT_FILES).
  (pdf-local, info-local, ps-local): Likewise.
* doc/guix.texi (Packages with Multiple Outputs): Add cross-reference to 'guix
  graph'.
  (Invoking guix gc): Likewise.
  (Invoking guix graph): New section.
gn-latest-20200428
Ludovic Courtès 5 years ago
parent
commit
888569161c
9 changed files with 1017 additions and 8 deletions
  1. +4
    -0
      .gitignore
  2. +3
    -0
      Makefile.am
  3. +16
    -7
      doc.am
  4. +105
    -1
      doc/guix.texi
  5. +213
    -0
      doc/images/coreutils-bag-graph.dot
  6. +23
    -0
      doc/images/coreutils-graph.dot
  7. +426
    -0
      guix/scripts/graph.scm
  8. +193
    -0
      tests/graph.scm
  9. +34
    -0
      tests/guix-graph.sh

+ 4
- 0
.gitignore View File

@@ -126,3 +126,7 @@ GTAGS
/doc/os-config-desktop.texi
/doc/*.1
/etc/guix-daemon.service
/doc/images/bootstrap-graph.pdf
/doc/images/coreutils-bag-graph.png
/doc/images/coreutils-graph.png
/doc/images/coreutils-size-map.eps

+ 3
- 0
Makefile.am View File

@@ -120,6 +120,7 @@ MODULES = \
guix/scripts/publish.scm \
guix/scripts/edit.scm \
guix/scripts/size.scm \
guix/scripts/graph.scm \
guix.scm \
$(GNU_SYSTEM_MODULES)

@@ -209,6 +210,7 @@ SCM_TESTS = \
tests/lint.scm \
tests/publish.scm \
tests/size.scm \
tests/graph.scm \
tests/file-systems.scm \
tests/containers.scm

@@ -238,6 +240,7 @@ SH_TESTS = \
tests/guix-archive.sh \
tests/guix-authenticate.sh \
tests/guix-environment.sh \
tests/guix-graph.sh \
tests/guix-lint.sh

if BUILD_DAEMON


+ 16
- 7
doc.am View File

@@ -18,13 +18,22 @@
# along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.

info_TEXINFOS = doc/guix.texi

DOT_FILES = \
doc/images/bootstrap-graph.dot \
doc/images/coreutils-graph.dot \
doc/images/coreutils-bag-graph.dot

DOT_VECTOR_GRAPHICS = \
$(DOT_FILES:%.dot=%.eps) \
$(DOT_FILES:%.dot=%.pdf)

EXTRA_DIST += \
doc/contributing.texi \
doc/emacs.texi \
doc/fdl-1.3.texi \
doc/images/bootstrap-graph.dot \
doc/images/bootstrap-graph.eps \
doc/images/bootstrap-graph.pdf \
$(DOT_FILES) \
$(DOT_VECTOR_GRAPHICS) \
doc/images/coreutils-size-map.eps \
doc/environment-gdb.scm \
doc/package-hello.scm
@@ -44,7 +53,7 @@ doc/os-config-%.texi: gnu/system/examples/%.tmpl

infoimagedir = $(infodir)/images
dist_infoimage_DATA = \
doc/images/bootstrap-graph.png \
$(DOT_FILES:%.dot=%.png) \
doc/images/coreutils-size-map.png

# Try hard to obtain an image size and aspect that's reasonable for inclusion
@@ -72,9 +81,9 @@ DOT_OPTIONS = \
# We cannot add new dependencies to `doc/guix.pdf' & co. (info "(automake)
# Extending"). Using the `-local' rules is imperfect, because they may be
# triggered after the main rule. Oh, well.
pdf-local: $(top_srcdir)/doc/images/bootstrap-graph.pdf
info-local: $(top_srcdir)/doc/images/bootstrap-graph.png
ps-local: $(top_srcdir)/doc/images/bootstrap-graph.eps \
pdf-local: $(DOT_FILES=%.dot=$(top_srcdir)/%.pdf)
info-local: $(DOT_FILES=%.dot=$(top_srcdir)/%.png)
ps-local: $(DOT_FILES=%.dot=$(top_srcdir)/%.eps) \
$(top_srcdir)/doc/images/coreutils-size-map.eps
dvi-local: ps-local



+ 105
- 1
doc/guix.texi View File

@@ -132,6 +132,7 @@ Utilities
* Invoking guix refresh:: Updating package definitions.
* Invoking guix lint:: Finding errors in package definitions.
* Invoking guix size:: Profiling disk usage.
* Invoking guix graph:: Visualizing the graph of packages.
* Invoking guix environment:: Setting up development environments.
* Invoking guix publish:: Sharing substitutes.

@@ -1604,6 +1605,7 @@ libraries. In this case, we leave the command-line tools in the default
output, whereas the GUIs are in a separate output. This allows users
who do not need the GUIs to save space. The @command{guix size} command
can help find out about such situations (@pxref{Invoking guix size}).
@command{guix graph} can also be helpful (@pxref{Invoking guix graph}).

There are several such multiple-output packages in the GNU distribution.
Other conventional output names include @code{lib} for libraries and
@@ -1690,7 +1692,8 @@ of these, recursively. In other words, the returned list is the
@dfn{transitive closure} of the store files.

@xref{Invoking guix size}, for a tool to profile the size of an
element's closure.
element's closure. @xref{Invoking guix graph}, for a tool to visualize
the graph of references.

@end table

@@ -3434,6 +3437,7 @@ programming interface of Guix in a convenient way.
* Invoking guix refresh:: Updating package definitions.
* Invoking guix lint:: Finding errors in package definitions.
* Invoking guix size:: Profiling disk usage.
* Invoking guix graph:: Visualizing the graph of packages.
* Invoking guix environment:: Setting up development environments.
* Invoking guix publish:: Sharing substitutes.
@end menu
@@ -4263,6 +4267,106 @@ Consider packages for @var{system}---e.g., @code{x86_64-linux}.

@end table

@node Invoking guix graph
@section Invoking @command{guix graph}

@cindex DAG
Packages and their dependencies form a @dfn{graph}, specifically a
directed acyclic graph (DAG). It can quickly become difficult to have a
mental model of the package DAG, so the @command{guix graph} command is
here to provide a visual representation of the DAG. @command{guix
graph} emits a DAG representation in the input format of
@uref{http://www.graphviz.org/, Graphviz}, so its output can be passed
directly to Graphviz's @command{dot} command, for instance. The general
syntax is:

@example
guix graph @var{options} @var{package}@dots{}
@end example

For example, the following command generates a PDF file representing the
package DAG for the GNU@tie{}Core Utilities, showing its build-time
dependencies:

@example
guix graph coreutils | dot -Tpdf > dag.pdf
@end example

The output looks like this:

@image{images/coreutils-graph,2in,,Dependency graph of the GNU Coreutils}

Nice little graph, no?

But there's more than one graph! The one above is concise: it's the
graph of package objects, omitting implicit inputs such as GCC, libc,
grep, etc. It's often useful to have such a concise graph, but
sometimes you want to see more details. @command{guix graph} supports
several types of graphs, allowing you to choose the level of details:

@table @code
@item package
This is the default type, the one we used above. It shows the DAG of
package objects, excluding implicit dependencies. It is concise, but
filters out many details.

@item bag-emerged
This is the package DAG, @emph{including} implicit inputs.

For instance, the following command:

@example
guix graph --type=bag-emerged coreutils | dot -Tpdf > dag.pdf
@end example

... yields this bigger graph:

@image{images/coreutils-bag-graph,,5in,Detailed dependency graph of the GNU Coreutils}

At the bottom of the graph, we see all the implicit inputs of
@var{gnu-build-system} (@pxref{Build Systems, @code{gnu-build-system}}).

Now, note that the dependencies of those implicit inputs---that is, the
@dfn{bootstrap dependencies} (@pxref{Bootstrapping})---are not shown
here, for conciseness.

@item bag
Similar to @code{bag-emerged}, but this time including all the bootstrap
dependencies.

@item derivations
This is the most detailed representation: It shows the DAG of
derivations (@pxref{Derivations}) and plain store items. Compared to
the above representation, many additional nodes are visible, including
builds scripts, patches, Guile modules, etc.

@end table

All the above types correspond to @emph{build-time dependencies}. The
following graph type represents the @emph{run-time dependencies}:

@table @code
@item references
This is the graph of @dfn{references} of a package output, as returned
by @command{guix gc --references} (@pxref{Invoking guix gc}).

If the given package output is not available in the store, @command{guix
graph} attempts to obtain dependency information from substitutes.
@end table

The available options are the following:

@table @option
@item --type=@var{type}
@itemx -t @var{type}
Produce a graph output of @var{type}, where @var{type} must be one of
the values listed above.

@item --list-types
List the supported graph types.
@end table


@node Invoking guix environment
@section Invoking @command{guix environment}



+ 213
- 0
doc/images/coreutils-bag-graph.dot View File

@@ -0,0 +1,213 @@
digraph "Guix bag-emerged" {
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" [label = "coreutils-8.24", shape = box, fontname = Helvetica];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/7176h825gaw745sdkwkgh7jip9w26w8m-tar-1.28.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/86bbbaav5ilnr63cpihi9h03ila7cr1k-gzip-1.6.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/ab82abh8l2dr56j0s9z68v6i872dic45-bzip2-1.0.6.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/x9dji1ms9cj9vbl15bksci7w76zcwvkj-xz-5.0.4.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/l8712bh52742kzav8w11n97l0vzim838-file-5.22.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/52b3d4q4nyv0i0n1phnwms3xan38q8is-diffutils-3.3.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/vaksjdasfzhbj6jzc46fdglwy75y8ggs-patch-2.7.5.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/4dikg9vw3fnhvjx86wq5jlpaw58nfmbv-sed-4.2.2.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/6q81294lvwzwqwj3s5flhl2fap5ac1qf-findutils-4.4.2.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/0qzl2vj3fwz03m6a8v7yypqhb58b4408-gawk-4.1.3.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/0w9md4s7vasgi5jy1xvxnsg4a3s134a9-grep-2.21.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/ldxarpgn1f4xbghbw0vqibdbi5cv3snl-coreutils-8.24.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/j7h01h99vrcs8wr0xx997wl2ijqhrz9b-make-4.1.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/8ghhz8yi3m9d4s07r443106g4pffd8q2-bash-4.3.39.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/sx1s4j6p0sm66znaaizb9a4cfwy109zy-ld-wrapper-0.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/gj0jr0lz5siyn0ifq1vnksvfdcmd1gw7-binutils-2.25.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/a74b2jvm3vv405a9wkd0c2v47s17alyi-gcc-4.9.3.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/0b68fcwgd01v2mji5pyda5ag9amg7d10-glibc-2.21.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/phkvp3cp8yqfqiv7i35j64lv671iv00x-glibc-utf8-locales-2.21.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" [color = red];
"/gnu/store/rgbnfjyvx2i44x2iwi62jsk76rg5vfr0-coreutils-8.24.drv" -> "/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" [label = "perl-5.16.1", shape = box, fontname = Helvetica];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/7176h825gaw745sdkwkgh7jip9w26w8m-tar-1.28.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/86bbbaav5ilnr63cpihi9h03ila7cr1k-gzip-1.6.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/ab82abh8l2dr56j0s9z68v6i872dic45-bzip2-1.0.6.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/x9dji1ms9cj9vbl15bksci7w76zcwvkj-xz-5.0.4.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/l8712bh52742kzav8w11n97l0vzim838-file-5.22.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/52b3d4q4nyv0i0n1phnwms3xan38q8is-diffutils-3.3.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/vaksjdasfzhbj6jzc46fdglwy75y8ggs-patch-2.7.5.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/4dikg9vw3fnhvjx86wq5jlpaw58nfmbv-sed-4.2.2.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/6q81294lvwzwqwj3s5flhl2fap5ac1qf-findutils-4.4.2.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/0qzl2vj3fwz03m6a8v7yypqhb58b4408-gawk-4.1.3.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/0w9md4s7vasgi5jy1xvxnsg4a3s134a9-grep-2.21.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/ldxarpgn1f4xbghbw0vqibdbi5cv3snl-coreutils-8.24.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/j7h01h99vrcs8wr0xx997wl2ijqhrz9b-make-4.1.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/8ghhz8yi3m9d4s07r443106g4pffd8q2-bash-4.3.39.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/sx1s4j6p0sm66znaaizb9a4cfwy109zy-ld-wrapper-0.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/gj0jr0lz5siyn0ifq1vnksvfdcmd1gw7-binutils-2.25.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/a74b2jvm3vv405a9wkd0c2v47s17alyi-gcc-4.9.3.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/0b68fcwgd01v2mji5pyda5ag9amg7d10-glibc-2.21.drv" [color = red];
"/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" -> "/gnu/store/phkvp3cp8yqfqiv7i35j64lv671iv00x-glibc-utf8-locales-2.21.drv" [color = red];
"/gnu/store/7176h825gaw745sdkwkgh7jip9w26w8m-tar-1.28.drv" [label = "tar-1.28", shape = box, fontname = Helvetica];
"/gnu/store/86bbbaav5ilnr63cpihi9h03ila7cr1k-gzip-1.6.drv" [label = "gzip-1.6", shape = box, fontname = Helvetica];
"/gnu/store/ab82abh8l2dr56j0s9z68v6i872dic45-bzip2-1.0.6.drv" [label = "bzip2-1.0.6", shape = box, fontname = Helvetica];
"/gnu/store/x9dji1ms9cj9vbl15bksci7w76zcwvkj-xz-5.0.4.drv" [label = "xz-5.0.4", shape = box, fontname = Helvetica];
"/gnu/store/l8712bh52742kzav8w11n97l0vzim838-file-5.22.drv" [label = "file-5.22", shape = box, fontname = Helvetica];
"/gnu/store/52b3d4q4nyv0i0n1phnwms3xan38q8is-diffutils-3.3.drv" [label = "diffutils-3.3", shape = box, fontname = Helvetica];
"/gnu/store/vaksjdasfzhbj6jzc46fdglwy75y8ggs-patch-2.7.5.drv" [label = "patch-2.7.5", shape = box, fontname = Helvetica];
"/gnu/store/4dikg9vw3fnhvjx86wq5jlpaw58nfmbv-sed-4.2.2.drv" [label = "sed-4.2.2", shape = box, fontname = Helvetica];
"/gnu/store/6q81294lvwzwqwj3s5flhl2fap5ac1qf-findutils-4.4.2.drv" [label = "findutils-4.4.2", shape = box, fontname = Helvetica];
"/gnu/store/0qzl2vj3fwz03m6a8v7yypqhb58b4408-gawk-4.1.3.drv" [label = "gawk-4.1.3", shape = box, fontname = Helvetica];
"/gnu/store/0w9md4s7vasgi5jy1xvxnsg4a3s134a9-grep-2.21.drv" [label = "grep-2.21", shape = box, fontname = Helvetica];
"/gnu/store/ldxarpgn1f4xbghbw0vqibdbi5cv3snl-coreutils-8.24.drv" [label = "coreutils-8.24", shape = box, fontname = Helvetica];
"/gnu/store/j7h01h99vrcs8wr0xx997wl2ijqhrz9b-make-4.1.drv" [label = "make-4.1", shape = box, fontname = Helvetica];
"/gnu/store/8ghhz8yi3m9d4s07r443106g4pffd8q2-bash-4.3.39.drv" [label = "bash-4.3.39", shape = box, fontname = Helvetica];
"/gnu/store/sx1s4j6p0sm66znaaizb9a4cfwy109zy-ld-wrapper-0.drv" [label = "ld-wrapper-0", shape = box, fontname = Helvetica];
"/gnu/store/gj0jr0lz5siyn0ifq1vnksvfdcmd1gw7-binutils-2.25.drv" [label = "binutils-2.25", shape = box, fontname = Helvetica];
"/gnu/store/a74b2jvm3vv405a9wkd0c2v47s17alyi-gcc-4.9.3.drv" [label = "gcc-4.9.3", shape = box, fontname = Helvetica];
"/gnu/store/0b68fcwgd01v2mji5pyda5ag9amg7d10-glibc-2.21.drv" [label = "glibc-2.21", shape = box, fontname = Helvetica];
"/gnu/store/phkvp3cp8yqfqiv7i35j64lv671iv00x-glibc-utf8-locales-2.21.drv" [label = "glibc-utf8-locales-2.21", shape = box, fontname = Helvetica];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" [label = "acl-2.2.52", shape = box, fontname = Helvetica];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/7176h825gaw745sdkwkgh7jip9w26w8m-tar-1.28.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/86bbbaav5ilnr63cpihi9h03ila7cr1k-gzip-1.6.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/ab82abh8l2dr56j0s9z68v6i872dic45-bzip2-1.0.6.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/x9dji1ms9cj9vbl15bksci7w76zcwvkj-xz-5.0.4.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/l8712bh52742kzav8w11n97l0vzim838-file-5.22.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/52b3d4q4nyv0i0n1phnwms3xan38q8is-diffutils-3.3.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/vaksjdasfzhbj6jzc46fdglwy75y8ggs-patch-2.7.5.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/4dikg9vw3fnhvjx86wq5jlpaw58nfmbv-sed-4.2.2.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/6q81294lvwzwqwj3s5flhl2fap5ac1qf-findutils-4.4.2.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/0qzl2vj3fwz03m6a8v7yypqhb58b4408-gawk-4.1.3.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/0w9md4s7vasgi5jy1xvxnsg4a3s134a9-grep-2.21.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/ldxarpgn1f4xbghbw0vqibdbi5cv3snl-coreutils-8.24.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/j7h01h99vrcs8wr0xx997wl2ijqhrz9b-make-4.1.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/8ghhz8yi3m9d4s07r443106g4pffd8q2-bash-4.3.39.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/sx1s4j6p0sm66znaaizb9a4cfwy109zy-ld-wrapper-0.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/gj0jr0lz5siyn0ifq1vnksvfdcmd1gw7-binutils-2.25.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/a74b2jvm3vv405a9wkd0c2v47s17alyi-gcc-4.9.3.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/0b68fcwgd01v2mji5pyda5ag9amg7d10-glibc-2.21.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/phkvp3cp8yqfqiv7i35j64lv671iv00x-glibc-utf8-locales-2.21.drv" [color = red];
"/gnu/store/bx5ksjc77qy38p2y8xr5cph59kkh5aqc-acl-2.2.52.drv" -> "/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" [label = "gettext-0.19.5", shape = box, fontname = Helvetica];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/7176h825gaw745sdkwkgh7jip9w26w8m-tar-1.28.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/86bbbaav5ilnr63cpihi9h03ila7cr1k-gzip-1.6.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/ab82abh8l2dr56j0s9z68v6i872dic45-bzip2-1.0.6.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/x9dji1ms9cj9vbl15bksci7w76zcwvkj-xz-5.0.4.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/l8712bh52742kzav8w11n97l0vzim838-file-5.22.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/52b3d4q4nyv0i0n1phnwms3xan38q8is-diffutils-3.3.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/vaksjdasfzhbj6jzc46fdglwy75y8ggs-patch-2.7.5.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/4dikg9vw3fnhvjx86wq5jlpaw58nfmbv-sed-4.2.2.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/6q81294lvwzwqwj3s5flhl2fap5ac1qf-findutils-4.4.2.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/0qzl2vj3fwz03m6a8v7yypqhb58b4408-gawk-4.1.3.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/0w9md4s7vasgi5jy1xvxnsg4a3s134a9-grep-2.21.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/ldxarpgn1f4xbghbw0vqibdbi5cv3snl-coreutils-8.24.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/j7h01h99vrcs8wr0xx997wl2ijqhrz9b-make-4.1.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/8ghhz8yi3m9d4s07r443106g4pffd8q2-bash-4.3.39.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/sx1s4j6p0sm66znaaizb9a4cfwy109zy-ld-wrapper-0.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/gj0jr0lz5siyn0ifq1vnksvfdcmd1gw7-binutils-2.25.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/a74b2jvm3vv405a9wkd0c2v47s17alyi-gcc-4.9.3.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/0b68fcwgd01v2mji5pyda5ag9amg7d10-glibc-2.21.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/phkvp3cp8yqfqiv7i35j64lv671iv00x-glibc-utf8-locales-2.21.drv" [color = red];
"/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" -> "/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" [label = "expat-2.1.0", shape = box, fontname = Helvetica];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/7176h825gaw745sdkwkgh7jip9w26w8m-tar-1.28.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/86bbbaav5ilnr63cpihi9h03ila7cr1k-gzip-1.6.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/ab82abh8l2dr56j0s9z68v6i872dic45-bzip2-1.0.6.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/x9dji1ms9cj9vbl15bksci7w76zcwvkj-xz-5.0.4.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/l8712bh52742kzav8w11n97l0vzim838-file-5.22.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/52b3d4q4nyv0i0n1phnwms3xan38q8is-diffutils-3.3.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/vaksjdasfzhbj6jzc46fdglwy75y8ggs-patch-2.7.5.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/4dikg9vw3fnhvjx86wq5jlpaw58nfmbv-sed-4.2.2.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/6q81294lvwzwqwj3s5flhl2fap5ac1qf-findutils-4.4.2.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/0qzl2vj3fwz03m6a8v7yypqhb58b4408-gawk-4.1.3.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/0w9md4s7vasgi5jy1xvxnsg4a3s134a9-grep-2.21.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/ldxarpgn1f4xbghbw0vqibdbi5cv3snl-coreutils-8.24.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/j7h01h99vrcs8wr0xx997wl2ijqhrz9b-make-4.1.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/8ghhz8yi3m9d4s07r443106g4pffd8q2-bash-4.3.39.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/sx1s4j6p0sm66znaaizb9a4cfwy109zy-ld-wrapper-0.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/gj0jr0lz5siyn0ifq1vnksvfdcmd1gw7-binutils-2.25.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/a74b2jvm3vv405a9wkd0c2v47s17alyi-gcc-4.9.3.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/0b68fcwgd01v2mji5pyda5ag9amg7d10-glibc-2.21.drv" [color = red];
"/gnu/store/zv0yx4506q6k13vkl8k7pqnfirnlqplg-expat-2.1.0.drv" -> "/gnu/store/phkvp3cp8yqfqiv7i35j64lv671iv00x-glibc-utf8-locales-2.21.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" [label = "sed-4.2.2", shape = box, fontname = Helvetica];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/7176h825gaw745sdkwkgh7jip9w26w8m-tar-1.28.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/86bbbaav5ilnr63cpihi9h03ila7cr1k-gzip-1.6.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/ab82abh8l2dr56j0s9z68v6i872dic45-bzip2-1.0.6.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/x9dji1ms9cj9vbl15bksci7w76zcwvkj-xz-5.0.4.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/l8712bh52742kzav8w11n97l0vzim838-file-5.22.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/52b3d4q4nyv0i0n1phnwms3xan38q8is-diffutils-3.3.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/vaksjdasfzhbj6jzc46fdglwy75y8ggs-patch-2.7.5.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/4dikg9vw3fnhvjx86wq5jlpaw58nfmbv-sed-4.2.2.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/6q81294lvwzwqwj3s5flhl2fap5ac1qf-findutils-4.4.2.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/0qzl2vj3fwz03m6a8v7yypqhb58b4408-gawk-4.1.3.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/0w9md4s7vasgi5jy1xvxnsg4a3s134a9-grep-2.21.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/ldxarpgn1f4xbghbw0vqibdbi5cv3snl-coreutils-8.24.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/j7h01h99vrcs8wr0xx997wl2ijqhrz9b-make-4.1.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/8ghhz8yi3m9d4s07r443106g4pffd8q2-bash-4.3.39.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/sx1s4j6p0sm66znaaizb9a4cfwy109zy-ld-wrapper-0.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/gj0jr0lz5siyn0ifq1vnksvfdcmd1gw7-binutils-2.25.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/a74b2jvm3vv405a9wkd0c2v47s17alyi-gcc-4.9.3.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/0b68fcwgd01v2mji5pyda5ag9amg7d10-glibc-2.21.drv" [color = red];
"/gnu/store/fi3hvhhi6jfm7qmlxayrd551d3wxp115-sed-4.2.2.drv" -> "/gnu/store/phkvp3cp8yqfqiv7i35j64lv671iv00x-glibc-utf8-locales-2.21.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" [label = "attr-2.4.46", shape = box, fontname = Helvetica];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/mw5q1c5flk83xwj7yvqv0mb3hi6xb316-gettext-0.19.5.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/7176h825gaw745sdkwkgh7jip9w26w8m-tar-1.28.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/86bbbaav5ilnr63cpihi9h03ila7cr1k-gzip-1.6.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/ab82abh8l2dr56j0s9z68v6i872dic45-bzip2-1.0.6.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/x9dji1ms9cj9vbl15bksci7w76zcwvkj-xz-5.0.4.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/l8712bh52742kzav8w11n97l0vzim838-file-5.22.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/52b3d4q4nyv0i0n1phnwms3xan38q8is-diffutils-3.3.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/vaksjdasfzhbj6jzc46fdglwy75y8ggs-patch-2.7.5.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/4dikg9vw3fnhvjx86wq5jlpaw58nfmbv-sed-4.2.2.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/6q81294lvwzwqwj3s5flhl2fap5ac1qf-findutils-4.4.2.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/0qzl2vj3fwz03m6a8v7yypqhb58b4408-gawk-4.1.3.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/0w9md4s7vasgi5jy1xvxnsg4a3s134a9-grep-2.21.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/ldxarpgn1f4xbghbw0vqibdbi5cv3snl-coreutils-8.24.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/j7h01h99vrcs8wr0xx997wl2ijqhrz9b-make-4.1.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/8ghhz8yi3m9d4s07r443106g4pffd8q2-bash-4.3.39.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/sx1s4j6p0sm66znaaizb9a4cfwy109zy-ld-wrapper-0.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/gj0jr0lz5siyn0ifq1vnksvfdcmd1gw7-binutils-2.25.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/a74b2jvm3vv405a9wkd0c2v47s17alyi-gcc-4.9.3.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/0b68fcwgd01v2mji5pyda5ag9amg7d10-glibc-2.21.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/phkvp3cp8yqfqiv7i35j64lv671iv00x-glibc-utf8-locales-2.21.drv" [color = red];
"/gnu/store/ww221j42552c05xrrbjjz9av7w7r9s5x-attr-2.4.46.drv" -> "/gnu/store/1vx9x5ml5q6irf4pnjrlfgmhcislmg1n-perl-5.16.1.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" [label = "gmp-6.0.0a", shape = box, fontname = Helvetica];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/7176h825gaw745sdkwkgh7jip9w26w8m-tar-1.28.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/86bbbaav5ilnr63cpihi9h03ila7cr1k-gzip-1.6.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/ab82abh8l2dr56j0s9z68v6i872dic45-bzip2-1.0.6.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/x9dji1ms9cj9vbl15bksci7w76zcwvkj-xz-5.0.4.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/l8712bh52742kzav8w11n97l0vzim838-file-5.22.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/52b3d4q4nyv0i0n1phnwms3xan38q8is-diffutils-3.3.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/vaksjdasfzhbj6jzc46fdglwy75y8ggs-patch-2.7.5.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/4dikg9vw3fnhvjx86wq5jlpaw58nfmbv-sed-4.2.2.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/6q81294lvwzwqwj3s5flhl2fap5ac1qf-findutils-4.4.2.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/0qzl2vj3fwz03m6a8v7yypqhb58b4408-gawk-4.1.3.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/0w9md4s7vasgi5jy1xvxnsg4a3s134a9-grep-2.21.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/ldxarpgn1f4xbghbw0vqibdbi5cv3snl-coreutils-8.24.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/j7h01h99vrcs8wr0xx997wl2ijqhrz9b-make-4.1.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/8ghhz8yi3m9d4s07r443106g4pffd8q2-bash-4.3.39.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/sx1s4j6p0sm66znaaizb9a4cfwy109zy-ld-wrapper-0.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/gj0jr0lz5siyn0ifq1vnksvfdcmd1gw7-binutils-2.25.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/a74b2jvm3vv405a9wkd0c2v47s17alyi-gcc-4.9.3.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/0b68fcwgd01v2mji5pyda5ag9amg7d10-glibc-2.21.drv" [color = red];
"/gnu/store/1jzdjkign6jjsanmfhzs45kngi9gw5k8-gmp-6.0.0a.drv" -> "/gnu/store/phkvp3cp8yqfqiv7i35j64lv671iv00x-glibc-utf8-locales-2.21.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" [label = "m4-1.4.17", shape = box, fontname = Helvetica];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/7176h825gaw745sdkwkgh7jip9w26w8m-tar-1.28.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/86bbbaav5ilnr63cpihi9h03ila7cr1k-gzip-1.6.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/ab82abh8l2dr56j0s9z68v6i872dic45-bzip2-1.0.6.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/x9dji1ms9cj9vbl15bksci7w76zcwvkj-xz-5.0.4.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/l8712bh52742kzav8w11n97l0vzim838-file-5.22.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/52b3d4q4nyv0i0n1phnwms3xan38q8is-diffutils-3.3.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/vaksjdasfzhbj6jzc46fdglwy75y8ggs-patch-2.7.5.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/4dikg9vw3fnhvjx86wq5jlpaw58nfmbv-sed-4.2.2.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/6q81294lvwzwqwj3s5flhl2fap5ac1qf-findutils-4.4.2.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/0qzl2vj3fwz03m6a8v7yypqhb58b4408-gawk-4.1.3.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/0w9md4s7vasgi5jy1xvxnsg4a3s134a9-grep-2.21.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/ldxarpgn1f4xbghbw0vqibdbi5cv3snl-coreutils-8.24.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/j7h01h99vrcs8wr0xx997wl2ijqhrz9b-make-4.1.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/8ghhz8yi3m9d4s07r443106g4pffd8q2-bash-4.3.39.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/sx1s4j6p0sm66znaaizb9a4cfwy109zy-ld-wrapper-0.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/gj0jr0lz5siyn0ifq1vnksvfdcmd1gw7-binutils-2.25.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/a74b2jvm3vv405a9wkd0c2v47s17alyi-gcc-4.9.3.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/0b68fcwgd01v2mji5pyda5ag9amg7d10-glibc-2.21.drv" [color = red];
"/gnu/store/zsi7a1v45zq9qc7fzzw463q907mwqwwr-m4-1.4.17.drv" -> "/gnu/store/phkvp3cp8yqfqiv7i35j64lv671iv00x-glibc-utf8-locales-2.21.drv" [color = red];

}

+ 23
- 0
doc/images/coreutils-graph.dot View File

@@ -0,0 +1,23 @@
digraph "Guix package" {
"50639808" [label = "coreutils-8.24", shape = box, fontname = Helvetica];
"50639808" -> "31984640" [color = red];
"50639808" -> "50641344" [color = red];
"50639808" -> "38428672" [color = red];
"31984640" [label = "perl-5.16.1", shape = box, fontname = Helvetica];
"50641344" [label = "acl-2.2.52", shape = box, fontname = Helvetica];
"50641344" -> "50641728" [color = red];
"50641344" -> "31984640" [color = red];
"50641344" -> "50640768" [color = red];
"50641344" -> "50641536" [color = red];
"50641728" [label = "gettext-0.19.5", shape = box, fontname = Helvetica];
"50641728" -> "50530368" [color = red];
"50530368" [label = "expat-2.1.0", shape = box, fontname = Helvetica];
"50640768" [label = "sed-4.2.2", shape = box, fontname = Helvetica];
"50641536" [label = "attr-2.4.46", shape = box, fontname = Helvetica];
"50641536" -> "50641728" [color = red];
"50641536" -> "31984640" [color = red];
"38428672" [label = "gmp-6.0.0a", shape = box, fontname = Helvetica];
"38428672" -> "38431168" [color = red];
"38431168" [label = "m4-1.4.17", shape = box, fontname = Helvetica];

}

+ 426
- 0
guix/scripts/graph.scm View File

@@ -0,0 +1,426 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.

(define-module (guix scripts graph)
#:use-module (guix ui)
#:use-module (guix utils)
#:use-module (guix packages)
#:use-module (guix monads)
#:use-module (guix store)
#:use-module (guix gexp)
#:use-module (guix derivations)
#:use-module ((guix build-system gnu) #:select (standard-packages))
#:use-module (gnu packages)
#:use-module (guix sets)
#:use-module (guix records)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-34)
#:use-module (srfi srfi-37)
#:use-module (ice-9 match)
#:use-module (web uri)
#:export (%package-node-type
%bag-node-type
%bag-emerged-node-type
%derivation-node-type
%reference-node-type

%graphviz-backend
graph-backend?
graph-backend

export-graph

guix-graph))

;;;
;;; Node types.
;;;

(define-record-type* <node-type> node-type make-node-type
node-type?
(identifier node-type-identifier) ;node -> M identifier
(label node-type-label) ;node -> string
(edges node-type-edges) ;node -> M list of nodes
(convert node-type-convert ;package -> M list of nodes
(default (lift1 list %store-monad)))
(name node-type-name) ;string
(description node-type-description)) ;string

;;;
;;; Package DAG.
;;;

(define (uri->file-name uri)
"Return the 'base name' of URI or URI itself, where URI is a string."
(let ((path (and=> (string->uri uri) uri-path)))
(if path
(basename path)
uri)))

(define (node-full-name thing)
"Return a human-readable name to denote THING, a package, origin, or file
name."
(cond ((package? thing)
(package-full-name thing))
((origin? thing)
(or (origin-file-name thing)
(match (origin-uri thing)
((head . tail)
(uri->file-name head))
((? string? uri)
(uri->file-name uri)))))
((string? thing) ;file name
(or (basename thing)
(error "basename" thing)))
(else
(number->string (object-address thing) 16))))

(define (package-node-edges package)
"Return the list of dependencies of PACKAGE."
(match (package-direct-inputs package)
(((labels packages . outputs) ...)
;; Filter out origins and other non-package dependencies.
(filter package? packages))))

(define %package-node-type
;; Type for the traversal of package nodes.
(node-type
(name "package")
(description "the DAG of packages, excluding implicit inputs")

;; We use package addresses as unique identifiers. This generally works
;; well, but for generated package objects, we could end up with two
;; packages that are not 'eq?', yet map to the same derivation (XXX).
(identifier (lift1 object-address %store-monad))
(label node-full-name)
(edges (lift1 package-node-edges %store-monad))))

;;;
;;; Package DAG using bags.
;;;

(define (bag-node-identifier thing)
"Return a unique identifier for THING, which may be a package, origin, or a
file name."
;; If THING is a file name (a string), we just return it; if it's a package
;; or origin, we return its address. That gives us the object graph, but
;; that may differ from the derivation graph (for instance,
;; 'package-with-bootstrap-guile' generates fresh package objects, and
;; several packages that are not 'eq?' may actually map to the same
;; derivation.) Thus, we lower THING and use its derivation file name as a
;; unique identifier.
(with-monad %store-monad
(if (string? thing)
(return thing)
(mlet %store-monad ((low (lower-object thing)))
(return (if (derivation? low)
(derivation-file-name low)
low))))))

(define (bag-node-edges thing)
"Return the list of dependencies of THING, a package or origin, etc."
(if (package? thing)
(match (bag-direct-inputs (package->bag thing))
(((labels things . outputs) ...)
(filter-map (match-lambda
((? package? p) p)
;; XXX: Here we choose to filter out origins, files,
;; etc. Replace "#f" with "x" to reinstate them.
(x #f))
things)))
'()))

(define %bag-node-type
;; Type for the traversal of package nodes via the "bag" representation,
;; which includes implicit inputs.
(node-type
(name "bag")
(description "the DAG of packages, including implicit inputs")
(identifier bag-node-identifier)
(label node-full-name)
(edges (lift1 bag-node-edges %store-monad))))

(define standard-package-set
(memoize
(lambda ()
"Return the set of standard packages provided by GNU-BUILD-SYSTEM."
(match (standard-packages)
(((labels packages . output) ...)
(list->setq packages))))))

(define (bag-node-edges-sans-bootstrap thing)
"Like 'bag-node-edges', but pretend that the standard packages of
GNU-BUILD-SYSTEM have zero dependencies."
(if (set-contains? (standard-package-set) thing)
'()
(bag-node-edges thing)))

(define %bag-emerged-node-type
;; Like %BAG-NODE-TYPE, but without the bootstrap subset of the DAG.
(node-type
(name "bag-emerged")
(description "same as 'bag', but without the bootstrap nodes")
(identifier bag-node-identifier)
(label node-full-name)
(edges (lift1 bag-node-edges-sans-bootstrap %store-monad))))

;;;
;;; Derivation DAG.
;;;

(define (file->derivation file)
"Read the derivation from FILE and return it."
(call-with-input-file file read-derivation))

(define (derivation-dependencies obj)
"Return the <derivation> objects and store items corresponding to the
dependencies of OBJ, a <derivation> or store item."
(if (derivation? obj)
(append (map (compose file->derivation derivation-input-path)
(derivation-inputs obj))
(derivation-sources obj))
'()))

(define (derivation-node-identifier node)
"Return a unique identifier for NODE, which may be either a <derivation> or
a plain store file."
(if (derivation? node)
(derivation-file-name node)
node))

(define (derivation-node-label node)
"Return a label for NODE, a <derivation> object or plain store item."
(store-path-package-name (match node
((? derivation? drv)
(derivation-file-name drv))
((? string? file)
file))))

(define %derivation-node-type
;; DAG of derivations. Very accurate, very detailed, but usually too much
;; detailed.
(node-type
(name "derivation")
(description "the DAG of derivations")
(convert (lambda (package)
(with-monad %store-monad
(>>= (package->derivation package)
(lift1 list %store-monad)))))
(identifier (lift1 derivation-node-identifier %store-monad))
(label derivation-node-label)
(edges (lift1 derivation-dependencies %store-monad))))

;;;
;;; DAG of residual references (aka. run-time dependencies).
;;;

(define (references* item)
"Return as a monadic value the references of ITEM, based either on the
information available in the local store or using information about
substitutes."
(lambda (store)
(guard (c ((nix-protocol-error? c)
(match (substitutable-path-info store (list item))
((info)
(values (substitutable-references info) store))
(()
(leave (_ "references for '~a' are not known~%")
item)))))
(values (references store item) store))))

(define %reference-node-type
(node-type
(name "references")
(description "the DAG of run-time dependencies (store references)")
(convert (lambda (package)
;; Return the output file names of PACKAGE.
(mlet %store-monad ((drv (package->derivation package)))
(return (match (derivation->output-paths drv)
(((_ . file-names) ...)
file-names))))))
(identifier (lift1 identity %store-monad))
(label store-path-package-name)
(edges references*)))

;;;
;;; List of node types.
;;;

(define %node-types
;; List of all the node types.
(list %package-node-type
%bag-node-type
%bag-emerged-node-type
%derivation-node-type
%reference-node-type))

(define (lookup-node-type name)
"Return the node type called NAME. Raise an error if it is not found."
(or (find (lambda (type)
(string=? (node-type-name type) name))
%node-types)
(leave (_ "~a: unknown node type~%") name)))

(define (list-node-types)
"Print the available node types along with their synopsis."
(display (_ "The available node types are:\n"))
(newline)
(for-each (lambda (type)
(format #t " - ~a: ~a~%"
(node-type-name type)
(node-type-description type)))
%node-types))

;;;
;;; Graphviz export.
;;;

(define-record-type <graph-backend>
(graph-backend prologue epilogue node edge)
graph-backend?
(prologue graph-backend-prologue)
(epilogue graph-backend-epilogue)
(node graph-backend-node)
(edge graph-backend-edge))

(define (emit-prologue name port)
(format port "digraph \"Guix ~a\" {\n"
name))
(define (emit-epilogue port)
(display "\n}\n" port))
(define (emit-node id label port)
(format port " \"~a\" [label = \"~a\", shape = box, fontname = Helvetica];~%"
id label))
(define (emit-edge id1 id2 port)
(format port " \"~a\" -> \"~a\" [color = red];~%"
id1 id2))

(define %graphviz-backend
(graph-backend emit-prologue emit-epilogue
emit-node emit-edge))

(define* (export-graph sinks port
#:key
(node-type %package-node-type)
(backend %graphviz-backend))
"Write to PORT the representation of the DAG with the given SINKS, using the
given BACKEND. Use NODE-TYPE to traverse the DAG."
(match backend
(($ <graph-backend> emit-prologue emit-epilogue emit-node emit-edge)
(emit-prologue (node-type-name node-type) port)

(match node-type
(($ <node-type> node-identifier node-label node-edges)
(let loop ((nodes sinks)
(visited (set)))
(match nodes
(()
(with-monad %store-monad
(emit-epilogue port)
(store-return #t)))
((head . tail)
(mlet %store-monad ((id (node-identifier head)))
(if (set-contains? visited id)
(loop tail visited)
(mlet* %store-monad ((dependencies (node-edges head))
(ids (mapm %store-monad
node-identifier
dependencies)))
(emit-node id (node-label head) port)
(for-each (lambda (dependency dependency-id)
(emit-edge id dependency-id port))
dependencies ids)
(loop (append dependencies tail)
(set-insert id visited)))))))))))))

;;;
;;; Command-line options.
;;;

(define %options
(list (option '(#\t "type") #t #f
(lambda (opt name arg result)
(alist-cons 'node-type (lookup-node-type arg)
result)))
(option '("list-types") #f #f
(lambda (opt name arg result)
(list-node-types)
(exit 0)))
(option '(#\h "help") #f #f
(lambda args
(show-help)
(exit 0)))
(option '(#\V "version") #f #f
(lambda args
(show-version-and-exit "guix edit")))))

(define (show-help)
;; TRANSLATORS: Here 'dot' is the name of a program; it must not be
;; translated.
(display (_ "Usage: guix graph PACKAGE...
Emit a Graphviz (dot) representation of the dependencies of PACKAGE...\n"))
(display (_ "
-t, --type=TYPE represent nodes of the given TYPE"))
(display (_ "
--list-types list the available graph types"))
(newline)
(display (_ "
-h, --help display this help and exit"))
(display (_ "
-V, --version display version information and exit"))
(newline)
(show-bug-report-information))

(define %default-options
`((node-type . ,%package-node-type)))

;;;
;;; Entry point.
;;;

(define (guix-graph . args)
(with-error-handling
(let* ((opts (parse-command-line args %options
(list %default-options)))
(specs (filter-map (match-lambda
(('argument . spec) spec)
(_ #f))
opts))
(type (assoc-ref opts 'node-type))
(packages (map specification->package specs)))
(with-store store
(run-with-store store
(mlet %store-monad ((nodes (mapm %store-monad
(node-type-convert type)
packages)))
(export-graph (concatenate nodes)
(current-output-port)
#:node-type type))))))
#t)

;;; graph.scm ends here

+ 193
- 0
tests/graph.scm View File

@@ -0,0 +1,193 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.

(define-module (test-graph)
#:use-module (guix tests)
#:use-module (guix scripts graph)
#:use-module (guix packages)
#:use-module (guix derivations)
#:use-module (guix store)
#:use-module (guix monads)
#:use-module (guix build-system gnu)
#:use-module (guix gexp)
#:use-module (gnu packages)
#:use-module (gnu packages bootstrap)
#:use-module (ice-9 match)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-11)
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-64))

(define %store
(open-connection-for-tests))

(define (make-recording-backend)
"Return a <graph-backend> and a thunk that returns the recorded nodes and
edges."
(let ((nodes '())
(edges '()))
(define (record-node id label port)
(set! nodes (cons (list id label) nodes)))
(define (record-edge source target port)
(set! edges (cons (list source target) edges)))
(define (return)
(values (reverse nodes) (reverse edges)))

(values (graph-backend (const #t) (const #t)
record-node record-edge)
return)))

(define (package->tuple package)
"Return a tuple representing PACKAGE as produced by %PACKAGE-NODE-TYPE."
(list (object-address package)
(package-full-name package)))

(define (edge->tuple source target)
"Likewise for an edge from SOURCE to TARGET."
(list (object-address source)
(object-address target)))

(test-begin "graph")

(test-assert "package DAG"
(let-values (((backend nodes+edges) (make-recording-backend)))
(let* ((p1 (dummy-package "p1"))
(p2 (dummy-package "p2" (inputs `(("p1" ,p1)))))
(p3 (dummy-package "p3" (inputs `(("p2" ,p2) ("p1", p1))))))
(run-with-store %store
(export-graph (list p3) 'port
#:node-type %package-node-type
#:backend backend))
;; We should see nothing more than these 3 packages.
(let-values (((nodes edges) (nodes+edges)))
(and (equal? nodes (map package->tuple (list p3 p2 p1)))
(equal? edges
(map edge->tuple
(list p3 p3 p2)
(list p2 p1 p1))))))))

(test-assert "bag-emerged DAG"
(let-values (((backend nodes+edges) (make-recording-backend)))
(let ((p (dummy-package "p"))
(implicit (map (match-lambda
((label package) package))
(standard-packages))))
(run-with-store %store
(export-graph (list p) 'port
#:node-type %bag-emerged-node-type
#:backend backend))
;; We should see exactly P and IMPLICIT, with one edge from P to each
;; element of IMPLICIT.
(let-values (((nodes edges) (nodes+edges)))
(and (equal? (match nodes
(((labels names) ...)
names))
(map package-full-name (cons p implicit)))
(equal? (match edges
(((sources destinations) ...)
(zip (map store-path-package-name sources)
(map store-path-package-name destinations))))
(map (lambda (destination)
(list "p-0.drv"
(string-append
(package-full-name destination)
".drv")))
implicit)))))))

(test-assert "bag DAG"
(let-values (((backend nodes+edges) (make-recording-backend)))
(let ((p (dummy-package "p")))
(run-with-store %store
(export-graph (list p) 'port
#:node-type %bag-node-type
#:backend backend))
;; We should see P, its implicit inputs as well as the whole DAG, which
;; should include bootstrap binaries.
(let-values (((nodes edges) (nodes+edges)))
(every (lambda (name)
(find (cut string=? name <>)
(match nodes
(((labels names) ...)
names))))
(match %bootstrap-inputs
(((labels packages) ...)
(map package-full-name packages))))))))

(test-assert "derivation DAG"
(let-values (((backend nodes+edges) (make-recording-backend)))
(run-with-store %store
(mlet* %store-monad ((txt (text-file "text-file" "Hello!"))
(guile (package->derivation %bootstrap-guile))
(drv (gexp->derivation "output"
#~(symlink #$txt #$output)
#:guile-for-build
guile)))
;; We should get at least these 3 nodes and corresponding edges.
(mbegin %store-monad
(export-graph (list drv) 'port
#:node-type %derivation-node-type
#:backend backend)
(let-values (((nodes edges) (nodes+edges)))
;; XXX: For some reason we need to throw in some 'basename'.
(return (and (match nodes
(((ids labels) ...)
(let ((ids (map basename ids)))
(every (lambda (item)
(member (basename item) ids))
(list txt
(derivation-file-name drv)
(derivation-file-name guile))))))
(every (cut member <>
(map (lambda (edge)
(map basename edge))
edges))
(list (map (compose basename derivation-file-name)
(list drv guile))
(list (basename (derivation-file-name drv))
(basename txt))))))))))))

(test-assert "reference DAG"
(let-values (((backend nodes+edges) (make-recording-backend)))
(run-with-store %store
(mlet* %store-monad ((txt (text-file "text-file" "Hello!"))
(guile (package->derivation %bootstrap-guile))
(drv (gexp->derivation "output"
#~(symlink #$txt #$output)
#:guile-for-build
guile))
(out -> (derivation->output-path drv)))
;; We should see only OUT and TXT, with an edge from the former to the
;; latter.
(mbegin %store-monad
(built-derivations (list drv))
(export-graph (list (derivation->output-path drv)) 'port
#:node-type %reference-node-type
#:backend backend)
(let-values (((nodes edges) (nodes+edges)))
(return
(and (equal? (match nodes
(((ids labels) ...)
ids))
(list out txt))
(equal? edges `((,out ,txt)))))))))))

(test-end "graph")

(exit (= (test-runner-fail-count (test-runner-current)) 0))

+ 34
- 0
tests/guix-graph.sh View File

@@ -0,0 +1,34 @@
# GNU Guix --- Functional package management for GNU
# Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
#
# This file is part of GNU Guix.
#
# GNU Guix is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or (at
# your option) any later version.
#
# GNU Guix is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.

#
# Test the 'guix graph' command-line utility.
#

guix graph --version

for package in guile-bootstrap coreutils python
do
for graph in package bag-emerged bag
do
guix graph -t "$graph" "$package" | grep "$package"
done
done

guix build guile-bootstrap
guix graph -t references guile-bootstrap | grep guile-bootstrap

Loading…
Cancel
Save