summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/guix.texi45
-rw-r--r--gnu/packages.scm3
-rw-r--r--guix/scripts/shell.scm161
-rw-r--r--guix/transformations.scm9
4 files changed, 142 insertions, 76 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 443059147fb..876172fa3af 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -5806,17 +5806,6 @@ This is similar to the same-named option in @command{guix package}
5806(@pxref{profile-manifest, @option{--manifest}}) and uses the same 5806(@pxref{profile-manifest, @option{--manifest}}) and uses the same
5807manifest files. 5807manifest files.
5808 5808
5809@item --rebuild-cache
5810When using @option{--manifest}, @option{--file}, or when invoked without
5811arguments, @command{guix shell} caches the environment so that
5812subsequent uses are instantaneous. The cache is invalidated anytime the
5813file is modified.
5814
5815The @option{--rebuild-cache} forces the cached environment to be
5816refreshed even if the file has not changed. This is useful if the
5817@command{guix.scm} or @command{manifest.scm} has external dependencies,
5818or if its behavior depends, say, on environment variables.
5819
5820@item --pure 5809@item --pure
5821Unset existing environment variables when building the new environment, except 5810Unset existing environment variables when building the new environment, except
5822those specified with @option{--preserve} (see below). This has the effect of 5811those specified with @option{--preserve} (see below). This has the effect of
@@ -5932,6 +5921,21 @@ directory:
5932guix shell --container --expose=$HOME=/exchange guile -- guile 5921guix shell --container --expose=$HOME=/exchange guile -- guile
5933@end example 5922@end example
5934 5923
5924@item --rebuild-cache
5925@cindex caching, of profiles
5926@cindex caching, in @command{guix shell}
5927In most cases, @command{guix shell} caches the environment so that
5928subsequent uses are instantaneous. Least-recently used cache entries
5929are periodically removed. The cache is also invalidated, when using
5930@option{--file} or @option{--manifest}, anytime the corresponding file
5931is modified.
5932
5933The @option{--rebuild-cache} forces the cached environment to be
5934refreshed. This is useful when using @option{--file} or
5935@option{--manifest} and the @command{guix.scm} or @command{manifest.scm}
5936file has external dependencies, or if its behavior depends, say, on
5937environment variables.
5938
5935@item --root=@var{file} 5939@item --root=@var{file}
5936@itemx -r @var{file} 5940@itemx -r @var{file}
5937@cindex persistent environment 5941@cindex persistent environment
@@ -5942,11 +5946,20 @@ register it as a garbage collector root.
5942This is useful if you want to protect your environment from garbage 5946This is useful if you want to protect your environment from garbage
5943collection, to make it ``persistent''. 5947collection, to make it ``persistent''.
5944 5948
5945When this option is omitted, the environment is protected from garbage 5949When this option is omitted, @command{guix shell} caches profiles so
5946collection only for the duration of the @command{guix shell} 5950that subsequent uses of the same environment are instantaneous---this is
5947session. This means that next time you recreate the same environment, 5951comparable to using @option{--root} except that @command{guix shell}
5948you could have to rebuild or re-download packages. @xref{Invoking guix 5952takes care of periodically removing the least-recently used garbage
5949gc}, for more on GC roots. 5953collector roots.
5954
5955In some cases, @command{guix shell} does not cache profiles---e.g., if
5956transformation options such as @option{--with-latest} are used. In
5957those cases, the environment is protected from garbage collection only
5958for the duration of the @command{guix shell} session. This means that
5959next time you recreate the same environment, you could have to rebuild
5960or re-download packages.
5961
5962@xref{Invoking guix gc}, for more on GC roots.
5950@end table 5963@end table
5951 5964
5952@command{guix shell} also supports all of the common build options that 5965@command{guix shell} also supports all of the common build options that
diff --git a/gnu/packages.scm b/gnu/packages.scm
index ccfc83dd117..65ab7a7c1e4 100644
--- a/gnu/packages.scm
+++ b/gnu/packages.scm
@@ -1,5 +1,5 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2012-2020, 2022 Ludovic Courtès <ludo@gnu.org>
3;;; Copyright © 2013 Mark H Weaver <mhw@netris.org> 3;;; Copyright © 2013 Mark H Weaver <mhw@netris.org>
4;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org> 4;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
5;;; Copyright © 2016, 2017 Alex Kost <alezost@gmail.com> 5;;; Copyright © 2016, 2017 Alex Kost <alezost@gmail.com>
@@ -51,6 +51,7 @@
51 %auxiliary-files-path 51 %auxiliary-files-path
52 %package-module-path 52 %package-module-path
53 %default-package-module-path 53 %default-package-module-path
54 cache-is-authoritative?
54 55
55 fold-packages 56 fold-packages
56 fold-available-packages 57 fold-available-packages
diff --git a/guix/scripts/shell.scm b/guix/scripts/shell.scm
index 546639818f1..a92932cbc95 100644
--- a/guix/scripts/shell.scm
+++ b/guix/scripts/shell.scm
@@ -1,5 +1,5 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2021 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2021-2022 Ludovic Courtès <ludo@gnu.org>
3;;; 3;;;
4;;; This file is part of GNU Guix. 4;;; This file is part of GNU Guix.
5;;; 5;;;
@@ -21,7 +21,8 @@
21 #:use-module ((guix diagnostics) #:select (location)) 21 #:use-module ((guix diagnostics) #:select (location))
22 #:use-module (guix scripts environment) 22 #:use-module (guix scripts environment)
23 #:autoload (guix scripts build) (show-build-options-help) 23 #:autoload (guix scripts build) (show-build-options-help)
24 #:autoload (guix transformations) (show-transformation-options-help) 24 #:autoload (guix transformations) (transformation-option-key?
25 show-transformation-options-help)
25 #:use-module (guix scripts) 26 #:use-module (guix scripts)
26 #:use-module (guix packages) 27 #:use-module (guix packages)
27 #:use-module (guix profiles) 28 #:use-module (guix profiles)
@@ -40,6 +41,7 @@
40 #:use-module ((guix build utils) #:select (mkdir-p)) 41 #:use-module ((guix build utils) #:select (mkdir-p))
41 #:use-module (guix cache) 42 #:use-module (guix cache)
42 #:use-module ((ice-9 ftw) #:select (scandir)) 43 #:use-module ((ice-9 ftw) #:select (scandir))
44 #:autoload (gnu packages) (cache-is-authoritative?)
43 #:export (guix-shell)) 45 #:export (guix-shell))
44 46
45(define (show-help) 47(define (show-help)
@@ -201,51 +203,35 @@ a hash-prefixed comment, or a blank line."
201 (const #f))) 203 (const #f)))
202 204
203(define (options-with-caching opts) 205(define (options-with-caching opts)
204 "If OPTS contains exactly one 'load' or one 'manifest' key, automatically 206 "If OPTS contains only options that allow us to compute a cache key,
205add a 'profile' key (when a profile for that file is already in cache) or a 207automatically add a 'profile' key (when a profile for that file is already in
206'gc-root' key (to add the profile to cache)." 208cache) or a 'gc-root' key (to add the profile to cache)."
207 (define (single-file-for-caching opts) 209 ;; Attempt to compute a file name for use as the cached profile GC root.
208 (let loop ((opts opts) 210 (let* ((root timestamp (profile-cached-gc-root opts))
209 (file #f)) 211 (stat (and root (false-if-exception (lstat root)))))
210 (match opts 212 (if (and (not (assoc-ref opts 'rebuild-cache?))
211 (() file) 213 stat
212 ((('package . _) . _) #f) 214 (<= timestamp (stat:mtime stat)))
213 ((('load . ('package candidate)) . rest) 215 (let ((now (current-time)))
214 (and (not file) (loop rest candidate))) 216 ;; Update the atime on ROOT to reflect usage.
215 ((('manifest . candidate) . rest) 217 (utime root
216 (and (not file) (loop rest candidate))) 218 now (stat:mtime stat) 0 (stat:mtimensec stat)
217 ((('expression . _) . _) #f) 219 AT_SYMLINK_NOFOLLOW)
218 ((_ . rest) (loop rest file))))) 220 (alist-cons 'profile root
219 221 (remove (match-lambda
220 ;; Check whether there's a single 'load' or 'manifest' option. When that is 222 (('load . _) #t)
221 ;; the case, arrange to automatically cache the resulting profile. 223 (('manifest . _) #t)
222 (match (single-file-for-caching opts) 224 (('package . _) #t)
223 (#f opts) 225 (('ad-hoc-package . _) #t)
224 (file 226 (_ #f))
225 (let* ((root (profile-cached-gc-root file)) 227 opts))) ;load right away
226 (stat (and root (false-if-exception (lstat root))))) 228 (if (and root (not (assq-ref opts 'gc-root)))
227 (if (and (not (assoc-ref opts 'rebuild-cache?)) 229 (begin
228 stat 230 (if stat
229 (<= (stat:mtime ((@ (guile) stat) file)) 231 (delete-file root)
230 (stat:mtime stat))) 232 (mkdir-p (dirname root)))
231 (let ((now (current-time))) 233 (alist-cons 'gc-root root opts))
232 ;; Update the atime on ROOT to reflect usage. 234 opts))))
233 (utime root
234 now (stat:mtime stat) 0 (stat:mtimensec stat)
235 AT_SYMLINK_NOFOLLOW)
236 (alist-cons 'profile root
237 (remove (match-lambda
238 (('load . _) #t)
239 (('manifest . _) #t)
240 (_ #f))
241 opts))) ;load right away
242 (if (and root (not (assq-ref opts 'gc-root)))
243 (begin
244 (if stat
245 (delete-file root)
246 (mkdir-p (dirname root)))
247 (alist-cons 'gc-root root opts))
248 opts))))))
249 235
250(define (auto-detect-manifest opts) 236(define (auto-detect-manifest opts)
251 "If OPTS do not specify packages or a manifest, load a \"guix.scm\" or 237 "If OPTS do not specify packages or a manifest, load a \"guix.scm\" or
@@ -308,28 +294,87 @@ echo ~a >> ~a
308 (make-parameter (string-append (cache-directory #:ensure? #f) 294 (make-parameter (string-append (cache-directory #:ensure? #f)
309 "/profiles"))) 295 "/profiles")))
310 296
311(define (profile-cache-key file) 297(define (profile-cache-primary-key)
298 "Return the \"primary key\" used when computing keys for the profile cache.
299Return #f if no such key can be obtained and caching cannot be
300performed--e.g., because the package cache is not authoritative."
301 (and (cache-is-authoritative?)
302 (match (current-channels)
303 (()
304 #f)
305 (((= channel-commit commits) ...)
306 (string-join commits)))))
307
308(define (profile-file-cache-key file system)
312 "Return the cache key for the profile corresponding to FILE, a 'guix.scm' or 309 "Return the cache key for the profile corresponding to FILE, a 'guix.scm' or
313'manifest.scm' file, or #f if we lack channel information." 310'manifest.scm' file, or #f if we lack channel information."
314 (match (current-channels) 311 (match (profile-cache-primary-key)
315 (() #f) 312 (#f #f)
316 (((= channel-commit commits) ...) 313 (primary-key
317 (let ((stat (stat file))) 314 (let ((stat (stat file)))
318 (bytevector->base32-string 315 (bytevector->base32-string
319 ;; Since FILE is not canonicalized, only include the device/inode 316 ;; Since FILE is not canonicalized, only include the device/inode
320 ;; numbers. XXX: In some rare cases involving Btrfs and NFS, this can 317 ;; numbers. XXX: In some rare cases involving Btrfs and NFS, this can
321 ;; be insufficient: <https://lwn.net/Articles/866582/>. 318 ;; be insufficient: <https://lwn.net/Articles/866582/>.
322 (sha256 (string->utf8 319 (sha256 (string->utf8
323 (string-append (string-join commits) ":" 320 (string-append primary-key ":" system ":"
324 (number->string (stat:dev stat)) ":" 321 (number->string (stat:dev stat)) ":"
325 (number->string (stat:ino stat)))))))))) 322 (number->string (stat:ino stat))))))))))
326 323
327(define (profile-cached-gc-root file) 324(define (profile-spec-cache-key specs system)
328 "Return the cached GC root for FILE, a 'guix.scm' or 'manifest.scm' file, or 325 "Return the cache key corresponding to SPECS built for SYSTEM, where SPECS
329#f if we lack information to cache it." 326is a list of package specs. Return #f if caching is not possible."
330 (match (profile-cache-key file) 327 (match (profile-cache-primary-key)
331 (#f #f) 328 (#f #f)
332 (key (string-append (%profile-cache-directory) "/" key)))) 329 (primary-key
330 (bytevector->base32-string
331 (sha256 (string->utf8
332 (string-append primary-key ":" system ":"
333 (object->string specs))))))))
334
335(define (profile-cached-gc-root opts)
336 "Return two values: the file name of a GC root for use as a profile cache
337for the options in OPTS, and a timestamp which, if greater than the GC root's
338mtime, indicates that the GC root is stale. If OPTS do not permit caching,
339return #f and #f."
340 (define (key->file key)
341 (string-append (%profile-cache-directory) "/" key))
342
343 (let loop ((opts opts)
344 (system (%current-system))
345 (file #f)
346 (specs '()))
347 (match opts
348 (()
349 (if file
350 (values (and=> (profile-file-cache-key file system) key->file)
351 (stat:mtime (stat file)))
352 (values (and=> (profile-spec-cache-key specs system) key->file)
353 0)))
354 (((and spec ('package . _)) . rest)
355 (if (not file)
356 (loop rest system file (cons spec specs))
357 (values #f #f)))
358 ((('load . ('package candidate)) . rest)
359 (if (and (not file) (null? specs))
360 (loop rest system candidate specs)
361 (values #f #f)))
362 ((('manifest . candidate) . rest)
363 (if (and (not file) (null? specs))
364 (loop rest system candidate specs)
365 (values #f #f)))
366 ((('expression . _) . _)
367 ;; Arbitrary expressions might be non-deterministic or otherwise depend
368 ;; on external state so do not cache when they're used.
369 (values #f #f))
370 ((((? transformation-option-key?) . _) . _)
371 ;; Transformation options are potentially "non-deterministic", or at
372 ;; least depending on external state (with-source, with-commit, etc.),
373 ;; so do not cache anything when they're used.
374 (values #f #f))
375 ((('system . system) . rest)
376 (loop rest system file specs))
377 ((_ . rest) (loop rest system file specs)))))
333 378
334 379
335;;; 380;;;
diff --git a/guix/transformations.scm b/guix/transformations.scm
index c43c00cdd38..0976f0d8245 100644
--- a/guix/transformations.scm
+++ b/guix/transformations.scm
@@ -1,5 +1,5 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2016-2022 Ludovic Courtès <ludo@gnu.org>
3;;; Copyright © 2021 Marius Bakke <marius@gnu.org> 3;;; Copyright © 2021 Marius Bakke <marius@gnu.org>
4;;; 4;;;
5;;; This file is part of GNU Guix. 5;;; This file is part of GNU Guix.
@@ -56,6 +56,7 @@
56 tuned-package 56 tuned-package
57 57
58 show-transformation-options-help 58 show-transformation-options-help
59 transformation-option-key?
59 %transformation-options)) 60 %transformation-options))
60 61
61;;; Commentary: 62;;; Commentary:
@@ -796,6 +797,12 @@ are replaced by their latest upstream version."
796 (and (eq? k key) proc))) 797 (and (eq? k key) proc)))
797 %transformations)) 798 %transformations))
798 799
800(define (transformation-option-key? key)
801 "Return true if KEY is an option key (as returned while parsing options with
802%TRANSFORMATION-OPTIONS) corresponding to a package transformation option.
803For example, (transformation-option-key? 'with-input) => #t."
804 (->bool (transformation-procedure key)))
805
799 806
800;;; 807;;;
801;;; Command-line handling. 808;;; Command-line handling.