download: Remove Guile 2.0 workaround.
[jackhill/guix/guix.git] / guix / store.scm
CommitLineData
233e7676 1;;; GNU Guix --- Functional package management for GNU
a65177a6 2;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
f3a42251 3;;; Copyright © 2018 Jan Nieuwenhuizen <janneke@gnu.org>
77d3cf08 4;;;
233e7676 5;;; This file is part of GNU Guix.
77d3cf08 6;;;
233e7676 7;;; GNU Guix is free software; you can redistribute it and/or modify it
77d3cf08
LC
8;;; under the terms of the GNU General Public License as published by
9;;; the Free Software Foundation; either version 3 of the License, or (at
10;;; your option) any later version.
11;;;
233e7676 12;;; GNU Guix is distributed in the hope that it will be useful, but
77d3cf08
LC
13;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;;; GNU General Public License for more details.
16;;;
17;;; You should have received a copy of the GNU General Public License
233e7676 18;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
77d3cf08
LC
19
20(define-module (guix store)
82058eff 21 #:use-module (guix utils)
d8eea3d2 22 #:use-module (guix config)
f9704f17 23 #:use-module (guix memoization)
0f41c26f 24 #:use-module (guix serialization)
e87f0591 25 #:use-module (guix monads)
c6080c32 26 #:use-module (guix records)
4c0c4db0 27 #:use-module (guix base16)
cd041b26 28 #:use-module (guix base32)
ca719424 29 #:use-module (gcrypt hash)
03870da8 30 #:use-module (guix profiling)
b0a6a971 31 #:autoload (guix build syscalls) (terminal-columns)
77d3cf08 32 #:use-module (rnrs bytevectors)
2535635f 33 #:use-module (ice-9 binary-ports)
c6080c32 34 #:use-module ((ice-9 control) #:select (let/ec))
77d3cf08
LC
35 #:use-module (srfi srfi-1)
36 #:use-module (srfi srfi-9)
bf8e7fc5 37 #:use-module (srfi srfi-9 gnu)
6581ec9a 38 #:use-module (srfi srfi-11)
77d3cf08 39 #:use-module (srfi srfi-26)
e87088c9
LC
40 #:use-module (srfi srfi-34)
41 #:use-module (srfi srfi-35)
26bbbb95 42 #:use-module (srfi srfi-39)
77d3cf08 43 #:use-module (ice-9 match)
e3d74106 44 #:use-module (ice-9 regex)
3f1e6939 45 #:use-module (ice-9 vlist)
6bfec3ed 46 #:use-module (ice-9 popen)
b100a704 47 #:use-module (ice-9 threads)
1f3ea898 48 #:use-module (ice-9 format)
1397b422
LC
49 #:use-module (web uri)
50 #:export (%daemon-socket-uri
a9d2a105 51 %gc-roots-directory
f8a8e0fe 52 %default-substitute-urls
9fd72fb1
LC
53
54 nix-server?
dc0f74e5 55 nix-server-version
77d3cf08
LC
56 nix-server-major-version
57 nix-server-minor-version
58 nix-server-socket
dc0f74e5 59 current-store-protocol-version ;for internal use
c6080c32 60 mcached
77d3cf08 61
e87088c9 62 &nix-error nix-error?
ef86c39f
LC
63 &nix-connection-error nix-connection-error?
64 nix-connection-error-file
65 nix-connection-error-code
e87088c9
LC
66 &nix-protocol-error nix-protocol-error?
67 nix-protocol-error-message
68 nix-protocol-error-status
69
26bbbb95 70 hash-algo
07e70f48 71 build-mode
26bbbb95 72
77d3cf08 73 open-connection
2f608c14 74 port->connection
3abaf0c4 75 close-connection
ce4a4829 76 with-store
77d3cf08 77 set-build-options
4f740b67 78 set-build-options*
31ef99a8 79 valid-path?
82058eff 80 query-path-hash
11e7a6cf 81 hash-part->path
533d1768 82 query-path-info
0d268c5d 83 add-data-to-store
77d3cf08
LC
84 add-text-to-store
85 add-to-store
7f11efba 86 add-file-tree-to-store
f3a42251 87 binary-file
abac874b
LC
88 build-things
89 build
16748d80
LC
90 query-failed-paths
91 clear-failed-paths
3259877d 92 add-temp-root
34811f02 93 add-indirect-root
a9d2a105
LC
94 add-permanent-root
95 remove-permanent-root
26bbbb95 96
0f3d2504
LC
97 substitutable?
98 substitutable-path
99 substitutable-deriver
100 substitutable-references
101 substitutable-download-size
102 substitutable-nar-size
103 has-substitutes?
104 substitutable-paths
105 substitutable-path-info
106
533d1768
DT
107 path-info?
108 path-info-deriver
109 path-info-hash
110 path-info-references
111 path-info-registration-time
112 path-info-nar-size
113
f9aefa2d 114 built-in-builders
fae31edc 115 references
6581ec9a 116 references/substitutes
e74f64b9 117 references*
0744a9f0 118 query-path-info*
3f1e6939 119 requisites
fae31edc 120 referrers
e3fd0ce6 121 optimize-store
c63d9403 122 verify-store
50add477 123 topologically-sorted
fae31edc
LC
124 valid-derivers
125 query-derivation-outputs
3259877d
LC
126 live-paths
127 dead-paths
128 collect-garbage
129 delete-paths
526382ff
LC
130 import-paths
131 export-paths
3259877d 132
dcee50c1
LC
133 current-build-output-port
134
e87f0591
LC
135 %store-monad
136 store-bind
137 store-return
138 store-lift
023d9892 139 store-lower
e87f0591
LC
140 run-with-store
141 %guile-for-build
98a7b528
LC
142 current-system
143 set-current-system
e87f0591
LC
144 text-file
145 interned-file
7f11efba 146 interned-file-tree
e87f0591 147
26bbbb95 148 %store-prefix
cd041b26
LC
149 store-path
150 output-path
151 fixed-output-path
26bbbb95 152 store-path?
9336e5b5 153 direct-store-path?
e3d74106 154 derivation-path?
2c6ab6cc 155 store-path-package-name
eddd4077 156 store-path-hash-part
cdb5b075 157 direct-store-path
fb94d82b 158 derivation-log-file
eddd4077 159 log-file))
77d3cf08 160
6ef61cc4 161(define %protocol-version #x163)
77d3cf08 162
d66b704b
LC
163(define %worker-magic-1 #x6e697863) ; "nixc"
164(define %worker-magic-2 #x6478696f) ; "dxio"
77d3cf08
LC
165
166(define (protocol-major magic)
167 (logand magic #xff00))
168(define (protocol-minor magic)
169 (logand magic #x00ff))
dc0f74e5
LC
170(define (protocol-version major minor)
171 (logior major minor))
77d3cf08
LC
172
173(define-syntax define-enumerate-type
174 (syntax-rules ()
175 ((_ name->int (name id) ...)
176 (define-syntax name->int
177 (syntax-rules (name ...)
178 ((_ name) id) ...)))))
179
180(define-enumerate-type operation-id
181 ;; operation numbers from worker-protocol.hh
182 (quit 0)
183 (valid-path? 1)
184 (has-substitutes? 3)
185 (query-path-hash 4)
186 (query-references 5)
187 (query-referrers 6)
188 (add-to-store 7)
189 (add-text-to-store 8)
abac874b 190 (build-things 9)
77d3cf08
LC
191 (ensure-path 10)
192 (add-temp-root 11)
193 (add-indirect-root 12)
194 (sync-with-gc 13)
195 (find-roots 14)
196 (export-path 16)
197 (query-deriver 18)
198 (set-options 19)
199 (collect-garbage 20)
63193ebf 200 ;;(query-substitutable-path-info 21) ; obsolete as of #x10c
77d3cf08 201 (query-derivation-outputs 22)
63193ebf 202 (query-all-valid-paths 23)
77d3cf08
LC
203 (query-failed-paths 24)
204 (clear-failed-paths 25)
205 (query-path-info 26)
206 (import-paths 27)
63193ebf
LC
207 (query-derivation-output-names 28)
208 (query-path-from-hash-part 29)
209 (query-substitutable-path-infos 30)
210 (query-valid-paths 31)
fae31edc 211 (query-substitutable-paths 32)
e3fd0ce6 212 (query-valid-derivers 33)
c63d9403 213 (optimize-store 34)
f9aefa2d
LC
214 (verify-store 35)
215 (built-in-builders 80))
77d3cf08
LC
216
217(define-enumerate-type hash-algo
218 ;; hash.hh
219 (md5 1)
220 (sha1 2)
221 (sha256 3))
222
07e70f48
LC
223(define-enumerate-type build-mode
224 ;; store-api.hh
225 (normal 0)
226 (repair 1)
227 (check 2))
228
3259877d
LC
229(define-enumerate-type gc-action
230 ;; store-api.hh
231 (return-live 0)
232 (return-dead 1)
233 (delete-dead 2)
234 (delete-specific 3))
235
77d3cf08 236(define %default-socket-path
80d0447c 237 (string-append %state-directory "/daemon-socket/socket"))
77d3cf08 238
1397b422
LC
239(define %daemon-socket-uri
240 ;; URI or file name of the socket the daemon listens too.
9fd72fb1
LC
241 (make-parameter (or (getenv "GUIX_DAEMON_SOCKET")
242 %default-socket-path)))
243
244
77d3cf08 245\f
0f3d2504
LC
246;; Information about a substitutable store path.
247(define-record-type <substitutable>
248 (substitutable path deriver refs dl-size nar-size)
249 substitutable?
250 (path substitutable-path)
251 (deriver substitutable-deriver)
252 (refs substitutable-references)
253 (dl-size substitutable-download-size)
254 (nar-size substitutable-nar-size))
255
256(define (read-substitutable-path-list p)
257 (let loop ((len (read-int p))
258 (result '()))
259 (if (zero? len)
260 (reverse result)
261 (let ((path (read-store-path p))
262 (deriver (read-store-path p))
263 (refs (read-store-path-list p))
264 (dl-size (read-long-long p))
265 (nar-size (read-long-long p)))
266 (loop (- len 1)
267 (cons (substitutable path deriver refs dl-size nar-size)
268 result))))))
269
533d1768
DT
270;; Information about a store path.
271(define-record-type <path-info>
272 (path-info deriver hash references registration-time nar-size)
273 path-info?
22572d56 274 (deriver path-info-deriver) ;string | #f
533d1768
DT
275 (hash path-info-hash)
276 (references path-info-references)
277 (registration-time path-info-registration-time)
278 (nar-size path-info-nar-size))
279
280(define (read-path-info p)
22572d56
LC
281 (let ((deriver (match (read-store-path p)
282 ("" #f)
283 (x x)))
533d1768
DT
284 (hash (base16-string->bytevector (read-string p)))
285 (refs (read-store-path-list p))
286 (registration-time (read-int p))
287 (nar-size (read-long-long p)))
288 (path-info deriver hash refs registration-time nar-size)))
289
77d3cf08 290(define-syntax write-arg
0d268c5d
LC
291 (syntax-rules (integer boolean bytevector
292 string string-list string-pairs
3259877d 293 store-path store-path-list base16)
77d3cf08
LC
294 ((_ integer arg p)
295 (write-int arg p))
296 ((_ boolean arg p)
297 (write-int (if arg 1 0) p))
0d268c5d
LC
298 ((_ bytevector arg p)
299 (write-bytevector arg p))
77d3cf08
LC
300 ((_ string arg p)
301 (write-string arg p))
302 ((_ string-list arg p)
82058eff 303 (write-string-list arg p))
6c20d1d0
LC
304 ((_ string-pairs arg p)
305 (write-string-pairs arg p))
3259877d
LC
306 ((_ store-path arg p)
307 (write-store-path arg p))
308 ((_ store-path-list arg p)
309 (write-store-path-list arg p))
82058eff
LC
310 ((_ base16 arg p)
311 (write-string (bytevector->base16-string arg) p))))
77d3cf08
LC
312
313(define-syntax read-arg
f9aefa2d 314 (syntax-rules (integer boolean string store-path store-path-list string-list
533d1768 315 substitutable-path-list path-info base16)
77d3cf08
LC
316 ((_ integer p)
317 (read-int p))
318 ((_ boolean p)
319 (not (zero? (read-int p))))
320 ((_ string p)
321 (read-string p))
322 ((_ store-path p)
82058eff 323 (read-store-path p))
3259877d
LC
324 ((_ store-path-list p)
325 (read-store-path-list p))
f9aefa2d
LC
326 ((_ string-list p)
327 (read-string-list p))
0f3d2504
LC
328 ((_ substitutable-path-list p)
329 (read-substitutable-path-list p))
533d1768
DT
330 ((_ path-info p)
331 (read-path-info p))
0f3d2504 332 ((_ base16 p)
82058eff 333 (base16-string->bytevector (read-string p)))))
77d3cf08
LC
334
335\f
336;; remote-store.cc
337
c6080c32 338(define-record-type* <nix-server> nix-server %make-nix-server
77d3cf08
LC
339 nix-server?
340 (socket nix-server-socket)
341 (major nix-server-major-version)
2c3f47ee
LC
342 (minor nix-server-minor-version)
343
e037e9db
LC
344 (buffer nix-server-output-port) ;output port
345 (flush nix-server-flush-output) ;thunk
346
2c3f47ee
LC
347 ;; Caches. We keep them per-connection, because store paths build
348 ;; during the session are temporary GC roots kept for the duration of
349 ;; the session.
bdcf35a6 350 (ats-cache nix-server-add-to-store-cache)
c6080c32
LC
351 (atts-cache nix-server-add-text-to-store-cache)
352 (object-cache nix-server-object-cache
353 (default vlist-null))) ;vhash
77d3cf08 354
bf8e7fc5
LC
355(set-record-type-printer! <nix-server>
356 (lambda (obj port)
357 (format port "#<build-daemon ~a.~a ~a>"
358 (nix-server-major-version obj)
359 (nix-server-minor-version obj)
360 (number->string (object-address obj)
361 16))))
362
e87088c9
LC
363(define-condition-type &nix-error &error
364 nix-error?)
365
ef86c39f
LC
366(define-condition-type &nix-connection-error &nix-error
367 nix-connection-error?
368 (file nix-connection-error-file)
369 (errno nix-connection-error-code))
370
e87088c9
LC
371(define-condition-type &nix-protocol-error &nix-error
372 nix-protocol-error?
373 (message nix-protocol-error-message)
374 (status nix-protocol-error-status))
375
3b5cd17a
LC
376(define-syntax-rule (system-error-to-connection-error file exp ...)
377 "Catch 'system-error' exceptions and translate them to
378'&nix-connection-error'."
379 (catch 'system-error
380 (lambda ()
381 exp ...)
382 (lambda args
383 (let ((errno (system-error-errno args)))
384 (raise (condition (&nix-connection-error
385 (file file)
386 (errno errno))))))))
387
6230d6f0
LC
388(define (open-unix-domain-socket file)
389 "Connect to the Unix-domain socket at FILE and return it. Raise a
390'&nix-connection-error' upon error."
77d3cf08
LC
391 (let ((s (with-fluids ((%default-port-encoding #f))
392 ;; This trick allows use of the `scm_c_read' optimization.
393 (socket PF_UNIX SOCK_STREAM 0)))
394 (a (make-socket-address PF_UNIX file)))
df1fab58 395
3b5cd17a
LC
396 (system-error-to-connection-error file
397 (connect s a)
398 s)))
ef86c39f 399
5df1395a
LC
400(define %default-guix-port
401 ;; Default port when connecting to a daemon over TCP/IP.
402 44146)
403
3dff90ce
LC
404(define (open-inet-socket host port)
405 "Connect to the Unix-domain socket at HOST:PORT and return it. Raise a
406'&nix-connection-error' upon error."
407 (let ((sock (with-fluids ((%default-port-encoding #f))
408 ;; This trick allows use of the `scm_c_read' optimization.
409 (socket PF_UNIX SOCK_STREAM 0))))
410 (define addresses
411 (getaddrinfo host
412 (if (number? port) (number->string port) port)
413 (if (number? port)
414 (logior AI_ADDRCONFIG AI_NUMERICSERV)
7ae97a4c
LC
415 AI_ADDRCONFIG)
416 0 ;any address family
417 SOCK_STREAM)) ;TCP only
3dff90ce
LC
418
419 (let loop ((addresses addresses))
420 (match addresses
421 ((ai rest ...)
422 (let ((s (socket (addrinfo:fam ai)
423 ;; TCP/IP only
424 SOCK_STREAM IPPROTO_IP)))
425
426 (catch 'system-error
427 (lambda ()
428 (connect s (addrinfo:addr ai))
950d51c9
LC
429
430 ;; Setting this option makes a dramatic difference because it
431 ;; avoids the "ACK delay" on our RPC messages.
432 (setsockopt s IPPROTO_TCP TCP_NODELAY 1)
3dff90ce
LC
433 s)
434 (lambda args
435 ;; Connection failed, so try one of the other addresses.
436 (close s)
437 (if (null? rest)
438 (raise (condition (&nix-connection-error
439 (file host)
440 (errno (system-error-errno args)))))
441 (loop rest))))))))))
442
1397b422
LC
443(define (connect-to-daemon uri)
444 "Connect to the daemon at URI, a string that may be an actual URI or a file
445name."
285f63e8
LC
446 (define (not-supported)
447 (raise (condition (&nix-connection-error
448 (file uri)
449 (errno ENOTSUP)))))
450
1397b422
LC
451 (define connect
452 (match (string->uri uri)
453 (#f ;URI is a file name
454 open-unix-domain-socket)
455 ((? uri? uri)
456 (match (uri-scheme uri)
457 ((or #f 'file 'unix)
458 (lambda (_)
459 (open-unix-domain-socket (uri-path uri))))
3dff90ce
LC
460 ('guix
461 (lambda (_)
5df1395a
LC
462 (open-inet-socket (uri-host uri)
463 (or (uri-port uri) %default-guix-port))))
285f63e8
LC
464 ((? symbol? scheme)
465 ;; Try to dynamically load a module for SCHEME.
466 ;; XXX: Errors are swallowed.
467 (match (false-if-exception
468 (resolve-interface `(guix store ,scheme)))
469 ((? module? module)
470 (match (false-if-exception
471 (module-ref module 'connect-to-daemon))
472 ((? procedure? connect)
473 (lambda (_)
474 (connect uri)))
475 (x (not-supported))))
476 (#f (not-supported))))
1397b422 477 (x
285f63e8 478 (not-supported))))))
1397b422
LC
479
480 (connect uri))
481
482(define* (open-connection #:optional (uri (%daemon-socket-uri))
6230d6f0 483 #:key port (reserve-space? #t) cpu-affinity)
1397b422
LC
484 "Connect to the daemon at URI (a string), or, if PORT is not #f, use it as
485the I/O port over which to communicate to a build daemon.
6230d6f0
LC
486
487When RESERVE-SPACE? is true, instruct it to reserve a little bit of extra
488space on the file system so that the garbage collector can still operate,
489should the disk become full. When CPU-AFFINITY is true, it must be an integer
490corresponding to an OS-level CPU number to which the daemon's worker process
491for this connection will be pinned. Return a server object."
13d5e8da
LC
492 (guard (c ((nar-error? c)
493 ;; One of the 'write-' or 'read-' calls below failed, but this is
494 ;; really a connection error.
495 (raise (condition
1397b422 496 (&nix-connection-error (file (or port uri))
13d5e8da
LC
497 (errno EPROTO))
498 (&message (message "build daemon handshake failed"))))))
e037e9db
LC
499 (let*-values (((port)
500 (or port (connect-to-daemon uri)))
501 ((output flush)
502 (buffering-output-port port
503 (make-bytevector 8192))))
13d5e8da
LC
504 (write-int %worker-magic-1 port)
505 (let ((r (read-int port)))
506 (and (eqv? r %worker-magic-2)
507 (let ((v (read-int port)))
508 (and (eqv? (protocol-major %protocol-version)
509 (protocol-major v))
510 (begin
511 (write-int %protocol-version port)
512 (when (>= (protocol-minor v) 14)
513 (write-int (if cpu-affinity 1 0) port)
514 (when cpu-affinity
515 (write-int cpu-affinity port)))
516 (when (>= (protocol-minor v) 11)
517 (write-int (if reserve-space? 1 0) port))
518 (let ((conn (%make-nix-server port
519 (protocol-major v)
520 (protocol-minor v)
e037e9db 521 output flush
13d5e8da 522 (make-hash-table 100)
c6080c32
LC
523 (make-hash-table 100)
524 vlist-null)))
13d5e8da
LC
525 (let loop ((done? (process-stderr conn)))
526 (or done? (process-stderr conn)))
527 conn)))))))))
77d3cf08 528
2f608c14
LC
529(define* (port->connection port
530 #:key (version %protocol-version))
531 "Assimilate PORT, an input/output port, and return a connection to the
532daemon, assuming the given protocol VERSION.
533
534Warning: this procedure assumes that the initial handshake with the daemon has
535already taken place on PORT and that we're just continuing on this established
536connection. Use with care."
537 (let-values (((output flush)
538 (buffering-output-port port (make-bytevector 8192))))
539 (%make-nix-server port
540 (protocol-major version)
541 (protocol-minor version)
542 output flush
543 (make-hash-table 100)
c6080c32
LC
544 (make-hash-table 100)
545 vlist-null)))
2f608c14 546
dc0f74e5
LC
547(define (nix-server-version store)
548 "Return the protocol version of STORE as an integer."
549 (protocol-version (nix-server-major-version store)
550 (nix-server-minor-version store)))
551
e037e9db
LC
552(define (write-buffered-output server)
553 "Flush SERVER's output port."
554 (force-output (nix-server-output-port server))
555 ((nix-server-flush-output server)))
556
3abaf0c4
LC
557(define (close-connection server)
558 "Close the connection to SERVER."
559 (close (nix-server-socket server)))
560
ce4a4829
LC
561(define-syntax-rule (with-store store exp ...)
562 "Bind STORE to an open connection to the store and evaluate EXPs;
563automatically close the store when the dynamic extent of EXP is left."
564 (let ((store (open-connection)))
565 (dynamic-wind
566 (const #f)
567 (lambda ()
dc0f74e5
LC
568 (parameterize ((current-store-protocol-version
569 (nix-server-version store)))
570 exp) ...)
ce4a4829
LC
571 (lambda ()
572 (false-if-exception (close-connection store))))))
573
dc0f74e5
LC
574(define current-store-protocol-version
575 ;; Protocol version of the store currently used. XXX: This is a hack to
576 ;; communicate the protocol version to the build output port. It's a hack
577 ;; because it could be inaccurrate, for instance if there's code that
578 ;; manipulates several store connections at once; it works well for the
579 ;; purposes of (guix status) though.
580 (make-parameter #f))
581
dcee50c1
LC
582(define current-build-output-port
583 ;; The port where build output is sent.
584 (make-parameter (current-error-port)))
585
526382ff
LC
586(define* (dump-port in out
587 #:optional len
588 #:key (buffer-size 16384))
589 "Read LEN bytes from IN (or as much as possible if LEN is #f) and write it
590to OUT, using chunks of BUFFER-SIZE bytes."
591 (define buffer
592 (make-bytevector buffer-size))
593
594 (let loop ((total 0)
595 (bytes (get-bytevector-n! in buffer 0
596 (if len
597 (min len buffer-size)
598 buffer-size))))
599 (or (eof-object? bytes)
600 (and len (= total len))
601 (let ((total (+ total bytes)))
602 (put-bytevector out buffer 0 bytes)
603 (loop total
604 (get-bytevector-n! in buffer 0
605 (if len
606 (min (- len total) buffer-size)
607 buffer-size)))))))
608
d28869af
LC
609(define %newlines
610 ;; Newline characters triggering a flush of 'current-build-output-port'.
611 ;; Unlike Guile's _IOLBF, we flush upon #\return so that progress reports
612 ;; that use that trick are correctly displayed.
613 (char-set #\newline #\return))
614
526382ff 615(define* (process-stderr server #:optional user-port)
dcee50c1
LC
616 "Read standard output and standard error from SERVER, writing it to
617CURRENT-BUILD-OUTPUT-PORT. Return #t when SERVER is done sending data, and
618#f otherwise; in the latter case, the caller should call `process-stderr'
bbdb3ffa
LC
619again until #t is returned or an error is raised.
620
621Since the build process's output cannot be assumed to be UTF-8, we
622conservatively consider it to be Latin-1, thereby avoiding possible
623encoding conversion errors."
77d3cf08
LC
624 (define p
625 (nix-server-socket server))
626
627 ;; magic cookies from worker-protocol.hh
5674a3fd
LC
628 (define %stderr-next #x6f6c6d67) ; "olmg", build log
629 (define %stderr-read #x64617461) ; "data", data needed from source
630 (define %stderr-write #x64617416) ; "dat\x16", data for sink
631 (define %stderr-last #x616c7473) ; "alts", we're done
632 (define %stderr-error #x63787470) ; "cxtp", error reporting
77d3cf08
LC
633
634 (let ((k (read-int p)))
635 (cond ((= k %stderr-write)
526382ff
LC
636 ;; Write a byte stream to USER-PORT.
637 (let* ((len (read-int p))
638 (m (modulo len 8)))
6374633b
LC
639 (dump-port p user-port len
640 #:buffer-size (if (<= len 16384) 16384 65536))
526382ff
LC
641 (unless (zero? m)
642 ;; Consume padding, as for strings.
643 (get-bytevector-n p (- 8 m))))
dcee50c1 644 #f)
77d3cf08 645 ((= k %stderr-read)
526382ff 646 ;; Read a byte stream from USER-PORT.
5895f244
LC
647 ;; Note: Avoid 'get-bytevector-n' to work around
648 ;; <http://bugs.gnu.org/17591> in Guile up to 2.0.11.
526382ff 649 (let* ((max-len (read-int p))
5895f244
LC
650 (data (make-bytevector max-len))
651 (len (get-bytevector-n! user-port data 0 max-len)))
39d1e965 652 (write-bytevector data p len)
dcee50c1 653 #f))
77d3cf08 654 ((= k %stderr-next)
ce72c780
LC
655 ;; Log a string. Build logs are usually UTF-8-encoded, but they
656 ;; may also contain arbitrary byte sequences that should not cause
657 ;; this to fail. Thus, use the permissive
658 ;; 'read-maybe-utf8-string'.
659 (let ((s (read-maybe-utf8-string p)))
dcee50c1 660 (display s (current-build-output-port))
d28869af 661 (when (string-any %newlines s)
2535635f 662 (force-output (current-build-output-port)))
dcee50c1 663 #f))
77d3cf08 664 ((= k %stderr-error)
526382ff 665 ;; Report an error.
ce72c780 666 (let ((error (read-maybe-utf8-string p))
0ff3e3aa
LC
667 ;; Currently the daemon fails to send a status code for early
668 ;; errors like DB schema version mismatches, so check for EOF.
669 (status (if (and (>= (nix-server-minor-version server) 8)
670 (not (eof-object? (lookahead-u8 p))))
77d3cf08
LC
671 (read-int p)
672 1)))
e87088c9
LC
673 (raise (condition (&nix-protocol-error
674 (message error)
675 (status status))))))
77d3cf08 676 ((= k %stderr-last)
dcee50c1 677 ;; The daemon is done (see `stopWork' in `nix-worker.cc'.)
77d3cf08
LC
678 #t)
679 (else
e87088c9
LC
680 (raise (condition (&nix-protocol-error
681 (message "invalid error code")
682 (status k))))))))
77d3cf08 683
4d581220 684(define %default-substitute-urls
d70533cb
LC
685 ;; Default list of substituters. This is *not* the list baked in
686 ;; 'guix-daemon', but it is used by 'guix-service-type' and and a couple of
687 ;; clients ('guix build --log-file' uses it.)
df061d07
LC
688 (map (if (false-if-exception (resolve-interface '(gnutls)))
689 (cut string-append "https://" <>)
690 (cut string-append "http://" <>))
0a5fa004 691 '("ci.guix.info")))
4d581220 692
77d3cf08 693(define* (set-build-options server
c3eb878f 694 #:key keep-failed? keep-going? fallback?
77d3cf08 695 (verbosity 0)
2fba87ac 696 rounds ;number of build rounds
deac976d 697 max-build-jobs
6c20d1d0 698 timeout
deac976d 699 max-silent-time
77d3cf08
LC
700 (use-build-hook? #t)
701 (build-verbosity 0)
702 (log-type 0)
e036c31b 703 (print-build-trace #t)
dc0f74e5
LC
704
705 ;; When true, provide machine-readable "build
706 ;; traces" for use by (guix status). Old clients
707 ;; are unable to make sense, which is why it's
708 ;; disabled by default.
709 print-extended-build-trace?
710
6ef61cc4
LC
711 ;; When true, the daemon prefixes builder output
712 ;; with "@ build-log" traces so we can
713 ;; distinguish it from daemon output, and we can
714 ;; distinguish each builder's output
715 ;; (PRINT-BUILD-TRACE must be true as well.) The
716 ;; latter is particularly useful when
717 ;; MAX-BUILD-JOBS > 1.
718 multiplexed-build-output?
719
deac976d 720 build-cores
63193ebf 721 (use-substitutes? #t)
4d581220 722
fb4bf72b
LC
723 ;; Client-provided substitute URLs. If it is #f,
724 ;; the daemon's settings are used. Otherwise, it
725 ;; overrides the daemons settings; see 'guix
726 ;; substitute'.
b0a6a971
LC
727 (substitute-urls #f)
728
729 ;; Number of columns in the client's terminal.
38f50f49
LC
730 (terminal-columns (terminal-columns))
731
732 ;; Locale of the client.
733 (locale (false-if-exception (setlocale LC_ALL))))
77d3cf08
LC
734 ;; Must be called after `open-connection'.
735
736 (define socket
737 (nix-server-socket server))
738
739 (let-syntax ((send (syntax-rules ()
e036c31b
LC
740 ((_ (type option) ...)
741 (begin
742 (write-arg type option socket)
743 ...)))))
744 (write-int (operation-id set-options) socket)
745 (send (boolean keep-failed?) (boolean keep-going?)
deac976d
LC
746 (boolean fallback?) (integer verbosity))
747 (when (< (nix-server-minor-version server) #x61)
748 (let ((max-build-jobs (or max-build-jobs 1))
749 (max-silent-time (or max-silent-time 3600)))
750 (send (integer max-build-jobs) (integer max-silent-time))))
371e87d2
LC
751 (when (>= (nix-server-minor-version server) 2)
752 (send (boolean use-build-hook?)))
753 (when (>= (nix-server-minor-version server) 4)
754 (send (integer build-verbosity) (integer log-type)
755 (boolean print-build-trace)))
deac976d
LC
756 (when (and (>= (nix-server-minor-version server) 6)
757 (< (nix-server-minor-version server) #x61))
758 (let ((build-cores (or build-cores (current-processor-count))))
759 (send (integer build-cores))))
371e87d2
LC
760 (when (>= (nix-server-minor-version server) 10)
761 (send (boolean use-substitutes?)))
762 (when (>= (nix-server-minor-version server) 12)
dc0f74e5
LC
763 (let ((pairs `(;; This option is honored by 'guix substitute' et al.
764 ,@(if print-build-trace
765 `(("print-extended-build-trace"
766 . ,(if print-extended-build-trace? "1" "0")))
767 '())
6ef61cc4
LC
768 ,@(if multiplexed-build-output?
769 `(("multiplexed-build-output"
770 . ,(if multiplexed-build-output? "true" "false")))
771 '())
dc0f74e5 772 ,@(if timeout
41c45e78
LC
773 `(("build-timeout" . ,(number->string timeout)))
774 '())
deac976d
LC
775 ,@(if max-silent-time
776 `(("build-max-silent-time"
777 . ,(number->string max-silent-time)))
778 '())
779 ,@(if max-build-jobs
780 `(("build-max-jobs"
781 . ,(number->string max-build-jobs)))
782 '())
783 ,@(if build-cores
784 `(("build-cores" . ,(number->string build-cores)))
785 '())
fb4bf72b
LC
786 ,@(if substitute-urls
787 `(("substitute-urls"
788 . ,(string-join substitute-urls)))
2fba87ac
LC
789 '())
790 ,@(if rounds
791 `(("build-repeat"
792 . ,(number->string (max 0 (1- rounds)))))
b0a6a971
LC
793 '())
794 ,@(if terminal-columns
795 `(("terminal-columns"
796 . ,(number->string terminal-columns)))
38f50f49
LC
797 '())
798 ,@(if locale
799 `(("locale" . ,locale))
fb4bf72b 800 '()))))
f401b1e9 801 (send (string-pairs pairs))))
dcee50c1
LC
802 (let loop ((done? (process-stderr server)))
803 (or done? (process-stderr server)))))
77d3cf08 804
e037e9db
LC
805(define (buffering-output-port port buffer)
806 "Return two value: an output port wrapped around PORT that uses BUFFER (a
807bytevector) as its internal buffer, and a thunk to flush this output port."
808 ;; Note: In Guile 2.2.2, custom binary output ports already have their own
809 ;; 4K internal buffer.
810 (define size
811 (bytevector-length buffer))
812
813 (define total 0)
814
815 (define (flush)
816 (put-bytevector port buffer 0 total)
38098241 817 (force-output port)
e037e9db
LC
818 (set! total 0))
819
820 (define (write bv offset count)
821 (if (zero? count) ;end of file
822 (flush)
823 (let loop ((offset offset)
824 (count count)
825 (written 0))
826 (cond ((= total size)
827 (flush)
828 (loop offset count written))
829 ((zero? count)
830 written)
831 (else
832 (let ((to-copy (min count (- size total))))
833 (bytevector-copy! bv offset buffer total to-copy)
834 (set! total (+ total to-copy))
835 (loop (+ offset to-copy) (- count to-copy)
836 (+ written to-copy))))))))
837
838 ;; Note: We need to return FLUSH because the custom binary port has no way
839 ;; to be notified of a 'force-output' call on itself.
840 (values (make-custom-binary-output-port "buffering-output-port"
841 write #f #f flush)
842 flush))
843
73b0ebdd
LC
844(define profiled?
845 (let ((profiled
846 (or (and=> (getenv "GUIX_PROFILING") string-tokenize)
847 '())))
848 (lambda (component)
849 "Return true if COMPONENT profiling is active."
850 (member component profiled))))
851
f4453df9
LC
852(define %rpc-calls
853 ;; Mapping from RPC names (symbols) to invocation counts.
854 (make-hash-table))
855
856(define* (show-rpc-profile #:optional (port (current-error-port)))
857 "Write to PORT a summary of the RPCs that have been made."
858 (let ((profile (sort (hash-fold alist-cons '() %rpc-calls)
859 (lambda (rpc1 rpc2)
860 (< (cdr rpc1) (cdr rpc2))))))
861 (format port "Remote procedure call summary: ~a RPCs~%"
862 (match profile
863 (((names . counts) ...)
864 (reduce + 0 counts))))
865 (for-each (match-lambda
866 ((rpc . count)
867 (format port " ~30a ... ~5@a~%" rpc count)))
868 profile)))
869
870(define record-operation
871 ;; Optionally, increment the number of calls of the given RPC.
03870da8
LC
872 (if (profiled? "rpc")
873 (begin
874 (register-profiling-hook! "rpc" show-rpc-profile)
875 (lambda (name)
876 (let ((count (or (hashq-ref %rpc-calls name) 0)))
877 (hashq-set! %rpc-calls name (+ count 1)))))
878 (lambda (_)
879 #t)))
f4453df9 880
fd060fd3 881(define-syntax operation
77d3cf08 882 (syntax-rules ()
fd060fd3 883 "Define a client-side RPC stub for the given operation."
3259877d 884 ((_ (name (type arg) ...) docstring return ...)
fd060fd3 885 (lambda (server arg ...)
77d3cf08 886 docstring
e037e9db
LC
887 (let* ((s (nix-server-socket server))
888 (buffered (nix-server-output-port server)))
f4453df9 889 (record-operation 'name)
e037e9db
LC
890 (write-int (operation-id name) buffered)
891 (write-arg type arg buffered)
77d3cf08 892 ...
e037e9db
LC
893 (write-buffered-output server)
894
dcee50c1
LC
895 ;; Loop until the server is done sending error output.
896 (let loop ((done? (process-stderr server)))
897 (or done? (loop (process-stderr server))))
3259877d 898 (values (read-arg return s) ...))))))
77d3cf08 899
fd060fd3
LC
900(define-syntax-rule (define-operation (name args ...)
901 docstring return ...)
902 (define name
903 (operation (name args ...) docstring return ...)))
904
31ef99a8 905(define-operation (valid-path? (string path))
06b76acc
LC
906 "Return #t when PATH designates a valid store item and #f otherwise (an
907invalid item may exist on disk but still be invalid, for instance because it
908is the result of an aborted or failed build.)
909
910A '&nix-protocol-error' condition is raised if PATH is not prefixed by the
911store directory (/gnu/store)."
31ef99a8
LC
912 boolean)
913
63193ebf 914(define-operation (query-path-hash (store-path path))
aa8fff0c 915 "Return the SHA256 hash of the nar serialization of PATH as a bytevector."
82058eff
LC
916 base16)
917
11e7a6cf
LC
918(define hash-part->path
919 (let ((query-path-from-hash-part
920 (operation (query-path-from-hash-part (string hash))
921 #f
922 store-path)))
923 (lambda (server hash-part)
924 "Return the store path whose hash part is HASH-PART (a nix-base32
925string). Raise an error if no such path exists."
926 ;; This RPC is primarily used by Hydra to reply to HTTP GETs of
927 ;; /HASH.narinfo.
928 (query-path-from-hash-part server hash-part))))
929
533d1768
DT
930(define-operation (query-path-info (store-path path))
931 "Return the info (hash, references, etc.) for PATH."
932 path-info)
933
0d268c5d 934(define add-data-to-store
fd060fd3
LC
935 ;; A memoizing version of `add-to-store', to avoid repeated RPCs with
936 ;; the very same arguments during a given session.
937 (let ((add-text-to-store
0d268c5d 938 (operation (add-text-to-store (string name) (bytevector text)
fd060fd3
LC
939 (string-list references))
940 #f
941 store-path)))
0d268c5d
LC
942 (lambda* (server name bytes #:optional (references '()))
943 "Add BYTES under file NAME in the store, and return its store path.
bdcf35a6
LC
944REFERENCES is the list of store paths referred to by the resulting store
945path."
0d268c5d
LC
946 (let* ((args `(,bytes ,name ,references))
947 (cache (nix-server-add-text-to-store-cache server)))
bdcf35a6 948 (or (hash-ref cache args)
0d268c5d 949 (let ((path (add-text-to-store server name bytes references)))
bdcf35a6
LC
950 (hash-set! cache args path)
951 path))))))
952
0d268c5d
LC
953(define* (add-text-to-store store name text #:optional (references '()))
954 "Add TEXT under file NAME in the store, and return its store path.
955REFERENCES is the list of store paths referred to by the resulting store
956path."
957 (add-data-to-store store name (string->utf8 text) references))
958
1ec32f4a
LC
959(define true
960 ;; Define it once and for all since we use it as a default value for
961 ;; 'add-to-store' and want to make sure two default values are 'eq?' for the
962 ;; purposes or memoization.
963 (lambda (file stat)
964 #t))
965
fd060fd3 966(define add-to-store
a7b6ffee
LC
967 ;; A memoizing version of `add-to-store'. This is important because
968 ;; `add-to-store' leads to huge data transfers to the server, and
969 ;; because it's often called many times with the very same argument.
1ec32f4a
LC
970 (let ((add-to-store
971 (lambda* (server basename recursive? hash-algo file-name
972 #:key (select? true))
973 ;; We don't use the 'operation' macro so we can pass SELECT? to
974 ;; 'write-file'.
0ca3d556 975 (record-operation 'add-to-store)
1ec32f4a
LC
976 (let ((port (nix-server-socket server)))
977 (write-int (operation-id add-to-store) port)
978 (write-string basename port)
979 (write-int 1 port) ;obsolete, must be #t
980 (write-int (if recursive? 1 0) port)
981 (write-string hash-algo port)
982 (write-file file-name port #:select? select?)
38098241 983 (write-buffered-output server)
1ec32f4a
LC
984 (let loop ((done? (process-stderr server)))
985 (or done? (loop (process-stderr server))))
986 (read-store-path port)))))
987 (lambda* (server basename recursive? hash-algo file-name
988 #:key (select? true))
a9ebd9ef 989 "Add the contents of FILE-NAME under BASENAME to the store. When
69792b28
LC
990RECURSIVE? is false, FILE-NAME must designate a regular file--not a directory
991nor a symlink. When RECURSIVE? is true and FILE-NAME designates a directory,
992the contents of FILE-NAME are added recursively; if FILE-NAME designates a
993flat file and RECURSIVE? is true, its contents are added, and its permission
1ec32f4a
LC
994bits are kept. HASH-ALGO must be a string such as \"sha256\".
995
996When RECURSIVE? is true, call (SELECT? FILE STAT) for each directory entry,
997where FILE is the entry's absolute file name and STAT is the result of
998'lstat'; exclude entries for which SELECT? does not return true."
b4671215
LC
999 ;; Note: We don't stat FILE-NAME at each call, and thus we assume that
1000 ;; the file remains unchanged for the lifetime of SERVER.
1001 (let* ((args `(,file-name ,basename ,recursive? ,hash-algo ,select?))
2c3f47ee 1002 (cache (nix-server-add-to-store-cache server)))
b4671215 1003 (or (hash-ref cache args)
1ec32f4a
LC
1004 (let ((path (add-to-store server basename recursive?
1005 hash-algo file-name
1006 #:select? select?)))
a7b6ffee
LC
1007 (hash-set! cache args path)
1008 path))))))
1009
7f11efba
LC
1010(define %not-slash
1011 (char-set-complement (char-set #\/)))
1012
1013(define* (add-file-tree-to-store server tree
1014 #:key
1015 (hash-algo "sha256")
1016 (recursive? #t))
1017 "Add the given TREE to the store on SERVER. TREE must be an entry such as:
1018
1019 (\"my-tree\" directory
1020 (\"a\" regular (data \"hello\"))
1021 (\"b\" symlink \"a\")
1022 (\"c\" directory
1023 (\"d\" executable (file \"/bin/sh\"))))
1024
1025This is a generalized version of 'add-to-store'. It allows you to reproduce
1026an arbitrary directory layout in the store without creating a derivation."
1027
1028 ;; Note: The format of TREE was chosen to allow trees to be compared with
1029 ;; 'equal?', which in turn allows us to memoize things.
1030
1031 (define root
1032 ;; TREE is a single entry.
1033 (list tree))
1034
1035 (define basename
1036 (match tree
1037 ((name . _) name)))
1038
1039 (define (lookup file)
1040 (let loop ((components (string-tokenize file %not-slash))
1041 (tree root))
1042 (match components
1043 ((basename)
1044 (assoc basename tree))
1045 ((head . rest)
1046 (loop rest
1047 (match (assoc-ref tree head)
1048 (('directory . entries) entries)))))))
1049
1050 (define (file-type+size file)
1051 (match (lookup file)
1052 ((_ (and type (or 'directory 'symlink)) . _)
1053 (values type 0))
1054 ((_ type ('file file))
1055 (values type (stat:size (stat file))))
1056 ((_ type ('data (? string? data)))
1057 (values type (string-length data)))
1058 ((_ type ('data (? bytevector? data)))
1059 (values type (bytevector-length data)))))
1060
1061 (define (file-port file)
1062 (match (lookup file)
1063 ((_ (or 'regular 'executable) content)
1064 (match content
1065 (('file (? string? file))
1066 (open-file file "r0b"))
1067 (('data (? string? str))
1068 (open-input-string str))
1069 (('data (? bytevector? bv))
1070 (open-bytevector-input-port bv))))))
1071
1072 (define (symlink-target file)
1073 (match (lookup file)
1074 ((_ 'symlink target) target)))
1075
1076 (define (directory-entries directory)
1077 (match (lookup directory)
1078 ((_ 'directory (names . _) ...) names)))
1079
1080 (define cache
1081 (nix-server-add-to-store-cache server))
1082
1083 (or (hash-ref cache tree)
1084 (begin
1085 ;; We don't use the 'operation' macro so we can use 'write-file-tree'
1086 ;; instead of 'write-file'.
1087 (record-operation 'add-to-store/tree)
1088 (let ((port (nix-server-socket server)))
1089 (write-int (operation-id add-to-store) port)
1090 (write-string basename port)
1091 (write-int 1 port) ;obsolete, must be #t
1092 (write-int (if recursive? 1 0) port)
1093 (write-string hash-algo port)
1094 (write-file-tree basename port
1095 #:file-type+size file-type+size
1096 #:file-port file-port
1097 #:symlink-target symlink-target
1098 #:directory-entries directory-entries)
000bbe02 1099 (write-buffered-output server)
7f11efba
LC
1100 (let loop ((done? (process-stderr server)))
1101 (or done? (loop (process-stderr server))))
1102 (let ((result (read-store-path port)))
1103 (hash-set! cache tree result)
1104 result)))))
1105
07e70f48
LC
1106(define build-things
1107 (let ((build (operation (build-things (string-list things)
1108 (integer mode))
1109 "Do it!"
2734cbb8
LC
1110 boolean))
1111 (build/old (operation (build-things (string-list things))
1112 "Do it!"
1113 boolean)))
07e70f48
LC
1114 (lambda* (store things #:optional (mode (build-mode normal)))
1115 "Build THINGS, a list of store items which may be either '.drv' files or
abac874b
LC
1116outputs, and return when the worker is done building them. Elements of THINGS
1117that are not derivations can only be substituted and not built locally.
dcee50c1 1118Return #t on success."
dc0f74e5
LC
1119 (parameterize ((current-store-protocol-version
1120 (nix-server-version store)))
1121 (if (>= (nix-server-minor-version store) 15)
1122 (build store things mode)
1123 (if (= mode (build-mode normal))
1124 (build/old store things)
1125 (raise (condition (&nix-protocol-error
1126 (message "unsupported build mode")
1127 (status 1))))))))))
26bbbb95 1128
d3648e01
LC
1129(define-operation (add-temp-root (store-path path))
1130 "Make PATH a temporary root for the duration of the current session.
1131Return #t."
1132 boolean)
1133
34811f02 1134(define-operation (add-indirect-root (string file-name))
a9d2a105
LC
1135 "Make the symlink FILE-NAME an indirect root for the garbage collector:
1136whatever store item FILE-NAME points to will not be collected. Return #t on
1137success.
1138
1139FILE-NAME can be anywhere on the file system, but it must be an absolute file
1140name--it is the caller's responsibility to ensure that it is an absolute file
1141name."
34811f02
LC
1142 boolean)
1143
a9d2a105
LC
1144(define %gc-roots-directory
1145 ;; The place where garbage collector roots (symlinks) are kept.
1146 (string-append %state-directory "/gcroots"))
1147
1148(define (add-permanent-root target)
1149 "Add a garbage collector root pointing to TARGET, an element of the store,
1150preventing TARGET from even being collected. This can also be used if TARGET
1151does not exist yet.
1152
1153Raise an error if the caller does not have write access to the GC root
1154directory."
1155 (let* ((root (string-append %gc-roots-directory "/" (basename target))))
1156 (catch 'system-error
1157 (lambda ()
1158 (symlink target root))
1159 (lambda args
1160 ;; If ROOT already exists, this is fine; otherwise, re-throw.
1161 (unless (= EEXIST (system-error-errno args))
1162 (apply throw args))))))
1163
1164(define (remove-permanent-root target)
1165 "Remove the permanent garbage collector root pointing to TARGET. Raise an
1166error if there is no such root."
1167 (delete-file (string-append %gc-roots-directory "/" (basename target))))
1168
fae31edc
LC
1169(define references
1170 (operation (query-references (store-path path))
1171 "Return the list of references of PATH."
1172 store-path-list))
1173
f09aea1b
LC
1174(define %reference-cache
1175 ;; Brute-force cache mapping store items to their list of references.
1176 ;; Caching matters because when building a profile in the presence of
1177 ;; grafts, we keep calling 'graft-derivation', which in turn calls
1178 ;; 'references/substitutes' many times with the same arguments. Ideally we
1179 ;; would use a cache associated with the daemon connection instead (XXX).
1180 (make-hash-table 100))
1181
6581ec9a
LC
1182(define (references/substitutes store items)
1183 "Return the list of list of references of ITEMS; the result has the same
1184length as ITEMS. Query substitute information for any item missing from the
1185store at once. Raise a '&nix-protocol-error' exception if reference
1186information for one of ITEMS is missing."
b2fde480
LC
1187 (let* ((requested items)
1188 (local-refs (map (lambda (item)
f09aea1b
LC
1189 (or (hash-ref %reference-cache item)
1190 (guard (c ((nix-protocol-error? c) #f))
1191 (references store item))))
6581ec9a
LC
1192 items))
1193 (missing (fold-right (lambda (item local-ref result)
1194 (if local-ref
1195 result
1196 (cons item result)))
1197 '()
1198 items local-refs))
1199
1200 ;; Query all the substitutes at once to minimize the cost of
1201 ;; launching 'guix substitute' and making HTTP requests.
2633bd32
LC
1202 (substs (if (null? missing)
1203 '()
1204 (substitutable-path-info store missing))))
6581ec9a
LC
1205 (when (< (length substs) (length missing))
1206 (raise (condition (&nix-protocol-error
1207 (message "cannot determine \
1208the list of references")
1209 (status 1)))))
1210
1211 ;; Intersperse SUBSTS and LOCAL-REFS.
dd78e90a
LC
1212 (let loop ((items items)
1213 (local-refs local-refs)
6581ec9a 1214 (result '()))
dd78e90a 1215 (match items
6581ec9a 1216 (()
f09aea1b
LC
1217 (let ((result (reverse result)))
1218 (for-each (cut hash-set! %reference-cache <> <>)
b2fde480 1219 requested result)
f09aea1b 1220 result))
dd78e90a
LC
1221 ((item items ...)
1222 (match local-refs
1223 ((#f tail ...)
1224 (loop items tail
1225 (cons (any (lambda (subst)
1226 (and (string=? (substitutable-path subst) item)
1227 (substitutable-references subst)))
1228 substs)
1229 result)))
1230 ((head tail ...)
1231 (loop items tail
1232 (cons head result)))))))))
6581ec9a 1233
f6fee16e 1234(define* (fold-path store proc seed paths
3f1e6939 1235 #:optional (relatives (cut references store <>)))
f6fee16e 1236 "Call PROC for each of the RELATIVES of PATHS, exactly once, and return the
3f1e6939
LC
1237result formed from the successive calls to PROC, the first of which is passed
1238SEED."
f6fee16e 1239 (let loop ((paths paths)
3f1e6939
LC
1240 (result seed)
1241 (seen vlist-null))
1242 (match paths
1243 ((path rest ...)
1244 (if (vhash-assoc path seen)
1245 (loop rest result seen)
1246 (let ((seen (vhash-cons path #t seen))
1247 (rest (append rest (relatives path)))
1248 (result (proc path result)))
1249 (loop rest result seen))))
1250 (()
1251 result))))
1252
f6fee16e
LC
1253(define (requisites store paths)
1254 "Return the requisites of PATHS, including PATHS---i.e., their closures (all
1255its references, recursively)."
1256 (fold-path store cons '() paths))
3f1e6939 1257
50add477
LC
1258(define (topologically-sorted store paths)
1259 "Return a list containing PATHS and all their references sorted in
1260topological order."
1261 (define (traverse)
1262 ;; Do a simple depth-first traversal of all of PATHS.
1263 (let loop ((paths paths)
1264 (visited vlist-null)
1265 (result '()))
1266 (define (visit n)
1267 (vhash-cons n #t visited))
1268
1269 (define (visited? n)
1270 (vhash-assoc n visited))
1271
1272 (match paths
1273 ((head tail ...)
1274 (if (visited? head)
1275 (loop tail visited result)
1276 (call-with-values
1277 (lambda ()
1278 (loop (references store head)
1279 (visit head)
1280 result))
1281 (lambda (visited result)
1282 (loop tail
1283 visited
1284 (cons head result))))))
1285 (()
1286 (values visited result)))))
1287
1288 (call-with-values traverse
1289 (lambda (_ result)
1290 (reverse result))))
1291
fae31edc
LC
1292(define referrers
1293 (operation (query-referrers (store-path path))
1294 "Return the list of path that refer to PATH."
1295 store-path-list))
1296
1297(define valid-derivers
1298 (operation (query-valid-derivers (store-path path))
1299 "Return the list of valid \"derivers\" of PATH---i.e., all the
1300.drv present in the store that have PATH among their outputs."
1301 store-path-list))
1302
1303(define query-derivation-outputs ; avoid name clash with `derivation-outputs'
1304 (operation (query-derivation-outputs (store-path path))
1305 "Return the list of outputs of PATH, a .drv file."
1306 store-path-list))
1307
0f3d2504
LC
1308(define-operation (has-substitutes? (store-path path))
1309 "Return #t if binary substitutes are available for PATH, and #f otherwise."
1310 boolean)
1311
1312(define substitutable-paths
1313 (operation (query-substitutable-paths (store-path-list paths))
1314 "Return the subset of PATHS that is substitutable."
1315 store-path-list))
1316
1317(define substitutable-path-info
f65cf81a 1318 (operation (query-substitutable-path-infos (store-path-list paths))
0f3d2504
LC
1319 "Return information about the subset of PATHS that is
1320substitutable. For each substitutable path, a `substitutable?' object is
dd78e90a
LC
1321returned; thus, the resulting list can be shorter than PATHS. Furthermore,
1322that there is no guarantee that the order of the resulting list matches the
1323order of PATHS."
0f3d2504
LC
1324 substitutable-path-list))
1325
f9aefa2d
LC
1326(define built-in-builders
1327 (let ((builders (operation (built-in-builders)
1328 "Return the built-in builders."
1329 string-list)))
1330 (lambda (store)
1331 "Return the names of the supported built-in derivation builders
1332supported by STORE."
1333 ;; Check whether STORE's version supports this RPC and built-in
1334 ;; derivation builders in general, which appeared in Guix > 0.11.0.
1335 ;; Return the empty list if it doesn't. Note that this RPC does not
1336 ;; exist in 'nix-daemon'.
1337 (if (or (> (nix-server-major-version store) #x100)
1338 (and (= (nix-server-major-version store) #x100)
1339 (>= (nix-server-minor-version store) #x60)))
1340 (builders store)
1341 '()))))
1342
e3fd0ce6
LC
1343(define-operation (optimize-store)
1344 "Optimize the store by hard-linking identical files (\"deduplication\".)
1345Return #t on success."
1346 ;; Note: the daemon in Guix <= 0.8.2 does not implement this RPC.
1347 boolean)
1348
c63d9403
LC
1349(define verify-store
1350 (let ((verify (operation (verify-store (boolean check-contents?)
1351 (boolean repair?))
1352 "Verify the store."
1353 boolean)))
1354 (lambda* (store #:key check-contents? repair?)
1355 "Verify the integrity of the store and return false if errors remain,
1356and true otherwise. When REPAIR? is true, repair any missing or altered store
1357items by substituting them (this typically requires root privileges because it
1358is not an atomic operation.) When CHECK-CONTENTS? is true, check the contents
1359of store items; this can take a lot of time."
1360 (not (verify store check-contents? repair?)))))
1361
3259877d
LC
1362(define (run-gc server action to-delete min-freed)
1363 "Perform the garbage-collector operation ACTION, one of the
1364`gc-action' values. When ACTION is `delete-specific', the TO-DELETE is
1365the list of store paths to delete. IGNORE-LIVENESS? should always be
1366#f. MIN-FREED is the minimum amount of disk space to be freed, in
1367bytes, before the GC can stop. Return the list of store paths delete,
1368and the number of bytes freed."
1369 (let ((s (nix-server-socket server)))
1370 (write-int (operation-id collect-garbage) s)
1371 (write-int action s)
1372 (write-store-path-list to-delete s)
1373 (write-arg boolean #f s) ; ignore-liveness?
1374 (write-long-long min-freed s)
1375 (write-int 0 s) ; obsolete
1376 (when (>= (nix-server-minor-version server) 5)
1377 ;; Obsolete `use-atime' and `max-atime' parameters.
1378 (write-int 0 s)
1379 (write-int 0 s))
1380
1381 ;; Loop until the server is done sending error output.
1382 (let loop ((done? (process-stderr server)))
1383 (or done? (loop (process-stderr server))))
1384
1385 (let ((paths (read-store-path-list s))
1386 (freed (read-long-long s))
1387 (obsolete (read-long-long s)))
000c59b6
LC
1388 (unless (null? paths)
1389 ;; To be on the safe side, completely invalidate both caches.
1390 ;; Otherwise we could end up returning store paths that are no longer
1391 ;; valid.
1392 (hash-clear! (nix-server-add-to-store-cache server))
1393 (hash-clear! (nix-server-add-text-to-store-cache server)))
1394
3259877d
LC
1395 (values paths freed))))
1396
1397(define-syntax-rule (%long-long-max)
1398 ;; Maximum unsigned 64-bit integer.
1399 (- (expt 2 64) 1))
1400
1401(define (live-paths server)
1402 "Return the list of live store paths---i.e., store paths still
1403referenced, and thus not subject to being garbage-collected."
1404 (run-gc server (gc-action return-live) '() (%long-long-max)))
1405
1406(define (dead-paths server)
1407 "Return the list of dead store paths---i.e., store paths no longer
1408referenced, and thus subject to being garbage-collected."
1409 (run-gc server (gc-action return-dead) '() (%long-long-max)))
1410
1411(define* (collect-garbage server #:optional (min-freed (%long-long-max)))
1412 "Collect garbage from the store at SERVER. If MIN-FREED is non-zero,
1413then collect at least MIN-FREED bytes. Return the paths that were
1414collected, and the number of bytes freed."
1415 (run-gc server (gc-action delete-dead) '() min-freed))
1416
1417(define* (delete-paths server paths #:optional (min-freed (%long-long-max)))
1418 "Delete PATHS from the store at SERVER, if they are no longer
1419referenced. If MIN-FREED is non-zero, then stop after at least
1420MIN-FREED bytes have been collected. Return the paths that were
1421collected, and the number of bytes freed."
1422 (run-gc server (gc-action delete-specific) paths min-freed))
1423
526382ff
LC
1424(define (import-paths server port)
1425 "Import the set of store paths read from PORT into SERVER's store. An error
1426is raised if the set of paths read from PORT is not signed (as per
1427'export-path #:sign? #t'.) Return the list of store paths imported."
1428 (let ((s (nix-server-socket server)))
1429 (write-int (operation-id import-paths) s)
1430 (let loop ((done? (process-stderr server port)))
1431 (or done? (loop (process-stderr server port))))
1432 (read-store-path-list s)))
1433
1434(define* (export-path server path port #:key (sign? #t))
1435 "Export PATH to PORT. When SIGN? is true, sign it."
1436 (let ((s (nix-server-socket server)))
1437 (write-int (operation-id export-path) s)
1438 (write-store-path path s)
1439 (write-arg boolean sign? s)
1440 (let loop ((done? (process-stderr server port)))
1441 (or done? (loop (process-stderr server port))))
1442 (= 1 (read-int s))))
1443
5b3d863f 1444(define* (export-paths server paths port #:key (sign? #t) recursive?)
99fbddf9 1445 "Export the store paths listed in PATHS to PORT, in topological order,
5b3d863f
LC
1446signing them if SIGN? is true. When RECURSIVE? is true, export the closure of
1447PATHS---i.e., PATHS and all their dependencies."
cafb92d8 1448 (define ordered
5b3d863f
LC
1449 (let ((sorted (topologically-sorted server paths)))
1450 ;; When RECURSIVE? is #f, filter out the references of PATHS.
1451 (if recursive?
1452 sorted
1453 (filter (cut member <> paths) sorted))))
cafb92d8 1454
1d506993
LC
1455 (let loop ((paths ordered))
1456 (match paths
1457 (()
1458 (write-int 0 port))
1459 ((head tail ...)
1460 (write-int 1 port)
1461 (and (export-path server head port #:sign? sign?)
1462 (loop tail))))))
526382ff 1463
16748d80
LC
1464(define-operation (query-failed-paths)
1465 "Return the list of store items for which a build failure is cached.
1466
1467The result is always the empty list unless the daemon was started with
1468'--cache-failures'."
1469 store-path-list)
1470
1471(define-operation (clear-failed-paths (store-path-list items))
1472 "Remove ITEMS from the list of cached build failures.
1473
1474This makes sense only when the daemon was started with '--cache-failures'."
1475 boolean)
1476
26bbbb95 1477\f
e87f0591
LC
1478;;;
1479;;; Store monad.
1480;;;
1481
4e190c28
LC
1482(define-syntax-rule (define-alias new old)
1483 (define-syntax new (identifier-syntax old)))
e87f0591 1484
4e190c28
LC
1485;; The store monad allows us to (1) build sequences of operations in the
1486;; store, and (2) make the store an implicit part of the execution context,
1487;; rather than a parameter of every single function.
1488(define-alias %store-monad %state-monad)
1489(define-alias store-return state-return)
1490(define-alias store-bind state-bind)
e87f0591 1491
dcb95c1f
LC
1492;; Instantiate templates for %STORE-MONAD since it's syntactically different
1493;; from %STATE-MONAD.
1494(template-directory instantiations %store-monad)
1495
c6080c32
LC
1496(define* (cache-object-mapping object keys result)
1497 "Augment the store's object cache with a mapping from OBJECT/KEYS to RESULT.
1498KEYS is a list of additional keys to match against, for instance a (SYSTEM
1499TARGET) tuple.
1500
1501OBJECT is typically a high-level object such as a <package> or an <origin>,
1502and RESULT is typically its derivation."
1503 (lambda (store)
1504 (values result
1505 (nix-server
1506 (inherit store)
1507 (object-cache (vhash-consq object (cons result keys)
1508 (nix-server-object-cache store)))))))
1509
73b0ebdd
LC
1510(define record-cache-lookup!
1511 (if (profiled? "object-cache")
1512 (let ((fresh 0)
1513 (lookups 0)
1514 (hits 0))
1515 (register-profiling-hook!
1516 "object-cache"
1517 (lambda ()
1518 (format (current-error-port) "Store object cache:
1519 fresh caches: ~5@a
1520 lookups: ~5@a
1521 hits: ~5@a (~,1f%)~%"
1522 fresh lookups hits
1523 (if (zero? lookups)
1524 100.
1525 (* 100. (/ hits lookups))))))
1526
1527 (lambda (hit? cache)
1528 (set! fresh
1529 (if (eq? cache vlist-null)
1530 (+ 1 fresh)
1531 fresh))
1532 (set! lookups (+ 1 lookups))
1533 (set! hits (if hit? (+ hits 1) hits))))
1534 (lambda (x y)
1535 #t)))
1536
c6080c32
LC
1537(define* (lookup-cached-object object #:optional (keys '()))
1538 "Return the cached object in the store connection corresponding to OBJECT
1539and KEYS. KEYS is a list of additional keys to match against, and which are
1540compared with 'equal?'. Return #f on failure and the cached result
1541otherwise."
1542 (lambda (store)
73b0ebdd
LC
1543 (let* ((cache (nix-server-object-cache store))
1544
1545 ;; Escape as soon as we find the result. This avoids traversing
1546 ;; the whole vlist chain and significantly reduces the number of
1547 ;; 'hashq' calls.
1548 (value (let/ec return
1549 (vhash-foldq* (lambda (item result)
1550 (match item
1551 ((value . keys*)
1552 (if (equal? keys keys*)
1553 (return value)
1554 result))))
1555 #f object
1556 cache))))
1557 (record-cache-lookup! value cache)
1558 (values value store))))
c6080c32
LC
1559
1560(define* (%mcached mthunk object #:optional (keys '()))
1561 "Bind the monadic value returned by MTHUNK, which supposedly corresponds to
1562OBJECT/KEYS, or return its cached value."
1563 (mlet %store-monad ((cached (lookup-cached-object object keys)))
1564 (if cached
1565 (return cached)
1566 (>>= (mthunk)
1567 (lambda (result)
1568 (cache-object-mapping object keys result))))))
1569
1570(define-syntax-rule (mcached mvalue object keys ...)
1571 "Run MVALUE, which corresponds to OBJECT/KEYS, and cache it; or return the
1572value associated with OBJECT/KEYS in the store's object cache if there is
1573one."
1574 (%mcached (lambda () mvalue)
1575 object (list keys ...)))
1576
5808dcc2
LC
1577(define (preserve-documentation original proc)
1578 "Return PROC with documentation taken from ORIGINAL."
1579 (set-object-property! proc 'documentation
1580 (procedure-property original 'documentation))
1581 proc)
1582
e87f0591
LC
1583(define (store-lift proc)
1584 "Lift PROC, a procedure whose first argument is a connection to the store,
1585in the store monad."
5808dcc2
LC
1586 (preserve-documentation proc
1587 (lambda args
1588 (lambda (store)
1589 (values (apply proc store args) store)))))
e87f0591 1590
023d9892
LC
1591(define (store-lower proc)
1592 "Lower PROC, a monadic procedure in %STORE-MONAD, to a \"normal\" procedure
1593taking the store as its first argument."
5808dcc2
LC
1594 (preserve-documentation proc
1595 (lambda (store . args)
1596 (run-with-store store (apply proc args)))))
023d9892 1597
e87f0591
LC
1598;;
1599;; Store monad operators.
1600;;
1601
f3a42251
JN
1602(define* (binary-file name
1603 data ;bytevector
1604 #:optional (references '()))
1605 "Return as a monadic value the absolute file name in the store of the file
1606containing DATA, a bytevector. REFERENCES is a list of store items that the
1607resulting text file refers to; it defaults to the empty list."
1608 (lambda (store)
1609 (values (add-data-to-store store name data references)
1610 store)))
1611
1612(define* (text-file name
1613 text ;string
ad372953 1614 #:optional (references '()))
e87f0591 1615 "Return as a monadic value the absolute file name in the store of the file
ad372953
LC
1616containing TEXT, a string. REFERENCES is a list of store items that the
1617resulting text file refers to; it defaults to the empty list."
e87f0591 1618 (lambda (store)
ad372953 1619 (values (add-text-to-store store name text references)
4e190c28 1620 store)))
e87f0591
LC
1621
1622(define* (interned-file file #:optional name
1ec32f4a 1623 #:key (recursive? #t) (select? true))
e87f0591
LC
1624 "Return the name of FILE once interned in the store. Use NAME as its store
1625name, or the basename of FILE if NAME is omitted.
1626
1627When RECURSIVE? is true, the contents of FILE are added recursively; if FILE
1628designates a flat file and RECURSIVE? is true, its contents are added, and its
1ec32f4a
LC
1629permission bits are kept.
1630
1631When RECURSIVE? is true, call (SELECT? FILE STAT) for each directory entry,
1632where FILE is the entry's absolute file name and STAT is the result of
1633'lstat'; exclude entries for which SELECT? does not return true."
e87f0591 1634 (lambda (store)
4e190c28 1635 (values (add-to-store store (or name (basename file))
1ec32f4a
LC
1636 recursive? "sha256" file
1637 #:select? select?)
4e190c28 1638 store)))
e87f0591 1639
7f11efba
LC
1640(define interned-file-tree
1641 (store-lift add-file-tree-to-store))
1642
abac874b
LC
1643(define build
1644 ;; Monadic variant of 'build-things'.
1645 (store-lift build-things))
1646
4f740b67
AK
1647(define set-build-options*
1648 (store-lift set-build-options))
1649
e74f64b9
LC
1650(define references*
1651 (store-lift references))
1652
0744a9f0
LC
1653(define (query-path-info* item)
1654 "Monadic version of 'query-path-info' that returns #f when ITEM is not in
1655the store."
1656 (lambda (store)
1657 (guard (c ((nix-protocol-error? c)
1658 ;; ITEM is not in the store; return #f.
1659 (values #f store)))
1660 (values (query-path-info store item) store))))
1661
98a7b528
LC
1662(define-inlinable (current-system)
1663 ;; Consult the %CURRENT-SYSTEM fluid at bind time. This is equivalent to
1664 ;; (lift0 %current-system %store-monad), but inlinable, thus avoiding
1665 ;; closure allocation in some cases.
1666 (lambda (state)
1667 (values (%current-system) state)))
1668
1669(define-inlinable (set-current-system system)
1670 ;; Set the %CURRENT-SYSTEM fluid at bind time.
1671 (lambda (state)
1672 (values (%current-system system) state)))
1673
e87f0591
LC
1674(define %guile-for-build
1675 ;; The derivation of the Guile to be used within the build environment,
1676 ;; when using 'gexp->derivation' and co.
1677 (make-parameter #f))
1678
1679(define* (run-with-store store mval
1680 #:key
1681 (guile-for-build (%guile-for-build))
45bba475
LC
1682 (system (%current-system))
1683 (target #f))
e87f0591 1684 "Run MVAL, a monadic value in the store monad, in STORE, an open store
3698f524 1685connection, and return the result."
a8afb9ae
LC
1686 ;; Initialize the dynamic bindings here to avoid bad surprises. The
1687 ;; difficulty lies in the fact that dynamic bindings are resolved at
1688 ;; bind-time and not at call time, which can be disconcerting.
e87f0591 1689 (parameterize ((%guile-for-build guile-for-build)
a8afb9ae 1690 (%current-system system)
45bba475 1691 (%current-target-system target))
3698f524
LC
1692 (call-with-values (lambda ()
1693 (run-with-state mval store))
1694 (lambda (result store)
1695 ;; Discard the state.
1696 result))))
e87f0591
LC
1697
1698\f
26bbbb95
LC
1699;;;
1700;;; Store paths.
1701;;;
1702
1703(define %store-prefix
1704 ;; Absolute path to the Nix store.
1d6816f9 1705 (make-parameter %store-directory))
26bbbb95 1706
cd041b26
LC
1707(define (compressed-hash bv size) ; `compressHash'
1708 "Given the hash stored in BV, return a compressed version thereof that fits
1709in SIZE bytes."
1710 (define new (make-bytevector size 0))
1711 (define old-size (bytevector-length bv))
1712 (let loop ((i 0))
1713 (if (= i old-size)
1714 new
1715 (let* ((j (modulo i size))
1716 (o (bytevector-u8-ref new j)))
1717 (bytevector-u8-set! new j
1718 (logxor o (bytevector-u8-ref bv i)))
1719 (loop (+ 1 i))))))
1720
1721(define (store-path type hash name) ; makeStorePath
1722 "Return the store path for NAME/HASH/TYPE."
1723 (let* ((s (string-append type ":sha256:"
1724 (bytevector->base16-string hash) ":"
1725 (%store-prefix) ":" name))
1726 (h (sha256 (string->utf8 s)))
1727 (c (compressed-hash h 20)))
1728 (string-append (%store-prefix) "/"
1729 (bytevector->nix-base32-string c) "-"
1730 name)))
1731
1732(define (output-path output hash name) ; makeOutputPath
1733 "Return an output path for OUTPUT (the name of the output as a string) of
1734the derivation called NAME with hash HASH."
1735 (store-path (string-append "output:" output) hash
1736 (if (string=? output "out")
1737 name
1738 (string-append name "-" output))))
1739
1740(define* (fixed-output-path name hash
1741 #:key
1742 (output "out")
1743 (hash-algo 'sha256)
1744 (recursive? #t))
1745 "Return an output path for the fixed output OUTPUT defined by HASH of type
1746HASH-ALGO, of the derivation NAME. RECURSIVE? has the same meaning as for
1747'add-to-store'."
1748 (if (and recursive? (eq? hash-algo 'sha256))
1749 (store-path "source" hash name)
1750 (let ((tag (string-append "fixed:" output ":"
1751 (if recursive? "r:" "")
1752 (symbol->string hash-algo) ":"
1753 (bytevector->base16-string hash) ":")))
1754 (store-path (string-append "output:" output)
1755 (sha256 (string->utf8 tag))
1756 name))))
1757
f39bd08a
LC
1758(define (store-path? path)
1759 "Return #t if PATH is a store path."
1760 ;; This is a lightweight check, compared to using a regexp, but this has to
1761 ;; be fast as it's called often in `derivation', for instance.
1762 ;; `isStorePath' in Nix does something similar.
1763 (string-prefix? (%store-prefix) path))
26bbbb95 1764
9336e5b5
LC
1765(define (direct-store-path? path)
1766 "Return #t if PATH is a store path, and not a sub-directory of a store path.
1767This predicate is sometimes needed because files *under* a store path are not
1768valid inputs."
1769 (and (store-path? path)
eee21271 1770 (not (string=? path (%store-prefix)))
9336e5b5
LC
1771 (let ((len (+ 1 (string-length (%store-prefix)))))
1772 (not (string-index (substring path len) #\/)))))
1773
cdb5b075
CS
1774(define (direct-store-path path)
1775 "Return the direct store path part of PATH, stripping components after
1776'/gnu/store/xxxx-foo'."
1777 (let ((prefix-length (+ (string-length (%store-prefix)) 35)))
1778 (if (> (string-length path) prefix-length)
1779 (let ((slash (string-index path #\/ prefix-length)))
1780 (if slash (string-take path slash) path))
1781 path)))
1782
26bbbb95
LC
1783(define (derivation-path? path)
1784 "Return #t if PATH is a derivation path."
1785 (and (store-path? path) (string-suffix? ".drv" path)))
e3d74106 1786
5c0f1845
LC
1787(define store-regexp*
1788 ;; The substituter makes repeated calls to 'store-path-hash-part', hence
1789 ;; this optimization.
55b2d921
LC
1790 (mlambda (store)
1791 "Return a regexp matching a file in STORE."
1792 (make-regexp (string-append "^" (regexp-quote store)
1793 "/([0-9a-df-np-sv-z]{32})-([^/]+)$"))))
5c0f1845 1794
e3d74106
LC
1795(define (store-path-package-name path)
1796 "Return the package name part of PATH, a file name in the store."
5c0f1845
LC
1797 (let ((path-rx (store-regexp* (%store-prefix))))
1798 (and=> (regexp-exec path-rx path)
1799 (cut match:substring <> 2))))
2c6ab6cc
LC
1800
1801(define (store-path-hash-part path)
1802 "Return the hash part of PATH as a base32 string, or #f if PATH is not a
1803syntactically valid store path."
35eb77b0
LC
1804 (and (string-prefix? (%store-prefix) path)
1805 (let ((base (string-drop path (+ 1 (string-length (%store-prefix))))))
1806 (and (> (string-length base) 33)
1807 (let ((hash (string-take base 32)))
1808 (and (string-every %nix-base32-charset hash)
1809 hash))))))
eddd4077 1810
fb94d82b
LC
1811(define (derivation-log-file drv)
1812 "Return the build log file for DRV, a derivation file name, or #f if it
1813could not be found."
1814 (let* ((base (basename drv))
1815 (log (string-append (dirname %state-directory) ; XXX
1816 "/log/guix/drvs/"
1817 (string-take base 2) "/"
1818 (string-drop base 2)))
1819 (log.gz (string-append log ".gz"))
1820 (log.bz2 (string-append log ".bz2")))
1821 (cond ((file-exists? log.gz) log.gz)
1822 ((file-exists? log.bz2) log.bz2)
1823 ((file-exists? log) log)
1824 (else #f))))
1825
eddd4077
LC
1826(define (log-file store file)
1827 "Return the build log file for FILE, or #f if none could be found. FILE
1828must be an absolute store file name, or a derivation file name."
eddd4077 1829 (cond ((derivation-path? file)
fb94d82b 1830 (derivation-log-file file))
eddd4077
LC
1831 (else
1832 (match (valid-derivers store file)
1833 ((derivers ...)
1834 ;; Return the first that works.
1835 (any (cut log-file store <>) derivers))
1836 (_ #f)))))
3b5cd17a
LC
1837
1838;;; Local Variables:
1839;;; eval: (put 'system-error-to-connection-error 'scheme-indent-function 1)
1840;;; End: