Subject: [bug#73833] [PATCH v2 5/5] guix: refresh: Implement basic upstream-source-inputs rich updates.

From: Nicolas Graves <[email-masked]>
Date: Fri, 18 Oct 2024 00:26:01 +0200

* guix/scripts/refresh.scm (options->user-updaters): Add variable.
(options->update-specs)[input->update-spec]: Restrained default where
the min-version and max-version have the same major+minor version.
[update-specs]: Adapt user-specified packages to be aware of
upstream-source-inputs version in this restrained default.

This should allow to update dependent packages to the right version
as opposed to the latest version. Tested in some capacity, but very
alpha.

This also implies that the upstream-updater-import is able to provide
versions on top of packages, that the updater is able to read
incomplete semver versions (such as 3.2 instead of 3.2.1), and that
the upstream-inputs have their min-version and max-version set.
---
 guix/scripts/refresh.scm | 36 ++++++++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/guix/scripts/refresh.scm b/guix/scripts/refresh.scm
index 810c33c786..70685ddbc1 100644
--- a/guix/scripts/refresh.scm
+++ b/guix/scripts/refresh.scm
@@ -229,6 +229,14 @@ (define (update-specification->update-spec spec fallback-version)
     (idx (update-spec (specification->package (substring spec 0 idx))
                       (substring spec (1+ idx))))))
 
+(define (options->user-updaters opts)
+  ;; Return the list of user-specified updaters.
+  (filter-map (match-lambda
+                (('updaters . names)
+                 (map lookup-updater-by-name names))
+                (_ #f))
+              opts))
+
 (define (options->update-specs opts)
   "Return the list of <update-spec> records requested by OPTS, honoring
 options like '--recursive'."
@@ -269,6 +277,14 @@ (define (keep-newest package lst)
         (_
          (cons package lst)))))
 
+  (define (input->update-spec input)
+    (%update-spec
+     (specification->package (upstream-input-downstream-name input))
+     (if (string=? (version-major+minor (upstream-input-max-version input))
+                   (version-major+minor (upstream-input-min-version input)))
+         (version-major+minor (upstream-input-max-version input))
+         #f)))
+
   (define update-specs
     ;; Update specs explicitly passed as command-line arguments.
     (match (append-map (match-lambda
@@ -307,7 +323,19 @@ (define update-specs
                              '()
                              modules))))
       (some                                       ;user-specified packages
-       some)))
+       ;; When the user specifies updaters, and these updaters support
+       ;; min/max versions, updates specs so that they account for this
+       ;; updater.
+       (let ((user-updaters (options->user-updaters opts)))
+         (if (and user-updaters (not (unspecified? user-updaters))
+                  (not (null? user-updaters)))
+             (let* ((import (upstream-updater-import (caar user-updaters)))
+                    (package (update-spec-package (car some)))
+                    (version (update-spec-version (car some)))
+                    (source (import package #:version version))
+                    (upstream-inputs (upstream-source-inputs source)))
+               (append some (map input->update-spec upstream-inputs)))
+             some)))))
 
   (if (assoc-ref opts 'recursive?)
       (mlet* %store-monad
@@ -571,11 +599,7 @@ (define (parse-options)
 
   (define (options->updaters opts)
     ;; Return the list of updaters to use.
-    (match (filter-map (match-lambda
-                         (('updaters . names)
-                          (map lookup-updater-by-name names))
-                         (_ #f))
-                       opts)
+    (match (options->user-updaters opts)
       (()
        ;; Use the default updaters.
        (force %updaters))
-- 
2.46.0