1120 lines
51 KiB
Scheme
1120 lines
51 KiB
Scheme
;;; Guix Data Service -- Information about Guix over time
|
|
;;; Copyright © 2019 Christopher Baines <mail@cbaines.net>
|
|
;;;
|
|
;;; This program is free software: you can redistribute it and/or
|
|
;;; modify it under the terms of the GNU Affero General Public License
|
|
;;; as published by the Free Software Foundation, either version 3 of
|
|
;;; the License, or (at your option) any later version.
|
|
;;;
|
|
;;; This program is distributed in the hope that it will be useful,
|
|
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
;;; Affero General Public License for more details.
|
|
;;;
|
|
;;; You should have received a copy of the GNU Affero General Public
|
|
;;; License along with this program. If not, see
|
|
;;; <http://www.gnu.org/licenses/>.
|
|
|
|
(define-module (guix-data-service web compare controller)
|
|
#:use-module (srfi srfi-1)
|
|
#:use-module (srfi srfi-11)
|
|
#:use-module (srfi srfi-19)
|
|
#:use-module (ice-9 match)
|
|
#:use-module (ice-9 vlist)
|
|
#:use-module (texinfo)
|
|
#:use-module (texinfo html)
|
|
#:use-module (texinfo plain-text)
|
|
#:use-module (guix-data-service utils)
|
|
#:use-module (guix-data-service database)
|
|
#:use-module (guix-data-service web sxml)
|
|
#:use-module (guix-data-service web util)
|
|
#:use-module (guix-data-service web render)
|
|
#:use-module (guix-data-service web query-parameters)
|
|
#:use-module (guix-data-service model utils)
|
|
#:use-module (guix-data-service comparison)
|
|
#:use-module (guix-data-service jobs load-new-guix-revision)
|
|
#:use-module (guix-data-service model guix-revision)
|
|
#:use-module (guix-data-service model system)
|
|
#:use-module (guix-data-service model git-repository)
|
|
#:use-module (guix-data-service model derivation)
|
|
#:use-module (guix-data-service model build-server)
|
|
#:use-module (guix-data-service model build-status)
|
|
#:use-module (guix-data-service model lint-warning-message)
|
|
#:use-module (guix-data-service web compare html)
|
|
#:export (compare-controller))
|
|
|
|
(define cache-control-default-max-age
|
|
(* 60 60 24)) ; One day
|
|
|
|
(define http-headers-for-unchanging-content
|
|
`((cache-control
|
|
. (public
|
|
(max-age . ,cache-control-default-max-age)))))
|
|
|
|
(define (parse-build-status s)
|
|
s)
|
|
|
|
(define (parse-commit s)
|
|
(parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(let* ((job-details
|
|
(select-job-for-commit conn s))
|
|
(job-state
|
|
(assq-ref job-details 'state)))
|
|
(if job-details
|
|
(cond
|
|
((string=? job-state "succeeded")
|
|
s)
|
|
((string=? job-state "queued")
|
|
(make-invalid-query-parameter
|
|
s
|
|
`("data unavailable, "
|
|
(a (@ (href ,(string-append
|
|
"/revision/" s)))
|
|
"yet to process revision"))))
|
|
((string=? job-state "failed")
|
|
(make-invalid-query-parameter
|
|
s
|
|
`("data unavailable, "
|
|
(a (@ (href ,(string-append
|
|
"/revision/" s)))
|
|
"failed to process revision"))))
|
|
(else
|
|
(make-invalid-query-parameter
|
|
s "unknown job state")))
|
|
(make-invalid-query-parameter
|
|
s "unknown commit")))))))
|
|
|
|
(define (parse-derivation file-name)
|
|
(if (parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(select-derivation-by-file-name conn file-name))))
|
|
file-name
|
|
(make-invalid-query-parameter
|
|
file-name "unknown derivation")))
|
|
|
|
(define (parse-build-change val)
|
|
(or (if (member val '("broken" "fixed"
|
|
"still-working"
|
|
"still-failing"
|
|
"unknown"))
|
|
val
|
|
#f)
|
|
(make-invalid-query-parameter
|
|
val
|
|
"unknown build change value")))
|
|
|
|
(define (compare-controller request
|
|
method-and-path-components
|
|
mime-types
|
|
body)
|
|
(match method-and-path-components
|
|
(('GET "compare")
|
|
(let* ((parsed-query-parameters
|
|
(parse-query-parameters
|
|
request
|
|
`((base_commit ,parse-commit #:required)
|
|
(target_commit ,parse-commit #:required)
|
|
(locale ,identity #:default "en_US.UTF-8")))))
|
|
(render-compare mime-types
|
|
parsed-query-parameters)))
|
|
(('GET "compare-by-datetime")
|
|
(let* ((parsed-query-parameters
|
|
(parse-query-parameters
|
|
request
|
|
`((base_branch ,identity #:required)
|
|
(base_datetime ,parse-datetime
|
|
#:default ,(current-date))
|
|
(target_branch ,identity #:required)
|
|
(target_datetime ,parse-datetime
|
|
#:default ,(current-date))
|
|
(locale ,identity #:default "en_US.UTF-8")))))
|
|
(render-compare-by-datetime mime-types
|
|
parsed-query-parameters)))
|
|
(('GET "compare" "derivation")
|
|
(let* ((parsed-query-parameters
|
|
(parse-query-parameters
|
|
request
|
|
`((base_derivation ,parse-derivation #:required)
|
|
(target_derivation ,parse-derivation #:required)))))
|
|
(render-compare/derivation mime-types
|
|
parsed-query-parameters)))
|
|
(('GET "compare" "package-derivations")
|
|
(let* ((parsed-query-parameters
|
|
(guard-against-mutually-exclusive-query-parameters
|
|
(parse-query-parameters
|
|
request
|
|
`((base_commit ,parse-commit #:required)
|
|
(target_commit ,parse-commit #:required)
|
|
(system ,parse-system #:multi-value)
|
|
(target ,parse-target #:multi-value)
|
|
(build_status ,parse-build-status #:multi-value)
|
|
(build_change ,parse-build-change)
|
|
(after_name ,identity)
|
|
(limit_results ,parse-result-limit
|
|
#:no-default-when (all_results)
|
|
#:default 40)
|
|
(all_results ,parse-checkbox-value)))
|
|
'((limit_results all_results)))))
|
|
|
|
(render-compare/package-derivations mime-types
|
|
parsed-query-parameters)))
|
|
(('GET "compare-by-datetime" "package-derivations")
|
|
(let* ((parsed-query-parameters
|
|
(guard-against-mutually-exclusive-query-parameters
|
|
(parse-query-parameters
|
|
request
|
|
`((base_branch ,identity #:required)
|
|
(base_datetime ,parse-datetime
|
|
#:default ,(current-date))
|
|
(target_branch ,identity #:required)
|
|
(target_datetime ,parse-datetime
|
|
#:default ,(current-date))
|
|
(system ,parse-system #:multi-value)
|
|
(target ,parse-target #:multi-value)
|
|
(build_status ,parse-build-status #:multi-value)
|
|
(build_change ,parse-build-change)
|
|
(after_name ,identity)
|
|
(limit_results ,parse-result-limit
|
|
#:no-default-when (all_results)
|
|
#:default 40)
|
|
(all_results ,parse-checkbox-value)))
|
|
'((base_commit base_datetime)
|
|
(target_commit target_datetime)
|
|
(limit_results all_results)))))
|
|
(render-compare-by-datetime/package-derivations mime-types
|
|
parsed-query-parameters)))
|
|
(('GET "compare" "packages")
|
|
(let* ((parsed-query-parameters
|
|
(parse-query-parameters
|
|
request
|
|
`((base_commit ,parse-commit #:required)
|
|
(target_commit ,parse-commit #:required)))))
|
|
(render-compare/packages mime-types
|
|
parsed-query-parameters)))
|
|
(('GET "compare" "system-test-derivations")
|
|
(let* ((parsed-query-parameters
|
|
(parse-query-parameters
|
|
request
|
|
`((base_commit ,parse-commit #:required)
|
|
(target_commit ,parse-commit #:required)
|
|
(system ,parse-system #:default "x86_64-linux")))))
|
|
|
|
(render-compare/system-test-derivations mime-types
|
|
parsed-query-parameters)))
|
|
(('GET "compare-by-datetime" "system-test-derivations")
|
|
(let* ((parsed-query-parameters
|
|
(parse-query-parameters
|
|
request
|
|
`((base_branch ,identity #:required)
|
|
(base_datetime ,parse-datetime
|
|
#:default ,(current-date))
|
|
(target_branch ,identity #:required)
|
|
(target_datetime ,parse-datetime
|
|
#:default ,(current-date))
|
|
(system ,parse-system #:default "x86_64-linux")))))
|
|
|
|
(render-compare-by-datetime/system-test-derivations
|
|
mime-types
|
|
parsed-query-parameters)))
|
|
(_ #f)))
|
|
|
|
(define (texinfo->variants-alist s)
|
|
(let ((stexi (texi-fragment->stexi s)))
|
|
`((source . ,s)
|
|
(html . ,(with-output-to-string
|
|
(lambda ()
|
|
(sxml->html (stexi->shtml stexi)))))
|
|
(plain . ,(stexi->plain-text stexi)))))
|
|
|
|
(define (render-compare mime-types
|
|
query-parameters)
|
|
(if (any-invalid-query-parameters? query-parameters)
|
|
(letpar& ((base-job
|
|
(match (assq-ref query-parameters 'base_commit)
|
|
(($ <invalid-query-parameter> value)
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(and (string? value)
|
|
(select-job-for-commit conn value)))))
|
|
(_ #f)))
|
|
(target-job
|
|
(match (assq-ref query-parameters 'target_commit)
|
|
(($ <invalid-query-parameter> value)
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(and (string? value)
|
|
(select-job-for-commit conn value)))))
|
|
(_ #f))))
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
`((error . "invalid query")
|
|
(base_job . ,base-job)
|
|
(target_job . ,target-job))))
|
|
(else
|
|
(render-html
|
|
#:sxml (compare query-parameters
|
|
'revision
|
|
#f
|
|
#f
|
|
#f
|
|
#f
|
|
#f
|
|
#f
|
|
#f)))))
|
|
(letpar& ((base-revision-id
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(commit->revision-id
|
|
conn
|
|
(assq-ref query-parameters 'base_commit)))))
|
|
(target-revision-id
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(commit->revision-id
|
|
conn
|
|
(assq-ref query-parameters 'target_commit)))))
|
|
(locale
|
|
(assq-ref query-parameters 'locale)))
|
|
(let-values
|
|
(((base-packages-vhash target-packages-vhash)
|
|
(package-data->package-data-vhashes
|
|
(parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(package-differences-data conn
|
|
base-revision-id
|
|
target-revision-id)))))))
|
|
(let ((new-packages
|
|
(package-data-vhashes->new-packages base-packages-vhash
|
|
target-packages-vhash))
|
|
(removed-packages
|
|
(package-data-vhashes->removed-packages base-packages-vhash
|
|
target-packages-vhash))
|
|
(version-changes
|
|
(package-data-version-changes base-packages-vhash
|
|
target-packages-vhash)))
|
|
(letpar& ((lint-warnings-data
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(group-list-by-first-n-fields
|
|
2
|
|
(lint-warning-differences-data conn
|
|
base-revision-id
|
|
target-revision-id
|
|
locale)))))
|
|
(channel-news-data
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(channel-news-differences-data conn
|
|
base-revision-id
|
|
target-revision-id)))))
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
`((base-commit . ,(assq-ref query-parameters 'base_commit))
|
|
(target-commit . ,(assq-ref query-parameters 'target_commit))
|
|
(channel-news . ,(list->vector
|
|
(map
|
|
(match-lambda
|
|
((commit tag title_text body_text change)
|
|
`(,@(if (null? commit)
|
|
'()
|
|
`((commit . ,commit)))
|
|
,@(if (null? tag)
|
|
'()
|
|
`((tag . ,tag)))
|
|
(title-text
|
|
. ,(map
|
|
(match-lambda
|
|
((lang . text)
|
|
(cons
|
|
lang
|
|
(texinfo->variants-alist text))))
|
|
title_text))
|
|
(body-text
|
|
. ,(map
|
|
(match-lambda
|
|
((lang . text)
|
|
(cons
|
|
lang
|
|
(texinfo->variants-alist text))))
|
|
body_text))
|
|
(change . ,change))))
|
|
channel-news-data)))
|
|
(new-packages . ,(list->vector new-packages))
|
|
(removed-packages . ,(list->vector removed-packages))
|
|
(version-changes . ,(list->vector
|
|
(map
|
|
(match-lambda
|
|
((name data ...)
|
|
`((name . ,name)
|
|
,@data)))
|
|
version-changes))))
|
|
#:extra-headers http-headers-for-unchanging-content))
|
|
(else
|
|
(letpar& ((lint-warnings-locale-options
|
|
(map
|
|
(match-lambda
|
|
((locale)
|
|
locale))
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(lint-warning-message-locales-for-revision
|
|
conn
|
|
(assq-ref query-parameters 'target_commit))))))
|
|
(cgit-url-bases
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(guix-revisions-cgit-url-bases
|
|
conn
|
|
(list base-revision-id
|
|
target-revision-id))))))
|
|
(render-html
|
|
#:sxml (compare query-parameters
|
|
'revision
|
|
cgit-url-bases
|
|
new-packages
|
|
removed-packages
|
|
version-changes
|
|
lint-warnings-data
|
|
lint-warnings-locale-options
|
|
channel-news-data)
|
|
#:extra-headers http-headers-for-unchanging-content))))))))))
|
|
|
|
(define (render-compare-by-datetime mime-types
|
|
query-parameters)
|
|
(if (any-invalid-query-parameters? query-parameters)
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
'((error . "invalid query"))))
|
|
(else
|
|
(letpar& ((base-job
|
|
(match (assq-ref query-parameters 'base_commit)
|
|
(($ <invalid-query-parameter> value)
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(select-job-for-commit conn value))))
|
|
(_ #f)))
|
|
(target-job
|
|
(match (assq-ref query-parameters 'target_commit)
|
|
(($ <invalid-query-parameter> value)
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(select-job-for-commit conn value))))
|
|
(_ #f))))
|
|
(render-html
|
|
#:sxml (compare query-parameters
|
|
'datetime
|
|
#f
|
|
#f
|
|
#f
|
|
#f
|
|
#f
|
|
#f
|
|
#f)))))
|
|
|
|
(let ((base-branch (assq-ref query-parameters 'base_branch))
|
|
(base-datetime (assq-ref query-parameters 'base_datetime))
|
|
(target-branch (assq-ref query-parameters 'target_branch))
|
|
(target-datetime (assq-ref query-parameters 'target_datetime))
|
|
(locale (assq-ref query-parameters 'locale)))
|
|
(letpar& ((base-revision-details
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(select-guix-revision-for-branch-and-datetime
|
|
conn
|
|
base-branch
|
|
base-datetime))))
|
|
(target-revision-details
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(select-guix-revision-for-branch-and-datetime
|
|
conn
|
|
target-branch
|
|
target-datetime)))))
|
|
(letpar& ((lint-warnings-locale-options
|
|
(map
|
|
(match-lambda
|
|
((locale)
|
|
locale))
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(lint-warning-message-locales-for-revision
|
|
conn
|
|
(second base-revision-details)))))))
|
|
(let ((base-revision-id
|
|
(first base-revision-details))
|
|
(target-revision-id
|
|
(first target-revision-details)))
|
|
(let-values
|
|
(((base-packages-vhash target-packages-vhash)
|
|
(package-data->package-data-vhashes
|
|
(parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(package-differences-data conn
|
|
base-revision-id
|
|
target-revision-id)))))))
|
|
(let* ((new-packages
|
|
(package-data-vhashes->new-packages base-packages-vhash
|
|
target-packages-vhash))
|
|
(removed-packages
|
|
(package-data-vhashes->removed-packages base-packages-vhash
|
|
target-packages-vhash))
|
|
(version-changes
|
|
(package-data-version-changes base-packages-vhash
|
|
target-packages-vhash))
|
|
(channel-news-data
|
|
(parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(channel-news-differences-data conn
|
|
base-revision-id
|
|
target-revision-id))))))
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
`((revisions
|
|
. ((base
|
|
. ((commit . ,(second base-revision-details))
|
|
(datetime . ,(fourth base-revision-details))))
|
|
(target
|
|
. ((commit . ,(second target-revision-details))
|
|
(datetime . ,(fourth target-revision-details))))))
|
|
(channel-news . ,(list->vector
|
|
(map
|
|
(match-lambda
|
|
((commit tag title_text body_text change)
|
|
`(,@(if (null? commit)
|
|
'()
|
|
`((commit . ,commit)))
|
|
,@(if (null? tag)
|
|
'()
|
|
`((tag . ,tag)))
|
|
(title-text
|
|
. ,(map
|
|
(match-lambda
|
|
((lang . text)
|
|
(cons
|
|
lang
|
|
(texinfo->variants-alist text))))
|
|
title_text))
|
|
(body-text
|
|
. ,(map
|
|
(match-lambda
|
|
((lang . text)
|
|
(cons
|
|
lang
|
|
(texinfo->variants-alist text))))
|
|
body_text))
|
|
(change . ,change))))
|
|
channel-news-data)))
|
|
(new-packages . ,(list->vector new-packages))
|
|
(removed-packages . ,(list->vector removed-packages))
|
|
(version-changes . ,(list->vector
|
|
(map
|
|
(match-lambda
|
|
((name data ...)
|
|
`((name . ,name)
|
|
,@data)))
|
|
version-changes))))
|
|
#:extra-headers http-headers-for-unchanging-content))
|
|
(else
|
|
(render-html
|
|
#:sxml (compare `(,@query-parameters
|
|
(base_commit . ,(second base-revision-details))
|
|
(target_commit . ,(second target-revision-details)))
|
|
'datetime
|
|
(parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(guix-revisions-cgit-url-bases
|
|
conn
|
|
(list base-revision-id
|
|
target-revision-id)))))
|
|
new-packages
|
|
removed-packages
|
|
version-changes
|
|
(parallel-via-thread-pool-channel
|
|
(group-list-by-first-n-fields
|
|
2
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(lint-warning-differences-data
|
|
conn
|
|
base-revision-id
|
|
target-revision-id
|
|
locale)))))
|
|
lint-warnings-locale-options
|
|
channel-news-data)
|
|
#:extra-headers http-headers-for-unchanging-content)))))))))))
|
|
|
|
(define (render-compare/derivation mime-types
|
|
query-parameters)
|
|
(if (any-invalid-query-parameters? query-parameters)
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
'((error . "invalid query"))))
|
|
(else
|
|
(render-html
|
|
#:sxml (compare/derivation
|
|
query-parameters
|
|
'()))))
|
|
|
|
(let ((base-derivation (assq-ref query-parameters 'base_derivation))
|
|
(target-derivation (assq-ref query-parameters 'target_derivation)))
|
|
(letpar& ((data
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(derivation-differences-data conn
|
|
base-derivation
|
|
target-derivation)))))
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(let ((outputs
|
|
(map
|
|
(lambda (label items)
|
|
(cons label
|
|
(list->vector
|
|
(map
|
|
(match-lambda
|
|
((name path hash-alg hash recursive)
|
|
`((name . ,name)
|
|
(path . ,path)
|
|
,@(if (string? hash-alg)
|
|
`((hash-algorithm . ,hash-alg))
|
|
'())
|
|
,@(if (string? hash)
|
|
`((hash . ,hash))
|
|
'())
|
|
(recursive . ,(string=? recursive "t")))))
|
|
(or items '())))))
|
|
'(base target common)
|
|
(let ((output-groups (assq-ref data 'outputs)))
|
|
(list (assq-ref output-groups 'base)
|
|
(assq-ref output-groups 'target)
|
|
(assq-ref output-groups 'common)))))
|
|
|
|
(inputs
|
|
(map
|
|
(lambda (label items)
|
|
(cons label
|
|
(list->vector
|
|
(map
|
|
(match-lambda
|
|
((derivation output)
|
|
`((derivation . ,derivation)
|
|
(output . ,output))))
|
|
(or items '())))))
|
|
'(base target common)
|
|
(let ((input-groups (assq-ref data 'inputs)))
|
|
(list (assq-ref input-groups 'base)
|
|
(assq-ref input-groups 'target)
|
|
(assq-ref input-groups 'common)))))
|
|
|
|
(sources
|
|
(map
|
|
(lambda (label items)
|
|
(cons label
|
|
(list->vector
|
|
(map
|
|
(match-lambda
|
|
((derivation)
|
|
`((derivation . ,derivation))))
|
|
(or items '())))))
|
|
'(base target common)
|
|
(let ((source-groups (assq-ref data 'sources)))
|
|
(list (assq-ref source-groups 'base)
|
|
(assq-ref source-groups 'target)
|
|
(assq-ref source-groups 'common)))))
|
|
|
|
(arguments
|
|
(map
|
|
(match-lambda
|
|
((label args ...)
|
|
`(,label . ,(list->vector args))))
|
|
(assq-ref data 'arguments))))
|
|
|
|
(render-json
|
|
`((base . ((derivation . ,base-derivation)))
|
|
(target . ((derivation . ,target-derivation)))
|
|
(outputs . ,outputs)
|
|
(inputs . ,inputs)
|
|
(sources . ,sources)
|
|
(system . ,(assq-ref data 'system))
|
|
(builder . ,(assq-ref data 'builder))
|
|
(arguments . ,arguments)
|
|
(environment-variables . ,(assq-ref
|
|
data 'environment-variables)))
|
|
#:extra-headers http-headers-for-unchanging-content)))
|
|
(else
|
|
(render-html
|
|
#:sxml (compare/derivation
|
|
query-parameters
|
|
data)
|
|
#:extra-headers http-headers-for-unchanging-content)))))))
|
|
|
|
(define (render-compare/package-derivations mime-types
|
|
query-parameters)
|
|
(if (any-invalid-query-parameters? query-parameters)
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
'((error . "invalid query"))))
|
|
(else
|
|
(letpar& ((systems
|
|
(with-thread-postgresql-connection
|
|
list-systems))
|
|
(targets
|
|
(with-thread-postgresql-connection
|
|
valid-targets))
|
|
(build-server-urls
|
|
(with-thread-postgresql-connection
|
|
select-build-server-urls-by-id)))
|
|
(render-html
|
|
#:sxml (compare/package-derivations
|
|
query-parameters
|
|
'revision
|
|
systems
|
|
(valid-targets->options targets)
|
|
build-status-strings
|
|
build-server-urls
|
|
'())))))
|
|
|
|
(let ((base-commit (assq-ref query-parameters 'base_commit))
|
|
(target-commit (assq-ref query-parameters 'target_commit))
|
|
(systems (assq-ref query-parameters 'system))
|
|
(targets (assq-ref query-parameters 'target))
|
|
(build-change (and=>
|
|
(assq-ref query-parameters 'build_change)
|
|
string->symbol))
|
|
(after-name (assq-ref query-parameters 'after_name))
|
|
(limit-results (assq-ref query-parameters 'limit_results)))
|
|
(letpar& ((data
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(package-derivation-differences-data
|
|
conn
|
|
(commit->revision-id conn base-commit)
|
|
(commit->revision-id conn target-commit)
|
|
#:systems systems
|
|
#:targets targets
|
|
#:build-change build-change
|
|
#:after-name after-name
|
|
#:limit-results limit-results))))
|
|
(build-server-urls
|
|
(with-thread-postgresql-connection
|
|
select-build-server-urls-by-id)))
|
|
(let ((names-and-versions
|
|
(package-derivation-data->names-and-versions data)))
|
|
(let-values
|
|
(((base-packages-vhash target-packages-vhash)
|
|
(package-derivation-data->package-derivation-data-vhashes data)))
|
|
(let ((derivation-changes
|
|
(package-derivation-data-changes names-and-versions
|
|
base-packages-vhash
|
|
target-packages-vhash)))
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
`((revisions
|
|
. ((base
|
|
. ((commit . ,base-commit)))
|
|
(target
|
|
. ((commit . ,target-commit)))))
|
|
(derivation_changes
|
|
. ,derivation-changes))))
|
|
(else
|
|
(letpar& ((systems
|
|
(with-thread-postgresql-connection
|
|
list-systems))
|
|
(targets
|
|
(with-thread-postgresql-connection
|
|
valid-targets)))
|
|
(render-html
|
|
#:sxml (compare/package-derivations
|
|
query-parameters
|
|
'revision
|
|
systems
|
|
(valid-targets->options targets)
|
|
build-status-strings
|
|
build-server-urls
|
|
derivation-changes))))))))))))
|
|
|
|
(define (render-compare-by-datetime/package-derivations mime-types
|
|
query-parameters)
|
|
(if (any-invalid-query-parameters? query-parameters)
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
'((error . "invalid query"))))
|
|
(else
|
|
(render-html
|
|
#:sxml (compare/package-derivations
|
|
query-parameters
|
|
'datetime
|
|
(parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection list-systems))
|
|
(valid-targets->options
|
|
(parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection valid-targets)))
|
|
build-status-strings
|
|
'()
|
|
'()
|
|
'()))))
|
|
|
|
(let ((base-branch (assq-ref query-parameters 'base_branch))
|
|
(base-datetime (assq-ref query-parameters 'base_datetime))
|
|
(target-branch (assq-ref query-parameters 'target_branch))
|
|
(target-datetime (assq-ref query-parameters 'target_datetime))
|
|
(systems (assq-ref query-parameters 'system))
|
|
(targets (assq-ref query-parameters 'target))
|
|
(build-change (and=>
|
|
(assq-ref query-parameters 'build_change)
|
|
string->symbol))
|
|
(after-name (assq-ref query-parameters 'after_name))
|
|
(limit-results (assq-ref query-parameters 'limit_results)))
|
|
(letpar&
|
|
((base-revision-details
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(select-guix-revision-for-branch-and-datetime conn
|
|
base-branch
|
|
base-datetime))))
|
|
(target-revision-details
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(select-guix-revision-for-branch-and-datetime conn
|
|
target-branch
|
|
target-datetime)))))
|
|
(letpar&
|
|
((data
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(package-derivation-differences-data
|
|
conn
|
|
(first base-revision-details)
|
|
(first target-revision-details)
|
|
#:systems systems
|
|
#:targets targets
|
|
#:build-change build-change
|
|
#:after-name after-name
|
|
#:limit-results limit-results)))))
|
|
(let ((names-and-versions
|
|
(package-derivation-data->names-and-versions data)))
|
|
(let-values
|
|
(((base-packages-vhash target-packages-vhash)
|
|
(package-derivation-data->package-derivation-data-vhashes data)))
|
|
(let ((derivation-changes
|
|
(package-derivation-data-changes names-and-versions
|
|
base-packages-vhash
|
|
target-packages-vhash)))
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
`((revisions
|
|
. ((base
|
|
. ((commit . ,(second base-revision-details))
|
|
(datetime . ,(fourth base-revision-details))))
|
|
(target
|
|
. ((commit . ,(second target-revision-details))
|
|
(datetime . ,(fourth target-revision-details))))))
|
|
(derivation_changes
|
|
. ,derivation-changes))))
|
|
(else
|
|
(render-html
|
|
#:sxml (compare/package-derivations
|
|
query-parameters
|
|
'datetime
|
|
(parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection list-systems))
|
|
(valid-targets->options
|
|
(parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection valid-targets)))
|
|
build-status-strings
|
|
(parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection
|
|
select-build-server-urls-by-id))
|
|
derivation-changes
|
|
base-revision-details
|
|
target-revision-details))))))))))))
|
|
|
|
(define (render-compare/packages mime-types
|
|
query-parameters)
|
|
(define (package-data-vhash->json vh)
|
|
(delete-duplicates
|
|
(vhash-fold (lambda (name data result)
|
|
(cons `((name . ,name)
|
|
(version . ,(car data)))
|
|
result))
|
|
'()
|
|
vh)))
|
|
|
|
(if (any-invalid-query-parameters? query-parameters)
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
'((error . "invalid query"))))
|
|
(else
|
|
(letpar& ((base-job
|
|
(match (assq-ref query-parameters 'base_commit)
|
|
(($ <invalid-query-parameter> value)
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(select-job-for-commit conn value))))
|
|
(_ #f)))
|
|
(target-job
|
|
(match (assq-ref query-parameters 'target_commit)
|
|
(($ <invalid-query-parameter> value)
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(select-job-for-commit conn value))))
|
|
(_ #f))))
|
|
(render-html
|
|
#:sxml (compare-invalid-parameters
|
|
query-parameters
|
|
base-job
|
|
target-job)))))
|
|
|
|
(let ((base-commit (assq-ref query-parameters 'base_commit))
|
|
(target-commit (assq-ref query-parameters 'target_commit)))
|
|
(letpar& ((base-revision-id
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(commit->revision-id
|
|
conn
|
|
base-commit))))
|
|
(target-revision-id
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(commit->revision-id
|
|
conn
|
|
target-commit)))))
|
|
(let-values
|
|
(((base-packages-vhash target-packages-vhash)
|
|
(package-data->package-data-vhashes
|
|
(parallel-via-thread-pool-channel
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(package-differences-data conn
|
|
base-revision-id
|
|
target-revision-id)))))))
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
`((base
|
|
. ((commit . ,base-commit)
|
|
(packages . ,(list->vector
|
|
(package-data-vhash->json base-packages-vhash)))))
|
|
(target
|
|
. ((commit . ,target-commit)
|
|
(packages . ,(list->vector
|
|
(package-data-vhash->json target-packages-vhash))))))
|
|
#:extra-headers http-headers-for-unchanging-content))
|
|
(else
|
|
(render-html
|
|
#:sxml (compare/packages
|
|
query-parameters
|
|
base-packages-vhash
|
|
target-packages-vhash)
|
|
#:extra-headers http-headers-for-unchanging-content))))))))
|
|
|
|
(define (render-compare/system-test-derivations mime-types
|
|
query-parameters)
|
|
(if (any-invalid-query-parameters? query-parameters)
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
'((error . "invalid query"))))
|
|
(else
|
|
(letpar& ((systems
|
|
(with-thread-postgresql-connection
|
|
list-systems))
|
|
(build-server-urls
|
|
(with-thread-postgresql-connection
|
|
select-build-server-urls-by-id)))
|
|
(render-html
|
|
#:sxml (compare/system-test-derivations
|
|
query-parameters
|
|
'revision
|
|
systems
|
|
build-server-urls
|
|
'()
|
|
'()
|
|
'())))))
|
|
|
|
(let ((base-commit (assq-ref query-parameters 'base_commit))
|
|
(target-commit (assq-ref query-parameters 'target_commit))
|
|
(system (assq-ref query-parameters 'system)))
|
|
(letpar& ((data
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(system-test-derivations-differences-data
|
|
conn
|
|
(commit->revision-id conn base-commit)
|
|
(commit->revision-id conn target-commit)
|
|
system))))
|
|
(build-server-urls
|
|
(with-thread-postgresql-connection
|
|
select-build-server-urls-by-id))
|
|
(base-git-repositories
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(git-repositories-containing-commit conn base-commit))))
|
|
(target-git-repositories
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(git-repositories-containing-commit conn target-commit))))
|
|
(systems
|
|
(with-thread-postgresql-connection
|
|
list-systems)))
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
`((revisions
|
|
. ((base
|
|
. ((commit . ,base-commit)))
|
|
(target
|
|
. ((commit . ,target-commit)))))
|
|
(changes . ,(list->vector data)))))
|
|
(else
|
|
(render-html
|
|
#:sxml (compare/system-test-derivations
|
|
query-parameters
|
|
'revision
|
|
systems
|
|
build-server-urls
|
|
base-git-repositories
|
|
target-git-repositories
|
|
data))))))))
|
|
|
|
(define (render-compare-by-datetime/system-test-derivations mime-types
|
|
query-parameters)
|
|
(if (any-invalid-query-parameters? query-parameters)
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
'((error . "invalid query"))))
|
|
(else
|
|
(letpar& ((systems
|
|
(with-thread-postgresql-connection
|
|
list-systems))
|
|
(build-server-urls
|
|
(with-thread-postgresql-connection
|
|
select-build-server-urls-by-id)))
|
|
(render-html
|
|
#:sxml (compare/system-test-derivations
|
|
query-parameters
|
|
'datetime
|
|
systems
|
|
build-server-urls
|
|
'()
|
|
'()
|
|
'())))))
|
|
|
|
(let ((base-branch (assq-ref query-parameters 'base_branch))
|
|
(base-datetime (assq-ref query-parameters 'base_datetime))
|
|
(target-branch (assq-ref query-parameters 'target_branch))
|
|
(target-datetime (assq-ref query-parameters 'target_datetime))
|
|
(system (assq-ref query-parameters 'system)))
|
|
(letpar&
|
|
((base-revision-details
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(select-guix-revision-for-branch-and-datetime conn
|
|
base-branch
|
|
base-datetime))))
|
|
(target-revision-details
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(select-guix-revision-for-branch-and-datetime conn
|
|
target-branch
|
|
target-datetime)))))
|
|
(letpar& ((data
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(system-test-derivations-differences-data
|
|
conn
|
|
(first base-revision-details)
|
|
(first target-revision-details)
|
|
system))))
|
|
(build-server-urls
|
|
(with-thread-postgresql-connection
|
|
select-build-server-urls-by-id))
|
|
(base-git-repositories
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(git-repositories-containing-commit
|
|
conn
|
|
(second base-revision-details)))))
|
|
(target-git-repositories
|
|
(with-thread-postgresql-connection
|
|
(lambda (conn)
|
|
(git-repositories-containing-commit
|
|
conn
|
|
(second target-revision-details)))))
|
|
(systems
|
|
(with-thread-postgresql-connection
|
|
list-systems)))
|
|
(case (most-appropriate-mime-type
|
|
'(application/json text/html)
|
|
mime-types)
|
|
((application/json)
|
|
(render-json
|
|
`((revisions
|
|
. ((base
|
|
. ((commit . ,(second base-revision-details))
|
|
(datetime . ,(fourth base-revision-details))))
|
|
(target
|
|
. ((commit . ,(second target-revision-details))
|
|
(datetime . ,(fourth target-revision-details))))))
|
|
(changes . ,(list->vector data)))))
|
|
(else
|
|
(render-html
|
|
#:sxml (compare/system-test-derivations
|
|
query-parameters
|
|
'datetime
|
|
systems
|
|
build-server-urls
|
|
base-git-repositories
|
|
target-git-repositories
|
|
data
|
|
base-revision-details
|
|
target-revision-details)))))))))
|