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