[PATCH 0/1] Partial version support for 'guix refresh --target-version'.

  • Open
  • quality assurance status badge
Details
One participant
  • Maxim Cournoyer
Owner
unassigned
Submitted by
Maxim Cournoyer
Severity
normal
M
M
Maxim Cournoyer wrote 3 days ago
(address . guix-patches@gnu.org)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)
cover.1737903192.git.maxim.cournoyer@gmail.com
Hello,

This adds support for providing incomplete version strings to 'guix refresh
--target-version', for example allowing to do:

$ guix refresh --target-version=46 evince
gnu/packages/gnome.scm:2710:13: evince would be upgraded from 44.3 to 46.3.1

The change looks massive because all the importers are adjusted to support
this, but the adjustments needed are mechanical and simple, hopefully making
the review not overly painful. The most critical and complex bit may be in
the modified 'rewrite-url' procedure, which is covered by unit tests.

Maxim Cournoyer (1):
refresh: Add support for partial target versions.

doc/guix.texi | 12 +++
guix/gnu-maintenance.scm | 120 ++++++++++++++-----------
guix/import/composer.scm | 59 ++++++------
guix/import/cpan.scm | 2 +-
guix/import/cran.scm | 4 +-
guix/import/crate.scm | 51 ++++++-----
guix/import/egg.scm | 33 +++----
guix/import/elpa.scm | 2 +-
guix/import/gem.scm | 29 ++++--
guix/import/git.scm | 103 +++++++++------------
guix/import/github.scm | 114 +++++++++++------------
guix/import/gnome.scm | 50 ++++-------
guix/import/hackage.scm | 2 +-
guix/import/hexpm.scm | 42 +++++----
guix/import/kde.scm | 57 ++++++------
guix/import/launchpad.scm | 36 ++++----
guix/import/minetest.scm | 2 +-
guix/import/opam.scm | 2 +-
guix/import/pypi.scm | 25 ++++--
guix/import/stackage.scm | 2 +-
guix/import/test.scm | 15 ++--
guix/import/texlive.scm | 38 ++++----
guix/import/utils.scm | 20 ++++-
guix/scripts/refresh.scm | 185 ++++++++++++++++++++------------------
guix/upstream.scm | 26 +++---
tests/gem.scm | 22 +++++
tests/gnu-maintenance.scm | 65 +++++++++++---
tests/guix-refresh.sh | 10 ++-
tests/import-git.scm | 4 +
29 files changed, 629 insertions(+), 503 deletions(-)


