From 1ce270fb85be517c32c0369df6293ca73b26ebac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= Date: Tue, 4 Nov 2025 14:22:08 +0100 Subject: [PATCH] =?UTF-8?q?gnu-maintenance:=20=E2=80=98generic-html?= =?UTF-8?q?=E2=80=99=20recognizes=20=E2=80=98release-file-regexp=E2=80=99?= =?UTF-8?q?=20property.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 --- doc/guix.texi | 30 ++++++++++++++++++-- guix/gnu-maintenance.scm | 45 +++++++++++++++++++++++++----- tests/gnu-maintenance.scm | 58 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 121 insertions(+), 12 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 8b569c7fbc2..7bba256b838 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -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 diff --git a/guix/gnu-maintenance.scm b/guix/gnu-maintenance.scm index 08332425083..a33f941cb80 100644 --- a/guix/gnu-maintenance.scm +++ b/guix/gnu-maintenance.scm @@ -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 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) diff --git a/tests/gnu-maintenance.scm b/tests/gnu-maintenance.scm index 644cd1f2a90..01bcea04aab 100644 --- a/tests/gnu-maintenance.scm +++ b/tests/gnu-maintenance.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2015, 2021 Ludovic Courtès +;;; Copyright © 2015, 2021, 2025 Ludovic Courtès ;;; Copyright © 2022 Maxime Devos ;;; Copyright © 2023-2024 Maxim Cournoyer ;;; @@ -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 " + +Releases with unusual file names + +version 1.2 + +")) + (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 " + +Releases with unusual file names + +version 1.2 + +")) + (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 "