guix system: Add 'init' sub-command.

* guix/scripts/system.scm (install): New procedure.
  (guix-system)[parse-option]: Remove check for extraneous arguments.
  [match-pair, option-arguments]: New procedures.
  Use 'option-arguments'.  Honor 'init'.
  (show-help): Document 'init'.
* doc/guix.texi (Invoking guix system): Document 'init'.
This commit is contained in:
Ludovic Courtès 2014-05-18 21:32:57 +02:00
parent bb31e0a3ee
commit 72b9d60df4
2 changed files with 93 additions and 9 deletions

View file

@ -3209,6 +3209,21 @@ Build the operating system's derivation, which includes all the
configuration files and programs needed to boot and run the system. configuration files and programs needed to boot and run the system.
This action does not actually install anything. This action does not actually install anything.
@item init
Populate the given directory with all the files necessary to run the
operating system specified in @var{file}. This is useful for first-time
installations of the GNU system. For instance:
@example
guix system init my-os-config.scm /mnt
@end example
copies to @file{/mnt} all the store items required by the configuration
specified in @file{my-os-config.scm}. This includes configuration
files, packages, and so on. It also creates other essential files
needed for the system to operate correctly---e.g., the @file{/etc},
@file{/var}, and @file{/run} directories, and the @file{/bin/sh} file.
@item vm @item vm
@cindex virtual machine @cindex virtual machine
Build a virtual machine that contain the operating system declared in Build a virtual machine that contain the operating system declared in

View file

@ -19,14 +19,18 @@
(define-module (guix scripts system) (define-module (guix scripts system)
#:use-module (guix ui) #:use-module (guix ui)
#:use-module (guix store) #:use-module (guix store)
#:use-module (guix gexp)
#:use-module (guix derivations) #:use-module (guix derivations)
#:use-module (guix packages) #:use-module (guix packages)
#:use-module (guix utils) #:use-module (guix utils)
#:use-module (guix monads) #:use-module (guix monads)
#:use-module (guix scripts build) #:use-module (guix scripts build)
#:use-module (guix build utils)
#:use-module (guix build install)
#:use-module (gnu system) #:use-module (gnu system)
#:use-module (gnu system vm) #:use-module (gnu system vm)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-37) #:use-module (srfi srfi-37)
#:use-module (ice-9 match) #:use-module (ice-9 match)
#:export (guix-system #:export (guix-system
@ -64,6 +68,38 @@ (define (read-operating-system file)
(leave (_ "failed to load machine file '~a': ~s~%") (leave (_ "failed to load machine file '~a': ~s~%")
file args)))))) file args))))))
(define* (install store os-dir target
#:key (log-port (current-output-port)))
"Copy OS-DIR and its dependencies to directory TARGET. TARGET must be an
absolute directory name since that's what 'guix-register' expects."
(define to-copy
(let ((lst (delete-duplicates (cons os-dir (references store os-dir))
string=?)))
(topologically-sorted store lst)))
;; Copy items to the new store.
(for-each (lambda (item)
(let ((dest (string-append target item))
(refs (references store item)))
(format log-port "copying '~a'...~%" item)
(copy-recursively item dest
#:log (%make-void-port "w"))
;; Register ITEM; as a side-effect, it resets timestamps, etc.
(unless (register-path item
#:prefix target
#:references refs)
(leave (_ "failed to register '~a' under '~a'~%")
item target))))
to-copy)
;; Create a bunch of additional files.
(format log-port "populating '~a'...~%" target)
(populate-root-file-system target)
;; TODO: Install GRUB.
)
;;; ;;;
;;; Options. ;;; Options.
@ -79,7 +115,9 @@ (define (show-help)
(display (_ "\ (display (_ "\
- 'vm', build a virtual machine image that shares the host's store\n")) - 'vm', build a virtual machine image that shares the host's store\n"))
(display (_ "\ (display (_ "\
- 'vm-image', build a freestanding virtual machine image.\n")) - 'vm-image', build a freestanding virtual machine image\n"))
(display (_ "\
- 'init', initialize a root file system to run GNU.\n"))
(show-build-options-help) (show-build-options-help)
(display (_ " (display (_ "
@ -132,27 +170,50 @@ (define (parse-options)
(leave (_ "~A: unrecognized option~%") name)) (leave (_ "~A: unrecognized option~%") name))
(lambda (arg result) (lambda (arg result)
(if (assoc-ref result 'action) (if (assoc-ref result 'action)
(let ((previous (assoc-ref result 'argument))) (alist-cons 'argument arg result)
(if previous
(leave (_ "~a: extraneous argument~%") previous)
(alist-cons 'argument arg result)))
(let ((action (string->symbol arg))) (let ((action (string->symbol arg)))
(case action (case action
((build vm vm-image) ((build vm vm-image init)
(alist-cons 'action action result)) (alist-cons 'action action result))
(else (leave (_ "~a: unknown action~%") (else (leave (_ "~a: unknown action~%")
action)))))) action))))))
%default-options)) %default-options))
(define (match-pair car)
;; Return a procedure that matches a pair with CAR.
(match-lambda
((head . tail)
(and (eq? car head) tail))
(_ #f)))
(define (option-arguments opts)
;; Extract the plain arguments from OPTS.
(let* ((args (reverse (filter-map (match-pair 'argument) opts)))
(count (length args))
(action (assoc-ref opts 'action)))
(define (fail)
(leave (_ "wrong number of arguments for action '~a'~%")
action))
(case action
((build vm vm-image)
(unless (= count 1)
(fail)))
((init)
(unless (= count 2)
(fail))))
args))
(with-error-handling (with-error-handling
(let* ((opts (parse-options)) (let* ((opts (parse-options))
(file (assoc-ref opts 'argument)) (args (option-arguments opts))
(file (first args))
(action (assoc-ref opts 'action)) (action (assoc-ref opts 'action))
(os (if file (os (if file
(read-operating-system file) (read-operating-system file)
(leave (_ "no configuration file specified~%")))) (leave (_ "no configuration file specified~%"))))
(mdrv (case action (mdrv (case action
((build) ((build init)
(operating-system-derivation os)) (operating-system-derivation os))
((vm-image) ((vm-image)
(let ((size (assoc-ref opts 'image-size))) (let ((size (assoc-ref opts 'image-size)))
@ -171,4 +232,12 @@ (define (parse-options)
(unless dry? (unless dry?
(build-derivations store (list drv)) (build-derivations store (list drv))
(display (derivation->output-path drv)) (display (derivation->output-path drv))
(newline))))) (newline)
(when (eq? action 'init)
(let ((target (second args)))
(format #t (_ "initializing operating system under '~a'...~%")
target)
(install store (derivation->output-path drv)
(canonicalize-path target))))))))