base-commit: be058cf6fcf01be49e98b8a646e1ffdb34130db6
--
2.47.1
M
M
Maxim Cournoyer wrote 3 days ago
[PATCH] refresh: Add support for partial target versions.
(address . 75871@debbugs.gnu.org)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)
c2f25efa1b6f666c0a60b64ab524e6bfa7fd339c.1737903740.git.maxim.cournoyer@gmail.com
* guix/import/utils.scm (find-version): New procedure.
* guix/scripts/refresh.scm (<update-spec>) [partial?]: New field.
(update-spec-partial?): New accessor.
(update-spec): Add a PARTIAL? optional argument.
(update-specification->update-spec) <update-spec>: Call with its new PARTIAL?
optional argument when FALLBACK-VERSION is provided, i.e. when
'--target-version' was used.
(update-package): Remove the PACKAGE and VERSION positional arguments, and
replace them with UPDATE-SPEC. Update doc. Call `package-update' with its
new #:partial-version? argument.
(check-for-package-update) <package-latest-release>: Pass the new
#:partial-version? argument to it.
(guix-refresh) <update-package>: Adjust call accordingly.
(show-help): Udate doc.
* guix/upstream.scm (package-latest-release): Add #:partial-version? argument,
and apply it to the importer call.
(package-update): Add #:partial-version?> argument. Update doc. Pass it to
the `package-latest-release' call.
* guix/gnu-maintenance.scm (rewrite-url): Add #:partial-version? argument.
Update doc. Crawl URL for newer compatible versions when provided.
(import-html-release): Add #:partial-version? argument, and pass it to the
`rewrite-url' call. Use `find-version' to find the best version.
(import-release, import-ftp-release, import-gnu-release)
(import-release*): Add #:partial-version? argument and honor it.
(import-html-updatable-release): Add #:partial-version? argument, and pass it
to the `import-html-release' call.
* guix/import/gnome.scm (import-gnome-release)
<#:partial-version?>: Add new argument and honor it.
* guix/import/texlive.scm (latest-texlive-tag): Rename to...
(texlive-tags): ... this, and have it return all tags.
(texlive->guix-package): Adjust accordingly.
(latest-release): Add a #:partial-version? argument. Update doc.
* guix/import/stackage.scm (latest-lts-release): New #:partial-version?
argument.
* guix/import/pypi.scm (import-release): New #:partial-version? argument; pass
it to `pypi-package->upstream-source'.
* guix/import/opam.scm (latest-release): New #:partial-version? argument.
* guix/import/minetest.scm (latest-minetest-release): New #:partial-version?
argument.
(pypi-package->upstream-source): New #:partial-version? argument. Update doc.
* guix/import/launchpad.scm (latest-released-version): Rename to...
(release-versions): ... this, making it return all versions.
(import-release) <#:partial-version?>: New argument.
* guix/import/kde.scm (import-kde-release)
<#:partial-version?>: New argument. Update doc. Refactor to honor argument.
* guix/import/hexpm.scm (lookup-hexpm): Update doc.
(hexpm-latest-release): Rename to...
(hexpm-releases): ... this; return all release strings.
(hexpm->guix-package): Adjust accordingly.
(import-release): Add and honor a #:partial-version? argument. Update doc.
* guix/import/hackage.scm (import-release): New #:partial-version? argument.
* guix/import/cpan.scm (latest-release): New #:partial-version? argument.
* guix/import/crate.scm (max-crate-version-of-semver): Improve doc.
(import-release): Add a #:partial-version? argument and honor it.
* guix/import/egg.scm (find-latest-version): Rename to...
(get-versions): ... this, returning all versions.
(egg-metadata): Adjust accordingly.
(egg->guix-package): Likewise.
(import-release): Add a new #:partial-version? argument and honor it.
* guix/import/elpa.scm (latest-release): New #:partial-version? argument.
* guix/import/gem.scm (get-versions): New procedure.
(import-release): Add a new #:partial-version? argument and honor it.
* guix/import/git.scm (version-mapping): Update doc; streamline a bit.
(latest-tag): Rename to...
(get-tags): ... this, dropping the #:version keyword and returning the complete
tags alist. Update doc.
(latest-git-tag-version): Rename to...
(get-package-tags): ... this, returning the complete tags alist of the
package. Update doc.
(import-git-release): Add a new #:partial-version? argument and honor it.
Update doc.
* guix/import/github.scm (latest-released-version): Rename to...
(get-package-tags): ... this, returning all tags. Update doc.
(import-release): Add a new #:partial-version? argument and honor it.
* guix/import/cran.scm (latest-cran-release)
(latest-bioconductor-release): Add #:partial-version? argument.
* guix/import/composer.scm (latest-version): Delete procedure.
(composer-fetch): Add #:partial-version? keyword and honor it. Update doc.
(import-release): Likewise.
* guix/import/test.scm (import-release): Add #:partial-version? argument.
* tests/guix-refresh.sh: Add test.
* tests/gem.scm (test-foo-versions-json): New variable.
(package-latest-release): Mock new URL.
* tests/import-git.scm (latest-git-tag-version): New procedure.
* tests/gnu-maintenance.scm (libuv-dist-html)
(libuv-dist-1.46.0-html, libuv-dist-1.44.2-html)
(libuv-html-data): New variables.
(mock-http-fetch/cached): New procedure.
("rewrite-url, without to-version"): Rewrite using the above.
("rewrite-url, partial to-version"): New test.
* doc/guix.texi <"Invoking guix refresh">: Update doc.

Change-Id: I092a58b57ac42e54a2fa55e7761e8c6993af8ad4
---

