unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
From: "Ludovic Courtès" <ludo@gnu.org>
To: 41164@debbugs.gnu.org
Cc: "Ludovic Courtès" <ludo@gnu.org>
Subject: [bug#41164] [PATCH 3/3] guix graph: Add '--path'.
Date: Sun, 10 May 2020 01:27:39 +0200	[thread overview]
Message-ID: <20200509232739.29016-3-ludo@gnu.org> (raw)
In-Reply-To: <20200509232739.29016-1-ludo@gnu.org>

* guix/scripts/graph.scm (display-path): New procedure.
(%options, show-help): Add '--path'.
(guix-graph): Handle it.
* tests/guix-graph.sh: Add tests.
* doc/guix.texi (Invoking guix graph): Document it.
(Invoking guix size): Mention it.
---
 doc/guix.texi          | 48 ++++++++++++++++++++++++++++++++++++++++--
 guix/scripts/graph.scm | 46 +++++++++++++++++++++++++++++++++++-----
 tests/guix-graph.sh    | 16 +++++++++++++-
 3 files changed, 102 insertions(+), 8 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 2ed545847b..e174e13887 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -10021,6 +10021,12 @@ In this example we see that the combination of the four packages takes
 102.3@tie{}MiB in total, which is much less than the sum of each closure
 since they have a lot of dependencies in common.
 
+When looking at the profile returned by @command{guix size}, you may
+find yourself wondering why a given package shows up in the profile at
+all.  To understand it, you can use @command{guix graph --path -t
+references} to display the shortest path between the two packages
+(@pxref{Invoking guix graph}).
+
 The available options are:
 
 @table @option
@@ -10081,8 +10087,9 @@ directly to the @command{dot} command of Graphviz.  It can also emit an
 HTML page with embedded JavaScript code to display a ``chord diagram''
 in a Web browser, using the @uref{https://d3js.org/, d3.js} library, or
 emit Cypher queries to construct a graph in a graph database supporting
-the @uref{https://www.opencypher.org/, openCypher} query language.
-The general syntax is:
+the @uref{https://www.opencypher.org/, openCypher} query language.  With
+@option{--path}, it simply displays the shortest path between two
+packages.  The general syntax is:
 
 @example
 guix graph @var{options} @var{package}@dots{}
@@ -10228,6 +10235,29 @@ collected.
 
 @end table
 
+@cindex shortest path, between packages
+Often, the graph of the package you are interested in does not fit on
+your screen, and anyway all you want to know is @emph{why} that package
+actually depends on some seemingly unrelated package.  The
+@option{--path} option instructs @command{guix graph} to display the
+shortest path between two packages (or derivations, or store items,
+etc.):
+
+@example
+$ guix graph --path emacs libunistring
+emacs@@26.3
+mailutils@@3.9
+libunistring@@0.9.10
+$ guix graph --path -t derivation emacs libunistring
+/gnu/store/@dots{}-emacs-26.3.drv
+/gnu/store/@dots{}-mailutils-3.9.drv
+/gnu/store/@dots{}-libunistring-0.9.10.drv
+$ guix graph --path -t references emacs libunistring
+/gnu/store/@dots{}-emacs-26.3
+/gnu/store/@dots{}-libidn2-2.2.0
+/gnu/store/@dots{}-libunistring-0.9.10
+@end example
+
 The available options are the following:
 
 @table @option
@@ -10248,6 +10278,20 @@ List the supported graph backends.
 
 Currently, the available backends are Graphviz and d3.js.
 
+@item --path
+Display the shortest path between two nodes of the type specified by
+@option{--type}.  The example below shows the shortest path between
+@code{libreoffice} and @code{llvm} according to the references of
+@code{libreoffice}:
+
+@example
+$ guix graph --path -t references libreoffice llvm
+/gnu/store/@dots{}-libreoffice-6.4.2.2
+/gnu/store/@dots{}-libepoxy-1.5.4
+/gnu/store/@dots{}-mesa-19.3.4
+/gnu/store/@dots{}-llvm-9.0.1
+@end example
+
 @item --expression=@var{expr}
 @itemx -e @var{expr}
 Consider the package @var{expr} evaluates to.
diff --git a/guix/scripts/graph.scm b/guix/scripts/graph.scm
index d69dace14f..1d5db3b3cb 100644
--- a/guix/scripts/graph.scm
+++ b/guix/scripts/graph.scm
@@ -455,6 +455,29 @@ package modules, while attempting to retain user package modules."
                       (graph-backend-description backend)))
             %graph-backends))
 
