From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp1 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id eLHcA3w8t170AgAA0tVLHw (envelope-from ) for ; Sat, 09 May 2020 23:27:56 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp1 with LMTPS id AA1rFIk8t17CWQAAbx9fmQ (envelope-from ) for ; Sat, 09 May 2020 23:28:09 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 216819400EF for ; Sat, 9 May 2020 23:28:07 +0000 (UTC) Received: from localhost ([::1]:49870 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jXYt5-00077W-SZ for larch@yhetil.org; Sat, 09 May 2020 19:28:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50736) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jXYt1-00075V-Js for guix-patches@gnu.org; Sat, 09 May 2020 19:28:03 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:37044) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jXYt1-00081k-BD for guix-patches@gnu.org; Sat, 09 May 2020 19:28:03 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1jXYt1-00055f-8G for guix-patches@gnu.org; Sat, 09 May 2020 19:28:03 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#41164] [PATCH 3/3] guix graph: Add '--path'. Resent-From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 09 May 2020 23:28:03 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 41164 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 41164@debbugs.gnu.org Cc: Ludovic =?UTF-8?Q?Court=C3=A8s?= Received: via spool by 41164-submit@debbugs.gnu.org id=B41164.158906687819541 (code B ref 41164); Sat, 09 May 2020 23:28:03 +0000 Received: (at 41164) by debbugs.gnu.org; 9 May 2020 23:27:58 +0000 Received: from localhost ([127.0.0.1]:48588 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jXYsv-000556-N2 for submit@debbugs.gnu.org; Sat, 09 May 2020 19:27:58 -0400 Received: from eggs.gnu.org ([209.51.188.92]:47718) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jXYss-00054T-4q for 41164@debbugs.gnu.org; Sat, 09 May 2020 19:27:54 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]:34095) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jXYsm-0007EV-UI; Sat, 09 May 2020 19:27:48 -0400 Received: from [2a01:e0a:1d:7270:af76:b9b:ca24:c465] (port=40868 helo=gnu.org) by fencepost.gnu.org with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1jXYsl-00020y-U1; Sat, 09 May 2020 19:27:48 -0400 From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Date: Sun, 10 May 2020 01:27:39 +0200 Message-Id: <20200509232739.29016-3-ludo@gnu.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200509232739.29016-1-ludo@gnu.org> References: <20200509232739.29016-1-ludo@gnu.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-Spam-Score: -3.3 (---) X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: "Guix-patches" X-Scanner: scn0 X-Spam-Score: 1.49 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of guix-patches-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-patches-bounces@gnu.org X-Scan-Result: default: False [1.49 / 13.00]; RCVD_VIA_SMTP_AUTH(0.00)[]; GENERIC_REPUTATION(0.00)[-0.53962218373628]; MX_INVALID(1.00)[cached]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(-0.20)[+ip4:209.51.188.0/24:c]; IP_REPUTATION_HAM(0.00)[asn: 22989(0.09), country: US(-0.00), ip: 209.51.188.17(-0.54)]; DWL_DNSWL_FAIL(0.00)[209.51.188.17:server fail]; RCPT_COUNT_TWO(0.00)[2]; MAILLIST(-0.20)[mailman]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; R_DKIM_NA(0.00)[]; MIME_TRACE(0.00)[0:+]; ASN(0.00)[asn:22989, ipnet:209.51.188.0/24, country:US]; TAGGED_FROM(0.00)[larch=yhetil.org]; FROM_NEQ_ENVFROM(0.00)[ludo@gnu.org,guix-patches-bounces@gnu.org]; ARC_NA(0.00)[]; URIBL_BLOCKED(0.00)[gnu.org:email,opencypher.org:url,d3js.org:url]; FROM_HAS_DN(0.00)[]; MIME_GOOD(-0.10)[text/plain]; RCVD_TLS_LAST(0.00)[]; DMARC_NA(0.00)[gnu.org]; HAS_LIST_UNSUB(-0.01)[]; DNSWL_BLOCKED(0.00)[209.51.188.17:from]; MID_CONTAINS_FROM(1.00)[]; RWL_MAILSPIKE_POSSIBLE(0.00)[209.51.188.17:from]; RCVD_COUNT_SEVEN(0.00)[9]; FORGED_SENDER_MAILLIST(0.00)[] X-TUID: JbwY8yeu/8fc * 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)) + +;;; +;;; 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))) + ;;; ;;; 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 +# Copyright © 2015, 2016, 2019, 2020 Ludovic Courtès # Copyright © 2019 Simon Tournier # # 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