guix: store: Register derivation outputs.

* guix/store/database.scm (register-output-sql, derivation-outputs-sql): new
  variables.
  (registered-derivation-outputs): new procedure.
  ((guix store derivations), (guix store files)): used for <derivation> and
  derivation-path?, respectively.
  (register-items): if item is a derivation, also register its outputs.

* tests/store-database.scm (register-path): first register a dummy derivation
  for the test file, and check that its outputs are registered in the
  DerivationOutputs table and are equal to what was specified in the dummy
  derivation.
This commit is contained in:
Caleb Ristvedt 2019-02-13 02:19:42 -06:00
parent bdc366cbdc
commit 14499efc25
No known key found for this signature in database
GPG key ID: C166AA495F7F189C
2 changed files with 70 additions and 1 deletions

View file

@ -21,6 +21,8 @@ (define-module (guix store database)
#:use-module (sqlite3) #:use-module (sqlite3)
#:use-module (guix config) #:use-module (guix config)
#:use-module (guix serialization) #:use-module (guix serialization)
#:use-module (guix store derivations)
#:use-module (guix store files)
#:use-module (guix store deduplication) #:use-module (guix store deduplication)
#:use-module (guix base16) #:use-module (guix base16)
#:use-module (guix progress) #:use-module (guix progress)
@ -42,6 +44,7 @@ (define-module (guix store database)
sqlite-register sqlite-register
register-path register-path
register-items register-items
registered-derivation-outputs
%epoch %epoch
reset-timestamps)) reset-timestamps))
@ -282,6 +285,26 @@ (define %epoch
;; When it all began. ;; When it all began.
(make-time time-utc 0 1)) (make-time time-utc 0 1))
(define derivation-outputs-sql "SELECT id, path FROM DerivationOutputs WHERE
drv in (SELECT id from ValidPaths where path = :drv)")
(define (registered-derivation-outputs db drv)
"Get the list of (id, output-path) pairs registered for DRV."
(let ((stmt (sqlite-prepare db derivation-outputs-sql #:cache? #t)))
(sqlite-bind-arguments stmt #:drv drv)
(let ((result (sqlite-fold (lambda (current prev)
(match current
(#(id path)
(cons (cons id path)
prev))))
'() stmt)))
(sqlite-finalize stmt)
result)))
(define register-output-sql
"INSERT OR REPLACE INTO DerivationOutputs (drv, id, path) SELECT id, :outid,
:outpath FROM ValidPaths WHERE path = :drvpath;")
(define* (register-items items (define* (register-items items
#:key prefix state-directory #:key prefix state-directory
(deduplicate? #t) (deduplicate? #t)
@ -330,6 +353,21 @@ (define to-register
(define real-file-name (define real-file-name
(string-append store-dir "/" (basename (store-info-item item)))) (string-append store-dir "/" (basename (store-info-item item))))
(define (register-derivation-outputs drv)
"Register all output paths of DRV as being produced by it (note that
this doesn't mean 'already produced by it', but rather just 'associated with
it')."
(let ((stmt (sqlite-prepare db register-output-sql #:cache? #t)))
(for-each (match-lambda
((outid . ($ <derivation-output> path))
(sqlite-bind-arguments stmt
#:drvpath (derivation-file-name
drv)
#:outid outid
#:outpath path)
(sqlite-fold noop #f stmt)))
(derivation-outputs drv))
(sqlite-finalize stmt)))
;; When TO-REGISTER is already registered, skip it. This makes a ;; When TO-REGISTER is already registered, skip it. This makes a
;; significant differences when 'register-closures' is called ;; significant differences when 'register-closures' is called
@ -345,6 +383,9 @@ (define real-file-name
(bytevector->base16-string hash)) (bytevector->base16-string hash))
#:nar-size nar-size #:nar-size nar-size
#:time registration-time) #:time registration-time)
(when (derivation-path? real-file-name)
(register-derivation-outputs (read-derivation-from-file
real-file-name)))
(when deduplicate? (when deduplicate?
(deduplicate real-file-name hash #:store store-dir))))) (deduplicate real-file-name hash #:store store-dir)))))

View file

@ -20,6 +20,7 @@ (define-module (test-store-database)
#:use-module (guix tests) #:use-module (guix tests)
#:use-module (guix store) #:use-module (guix store)
#:use-module (guix store database) #:use-module (guix store database)
#:use-module (guix derivations)
#:use-module ((guix utils) #:select (call-with-temporary-output-file)) #:use-module ((guix utils) #:select (call-with-temporary-output-file))
#:use-module (srfi srfi-26) #:use-module (srfi srfi-26)
#:use-module (srfi srfi-64)) #:use-module (srfi srfi-64))
@ -44,14 +45,41 @@ (define %store
(drv (string-append file ".drv"))) (drv (string-append file ".drv")))
(call-with-output-file file (call-with-output-file file
(cut display "This is a fake store item.\n" <>)) (cut display "This is a fake store item.\n" <>))
(when (valid-path? %store drv)
(delete-paths %store (list drv)))
(call-with-output-file drv
(lambda (port)
;; XXX: we should really go from derivation to output path as is
;; usual, currently any verification done on this derivation will
;; cause an error.
(write-derivation ((@@ (guix derivations) make-derivation)
;; outputs
(list (cons "out"
((@@ (guix derivations)
make-derivation-output)
file
#f
#f
#f)))
;; inputs sources system builder args
'() '() "" "" '()
;; env-vars filename
'() drv)
port)))
(register-path drv)
(register-path file (register-path file
#:references (list ref) #:references (list ref)
#:deriver drv) #:deriver drv)
(and (valid-path? %store file) (and (valid-path? %store file)
(equal? (references %store file) (list ref)) (equal? (references %store file) (list ref))
(null? (valid-derivers %store file)) ;; We expect the derivation outputs to be automatically
;; registered.
(not (null? (valid-derivers %store file)))
(null? (referrers %store file)) (null? (referrers %store file))
(equal? (with-database %default-database-file db
(registered-derivation-outputs db drv))
`(("out" . ,file)))
(list (stat:mtime (lstat file)) (list (stat:mtime (lstat file))
(stat:mtime (lstat ref))))))) (stat:mtime (lstat ref)))))))