environment: Add '--root' option.
* guix/scripts/environment.scm (show-help, %options): Add --root. (register-gc-root): New procedure. (guix-environment): Call 'register-gc-root' when OPTS has a 'gc-root' option. * doc/guix.texi (Invoking guix environment): Document it. * tests/guix-environment.sh: Add tests.
This commit is contained in:
parent
7d2511bc6b
commit
f943c317fb
|
@ -5997,6 +5997,21 @@ The @code{--container} option requires Linux-libre 3.19 or newer.
|
||||||
The available options are summarized below.
|
The available options are summarized below.
|
||||||
|
|
||||||
@table @code
|
@table @code
|
||||||
|
@item --root=@var{file}
|
||||||
|
@itemx -r @var{file}
|
||||||
|
@cindex persistent environment
|
||||||
|
@cindex garbage collector root, for environments
|
||||||
|
Make @var{file} a symlink to the profile for this environment, and
|
||||||
|
register it as a garbage collector root.
|
||||||
|
|
||||||
|
This is useful if you want to protect your environment from garbage
|
||||||
|
collection, to make it ``persistent''.
|
||||||
|
|
||||||
|
When this option is omitted, the environment is protected from garbage
|
||||||
|
collection only for the duration of the @command{guix environment}
|
||||||
|
session. This means that next time you recreate the same environment,
|
||||||
|
you could have to rebuild or re-download packages.
|
||||||
|
|
||||||
@item --expression=@var{expr}
|
@item --expression=@var{expr}
|
||||||
@itemx -e @var{expr}
|
@itemx -e @var{expr}
|
||||||
Create an environment for the package or list of packages that
|
Create an environment for the package or list of packages that
|
||||||
|
|
|
@ -155,6 +155,9 @@ COMMAND or an interactive shell in that environment.\n"))
|
||||||
(display (_ "
|
(display (_ "
|
||||||
-s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\""))
|
-s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\""))
|
||||||
(display (_ "
|
(display (_ "
|
||||||
|
-r, --root=FILE make FILE a symlink to the result, and register it
|
||||||
|
as a garbage collector root"))
|
||||||
|
(display (_ "
|
||||||
-C, --container run command within an isolated container"))
|
-C, --container run command within an isolated container"))
|
||||||
(display (_ "
|
(display (_ "
|
||||||
-N, --network allow containers to access the network"))
|
-N, --network allow containers to access the network"))
|
||||||
|
@ -247,6 +250,9 @@ COMMAND or an interactive shell in that environment.\n"))
|
||||||
(alist-cons 'file-system-mapping
|
(alist-cons 'file-system-mapping
|
||||||
(specification->file-system-mapping arg #f)
|
(specification->file-system-mapping arg #f)
|
||||||
result)))
|
result)))
|
||||||
|
(option '(#\r "root") #t #f
|
||||||
|
(lambda (opt name arg result)
|
||||||
|
(alist-cons 'gc-root arg result)))
|
||||||
(option '("bootstrap") #f #f
|
(option '("bootstrap") #f #f
|
||||||
(lambda (opt name arg result)
|
(lambda (opt name arg result)
|
||||||
(alist-cons 'bootstrap? #t result)))
|
(alist-cons 'bootstrap? #t result)))
|
||||||
|
@ -523,7 +529,26 @@ message if any test fails."
|
||||||
(report-error (_ "cannot create container: /proc/self/setgroups does not exist\n"))
|
(report-error (_ "cannot create container: /proc/self/setgroups does not exist\n"))
|
||||||
(leave (_ "is your kernel version < 3.19?\n"))))
|
(leave (_ "is your kernel version < 3.19?\n"))))
|
||||||
|
|
||||||
;; Entry point.
|
(define (register-gc-root target root)
|
||||||
|
"Make ROOT an indirect root to TARGET. This is procedure is idempotent."
|
||||||
|
(let* ((root (string-append (canonicalize-path (dirname root))
|
||||||
|
"/" root)))
|
||||||
|
(catch 'system-error
|
||||||
|
(lambda ()
|
||||||
|
(symlink target root)
|
||||||
|
((store-lift add-indirect-root) root))
|
||||||
|
(lambda args
|
||||||
|
(if (and (= EEXIST (system-error-errno args))
|
||||||
|
(equal? (false-if-exception (readlink root)) target))
|
||||||
|
(with-monad %store-monad
|
||||||
|
(return #t))
|
||||||
|
(apply throw args))))))
|
||||||
|
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; Entry point.
|
||||||
|
;;;
|
||||||
|
|
||||||
(define (guix-environment . args)
|
(define (guix-environment . args)
|
||||||
(with-error-handling
|
(with-error-handling
|
||||||
(let* ((opts (parse-args args))
|
(let* ((opts (parse-args args))
|
||||||
|
@ -579,7 +604,9 @@ message if any test fails."
|
||||||
system))
|
system))
|
||||||
(prof-drv (inputs->profile-derivation
|
(prof-drv (inputs->profile-derivation
|
||||||
inputs system bootstrap?))
|
inputs system bootstrap?))
|
||||||
(profile -> (derivation->output-path prof-drv)))
|
(profile -> (derivation->output-path prof-drv))
|
||||||
|
(gc-root -> (assoc-ref opts 'gc-root)))
|
||||||
|
|
||||||
;; First build the inputs. This is necessary even for
|
;; First build the inputs. This is necessary even for
|
||||||
;; --search-paths. Additionally, we might need to build bash for
|
;; --search-paths. Additionally, we might need to build bash for
|
||||||
;; a container.
|
;; a container.
|
||||||
|
@ -588,6 +615,9 @@ message if any test fails."
|
||||||
(list prof-drv bash)
|
(list prof-drv bash)
|
||||||
(list prof-drv))
|
(list prof-drv))
|
||||||
opts)
|
opts)
|
||||||
|
(mwhen gc-root
|
||||||
|
(register-gc-root profile gc-root))
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
((assoc-ref opts 'dry-run?)
|
((assoc-ref opts 'dry-run?)
|
||||||
(return #t))
|
(return #t))
|
||||||
|
|
|
@ -25,7 +25,8 @@ set -e
|
||||||
guix environment --version
|
guix environment --version
|
||||||
|
|
||||||
tmpdir="t-guix-environment-$$"
|
tmpdir="t-guix-environment-$$"
|
||||||
trap 'rm -r "$tmpdir"' EXIT
|
gcroot="t-guix-environment-gc-root-$$"
|
||||||
|
trap 'rm -r "$tmpdir"; rm -f "$gcroot"' EXIT
|
||||||
|
|
||||||
mkdir "$tmpdir"
|
mkdir "$tmpdir"
|
||||||
|
|
||||||
|
@ -61,6 +62,20 @@ fi
|
||||||
guix environment --bootstrap --ad-hoc guile-bootstrap --pure \
|
guix environment --bootstrap --ad-hoc guile-bootstrap --pure \
|
||||||
-- "$SHELL" -c 'test -f "$GUIX_ENVIRONMENT/bin/guile"'
|
-- "$SHELL" -c 'test -f "$GUIX_ENVIRONMENT/bin/guile"'
|
||||||
|
|
||||||
|
# Make sure '-r' works as expected.
|
||||||
|
rm -f "$gcroot"
|
||||||
|
expected="`guix environment --bootstrap --ad-hoc guile-bootstrap \
|
||||||
|
-- "$SHELL" -c 'echo $GUIX_ENVIRONMENT'`"
|
||||||
|
guix environment --bootstrap -r "$gcroot" --ad-hoc guile-bootstrap \
|
||||||
|
-- guile -c 1
|
||||||
|
test `readlink "$gcroot"` = "$expected"
|
||||||
|
|
||||||
|
# Make sure '-r' is idempotent.
|
||||||
|
guix environment --bootstrap -r "$gcroot" --ad-hoc guile-bootstrap \
|
||||||
|
-- guile -c 1
|
||||||
|
test `readlink "$gcroot"` = "$expected"
|
||||||
|
|
||||||
|
|
||||||
case "`uname -m`" in
|
case "`uname -m`" in
|
||||||
x86_64)
|
x86_64)
|
||||||
# On x86_64, we should be able to create a 32-bit environment.
|
# On x86_64, we should be able to create a 32-bit environment.
|
||||||
|
|
Loading…
Reference in New Issue