gnu: automake: Update to 1.13.1.
[jackhill/guix/guix.git] / guix-package.in
CommitLineData
0afdc485
LC
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-package)) '\'guix-package')'
11exec ${GUILE-@GUILE@} -L "@guilemoduledir@" -l "$0" \
12 -c "(apply $main (cdr (command-line)))" "$@"
13!#
233e7676
LC
14;;; GNU Guix --- Functional package management for GNU
15;;; Copyright © 2012, 2013 Ludovic Courtès <ludo@gnu.org>
24e262f0 16;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
0afdc485 17;;;
233e7676 18;;; This file is part of GNU Guix.
0afdc485 19;;;
233e7676 20;;; GNU Guix is free software; you can redistribute it and/or modify it
0afdc485
LC
21;;; under the terms of the GNU General Public License as published by
22;;; the Free Software Foundation; either version 3 of the License, or (at
23;;; your option) any later version.
24;;;
233e7676 25;;; GNU Guix is distributed in the hope that it will be useful, but
0afdc485
LC
26;;; WITHOUT ANY WARRANTY; without even the implied warranty of
27;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28;;; GNU General Public License for more details.
29;;;
30;;; You should have received a copy of the GNU General Public License
233e7676 31;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
0afdc485
LC
32
33(define-module (guix-package)
cdd5d6f9 34 #:use-module (guix ui)
0afdc485
LC
35 #:use-module (guix store)
36 #:use-module (guix derivations)
37 #:use-module (guix packages)
38 #:use-module (guix utils)
a020d2a9 39 #:use-module (guix config)
0ec1af59 40 #:use-module ((guix build utils) #:select (directory-exists? mkdir-p))
0afdc485
LC
41 #:use-module (ice-9 ftw)
42 #:use-module (ice-9 format)
43 #:use-module (ice-9 match)
44 #:use-module (ice-9 regex)
45 #:use-module (srfi srfi-1)
46 #:use-module (srfi srfi-11)
47 #:use-module (srfi srfi-26)
48 #:use-module (srfi srfi-34)
49 #:use-module (srfi srfi-37)
59a43334 50 #:use-module (gnu packages)
1ffa7090
LC
51 #:use-module ((gnu packages base) #:select (guile-final))
52 #:use-module ((gnu packages bootstrap) #:select (%bootstrap-guile))
0afdc485
LC
53 #:export (guix-package))
54
0afdc485 55(define %store
c4d64534 56 (make-parameter #f))
0afdc485
LC
57
58\f
59;;;
60;;; User environment.
61;;;
62
63(define %user-environment-directory
64 (and=> (getenv "HOME")
65 (cut string-append <> "/.guix-profile")))
66
67(define %profile-directory
0ec1af59 68 (string-append (or (getenv "NIX_STATE_DIR") %state-directory) "/profiles/"
0afdc485
LC
69 (or (and=> (getenv "USER")
70 (cut string-append "per-user/" <>))
71 "default")))
72
73(define %current-profile
4aa52039
LC
74 ;; Call it `guix-profile', not `profile', to allow Guix profiles to
75 ;; coexist with Nix profiles.
76 (string-append %profile-directory "/guix-profile"))
0afdc485
LC
77
78(define (profile-manifest profile)
79 "Return the PROFILE's manifest."
80 (let ((manifest (string-append profile "/manifest")))
81 (if (file-exists? manifest)
82 (call-with-input-file manifest read)
83 '(manifest (version 0) (packages ())))))
84
85(define (manifest-packages manifest)
86 "Return the packages listed in MANIFEST."
87 (match manifest
88 (('manifest ('version 0) ('packages packages))
89 packages)
90 (_
91 (error "unsupported manifest format" manifest))))
92
24e262f0
LC
93(define (profile-regexp profile)
94 "Return a regular expression that matches PROFILE's name and number."
95 (make-regexp (string-append "^" (regexp-quote (basename profile))
96 "-([0-9]+)")))
97
9241172c
LC
98(define (profile-numbers profile)
99 "Return the list of generation numbers of PROFILE, or '(0) if no
100former profiles were found."
0afdc485
LC
101 (define* (scandir name #:optional (select? (const #t))
102 (entry<? (@ (ice-9 i18n) string-locale<?)))
103 ;; XXX: Bug-fix version introduced in Guile v2.0.6-62-g139ce19.
104 (define (enter? dir stat result)
105 (and stat (string=? dir name)))
106
107 (define (visit basename result)
108 (if (select? basename)
109 (cons basename result)
110 result))
111
112 (define (leaf name stat result)
113 (and result
114 (visit (basename name) result)))
115
116 (define (down name stat result)
117 (visit "." '()))
118
119 (define (up name stat result)
120 (visit ".." result))
121
122 (define (skip name stat result)
123 ;; All the sub-directories are skipped.
124 (visit (basename name) result))
125
126 (define (error name* stat errno result)
127 (if (string=? name name*) ; top-level NAME is unreadable
128 result
129 (visit (basename name*) result)))
130
131 (and=> (file-system-fold enter? leaf down up skip error #f name lstat)
132 (lambda (files)
133 (sort files entry<?))))
134
135 (match (scandir (dirname profile)
24e262f0 136 (cute regexp-exec (profile-regexp profile) <>))
0afdc485 137 (#f ; no profile directory
9241172c 138 '(0))
0afdc485 139 (() ; no profiles
9241172c 140 '(0))
0afdc485 141 ((profiles ...) ; former profiles around
9241172c
LC
142 (map (compose string->number
143 (cut match:substring <> 1)
144 (cute regexp-exec (profile-regexp profile) <>))
145 profiles))))
146
9241172c
LC
147(define (previous-profile-number profile number)
148 "Return the number of the generation before generation NUMBER of
149PROFILE, or 0 if none exists. It could be NUMBER - 1, but it's not the
150case when generations have been deleted (there are \"holes\")."
151 (fold (lambda (candidate highest)
152 (if (and (< candidate number) (> candidate highest))
153 candidate
154 highest))
155 0
156 (profile-numbers profile)))
0afdc485
LC
157
158(define (profile-derivation store packages)
159 "Return a derivation that builds a profile (a user environment) with
160all of PACKAGES, a list of name/version/output/path tuples."
161 (define builder
162 `(begin
163 (use-modules (ice-9 pretty-print)
164 (guix build union))
165
166 (setvbuf (current-output-port) _IOLBF)
167 (setvbuf (current-error-port) _IOLBF)
168
169 (let ((output (assoc-ref %outputs "out"))
170 (inputs (map cdr %build-inputs)))
171 (format #t "building user environment `~a' with ~a packages...~%"
172 output (length inputs))
173 (union-build output inputs)
174 (call-with-output-file (string-append output "/manifest")
175 (lambda (p)
176 (pretty-print '(manifest (version 0)
177 (packages ,packages))
178 p))))))
179
180 (build-expression->derivation store "user-environment"
181 (%current-system)
182 builder
183 (map (match-lambda
184 ((name version output path)
185 `(,name ,path)))
186 packages)
187 #:modules '((guix build union))))
188
24e262f0
LC
189(define (profile-number profile)
190 "Return PROFILE's number or 0. An absolute file name must be used."
191 (or (and=> (false-if-exception (regexp-exec (profile-regexp profile)
192 (basename (readlink profile))))
193 (compose string->number (cut match:substring <> 1)))
194 0))
195
82fe08ed
LC
196(define (switch-symlinks link target)
197 "Atomically switch LINK, a symbolic link, to point to TARGET. Works
198both when LINK already exists and when it does not."
199 (let ((pivot (string-append link ".new")))
200 (symlink target pivot)
201 (rename-file pivot link)))
202
24e262f0
LC
203(define (roll-back profile)
204 "Roll back to the previous generation of PROFILE."
9241172c
LC
205 (let* ((number (profile-number profile))
206 (previous-number (previous-profile-number profile number))
67668155
LC
207 (previous-profile (format #f "~a-~a-link"
208 profile previous-number))
9241172c 209 (manifest (string-append previous-profile "/manifest")))
24e262f0
LC
210
211 (define (switch-link)
212 ;; Atomically switch PROFILE to the previous profile.
82fe08ed
LC
213 (format #t (_ "switching from generation ~a to ~a~%")
214 number previous-number)
215 (switch-symlinks profile previous-profile))
24e262f0 216
d9307267 217 (cond ((not (file-exists? profile)) ; invalid profile
9241172c 218 (format (current-error-port)
d9307267 219 (_ "error: profile `~a' does not exist~%")
9241172c 220 profile))
d9307267
LC
221 ((zero? number) ; empty profile
222 (format (current-error-port)
223 (_ "nothing to do: already at the empty profile~%")))
224 ((or (zero? previous-number) ; going to emptiness
9241172c 225 (not (file-exists? previous-profile)))
d9307267
LC
226 (let*-values (((drv-path drv)
227 (profile-derivation (%store) '()))
228 ((prof)
229 (derivation-output-path
230 (assoc-ref (derivation-outputs drv) "out"))))
231 (when (not (build-derivations (%store) (list drv-path)))
232 (leave (_ "failed to build the empty profile~%")))
233
82fe08ed 234 (switch-symlinks previous-profile prof)
d9307267
LC
235 (switch-link)))
236 (else (switch-link))))) ; anything else
24e262f0 237
0afdc485
LC
238\f
239;;;
240;;; Command-line options.
241;;;
242
243(define %default-options
244 ;; Alist of default option values.
245 `((profile . ,%current-profile)))
246
0afdc485
LC
247(define (show-help)
248 (display (_ "Usage: guix-package [OPTION]... PACKAGES...
249Install, remove, or upgrade PACKAGES in a single transaction.\n"))
250 (display (_ "
251 -i, --install=PACKAGE install PACKAGE"))
252 (display (_ "
253 -r, --remove=PACKAGE remove PACKAGE"))
254 (display (_ "
255 -u, --upgrade=REGEXP upgrade all the installed packages matching REGEXP"))
24e262f0
LC
256 (display (_ "
257 --roll-back roll back to the previous generation"))
0afdc485
LC
258 (newline)
259 (display (_ "
260 -p, --profile=PROFILE use PROFILE instead of the user's default profile"))
261 (display (_ "
262 -n, --dry-run show what would be done without actually doing it"))
263 (display (_ "
cc57f25d 264 --bootstrap use the bootstrap Guile to build the profile"))
70915c1a
LC
265 (display (_ "
266 --verbose produce verbose output"))
0afdc485
LC
267 (newline)
268 (display (_ "
733b4130
LC
269 -I, --list-installed[=REGEXP]
270 list installed packages matching REGEXP"))
64fc89b6
LC
271 (display (_ "
272 -A, --list-available[=REGEXP]
273 list available packages matching REGEXP"))
733b4130
LC
274 (newline)
275 (display (_ "
0afdc485
LC
276 -h, --help display this help and exit"))
277 (display (_ "
278 -V, --version display version information and exit"))
279 (newline)
3441e164 280 (show-bug-report-information))
0afdc485
LC
281
282(define %options
283 ;; Specification of the command-line options.
284 (list (option '(#\h "help") #f #f
285 (lambda args
286 (show-help)
287 (exit 0)))
288 (option '(#\V "version") #f #f
289 (lambda args
cdd5d6f9 290 (show-version-and-exit "guix-package")))
0afdc485
LC
291
292 (option '(#\i "install") #t #f
293 (lambda (opt name arg result)
294 (alist-cons 'install arg result)))
295 (option '(#\r "remove") #t #f
296 (lambda (opt name arg result)
297 (alist-cons 'remove arg result)))
24e262f0
LC
298 (option '("roll-back") #f #f
299 (lambda (opt name arg result)
300 (alist-cons 'roll-back? #t result)))
0afdc485
LC
301 (option '(#\p "profile") #t #f
302 (lambda (opt name arg result)
303 (alist-cons 'profile arg
304 (alist-delete 'profile result))))
305 (option '(#\n "dry-run") #f #f
306 (lambda (opt name arg result)
307 (alist-cons 'dry-run? #t result)))
cc57f25d 308 (option '("bootstrap") #f #f
0afdc485 309 (lambda (opt name arg result)
733b4130 310 (alist-cons 'bootstrap? #t result)))
70915c1a
LC
311 (option '("verbose") #f #f
312 (lambda (opt name arg result)
313 (alist-cons 'verbose? #t result)))
733b4130
LC
314 (option '(#\I "list-installed") #f #t
315 (lambda (opt name arg result)
316 (cons `(query list-installed ,(or arg ""))
64fc89b6
LC
317 result)))
318 (option '(#\A "list-available") #f #t
319 (lambda (opt name arg result)
320 (cons `(query list-available ,(or arg ""))
733b4130 321 result)))))
0afdc485
LC
322
323\f
324;;;
325;;; Entry point.
326;;;
327
328(define (guix-package . args)
329 (define (parse-options)
330 ;; Return the alist of option values.
331 (args-fold args %options
332 (lambda (opt name arg result)
333 (leave (_ "~A: unrecognized option~%") name))
334 (lambda (arg result)
3b9c0020 335 (leave (_ "~A: extraneous argument~%") arg))
0afdc485
LC
336 %default-options))
337
9762706b
LC
338 (define (guile-missing?)
339 ;; Return #t if %GUILE-FOR-BUILD is not available yet.
340 (let ((out (derivation-path->output-path (%guile-for-build))))
c4d64534 341 (not (valid-path? (%store) out))))
9762706b 342
0afdc485
LC
343 (define (show-what-to-build drv dry-run?)
344 ;; Show what will/would be built in realizing the derivations listed
345 ;; in DRV.
346 (let* ((req (append-map (lambda (drv-path)
347 (let ((d (call-with-input-file drv-path
348 read-derivation)))
c4d64534
LC
349 (derivation-prerequisites-to-build
350 (%store) d)))
0afdc485
LC
351 drv))
352 (req* (delete-duplicates
c4d64534 353 (append (remove (compose (cute valid-path? (%store) <>)
0afdc485
LC
354 derivation-path->output-path)
355 drv)
356 (map derivation-input-path req)))))
357 (if dry-run?
358 (format (current-error-port)
359 (N_ "~:[the following derivation would be built:~%~{ ~a~%~}~;~]"
360 "~:[the following derivations would be built:~%~{ ~a~%~}~;~]"
361 (length req*))
362 (null? req*) req*)
363 (format (current-error-port)
364 (N_ "~:[the following derivation will be built:~%~{ ~a~%~}~;~]"
365 "~:[the following derivations will be built:~%~{ ~a~%~}~;~]"
366 (length req*))
367 (null? req*) req*))))
368
369 (define (find-package name)
370 ;; Find the package NAME; NAME may contain a version number and a
371 ;; sub-derivation name.
372 (define request name)
0afdc485
LC
373
374 (let*-values (((name sub-drv)
375 (match (string-rindex name #\:)
376 (#f (values name "out"))
9518856b
LC
377 (colon (values (substring name 0 colon)
378 (substring name (+ 1 colon))))))
0afdc485 379 ((name version)
9b48fb88 380 (package-name->name+version name)))
0afdc485
LC
381 (match (find-packages-by-name name version)
382 ((p)
d9d05363 383 (list name (package-version p) sub-drv p))
c6f09dfa 384 ((p p* ...)
0afdc485
LC
385 (format (current-error-port)
386 (_ "warning: ambiguous package specification `~a'~%")
387 request)
388 (format (current-error-port)
d9d05363
LC
389 (_ "warning: choosing ~a from ~a~%")
390 (package-full-name p)
391 (location->string (package-location p)))
392 (list name (package-version p) sub-drv p))
0afdc485
LC
393 (()
394 (leave (_ "~a: package not found~%") request)))))
395
0ec1af59
LC
396 (define (ensure-default-profile)
397 ;; Ensure the default profile symlink and directory exist.
398
399 ;; Create ~/.guix-profile if it doesn't exist yet.
400 (when (and %user-environment-directory
401 %current-profile
402 (not (false-if-exception
403 (lstat %user-environment-directory))))
404 (symlink %current-profile %user-environment-directory))
405
406 ;; Attempt to create /…/profiles/per-user/$USER if needed.
407 (unless (directory-exists? %profile-directory)
408 (catch 'system-error
409 (lambda ()
410 (mkdir-p %profile-directory))
411 (lambda args
412 ;; Often, we cannot create %PROFILE-DIRECTORY because its
413 ;; parent directory is root-owned and we're running
414 ;; unprivileged.
415 (format (current-error-port)
416 (_ "error: while creating directory `~a': ~a~%")
417 %profile-directory
418 (strerror (system-error-errno args)))
419 (format (current-error-port)
420 (_ "Please create the `~a' directory, with you as the owner.~%")
421 %profile-directory)
422 (exit 1)))))
423
733b4130
LC
424 (define (process-actions opts)
425 ;; Process any install/remove/upgrade action from OPTS.
24e262f0
LC
426
427 (define dry-run? (assoc-ref opts 'dry-run?))
428 (define verbose? (assoc-ref opts 'verbose?))
429 (define profile (assoc-ref opts 'profile))
430
431 ;; First roll back if asked to.
432 (if (and (assoc-ref opts 'roll-back?) (not dry-run?))
433 (begin
434 (roll-back profile)
435 (process-actions (alist-delete 'roll-back? opts)))
436 (let* ((install (filter-map (match-lambda
437 (('install . (? store-path?))
438 #f)
439 (('install . package)
440 (find-package package))
441 (_ #f))
442 opts))
443 (drv (filter-map (match-lambda
444 ((name version sub-drv
445 (? package? package))
446 (package-derivation (%store) package))
447 (_ #f))
448 install))
449 (install* (append
450 (filter-map (match-lambda
451 (('install . (? store-path? path))
452 (let-values (((name version)
453 (package-name->name+version
454 (store-path-package-name
455 path))))
456 `(,name ,version #f ,path)))
457 (_ #f))
458 opts)
459 (map (lambda (tuple drv)
460 (match tuple
461 ((name version sub-drv _)
462 (let ((output-path
463 (derivation-path->output-path
464 drv sub-drv)))
465 `(,name ,version ,sub-drv ,output-path)))))
466 install drv)))
467 (remove (filter-map (match-lambda
468 (('remove . package)
469 package)
470 (_ #f))
471 opts))
472 (packages (append install*
473 (fold (lambda (package result)
474 (match package
475 ((name _ ...)
476 (alist-delete name result))))
477 (fold alist-delete
478 (manifest-packages
479 (profile-manifest profile))
480 remove)
481 install*))))
482
483 (when (equal? profile %current-profile)
484 (ensure-default-profile))
485
486 (show-what-to-build drv dry-run?)
487
488 (or dry-run?
489 (and (build-derivations (%store) drv)
490 (let* ((prof-drv (profile-derivation (%store) packages))
491 (prof (derivation-path->output-path prof-drv))
492 (old-drv (profile-derivation
493 (%store) (manifest-packages
494 (profile-manifest profile))))
495 (old-prof (derivation-path->output-path old-drv))
82fe08ed
LC
496 (number (profile-number profile))
497
498 ;; Always use NUMBER + 1 for the new profile,
499 ;; possibly overwriting a "previous future
500 ;; generation".
501 (name (format #f "~a-~a-link"
502 profile (+ 1 number))))
24e262f0
LC
503 (if (string=? old-prof prof)
504 (when (or (pair? install) (pair? remove))
505 (format (current-error-port)
506 (_ "nothing to be done~%")))
507 (and (parameterize ((current-build-output-port
508 ;; Output something when Guile
509 ;; needs to be built.
510 (if (or verbose? (guile-missing?))
511 (current-error-port)
512 (%make-void-port "w"))))
513 (build-derivations (%store) (list prof-drv)))
514 (begin
82fe08ed
LC
515 (switch-symlinks name prof)
516 (switch-symlinks profile name))))))))))
733b4130
LC
517
518 (define (process-query opts)
519 ;; Process any query specified by OPTS. Return #t when a query was
520 ;; actually processed, #f otherwise.
521 (let ((profile (assoc-ref opts 'profile)))
522 (match (assoc-ref opts 'query)
523 (('list-installed regexp)
524 (let* ((regexp (and regexp (make-regexp regexp)))
525 (manifest (profile-manifest profile))
526 (installed (manifest-packages manifest)))
527 (for-each (match-lambda
528 ((name version output path)
529 (when (or (not regexp)
530 (regexp-exec regexp name))
531 (format #t "~a\t~a\t~a\t~a~%"
532 name (or version "?") output path))))
64fc89b6
LC
533 installed)
534 #t))
535 (('list-available regexp)
536 (let* ((regexp (and regexp (make-regexp regexp)))
537 (available (fold-packages
538 (lambda (p r)
539 (let ((n (package-name p)))
540 (if regexp
541 (if (regexp-exec regexp n)
542 (cons p r)
543 r)
544 (cons p r))))
545 '())))
546 (for-each (lambda (p)
44b6be77 547 (format #t "~a\t~a\t~a\t~a~%"
64fc89b6
LC
548 (package-name p)
549 (package-version p)
44b6be77 550 (string-join (package-outputs p) ",")
64fc89b6
LC
551 (location->string (package-location p))))
552 (sort available
553 (lambda (p1 p2)
554 (string<? (package-name p1)
555 (package-name p2)))))
556 #t))
733b4130
LC
557 (_ #f))))
558
0afdc485
LC
559 (setlocale LC_ALL "")
560 (textdomain "guix")
561 (setvbuf (current-output-port) _IOLBF)
562 (setvbuf (current-error-port) _IOLBF)
563
564 (let ((opts (parse-options)))
c4d64534
LC
565 (parameterize ((%store (open-connection)))
566 (with-error-handling
567 (or (process-query opts)
568 (parameterize ((%guile-for-build
569 (package-derivation (%store)
570 (if (assoc-ref opts 'bootstrap?)
571 %bootstrap-guile
572 guile-final))))
573 (process-actions opts)))))))