summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am6
-rw-r--r--configure.ac4
-rw-r--r--doc/guix.texi57
-rw-r--r--guix-gc.in183
-rw-r--r--po/POTFILES.in1
-rw-r--r--tests/guix-gc.sh54
7 files changed, 299 insertions, 7 deletions
diff --git a/.gitignore b/.gitignore
index b6786d212b5..0b21a03ecee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -64,3 +64,4 @@ stamp-h[0-9]
64/nix/scripts/list-runtime-roots 64/nix/scripts/list-runtime-roots
65/test-env 65/test-env
66/nix/nix-setuid-helper/nix-setuid-helper.cc 66/nix/nix-setuid-helper/nix-setuid-helper.cc
67/guix-gc
diff --git a/Makefile.am b/Makefile.am
index 805ce446bd1..7ad34f1787a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
1# Guix --- Nix package management from Guile. -*- coding: utf-8 -*- 1# Guix --- Nix package management from Guile. -*- coding: utf-8 -*-
2# Copyright (C) 2012 Ludovic Courtès <ludo@gnu.org> 2# Copyright (C) 2012, 2013 Ludovic Courtès <ludo@gnu.org>
3# 3#
4# This file is part of Guix. 4# This file is part of Guix.
5# 5#
@@ -20,7 +20,8 @@ bin_SCRIPTS = \
20 guix-build \ 20 guix-build \
21 guix-download \ 21 guix-download \
22 guix-import \ 22 guix-import \
23 guix-package 23 guix-package \
24 guix-gc
24 25
25MODULES = \ 26MODULES = \
26 guix/base32.scm \ 27 guix/base32.scm \
@@ -189,6 +190,7 @@ TESTS = \
189 tests/union.scm \ 190 tests/union.scm \
190 tests/guix-build.sh \ 191 tests/guix-build.sh \
191 tests/guix-download.sh \ 192 tests/guix-download.sh \
193 tests/guix-gc.sh \
192 tests/guix-package.sh 194 tests/guix-package.sh
193 195
194TEST_EXTENSIONS = .scm .sh 196TEST_EXTENSIONS = .scm .sh
diff --git a/configure.ac b/configure.ac
index bebb9885c49..0c3a9e5f6f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -114,10 +114,12 @@ AC_CONFIG_FILES([Makefile
114 guix-download 114 guix-download
115 guix-import 115 guix-import
116 guix-package 116 guix-package
117 guix-gc
117 pre-inst-env 118 pre-inst-env
118 test-env]) 119 test-env])
119 120
120AC_CONFIG_COMMANDS([commands-exec], 121AC_CONFIG_COMMANDS([commands-exec],
121 [chmod +x guix-build guix-download guix-import guix-package pre-inst-env test-env]) 122 [chmod +x guix-build guix-download guix-import guix-package guix-gc \
123 pre-inst-env test-env])
122 124
123AC_OUTPUT 125AC_OUTPUT
diff --git a/doc/guix.texi b/doc/guix.texi
index 21f6d87b3a4..2ca1496bacb 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -43,7 +43,7 @@ Documentation License''.
43@copying 43@copying
44This manual documents GNU Guix version @value{VERSION}. 44This manual documents GNU Guix version @value{VERSION}.
45 45
46Copyright (C) 2012 Ludovic Courtès 46Copyright (C) 2012, 2013 Ludovic Courtès
47 47
48Permission is granted to copy, distribute and/or modify this document 48Permission is granted to copy, distribute and/or modify this document
49under the terms of the GNU Free Documentation License, Version 1.3 or 49under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -133,6 +133,7 @@ management tools it provides.
133@menu 133@menu
134* Features:: How Guix will make your life brighter. 134* Features:: How Guix will make your life brighter.
135* Invoking guix-package:: Package installation, removal, etc. 135* Invoking guix-package:: Package installation, removal, etc.
136* Invoking guix-gc:: Running the garbage collector.
136@end menu 137@end menu
137 138
138@node Features 139@node Features
@@ -172,9 +173,10 @@ of their profile, which was known to work well.
172 173
173All those packages in the package store may be @emph{garbage-collected}. 174All those packages in the package store may be @emph{garbage-collected}.
174Guix can determine which packages are still referenced by the user 175Guix can determine which packages are still referenced by the user
175profiles, and remove those that are provably no longer referenced. 176profiles, and remove those that are provably no longer referenced
176Users may also explicitly remove old generations of their profile so 177(@pxref{Invoking guix-gc}). Users may also explicitly remove old
177that the packages they refer to can be collected. 178generations of their profile so that the packages they refer to can be
179collected.
178 180
179Finally, Guix takes a @dfn{purely functional} approach to package 181Finally, Guix takes a @dfn{purely functional} approach to package
180management, as described in the introduction (@pxref{Introduction}). 182management, as described in the introduction (@pxref{Introduction}).
@@ -275,6 +277,53 @@ its version string, and the source location of its definition.
275@end table 277@end table
276 278
277 279
280@node Invoking guix-gc
281@section Invoking @command{guix-gc}
282
283@cindex garbage collector
284Packages that are installed but not used may be @dfn{garbage-collected}.
285The @command{guix-gc} command allows users to explicitly run the garbage
286collector to reclaim space from the @file{/nix/store} directory.
287
288The garbage collector has a set of known @dfn{roots}: any file under
289@file{/nix/store} reachable from a root is considered @dfn{live} and
290cannot be deleted; any other file is considered @dfn{dead} and may be
291deleted. The set of garbage collector roots includes default user
292profiles, and may be augmented with @command{guix-build --root}, for
293example (@pxref{Invoking guix-build}).
294
295The @command{guix-gc} command has three mode of operations: it can be
296used to garbage-collect any dead files (the default), to delete specific
297files (the @code{--delete} option), or to print garbage-collector
298information. The available options are listed below:
299
300@table @code
301@item --collect-garbage[=@var{min}]
302@itemx -C [@var{min}]
303Collect garbage---i.e., unreachable @file{/nix/store} files and
304sub-directories. This is the default operation when no option is
305specified.
306
307When @var{min} is given, stop once @var{min} bytes have been collected.
308@var{min} may be a number of bytes, or it may include a unit as a
309suffix, such as @code{MiB} for mebibytes and @code{GB} for gigabytes.
310
311When @var{min} is omitted, collect all the garbage.
312
313@item --delete
314@itemx -d
315Attempt to delete all the store files and directories specified as
316arguments. This fails if some of the files are not in the store, or if
317they are still live.
318
319@item --list-dead
320Show the list of dead files and directories still present in the
321store---i.e., files and directories no longer reachable from any root.
322
323@item --list-live
324Show the list of live store files and directories.
325@end table
326
278 327
279@c ********************************************************************* 328@c *********************************************************************
280@node Programming Interface 329@node Programming Interface
diff --git a/guix-gc.in b/guix-gc.in
new file mode 100644
index 00000000000..4e2da697f03
--- /dev/null
+++ b/guix-gc.in
@@ -0,0 +1,183 @@
1#!/bin/sh
2# aside from this initial boilerplate, this is actually -*- scheme -*- code
3
4prefix="@prefix@"
5datarootdir="@datarootdir@"
6
7GUILE_LOAD_COMPILED_PATH="@guilemoduledir@:$GUILE_LOAD_COMPILED_PATH"
8export GUILE_LOAD_COMPILED_PATH
9
10main='(module-ref (resolve-interface '\''(guix-gc)) '\'guix-gc')'
11exec ${GUILE-@GUILE@} -L "@guilemoduledir@" -l "$0" \
12 -c "(apply $main (cdr (command-line)))" "$@"
13!#
14;;; Guix --- Nix package management from Guile. -*- coding: utf-8 -*-
15;;; Copyright (C) 2012, 2013 Ludovic Courtès <ludo@gnu.org>
16;;;
17;;; This file is part of Guix.
18;;;
19;;; Guix is free software; you can redistribute it and/or modify it
20;;; under the terms of the GNU General Public License as published by
21;;; the Free Software Foundation; either version 3 of the License, or (at
22;;; your option) any later version.
23;;;
24;;; Guix is distributed in the hope that it will be useful, but
25;;; WITHOUT ANY WARRANTY; without even the implied warranty of
26;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27;;; GNU General Public License for more details.
28;;;
29;;; You should have received a copy of the GNU General Public License
30;;; along with Guix. If not, see <http://www.gnu.org/licenses/>.
31
32(define-module (guix-gc)
33 #:use-module (guix ui)
34 #:use-module (guix store)
35 #:use-module (ice-9 match)
36 #:use-module (srfi srfi-1)
37 #:use-module (srfi srfi-26)
38 #:use-module (srfi srfi-37)
39 #:export (guix-gc))
40
41
42;;;
43;;; Command-line options.
44;;;
45
46(define %default-options
47 ;; Alist of default option values.
48 `((action . collect-garbage)))
49
50(define (show-help)
51 (display (_ "Usage: guix-gc [OPTION]... PATHS...
52Invoke the garbage collector.\n"))
53 (display (_ "
54 -C, --collect-garbage[=MIN]
55 collect at least MIN bytes of garbage"))
56 (display (_ "
57 -d, --delete attempt to delete PATHS"))
58 (display (_ "
59 --list-dead list dead paths"))
60 (display (_ "
61 --list-live list live paths"))
62 (newline)
63 (display (_ "
64 -h, --help display this help and exit"))
65 (display (_ "
66 -V, --version display version information and exit"))
67 (newline)
68 (show-bug-report-information))
69
70(define (size->number str)
71 "Convert STR, a storage measurement representation such as \"1024\" or
72\"1MiB\", to a number of bytes. Raise an error if STR could not be
73interpreted."
74 (define unit-pos
75 (string-rindex str char-set:digit))
76
77 (define unit
78 (and unit-pos (substring str (+ 1 unit-pos))))
79
80 (let* ((numstr (if unit-pos
81 (substring str 0 (+ 1 unit-pos))
82 str))
83 (num (string->number numstr)))
84 (if num
85 (* num
86 (match unit
87 ("KiB" (expt 2 10))
88 ("MiB" (expt 2 20))
89 ("GiB" (expt 2 30))
90 ("TiB" (expt 2 40))
91 ("KB" (expt 10 3))
92 ("MB" (expt 10 6))
93 ("GB" (expt 10 9))
94 ("TB" (expt 10 12))
95 ("" 1)
96 (_
97 (format (current-error-port) (_ "error: unknown unit: ~a~%")
98 unit)
99 (exit 1))))
100 (begin
101 (format (current-error-port)
102 (_ "error: invalid number: ~a") numstr)
103 (exit 1)))))
104
105(define %options
106 ;; Specification of the command-line options.
107 (list (option '(#\h "help") #f #f
108 (lambda args
109 (show-help)
110 (exit 0)))
111 (option '(#\V "version") #f #f
112 (lambda args
113 (show-version-and-exit "guix-gc")))
114
115 (option '(#\C "collect-garbage") #f #t
116 (lambda (opt name arg result)
117 (let ((result (alist-cons 'action 'collect-garbage
118 (alist-delete 'action result))))
119 (match arg
120 ((? string?)
121 (let ((amount (size->number arg)))
122 (if arg
123 (alist-cons 'min-freed amount result)
124 (begin
125 (format (current-error-port)
126 (_ "error: invalid amount of storage: ~a~%")
127 arg)
128 (exit 1)))))
129 (#f result)))))
130 (option '(#\d "delete") #f #f
131 (lambda (opt name arg result)
132 (alist-cons 'action 'delete
133 (alist-delete 'action result))))
134 (option '("list-dead") #f #f
135 (lambda (opt name arg result)
136 (alist-cons 'action 'list-dead
137 (alist-delete 'action result))))
138 (option '("list-live") #f #f
139 (lambda (opt name arg result)
140 (alist-cons 'action 'list-live
141 (alist-delete 'action result))))))
142
143
144;;;
145;;; Entry point.
146;;;
147
148(define (guix-gc . args)
149 (define (parse-options)
150 ;; Return the alist of option values.
151 (args-fold args %options
152 (lambda (opt name arg result)
153 (leave (_ "~A: unrecognized option~%") name))
154 (lambda (arg result)
155 (alist-cons 'argument arg result))
156 %default-options))
157
158 (setlocale LC_ALL "")
159 (textdomain "guix")
160 (setvbuf (current-output-port) _IOLBF)
161 (setvbuf (current-error-port) _IOLBF)
162
163 (with-error-handling
164 (let ((opts (parse-options))
165 (store (open-connection)))
166 (case (assoc-ref opts 'action)
167 ((collect-garbage)
168 (let ((min-freed (assoc-ref opts 'min-freed)))
169 (if min-freed
170 (collect-garbage store min-freed)
171 (collect-garbage store))))
172 ((delete)
173 (let ((paths (filter-map (match-lambda
174 (('argument . arg) arg)
175 (_ #f))
176 opts)))
177 (delete-paths store paths)))
178 ((list-dead)
179 (for-each (cut simple-format #t "~a~%" <>)
180 (dead-paths store)))
181 ((list-live)
182 (for-each (cut simple-format #t "~a~%" <>)
183 (live-paths store)))))))
diff --git a/po/POTFILES.in b/po/POTFILES.in
index fbcd957a160..2ca98ed1b57 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -8,3 +8,4 @@ guix/ui.scm
8guix-build.in 8guix-build.in
9guix-download.in 9guix-download.in
10guix-package.in 10guix-package.in
11guix-gc.in
diff --git a/tests/guix-gc.sh b/tests/guix-gc.sh
new file mode 100644
index 00000000000..a216e6941cc
--- /dev/null
+++ b/tests/guix-gc.sh
@@ -0,0 +1,54 @@
1# Guix --- Nix package management from Guile. -*- coding: utf-8 -*-
2# Copyright (C) 2013 Ludovic Courtès <ludo@gnu.org>
3#
4# This file is part of Guix.
5#
6# 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.
10#
11# 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.
15#
16# You should have received a copy of the GNU General Public License
17# along with Guix. If not, see <http://www.gnu.org/licenses/>.
18
19#
20# Test the `guix-gc' command-line utility.
21#
22
23guix-gc --version
24
25trap "rm -f guix-gc-root" EXIT
26rm -f guix-gc-root
27
28# Add then reclaim a .drv file.
29drv="`guix-build idutils -d`"
30test -f "$drv"
31
32guix-gc --list-dead | grep "$drv"
33guix-gc --delete "$drv"
34! test -f "$drv"
35
36# Add a .drv, register it as a root.
37drv="`guix-build --root=guix-gc-root lsh -d`"
38test -f "$drv" && test -L guix-gc-root
39
40guix-gc --list-live | grep "$drv"
41if guix-gc --delete "$drv";
42then false; else true; fi
43
44rm guix-gc-root
45guix-gc --list-dead | grep "$drv"
46guix-gc --delete "$drv"
47! test -f "$drv"
48
49# Try a random collection.
50guix-gc -C 1KiB
51
52# Check trivial error cases.
53if guix-gc --delete /dev/null;
54then false; else true; fi