doc/guix.texi | 12 +++
guix/gnu-maintenance.scm | 120 ++++++++++++++-----------
guix/import/composer.scm | 59 ++++++------
guix/import/cpan.scm | 2 +-
guix/import/cran.scm | 4 +-
guix/import/crate.scm | 51 ++++++-----
guix/import/egg.scm | 33 +++----
guix/import/elpa.scm | 2 +-
guix/import/gem.scm | 29 ++++--
guix/import/git.scm | 103 +++++++++------------
guix/import/github.scm | 114 +++++++++++------------
guix/import/gnome.scm | 50 ++++-------
guix/import/hackage.scm | 2 +-
guix/import/hexpm.scm | 42 +++++----
guix/import/kde.scm | 57 ++++++------
guix/import/launchpad.scm | 36 ++++----
guix/import/minetest.scm | 2 +-
guix/import/opam.scm | 2 +-
guix/import/pypi.scm | 25 ++++--
guix/import/stackage.scm | 2 +-
guix/import/test.scm | 15 ++--
guix/import/texlive.scm | 38 ++++----
guix/import/utils.scm | 20 ++++-
guix/scripts/refresh.scm | 185 ++++++++++++++++++++------------------
guix/upstream.scm | 26 +++---
tests/gem.scm | 22 +++++
tests/gnu-maintenance.scm | 65 +++++++++++---
tests/guix-refresh.sh | 10 ++-
tests/import-git.scm | 4 +
29 files changed, 629 insertions(+), 503 deletions(-)

