transformations: Add '--with-version'.

This is a followup to 8aeccc6240.

* guix/transformations.scm (package-with-upstream-version): New procedure.
(transform-package-latest)[package-with-latest-upstream]: Remove.
Use 'package-with-upstream-version' instead.
(transform-package-version): New procedure.
(%transformations, %transformation-options)
(show-transformation-options-help/detailed): Add '-with-version'.
* tests/transformations.scm ("options->transformation, with-version"):
New test.
* doc/guix.texi (Package Transformation Options): Document '--with-version'.
(Defining Package Variants): Mention it.
This commit is contained in:
Ludovic Courtès 2023-01-07 15:22:14 +01:00
parent f094c3831f
commit 137b91f03b
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5
3 changed files with 113 additions and 33 deletions

View file

@ -8073,8 +8073,9 @@ vintage!):
"0lappv4slgb5spyqbh6yl5r013zv72yqg2pcl30mginf3wdqd8k9")))))) "0lappv4slgb5spyqbh6yl5r013zv72yqg2pcl30mginf3wdqd8k9"))))))
@end lisp @end lisp
The example above corresponds to what the @option{--with-source} package The example above corresponds to what the @option{--with-version}
transformation option does. Essentially @code{hello-2.2} preserves all or @option{--with-source} package transformations option do.
Essentially @code{hello-2.2} preserves all
the fields of @code{hello}, except @code{version} and @code{source}, the fields of @code{hello}, except @code{version} and @code{source},
which it overrides. Note that the original @code{hello} variable is which it overrides. Note that the original @code{hello} variable is
still there, in the @code{(gnu packages base)} module, unchanged. When still there, in the @code{(gnu packages base)} module, unchanged. When
@ -12740,7 +12741,9 @@ Coreutils in the dependency graph is rebuilt.
@cindex upstream, latest version @cindex upstream, latest version
@item --with-latest=@var{package} @item --with-latest=@var{package}
So you like living on the bleeding edge? This option is for you! It @itemx --with-version=@var{package}=@var{version}
So you like living on the bleeding edge? The @option{--with-latest}
option is for you! It
replaces occurrences of @var{package} in the dependency graph with its replaces occurrences of @var{package} in the dependency graph with its
latest upstream version, as reported by @command{guix refresh} latest upstream version, as reported by @command{guix refresh}
(@pxref{Invoking guix refresh}). (@pxref{Invoking guix refresh}).
@ -12756,6 +12759,26 @@ of Guile-JSON:
guix build guix --with-latest=guile-json guix build guix --with-latest=guile-json
@end example @end example
The @option{--with-version} works similarly except that it lets you
specify that you want precisely @var{version}, assuming that version
exists upstream. For example, to spawn a development environment with
SciPy built against version 1.22.4 of NumPy (skipping its test suite
because hey, we're not gonna wait this long), you would run:
@example
guix shell python python-scipy --with-version=python-numpy=1.22.4
@end example
@quotation Warning
Because they depend on source code published at a given point in time on
upstream servers, deployments made with @option{--with-latest} and
@option{--with-version} may be non-reproducible: source might disappear
or be modified in place on the servers.
To deploy old software versions without compromising on reproducibility,
@ref{Invoking guix time-machine, @command{guix time-machine}}.
@end quotation
There are limitations. First, in cases where the tool cannot or does There are limitations. First, in cases where the tool cannot or does
not know how to authenticate source code, you are at risk of running not know how to authenticate source code, you are at risk of running
malicious code; a warning is emitted in this case. Second, this option malicious code; a warning is emitted in this case. Second, this option
@ -12764,10 +12787,10 @@ which is not always sufficient: there might be additional dependencies
that need to be added, patches to apply, and more generally the quality that need to be added, patches to apply, and more generally the quality
assurance work that Guix developers normally do will be missing. assurance work that Guix developers normally do will be missing.
You've been warned! In all the other cases, it's a snappy way to stay You've been warned! When those limitations are acceptable, it's a
on top. We encourage you to submit patches updating the actual package snappy way to stay on top. We encourage you to submit patches updating
definitions once you have successfully tested an upgrade the actual package definitions once you have successfully tested an
(@pxref{Contributing}). upgrade with @option{--with-latest} (@pxref{Contributing}).
@cindex test suite, skipping @cindex test suite, skipping
@item --without-tests=@var{package} @item --without-tests=@var{package}

View file

@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016-2022 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2016-2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2021 Marius Bakke <marius@gnu.org> ;;; Copyright © 2021 Marius Bakke <marius@gnu.org>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
@ -757,35 +757,69 @@ (define rewrite
(rewrite obj) (rewrite obj)
obj))) obj)))
(define* (package-with-upstream-version p #:optional version)
"Return package P changed to use the given upstream VERSION or, if VERSION
is #f, the latest known upstream version."
(let ((source (package-latest-release p #:version version)))
(cond ((not source)
(if version
(warning
(G_ "could not find version ~a of '~a' upstream~%")
version (package-name p))
(warning
(G_ "could not determine latest upstream release of '~a'~%")
(package-name p)))
p)
((string=? (upstream-source-version source)
(package-version p))
p)
(else
(when (version>? (package-version p)
(upstream-source-version source))
(warning (G_ "using ~a ~a, which is older than the packaged \
version (~a)~%")
(package-name p)
(upstream-source-version source)
(package-version p)))
(unless (pair? (upstream-source-signature-urls source))
(warning (G_ "cannot authenticate source of '~a', version ~a~%")
(package-name p)
(upstream-source-version source)))
;; TODO: Take 'upstream-source-input-changes' into account.
(package
(inherit p)
(version (upstream-source-version source))
(source source))))))
(define (transform-package-latest specs) (define (transform-package-latest specs)
"Return a procedure that rewrites package graphs such that those in SPECS "Return a procedure that rewrites package graphs such that those in SPECS
are replaced by their latest upstream version." are replaced by their latest upstream version."
(define (package-with-latest-upstream p)
(let ((source (package-latest-release p)))
(cond ((not source)
(warning
(G_ "could not determine latest upstream release of '~a'~%")
(package-name p))
p)
((string=? (upstream-source-version source)
(package-version p))
p)
(else
(unless (pair? (upstream-source-signature-urls source))
(warning (G_ "cannot authenticate source of '~a', version ~a~%")
(package-name p)
(upstream-source-version source)))
;; TODO: Take 'upstream-source-input-changes' into account.
(package
(inherit p)
(version (upstream-source-version source))
(source source))))))
(define rewrite (define rewrite
(package-input-rewriting/spec (package-input-rewriting/spec
(map (lambda (spec) (map (lambda (spec)
(cons spec package-with-latest-upstream)) (cons spec package-with-upstream-version))
specs)))
(lambda (obj)
(if (package? obj)
(rewrite obj)
obj)))
(define (transform-package-version specs)
"Return a procedure that rewrites package graphs such that those in SPECS
are replaced by the specified upstream version."
(define rewrite
(package-input-rewriting/spec
(map (lambda (spec)
(match (string-tokenize spec %not-equal)
((spec version)
(cons spec (cut package-with-upstream-version <> version)))
(_
(raise (formatted-message
(G_ "~a: invalid upstream version specification")
spec)))))
specs))) specs)))
(lambda (obj) (lambda (obj)
@ -809,7 +843,8 @@ (define %transformations
(with-debug-info . ,transform-package-with-debug-info) (with-debug-info . ,transform-package-with-debug-info)
(without-tests . ,transform-package-tests) (without-tests . ,transform-package-tests)
(with-patch . ,transform-package-patches) (with-patch . ,transform-package-patches)
(with-latest . ,transform-package-latest))) (with-latest . ,transform-package-latest)
(with-version . ,transform-package-version)))
(define (transformation-procedure key) (define (transformation-procedure key)
"Return the transformation procedure associated with KEY, a symbol such as "Return the transformation procedure associated with KEY, a symbol such as
@ -881,6 +916,8 @@ (define micro-architecture
(parser 'with-patch)) (parser 'with-patch))
(option '("with-latest") #t #f (option '("with-latest") #t #f
(parser 'with-latest)) (parser 'with-latest))
(option '("with-version") #t #f
(parser 'with-version))
(option '("help-transform") #f #f (option '("help-transform") #f #f
(lambda _ (lambda _
@ -915,6 +952,9 @@ (define (show-transformation-options-help/detailed)
(display (G_ " (display (G_ "
--with-latest=PACKAGE --with-latest=PACKAGE
use the latest upstream release of PACKAGE")) use the latest upstream release of PACKAGE"))
(display (G_ "
--with-version=PACKAGE=VERSION
use the given upstream VERSION of PACKAGE"))
(display (G_ " (display (G_ "
--with-c-toolchain=PACKAGE=TOOLCHAIN --with-c-toolchain=PACKAGE=TOOLCHAIN
build PACKAGE and its dependents with TOOLCHAIN")) build PACKAGE and its dependents with TOOLCHAIN"))

View file

@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016-2017, 2019-2022 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2016-2017, 2019-2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2021 Marius Bakke <marius@gnu.org> ;;; Copyright © 2021 Marius Bakke <marius@gnu.org>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
@ -497,6 +497,23 @@ (define (package-name* obj)
`((with-latest . "foo"))))) `((with-latest . "foo")))))
(package-version (t p))))) (package-version (t p)))))
(test-equal "options->transformation, with-version"
"1.0"
(mock ((guix upstream) %updaters
(delay (list (upstream-updater
(name 'dummy)
(pred (const #t))
(description "")
(import (const (upstream-source
(package "foo")
(version "1.0")
(urls '("http://example.org")))))))))
(let* ((p0 (dummy-package "foo" (version "7.7")))
(p1 (dummy-package "bar" (inputs (list p0))))
(t (options->transformation
`((with-version . "foo=1.0")))))
(package-version (lookup-package-input (t p1) "foo")))))
(test-equal "options->transformation, tune" (test-equal "options->transformation, tune"
'(cpu-tuning . "superfast") '(cpu-tuning . "superfast")
(let* ((p0 (dummy-package "p0")) (let* ((p0 (dummy-package "p0"))