2018-08-05 15:50:15 +02:00
|
|
|
|
;;; guix-ui-store-item.el --- Interface for displaying store items -*- lexical-binding: t -*-
|
|
|
|
|
|
|
|
|
|
;; Copyright © 2018 Alex Kost <alezost@gmail.com>
|
|
|
|
|
|
|
|
|
|
;; This file is part of Emacs-Guix.
|
|
|
|
|
|
|
|
|
|
;; Emacs-Guix is free software; you can redistribute it and/or modify
|
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
;;
|
|
|
|
|
;; Emacs-Guix is distributed in the hope that it will be useful,
|
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
;;
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
|
;; along with Emacs-Guix. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
|
|
;; This file provides an interface to display store items in 'list' and
|
|
|
|
|
;; 'info' buffers.
|
|
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
|
|
(require 'cl-lib)
|
|
|
|
|
(require 'ffap)
|
2018-12-11 16:12:52 +01:00
|
|
|
|
(require 'dash)
|
2018-08-05 15:50:15 +02:00
|
|
|
|
(require 'bui)
|
|
|
|
|
(require 'guix-package)
|
|
|
|
|
(require 'guix-guile)
|
|
|
|
|
(require 'guix-repl)
|
2018-08-05 22:38:49 +02:00
|
|
|
|
(require 'guix-misc)
|
2018-08-05 15:50:15 +02:00
|
|
|
|
(require 'guix-utils)
|
|
|
|
|
(require 'guix-auto-mode) ; for regexps
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Misc functionality (move to "guix-store.el"?)
|
|
|
|
|
|
|
|
|
|
(defun guix-store-file-name-read ()
|
|
|
|
|
"Read from minibuffer a store file name."
|
|
|
|
|
(let* ((file (ffap-file-at-point))
|
|
|
|
|
(file (and file
|
|
|
|
|
(string-match-p guix-store-directory file)
|
|
|
|
|
file)))
|
|
|
|
|
;; Read a string (not a file name), since using completions for
|
|
|
|
|
;; "/gnu/store" would probably be too much.
|
|
|
|
|
(read-string "File from store: " file)))
|
|
|
|
|
|
|
|
|
|
(defvar guix-store-file-name-regexp
|
|
|
|
|
(rx-to-string
|
|
|
|
|
`(and ,guix-store-directory "/"
|
|
|
|
|
(regexp ,guix-hash-regexp) "-"
|
|
|
|
|
(group (* any)))
|
|
|
|
|
t)
|
|
|
|
|
"Regexp matching a string with store file name.
|
|
|
|
|
The first parenthesized group is the name itself (placed right
|
|
|
|
|
after the hash part).")
|
|
|
|
|
|
|
|
|
|
(defun guix-store-file-name< (a b)
|
|
|
|
|
"Return non-nil if store file name A is less than B.
|
|
|
|
|
This is similar to `string<', except the '/gnu/store/...-' parts
|
|
|
|
|
of the file names are ignored."
|
|
|
|
|
(cl-flet ((name (str)
|
|
|
|
|
(and (string-match guix-store-file-name-regexp str)
|
|
|
|
|
(match-string 1 str))))
|
|
|
|
|
(string-lessp (name a) (name b))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Common for both interfaces
|
|
|
|
|
|
|
|
|
|
(guix-define-groups store-item)
|
|
|
|
|
|
|
|
|
|
(bui-define-entry-type guix-store-item
|
|
|
|
|
:message-function 'guix-store-item-message
|
|
|
|
|
:titles '((id . "File name")
|
2018-08-09 17:12:44 +02:00
|
|
|
|
(time . "Registration time")
|
|
|
|
|
(number-of-derivers . "Derivers")
|
|
|
|
|
(number-of-references . "References")
|
|
|
|
|
(number-of-referrers . "Referrers")
|
|
|
|
|
(number-of-requisites . "Requisites")))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
2018-12-11 16:12:52 +01:00
|
|
|
|
(defcustom guix-store-item-show-total-size t
|
|
|
|
|
"If non-nil, show total size after displaying store items."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'guix-store-item)
|
|
|
|
|
|
2018-08-08 16:07:47 +02:00
|
|
|
|
(defface guix-store-item-invalid
|
|
|
|
|
'((t :inherit font-lock-warning-face))
|
|
|
|
|
"Face used for store items that are not valid."
|
|
|
|
|
:group 'guix-store-item-faces)
|
|
|
|
|
|
2018-08-05 15:50:15 +02:00
|
|
|
|
(defun guix-store-item-get-entries (search-type
|
|
|
|
|
&optional search-values params)
|
|
|
|
|
"Receive 'store-item' entries.
|
|
|
|
|
SEARCH-TYPE may be one of the following symbols: `id', `live',
|
|
|
|
|
`dead', `referrers', `references', `derivers', `requisites',
|
|
|
|
|
`failures'."
|
|
|
|
|
(guix-eval-read
|
|
|
|
|
(guix-make-guile-expression
|
|
|
|
|
'store-item-sexps search-type search-values params)))
|
|
|
|
|
|
|
|
|
|
(defun guix-store-item-get-display (search-type &rest search-values)
|
|
|
|
|
"Search for store items and show results."
|
|
|
|
|
(apply #'bui-list-get-display-entries
|
|
|
|
|
'guix-store-item search-type search-values))
|
|
|
|
|
|
|
|
|
|
(defun guix-store-item-message (entries search-type &rest search-values)
|
|
|
|
|
"Display a message after showing store item ENTRIES."
|
|
|
|
|
(let ((count (length entries))
|
|
|
|
|
(val (car search-values)))
|
2018-12-11 16:12:52 +01:00
|
|
|
|
(cl-flet ((msg (str &rest args)
|
|
|
|
|
(if guix-store-item-show-total-size
|
|
|
|
|
(apply #'message
|
|
|
|
|
(concat str "\nTotal size: %s.")
|
|
|
|
|
(-snoc args
|
|
|
|
|
(guix-file-size-string
|
|
|
|
|
(guix-store-item-entries-size entries))))
|
|
|
|
|
(apply #'message str args ))))
|
|
|
|
|
(cl-case search-type
|
|
|
|
|
((id path)
|
|
|
|
|
(cl-case count
|
|
|
|
|
(0 (message "No info on the store item(s) found."))
|
|
|
|
|
(1 (msg "Store item '%s'." val))
|
|
|
|
|
(t (msg "%d store items displayed." count))))
|
|
|
|
|
(live (msg "%d live store items." count))
|
|
|
|
|
(dead (msg "%d dead store items." count))
|
|
|
|
|
(failures
|
2018-08-05 15:50:15 +02:00
|
|
|
|
(cl-case count
|
2018-12-11 16:12:52 +01:00
|
|
|
|
(0 (message "No failures found."))
|
|
|
|
|
(1 (msg "A single failure found."))
|
|
|
|
|
(t (msg "%d failures found." count))))
|
|
|
|
|
(t
|
|
|
|
|
(let ((type (symbol-name search-type))
|
|
|
|
|
(paths (mapconcat #'identity search-values ", ")))
|
|
|
|
|
(cl-case count
|
|
|
|
|
(0 (message "No %s of '%s' found." type paths))
|
|
|
|
|
(1 (msg "A single %s of '%s'."
|
|
|
|
|
;; Remove the trailing "s" from the search type
|
|
|
|
|
;; ("derivers" -> "deriver").
|
|
|
|
|
(substring type 0 (1- (length type)))
|
|
|
|
|
paths))
|
|
|
|
|
(t (msg "%d %s of '%s'." count type paths)))))))))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
2018-08-09 17:51:59 +02:00
|
|
|
|
(defun guix-store-item-delete (&rest file-names)
|
|
|
|
|
"Delete FILE-NAMES from the store."
|
|
|
|
|
(or file-names
|
|
|
|
|
(error "Nothing to delete"))
|
|
|
|
|
(when (or (not guix-operation-confirm)
|
|
|
|
|
(y-or-n-p
|
|
|
|
|
(let ((count (length file-names)))
|
|
|
|
|
(if (> count 1)
|
|
|
|
|
(format "Try to delete these %d store items? " count)
|
|
|
|
|
(format "Try to delete store item '%s'? "
|
|
|
|
|
(car file-names))))))
|
|
|
|
|
(guix-eval-in-repl
|
|
|
|
|
(apply #'guix-make-guile-expression
|
|
|
|
|
'guix-command "gc" "--delete" file-names)
|
|
|
|
|
(current-buffer))))
|
|
|
|
|
|
2018-12-11 16:12:52 +01:00
|
|
|
|
(defun guix-store-item-entries-size (entries)
|
|
|
|
|
"Return total size of store item ENTRIES."
|
|
|
|
|
(--reduce-from (+ acc
|
|
|
|
|
(or (bui-entry-non-void-value it 'size)
|
|
|
|
|
0))
|
|
|
|
|
0 entries))
|
|
|
|
|
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
;;; Store item 'info'
|
|
|
|
|
|
|
|
|
|
(bui-define-interface guix-store-item info
|
|
|
|
|
:mode-name "Store-Item-Info"
|
|
|
|
|
:buffer-name "*Guix Store Item Info*"
|
|
|
|
|
:get-entries-function 'guix-store-item-info-get-entries
|
2018-08-09 17:51:59 +02:00
|
|
|
|
:format '((id nil (guix-info-insert-file-name))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
nil
|
2018-08-08 16:07:47 +02:00
|
|
|
|
guix-store-item-info-insert-invalid
|
2018-08-05 15:50:15 +02:00
|
|
|
|
(size format guix-store-item-info-insert-size)
|
|
|
|
|
(time format (time))
|
2018-08-09 17:12:44 +02:00
|
|
|
|
(number-of-derivers
|
|
|
|
|
format guix-store-item-info-insert-number-of-derivers)
|
|
|
|
|
(number-of-references
|
|
|
|
|
format guix-store-item-info-insert-number-of-references)
|
|
|
|
|
(number-of-referrers
|
|
|
|
|
format guix-store-item-info-insert-number-of-referrers)
|
|
|
|
|
(number-of-requisites
|
|
|
|
|
format guix-store-item-info-insert-number-of-requisites)))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
(defvar guix-store-item-info-required-params
|
|
|
|
|
'(id)
|
|
|
|
|
"List of the required 'store-item' parameters.
|
|
|
|
|
These parameters are received from the Scheme side
|
|
|
|
|
along with the displayed parameters.
|
|
|
|
|
|
|
|
|
|
Do not remove `id' from this info as it is required for
|
|
|
|
|
identifying an entry.")
|
|
|
|
|
|
|
|
|
|
(defun guix-store-item-info-get-entries (search-type &rest search-values)
|
|
|
|
|
"Return 'store-item' entries for displaying them in 'info' buffer."
|
|
|
|
|
(guix-store-item-get-entries
|
|
|
|
|
search-type search-values
|
|
|
|
|
(cl-union guix-store-item-info-required-params
|
|
|
|
|
(bui-info-displayed-params 'guix-store-item))))
|
|
|
|
|
|
2018-08-09 17:51:59 +02:00
|
|
|
|
(defun guix-info-insert-file-name (file-name)
|
|
|
|
|
"Insert store item FILE-NAME at point."
|
|
|
|
|
(bui-insert-button file-name 'bui-file)
|
|
|
|
|
(bui-insert-indent)
|
|
|
|
|
(bui-insert-action-button
|
|
|
|
|
"Delete"
|
|
|
|
|
(lambda (btn)
|
|
|
|
|
(guix-store-item-delete (button-get btn 'file-name)))
|
|
|
|
|
(format "Delete '%s' from the store" file-name)
|
|
|
|
|
'file-name file-name))
|
|
|
|
|
|
2018-08-05 15:50:15 +02:00
|
|
|
|
(defun guix-store-item-info-insert-size (size entry)
|
|
|
|
|
"Insert SIZE of the store item ENTRY at point."
|
2018-08-09 17:39:15 +02:00
|
|
|
|
(bui-insert-non-nil size
|
2018-12-10 20:52:13 +01:00
|
|
|
|
(insert (guix-file-size-string size))
|
2018-08-09 17:39:15 +02:00
|
|
|
|
(bui-insert-indent)
|
|
|
|
|
(let ((file-name (bui-entry-id entry)))
|
|
|
|
|
(bui-insert-action-button
|
|
|
|
|
"Size"
|
|
|
|
|
(lambda (btn)
|
|
|
|
|
(guix-package-size (button-get btn 'file-name)
|
|
|
|
|
(guix-read-package-size-type)))
|
|
|
|
|
(format "Show full size info on '%s'" file-name)
|
|
|
|
|
'file-name file-name))))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
(defun guix-info-insert-store-item (file-name)
|
|
|
|
|
"Insert store FILE-NAME at point."
|
|
|
|
|
(bui-insert-button file-name 'bui-file)
|
|
|
|
|
(bui-insert-indent)
|
|
|
|
|
(bui-insert-action-button
|
|
|
|
|
"Store item"
|
|
|
|
|
(lambda (btn)
|
|
|
|
|
(guix-store-item (button-get btn 'file-name)))
|
|
|
|
|
(format "Show more info on %s" file-name)
|
|
|
|
|
'file-name file-name))
|
|
|
|
|
|
|
|
|
|
(defun guix-info-insert-store-items (file-names)
|
|
|
|
|
"Insert store FILE-NAMES at point.
|
|
|
|
|
FILE-NAMES can be a list or a single string."
|
|
|
|
|
(bui-insert-non-nil file-names
|
|
|
|
|
(dolist (file-name (guix-list-maybe file-names))
|
|
|
|
|
(bui-newline)
|
|
|
|
|
(bui-insert-indent)
|
|
|
|
|
(guix-info-insert-store-item file-name))))
|
|
|
|
|
|
2018-08-08 16:07:47 +02:00
|
|
|
|
(defun guix-store-item-info-insert-invalid (entry)
|
|
|
|
|
"Insert a text if the store item ENTRY is not valid."
|
|
|
|
|
(when (bui-entry-non-void-value entry 'invalid)
|
2018-08-10 14:56:06 +02:00
|
|
|
|
(if (not (file-exists-p (bui-entry-id entry)))
|
|
|
|
|
(insert "This file does not exist.\n\n")
|
|
|
|
|
(insert "Guix daemon says this path is ")
|
|
|
|
|
(bui-format-insert "not valid" 'guix-store-item-invalid)
|
|
|
|
|
(insert ".\nApparently, you may remove it from the store.\n\n"))))
|
2018-08-08 16:07:47 +02:00
|
|
|
|
|
2018-08-09 17:12:44 +02:00
|
|
|
|
(defun guix-store-item-info-insert-type-button (type entry)
|
|
|
|
|
"Insert button to display TYPE of store item ENTRY at point.
|
|
|
|
|
TYPE should be one of the following symbols: `derivers',
|
|
|
|
|
`references', `referrers', `requisites'."
|
|
|
|
|
(let ((file-name (bui-entry-id entry))
|
|
|
|
|
(type-str (symbol-name type)))
|
|
|
|
|
(bui-insert-action-button
|
|
|
|
|
"Show"
|
|
|
|
|
(lambda (btn)
|
|
|
|
|
(guix-store-item-get-display (button-get btn 'search-type)
|
|
|
|
|
(button-get btn 'file-name)))
|
|
|
|
|
(format "Show %s of '%s'" type-str file-name)
|
|
|
|
|
'search-type type
|
|
|
|
|
'file-name file-name)))
|
|
|
|
|
|
|
|
|
|
(defmacro guix-store-item-info-define-insert-number (type)
|
|
|
|
|
"Define a function to insert number of TYPE.
|
2018-08-12 21:49:44 +02:00
|
|
|
|
See `guix-store-item-info-insert-type-button' for the meaning of TYPE."
|
2018-08-09 17:12:44 +02:00
|
|
|
|
(let* ((type-str (symbol-name type))
|
|
|
|
|
(name (intern (concat "guix-store-item-info-insert-number-of-"
|
|
|
|
|
type-str)))
|
|
|
|
|
(desc (concat "Insert NUMBER of " type-str
|
|
|
|
|
" of store item ENTRY at point.")))
|
|
|
|
|
`(defun ,name (number entry)
|
|
|
|
|
,desc
|
|
|
|
|
(bui-insert-non-nil number
|
|
|
|
|
(bui-format-insert number)
|
|
|
|
|
(unless (= 0 number)
|
|
|
|
|
(bui-insert-indent)
|
|
|
|
|
(guix-store-item-info-insert-type-button ',type entry))))))
|
|
|
|
|
|
|
|
|
|
(guix-store-item-info-define-insert-number derivers)
|
|
|
|
|
(guix-store-item-info-define-insert-number references)
|
|
|
|
|
(guix-store-item-info-define-insert-number referrers)
|
|
|
|
|
(guix-store-item-info-define-insert-number requisites)
|
|
|
|
|
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
;;; Store item 'list'
|
|
|
|
|
|
|
|
|
|
(bui-define-interface guix-store-item list
|
|
|
|
|
:mode-name "Store-Item-List"
|
|
|
|
|
:buffer-name "*Guix Store Items*"
|
|
|
|
|
:get-entries-function 'guix-store-item-list-get-entries
|
|
|
|
|
:describe-function 'guix-store-item-list-describe
|
2018-08-08 16:07:47 +02:00
|
|
|
|
:format '((id guix-store-item-list-get-name 65
|
|
|
|
|
guix-store-item-list-sort-file-names-0)
|
2018-08-05 15:50:15 +02:00
|
|
|
|
(size nil 20 bui-list-sort-numerically-1 :right-align t))
|
2018-08-05 22:38:49 +02:00
|
|
|
|
:hint 'guix-store-item-list-hint
|
2018-08-05 15:50:15 +02:00
|
|
|
|
:sort-key '(size . t)
|
2018-08-05 22:38:49 +02:00
|
|
|
|
:marks '((delete . ?D)))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
(defvar guix-store-item-list-required-params
|
|
|
|
|
'(id)
|
|
|
|
|
"List of the required 'store-item' parameters.
|
|
|
|
|
These parameters are received from the Scheme side
|
|
|
|
|
along with the displayed parameters.
|
|
|
|
|
|
|
|
|
|
Do not remove `id' from this list as it is required for
|
|
|
|
|
identifying an entry.")
|
|
|
|
|
|
|
|
|
|
(let ((map guix-store-item-list-mode-map))
|
2018-08-05 22:38:49 +02:00
|
|
|
|
(define-key map (kbd "e") 'guix-store-item-list-edit)
|
|
|
|
|
(define-key map (kbd "d") 'guix-store-item-list-mark-delete)
|
2018-08-12 21:49:44 +02:00
|
|
|
|
(define-key map (kbd "f") 'guix-store-item-list-referrers)
|
|
|
|
|
(define-key map (kbd "F") 'guix-store-item-list-references)
|
|
|
|
|
(define-key map (kbd "D") 'guix-store-item-list-derivers)
|
|
|
|
|
(define-key map (kbd "R") 'guix-store-item-list-requisites)
|
2018-12-11 16:22:27 +01:00
|
|
|
|
(define-key map (kbd "z") 'guix-store-item-list-size)
|
2018-08-05 22:38:49 +02:00
|
|
|
|
(define-key map (kbd "x") 'guix-store-item-list-execute))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
(defvar guix-store-item-list-default-hint
|
2018-08-05 22:38:49 +02:00
|
|
|
|
'(("\\[guix-store-item-list-edit]") " go to the current store item;\n"
|
2018-08-12 21:49:44 +02:00
|
|
|
|
("\\[guix-store-item-list-derivers]") " show derivers; "
|
|
|
|
|
("\\[guix-store-item-list-requisites]") " show requisites;\n"
|
|
|
|
|
("\\[guix-store-item-list-referrers]") " show referrers; "
|
|
|
|
|
("\\[guix-store-item-list-references]") " show references;\n"
|
2018-08-05 22:38:49 +02:00
|
|
|
|
("\\[guix-store-item-list-mark-delete]") " mark for deletion; "
|
2018-12-11 16:22:27 +01:00
|
|
|
|
("\\[guix-store-item-list-execute]") " execute operation (deletions);\n"
|
|
|
|
|
("\\[guix-store-item-list-size]") " show size of the marked items;\n"))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
(defun guix-store-item-list-hint ()
|
|
|
|
|
(bui-format-hints
|
|
|
|
|
guix-store-item-list-default-hint
|
|
|
|
|
(bui-default-hint)))
|
|
|
|
|
|
|
|
|
|
(defun guix-store-item-list-get-entries (search-type &rest search-values)
|
|
|
|
|
"Return 'store-item' entries for displaying them in 'list' buffer."
|
|
|
|
|
(guix-store-item-get-entries
|
|
|
|
|
search-type search-values
|
|
|
|
|
(cl-union guix-store-item-list-required-params
|
|
|
|
|
(bui-list-displayed-params 'guix-store-item))))
|
|
|
|
|
|
2018-08-08 16:07:47 +02:00
|
|
|
|
(defun guix-store-item-list-get-name (name entry)
|
|
|
|
|
"Return NAME of the store item ENTRY.
|
|
|
|
|
Colorize it with an appropriate face if needed."
|
|
|
|
|
(bui-get-string
|
|
|
|
|
name
|
|
|
|
|
(and (bui-entry-non-void-value entry 'invalid)
|
|
|
|
|
'guix-store-item-invalid)))
|
|
|
|
|
|
2018-08-05 15:50:15 +02:00
|
|
|
|
(defun guix-store-item-list-sort-file-names-0 (a b)
|
|
|
|
|
"Compare column 0 of tabulated entries A and B numerically.
|
|
|
|
|
This function is used for sort predicates for `tabulated-list-format'.
|
|
|
|
|
Return non-nil, if B is bigger than A."
|
|
|
|
|
(cl-flet ((name (entry) (aref (cadr entry) 0)))
|
|
|
|
|
(guix-store-file-name< (name a) (name b))))
|
|
|
|
|
|
|
|
|
|
(defun guix-store-item-list-describe (&rest ids)
|
|
|
|
|
"Describe store-items with IDS (list of identifiers)."
|
|
|
|
|
(bui-get-display-entries 'guix-store-item 'info (cons 'id ids)))
|
|
|
|
|
|
|
|
|
|
(defun guix-store-item-list-edit ()
|
|
|
|
|
"Go to the current store item."
|
|
|
|
|
(interactive)
|
|
|
|
|
(guix-find-file (bui-list-current-id)))
|
|
|
|
|
|
2018-08-05 22:38:49 +02:00
|
|
|
|
(defun guix-store-item-list-mark-delete (&optional arg)
|
|
|
|
|
"Mark the current store-item for deletion and move to the next line.
|
|
|
|
|
With ARG, mark all store-items for deletion."
|
|
|
|
|
(interactive "P")
|
|
|
|
|
(if arg
|
|
|
|
|
(bui-list-mark-all 'delete)
|
|
|
|
|
(bui-list--mark 'delete t)))
|
|
|
|
|
|
|
|
|
|
(defun guix-store-item-list-execute ()
|
|
|
|
|
"Delete store items marked with '\\[guix-store-item-list-mark-delete]'."
|
|
|
|
|
(interactive)
|
|
|
|
|
(let ((marked (bui-list-get-marked-id-list 'delete)))
|
|
|
|
|
(or marked
|
|
|
|
|
(user-error "No store items marked for deletion"))
|
2018-08-09 17:51:59 +02:00
|
|
|
|
(apply #'guix-store-item-delete marked)))
|
2018-08-05 22:38:49 +02:00
|
|
|
|
|
2018-12-11 16:22:27 +01:00
|
|
|
|
(defun guix-store-item-list-size ()
|
|
|
|
|
"Show size of the marked (or current) store items.
|
|
|
|
|
Store items can be marked with any mark."
|
|
|
|
|
(interactive)
|
|
|
|
|
(let* ((marked (bui-list-marked-or-current))
|
|
|
|
|
(count (length marked))
|
|
|
|
|
(msg (if (= 1 count)
|
|
|
|
|
(format "Size of '%s': %%s." (car marked))
|
|
|
|
|
(format "Size of %d marked items: %%s." count)))
|
|
|
|
|
(size (guix-file-size-string
|
|
|
|
|
(guix-store-item-entries-size
|
|
|
|
|
(bui-entries-by-ids (bui-current-entries) marked)))))
|
|
|
|
|
(message msg size)))
|
|
|
|
|
|
2018-08-12 21:49:44 +02:00
|
|
|
|
(defmacro guix-store-item-list-define-show-items (type)
|
|
|
|
|
"Define a function to show items by TYPE.
|
|
|
|
|
See `guix-store-item-list-insert-type-button' for the meaning of TYPE."
|
|
|
|
|
(let* ((type-str (symbol-name type))
|
|
|
|
|
(name (intern (concat "guix-store-item-list-" type-str)))
|
|
|
|
|
(desc (concat "Display " type-str
|
|
|
|
|
" of the marked (or current) store items.")))
|
|
|
|
|
`(defun ,name ()
|
|
|
|
|
,desc
|
|
|
|
|
(interactive)
|
|
|
|
|
(apply #'guix-store-item-get-display ',type
|
2018-12-11 16:00:35 +01:00
|
|
|
|
(bui-list-marked-or-current 'general)))))
|
2018-08-12 21:49:44 +02:00
|
|
|
|
|
|
|
|
|
(guix-store-item-list-define-show-items derivers)
|
|
|
|
|
(guix-store-item-list-define-show-items references)
|
|
|
|
|
(guix-store-item-list-define-show-items referrers)
|
|
|
|
|
(guix-store-item-list-define-show-items requisites)
|
|
|
|
|
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
;;; Interactive commands
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun guix-store-item (&rest file-names)
|
|
|
|
|
"Display store items with FILE-NAMES.
|
|
|
|
|
Interactively, prompt for a single file name."
|
|
|
|
|
(interactive (list (guix-store-file-name-read)))
|
2018-08-09 17:28:58 +02:00
|
|
|
|
(apply #'guix-assert-files-exist file-names)
|
2018-08-05 15:50:15 +02:00
|
|
|
|
(apply #'guix-store-item-get-display 'id file-names))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2018-08-12 21:41:50 +02:00
|
|
|
|
(defun guix-store-item-referrers (&rest file-names)
|
|
|
|
|
"Display referrers of the FILE-NAMES store item.
|
|
|
|
|
This is analogous to 'guix gc --referrers FILE-NAMES' shell
|
2018-08-05 15:50:15 +02:00
|
|
|
|
command. See Info node `(guix) Invoking guix gc'."
|
|
|
|
|
(interactive (list (guix-store-file-name-read)))
|
2018-08-12 21:41:50 +02:00
|
|
|
|
(apply #'guix-assert-files-exist file-names)
|
|
|
|
|
(apply #'guix-store-item-get-display 'referrers file-names))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2018-08-12 21:41:50 +02:00
|
|
|
|
(defun guix-store-item-references (&rest file-names)
|
|
|
|
|
"Display references of the FILE-NAMES store item.
|
|
|
|
|
This is analogous to 'guix gc --references FILE-NAMES' shell
|
2018-08-05 15:50:15 +02:00
|
|
|
|
command. See Info node `(guix) Invoking guix gc'."
|
|
|
|
|
(interactive (list (guix-store-file-name-read)))
|
2018-08-12 21:41:50 +02:00
|
|
|
|
(apply #'guix-assert-files-exist file-names)
|
|
|
|
|
(apply #'guix-store-item-get-display 'references file-names))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2018-08-12 21:41:50 +02:00
|
|
|
|
(defun guix-store-item-requisites (&rest file-names)
|
|
|
|
|
"Display requisites of the FILE-NAMES store item.
|
|
|
|
|
This is analogous to 'guix gc --requisites FILE-NAMES' shell
|
2018-08-05 15:50:15 +02:00
|
|
|
|
command. See Info node `(guix) Invoking guix gc'."
|
|
|
|
|
(interactive (list (guix-store-file-name-read)))
|
2018-08-12 21:41:50 +02:00
|
|
|
|
(apply #'guix-assert-files-exist file-names)
|
|
|
|
|
(apply #'guix-store-item-get-display 'requisites file-names))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
2018-08-12 21:41:50 +02:00
|
|
|
|
(defun guix-store-item-derivers (&rest file-names)
|
|
|
|
|
"Display derivers of the FILE-NAMES store item.
|
|
|
|
|
This is analogous to 'guix gc --derivers FILE-NAMES' shell
|
2018-08-05 15:50:15 +02:00
|
|
|
|
command. See Info node `(guix) Invoking guix gc'."
|
|
|
|
|
(interactive (list (guix-store-file-name-read)))
|
2018-08-12 21:41:50 +02:00
|
|
|
|
(apply #'guix-assert-files-exist file-names)
|
|
|
|
|
(apply #'guix-store-item-get-display 'derivers file-names))
|
2018-08-05 15:50:15 +02:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun guix-store-failures ()
|
|
|
|
|
"Display store items corresponding to cached build failures.
|
|
|
|
|
This is analogous to 'guix gc --list-failures' shell command.
|
|
|
|
|
See Info node `(guix) Invoking guix gc'."
|
|
|
|
|
(interactive)
|
|
|
|
|
(guix-store-item-get-display 'failures))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun guix-store-live-items ()
|
|
|
|
|
"Display live store items.
|
|
|
|
|
This is analogous to 'guix gc --list-live' shell command.
|
|
|
|
|
See Info node `(guix) Invoking guix gc'."
|
|
|
|
|
(interactive)
|
|
|
|
|
(guix-store-item-get-display 'live))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun guix-store-dead-items ()
|
|
|
|
|
"Display dead store items.
|
|
|
|
|
This is analogous to 'guix gc --list-dead' shell command.
|
|
|
|
|
See Info node `(guix) Invoking guix gc'."
|
|
|
|
|
(interactive)
|
|
|
|
|
(guix-store-item-get-display 'dead))
|
|
|
|
|
|
|
|
|
|
(provide 'guix-ui-store-item)
|
|
|
|
|
|
|
|
|
|
;;; guix-ui-store-item.el ends here
|