1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2012, 2013, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
4 ;;; This file is part of GNU Guix.
6 ;;; GNU Guix is free software; you can redistribute it and/or modify it
7 ;;; under the terms of the GNU General Public License as published by
8 ;;; the Free Software Foundation; either version 3 of the License, or (at
9 ;;; your option) any later version.
11 ;;; GNU Guix is distributed in the hope that it will be useful, but
12 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ;;; GNU General Public License for more details.
16 ;;; You should have received a copy of the GNU General Public License
17 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19 (define-module (guix scripts gc)
20 #:use-module (guix ui)
21 #:use-module (guix scripts)
22 #:use-module (guix store)
23 #:autoload (guix build syscalls) (statfs)
24 #:use-module (ice-9 match)
25 #:use-module (ice-9 regex)
26 #:use-module (srfi srfi-1)
27 #:use-module (srfi srfi-11)
28 #:use-module (srfi srfi-26)
29 #:use-module (srfi srfi-37)
34 ;;; Command-line options.
37 (define %default-options
38 ;; Alist of default option values.
39 `((action . collect-garbage)))
42 (display (G_ "Usage: guix gc [OPTION]... PATHS...
43 Invoke the garbage collector.\n"))
45 -C, --collect-garbage[=MIN]
46 collect at least MIN bytes of garbage"))
48 -F, --free-space=FREE attempt to reach FREE available space in the store"))
50 -d, --delete attempt to delete PATHS"))
52 --optimize optimize the store by deduplicating identical files"))
54 --list-dead list dead paths"))
56 --list-live list live paths"))
59 --references list the references of PATHS"))
61 -R, --requisites list the requisites of PATHS"))
63 --referrers list the referrers of PATHS"))
66 --verify[=OPTS] verify the integrity of the store; OPTS is a
67 comma-separated combination of 'repair' and
70 --list-failures list cached build failures"))
72 --clear-failures remove PATHS from the set of cached failures"))
75 -h, --help display this help and exit"))
77 -V, --version display version information and exit"))
79 (show-bug-report-information))
82 ;; Specification of the command-line options.
83 (list (option '(#\h "help") #f #f
87 (option '(#\V "version") #f #f
89 (show-version-and-exit "guix gc")))
91 (option '(#\C "collect-garbage") #f #t
92 (lambda (opt name arg result)
93 (let ((result (alist-cons 'action 'collect-garbage
94 (alist-delete 'action result))))
97 (let ((amount (size->number arg)))
99 (alist-cons 'min-freed amount result)
100 (leave (G_ "invalid amount of storage: ~a~%")
103 (option '(#\F "free-space") #t #f
104 (lambda (opt name arg result)
105 (alist-cons 'free-space (size->number arg) result)))
106 (option '(#\d "delete") #f #f
107 (lambda (opt name arg result)
108 (alist-cons 'action 'delete
109 (alist-delete 'action result))))
110 (option '("optimize") #f #f
111 (lambda (opt name arg result)
112 (alist-cons 'action 'optimize
113 (alist-delete 'action result))))
114 (option '("verify") #f #t
115 (let ((not-comma (char-set-complement (char-set #\,))))
116 (lambda (opt name arg result)
117 (let ((options (if arg
119 (string-tokenize arg not-comma))
121 (alist-cons 'action 'verify
122 (alist-cons 'verify-options options
123 (alist-delete 'action
125 (option '("list-dead") #f #f
126 (lambda (opt name arg result)
127 (alist-cons 'action 'list-dead
128 (alist-delete 'action result))))
129 (option '("list-live") #f #f
130 (lambda (opt name arg result)
131 (alist-cons 'action 'list-live
132 (alist-delete 'action result))))
133 (option '("references") #f #f
134 (lambda (opt name arg result)
135 (alist-cons 'action 'list-references
136 (alist-delete 'action result))))
137 (option '(#\R "requisites") #f #f
138 (lambda (opt name arg result)
139 (alist-cons 'action 'list-requisites
140 (alist-delete 'action result))))
141 (option '("referrers") #f #f
142 (lambda (opt name arg result)
143 (alist-cons 'action 'list-referrers
144 (alist-delete 'action result))))
145 (option '("list-failures") #f #f
146 (lambda (opt name arg result)
147 (alist-cons 'action 'list-failures
148 (alist-delete 'action result))))
149 (option '("clear-failures") #f #f
150 (lambda (opt name arg result)
151 (alist-cons 'action 'clear-failures
152 (alist-delete 'action result))))))
159 (define (guix-gc . args)
160 (define (parse-options)
161 ;; Return the alist of option values.
162 (args-fold* args %options
163 (lambda (opt name arg result)
164 (leave (G_ "~A: unrecognized option~%") name))
166 (alist-cons 'argument arg result))
169 (define (symlink-target file)
170 (let ((s (false-if-exception (lstat file))))
171 (if (and s (eq? 'symlink (stat:type s)))
172 (symlink-target (readlink file))
175 (define (store-directory file)
176 ;; Return the store directory that holds FILE if it's in the store,
177 ;; otherwise return FILE.
178 (or (and=> (string-match (string-append "^" (regexp-quote (%store-prefix))
181 (compose (cut string-append (%store-prefix) "/" <>)
182 (cut match:substring <> 1)))
185 (define (ensure-free-space store space)
186 ;; Attempt to have at least SPACE bytes available in STORE.
187 (let* ((fs (statfs (%store-prefix)))
188 (free (* (file-system-block-size fs)
189 (file-system-blocks-available fs))))
191 (info (G_ "already ~h bytes available on ~a, nothing to do~%")
192 free (%store-prefix))
193 (let ((to-free (- space free)))
194 (info (G_ "freeing ~h bytes~%") to-free)
195 (collect-garbage store to-free)))))
198 (let* ((opts (parse-options))
199 (store (open-connection))
200 (paths (filter-map (match-lambda
201 (('argument . arg) arg)
204 (define (assert-no-extra-arguments)
205 (unless (null? paths)
206 (leave (G_ "extraneous arguments: ~{~a ~}~%") paths)))
208 (define (list-relatives relatives)
209 (for-each (compose (lambda (path)
210 (for-each (cut simple-format #t "~a~%" <>)
211 (relatives store path)))
216 (case (assoc-ref opts 'action)
218 (assert-no-extra-arguments)
219 (let ((min-freed (assoc-ref opts 'min-freed))
220 (free-space (assoc-ref opts 'free-space)))
223 (ensure-free-space store free-space))
225 (let-values (((paths freed) (collect-garbage store min-freed)))
226 (info (G_ "freed ~h bytes~%") freed)))
228 (let-values (((paths freed) (collect-garbage store)))
229 (info (G_ "freed ~h bytes~%") freed))))))
231 (delete-paths store (map direct-store-path paths)))
233 (list-relatives references))
235 (list-relatives (lambda (store item)
236 (requisites store (list item)))))
238 (list-relatives referrers))
240 (assert-no-extra-arguments)
241 (optimize-store store))
243 (assert-no-extra-arguments)
244 (let ((options (assoc-ref opts 'verify-options)))
247 #:check-contents? (memq 'contents options)
248 #:repair? (memq 'repair options)))))
250 (for-each (cut simple-format #t "~a~%" <>)
251 (query-failed-paths store)))
253 (clear-failed-paths store (map direct-store-path paths)))
255 (for-each (cut simple-format #t "~a~%" <>)
258 (for-each (cut simple-format #t "~a~%" <>)
259 (live-paths store)))))))