summaryrefslogtreecommitdiff
path: root/gnu/packages.scm
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2019-01-11 17:23:39 +0100
committerLudovic Courtès <ludo@gnu.org>2019-01-15 20:24:09 +0100
commit5fbdc9a5aa63fd51c65d30fe3d30608d01fe1bc8 (patch)
treeab2940f0c7250e8267609e3db9f6e4b517bd0546 /gnu/packages.scm
parent1d90e9d7c906b1e9e94d1642bfd60c51609fd0df (diff)
channels: Compute a package cache and use it.
* gnu/packages.scm (cache-is-authoritative?, load-package-cache) (cache-lookup, generate-package-cache): New procedures. (%package-cache-file): New variable. (find-packages-by-name): Rename to... (find-packages-by-name/direct): ... this. (find-packages-by-name): Rewrite to use the package cache when 'cache-is-authoritative?' returns true. * tests/packages.scm ("find-packages-by-name + version, with cache") ("find-packages-by-name with cache"): New tests. * guix/channels.scm (package-cache-file): New procedure. (%channel-profile-hooks): New variable. (channel-instances->derivation): Use it in #:hooks. * guix/scripts/package.scm (build-and-use-profile): Add #:hooks and honor it. * guix/scripts/pull.scm (build-and-install): Pass #:hooks to UPDATE-PROFILE.
Diffstat (limited to 'gnu/packages.scm')
-rw-r--r--gnu/packages.scm127
1 files changed, 124 insertions, 3 deletions
diff --git a/gnu/packages.scm b/gnu/packages.scm
index 4a85cf4b877..6796db80a47 100644
--- a/gnu/packages.scm
+++ b/gnu/packages.scm
@@ -28,11 +28,14 @@
28 #:use-module (guix memoization) 28 #:use-module (guix memoization)
29 #:use-module ((guix build utils) 29 #:use-module ((guix build utils)
30 #:select ((package-name->name+version 30 #:select ((package-name->name+version
31 . hyphen-separated-name->name+version))) 31 . hyphen-separated-name->name+version)
32 mkdir-p))
32 #:autoload (guix profiles) (packages->manifest) 33 #:autoload (guix profiles) (packages->manifest)
33 #:use-module (guix describe) 34 #:use-module (guix describe)
34 #:use-module (ice-9 vlist) 35 #:use-module (ice-9 vlist)
35 #:use-module (ice-9 match) 36 #:use-module (ice-9 match)
37 #:autoload (ice-9 binary-ports) (put-bytevector)
38 #:autoload (system base compile) (compile)
36 #:use-module (srfi srfi-1) 39 #:use-module (srfi srfi-1)
37 #:use-module (srfi srfi-11) 40 #:use-module (srfi srfi-11)
38 #:use-module (srfi srfi-26) 41 #:use-module (srfi srfi-26)
@@ -56,7 +59,9 @@
56 59
57 specification->package 60 specification->package
58 specification->package+output 61 specification->package+output
59 specifications->manifest)) 62 specifications->manifest
63
64 generate-package-cache))
60 65
61;;; Commentary: 66;;; Commentary:
62;;; 67;;;
@@ -135,6 +140,14 @@ for system '~a'")
135 ;; Default search path for package modules. 140 ;; Default search path for package modules.
136 `((,%distro-root-directory . "gnu/packages"))) 141 `((,%distro-root-directory . "gnu/packages")))
137 142
143(define (cache-is-authoritative?)
144 "Return true if the pre-computed package cache is authoritative. It is not
145authoritative when entries have been added via GUIX_PACKAGE_PATH or '-L'
146flags."
147 (equal? (%package-module-path)
148 (append %default-package-module-path
149 (package-path-entries))))
150
138(define %package-module-path 151(define %package-module-path
139 ;; Search path for package modules. Each item must be either a directory 152 ;; Search path for package modules. Each item must be either a directory
140 ;; name or a pair whose car is a directory and whose cdr is a sub-directory 153 ;; name or a pair whose car is a directory and whose cdr is a sub-directory
@@ -183,7 +196,35 @@ is guaranteed to never traverse the same package twice."
183 init 196 init
184 modules)) 197 modules))
185 198
186(define find-packages-by-name 199(define %package-cache-file
200 ;; Location of the package cache.
201 "/lib/guix/package.cache")
202
203(define load-package-cache
204 (mlambda (profile)
205 "Attempt to load the package cache. On success return a vhash keyed by
206package names. Return #f on failure."
207 (match profile
208 (#f #f)
209 (profile
210 (catch 'system-error
211 (lambda ()
212 (define lst
213 (load-compiled (string-append profile %package-cache-file)))
214 (fold (lambda (item vhash)
215 (match item
216 (#(name version module symbol outputs
217 supported? deprecated?
218 file line column)
219 (vhash-cons name item vhash))))
220 vlist-null
221 lst))
222 (lambda args
223 (if (= ENOENT (system-error-errno args))
224 #f
225 (apply throw args))))))))
226
227(define find-packages-by-name/direct ;bypass the cache
187 (let ((packages (delay 228 (let ((packages (delay
188 (fold-packages (lambda (p r) 229 (fold-packages (lambda (p r)
189 (vhash-cons (package-name p) p r)) 230 (vhash-cons (package-name p) p r))
@@ -202,6 +243,37 @@ decreasing version order."
202 matching) 243 matching)
203 matching))))) 244 matching)))))
204 245
246(define (cache-lookup cache name)
247 "Lookup package NAME in CACHE. Return a list sorted in increasing version
248order."
249 (define (package-version<? v1 v2)
250 (version>? (vector-ref v2 1) (vector-ref v1 1)))
251
252 (sort (vhash-fold* cons '() name cache)
253 package-version<?))
254
255(define* (find-packages-by-name name #:optional version)
256 "Return the list of packages with the given NAME. If VERSION is not #f,
257then only return packages whose version is prefixed by VERSION, sorted in
258decreasing version order."
259 (define cache
260 (load-package-cache (current-profile)))
261
262 (if (and (cache-is-authoritative?) cache)
263 (match (cache-lookup cache name)
264 (#f #f)
265 ((#(_ versions modules symbols _ _ _ _ _ _) ...)
266 (fold (lambda (version* module symbol result)
267 (if (or (not version)
268 (version-prefix? version version*))
269 (cons (module-ref (resolve-interface module)
270 symbol)
271 result)
272 result))
273 '()
274 versions modules symbols)))
275 (find-packages-by-name/direct name version)))
276
205(define (find-best-packages-by-name name version) 277(define (find-best-packages-by-name name version)
206 "If version is #f, return the list of packages named NAME with the highest 278 "If version is #f, return the list of packages named NAME with the highest
207version numbers; otherwise, return the list of packages named NAME and at 279version numbers; otherwise, return the list of packages named NAME and at
@@ -218,6 +290,55 @@ VERSION."
218 (string=? (package-version p) highest)) 290 (string=? (package-version p) highest))
219 matches)))))) 291 matches))))))
220 292
293(define (generate-package-cache directory)
294 "Generate under DIRECTORY a cache of all the available packages.
295
296The primary purpose of the cache is to speed up package lookup by name such
297that we don't have to traverse and load all the package modules, thereby also
298reducing the memory footprint."
299 (define cache-file
300 (string-append directory %package-cache-file))
301
302 (define (expand-cache module symbol variable result)
303 (match (false-if-exception (variable-ref variable))
304 ((? package? package)
305 (if (hidden-package? package)
306 result
307 (cons `#(,(package-name package)
308 ,(package-version package)
309 ,(module-name module)
310 ,symbol
311 ,(package-outputs package)
312 ,(->bool (member (%current-system)
313 (package-supported-systems package)))
314 ,(->bool (package-superseded package))
315 ,@(let ((loc (package-location package)))
316 (if loc
317 `(,(location-file loc)
318 ,(location-line loc)
319 ,(location-column loc))
320 '(#f #f #f))))
321 result)))
322 (_
323 result)))
324
325 (define exp
326 (fold-module-public-variables* expand-cache '()
327 (all-modules (%package-module-path)
328 #:warn
329 warn-about-load-error)))
330
331 (mkdir-p (dirname cache-file))
332 (call-with-output-file cache-file
333 (lambda (port)
334 ;; Store the cache as a '.go' file. This makes loading fast and reduces
335 ;; heap usage since some of the static data is directly mmapped.
336 (put-bytevector port
337 (compile `'(,@exp)
338 #:to 'bytecode
339 #:opts '(#:to-file? #t)))))
340 cache-file)
341
221 342
222(define %sigint-prompt 343(define %sigint-prompt
223 ;; The prompt to jump to upon SIGINT. 344 ;; The prompt to jump to upon SIGINT.