~ruther/guix-local

1ce270fb85be517c32c0369df6293ca73b26ebac — Ludovic Courtès 11 months ago 830562e
gnu-maintenance: ‘generic-html’ recognizes ‘release-file-regexp’ property.

* guix/gnu-maintenance.scm (package-release-file?): New procedure.
(tarball->version): Add optional parameter and honor it.
(import-html-release): Use ‘package-release-file?’ and pass second argument to
‘tarball->version’.
* tests/gnu-maintenance.scm ("latest-html-release, 'release-file-regexp' property")
("latest-html-release, invalid 'release-file-regexp' property"): New tests.
* doc/guix.texi (Invoking guix refresh): Document it.

Change-Id: Ia9328418fdd2faf118e4ec9d5fbde4a279e100ed
Reviewed-by: Maxim Cournoyer <maxim@guixotic.coop>
3 files changed, 121 insertions(+), 12 deletions(-)

M doc/guix.texi
M guix/gnu-maintenance.scm
M tests/gnu-maintenance.scm
M doc/guix.texi => doc/guix.texi +27 -3
@@ 15530,10 15530,34 @@ the updater for @uref{https://www.stackage.org, Stackage} packages.
the updater for @uref{https://crates.io, Crates} packages.
@item launchpad
the updater for @uref{https://launchpad.net, Launchpad} packages.

@item generic-html
a generic updater that crawls the HTML page where the source tarball of
the package is hosted, when applicable, or the HTML page specified by
the @code{release-monitoring-url} property of the package.
a generic updater that crawls, by default, the HTML page where the
source tarball of the package is hosted, when applicable.  Behavior can
be customized with the following package properties:

@table @code
@item release-monitoring-url
an alternate URL to crawl;

@item release-file-regexp
an regular expression matching release file names, whose first
subexpression must correspond to the version string.
@end table

Here is an example package with a custom release monitoring URL and a
regexp matching an unconventional release file name (it's unconventional
due to the use of upper case letter and the lack of a hyphen before the
version string):

@lisp
(package
  ;; @dots{}
  (home-page "http://example.org/software/the-package.html")
  (properties
    `((release-monitoring-url . ,home-page)
      (release-file-regexp . "ThePackage([0-9\\.]+)\\.tgz"))))
@end lisp

@item generic-git
a generic updater for packages hosted on Git repositories.  It tries to

M guix/gnu-maintenance.scm => guix/gnu-maintenance.scm +38 -7
@@ 288,13 288,41 @@ network to check in GNU's database."
       (let ((s (tarball-sans-extension file)))
         (regexp-exec %package-name-rx s))))

(define (tarball->version tarball)
(define (package-release-file? package file)
  "Return true if FILE, a string like \"NPB2.3.tar.gz\", denotes a release
file for PACKAGE."
  (match (assoc-ref (package-properties package) 'release-file-regexp)
    (#f
     (release-file? (package-upstream-name package) file))
    (str
     (catch #t
       (lambda ()
         (string-match str file))
       (lambda _
         (warning (package-field-location package 'properties)
                  (G_ "~a: invalid 'release-file-regexp' property~%")
                  (package-full-name package))
         #f)))))

(define* (tarball->version tarball #:optional regexp)
  "Return the version TARBALL corresponds to.  TARBALL is a file name like
\"coreutils-8.23.tar.xz\"."
  (let-values (((name version)
                (gnu-package-name->name+version
                 (tarball-sans-extension tarball))))
    version))
  (if regexp
      (let ((match (string-match regexp tarball)))
        (if (= 2 (match:count match))
            (match:substring match 1)
            (begin
              (warning (N_ "release file regexp ~s has ~a subexpression\
 (expected one for the version string)~%"
                           "release file regexp ~s has ~a subexpressions\
 (expected one for the version string)~%"
                           (- (match:count match) 1))
                       regexp (- (match:count match) 1))
              #f)))
      (let-values (((name version)
                    (gnu-package-name->name+version
                     (tarball-sans-extension tarball))))
        version)))

(define* (releases project
                   #:key


@@ 705,8 733,11 @@ also updated to the latest version, as explained in the doc of the
      "Return an <upstream-source> object if a release file was found at URL,
else #f.  URL is assumed to fully specified."
      (let ((base (basename url)))
        (and (release-file? name base)
             (let ((version (tarball->version base)))
        (and (package-release-file? package base)
             (let ((version (tarball->version
                             base
                             (assoc-ref (package-properties package)
                                        'release-file-regexp))))
               (upstream-source
                (package name)
                (version version)

M tests/gnu-maintenance.scm => tests/gnu-maintenance.scm +56 -2
@@ 1,5 1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2015, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2015, 2021, 2025 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2022 Maxime Devos <maximedevos@telenet.be>
;;; Copyright © 2023-2024 Maxim Cournoyer <maxim@guixotic.coop>
;;;


@@ 27,7 27,7 @@
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-64)
  #:use-module ((web client) #:select (current-http-proxy))
  #:use-module ((web uri) #:select (uri? uri->string))
  #:use-module ((web uri) #:select (uri? uri->string string->uri uri-path))
  #:use-module (ice-9 match))

(test-begin "gnu-maintenance")


@@ 91,6 91,60 @@
           (equal? (upstream-source-version update) "2")
           (equal? (list expected-new-url) (upstream-source-urls update))))))

(test-equal "latest-html-release, 'release-file-regexp' property"
  '("foo"
    "1.2.3"
    ("/dl/FOO1.2.3.tgz"))
  (with-http-server
      `((200 "<html xmlns=\"http://www.w3.org/1999/xhtml\">
<head>
<title>Releases with unusual file names</title>
</head>
<body
<a href=\"FOO1.2.3.tgz\">version 1.2</a>
</body>
</html>"))
    (let ()
      (define package
        (dummy-package "foo"
                       (source
                        (dummy-origin
                         (uri (string-append (%local-url #:path "/dl")
                                             "/FOO1.0.0.tar.gz"))))
                       (properties
                        `((release-monitoring-url . ,(%local-url #:path "/dl/"))
                          (release-file-regexp . "FOO([0-9\\.]+)\\.tgz")))))
      (define update
        ((upstream-updater-import %generic-html-updater) package))

      (list (upstream-source-package update)
            (upstream-source-version update)
            (map (compose uri-path string->uri)
                 (upstream-source-urls update))))))

(test-assert "latest-html-release, invalid 'release-file-regexp' property"
  (with-http-server
      `((200 "<html xmlns=\"http://www.w3.org/1999/xhtml\">
<head>
<title>Releases with unusual file names</title>
</head>
<body
<a href=\"FOO1.2.3.tgz\">version 1.2</a>
</body>
</html>"))
    (let ()
      (define package
        (dummy-package "foo"
                       (source
                        (dummy-origin
                         (uri (string-append (%local-url #:path "/dl")
                                             "/FOO1.0.0.tar.gz"))))
                       (properties
                        `((release-monitoring-url . ,(%local-url #:path "/dl/"))
                          (release-file-regexp . "FOO[0-9\\.]+\\.tgz")))))
      (not ((upstream-updater-import %generic-html-updater) package)))))


(test-assert "latest-html-release, no signature"
  (with-http-server
      `((200 "<html xmlns=\"http://www.w3.org/1999/xhtml\">