summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--guix/profiles.scm41
-rw-r--r--guix/scripts/environment.scm51
-rw-r--r--tests/profiles.scm27
3 files changed, 76 insertions, 43 deletions
diff --git a/guix/profiles.scm b/guix/profiles.scm
index 8cbffa4d2bf..09b2d1525ab 100644
--- a/guix/profiles.scm
+++ b/guix/profiles.scm
@@ -11,6 +11,7 @@
11;;; Copyright © 2019 Kyle Meyer <kyle@kyleam.com> 11;;; Copyright © 2019 Kyle Meyer <kyle@kyleam.com>
12;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@gmail.com> 12;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@gmail.com>
13;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org> 13;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org>
14;;; Copyright © 2014 David Thompson <davet@gnu.org>
14;;; 15;;;
15;;; This file is part of GNU Guix. 16;;; This file is part of GNU Guix.
16;;; 17;;;
@@ -54,6 +55,7 @@
54 #:use-module (srfi srfi-26) 55 #:use-module (srfi srfi-26)
55 #:use-module (srfi srfi-34) 56 #:use-module (srfi srfi-34)
56 #:use-module (srfi srfi-35) 57 #:use-module (srfi srfi-35)
58 #:autoload (srfi srfi-98) (get-environment-variables)
57 #:export (&profile-error 59 #:export (&profile-error
58 profile-error? 60 profile-error?
59 profile-error-profile 61 profile-error-profile
@@ -127,6 +129,7 @@
127 %default-profile-hooks 129 %default-profile-hooks
128 profile-derivation 130 profile-derivation
129 profile-search-paths 131 profile-search-paths
132 load-profile
130 133
131 profile 134 profile
132 profile? 135 profile?
@@ -1916,6 +1919,44 @@ already effective."
1916 (evaluate-search-paths (manifest-search-paths manifest) 1919 (evaluate-search-paths (manifest-search-paths manifest)
1917 (list profile) getenv)) 1920 (list profile) getenv))
1918 1921
1922(define %precious-variables
1923 ;; Environment variables in the default 'load-profile' white list.
1924 '("HOME" "USER" "LOGNAME" "DISPLAY" "TERM" "TZ" "PAGER"))
1925
1926(define (purify-environment white-list white-list-regexps)
1927 "Unset all environment variables except those that match the regexps in
1928WHITE-LIST-REGEXPS and those listed in WHITE-LIST."
1929 (for-each unsetenv
1930 (remove (lambda (variable)
1931 (or (member variable white-list)
1932 (find (cut regexp-exec <> variable)
1933 white-list-regexps)))
1934 (match (get-environment-variables)
1935 (((names . _) ...)
1936 names)))))
1937
1938(define* (load-profile profile
1939 #:optional (manifest (profile-manifest profile))
1940 #:key pure? (white-list-regexps '())
1941 (white-list %precious-variables))
1942 "Set the environment variables specified by MANIFEST for PROFILE. When
1943PURE? is #t, unset the variables in the current environment except those that
1944match the regexps in WHITE-LIST-REGEXPS and those listed in WHITE-LIST.
1945Otherwise, augment existing environment variables with additional search
1946paths."
1947 (when pure?
1948 (purify-environment white-list white-list-regexps))
1949 (for-each (match-lambda
1950 ((($ <search-path-specification> variable _ separator) . value)
1951 (let ((current (getenv variable)))
1952 (setenv variable
1953 (if (and current (not pure?))
1954 (if separator
1955 (string-append value separator current)
1956 value)
1957 value)))))
1958 (profile-search-paths profile manifest)))
1959
1919(define (profile-regexp profile) 1960(define (profile-regexp profile)
1920 "Return a regular expression that matches PROFILE's name and number." 1961 "Return a regular expression that matches PROFILE's name and number."
1921 (make-regexp (string-append "^" (regexp-quote (basename profile)) 1962 (make-regexp (string-append "^" (regexp-quote (basename profile))
diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm
index 5ceb86f7a9a..6958bd6238b 100644
--- a/guix/scripts/environment.scm
+++ b/guix/scripts/environment.scm
@@ -52,50 +52,9 @@
52 #:export (assert-container-features 52 #:export (assert-container-features
53 guix-environment)) 53 guix-environment))
54 54
55;; Protect some env vars from purification. Borrowed from nix-shell.
56(define %precious-variables
57 '("HOME" "USER" "LOGNAME" "DISPLAY" "TERM" "TZ" "PAGER"))
58
59(define %default-shell 55(define %default-shell
60 (or (getenv "SHELL") "/bin/sh")) 56 (or (getenv "SHELL") "/bin/sh"))
61 57
62(define (purify-environment white-list)
63 "Unset all environment variables except those that match the regexps in
64WHITE-LIST and those listed in %PRECIOUS-VARIABLES. A small number of
65variables such as 'HOME' and 'USER' are left untouched."
66 (for-each unsetenv
67 (remove (lambda (variable)
68 (or (member variable %precious-variables)
69 (find (cut regexp-exec <> variable)
70 white-list)))
71 (match (get-environment-variables)
72 (((names . _) ...)
73 names)))))
74
75(define* (create-environment profile manifest
76 #:key pure? (white-list '()))
77 "Set the environment variables specified by MANIFEST for PROFILE. When
78PURE? is #t, unset the variables in the current environment except those that
79match the regexps in WHITE-LIST. Otherwise, augment existing environment
80variables with additional search paths."
81 (when pure?
82 (purify-environment white-list))
83 (for-each (match-lambda
84 ((($ <search-path-specification> variable _ separator) . value)
85 (let ((current (getenv variable)))
86 (setenv variable
87 (if (and current (not pure?))
88 (if separator
89 (string-append value separator current)
90 value)
91 value)))))
92 (profile-search-paths profile manifest))
93
94 ;; Give users a way to know that they're in 'guix environment', so they can
95 ;; adjust 'PS1' accordingly, for instance. Set it to PROFILE so users can
96 ;; conveniently access its contents.
97 (setenv "GUIX_ENVIRONMENT" profile))
98
99(define* (show-search-paths profile manifest #:key pure?) 58(define* (show-search-paths profile manifest #:key pure?)
100 "Display the search paths of MANIFEST applied to PROFILE. When PURE? is #t, 59 "Display the search paths of MANIFEST applied to PROFILE. When PURE? is #t,
101do not augment existing environment variables with additional search paths." 60do not augment existing environment variables with additional search paths."
@@ -425,8 +384,14 @@ regexps in WHITE-LIST."
425 ;; Properly handle SIGINT, so pressing C-c in an interactive terminal 384 ;; Properly handle SIGINT, so pressing C-c in an interactive terminal
426 ;; application works. 385 ;; application works.
427 (sigaction SIGINT SIG_DFL) 386 (sigaction SIGINT SIG_DFL)
428 (create-environment profile manifest 387 (load-profile profile manifest
429 #:pure? pure? #:white-list white-list) 388 #:pure? pure? #:white-list-regexps white-list)
389
390 ;; Give users a way to know that they're in 'guix environment', so they can
391 ;; adjust 'PS1' accordingly, for instance. Set it to PROFILE so users can
392 ;; conveniently access its contents.
393 (setenv "GUIX_ENVIRONMENT" profile)
394
430 (match command 395 (match command
431 ((program . args) 396 ((program . args)
432 (apply execlp program program args)))) 397 (apply execlp program program args))))
diff --git a/tests/profiles.scm b/tests/profiles.scm
index ce77711d63c..1a06ff88f34 100644
--- a/tests/profiles.scm
+++ b/tests/profiles.scm
@@ -279,6 +279,33 @@
279 (string=? (dirname (readlink bindir)) 279 (string=? (dirname (readlink bindir))
280 (derivation->output-path guile)))))) 280 (derivation->output-path guile))))))
281 281
282(test-assertm "load-profile"
283 (mlet* %store-monad
284 ((entry -> (package->manifest-entry %bootstrap-guile))
285 (guile (package->derivation %bootstrap-guile))
286 (drv (profile-derivation (manifest (list entry))
287 #:hooks '()
288 #:locales? #f))
289 (profile -> (derivation->output-path drv))
290 (bindir -> (string-append profile "/bin"))
291 (_ (built-derivations (list drv))))
292 (define-syntax-rule (with-environment-excursion exp ...)
293 (let ((env (environ)))
294 (dynamic-wind
295 (const #t)
296 (lambda () exp ...)
297 (lambda () (environ env)))))
298
299 (return (and (with-environment-excursion
300 (load-profile profile)
301 (and (string-prefix? (string-append bindir ":")
302 (getenv "PATH"))
303 (getenv "GUILE_LOAD_PATH")))
304 (with-environment-excursion
305 (load-profile profile #:pure? #t #:white-list '())
306 (equal? (list (string-append "PATH=" bindir))
307 (environ)))))))
308
282(test-assertm "<profile>" 309(test-assertm "<profile>"
283 (mlet* %store-monad 310 (mlet* %store-monad
284 ((entry -> (package->manifest-entry %bootstrap-guile)) 311 ((entry -> (package->manifest-entry %bootstrap-guile))