From b73981369e414bfef6c4f8e48fc457a43c0e12cb Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Thu, 12 Nov 2020 09:29:05 +0100 Subject: lint: patch-file-names: Simplify 'search-patch' error handling. * guix/lint.scm (check-patch-file-names): Remove 'message-condition?' guard, which is useless since d51bfe242fbe6f3f8f71d723e8fe0c7bbe711ba1. Remove call to 'format' in the 'formatted-message?' case. --- guix/lint.scm | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'guix/lint.scm') diff --git a/guix/lint.scm b/guix/lint.scm index e1a77e8ac7..91dbc806dc 100644 --- a/guix/lint.scm +++ b/guix/lint.scm @@ -663,17 +663,11 @@ from ~a") (define (check-patch-file-names package) "Emit a warning if the patches requires by PACKAGE are badly named or if the patch could not be found." - (guard (c ((message-condition? c) ;raised by 'search-patch' - (list - ;; Use %make-warning, as condition-mesasge is already - ;; translated. - (%make-warning package (condition-message c) - #:field 'patch-file-names))) - ((formatted-message? c) + (guard (c ((formatted-message? c) ;raised by 'search-patch' (list (%make-warning package - (apply format #f - (G_ (formatted-message-string c)) - (formatted-message-arguments c)))))) + (formatted-message-string c) + (formatted-message-arguments c) + #:field 'source)))) (define patches (match (package-source package) ((? origin? origin) (origin-patches origin)) -- cgit v1.2.3 From 4f156c259f984f4f5a3692364746446294ee102c Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Thu, 12 Nov 2020 12:50:44 +0100 Subject: lint: Add 'patch-headers' checker. * guix/lint.scm (check-patch-headers): New procedure. (%local-checkers): Add 'patch-headers' checker. * tests/lint.scm ("patch headers: no warnings") ("patch headers: missing comment", "patch headers: empty") ("patch headers: patch not found"): New tests. --- guix/lint.scm | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/lint.scm | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) (limited to 'guix/lint.scm') diff --git a/guix/lint.scm b/guix/lint.scm index 91dbc806dc..0b38ca0d33 100644 --- a/guix/lint.scm +++ b/guix/lint.scm @@ -35,6 +35,8 @@ #:use-module (guix http-client) #:use-module (guix packages) #:use-module (guix i18n) + #:use-module ((guix gexp) + #:select (local-file? local-file-absolute-file-name)) #:use-module (guix licenses) #:use-module (guix records) #:use-module (guix grafts) @@ -73,6 +75,7 @@ check-inputs-should-be-native check-inputs-should-not-be-an-input-at-all check-patch-file-names + check-patch-headers check-synopsis-style check-derivation check-home-page @@ -712,6 +715,54 @@ patch could not be found." (_ #f)) patches))))) +(define (check-patch-headers package) + "Check that PACKAGE's patches start with a comment. Return a list of +warnings." + (define (blank? str) + (string-every char-set:blank str)) + + (define (patch-header-warnings patch) + (call-with-input-file patch + (lambda (port) + ;; Read from PORT until a non-blank line is found or EOF is reached. + (let loop () + (let ((line (read-line port))) + (cond ((eof-object? line) + (list (make-warning package + (G_ "~a: empty patch") + (list (basename patch)) + #:field 'source))) + ((blank? line) + (loop)) + ((or (string-prefix? "--- " line) + (string-prefix? "+++ " line)) + (list (make-warning package + (G_ "~a: patch lacks comment and \ +upstream status") + (list (basename patch)) + #:field 'source))) + (else + '()))))))) + + (guard (c ((formatted-message? c) ;raised by 'search-patch' + (list (%make-warning package + (formatted-message-string c) + (formatted-message-arguments c) + #:field 'source)))) + (let ((patches (if (origin? (package-source package)) + (origin-patches (package-source package)) + '()))) + (append-map (lambda (patch) + ;; Dismiss PATCH if it's an origin or similar. + (cond ((string? patch) + (patch-header-warnings patch)) + ((local-file? patch) + (patch-header-warnings + (local-file-absolute-file-name patch))) + (else + '()))) + patches)))) + (define (escape-quotes str) "Replace any quote character in STR by an escaped quote character." (list->string @@ -1417,6 +1468,10 @@ or a list thereof") (name 'patch-file-names) (description "Validate file names and availability of patches") (check check-patch-file-names)) + (lint-checker + (name 'patch-headers) + (description "Validate patch headers") + (check check-patch-headers)) (lint-checker (name 'formatting) (description "Look for formatting issues in the source") diff --git a/tests/lint.scm b/tests/lint.scm index 95abd71378..bd052842f3 100644 --- a/tests/lint.scm +++ b/tests/lint.scm @@ -36,6 +36,8 @@ #:use-module (guix lint) #:use-module (guix ui) #:use-module (guix swh) + #:use-module ((guix gexp) #:select (local-file)) + #:use-module ((guix utils) #:select (call-with-temporary-directory)) #:use-module (gnu packages) #:use-module (gnu packages glib) #:use-module (gnu packages pkg-config) @@ -344,6 +346,60 @@ (list (search-patch "this-patch-does-not-exist!")))))))) (check-patch-file-names pkg)))) +(test-assert "patch headers: no warnings" + (call-with-temporary-directory + (lambda (directory) + (call-with-output-file (string-append directory "/t.patch") + (lambda (port) + (display "This is a patch.\n\n--- a\n+++ b\n" + port))) + + (parameterize ((%patch-path (list directory))) + (let ((pkg (dummy-package "x" + (source (dummy-origin + (patches (search-patches "t.patch"))))))) + (null? (check-patch-headers pkg))))))) + +(test-equal "patch headers: missing comment" + "t.patch: patch lacks comment and upstream status" + (call-with-temporary-directory + (lambda (directory) + (call-with-output-file (string-append directory "/t.patch") + (lambda (port) + (display "\n--- a\n+++ b\n" + port))) + + (parameterize ((%patch-path (list directory))) + (let ((pkg (dummy-package "x" + (source (dummy-origin + (patches (search-patches "t.patch"))))))) + (single-lint-warning-message (check-patch-headers pkg))))))) + +(test-equal "patch headers: empty" + "t.patch: empty patch" + (call-with-temporary-directory + (lambda (directory) + (call-with-output-file (string-append directory "/t.patch") + (const #t)) + + (parameterize ((%patch-path '())) + (let ((pkg (dummy-package "x" + (source (dummy-origin + (patches + (list (local-file + (string-append directory + "/t.patch"))))))))) + (single-lint-warning-message (check-patch-headers pkg))))))) + +(test-equal "patch headers: patch not found" + "does-not-exist.patch: patch not found\n" + (parameterize ((%patch-path '())) + (let ((pkg (dummy-package "x" + (source (dummy-origin + (patches + (search-patches "does-not-exist.patch"))))))) + (single-lint-warning-message (check-patch-headers pkg))))) + (test-equal "derivation: invalid arguments" "failed to create x86_64-linux derivation: (wrong-type-arg \"map\" \"Wrong type argument: ~S\" (invalid-module) ())" (match (let ((pkg (dummy-package "x" -- cgit v1.2.3 From 464b1fffb0f08a452b4ee67ba23c87730d73568e Mon Sep 17 00:00:00 2001 From: Timothy Sample Date: Tue, 3 Nov 2020 15:30:28 -0500 Subject: lint: Add 'check-haskell-stackage' checker. * guix/lint.scm (check-haskell-stackage): New procedure. (%network-dependent-checkers): Add 'haskell-stackage' checker. * guix/import/hackage.scm (%hackage-url): New variable. (hackage-source-url, hackage-cabal-url): Use it in place of a hard-coded string. * guix/import/stackage.scm (%stackage-url): Make it a parameter. (stackage-lts-info-fetch): Update accordingly. * tests/lint.scm ("hackage-stackage"): New test. --- guix/import/hackage.scm | 14 +++++++++----- guix/import/stackage.scm | 8 +++++--- guix/lint.scm | 28 +++++++++++++++++++++++++++- tests/lint.scm | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 9 deletions(-) (limited to 'guix/lint.scm') diff --git a/guix/import/hackage.scm b/guix/import/hackage.scm index 35c67cad8d..6ca4f65cb0 100644 --- a/guix/import/hackage.scm +++ b/guix/import/hackage.scm @@ -40,7 +40,8 @@ #:use-module (guix upstream) #:use-module (guix packages) #:use-module ((guix utils) #:select (call-with-temporary-output-file)) - #:export (hackage->guix-package + #:export (%hackage-url + hackage->guix-package hackage-recursive-import %hackage-updater @@ -92,20 +93,23 @@ (define package-name-prefix "ghc-") +(define %hackage-url + (make-parameter "https://hackage.haskell.org")) + (define (hackage-source-url name version) "Given a Hackage package NAME and VERSION, return a url to the source tarball." - (string-append "https://hackage.haskell.org/package/" name - "/" name "-" version ".tar.gz")) + (string-append (%hackage-url) "/package/" + name "/" name "-" version ".tar.gz")) (define* (hackage-cabal-url name #:optional version) "Given a Hackage package NAME and VERSION, return a url to the corresponding .cabal file on Hackage. If VERSION is #f or missing, the url for the latest version is returned." (if version - (string-append "https://hackage.haskell.org/package/" + (string-append (%hackage-url) "/package/" name "-" version "/" name ".cabal") - (string-append "https://hackage.haskell.org/package/" + (string-append (%hackage-url) "/package/" name "/" name ".cabal"))) (define (hackage-name->package-name name) diff --git a/guix/import/stackage.scm b/guix/import/stackage.scm index 93cf214127..77cc6350cb 100644 --- a/guix/import/stackage.scm +++ b/guix/import/stackage.scm @@ -30,7 +30,8 @@ #:use-module (guix memoization) #:use-module (guix packages) #:use-module (guix upstream) - #:export (stackage->guix-package + #:export (%stackage-url + stackage->guix-package stackage-recursive-import %stackage-updater)) @@ -39,7 +40,8 @@ ;;; Stackage info fetcher and access functions ;;; -(define %stackage-url "https://www.stackage.org") +(define %stackage-url + (make-parameter "https://www.stackage.org")) ;; Latest LTS version compatible with GHC 8.6.5. (define %default-lts-version "14.27") @@ -55,7 +57,7 @@ ;; "Retrieve the information about the LTS Stackage release VERSION." (memoize (lambda* (#:optional (version "")) - (let* ((url (string-append %stackage-url + (let* ((url (string-append (%stackage-url) "/lts-" (if (string-null? version) %default-lts-version version))) diff --git a/guix/lint.scm b/guix/lint.scm index 0b38ca0d33..be6bb4eb01 100644 --- a/guix/lint.scm +++ b/guix/lint.scm @@ -10,6 +10,7 @@ ;;; Copyright © 2017, 2018, 2020 Efraim Flashner ;;; Copyright © 2018, 2019 Arun Isaac ;;; Copyright © 2020 Chris Marusich +;;; Copyright © 2020 Timothy Sample ;;; ;;; This file is part of GNU Guix. ;;; @@ -52,6 +53,7 @@ #:use-module ((guix swh) #:hide (origin?)) #:autoload (guix git-download) (git-reference? git-reference-url git-reference-commit) + #:use-module (guix import stackage) #:use-module (ice-9 match) #:use-module (ice-9 regex) #:use-module (ice-9 format) @@ -90,6 +92,7 @@ check-formatting check-archival check-profile-collisions + check-haskell-stackage lint-warning lint-warning? @@ -1285,6 +1288,25 @@ Heritage") '() (apply throw key args)))))))) +(define (check-haskell-stackage package) + "Check whether PACKAGE is a Haskell package ahead of the current +Stackage LTS version." + (match (with-networking-fail-safe + (format #f (G_ "while retrieving upstream info for '~a'") + (package-name package)) + #f + (package-latest-release package (list %stackage-updater))) + ((? upstream-source? source) + (if (version>? (package-version package) + (upstream-source-version source)) + (list + (make-warning package + (G_ "ahead of Stackage LTS version ~a") + (list (upstream-source-version source)) + #:field 'version)) + '())) + (#f '()))) + ;;; ;;; Source code formatting. @@ -1511,7 +1533,11 @@ or a list thereof") (lint-checker (name 'archival) (description "Ensure source code archival on Software Heritage") - (check check-archival)))) + (check check-archival)) + (lint-checker + (name 'haskell-stackage) + (description "Ensure Haskell packages use Stackage LTS versions") + (check check-haskell-stackage)))) (define %all-checkers (append %local-checkers diff --git a/tests/lint.scm b/tests/lint.scm index bd052842f3..9b230814a5 100644 --- a/tests/lint.scm +++ b/tests/lint.scm @@ -7,6 +7,7 @@ ;;; Copyright © 2017 Alex Kost ;;; Copyright © 2017 Efraim Flashner ;;; Copyright © 2018, 2019 Arun Isaac +;;; Copyright © 2020 Timothy Sample ;;; ;;; This file is part of GNU Guix. ;;; @@ -38,6 +39,8 @@ #:use-module (guix swh) #:use-module ((guix gexp) #:select (local-file)) #:use-module ((guix utils) #:select (call-with-temporary-directory)) + #:use-module ((guix import hackage) #:select (%hackage-url)) + #:use-module ((guix import stackage) #:select (%stackage-url)) #:use-module (gnu packages) #:use-module (gnu packages glib) #:use-module (gnu packages pkg-config) @@ -1057,6 +1060,35 @@ (string-contains (single-lint-warning-message warnings) "rate limit reached"))) +(test-skip (if (http-server-can-listen?) 0 1)) +(test-assert "haskell-stackage" + (let* ((stackage (string-append "{ \"packages\": [{" + " \"name\":\"x\"," + " \"version\":\"1.0\" }]}")) + (packages (map (lambda (version) + (dummy-package + (string-append "ghc-x") + (version version) + (source + (dummy-origin + (method url-fetch) + (uri (string-append + "https://hackage.haskell.org/package/" + "x-" version "/x-" version ".tar.gz")))))) + '("0.9" "1.0" "2.0"))) + (warnings (pk (with-http-server `((200 ,stackage) ; memoized + (200 "name: x\nversion: 1.0\n") + (200 "name: x\nversion: 1.0\n") + (200 "name: x\nversion: 1.0\n")) + (parameterize ((%hackage-url (%local-url)) + (%stackage-url (%local-url))) + (append-map check-haskell-stackage packages)))))) + (match warnings + (((? lint-warning? warning)) + (and (string=? (package-version (lint-warning-package warning)) "2.0") + (string-contains (lint-warning-message warning) + "ahead of Stackage LTS version")))))) + (test-end "lint") ;; Local Variables: -- cgit v1.2.3