aboutsummaryrefslogtreecommitdiff
path: root/guix-data-service/model/nar.scm
blob: 0898ae4d2c769f091825bb2d8f4bdc887e4a4d46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
1(define-module (guix-data-service model nar)
  #:use-module (srfi srfi-1)
  #:use-module (ice-9 match)
  #:use-module (web uri)
  #:use-module (squee)
  #:use-module (json)
  #:use-module (rnrs bytevectors)
  #:use-module (gcrypt pk-crypto)
  #:use-module (gcrypt base16)
  #:use-module (guix scripts substitute)
  #:use-module (guix-data-service model utils)
  #:export (select-outputs-for-successful-builds-without-known-nar-entries

            record-narinfo-details-and-return-ids))

(define narinfo-contents
  (@@ (guix scripts substitute) narinfo-contents))

(define (record-narinfo-details-and-return-ids conn narinfos)
  (define data
    (map (lambda (narinfo)
           (match (string-split
                   (narinfo-hash narinfo)
                   #\:)
             ((hash-algorithm hash)
              (list
               (narinfo-path narinfo)
               hash-algorithm
               hash
               (narinfo-size narinfo)
               (or (narinfo-system narinfo) NULL)
               (or (narinfo-deriver narinfo) NULL)))))
         narinfos))

  (let ((nar-ids
         (insert-missing-data-and-return-all-ids
          conn
          "nars"
          '(store_path hash_algorithm hash size system deriver)
          data)))

    (exec-query
     conn
     (string-append
      "
INSERT INTO nar_references (nar_id, reference)
VALUES "
      (string-join
       (concatenate
        (map (lambda (nar-id narinfo)
               (map (lambda (reference)
                      (simple-format
                       #f
                       "(~A, ~A)"
                       nar-id
                       (quote-string reference)))
                    (narinfo-references narinfo)))
             nar-ids
             narinfos))
       ", ")
      "
ON CONFLICT DO NOTHING"))

    (exec-query
     conn
     (string-append
      "
INSERT INTO nar_urls (nar_id, url, compression, file_size)
VALUES "
      (string-join
       (concatenate
        (map (lambda (nar-id narinfo)
               (map (lambda (uri compression file-size)
                      (simple-format
                       #f
                       "(~A, ~A, ~A, ~A)"
                       nar-id
                       (quote-string
                        (uri->string uri))
                       (quote-string compression)
                       file-size))
                    (narinfo-uris narinfo)
                    (narinfo-compressions narinfo)
                    (narinfo-file-sizes narinfo)))
             nar-ids
             narinfos))
       ", ")
      "
ON CONFLICT DO NOTHING"))

    (for-each (lambda (nar-id narinfo)
                (let ((narinfo-signature-data-id
                       (narinfo-signature->data-id conn narinfo)))

                  (exec-query
                   conn
                   (string-append
                    "
INSERT INTO narinfo_signatures (nar_id, narinfo_signature_data_id)
VALUES "
                    (simple-format
                     #f
                     "(~A,~A)"
                     nar-id
                     narinfo-signature-data-id)
                    "
ON CONFLICT DO NOTHING"))))
              nar-ids
              narinfos)

    nar-ids))

(define (sexp->json-string sexp)
  (define (transform x)
    (if (list? x)
        (list->vector (map transform x))
        (if (bytevector? x)
            `((base16 . ,(bytevector->base16-string x)))
            x)))

  (scm->json-string (transform sexp)))

(define (narinfo-signature->data-id conn narinfo)
  (let ((public-key-id
         (narinfo-signature->public-key-id
          conn
          (narinfo-signature narinfo)))
        (contents
         (narinfo-contents narinfo)))

    (match (string-contains contents "Signature:")
      (#f #f)
      (index
       (let* ((body (string-take contents index))
              (signature-line (string-drop contents index))
              (signature-sexp
               (canonical-sexp->sexp
                (narinfo-signature narinfo))))

         (match (string-split (second (string-split signature-line
                                                    #\space))
                              #\;)
           ((version host-name signature-data)

            (first
             (insert-missing-data-and-return-all-ids
              conn
              "narinfo_signature_data"
              '(version host_name data_hash data_hash_algorithm
                        data_json sig_val_json narinfo_signature_public_key_id
                        narinfo_body narinfo_signature_line)
              (list
               (append (list (string->number version)
                             host-name)
                       (let* ((data-sexp
                               (find (match-lambda
                                       ((component data ...)
                                        (if (eq? component 'data)
                                            data
                                            #f))
                                       (_ #f))
                                     signature-sexp))
                              (hash-sexp
                               (third data-sexp))
                              (hash-algorithm
                               (second hash-sexp))
                              (hash
                               (third hash-sexp)))
                         (list
                          (bytevector->base16-string hash)
                          hash-algorithm
                          (cons "jsonb"
                                (sexp->json-string data-sexp))))
                       (let ((sig-val-sexp
                              (find (match-lambda
                                      ((component data ...)
                                       (if (eq? component 'sig-val)
                                           data
                                           #f))
                                      (_ #f))
                                    signature-sexp)))
                         (list
                          (cons "jsonb"
                                (sexp->json-string sig-val-sexp))))
                       (list public-key-id
                             body
                             signature-line))))))))))))

(define (narinfo-signature->public-key-id conn signature)
  (let* ((public-key-sexp
          (find (match-lambda
                  ((component data ...)
                   (if (eq? component 'public-key)
                       data
                       #f))
                  (_ #f))
                (canonical-sexp->sexp signature)))
         (public-key-json-string
          (sexp->json-string public-key-sexp)))

    (first
     (insert-missing-data-and-return-all-ids
      conn
      "narinfo_signature_public_keys"
      '(sexp_json)
      (list (list (cons "jsonb"
                        public-key-json-string)))))))

(define (select-outputs-for-successful-builds-without-known-nar-entries
         conn
         build-server-id
         guix-revision-commits)
  (define query
    (string-append "
SELECT DISTINCT derivation_output_details.path
FROM derivations
INNER JOIN derivation_outputs
  ON derivations.id = derivation_outputs.id
INNER JOIN derivation_output_details
  ON derivation_outputs.derivation_output_details_id = derivation_output_details.id
WHERE file_name IN (
  SELECT derivation_file_name
  FROM builds
  INNER JOIN build_status
    ON builds.id = build_status.build_id
  WHERE
    build_server_id = $1 AND
    build_status.status = 'succeeded'
) AND derivation_output_details.path NOT IN (
  SELECT store_path FROM nars
) AND
  derivations.id IN (
    SELECT derivation_id
    FROM package_derivations
    INNER JOIN guix_revision_package_derivations
      ON guix_revision_package_derivations.package_derivation_id = package_derivations.id
    INNER JOIN guix_revisions
      ON guix_revisions.id = guix_revision_package_derivations.revision_id
    WHERE guix_revisions.commit IN ("
                   (string-join (map quote-string guix-revision-commits)
                                ",")
                   ")
)
LIMIT 1500"))

  (map car (exec-query conn query (list (number->string
                                         build-server-id)))))