+\f
+;;;
+;;; Displaying a path.
+;;;
+
+(define (display-path node1 node2 type)
+  "Display the shortest path from NODE1 to NODE2, of TYPE."
+  (mlet %store-monad ((path (shortest-path node1 node2 type)))
+    (define node-label
+      (let ((label (node-type-label type)))
+        ;; Special-case derivations and store items to print them in full,
+        ;; contrary to what their 'node-type-label' normally does.
+        (match-lambda
+          ((? derivation? drv) (derivation-file-name drv))
+          ((? string? str) str)
+          (node (label node)))))
+
+    (if path
+        (format #t "~{~a~%~}" (map node-label path))
+        (leave (G_ "no path from '~a' to '~a'~%")
+               (node-label node1) (node-label node2)))
+    (return #t)))
+
 \f
 ;;;
 ;;; Command-line options.
@@ -465,6 +488,9 @@ package modules, while attempting to retain user package modules."
                  (lambda (opt name arg result)
                    (alist-cons 'node-type (lookup-node-type arg)
                                result)))
+         (option '("path") #f #f
+                 (lambda (opt name arg result)
+                   (alist-cons 'path? #t result)))
          (option '("list-types") #f #f
                  (lambda (opt name arg result)
                    (list-node-types)
@@ -510,6 +536,8 @@ Emit a representation of the dependency graph of PACKAGE...\n"))
   -t, --type=TYPE        represent nodes of the given TYPE"))
   (display (G_ "
       --list-types       list the available graph types"))
+  (display (G_ "
+      --path             display the shortest path between the given nodes"))
   (display (G_ "
   -e, --expression=EXPR  consider the package EXPR evaluates to"))
   (display (G_ "
@@ -566,11 +594,19 @@ Emit a representation of the dependency graph of PACKAGE...\n"))
           (mlet %store-monad ((_     (set-grafting #f))
                               (nodes (mapm %store-monad
                                            (node-type-convert type)
-                                           items)))
-            (export-graph (concatenate nodes)
-                          (current-output-port)
-                          #:node-type type
-                          #:backend backend))
+                                           (reverse items))))
+            (if (assoc-ref opts 'path?)
+                (match nodes
+                  (((node1 _ ...) (node2 _ ...))
+                   (display-path node1 node2 type))
+                  (_
+                   (leave (G_ "'--path' option requires exactly two \
+nodes (given ~a)~%")
+                          (length nodes))))
+                (export-graph (concatenate nodes)
+                              (current-output-port)
+                              #:node-type type
+                              #:backend backend)))
           #:system (assq-ref opts 'system)))))
   #t)
 
diff --git a/tests/guix-graph.sh b/tests/guix-graph.sh
index 4c37b61b38..ccb4933c88 100644
--- a/tests/guix-graph.sh
+++ b/tests/guix-graph.sh
@@ -1,5 +1,5 @@
 # GNU Guix --- Functional package management for GNU
-# Copyright © 2015, 2016, 2019 Ludovic Courtès <ludo@gnu.org>
+# Copyright © 2015, 2016, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
 # Copyright © 2019 Simon Tournier <zimon.toutoune@gmail.com>
 #
 # This file is part of GNU Guix.
@@ -82,3 +82,17 @@ then false; else true; fi
 
 # Try --load-path
 guix graph -L $module_dir dummy | grep 'label = "dummy'
+
+# Displaying shortest paths (or lack thereof).
+if guix graph --path emacs vim; then false; else true; fi
+
+path="\
+emacs
+gnutls
+guile
+libffi"
+test "`guix graph --path emacs libffi | cut -d '@' -f1`" = "$path"
+
+# At the derivation level, there's a direct path because libffi is propagated
+# via gtk+.
+test "`guix graph --path -t derivation emacs libffi | wc -l`" -ge 2
-- 
2.26.2





  parent reply	other threads:[~2020-05-09 23:27 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-09 23:04 [bug#41164] [PATCH 0/3] Add 'guix graph --path' Ludovic Courtès
2020-05-09 23:27 ` [bug#41164] [PATCH 1/3] graph: reference/referrer node types work with graph traversal Ludovic Courtès
2020-05-09 23:27   ` [bug#41164] [PATCH 2/3] graph: Add 'shortest-path' Ludovic Courtès
2020-05-09 23:27   ` Ludovic Courtès [this message]
2020-05-10 10:51 ` [bug#41164] [PATCH 0/3] Add 'guix graph --path' zimoun
2020-05-10 14:16   ` Ludovic Courtès
2020-05-10 16:18     ` zimoun
2020-05-10 19:27       ` zimoun
2020-05-11 12:33         ` Ludovic Courtès
2020-05-11 12:36       ` Ludovic Courtès
2020-05-11 14:02         ` zimoun
2020-05-11 20:55           ` Ludovic Courtès
2020-05-11 22:13             ` zimoun
2020-05-12  8:41               ` Ludovic Courtès
2020-05-12 11:56                 ` zimoun
2020-05-11 21:36           ` bug#41164: " Ludovic Courtès
2020-05-10 23:45     ` [bug#41164] Fix pipe 'guix show' zimoun

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://guix.gnu.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200509232739.29016-3-ludo@gnu.org \
    --to=ludo@gnu.org \
    --cc=41164@debbugs.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).