* [bug#50632] [PATCH] graph: Add '--max-depth'.
@ 2021-09-17 8:18 Ludovic Courtès
2021-09-20 15:00 ` zimoun
2021-09-21 13:45 ` bug#50632: " Ludovic Courtès
0 siblings, 2 replies; 6+ messages in thread
From: Ludovic Courtès @ 2021-09-17 8:18 UTC (permalink / raw)
To: 50632; +Cc: Ludovic Courtès
From: Ludovic Courtès <ludovic.courtes@inria.fr>
* guix/graph.scm (export-graph): Add #:max-depth and honor it, adding
'depths' argument to 'loop'.
* guix/scripts/graph.scm (%options, show-help): Add '--max-depth'.
(%default-options): Add 'max-depth'.
(guix-graph): Pass #:max-depth to 'export-graph'.
* tests/graph.scm ("package DAG, limited depth"): New test.
* doc/guix.texi (Invoking guix graph): Document it.
---
doc/guix.texi | 14 +++++++++++++
guix/graph.scm | 45 ++++++++++++++++++++++++++----------------
guix/scripts/graph.scm | 11 ++++++++++-
tests/graph.scm | 21 +++++++++++++++++++-
4 files changed, 72 insertions(+), 19 deletions(-)
Hello!
This patch adds a long-overdue ‘--max-depth’ option to ‘guix graph’,
which helps visualization somewhat.
Trimming of nodes beyond the max depth happens at export time. The
implementation is a bit naive (with a list containing the depth of
each node) but performance is mostly unchanged.
Feedback welcome!
Ludo’.
diff --git a/doc/guix.texi b/doc/guix.texi
index 2fc9687910..6c0a581463 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -12598,6 +12598,20 @@ $ guix graph --path -t references emacs libunistring
/gnu/store/@dots{}-libunistring-0.9.10
@end example
+Sometimes you still want to visualize the graph but would like to trim
+it so it can actually be displayed. One way to do it is via the
+@option{--max-depth} (or @option{-M}) option, which lets you specify the
+maximum depth of the graph. In the example below, we visualize only
+@code{libreoffice} and the nodes whose distance to @code{libreoffice} is
+at most 2:
+
+@example
+guix graph -M 2 libreoffice | xdot -f fdp -
+@end example
+
+Mind you, that's still a big ball of spaghetti, but at least
+@command{dot} can render it quickly and it can be browsed somewhat.
+
The available options are the following:
@table @option
diff --git a/guix/graph.scm b/guix/graph.scm
index 0d4cd83667..3a1cab244b 100644
--- a/guix/graph.scm
+++ b/guix/graph.scm
@@ -337,11 +337,12 @@ nodeArray.push(nodes[\"~a\"]);~%"
(define* (export-graph sinks port
#:key
- reverse-edges? node-type
+ reverse-edges? node-type (max-depth +inf.0)
(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. When REVERSE-EDGES? is
-true, draw reverse arrows."
+true, draw reverse arrows. Do not represent nodes whose distance to one of
+the SINKS is greater than MAX-DEPTH."
(match backend
(($ <graph-backend> _ _ emit-prologue emit-epilogue emit-node emit-edge)
(emit-prologue (node-type-name node-type) port)
@@ -349,6 +350,7 @@ true, draw reverse arrows."
(match node-type
(($ <node-type> node-identifier node-label node-edges)
(let loop ((nodes sinks)
+ (depths (make-list (length sinks) 0))
(visited (set)))
(match nodes
(()
@@ -356,20 +358,29 @@ true, draw reverse arrows."
(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)
- (if reverse-edges?
- (emit-edge dependency-id id port)
- (emit-edge id dependency-id port)))
- dependencies ids)
- (loop (append dependencies tail)
- (set-insert id visited)))))))))))))
+ (match depths
+ ((depth . depths)
+ (mlet %store-monad ((id (node-identifier head)))
+ (if (set-contains? visited id)
+ (loop tail depths visited)
+ (mlet* %store-monad ((dependencies
+ (if (= depth max-depth)
+ (return '())
+ (node-edges head)))
+ (ids
+ (mapm %store-monad
+ node-identifier
+ dependencies)))
+ (emit-node id (node-label head) port)
+ (for-each (lambda (dependency dependency-id)
+ (if reverse-edges?
+ (emit-edge dependency-id id port)
+ (emit-edge id dependency-id port)))
+ dependencies ids)
+ (loop (append dependencies tail)
+ (append (make-list (length dependencies)
+ (+ 1 depth))
+ depths)
+ (set-insert id visited)))))))))))))))
;;; graph.scm ends here
diff --git a/guix/scripts/graph.scm b/guix/scripts/graph.scm
index 66de824ef4..439fae0b52 100644
--- a/guix/scripts/graph.scm
+++ b/guix/scripts/graph.scm
@@ -500,6 +500,10 @@ package modules, while attempting to retain user package modules."
(lambda (opt name arg result)
(alist-cons 'backend (lookup-backend arg)
result)))
+ (option '(#\M "max-depth") #t #f
+ (lambda (opt name arg result)
+ (alist-cons 'max-depth (string->number* arg)
+ result)))
(option '("list-backends") #f #f
(lambda (opt name arg result)
(list-backends)
@@ -537,6 +541,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_ "
+ --max-depth=DEPTH limit to nodes within distance DEPTH"))
(display (G_ "
--path display the shortest path between the given nodes"))
(display (G_ "
@@ -559,6 +565,7 @@ Emit a representation of the dependency graph of PACKAGE...\n"))
(define %default-options
`((node-type . ,%package-node-type)
(backend . ,%graphviz-backend)
+ (max-depth . +inf.0)
(system . ,(%current-system))))
\f
@@ -582,6 +589,7 @@ Emit a representation of the dependency graph of PACKAGE...\n"))
(with-store store
(let* ((transform (options->transformation opts))
+ (max-depth (assoc-ref opts 'max-depth))
(items (filter-map (match-lambda
(('argument . (? store-path? item))
item)
@@ -613,7 +621,8 @@ nodes (given ~a)~%")
(export-graph (concatenate nodes)
(current-output-port)
#:node-type type
- #:backend backend)))
+ #:backend backend
+ #:max-depth max-depth)))
#:system (assq-ref opts 'system)))))
#t)
diff --git a/tests/graph.scm b/tests/graph.scm
index e374dad1a5..fadac265f9 100644
--- a/tests/graph.scm
+++ b/tests/graph.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -94,6 +94,25 @@ edges."
(list p3 p3 p2)
(list p2 p1 p1))))))))
+(test-assert "package DAG, limited depth"
+ (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 `(("p1" ,p1)))))
+ (p4 (dummy-package "p4" (inputs `(("p2" ,p2) ("p3" ,p3))))))
+ (run-with-store %store
+ (export-graph (list p4) 'port
+ #:max-depth 1
+ #: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 p4 p2 p3)))
+ (equal? edges
+ (map edge->tuple
+ (list p4 p4)
+ (list p2 p3))))))))
+
(test-assert "reverse package DAG"
(let-values (((backend nodes+edges) (make-recording-backend)))
(run-with-store %store
--
2.33.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [bug#50632] [PATCH] graph: Add '--max-depth'.
2021-09-17 8:18 [bug#50632] [PATCH] graph: Add '--max-depth' Ludovic Courtès
@ 2021-09-20 15:00 ` zimoun
2021-09-21 8:44 ` Ludovic Courtès
2021-09-21 13:45 ` bug#50632: " Ludovic Courtès
1 sibling, 1 reply; 6+ messages in thread
From: zimoun @ 2021-09-20 15:00 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: Ludovic Courtès, 50632
Hi,
On Fri, 17 Sept 2021 at 10:38, Ludovic Courtès <ludo@gnu.org> wrote:
> * guix/graph.scm (export-graph): Add #:max-depth and honor it, adding
> 'depths' argument to 'loop'.
> * guix/scripts/graph.scm (%options, show-help): Add '--max-depth'.
> (%default-options): Add 'max-depth'.
> (guix-graph): Pass #:max-depth to 'export-graph'.
> * tests/graph.scm ("package DAG, limited depth"): New test.
> * doc/guix.texi (Invoking guix graph): Document it.
> ---
> doc/guix.texi | 14 +++++++++++++
> guix/graph.scm | 45 ++++++++++++++++++++++++++----------------
> guix/scripts/graph.scm | 11 ++++++++++-
> tests/graph.scm | 21 +++++++++++++++++++-
> 4 files changed, 72 insertions(+), 19 deletions(-)
LGTM!
> Trimming of nodes beyond the max depth happens at export time. The
> implementation is a bit naive (with a list containing the depth of
> each node) but performance is mostly unchanged.
Well, I do not see how it could be better. :-)
And export time is also walk time, IIUC. :-)
> diff --git a/doc/guix.texi b/doc/guix.texi
> index 2fc9687910..6c0a581463 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -12598,6 +12598,20 @@ $ guix graph --path -t references emacs libunistring
> /gnu/store/@dots{}-libunistring-0.9.10
> @end example
>
> +Sometimes you still want to visualize the graph but would like to trim
> +it so it can actually be displayed. One way to do it is via the
> +@option{--max-depth} (or @option{-M}) option, which lets you specify the
> +maximum depth of the graph. In the example below, we visualize only
> +@code{libreoffice} and the nodes whose distance to @code{libreoffice} is
> +at most 2:
> +
> +@example
> +guix graph -M 2 libreoffice | xdot -f fdp -
> +@end example
I am not sure 'xdot' is part of the GraphViz toolsuite. Instead,
+@example
+guix graph -M 2 libreoffice | fdp -Tsvg > libreoffice.svg
+@end example
Cheers,
simon
^ permalink raw reply [flat|nested] 6+ messages in thread
* [bug#50632] [PATCH] graph: Add '--max-depth'.
2021-09-20 15:00 ` zimoun
@ 2021-09-21 8:44 ` Ludovic Courtès
2021-09-21 9:19 ` zimoun
0 siblings, 1 reply; 6+ messages in thread
From: Ludovic Courtès @ 2021-09-21 8:44 UTC (permalink / raw)
To: zimoun; +Cc: 50632
Hi,
zimoun <zimon.toutoune@gmail.com> skribis:
> On Fri, 17 Sept 2021 at 10:38, Ludovic Courtès <ludo@gnu.org> wrote:
[...]
>> +@example
>> +guix graph -M 2 libreoffice | xdot -f fdp -
>> +@end example
>
> I am not sure 'xdot' is part of the GraphViz toolsuite. Instead,
True, it’s a separate program, but it’s mentioned since
c2b2c19a7b8b75ef6dd153ca121dd8765cdcd746 because it’s more convenient
IMO.
Thanks for taking a look!
Ludo’.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [bug#50632] [PATCH] graph: Add '--max-depth'.
2021-09-21 8:44 ` Ludovic Courtès
@ 2021-09-21 9:19 ` zimoun
2021-09-21 13:49 ` Ludovic Courtès
0 siblings, 1 reply; 6+ messages in thread
From: zimoun @ 2021-09-21 9:19 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: 50632
Hi Ludo,
On Tue, 21 Sep 2021 at 10:44, Ludovic Courtès <ludo@gnu.org> wrote:
> True, it’s a separate program, but it’s mentioned since
> c2b2c19a7b8b75ef6dd153ca121dd8765cdcd746 because it’s more convenient
> IMO.
Ah, I should have missed this. However, it does not work out of the
box:
--8<---------------cut here---------------start------------->8---
$ guix environment --ad-hoc xdot
$ guix graph coreutils | xdot -
Traceback (most recent call last):
File "/gnu/store/gm49bvwdgjpx23wlcfrm8mbf8n75a77n-xdot-1.1/bin/.xdot-real", line 11, in <module>
load_entry_point('xdot==1.1', 'gui_scripts', 'xdot')()
File "/gnu/store/gm49bvwdgjpx23wlcfrm8mbf8n75a77n-xdot-1.1/lib/python3.8/site-packages/xdot/__main__.py", line 70, in main
win = DotWindow(width=width, height=height)
File "/gnu/store/gm49bvwdgjpx23wlcfrm8mbf8n75a77n-xdot-1.1/lib/python3.8/site-packages/xdot/ui/window.py", line 546, in __init__
self.dotwidget = widget or DotWidget()
File "/gnu/store/gm49bvwdgjpx23wlcfrm8mbf8n75a77n-xdot-1.1/lib/python3.8/site-packages/xdot/ui/window.py", line 67, in __init__
self.connect("draw", self.on_draw)
TypeError: <window.DotWidget object at 0x7f465dd1f400 (xdot+ui+window+DotWidget at 0x17b50f0)>: unknown signal name: draw
(.xdot-real:5940): Gtk-WARNING **: 11:09:08.420: A floating object was finalized. This means that someone
called g_object_unref() on an object that had only a floating
reference; the initial floating reference is not owned by anyone
and must be removed with g_object_ref_sink().
guix graph: error: fport_write: Broken pipe
Segmentation fault
--8<---------------cut here---------------end--------------->8---
That’s why I suggest to keep examples in the manual as simple as
possible. From my point of view, this package should be mentioned but
should not be part of the example.
The core of the comment is when releasing. Examples involving a complex
stack are harder to fix. And from my point of view, release broken
examples in the manual is not acceptable*; for an instance of this, see
<http://issues.guix.gnu.org/issue/47097>.
*not acceptable: well, it is not GNU high standard; even if we can live
with them. ;-)
Cheers,
simon
^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#50632: [PATCH] graph: Add '--max-depth'.
2021-09-17 8:18 [bug#50632] [PATCH] graph: Add '--max-depth' Ludovic Courtès
2021-09-20 15:00 ` zimoun
@ 2021-09-21 13:45 ` Ludovic Courtès
1 sibling, 0 replies; 6+ messages in thread
From: Ludovic Courtès @ 2021-09-21 13:45 UTC (permalink / raw)
To: 50632-done
Ludovic Courtès <ludo@gnu.org> skribis:
> * guix/graph.scm (export-graph): Add #:max-depth and honor it, adding
> 'depths' argument to 'loop'.
> * guix/scripts/graph.scm (%options, show-help): Add '--max-depth'.
> (%default-options): Add 'max-depth'.
> (guix-graph): Pass #:max-depth to 'export-graph'.
> * tests/graph.scm ("package DAG, limited depth"): New test.
> * doc/guix.texi (Invoking guix graph): Document it.
Pushed as 5b32ad4f6f555d305659cee825879df075b06331 followed by a news
entry!
Ludo’.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [bug#50632] [PATCH] graph: Add '--max-depth'.
2021-09-21 9:19 ` zimoun
@ 2021-09-21 13:49 ` Ludovic Courtès
0 siblings, 0 replies; 6+ messages in thread
From: Ludovic Courtès @ 2021-09-21 13:49 UTC (permalink / raw)
To: zimoun; +Cc: 50632
zimoun <zimon.toutoune@gmail.com> skribis:
> On Tue, 21 Sep 2021 at 10:44, Ludovic Courtès <ludo@gnu.org> wrote:
>
>> True, it’s a separate program, but it’s mentioned since
>> c2b2c19a7b8b75ef6dd153ca121dd8765cdcd746 because it’s more convenient
>> IMO.
>
> Ah, I should have missed this. However, it does not work out of the
> box:
>
> $ guix environment --ad-hoc xdot
> $ guix graph coreutils | xdot -
> Traceback (most recent call last):
> File "/gnu/store/gm49bvwdgjpx23wlcfrm8mbf8n75a77n-xdot-1.1/bin/.xdot-real", line 11, in <module>
> load_entry_point('xdot==1.1', 'gui_scripts', 'xdot')()
> File "/gnu/store/gm49bvwdgjpx23wlcfrm8mbf8n75a77n-xdot-1.1/lib/python3.8/site-packages/xdot/__main__.py", line 70, in main
> win = DotWindow(width=width, height=height)
> File "/gnu/store/gm49bvwdgjpx23wlcfrm8mbf8n75a77n-xdot-1.1/lib/python3.8/site-packages/xdot/ui/window.py", line 546, in __init__
> self.dotwidget = widget or DotWidget()
> File "/gnu/store/gm49bvwdgjpx23wlcfrm8mbf8n75a77n-xdot-1.1/lib/python3.8/site-packages/xdot/ui/window.py", line 67, in __init__
> self.connect("draw", self.on_draw)
> TypeError: <window.DotWidget object at 0x7f465dd1f400 (xdot+ui+window+DotWidget at 0x17b50f0)>: unknown signal name: draw
>
> (.xdot-real:5940): Gtk-WARNING **: 11:09:08.420: A floating object was finalized. This means that someone
> called g_object_unref() on an object that had only a floating
> reference; the initial floating reference is not owned by anyone
> and must be removed with g_object_ref_sink().
> guix graph: error: fport_write: Broken pipe
> Segmentation fault
Could you report a bug? This works for me:
--8<---------------cut here---------------start------------->8---
$ guix describe
Generacio 189 Aug 30 2021 12:09:27 (nuna)
guix f91ae94
repository URL: https://git.savannah.gnu.org/git/guix.git
branch: master
commit: f91ae9425bb385b60396a544afe27933896b8fa3
$ guix graph coreutils | guix environment --pure -E ^DISPLAY -E ^XAUTH --ad-hoc xdot -- xdot -
--8<---------------cut here---------------end--------------->8---
> That’s why I suggest to keep examples in the manual as simple as
> possible. From my point of view, this package should be mentioned but
> should not be part of the example.
>
> The core of the comment is when releasing. Examples involving a complex
> stack are harder to fix. And from my point of view, release broken
> examples in the manual is not acceptable*; for an instance of this, see
> <http://issues.guix.gnu.org/issue/47097>.
I sympathize with the general feeling. I think ‘xdot’ is not that bad
though, plus the first example in that section still uses ‘dot’.
Thanks,
Ludo’.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-09-21 13:50 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-17 8:18 [bug#50632] [PATCH] graph: Add '--max-depth' Ludovic Courtès
2021-09-20 15:00 ` zimoun
2021-09-21 8:44 ` Ludovic Courtès
2021-09-21 9:19 ` zimoun
2021-09-21 13:49 ` Ludovic Courtès
2021-09-21 13:45 ` bug#50632: " Ludovic Courtès
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/guix.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.