Toggle diff (285 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 9a53bdcd37..cc03dda4ee 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -14961,6 +14961,7 @@ Invoking guix refresh
@dots{}
@end example
+@cindex target version, guix refresh
In some specific cases, you may have many packages specified via a
manifest or a module selection which should all be updated together; for
these cases, the @option{--target-version} option can be provided to have
@@ -14981,6 +14982,17 @@ Invoking guix refresh
@dots{}
@end example
+@cindex partial target version, guix refresh
+The @option{--target-version} option accepts partial version prefixes,
+which can be useful to update to the latest major or major-minor
+prefixed version:
+
+@example
+$ guix refresh qtbase@@5 qtdeclarative@@5 --target-version=5
+gnu/packages/qt.scm:1472:13: qtdeclarative would be upgraded from 5.15.8 to 5.15.10
+gnu/packages/qt.scm:452:13: qtbase would be upgraded from 5.15.8 to 5.15.10
+@end example
+
Sometimes the upstream name differs from the package name used in Guix,
and @command{guix refresh} needs a little help. Most updaters honor the
@code{upstream-name} property in package definitions, which can be used
diff --git a/guix/gnu-maintenance.scm b/guix/gnu-maintenance.scm
index ee4882326f..f26d8c5fbc 100644
--- a/guix/gnu-maintenance.scm
+++ b/guix/gnu-maintenance.scm
@@ -3,7 +3,7 @@
;;; Copyright © 2012, 2013 Nikita Karetnikov <nikita@karetnikov.org>
;;; Copyright © 2021 Simon Tournier <zimon.toutoune@gmail.com>
;;; Copyright © 2022 Maxime Devos <maximedevos@telenet.be>
-;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
+;;; Copyright © 2023, 2025 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -44,7 +44,7 @@ (define-module (guix gnu-maintenance)
#:use-module (guix records)
#:use-module (guix upstream)
#:use-module (guix packages)
- #:autoload (guix import utils) (false-if-networking-error)
+ #:autoload (guix import utils) (false-if-networking-error find-version)
#:autoload (zlib) (call-with-gzip-input-port)
#:autoload (htmlprag) (html->sxml) ;from Guile-Lib
#:export (gnu-package-name
@@ -346,12 +346,15 @@ (define* (releases project
(define* (import-ftp-release project
#:key
- (version #f)
+ version
+ partial-version?
(server "ftp.gnu.org")
(directory (string-append "/gnu/" project))
(file->signature (cut string-append <> ".sig")))
"Return an <upstream-source> for the latest release of PROJECT on SERVER
-under DIRECTORY, or #f. Optionally include a VERSION string to fetch a specific version.
+under DIRECTORY, or #f. Optionally include a VERSION string to fetch a
+specific version, which may be marked as partially specified via
+PARTIAL-VERSION?.
Use FTP-OPEN and FTP-CLOSE to open (resp. close) FTP connections; this can be
useful to reuse connections.
@@ -417,7 +420,9 @@ (define* (import-ftp-release project
(and (release-file? project file)
(file->source directory file)))
(_ #f))
- entries)))
+ entries))
+ (versions (map upstream-source-version releases))
+ (version (find-version versions version partial-version?)))
;; Assume that SUBDIRS correspond to versions, and jump into the
;; one with the highest version number.
@@ -440,14 +445,17 @@ (define* (import-ftp-release project
(define* (import-release package
#:key
- (version #f)
+ version
+ partial-version?
(server "ftp.gnu.org")
(directory (string-append "/gnu/" package)))
"Return the <upstream-source> for the latest version of PACKAGE or #f.
PACKAGE must be the canonical name of a GNU package. Optionally include a
-VERSION string to fetch a specific version."
+VERSION string to fetch a specific version, which may be marked as partially
+specified via PARTIAL-VERSION?."
(import-ftp-release package
#:version version
+ #:partial-version? partial-version?
#:server server
#:directory directory))
@@ -463,7 +471,7 @@ (define-syntax-rule (false-if-ftp-error exp)
(close-port port))
#f)))
-(define* (import-release* package #:key (version #f))
+(define* (import-release* package #:key version partial-version?)
"Like 'import-release', but (1) take a <package> object, and (2) ignore FTP
errors that might occur when PACKAGE is not actually a GNU package, or not
hosted on ftp.gnu.org, or not under that name (this is the case for
@@ -474,6 +482,7 @@ (define* (import-release* package #:key (version #f))
(false-if-ftp-error
(import-release (package-upstream-name package)
#:version version
+ #:partial-version? partial-version?
#:server server
#:directory directory)))))
@@ -561,16 +570,23 @@ (define (strip-trailing-slash s)
;;; TODO: Extend to support the RPM and GNOME version schemes?
(define %version-rx "[0-9.]+")
-(define* (rewrite-url url version #:key to-version)
+(define* (rewrite-url url version #:key to-version partial-version?)
"Rewrite URL so that the URL path components matching the current VERSION or
VERSION-MAJOR.VERSION-MINOR are updated with that of the latest version found
by crawling the corresponding URL directories. Alternatively, when TO-VERSION
-is specified, rewrite version matches directly to it without crawling URL.
+is specified, rewrite version matches directly to it without crawling URL. If
+TO-VERSION is provided and PARTIAL-VERSION? set to #t, then crawl URL to find
+the newest compatible release (one that is prefixed by TO-VERSION).
For example, the URL
\"https://dist.libuv.org/dist/v1.45.0/libuv-v1.45.0.tar.gz\" could be
rewritten to something like
-\"https://dist.libuv.org/dist/v1.46.0/libuv-v1.46.0.tar.gz\"."
+\"https://dist.libuv.org/dist/v1.46.0/libuv-v1.46.0.tar.gz\".
+
+With TO-VERSION set to \"1.49\" and PARTIAL-VERSION? set to #t, the URL
+\"https://dist.libuv.org/dist/v1.45.0/libuv-v1.45.0.tar.gz\" could be
+rewritten to something like
+\"https://dist.libuv.org/dist/v1.49.2/libuv-v1.49.2.tar.gz\"."
;; XXX: major-minor may be #f if version is not a triplet but a single
;; number such as "2".
(let* ((major-minor (false-if-exception (version-major+minor version)))
@@ -590,14 +606,15 @@ (define* (rewrite-url url version #:key to-version)
(reverse
(fold
(lambda (s parents)
- (if to-version
+ (if (and to-version (not partial-version?))
;; Direct rewrite case; the archive is assumed to exist.
(let ((u (string-replace-substring s version to-version)))
(cons (if (and major-minor to-major-minor)
(string-replace-substring u major-minor to-major-minor)
u)
parents))
- ;; More involved HTML crawl case.
+ ;; More involved HTML crawl case to get the latest version or a
+ ;; partial to-version.
(let* ((pattern (if major-minor
(format #f "(~a|~a)" version major-minor)
(format #f "(~a)" version)))
@@ -620,15 +637,14 @@ (define* (rewrite-url url version #:key to-version)
(m (string-match pattern l))
(v (match:substring m 1)))
(cons v l)))
- links)))
- ;; Retrieve the item having the largest version.
- (if (null? candidates)
- parents
- (cons (cdr (first (sort candidates
- (lambda (x y)
- (version>? (car x)
- (car y))))))
- parents)))
+ links))
+ (versions (map car candidates))
+ (version (find-version versions to-version
+ partial-version?)))
+ ;; Retrieve the item having the greatest version.
+ (if version
+ (cons (assoc-ref candidates version) parents)
+ parents)) ;XXX: bogus case; throw an error?
;; No version found in path component; continue.
(cons s parents)))))
(reverse url-prefix-components)
@@ -639,12 +655,14 @@ (define* (import-html-release base-url package
#:key
rewrite-url?
version
+ partial-version?
(directory (string-append
"/" (package-upstream-name package)))
file->signature)
"Return an <upstream-source> for the latest release of PACKAGE under
DIRECTORY at BASE-URL, or #f. Optionally include a VERSION string to fetch a
-specific version.
+specific version, which may be marked as partially specified via
+PARTIAL-VERSION?.
BASE-URL should be the URL of an HTML page, typically a directory listing as
found on 'https://kernel.org/pub'.
@@ -663,7 +681,8 @@ (define* (import-html-release base-url package
base-url
(string-append base-url directory "/")))
(url (if rewrite-url?
- (rewrite-url url current-version #:to-version version)
+ (rewrite-url url current-version #:to-version version
+ #:partial-version? partial-version?)
url))
(links (map (cut canonicalize-url <> url) (url->links url))))
@@ -695,23 +714,18 @@ (define* (import-html-release base-url package
(lambda (url) (list (uri-mirror-rewrite url))))))))))
(define candidates
- (filter-map url->release links))
-
- (match candidates
- (() #f)
- ((first . _)
- (if version
- ;; Find matching release version and return it.
- (find (lambda (upstream)
- (string=? (upstream-source-version upstream) version))
- (coalesce-sources candidates))
- ;; Select the most recent release and return it.
- (reduce (lambda (r1 r2)
- (if (version>? (upstream-source-version r1)
- (upstream-source-version r2))
- r1 r2))
- first
- (coalesce-sources candidates)))))))
+ (coalesce-sources (filter-map url->release links)))
+
+ (define versions
+ (map upstream-source-version candidates))
+
+ (define new-version
+ (find-version versions version partial-version?))
+
+ (and new-version
+ (find (compose (cut string=? new-version <>)
+ upstream-source-version)
+ candidates))))
;;;
@@ -743,7 +757,7 @@ (define ftp.gnu.org-files
(call-with-gzip-input-port port
(compose string->lines get-string-all))))))
-(define* (import-gnu-release package #:key (version #f))
+(define* (import-gnu-release package #:key version partial-version?)
"Return the latest release of PACKAGE, a GNU package available via
ftp.gnu.org. Optionally include a VERSION string to fetch a specific version.
@@ -776,12 +790,15 @@ (define* (import-gnu-release package #:key (version #f))
(string-contains file directory)
(release-file? name (basename file))))
files))
- ;; find latest version
- (version (or version
- (and (not (null? relevant))
- (tarball->version
- (find-latest-tarball-version relevant)))))
- ;; find tarballs matching this version
+ (versions (delay (sort (delete-duplicates
+ (map tarball->version relevant))
+ version>?)))
+ (version (or (and version partial-version?
+ (find (cut version-prefix? version <>)
+ (force versions)))
+ version
+ (first (force versions))))
+ ;; Find tarballs matching this version.
(tarballs (filter (lambda (file)
(string=? version (tarball->version file)))
relevant)))
@@ -998,11 +1015,11 @@ (define (html-updatable-package? package)
(or (assoc-ref (package-properties package) 'release-monitoring-url)
((url-predicate http-url?) package)))
-(define* (import-html-updatable-rele
This message was truncated. Download the full message here.
?
Your comment

Commenting via the web interface is currently disabled.

To comment on this conversation send an email to 75871@debbugs.gnu.org

To respond to this issue using the mumi CLI, first switch to it
mumi current 75871
Then, you may apply the latest patchset in this issue (with sign off)
mumi am -- -s
Or, compose a reply to this issue
mumi compose
Or, send patches to this issue
mumi send-email *.patch