Subject: [bug#62047] [PATCH 2/2] packages: 'package-input-rewriting/spec' ignores hidden packages.

From: Ludovic Courtès <[email-masked]>
Date: Wed, 8 Mar 2023 13:03:45 +0100

The primary motivation is to support things like:

  guix build guix --with-input=guile=guile-next

without triggering a rebuild of (@@ (gnu packages commencement)
guile-final) and similar things.

It is also consistent with package name resolution on the command line:
a package that cannot be named cannot be replaced.

* guix/packages.scm (package-input-rewriting/spec)[rewrite]: When P is
hidden, return it as-is.
* tests/packages.scm ("package-input-rewriting/spec, hidden package"):
New test.
* doc/guix.texi (Defining Package Variants): Update.
(Package Transformation Options): Update '--with-input' example.
---
 doc/guix.texi      | 21 ++++++++++++---------
 guix/packages.scm  |  7 +++++--
 tests/packages.scm | 20 +++++++++++++++++++-
 3 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 6671ba9305..6803512435 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -8331,10 +8331,13 @@ be replaced by name rather than by identity.
 @deffn {Scheme Procedure} package-input-rewriting/spec @var{replacements} [#:deep? #t]
 Return a procedure that, given a package, applies the given
 @var{replacements} to all the package graph, including implicit inputs
-unless @var{deep?} is false.  @var{replacements} is a list of
-spec/procedures pair; each spec is a package specification such as
-@code{"gcc"} or @code{"guile@@2"}, and each procedure takes a matching
-package and returns a replacement for that package.
+unless @var{deep?} is false.
+
+@var{replacements} is a list of spec/procedures pair; each spec is a
+package specification such as @code{"gcc"} or @code{"guile@@2"}, and
+each procedure takes a matching package and returns a replacement for
+that package.  Matching packages that have the @code{hidden?} property
+set are not replaced.
 @end deffn
 
 The example above could be rewritten this way:
@@ -12664,18 +12667,18 @@ or @code{guile@@1.8}.
 
 For instance, the following command builds Guix, but replaces its
 dependency on the current stable version of Guile with a dependency on
-the legacy version of Guile, @code{guile@@2.0}:
+the legacy version of Guile, @code{guile@@2.2}:
 
 @example
-guix build --with-input=guile=guile@@2.0 guix
+guix build --with-input=guile=guile@@2.2 guix
 @end example
 
 This is a recursive, deep replacement.  So in this example, both
 @code{guix} and its dependency @code{guile-json} (which also depends on
-@code{guile}) get rebuilt against @code{guile@@2.0}.
+@code{guile}) get rebuilt against @code{guile@@2.2}.
 
-This is implemented using the @code{package-input-rewriting} Scheme
-procedure (@pxref{Defining Packages, @code{package-input-rewriting}}).
+This is implemented using the @code{package-input-rewriting/spec} Scheme
+procedure (@pxref{Defining Packages, @code{package-input-rewriting/spec}}).
 
 @item --with-graft=@var{package}=@var{replacement}
 This is similar to @option{--with-input} but with an important difference:
diff --git a/guix/packages.scm b/guix/packages.scm
index cd61878bcc..11c066b292 100644
--- a/guix/packages.scm
+++ b/guix/packages.scm
@@ -1527,9 +1527,11 @@ (define (cut? p)
 (define* (package-input-rewriting/spec replacements #:key (deep? #t))
   "Return a procedure that, given a package, applies the given REPLACEMENTS to
 all the package graph, including implicit inputs unless DEEP? is false.
+
 REPLACEMENTS is a list of spec/procedures pair; each spec is a package
 specification such as \"gcc\" or \"guile@2\", and each procedure takes a
-matching package and returns a replacement for that package."
+matching package and returns a replacement for that package.  Matching
+packages that have the 'hidden?' property set are not replaced."
   (define table
     (fold (lambda (replacement table)
             (match replacement
@@ -1557,7 +1559,8 @@ (define replacement-property
     (gensym " package-replacement"))
 
   (define (rewrite p)
-    (if (assq-ref (package-properties p) replacement-property)
+    (if (or (assq-ref (package-properties p) replacement-property)
+            (hidden-package? p))
         p
         (match (find-replacement p)
           (#f p)
diff --git a/tests/packages.scm b/tests/packages.scm
index f58c47817b..446be6ba52 100644
--- a/tests/packages.scm
+++ b/tests/packages.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012-2022 Ludovic Courtès <[email-masked]>
+;;; Copyright © 2012-2023 Ludovic Courtès <[email-masked]>
 ;;; Copyright © 2018 Jan (janneke) Nieuwenhuizen <[email-masked]>
 ;;; Copyright © 2021 Maxim Cournoyer <[email-masked]>
 ;;; Copyright © 2021 Maxime Devos <[email-masked]>
@@ -1577,6 +1577,24 @@ (define right-system?
     (match (delete-duplicates pythons eq?)
       ((p) (eq? p (rewrite python))))))
 
+(test-assert "package-input-rewriting/spec, hidden package"
+  ;; Hidden packages are not subject to rewriting.
+  (let* ((python  (hidden-package python))
+         (p0      (dummy-package "chbouib"
+                    (build-system trivial-build-system)
+                    (inputs (list python))))
+         (rewrite (package-input-rewriting/spec
+                   `(("python" . ,(const sed)))
+                   #:deep? #t))
+         (p1      (rewrite p0))
+         (bag1    (package->bag p1))
+         (pythons (filter-map (match-lambda
+                                (("python" python) python)
+                                (_ #f))
+                              (bag-transitive-inputs bag1))))
+    (match (delete-duplicates pythons eq?)
+      ((p) (eq? p python)))))
+
 (test-equal "package-input-rewriting/spec, graft"
   (derivation-file-name (package-derivation %store sed))
 
-- 
2.39.1