aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am8
-rw-r--r--guix-data-service/jobs/load-new-guix-revision.scm271
-rw-r--r--guix-data-service/model/lint-checker.scm15
-rw-r--r--guix-data-service/model/lint-warning-message.scm57
-rw-r--r--guix-data-service/model/lint-warning.scm36
-rw-r--r--sqitch/deploy/lint_warnings.sql41
-rw-r--r--sqitch/revert/lint_warnings.sql11
-rw-r--r--sqitch/sqitch.plan1
-rw-r--r--sqitch/verify/lint_warnings.sql7
-rw-r--r--tests/model-lint-checker.scm37
-rw-r--r--tests/model-lint-warning-message.scm57
11 files changed, 490 insertions, 51 deletions
diff --git a/Makefile.am b/Makefile.am
index e923ec1..8046df9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -57,8 +57,11 @@ SOURCES = \
guix-data-service/model/git-repository.scm \
guix-data-service/model/guix-revision-package-derivation.scm \
guix-data-service/model/guix-revision.scm \
- guix-data-service/model/license.scm \
guix-data-service/model/license-set.scm \
+ guix-data-service/model/license.scm \
+ guix-data-service/model/lint-checker.scm \
+ guix-data-service/model/lint-warning-message.scm \
+ guix-data-service/model/lint-warning.scm \
guix-data-service/model/location.scm \
guix-data-service/model/package-derivation.scm \
guix-data-service/model/package-metadata.scm \
@@ -84,6 +87,9 @@ TESTS = \
tests/model-git-repository.scm \
tests/model-license-set.scm \
tests/model-license.scm \
+ tests/model-lint-checker.scm \
+ tests/model-lint-warning.scm \
+ tests/model-lint-warning-message.scm \
tests/model-package-metadata.scm
AM_TESTS_ENVIRONMENT = abs_top_srcdir="$(abs_top_srcdir)"
diff --git a/guix-data-service/jobs/load-new-guix-revision.scm b/guix-data-service/jobs/load-new-guix-revision.scm
index 8b1ea84..a138b12 100644
--- a/guix-data-service/jobs/load-new-guix-revision.scm
+++ b/guix-data-service/jobs/load-new-guix-revision.scm
@@ -9,6 +9,7 @@
#:use-module (guix channels)
#:use-module (guix inferior)
#:use-module (guix profiles)
+ #:use-module (guix utils)
#:use-module (guix progress)
#:use-module (guix packages)
#:use-module (guix derivations)
@@ -21,6 +22,10 @@
#:use-module (guix-data-service model package-derivation)
#:use-module (guix-data-service model guix-revision-package-derivation)
#:use-module (guix-data-service model license-set)
+ #:use-module (guix-data-service model lint-checker)
+ #:use-module (guix-data-service model lint-warning)
+ #:use-module (guix-data-service model lint-warning-message)
+ #:use-module (guix-data-service model location)
#:use-module (guix-data-service model package-metadata)
#:use-module (guix-data-service model derivation)
#:export (log-for-job
@@ -193,6 +198,100 @@ WHERE job_id = $1"
(simple-format #t "debug: Finished ~A, took ~A seconds\n"
action time-taken)))))
+(define (all-inferior-lint-warnings inf store)
+ (define checkers
+ (inferior-eval
+ '(begin
+ (use-modules (guix lint))
+ (map (lambda (checker)
+ (list (lint-checker-name checker)
+ (lint-checker-description checker)
+ (if (memq checker %network-dependent-checkers)
+ #t
+ #f)))
+ %all-checkers))
+ inf))
+
+ (define locales
+ '("cs_CZ.utf8"
+ "da_DK.utf8"
+ "de_DE.utf8"
+ "eo_EO.utf8"
+ "es_ES.utf8"
+ "fr_FR.utf8"
+ "hu_HU.utf8"
+ "pl_PL.utf8"
+ "pt_BR.utf8"
+ ;;"sr_SR.utf8"
+ "sv_SE.utf8"
+ "vi_VN.utf8"
+ "zh_CN.utf8"))
+
+ (define (lint-warnings-for-checker checker-name)
+ `(lambda (store)
+ (let* ((checker (find (lambda (checker)
+ (eq? (lint-checker-name checker)
+ ',checker-name))
+ %local-checkers))
+ (check (lint-checker-check checker)))
+ (filter
+ (match-lambda
+ ((package-id . warnings)
+ (not (null? warnings))))
+ (hash-map->list
+ (lambda (package-id package)
+ (cons
+ package-id
+ (map
+ (lambda (lint-warning)
+ (list
+ (match (lint-warning-location lint-warning)
+ (($ <location> file line column)
+ (list (if (string-prefix? "/gnu/store/" file)
+ ;; Convert a string like
+ ;; /gnu/store/53xh0mpigin2rffg31s52x5dc08y0qmr-guix-module-union/share/guile/site/2.2/gnu/packages/xdisorg.scm
+ ;;
+ ;; This happens when the checker uses
+ ;; package-field-location.
+ (string-join (drop (string-split file #\/) 8) "/")
+ file)
+ line
+ column)))
+ (let* ((source-locale "en_US.utf8")
+ (source-message
+ (begin
+ (setlocale LC_MESSAGES source-locale)
+ (lint-warning-message lint-warning)))
+ (messages-by-locale
+ (filter-map
+ (lambda (locale)
+ (setlocale LC_MESSAGES locale)
+ (let ((message
+ (lint-warning-message lint-warning)))
+ (if (string=? message source-message)
+ #f
+ (cons locale message))))
+ (list ,@locales))))
+ (setlocale LC_MESSAGES "")
+ (cons (cons source-locale source-message)
+ messages-by-locale))))
+ (check package))))
+ %package-table)))))
+
+ (map
+ (match-lambda
+ ((name description network-dependent?)
+ (cons
+ (list name description network-dependent?)
+ (if network-dependent?
+ '()
+ (log-time
+ (simple-format #f "getting ~A lint warnings" name)
+ (lambda ()
+ (inferior-eval-with-store inf store (lint-warnings-for-checker
+ name))))))))
+ checkers))
+
(define (all-inferior-package-derivations store inf packages)
(define inferior-%supported-systems
(inferior-eval '(@ (guix packages) %supported-systems) inf))
@@ -332,9 +431,7 @@ WHERE job_id = $1"
(string<? a-name
b-name)))))))
-(define (packages-and-inferior-data->package-derivation-ids conn inf
- packages
- inferior-data-4-tuples)
+(define (insert-packages conn inf packages)
(let* ((package-license-set-ids
(log-time "fetching inferior package license metadata"
(lambda ()
@@ -344,43 +441,81 @@ WHERE job_id = $1"
(log-time "fetching inferior package metadata"
(lambda ()
(inferior-packages->package-metadata-ids
- conn packages package-license-set-ids))))
- (package-ids
- (log-time "getting package-ids"
- (lambda ()
- (inferior-packages->package-ids
- conn packages packages-metadata-ids)))))
-
- (simple-format
- #t "debug: finished loading information from inferior\n")
- (close-inferior inf)
-
- (let* ((derivation-ids
- (derivation-file-names->derivation-ids
- conn
- (map fourth inferior-data-4-tuples)))
- (inferior-package-id->package-id-hash-table
- (alist->hashq-table
- (map (lambda (package package-id)
- (cons (inferior-package-id package)
- package-id))
- packages
- package-ids)))
- (flat-package-ids-systems-and-targets
+ conn packages package-license-set-ids)))))
+
+ (log-time "getting package-ids"
+ (lambda ()
+ (inferior-packages->package-ids
+ conn packages packages-metadata-ids)))))
+
+(define (insert-lint-warnings conn inferior-package-id->package-database-id
+ lint-warnings-data)
+ (let ((lint-checker-ids
+ (lint-checkers->lint-checker-ids
+ conn
+ (map car lint-warnings-data))))
+
+ (lint-warnings-data->lint-warning-ids
+ conn
+ (append-map
+ (lambda (lint-checker-id warnings-by-package-id)
+ (append-map
+ (match-lambda
+ ((package-id . warnings)
(map
(match-lambda
- ((inferior-package-id system target derivation-file-name)
- (list (hashq-ref inferior-package-id->package-id-hash-table
- inferior-package-id)
- system
- target)))
- inferior-data-4-tuples))
- (package-derivation-ids
- (insert-package-derivations conn
- flat-package-ids-systems-and-targets
- derivation-ids)))
-
- package-derivation-ids)))
+ ((location-data messages-by-locale)
+ (let ((location-id
+ (location->location-id
+ conn
+ (apply location location-data)))
+ (lint-warning-message-set-id
+ (lint-warning-message-data->lint-warning-message-set-id
+ conn
+ messages-by-locale)))
+ (list lint-checker-id
+ (inferior-package-id->package-database-id package-id)
+ location-id
+ lint-warning-message-set-id))))
+ (fold (lambda (location-and-messages result)
+ (if (member location-and-messages result)
+ (begin
+ (apply
+ simple-format
+ (current-error-port)
+ "warning: skipping duplicate lint warning ~A ~A"
+ location-and-messages)
+ result)
+ (append result
+ (list location-and-messages))))
+ '()
+ warnings))))
+ warnings-by-package-id))
+ lint-checker-ids
+ (map cdr lint-warnings-data)))))
+
+(define (inferior-data->package-derivation-ids
+ conn inf
+ inferior-package-id->package-database-id
+ inferior-data-4-tuples)
+ (let ((derivation-ids
+ (derivation-file-names->derivation-ids
+ conn
+ (map fourth inferior-data-4-tuples)))
+ (flat-package-ids-systems-and-targets
+ (map
+ (match-lambda
+ ((inferior-package-id system target derivation-file-name)
+ (list (inferior-package-id->package-database-id
+ inferior-package-id)
+ system
+ target)))
+ inferior-data-4-tuples)))
+
+
+ (insert-package-derivations conn
+ flat-package-ids-systems-and-targets
+ derivation-ids)))
(define (inferior-package-transitive-supported-systems package)
((@@ (guix inferior) inferior-package-field)
@@ -575,6 +710,11 @@ WHERE job_id = $1"
(lambda ()
(deduplicate-inferior-packages
(inferior-packages inf)))))
+ (inferior-lint-warnings
+ (log-time
+ "fetching inferior lint warnings"
+ (lambda ()
+ (all-inferior-lint-warnings inf store))))
(inferior-data-4-tuples
(log-time
"getting inferior derivations"
@@ -586,26 +726,57 @@ WHERE job_id = $1"
(obtain-advisory-transaction-lock conn
'load-new-guix-revision-inserts)
- (let* ((package-derivation-ids
- (packages-and-inferior-data->package-derivation-ids
- conn inf packages inferior-data-4-tuples))
- (guix-revision-id
- (insert-guix-revision conn git-repository-id commit store-path)))
-
- (insert-guix-revision-package-derivations conn
- guix-revision-id
- package-derivation-ids)
+ (let* ((package-ids
+ (insert-packages conn inf packages))
+ (inferior-package-id->package-database-id
+ (let ((lookup-table
+ (alist->hashq-table
+ (map (lambda (package package-id)
+ (cons (inferior-package-id package)
+ package-id))
+ packages
+ package-ids))))
+ (lambda (inferior-id)
+ (hashq-ref lookup-table inferior-id)))))
(simple-format
- #t "Successfully loaded ~A package/derivation pairs\n"
- (length package-derivation-ids))))
+ #t "debug: finished loading information from inferior\n")
+ (close-inferior inf)
+
+ (let* ((lint-warning-ids
+ (insert-lint-warnings
+ conn
+ inferior-package-id->package-database-id
+ inferior-lint-warnings))
+ (package-derivation-ids
+ (inferior-data->package-derivation-ids
+ conn inf inferior-package-id->package-database-id
+ inferior-data-4-tuples))
+ (guix-revision-id
+ (insert-guix-revision conn git-repository-id
+ commit store-path)))
+
+ (insert-guix-revision-lint-warnings conn
+ guix-revision-id
+ lint-warning-ids)
+
+ (insert-guix-revision-package-derivations conn
+ guix-revision-id
+ package-derivation-ids)
+
+ (simple-format
+ #t "Successfully loaded ~A package/derivation pairs\n"
+ (length package-derivation-ids)))))
#t)
(lambda (key . args)
(simple-format (current-error-port)
"Failed extracting information from commit: ~A\n\n" commit)
(simple-format (current-error-port)
" ~A ~A\n\n" key args)
- #f)))))
+ #f)
+ (lambda (key . args)
+ (display-backtrace (make-stack #t) (current-error-port)))))))
+
(define (store-item-for-git-repository-id-and-commit
conn git-repository-id commit)
diff --git a/guix-data-service/model/lint-checker.scm b/guix-data-service/model/lint-checker.scm
new file mode 100644
index 0000000..6193966
--- /dev/null
+++ b/guix-data-service/model/lint-checker.scm
@@ -0,0 +1,15 @@
+(define-module (guix-data-service model lint-checker)
+ #:use-module (srfi srfi-1)
+ #:use-module (ice-9 match)
+ #:use-module (guix-data-service model utils)
+ #:export (lint-checkers->lint-checker-ids))
+
+(define (lint-checkers->lint-checker-ids conn lint-checkers-data)
+ (insert-missing-data-and-return-all-ids
+ conn
+ "lint_checkers"
+ `((name . ,(lambda (value)
+ (quote-string (symbol->string value))))
+ (description . ,quote-string)
+ (network_dependent . ,value->sql-boolean))
+ lint-checkers-data))
diff --git a/guix-data-service/model/lint-warning-message.scm b/guix-data-service/model/lint-warning-message.scm
new file mode 100644
index 0000000..70851d9
--- /dev/null
+++ b/guix-data-service/model/lint-warning-message.scm
@@ -0,0 +1,57 @@
+(define-module (guix-data-service model lint-warning-message)
+ #:use-module (ice-9 match)
+ #:use-module (squee)
+ #:use-module (guix-data-service database)
+ #:use-module (guix-data-service model utils)
+ #:export (lint-warning-message-data->lint-warning-message-ids
+
+ lint-warning-message-data->lint-warning-message-set-id))
+
+(define (lint-warning-message-data->lint-warning-message-ids conn
+ messages-by-locale)
+ (insert-missing-data-and-return-all-ids
+ conn
+ "lint_warning_messages"
+ `((locale . ,quote-string)
+ (message . ,quote-string))
+ (map (match-lambda
+ ((locale . message)
+ (list locale message)))
+ messages-by-locale)))
+
+(define (insert-lint-warning-message-set conn lint-message-ids)
+ (let ((query
+ (string-append
+ "INSERT INTO lint_warning_message_sets (message_ids) VALUES "
+ (string-append
+ "('{"
+ (string-join
+ (map number->string
+ (sort (map string->number lint-message-ids) <))
+ ", ")
+ "}')")
+ " RETURNING id")))
+
+ (match (exec-query conn query)
+ (((id)) id))))
+
+(define (lint-warning-message-data->lint-warning-message-set-id
+ conn
+ messages-by-locale)
+
+ (let* ((lint-warning-message-ids
+ (lint-warning-message-data->lint-warning-message-ids
+ conn messages-by-locale))
+ (lint-message-set-id
+ (exec-query
+ conn
+ (string-append
+ "SELECT id FROM lint_warning_message_sets "
+ "WHERE message_ids = ARRAY["
+ (string-join lint-warning-message-ids ", ")
+ "]"))))
+
+ (match lint-message-set-id
+ (((id)) id)
+ (()
+ (insert-lint-warning-message-set conn lint-warning-message-ids)))))
diff --git a/guix-data-service/model/lint-warning.scm b/guix-data-service/model/lint-warning.scm
new file mode 100644
index 0000000..e516618
--- /dev/null
+++ b/guix-data-service/model/lint-warning.scm
@@ -0,0 +1,36 @@
+(define-module (guix-data-service model lint-warning)
+ #:use-module (squee)
+ #:use-module (guix-data-service model utils)
+ #:export (lint-warnings-data->lint-warning-ids
+ insert-guix-revision-lint-warnings))
+
+(define (lint-warnings-data->lint-warning-ids
+ conn
+ ;; (lint-checker-id package-id location-id lint-warning-message-set-id)
+ lint-warnings-data)
+ (insert-missing-data-and-return-all-ids
+ conn
+ "lint_warnings"
+ `((lint_checker_id . ,identity)
+ (package_id . ,identity)
+ (location_id . ,identity)
+ (lint_warning_message_set_id . ,identity))
+ lint-warnings-data))
+
+(define (insert-guix-revision-lint-warnings conn
+ guix-revision-id
+ lint-warning-ids)
+ (exec-query
+ conn
+ (string-append
+ "INSERT INTO guix_revision_lint_warnings (lint_warning_id, guix_revision_id) "
+ "VALUES "
+ (string-join
+ (map (lambda (lint-warning-id)
+ (simple-format
+ #f
+ "(~A, ~A)"
+ lint-warning-id
+ guix-revision-id))
+ lint-warning-ids)
+ ", "))))
diff --git a/sqitch/deploy/lint_warnings.sql b/sqitch/deploy/lint_warnings.sql
new file mode 100644
index 0000000..1051b74
--- /dev/null
+++ b/sqitch/deploy/lint_warnings.sql
@@ -0,0 +1,41 @@
+-- Deploy guix-data-service:lint_warnings to pg
+
+BEGIN;
+
+CREATE TABLE lint_checkers (
+ id integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
+ name varchar NOT NULL,
+ description varchar NOT NULL,
+ network_dependent boolean NOT NULL,
+ UNIQUE (name, description, network_dependent)
+);
+
+CREATE TABLE lint_warning_messages (
+ id integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
+ locale varchar NOT NULL,
+ message varchar NOT NULL,
+ UNIQUE (locale, message)
+);
+
+CREATE TABLE lint_warning_message_sets (
+ id integer NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
+ message_ids integer[] NOT NULL,
+ UNIQUE (message_ids)
+);
+
+CREATE TABLE lint_warnings (
+ id integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
+ lint_checker_id integer NOT NULL,
+ package_id integer NOT NULL REFERENCES packages (id),
+ location_id integer NOT NULL REFERENCES locations (id),
+ lint_warning_message_set_id integer NOT NULL REFERENCES lint_warning_message_sets (id),
+ UNIQUE (lint_checker_id, package_id, location_id, lint_warning_message_set_id)
+);
+
+CREATE TABLE guix_revision_lint_warnings (
+ lint_warning_id integer NOT NULL REFERENCES lint_warnings (id),
+ guix_revision_id integer NOT NULL REFERENCES guix_revisions (id),
+ PRIMARY KEY (lint_warning_id, guix_revision_id)
+);
+
+COMMIT;
diff --git a/sqitch/revert/lint_warnings.sql b/sqitch/revert/lint_warnings.sql
new file mode 100644
index 0000000..ea36d37
--- /dev/null
+++ b/sqitch/revert/lint_warnings.sql
@@ -0,0 +1,11 @@
+-- Revert guix-data-service:lint_warnings from pg
+
+BEGIN;
+
+DROP TABLE guix_revision_lint_warnings;
+DROP TABLE lint_warnings;
+DROP TABLE lint_warning_message_sets;
+DROP TABLE lint_warning_messages;
+DROP TABLE lint_checkers;
+
+COMMIT;
diff --git a/sqitch/sqitch.plan b/sqitch/sqitch.plan
index 541074c..fb234ae 100644
--- a/sqitch/sqitch.plan
+++ b/sqitch/sqitch.plan
@@ -18,3 +18,4 @@ change_load_new_guix_revision_job_logs_contents_to_be_nullable 2019-07-07T20:10:
fix_duplicated_licenses 2019-07-30T05:48:17Z Christopher Baines <mail@cbaines.net> # Fix duplicated licenses, and add constraints
change_git_branches_primary_key 2019-08-05T18:57:41Z Christopher Baines <mail@cbaines.net> # Change the git_branches primary key to include the git_repository_id,\nas this will allow having the same branch in different repositories.
remove_duplicate_load_new_guix_revision_jobs 2019-08-05T19:06:36Z Christopher Baines <mail@cbaines.net> # Remove duplicate load_new_guix_revision_jobs
+lint_warnings 2019-08-18T17:10:12Z Christopher Baines <mail@cbaines.net> # Store lint warnings
diff --git a/sqitch/verify/lint_warnings.sql b/sqitch/verify/lint_warnings.sql
new file mode 100644
index 0000000..5af9a76
--- /dev/null
+++ b/sqitch/verify/lint_warnings.sql
@@ -0,0 +1,7 @@
+-- Verify guix-data-service:lint_warnings on pg
+
+BEGIN;
+
+-- XXX Add verifications here.
+
+ROLLBACK;
diff --git a/tests/model-lint-checker.scm b/tests/model-lint-checker.scm
new file mode 100644
index 0000000..64088e5
--- /dev/null
+++ b/tests/model-lint-checker.scm
@@ -0,0 +1,37 @@
+(define-module (tests model-lint-checker)
+ #:use-module (srfi srfi-64)
+ #:use-module (ice-9 match)
+ #:use-module (guix-data-service database)
+ #:use-module (guix-data-service model lint-checker))
+
+(test-begin "test-model-lint-checker")
+
+(define data
+ '((name-1 "description-1" #t)
+ (name-2 "description-2" #f)))
+
+(with-postgresql-connection
+ "test-model-lint-checker"
+ (lambda (conn)
+ (test-assert "single insert"
+ (with-postgresql-transaction
+ conn
+ (lambda (conn)
+ (match (lint-checkers->lint-checker-ids conn data)
+ (((? string? id1) (? string? id2))
+ #t)))
+ #:always-rollback? #t))
+
+ (test-assert "double insert"
+ (with-postgresql-transaction
+ conn
+ (lambda (conn)
+ (match (lint-checkers->lint-checker-ids conn data)
+ (((? string? id1) (? string? id2))
+ (match (lint-checkers->lint-checker-ids conn data)
+ (((? string? second-id1) (? string? second-id2))
+ (and (string=? id1 second-id1)
+ (string=? id2 second-id2)))))))
+ #:always-rollback? #t))))
+
+(test-end)
diff --git a/tests/model-lint-warning-message.scm b/tests/model-lint-warning-message.scm
new file mode 100644
index 0000000..c6fad55
--- /dev/null
+++ b/tests/model-lint-warning-message.scm
@@ -0,0 +1,57 @@
+(define-module (tests model-lint-warning-message)
+ #:use-module (srfi srfi-64)
+ #:use-module (ice-9 match)
+ #:use-module (guix-data-service database)
+ #:use-module (guix-data-service model lint-warning-message))
+
+(test-begin "test-model-lint-warning-message")
+
+(define data
+ '(("en" . "Test message")
+ ("es" . "Test message in Spanish")))
+
+(with-postgresql-connection
+ "test-model-lint-checker"
+ (lambda (conn)
+ (test-assert "single insert"
+ (with-postgresql-transaction
+ conn
+ (lambda (conn)
+ (match (lint-warning-message-data->lint-warning-message-ids conn data)
+ (((? string? id1) (? string? id2))
+ #t)))
+ #:always-rollback? #t))
+
+ (test-assert "double insert"
+ (with-postgresql-transaction
+ conn
+ (lambda (conn)
+ (match (lint-warning-message-data->lint-warning-message-ids conn data)
+ (((? string? id1) (? string? id2))
+ (match (lint-warning-message-data->lint-warning-message-ids conn data)
+ (((? string? second-id1) (? string? second-id2))
+ (and (string=? id1 second-id1)
+ (string=? id2 second-id2)))))))
+ #:always-rollback? #t))
+
+ (test-assert "single set insert"
+ (with-postgresql-transaction
+ conn
+ (lambda (conn)
+ (match (lint-warning-message-data->lint-warning-message-set-id conn data)
+ ((? string? id1)
+ #t)))
+ #:always-rollback? #t))
+
+ (test-assert "double set insert"
+ (with-postgresql-transaction
+ conn
+ (lambda (conn)
+ (match (lint-warning-message-data->lint-warning-message-set-id conn data)
+ ((? string? id)
+ (match (lint-warning-message-data->lint-warning-message-set-id conn data)
+ ((? string? second-id)
+ (string=? id second-id))))))
+ #:always-rollback? #t))))
+
+(test-end)