scripts: Emit GC hint if free space is lower than absolute and relative threshold.

* guix/scripts.scm (%disk-space-warning-absolute): New variable.
(warn-about-disk-space): Test against %disk-space-warning-absolute.
Fix error in display-hint due to extraneous 'profile' argument.

Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
Pierre Neidhardt 2020-02-25 11:23:30 +01:00 committed by Ludovic Courtès
parent 513c0a0f46
commit fb7eec3a84
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5

@ -181,32 +181,69 @@ Show what and how will/would be built."
(newline (guix-warning-port)))) (newline (guix-warning-port))))
(define %disk-space-warning (define %disk-space-warning
;; The fraction (between 0 and 1) of free disk space below which a warning ;; Return a pair of absolute threshold (number of bytes) and relative
;; is emitted. ;; threshold (fraction between 0 and 1) for the free disk space below which
(make-parameter (match (and=> (getenv "GUIX_DISK_SPACE_WARNING") ;; a warning is emitted.
string->number) ;; GUIX_DISK_SPACE_WARNING can contain both thresholds. A value in [0;100)
(#f .05) ;5% ;; is a relative threshold, otherwise it's absolute. The following
(threshold (/ threshold 100.))))) ;; example values are valid:
;; - 1GiB;10% ;1 GiB absolute, and 10% relative.
;; - 15G ;15 GiB absolute, and default relative.
;; - 99% ;99% relative, and default absolute.
;; - 99 ;Same.
;; - 100 ;100 absolute, and default relative.
(let* ((default-absolute-threshold (size->number "5GiB"))
(default-relative-threshold 0.05)
(percentage->float (lambda (percentage)
(or (and=> (string->number
(car (string-split percentage #\%)))
(lambda (n) (/ n 100.0)))
default-relative-threshold)))
(size->number* (lambda (size)
(or (false-if-exception (size->number size))
default-absolute-threshold)))
(absolute? (lambda (size)
(not (or (string-suffix? "%" size)
(false-if-exception (< (size->number size) 100)))))))
(make-parameter
(match (getenv "GUIX_DISK_SPACE_WARNING")
(#f (list default-absolute-threshold
default-relative-threshold))
(env-string (match (string-split env-string #\;)
((threshold)
(if (absolute? threshold)
(list (size->number* threshold)
default-relative-threshold)
(list default-absolute-threshold
(percentage->float threshold))))
((threshold1 threshold2)
(if (absolute? threshold1)
(list (size->number* threshold1)
(percentage->float threshold2))
(list (size->number* threshold2)
(percentage->float threshold1))))))))))
(define* (warn-about-disk-space #:optional profile (define* (warn-about-disk-space #:optional profile
#:key #:key
(threshold (%disk-space-warning))) (thresholds (%disk-space-warning)))
"Display a hint about 'guix gc' if less than THRESHOLD of /gnu/store is "Display a hint about 'guix gc' if less than THRESHOLD of /gnu/store is
available." available.
THRESHOLD is a pair of (ABSOLUTE-THRESHOLD RELATIVE-THRESHOLD)."
(let* ((stats (statfs (%store-prefix))) (let* ((stats (statfs (%store-prefix)))
(block-size (file-system-block-size stats)) (block-size (file-system-block-size stats))
(available (* block-size (file-system-blocks-available stats))) (available (* block-size (file-system-blocks-available stats)))
(total (* block-size (file-system-block-count stats))) (total (* block-size (file-system-block-count stats)))
(ratio (/ available total 1.))) (relative-threshold-in-bytes (* total (cadr thresholds)))
(when (< ratio threshold) (absolute-threshold-in-bytes (* 1024 1024 1024 (car thresholds))))
(warning (G_ "only ~,1f% of free space available on ~a~%") (when (< available (min relative-threshold-in-bytes
(* ratio 100) (%store-prefix)) absolute-threshold-in-bytes))
(warning (G_ "only ~,1f GiB of free space available on ~a~%")
available (%store-prefix))
(display-hint (format #f (G_ "Consider deleting old profile (display-hint (format #f (G_ "Consider deleting old profile
generations and collecting garbage, along these lines: generations and collecting garbage, along these lines:
@example @example
guix gc --delete-generations=1m guix gc --delete-generations=1m
@end example\n") @end example\n"))))))
profile)))))
;;; scripts.scm ends here ;;; scripts.scm ends here