From a8f996c605c181e5adae0de24b235d463825beab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= Date: Sun, 21 Jun 2015 23:25:19 +0200 Subject: [PATCH] size: Add '--map-file' option. * guix/scripts/size.scm (profile->page-map): New procedures. (show-help, %options): Add --map-file. (guix-size): Honor it. * doc/guix.texi (Invoking guix size): Document it. * doc/images/coreutils-size-map.png: New file. * doc.am (dist_infoimage_DATA): Add it. --- doc.am | 4 ++- doc/guix.texi | 15 ++++++++- doc/images/coreutils-size-map.png | Bin 0 -> 6755 bytes guix/scripts/size.scm | 51 +++++++++++++++++++++++++++++- 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 doc/images/coreutils-size-map.png diff --git a/doc.am b/doc.am index ee896c189b..9d72b11caa 100644 --- a/doc.am +++ b/doc.am @@ -40,7 +40,9 @@ doc/os-config-%.texi: gnu/system/examples/%.tmpl cp "$<" "$@" infoimagedir = $(infodir)/images -dist_infoimage_DATA = doc/images/bootstrap-graph.png +dist_infoimage_DATA = \ + doc/images/bootstrap-graph.png \ + doc/images/coreutils-size-map.png # Try hard to obtain an image size and aspect that's reasonable for inclusion # in an Info or PDF document. diff --git a/doc/guix.texi b/doc/guix.texi index a669464feb..f9c9f2ab93 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -4038,10 +4038,23 @@ reports information based on information about the available substitutes (@pxref{Substitutes}). This allows it to profile disk usage of store items that are not even on disk, only available remotely. -A single option is available: +The available options are: @table @option +@item --map-file=@var{file} +Write to @var{file} a graphical map of disk usage as a PNG file. + +For the example above, the map looks like this: + +@image{images/coreutils-size-map,5in,, map of Coreutils disk usage +produced by @command{guix size}} + +This option requires that +@uref{http://wingolog.org/software/guile-charting/, Guile-Charting} be +installed and visible in Guile's module search path. When that is not +the case, @command{guix size} fails as it tries to load it. + @item --system=@var{system} @itemx -s @var{system} Consider packages for @var{system}---e.g., @code{x86_64-linux}. diff --git a/doc/images/coreutils-size-map.png b/doc/images/coreutils-size-map.png new file mode 100644 index 0000000000000000000000000000000000000000..21d73a84587fec3ee66c4b78f14f9a8192f0ea62 GIT binary patch literal 6755 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 drv output))))))) + +;;; +;;; Charts. +;;; + +;; Autoload Guile-Charting. +;; XXX: Use this hack instead of #:autoload to avoid compilation errors. +;; See . +(module-autoload! (current-module) + '(charting) '(make-page-map)) + +(define (profile->page-map profiles file) + "Write a 'page map' chart of PROFILES, a list of objects, to FILE, +the name of a PNG file." + (define (strip name) + (string-drop name (+ (string-length (%store-prefix)) 28))) + + (define data + (fold2 (lambda (profile result offset) + (match profile + (($ name self) + (let ((self (inexact->exact + (round (/ self (expt 2. 10)))))) + (values `((,(strip name) ,offset . ,self) + ,@result) + (+ offset self)))))) + '() + 0 + (sort profiles + (match-lambda* + ((($ _ _ total1) ($ _ _ total2)) + (> total1 total2)))))) + + ;; TRANSLATORS: This is the title of a graph, meaning that the graph + ;; represents a profile of the store (the "store" being the place where + ;; packages are stored.) + (make-page-map (_ "store profile") (pk data) + #:write-to-png file)) + ;;; ;;; Options. @@ -191,6 +230,8 @@ as \"guile:debug\" or \"gcc-4.8\" and return its store file name." (define (show-help) (display (_ "Usage: guix size [OPTION]... PACKAGE Report the size of PACKAGE and its dependencies.\n")) + (display (_ " + -m, --map-file=FILE write to FILE a graphical map of disk usage")) (display (_ " -s, --system=SYSTEM consider packages for SYSTEM--e.g., \"i686-linux\"")) (newline) @@ -207,6 +248,9 @@ Report the size of PACKAGE and its dependencies.\n")) (lambda (opt name arg result) (alist-cons 'system arg (alist-delete 'system result eq?)))) + (option '(#\m "map-file") #t #f + (lambda (opt name arg result) + (alist-cons 'map-file arg result))) (option '(#\h "help") #f #f (lambda args (show-help) @@ -230,6 +274,7 @@ Report the size of PACKAGE and its dependencies.\n")) (('argument . file) file) (_ #f)) opts)) + (map-file (assoc-ref opts 'map-file)) (system (assoc-ref opts 'system))) (match files (() @@ -239,7 +284,11 @@ Report the size of PACKAGE and its dependencies.\n")) (run-with-store store (mlet* %store-monad ((item (ensure-store-item file)) (profile (store-profile item))) - (display-profile* profile)) + (if map-file + (begin + (profile->page-map profile map-file) + (return #t)) + (display-profile* profile))) #:system system))) ((files ...) (leave (_ "too many arguments\n")))))))