guix-install.sh: Create /etc/profile.d if it does not exist
[jackhill/guix/guix.git] / guix / gnu-maintenance.scm
CommitLineData
233e7676 1;;; GNU Guix --- Functional package management for GNU
637a2a23 2;;; Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
f9bbf2a8 3;;; Copyright © 2012, 2013 Nikita Karetnikov <nikita@karetnikov.org>
22189ed1 4;;;
233e7676 5;;; This file is part of GNU Guix.
22189ed1 6;;;
233e7676 7;;; GNU Guix is free software; you can redistribute it and/or modify it
22189ed1
NK
8;;; under the terms of the GNU General Public License as published by
9;;; the Free Software Foundation; either version 3 of the License, or (at
10;;; your option) any later version.
11;;;
233e7676 12;;; GNU Guix is distributed in the hope that it will be useful, but
22189ed1
NK
13;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;;; GNU General Public License for more details.
16;;;
17;;; You should have received a copy of the GNU General Public License
233e7676 18;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
22189ed1
NK
19
20(define-module (guix gnu-maintenance)
21 #:use-module (web uri)
22 #:use-module (web client)
23 #:use-module (web response)
5230dce1 24 #:use-module (sxml simple)
22189ed1 25 #:use-module (ice-9 regex)
98fefb21 26 #:use-module (ice-9 match)
22189ed1
NK
27 #:use-module (srfi srfi-1)
28 #:use-module (srfi srfi-11)
29 #:use-module (srfi srfi-26)
100b216d 30 #:use-module (rnrs io ports)
98fefb21 31 #:use-module (system foreign)
3b8258c5 32 #:use-module (guix http-client)
98fefb21 33 #:use-module (guix ftp-client)
0d1e6ce4 34 #:use-module (guix utils)
f9704f17 35 #:use-module (guix memoization)
c0cd1b3e 36 #:use-module (guix records)
0a7c5a09 37 #:use-module (guix upstream)
ef010c0f 38 #:use-module (guix packages)
100b216d 39 #:use-module (guix zlib)
f9bbf2a8
NK
40 #:export (gnu-package-name
41 gnu-package-mundane-name
42 gnu-package-copyright-holder
43 gnu-package-savannah
44 gnu-package-fsd
45 gnu-package-language
46 gnu-package-logo
47 gnu-package-doc-category
48 gnu-package-doc-summary
c4ca9411 49 gnu-package-doc-description
f9bbf2a8
NK
50 gnu-package-doc-urls
51 gnu-package-download-url
52
53 official-gnu-packages
dc794a72 54 find-package
ef010c0f 55 gnu-package?
f9bbf2a8 56
202440e0 57 release-file?
98fefb21
LC
58 releases
59 latest-release
7047133f 60 gnu-release-archive-types
0fdd3bea 61 gnu-package-name->name+version
7047133f 62
e80c0f85 63 %gnu-updater
100b216d 64 %gnu-ftp-updater
2fd370e8
LC
65 %xorg-updater
66 %kernel.org-updater))
98fefb21
LC
67
68;;; Commentary:
69;;;
70;;; Code for dealing with the maintenance of GNU packages, such as
71;;; auto-updates.
72;;;
73;;; Code:
74
75\f
76;;;
77;;; List of GNU packages.
78;;;
22189ed1 79
129f9e11 80(define %gnumaint-base-url
637a2a23 81 "https://web.cvs.savannah.gnu.org/viewvc/*checkout*/www/www/prep/gnumaint/")
129f9e11 82
22189ed1 83(define %package-list-url
1c9e7d65 84 (string->uri
daf76c7c 85 (string-append %gnumaint-base-url "rec/gnupackages.rec")))
22189ed1 86
129f9e11
LC
87(define %package-description-url
88 ;; This file contains package descriptions in recutils format.
daf76c7c
LC
89 ;; See <https://lists.gnu.org/archive/html/guix-devel/2013-10/msg00071.html>
90 ;; and <https://lists.gnu.org/archive/html/guix-devel/2018-06/msg00362.html>.
129f9e11 91 (string->uri
daf76c7c 92 (string-append %gnumaint-base-url "rec/pkgblurbs.rec")))
c4ca9411 93
f9bbf2a8
NK
94(define-record-type* <gnu-package-descriptor>
95 gnu-package-descriptor
96 make-gnu-package-descriptor
97
98 gnu-package-descriptor?
99
100 (name gnu-package-name)
101 (mundane-name gnu-package-mundane-name)
102 (copyright-holder gnu-package-copyright-holder)
103 (savannah gnu-package-savannah)
104 (fsd gnu-package-fsd)
b0efe83a 105 (language gnu-package-language) ; list of strings
f9bbf2a8
NK
106 (logo gnu-package-logo)
107 (doc-category gnu-package-doc-category)
108 (doc-summary gnu-package-doc-summary)
129f9e11 109 (doc-description gnu-package-doc-description) ; taken from 'pkgdescr.txt'
b0efe83a 110 (doc-urls gnu-package-doc-urls) ; list of strings
f9bbf2a8
NK
111 (download-url gnu-package-download-url))
112
9aec35d2
LC
113(define* (official-gnu-packages
114 #:optional (fetch http-fetch/cached))
115 "Return a list of records, which are GNU packages. Use FETCH,
116to fetch the list of GNU packages over HTTP."
c4ca9411 117 (define (read-records port)
f9bbf2a8
NK
118 ;; Return a list of alists. Each alist contains fields of a GNU
119 ;; package.
b0efe83a
LC
120 (let loop ((alist (recutils->alist port))
121 (result '()))
122 (if (null? alist)
c4ca9411 123 (reverse result)
b0efe83a 124 (loop (recutils->alist port)
daf76c7c
LC
125
126 ;; Ignore things like "%rec" (info "(recutils) Record
127 ;; Descriptors").
128 (if (assoc-ref alist "package")
129 (cons alist result)
130 result)))))
f9bbf2a8 131
129f9e11 132 (define official-description
9aec35d2 133 (let ((db (read-records (fetch %package-description-url #:text? #t))))
c4ca9411 134 (lambda (name)
129f9e11 135 ;; Return the description found upstream for package NAME, or #f.
c4ca9411 136 (and=> (find (lambda (alist)
129f9e11
LC
137 (equal? name (assoc-ref alist "package")))
138 db)
4d5f0bae
LC
139 (lambda (record)
140 (let ((field (assoc-ref record "blurb")))
141 ;; The upstream description file uses "redirect PACKAGE" as
142 ;; a blurb in cases where the description of the two
143 ;; packages should be considered the same (e.g., GTK+ has
144 ;; "redirect gnome".) This is usually not acceptable for
145 ;; us because we prefer to have distinct descriptions in
146 ;; such cases. Thus, ignore the 'blurb' field when that
147 ;; happens.
148 (and field
149 (not (string-prefix? "redirect " field))
150 field)))))))
c4ca9411
LC
151
152 (map (lambda (alist)
153 (let ((name (assoc-ref alist "package")))
129f9e11 154 (alist->record `(("description" . ,(official-description name))
c4ca9411
LC
155 ,@alist)
156 make-gnu-package-descriptor
daf76c7c 157 (list "package" "mundane_name" "copyright_holder"
c4ca9411 158 "savannah" "fsd" "language" "logo"
daf76c7c
LC
159 "doc_category" "doc_summary" "description"
160 "doc_url"
161 "download_url")
162 '("doc_url" "language"))))
2134228a
LC
163 (let* ((port (fetch %package-list-url #:text? #t))
164 (lst (read-records port)))
165 (close-port port)
166 lst)))
22189ed1 167
dc794a72
LC
168(define (find-package name)
169 "Find GNU package called NAME and return it. Return #f if it was not
170found."
171 (find (lambda (package)
172 (string=? name (gnu-package-name package)))
173 (official-gnu-packages)))
ef010c0f
LC
174
175(define gnu-package?
55b2d921 176 (let ((official-gnu-packages (memoize official-gnu-packages)))
3d520b54 177 (mlambdaq (package)
55b2d921 178 "Return true if PACKAGE is a GNU package. This procedure may access the
ef010c0f 179network to check in GNU's database."
55b2d921
LC
180 (define (mirror-type url)
181 (let ((uri (string->uri url)))
182 (and (eq? (uri-scheme uri) 'mirror)
183 (cond
184 ((member (uri-host uri)
185 '("gnu" "gnupg" "gcc" "gnome"))
186 ;; Definitely GNU.
187 'gnu)
188 ((equal? (uri-host uri) "cran")
189 ;; Possibly GNU: mirror://cran could be either GNU R itself
190 ;; or a non-GNU package.
191 #f)
192 (else
193 ;; Definitely non-GNU.
194 'non-gnu)))))
195
196 (define (gnu-home-page? package)
197 (letrec-syntax ((>> (syntax-rules ()
198 ((_ value proc)
199 (and=> value proc))
200 ((_ value proc rest ...)
201 (and=> value
202 (lambda (next)
203 (>> (proc next) rest ...)))))))
204 (>> package package-home-page
205 string->uri uri-host
206 (lambda (host)
207 (member host '("www.gnu.org" "gnu.org"))))))
208
209 (or (gnu-home-page? package)
210 (let ((url (and=> (package-source package) origin-uri))
211 (name (package-upstream-name package)))
212 (case (and (string? url) (mirror-type url))
213 ((gnu) #t)
214 ((non-gnu) #f)
215 (else
216 (and (member name (map gnu-package-name (official-gnu-packages)))
217 #t))))))))
ef010c0f 218
98fefb21
LC
219\f
220;;;
5230dce1 221;;; Latest FTP release.
98fefb21
LC
222;;;
223
63e8bb12
LC
224(define (ftp-server/directory package)
225 "Return the FTP server and directory where PACKAGE's tarball are stored."
3b0fcc67 226 (let ((name (package-upstream-name package)))
b03218d5
LC
227 (values (or (assoc-ref (package-properties package) 'ftp-server)
228 "ftp.gnu.org")
229 (or (assoc-ref (package-properties package) 'ftp-directory)
230 (string-append "/gnu/" name)))))
98fefb21 231
d55a99fe 232(define %tarball-rx
f00dccf4
LC
233 ;; The .zip extensions is notably used for freefont-ttf.
234 ;; The "-src" pattern is for "TeXmacs-1.0.7.9-src.tar.gz".
235 ;; The "-gnu[0-9]" pattern is for "icecat-38.4.0-gnu1.tar.bz2".
236 (make-regexp "^([^.]+)-([0-9]|[^-])+(-(src|gnu[0-9]))?\\.(tar\\.|zip$)"))
d55a99fe
LC
237
238(define %alpha-tarball-rx
239 (make-regexp "^.*-.*[0-9](-|~)?(alpha|beta|rc|cvs|svn|git)-?[0-9\\.]*\\.tar\\."))
240
501d7647 241(define (release-file? project file)
cac137aa 242 "Return #f if FILE is not a release tarball of PROJECT, otherwise return
501d7647 243true."
bc1ff4aa 244 (and (not (member (file-extension file) '("sig" "sign" "asc")))
d55a99fe
LC
245 (and=> (regexp-exec %tarball-rx file)
246 (lambda (match)
247 ;; Filter out unrelated files, like `guile-www-1.1.1'.
fa04a04f 248 ;; Case-insensitive for things like "TeXmacs" vs. "texmacs".
444bb0d8 249 ;; The "-src" suffix is for "freefont-src-20120503.tar.gz".
fa04a04f
LC
250 (and=> (match:substring match 1)
251 (lambda (name)
444bb0d8
LC
252 (or (string-ci=? name project)
253 (string-ci=? name
254 (string-append project
255 "-src")))))))
cac137aa 256 (not (regexp-exec %alpha-tarball-rx file))
da1027a7 257 (let ((s (tarball-sans-extension file)))
501d7647
LC
258 (regexp-exec %package-name-rx s))))
259
260(define (tarball->version tarball)
261 "Return the version TARBALL corresponds to. TARBALL is a file name like
262\"coreutils-8.23.tar.xz\"."
263 (let-values (((name version)
da1027a7
HG
264 (gnu-package-name->name+version
265 (tarball-sans-extension tarball))))
501d7647
LC
266 version))
267
63e8bb12
LC
268(define* (releases project
269 #:key
270 (server "ftp.gnu.org")
271 (directory (string-append "/gnu/" project)))
272 "Return the list of <upstream-release> of PROJECT as a list of release
273name/directory pairs."
cac137aa 274 ;; TODO: Parse something like fencepost.gnu.org:/gd/gnuorg/packages-ftp.
63e8bb12
LC
275 (define conn (ftp-open server))
276
277 (let loop ((directories (list directory))
278 (result '()))
279 (match directories
280 (()
281 (ftp-close conn)
282 (coalesce-sources result))
283 ((directory rest ...)
284 (let* ((files (ftp-list conn directory))
285 (subdirs (filter-map (match-lambda
286 ((name 'directory . _) name)
287 (_ #f))
288 files)))
289 (define (file->url file)
290 (string-append "ftp://" server directory "/" file))
291
292 (define (file->source file)
293 (let ((url (file->url file)))
294 (upstream-source
295 (package project)
296 (version (tarball->version file))
297 (urls (list url))
298 (signature-urls (list (string-append url ".sig"))))))
299
300 (loop (append (map (cut string-append directory "/" <>)
301 subdirs)
302 rest)
303 (append
304 ;; Filter out signatures, deltas, and files which
305 ;; are potentially not releases of PROJECT--e.g.,
306 ;; in /gnu/guile, filter out guile-oops and
307 ;; guile-www; in mit-scheme, filter out binaries.
308 (filter-map (match-lambda
309 ((file 'file . _)
310 (and (release-file? project file)
311 (file->source file)))
312 (_ #f))
313 files)
314 result)))))))
98fefb21 315
e946f2ec
LC
316(define* (latest-ftp-release project
317 #:key
318 (server "ftp.gnu.org")
319 (directory (string-append "/gnu/" project))
c4991257 320 (keep-file? (const #t))
6efa6f76 321 (file->signature (cut string-append <> ".sig"))
e946f2ec
LC
322 (ftp-open ftp-open) (ftp-close ftp-close))
323 "Return an <upstream-source> for the latest release of PROJECT on SERVER
324under DIRECTORY, or #f. Use FTP-OPEN and FTP-CLOSE to open (resp. close) FTP
c4991257
LC
325connections; this can be useful to reuse connections.
326
873d0ff2
LC
327KEEP-FILE? is a predicate to decide whether to enter a directory and to
328consider a given file (source tarball) as a valid candidate based on its name.
c4991257
LC
329
330FILE->SIGNATURE must be a procedure; it is passed a source file URL and must
331return the corresponding signature URL, or #f it signatures are unavailable."
cac137aa
LC
332 (define (latest a b)
333 (if (version>? a b) a b))
334
501d7647 335 (define (latest-release a b)
0a7c5a09 336 (if (version>? (upstream-source-version a) (upstream-source-version b))
501d7647
LC
337 a b))
338
a74da6b0
LC
339 (define patch-directory-name?
340 ;; Return #t for patch directory names such as 'bash-4.2-patches'.
341 (cut string-suffix? "patches" <>))
342
e946f2ec
LC
343 (define conn (ftp-open server))
344
345 (define (file->url directory file)
346 (string-append "ftp://" server directory "/" file))
347
348 (define (file->source directory file)
349 (let ((url (file->url directory file)))
350 (upstream-source
351 (package project)
352 (version (tarball->version file))
353 (urls (list url))
6efa6f76
LC
354 (signature-urls (match (file->signature url)
355 (#f #f)
356 (sig (list sig)))))))
e946f2ec
LC
357
358 (let loop ((directory directory)
359 (result #f))
360 (let* ((entries (ftp-list conn directory))
361
026f6a42 362 ;; Filter out things like /gnupg/patches. Filter out "w32"
e946f2ec
LC
363 ;; directories as found on ftp.gnutls.org.
364 (subdirs (filter-map (match-lambda
365 (((? patch-directory-name? dir)
366 'directory . _)
367 #f)
368 (("w32" 'directory . _)
369 #f)
58d9e71b
LC
370 (("unstable" 'directory . _)
371 ;; As seen at ftp.gnupg.org/gcrypt/pinentry.
372 #f)
026f6a42
LC
373 ((directory 'directory . _)
374 directory)
e946f2ec
LC
375 (_ #f))
376 entries))
377
378 ;; Whether or not SUBDIRS is empty, compute the latest releases
379 ;; for the current directory. This is necessary for packages
380 ;; such as 'sharutils' that have a sub-directory that contains
381 ;; only an older release.
382 (releases (filter-map (match-lambda
383 ((file 'file . _)
384 (and (release-file? project file)
c4991257 385 (keep-file? file)
e946f2ec
LC
386 (file->source directory file)))
387 (_ #f))
388 entries)))
389
390 ;; Assume that SUBDIRS correspond to versions, and jump into the
391 ;; one with the highest version number.
392 (let* ((release (reduce latest-release #f
393 (coalesce-sources releases)))
394 (result (if (and result release)
395 (latest-release release result)
396 (or release result)))
397 (target (reduce latest #f subdirs)))
398 (if target
399 (loop (string-append directory "/" target)
400 result)
401 (begin
402 (ftp-close conn)
403 result))))))
404
63e8bb12
LC
405(define* (latest-release package
406 #:key
407 (server "ftp.gnu.org")
408 (directory (string-append "/gnu/" package)))
e946f2ec 409 "Return the <upstream-source> for the latest version of PACKAGE or #f.
63e8bb12
LC
410PACKAGE must be the canonical name of a GNU package."
411 (latest-ftp-release package
412 #:server server
413 #:directory directory))
98fefb21 414
e80c0f85
LC
415(define-syntax-rule (false-if-ftp-error exp)
416 "Return #f if an FTP error is raise while evaluating EXP; return the result
417of EXP otherwise."
0a7c5a09
LC
418 (catch 'ftp-error
419 (lambda ()
e80c0f85 420 exp)
0a7c5a09
LC
421 (lambda (key port . rest)
422 (if (ftp-connection? port)
423 (ftp-close port)
424 (close-port port))
425 #f)))
7047133f 426
e80c0f85 427(define (latest-release* package)
63e8bb12
LC
428 "Like 'latest-release', but (1) take a <package> object, and (2) ignore FTP
429errors that might occur when PACKAGE is not actually a GNU package, or not
430hosted on ftp.gnu.org, or not under that name (this is the case for
431\"emacs-auctex\", for instance.)"
432 (let-values (((server directory)
433 (ftp-server/directory package)))
3b0fcc67
LC
434 (false-if-ftp-error (latest-release (package-upstream-name package)
435 #:server server
436 #:directory directory))))
e80c0f85 437
5230dce1
LC
438\f
439;;;
440;;; Latest HTTP release.
441;;;
442
443(define (html->sxml port)
444 "Read HTML from PORT and return the corresponding SXML tree."
445 (let ((str (get-string-all port)))
446 (catch #t
447 (lambda ()
448 ;; XXX: This is the poor developer's HTML-to-XML converter. It's good
449 ;; enough for directory listings at <https://kernel.org/pub> but if
450 ;; needed we could resort to (htmlprag) from Guile-Lib.
451 (call-with-input-string (string-replace-substring str "<hr>" "<hr />")
452 xml->sxml))
453 (const '(html))))) ;parse error
454
455(define (html-links sxml)
456 "Return the list of links found in SXML, the SXML tree of an HTML page."
457 (let loop ((sxml sxml)
458 (links '()))
459 (match sxml
460 (('a ('@ attributes ...) body ...)
461 (match (assq 'href attributes)
462 (#f (fold loop links body))
463 (('href url) (fold loop (cons url links) body))))
464 ((tag ('@ _ ...) body ...)
465 (fold loop links body))
466 ((tag body ...)
467 (fold loop links body))
468 (_
469 links))))
470
471(define* (latest-html-release package
472 #:key
473 (base-url "https://kernel.org/pub")
474 (directory (string-append "/" package))
475 (file->signature (cut string-append <> ".sig")))
476 "Return an <upstream-source> for the latest release of PACKAGE (a string) on
477SERVER under DIRECTORY, or #f. BASE-URL should be the URL of an HTML page,
478typically a directory listing as found on 'https://kernel.org/pub'.
479
480FILE->SIGNATURE must be a procedure; it is passed a source file URL and must
481return the corresponding signature URL, or #f it signatures are unavailable."
482 (let* ((uri (string->uri (string-append base-url directory "/")))
483 (port (http-fetch/cached uri #:ttl 3600))
484 (sxml (html->sxml port)))
485 (define (url->release url)
486 (and (string=? url (basename url)) ;relative reference?
487 (release-file? package url)
488 (let-values (((name version)
da1027a7
HG
489 (package-name->name+version
490 (tarball-sans-extension url)
491 #\-)))
5230dce1
LC
492 (upstream-source
493 (package name)
494 (version version)
495 (urls (list (string-append base-url directory "/" url)))
496 (signature-urls
497 (list (string-append base-url directory "/"
498 (file-sans-extension url)
499 ".sign")))))))
500
501 (define candidates
502 (filter-map url->release (html-links sxml)))
503
504 (close-port port)
505 (match candidates
506 (() #f)
507 ((first . _)
508 ;; Select the most recent release and return it.
509 (reduce (lambda (r1 r2)
510 (if (version>? (upstream-source-version r1)
511 (upstream-source-version r2))
512 r1 r2))
513 first
514 (coalesce-sources candidates))))))
515
516\f
517;;;
518;;; Updaters.
519;;;
520
100b216d
LC
521(define %gnu-file-list-uri
522 ;; URI of the file list for ftp.gnu.org.
523 (string->uri "https://ftp.gnu.org/find.txt.gz"))
524
525(define ftp.gnu.org-files
526 (mlambda ()
527 "Return the list of files available at ftp.gnu.org."
528
529 ;; XXX: Memoize the whole procedure to work around the fact that
530 ;; 'http-fetch/cached' caches the gzipped version.
531
532 (define (trim-leading-components str)
533 ;; Trim the leading ".", if any, in "./gnu/foo".
534 (string-trim str (char-set #\.)))
535
536 (define (string->lines str)
537 (string-tokenize str (char-set-complement (char-set #\newline))))
538
3ce1b902
LC
539 ;; Since https://ftp.gnu.org honors 'If-Modified-Since', the hard-coded
540 ;; TTL can be relatively short.
541 (let ((port (http-fetch/cached %gnu-file-list-uri #:ttl (* 15 60))))
100b216d
LC
542 (map trim-leading-components
543 (call-with-gzip-input-port port
544 (compose string->lines get-string-all))))))
545
546(define (latest-gnu-release package)
547 "Return the latest release of PACKAGE, a GNU package available via
548ftp.gnu.org.
549
550This method does not rely on FTP access at all; instead, it browses the file
551list available from %GNU-FILE-LIST-URI over HTTP(S)."
552 (let-values (((server directory)
553 (ftp-server/directory package))
554 ((name)
555 (package-upstream-name package)))
556 (let* ((files (ftp.gnu.org-files))
557 (relevant (filter (lambda (file)
1b3ebae4
LC
558 (and (string-prefix? "/gnu" file)
559 (string-contains file directory)
e9f38113 560 (release-file? name (basename file))))
100b216d
LC
561 files)))
562 (match (sort relevant (lambda (file1 file2)
da1027a7
HG
563 (version>? (tarball-sans-extension
564 (basename file1))
565 (tarball-sans-extension
566 (basename file2)))))
1b3ebae4
LC
567 ((and tarballs (reference _ ...))
568 (let* ((version (tarball->version reference))
569 (tarballs (filter (lambda (file)
da1027a7 570 (string=? (tarball-sans-extension
1b3ebae4 571 (basename file))
da1027a7 572 (tarball-sans-extension
1b3ebae4
LC
573 (basename reference))))
574 tarballs)))
575 (upstream-source
576 (package name)
577 (version version)
578 (urls (map (lambda (file)
579 (string-append "mirror://gnu/"
580 (string-drop file
581 (string-length "/gnu/"))))
582 tarballs))
583 (signature-urls (map (cut string-append <> ".sig") urls)))))
100b216d
LC
584 (()
585 #f)))))
586
98fefb21
LC
587(define %package-name-rx
588 ;; Regexp for a package name, e.g., "foo-X.Y". Since TeXmacs uses
589 ;; "TeXmacs-X.Y-src", the `-src' suffix is allowed.
590 (make-regexp "^(.*)-(([0-9]|\\.)+)(-src)?"))
591
592(define (gnu-package-name->name+version name+version)
593 "Return the package name and version number extracted from NAME+VERSION."
594 (let ((match (regexp-exec %package-name-rx name+version)))
595 (if (not match)
596 (values name+version #f)
597 (values (match:substring match 1) (match:substring match 2)))))
598
c1d8b3b3
LC
599(define gnome-package?
600 (url-prefix-predicate "mirror://gnome/"))
601
e80c0f85
LC
602(define (pure-gnu-package? package)
603 "Return true if PACKAGE is a non-Emacs and non-GNOME GNU package. This
604excludes AucTeX, for instance, whose releases are now uploaded to
2e2cf9a3
LC
605elpa.gnu.org, and all the GNOME packages; EMMS is included though, because its
606releases are on gnu.org."
607 (and (or (not (string-prefix? "emacs-" (package-name package)))
608 (gnu-hosted? package))
e80c0f85 609 (not (gnome-package? package))
0a7c5a09 610 (gnu-package? package)))
0fdd3bea 611
2e2cf9a3
LC
612(define gnu-hosted?
613 (url-prefix-predicate "mirror://gnu/"))
614
62061d6b
AW
615(define (latest-xorg-release package)
616 "Return the latest release of PACKAGE, the name of an X.org package."
7d27a025 617 (let ((uri (string->uri (origin-uri (package-source package)))))
62061d6b
AW
618 (false-if-ftp-error
619 (latest-ftp-release
7d27a025 620 (package-name package)
62061d6b
AW
621 #:server "ftp.freedesktop.org"
622 #:directory
623 (string-append "/pub/xorg/" (dirname (uri-path uri)))))))
624
2fd370e8
LC
625(define (latest-kernel.org-release package)
626 "Return the latest release of PACKAGE, the name of a kernel.org package."
5230dce1
LC
627 (define %kernel.org-base
628 ;; This URL and sub-directories thereof are nginx-generated directory
629 ;; listings suitable for 'latest-html-release'.
630 "https://mirrors.edge.kernel.org/pub")
631
632 (define (file->signature file)
633 (string-append (file-sans-extension file) ".sign"))
634
635 (let* ((uri (string->uri (origin-uri (package-source package))))
636 (package (package-upstream-name package))
637 (directory (dirname (uri-path uri))))
638 (latest-html-release package
639 #:base-url %kernel.org-base
640 #:directory directory
641 #:file->signature file->signature)))
2fd370e8 642
0a7c5a09 643(define %gnu-updater
100b216d 644 ;; This is for everything at ftp.gnu.org.
7e6b490d
AK
645 (upstream-updater
646 (name 'gnu)
647 (description "Updater for GNU packages")
100b216d
LC
648 (pred gnu-hosted?)
649 (latest latest-gnu-release)))
650
651(define %gnu-ftp-updater
652 ;; This is for GNU packages taken from alternate locations, such as
653 ;; alpha.gnu.org, ftp.gnupg.org, etc. It is obsolescent.
654 (upstream-updater
655 (name 'gnu-ftp)
656 (description "Updater for GNU packages only available via FTP")
657 (pred (lambda (package)
658 (and (not (gnu-hosted? package))
659 (pure-gnu-package? package))))
7e6b490d 660 (latest latest-release*)))
0fdd3bea 661
62061d6b
AW
662(define %xorg-updater
663 (upstream-updater
664 (name 'xorg)
665 (description "Updater for X.org packages")
7632f7bc 666 (pred (url-prefix-predicate "mirror://xorg/"))
62061d6b
AW
667 (latest latest-xorg-release)))
668
2fd370e8
LC
669(define %kernel.org-updater
670 (upstream-updater
671 (name 'kernel.org)
672 (description "Updater for packages hosted on kernel.org")
673 (pred (url-prefix-predicate "mirror://kernel.org/"))
674 (latest latest-kernel.org-release)))
675
98fefb21 676;;; gnu-maintenance.scm ends here