summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/guix.texi26
-rw-r--r--guix/scripts/lint.scm55
-rw-r--r--tests/guix-lint.sh20
3 files changed, 90 insertions, 11 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 209becd722a..30c91d0df9d 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -124,7 +124,7 @@ Copyright @copyright{} 2023 Thomas Ieong@*
124Copyright @copyright{} 2023 Saku Laesvuori@* 124Copyright @copyright{} 2023 Saku Laesvuori@*
125Copyright @copyright{} 2023 Graham James Addis@* 125Copyright @copyright{} 2023 Graham James Addis@*
126Copyright @copyright{} 2023-2025 Tomas Volf@* 126Copyright @copyright{} 2023-2025 Tomas Volf@*
127Copyright @copyright{} 2024, 2025 Herman Rimm@* 127Copyright @copyright{} 2024-2026 Herman Rimm@*
128Copyright @copyright{} 2024 Matthew Trzcinski@* 128Copyright @copyright{} 2024 Matthew Trzcinski@*
129Copyright @copyright{} 2024 Richard Sent@* 129Copyright @copyright{} 2024 Richard Sent@*
130Copyright @copyright{} 2024 Dariqq@* 130Copyright @copyright{} 2024 Dariqq@*
@@ -16710,6 +16710,12 @@ guix lint @var{options} @var{package}@dots{}
16710@end example 16710@end example
16711 16711
16712If no package is given on the command line, then all packages are checked. 16712If no package is given on the command line, then all packages are checked.
16713To check packages in particular source files, the syntax is:
16714
16715@example
16716guix lint @var{options} --whole-file @var{file}@dots{}
16717@end example
16718
16713The @var{options} may be zero or more of the following: 16719The @var{options} may be zero or more of the following:
16714 16720
16715@table @code 16721@table @code
@@ -16747,9 +16753,23 @@ Only enable the checkers that do not depend on Internet access.
16747Add @var{directory} to the front of the package module search path 16753Add @var{directory} to the front of the package module search path
16748(@pxref{Package Modules}). 16754(@pxref{Package Modules}).
16749 16755
16750This allows users to define their own packages and make them visible to 16756@item --whole-file
16751the command-line tools. 16757@itemx -f
16758Check the top-level package definitions in the given files; subsequent
16759arguments are treated as file names rather than package names. This
16760option also enables a special checker which checks if a package
16761alphabetically succeeds the one above it.
16762
16763For example, to check if the packages in @file{gnu/packages/matrix.scm}
16764are sorted alphabetically, and if the package names therein follow
16765established conventions, run:
16766
16767@example
16768guix lint -c name -f gnu/packages/matrix.scm
16769@end example
16752 16770
16771The previous two options allow users to define their own packages and
16772make them visible to the command-line tools.
16753@end table 16773@end table
16754 16774
16755@node Invoking guix size 16775@node Invoking guix size
diff --git a/guix/scripts/lint.scm b/guix/scripts/lint.scm
index ee3de51fb1a..6a317bf64d5 100644
--- a/guix/scripts/lint.scm
+++ b/guix/scripts/lint.scm
@@ -11,6 +11,7 @@
11;;; Copyright © 2018, 2019 Arun Isaac <arunisaac@systemreboot.net> 11;;; Copyright © 2018, 2019 Arun Isaac <arunisaac@systemreboot.net>
12;;; Copyright © 2019, 2020 Simon Tournier <zimon.toutoune@gmail.com> 12;;; Copyright © 2019, 2020 Simon Tournier <zimon.toutoune@gmail.com>
13;;; Copyright © 2020 Brice Waegeneire <brice@waegenei.re> 13;;; Copyright © 2020 Brice Waegeneire <brice@waegenei.re>
14;;; Copyright © 2024, 2026 Herman Rimm <herman@rimm.ee>
14;;; 15;;;
15;;; This file is part of GNU Guix. 16;;; This file is part of GNU Guix.
16;;; 17;;;
@@ -28,8 +29,10 @@
28;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. 29;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
29 30
30(define-module (guix scripts lint) 31(define-module (guix scripts lint)
32 #:use-module (guix diagnostics)
31 #:use-module (guix packages) 33 #:use-module (guix packages)
32 #:use-module (guix lint) 34 #:use-module (guix lint)
35 #:use-module (guix modules)
33 #:use-module (guix ui) 36 #:use-module (guix ui)
34 #:use-module (guix store) 37 #:use-module (guix store)
35 #:use-module (guix scripts) 38 #:use-module (guix scripts)
@@ -87,6 +90,28 @@
87 checkers) 90 checkers)
88 (exit 0)) 91 (exit 0))
89 92
93(define* (process-whole-file file checkers #:key store)
94 "Run the given CHECKERS on packages in FILE and check that the
95packages are sorted alphabetically."
96 (load* file '())
97 (let* ((module (resolve-interface (file-name->module-name file)))
98 (packages (sort (fold-packages cons '() (list module))
99 package-location<?)))
100 (fold (lambda (package previous)
101 (let ((line (location-line (package-location package)))
102 (name (package-name package)))
103 (run-checkers package checkers #:store store)
104 (and (string<? name previous)
105 (emit-warnings
106 (list (lint-warning
107 (package package)
108 (location (location file line 0))
109 (message-text
110 (G_ "breaks from alphabetical order"))
111 (message-data '())))))
112 name))
113 "" packages)))
114
90 115
91;;; 116;;;
92;;; Command-line options. 117;;; Command-line options.
@@ -115,6 +140,9 @@ run the checkers on all packages.\n"))
115 -L, --load-path=DIR prepend DIR to the package module search path")) 140 -L, --load-path=DIR prepend DIR to the package module search path"))
116 (newline) 141 (newline)
117 (display (G_ " 142 (display (G_ "
143 -f, --whole-file check the packages defined in the given file(s)"))
144 (newline)
145 (display (G_ "
118 -h, --help display this help and exit")) 146 -h, --help display this help and exit"))
119 (display (G_ " 147 (display (G_ "
120 -l, --list-checkers display the list of available lint checkers")) 148 -l, --list-checkers display the list of available lint checkers"))
@@ -161,6 +189,9 @@ run the checkers on all packages.\n"))
161 (lambda args 189 (lambda args
162 (leave-on-EPIPE (show-help)) 190 (leave-on-EPIPE (show-help))
163 (exit 0))) 191 (exit 0)))
192 (option '(#\f "whole-file") #f #f
193 (lambda (opt name arg result)
194 (alist-cons 'whole-file? #t result)))
164 (option '(#\l "list-checkers") #f #f 195 (option '(#\l "list-checkers") #f #f
165 (lambda (opt name arg result) 196 (lambda (opt name arg result)
166 (alist-cons 'list? #t result))) 197 (alist-cons 'list? #t result)))
@@ -187,12 +218,17 @@ run the checkers on all packages.\n"))
187 #:build-options? #f)) 218 #:build-options? #f))
188 219
189 (let* ((opts (parse-options)) 220 (let* ((opts (parse-options))
190 (args (filter-map (match-lambda 221 (whole-file? (assoc-ref opts 'whole-file?))
191 (('argument . spec) 222 (args (filter-map (if whole-file?
192 (specification->package spec)) 223 (match-lambda
193 (('expression . exp) 224 (('argument . file) file)
194 (read/eval-package-expression exp)) 225 (_ #f))
195 (_ #f)) 226 (match-lambda
227 (('argument . spec)
228 (specification->package spec))
229 (('expression . exp)
230 (read/eval-package-expression exp))
231 (_ #f)))
196 (reverse opts))) 232 (reverse opts)))
197 (no-checkers (or (assoc-ref opts 'exclude) '())) 233 (no-checkers (or (assoc-ref opts 'exclude) '()))
198 (the-checkers (filter (lambda (checker) 234 (the-checkers (filter (lambda (checker)
@@ -221,6 +257,13 @@ run the checkers on all packages.\n"))
221 (call-maybe-with-store 257 (call-maybe-with-store
222 (lambda (store) 258 (lambda (store)
223 (cond 259 (cond
260 (whole-file?
261 (when (null? args)
262 (warning (G_ "no files specified, nothing to do~%")))
263 (for-each
264 (lambda (file)
265 (process-whole-file file checkers #:store store))
266 args))
224 ((null? args) 267 ((null? args)
225 (fold-packages (lambda (p r) (run-checkers p checkers 268 (fold-packages (lambda (p r) (run-checkers p checkers
226 #:store store)) '())) 269 #:store store)) '()))
diff --git a/tests/guix-lint.sh b/tests/guix-lint.sh
index 97c2ea83fef..4a77315b3a2 100644
--- a/tests/guix-lint.sh
+++ b/tests/guix-lint.sh
@@ -1,5 +1,6 @@
1# GNU Guix --- Functional package management for GNU 1# GNU Guix --- Functional package management for GNU
2# Copyright © 2014 Cyril Roelandt <tipecaml@gmail.com> 2# Copyright © 2014 Cyril Roelandt <tipecaml@gmail.com>
3# Copyright © 2026 Herman Rimm <herman@rimm.ee>
3# 4#
4# This file is part of GNU Guix. 5# This file is part of GNU Guix.
5# 6#
@@ -35,12 +36,20 @@ cat > "$module_dir/foo.scm"<<EOF
35 #:use-module (guix packages) 36 #:use-module (guix packages)
36 #:use-module (gnu packages base)) 37 #:use-module (gnu packages base))
37 38
39;; This definition uses (the line number of) the hello package location
40;; instead of generating a new one.
41(define-public hi hello)
42
38(define-public dummy 43(define-public dummy
39 (package (inherit hello) 44 (package (inherit hello)
40 (name "dummy") 45 (name "dummy")
41 (version "42") 46 (version "42")
42 (synopsis "dummy package") 47 (synopsis "dummy package")
43 (description "dummy package. Only used for testing purposes."))) 48 (description "dummy package. Only used for testing purposes.")))
49
50(define-public bar
51 (package (inherit dummy)
52 (name "bar")))
44EOF 53EOF
45 54
46GUIX_PACKAGE_PATH="$module_dir" 55GUIX_PACKAGE_PATH="$module_dir"
@@ -52,10 +61,11 @@ grep_warning ()
52 echo $res 61 echo $res
53} 62}
54 63
55# Three issues with the dummy package: 64# Issues with the dummy package:
56# 1) the synopsis starts with the package name; 65# 1) the synopsis starts with the package name;
57# 2) the synopsis starts with a lower-case letter; 66# 2) the synopsis starts with a lower-case letter;
58# 3) the description has a single space following the end-of-sentence period. 67# 3) the description has a single space following the end-of-sentence period;
68# 4) the alphabetically lesser bar package succeeds it.
59 69
60out=`guix lint -c synopsis,description dummy 2>&1` 70out=`guix lint -c synopsis,description dummy 2>&1`
61test `grep_warning "$out"` -eq 3 71test `grep_warning "$out"` -eq 3
@@ -69,6 +79,12 @@ test `grep_warning "$out"` -eq 1
69out=`guix lint -c description,synopsis dummy 2>&1` 79out=`guix lint -c description,synopsis dummy 2>&1`
70test `grep_warning "$out"` -eq 3 80test `grep_warning "$out"` -eq 3
71 81
82working_dir="$(pwd)"
83cd "$module_dir"
84out=`guix lint -c name -f foo.scm 2>&1`
85cd "$working_dir"
86test `echo "$out" | grep -E -c "breaks from alphabetical order"` -eq 1
87
72guix lint -c synopsis,invalid-checker dummy 2>&1 | \ 88guix lint -c synopsis,invalid-checker dummy 2>&1 | \
73 grep -q 'invalid-checker: invalid checker' 89 grep -q 'invalid-checker: invalid checker'
74 90