diff options
Diffstat (limited to 'guix')
-rw-r--r-- | guix/import/cran.scm | 155 | ||||
-rw-r--r-- | guix/import/crate.scm | 3 | ||||
-rw-r--r-- | guix/import/egg.scm | 3 | ||||
-rw-r--r-- | guix/import/elm.scm | 2 | ||||
-rw-r--r-- | guix/import/gem.scm | 3 | ||||
-rw-r--r-- | guix/import/gnu.scm | 3 | ||||
-rw-r--r-- | guix/import/go.scm | 5 | ||||
-rw-r--r-- | guix/import/hackage.scm | 5 | ||||
-rw-r--r-- | guix/import/hexpm.scm | 2 | ||||
-rw-r--r-- | guix/import/minetest.scm | 5 | ||||
-rw-r--r-- | guix/import/opam.scm | 2 | ||||
-rw-r--r-- | guix/import/pypi.scm | 2 | ||||
-rw-r--r-- | guix/import/stackage.scm | 5 | ||||
-rw-r--r-- | guix/import/texlive.scm | 4 | ||||
-rw-r--r-- | guix/import/utils.scm | 15 | ||||
-rw-r--r-- | guix/scripts/import/cran.scm | 21 | ||||
-rw-r--r-- | guix/scripts/refresh.scm | 133 | ||||
-rw-r--r-- | guix/ui.scm | 4 | ||||
-rw-r--r-- | guix/upstream.scm | 17 |
19 files changed, 223 insertions, 166 deletions
diff --git a/guix/import/cran.scm b/guix/import/cran.scm index 1ed3580315..f6d24820a8 100644 --- a/guix/import/cran.scm +++ b/guix/import/cran.scm @@ -33,6 +33,7 @@ #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) #:use-module (srfi srfi-35) + #:use-module (srfi srfi-71) #:use-module (ice-9 receive) #:use-module (web uri) #:use-module (guix memoization) @@ -83,16 +84,16 @@ (define %input-style (make-parameter 'variable)) ; or 'specification -(define (string->licenses license-string) +(define (string->licenses license-string license-prefix) (let ((licenses (map string-trim-both (string-tokenize license-string (char-set-complement (char-set #\|)))))) - (string->license licenses))) + (string->license licenses license-prefix))) -(define string->license - (let ((prefix identity)) - (match-lambda +(define (string->license license-string license-prefix) + (let ((prefix license-prefix)) + (match license-string ("AGPL-3" (prefix 'agpl3)) ("AGPL (>= 3)" (prefix 'agpl3+)) ("Artistic-2.0" (prefix 'artistic2.0)) @@ -138,8 +139,8 @@ ("MIT + file LICENSE" (prefix 'expat)) ("file LICENSE" `(,(prefix 'fsdg-compatible) "file://LICENSE")) - ((x) (string->license x)) - ((lst ...) `(list ,@(map string->license lst))) + ((x) (string->license x license-prefix)) + ((lst ...) `(list ,@(map (cut string->license <> license-prefix) lst))) (unknown `(,(prefix 'fsdg-compatible) ,unknown))))) (define (description->alist description) @@ -395,7 +396,9 @@ empty list when the FIELD cannot be found." "c++11" "c++14" "c++17" + "c99" "getopt::long" + "gnu" "posix.1-2001" "linux" "none" @@ -406,42 +409,44 @@ empty list when the FIELD cannot be found." (define (transform-sysname sysname) "Return a Guix package name for the common package name SYSNAME." (match sysname + ("booktabs" "texlive-booktabs") + ("bowtie2" "bowtie") + ("cat" "coreutils") ("java" "openjdk") + ("exiftool" "perl-image-exiftool") ("fftw3" "fftw") - ("tcl/tk" "tcl") - ("booktabs" "texlive-booktabs") ("freetype2" "freetype") + ("gettext" "gnu-gettext") + ("gmake" "gnu-make") + ("libarchive-devel" "libarchive") + ("libarchive_dev" "libarchive") + ("libbz2" "bzip2") + ("libexpat" "expat") + ("liblz4" "lz4") + ("liblzma" "xz") + ("libzstd" "zstd") + ("libxml2-devel" "libxml2") + ("libz" "zlib") ("mariadb-devel" "mariadb") ("mysql56_dev" "mariadb") + ("pandoc-citeproc" "pandoc") + ("python3" "python-3") ("sqlite3" "sqlite") + ("svn" "subversion") + ("tcl/tk" "tcl") ("udunits-2" "udunits") + ("whoami" "coreutils") ("x11" "libx11") (_ sysname))) (define cran-guix-name (cut guix-name "r-" <>)) -(define (tarball-needs-fortran? tarball) - "Check if the TARBALL contains Fortran source files." - (define (check pattern) - (parameterize ((current-error-port (%make-void-port "rw+")) - (current-output-port (%make-void-port "rw+"))) - (zero? (system* "tar" "--wildcards" "--list" pattern "-f" tarball)))) - (or (check "*.f90") - (check "*.f95") - (check "*.f"))) - (define (directory-needs-fortran? dir) "Check if the directory DIR contains Fortran source files." - (match (find-files dir "\\.f(90|95)$") + (match (find-files dir "\\.f(90|95)?$") (() #f) (_ #t))) -(define (needs-fortran? thing tarball?) - "Check if the THING contains Fortran source files." - (if tarball? - (tarball-needs-fortran? thing) - (directory-needs-fortran? thing))) - (define (files-match-pattern? directory regexp . file-patterns) "Return #T if any of the files matching FILE-PATTERNS in the DIRECTORY match the given REGEXP." @@ -457,58 +462,42 @@ the given REGEXP." (else (loop)))))))) (apply find-files directory file-patterns)))) -(define (tarball-files-match-pattern? tarball regexp . file-patterns) - "Return #T if any of the files represented by FILE-PATTERNS in the TARBALL -match the given REGEXP." - (call-with-temporary-directory - (lambda (dir) - (parameterize ((current-error-port (%make-void-port "rw+"))) - (apply system* "tar" - "xf" tarball "-C" dir - `("--wildcards" ,@file-patterns))) - (files-match-pattern? dir regexp)))) - (define (directory-needs-zlib? dir) "Return #T if any of the Makevars files in the src directory DIR contain a zlib linker flag." (files-match-pattern? dir "-lz" "(Makevars.*|configure.*)")) -(define (tarball-needs-zlib? tarball) - "Return #T if any of the Makevars files in the src directory of the TARBALL -contain a zlib linker flag." - (tarball-files-match-pattern? - tarball "-lz" - "*/src/Makevars*" "*/src/configure*" "*/configure*")) - -(define (needs-zlib? thing tarball?) - "Check if the THING contains files indicating a dependency on zlib." - (if tarball? - (tarball-needs-zlib? thing) - (directory-needs-zlib? thing))) - (define (directory-needs-pkg-config? dir) "Return #T if any of the Makevars files in the src directory DIR reference the pkg-config tool." (files-match-pattern? dir "pkg-config" "(Makevars.*|configure.*)")) -(define (tarball-needs-pkg-config? tarball) - "Return #T if any of the Makevars files in the src directory of the TARBALL -reference the pkg-config tool." - (tarball-files-match-pattern? - tarball "pkg-config" - "*/src/Makevars*" "*/src/configure*" "*/configure*")) +(define (source-dir->dependencies dir) + "Guess dependencies of R package source in DIR and return two values: a list +of package names for INPUTS and another list of names of NATIVE-INPUTS." + (values + (if (directory-needs-zlib? dir) '("zlib") '()) + (append + (if (directory-needs-pkg-config? dir) '("pkg-config") '()) + (if (directory-needs-fortran? dir) '("gfortran") '())))) -(define (needs-pkg-config? thing tarball?) - "Check if the THING contains files indicating a dependency on pkg-config." +(define (source->dependencies source tarball?) + "SOURCE-DIR->DEPENDENCIES, but for directories and tarballs as indicated +by TARBALL?" (if tarball? - (tarball-needs-pkg-config? thing) - (directory-needs-pkg-config? thing))) + (call-with-temporary-directory + (lambda (dir) + (parameterize ((current-error-port (%make-void-port "rw+"))) + (system* "tar" "xf" source "-C" dir)) + (source-dir->dependencies dir))) + (source-dir->dependencies source))) (define (needs-knitr? meta) (member "knitr" (listify meta "VignetteBuilder"))) -(define (description->package repository meta) +(define* (description->package repository meta #:key (license-prefix identity) + (download-source download)) "Return the `package' s-expression for an R package published on REPOSITORY from the alist META, which was derived from the R package's DESCRIPTION file." (let* ((base-url (case repository @@ -528,7 +517,7 @@ from the alist META, which was derived from the R package's DESCRIPTION file." (name (assoc-ref meta "Package")) (synopsis (assoc-ref meta "Title")) (version (assoc-ref meta "Version")) - (license (string->licenses (assoc-ref meta "License"))) + (license (string->licenses (assoc-ref meta "License") license-prefix)) ;; Some packages have multiple home pages. Some have none. (home-page (case repository ((git) (assoc-ref meta 'git)) @@ -550,12 +539,15 @@ from the alist META, which was derived from the R package's DESCRIPTION file." (_ #f))))) (git? (if (assoc-ref meta 'git) #true #false)) (hg? (if (assoc-ref meta 'hg) #true #false)) - (source (download source-url #:method (cond - (git? 'git) - (hg? 'hg) - (else #f)))) + (source (download-source source-url #:method (cond + (git? 'git) + (hg? 'hg) + (else #f)))) + (tarball? (not (or git? hg?))) + (source-inputs source-native-inputs + (source->dependencies source tarball?)) (sysdepends (append - (if (needs-zlib? source (not (or git? hg?))) '("zlib") '()) + source-inputs (filter (lambda (name) (not (member name invalid-packages))) (map string-downcase (listify meta "SystemRequirements"))))) @@ -615,10 +607,7 @@ from the alist META, which was derived from the R package's DESCRIPTION file." ,@(maybe-inputs (map transform-sysname sysdepends)) ,@(maybe-inputs (map cran-guix-name propagate) 'propagated-inputs) ,@(maybe-inputs - `(,@(if (needs-fortran? source (not (or git? hg?))) - '("gfortran") '()) - ,@(if (needs-pkg-config? source (not (or git? hg?))) - '("pkg-config") '()) + `(,@source-native-inputs ,@(if (needs-knitr? meta) '("r-knitr") '())) 'native-inputs) @@ -644,31 +633,41 @@ from the alist META, which was derived from the R package's DESCRIPTION file." (define cran->guix-package (memoize - (lambda* (package-name #:key (repo 'cran) version) + (lambda* (package-name #:key (repo 'cran) version (license-prefix identity) + (fetch-description fetch-description) + (download-source download) + #:allow-other-keys) "Fetch the metadata for PACKAGE-NAME from REPO and return the `package' s-expression corresponding to that package, or #f on failure." (let ((description (fetch-description repo package-name version))) (if description - (description->package repo description) + (description->package repo description + #:license-prefix license-prefix + #:download-source download-source) (case repo ((git) ;; Retry import from Bioconductor - (cran->guix-package package-name #:repo 'bioconductor)) + (cran->guix-package package-name #:repo 'bioconductor + #:license-prefix license-prefix)) ((hg) ;; Retry import from Bioconductor - (cran->guix-package package-name #:repo 'bioconductor)) + (cran->guix-package package-name #:repo 'bioconductor + #:license-prefix license-prefix)) ((bioconductor) ;; Retry import from CRAN - (cran->guix-package package-name #:repo 'cran)) + (cran->guix-package package-name #:repo 'cran + #:license-prefix license-prefix)) (else (values #f '())))))))) -(define* (cran-recursive-import package-name #:key (repo 'cran) version) +(define* (cran-recursive-import package-name #:key (repo 'cran) version + (license-prefix identity)) (recursive-import package-name #:version version #:repo repo #:repo->guix-package cran->guix-package - #:guix-name cran-guix-name)) + #:guix-name cran-guix-name + #:license-prefix license-prefix)) ;;; diff --git a/guix/import/crate.scm b/guix/import/crate.scm index 339dbcd74c..c17d96ef41 100644 --- a/guix/import/crate.scm +++ b/guix/import/crate.scm @@ -217,7 +217,8 @@ and LICENSE." 'unknown-license!))) (string-split string (string->char-set " /")))) -(define* (crate->guix-package crate-name #:key version include-dev-deps? repo) +(define* (crate->guix-package crate-name #:key version include-dev-deps? + #:allow-other-keys) "Fetch the metadata for CRATE-NAME from crates.io, and return the `package' s-expression corresponding to that package, or #f on failure. When VERSION is specified, convert it into a semver range and attempt to fetch diff --git a/guix/import/egg.scm b/guix/import/egg.scm index 10a40fe4f8..90d97909b5 100644 --- a/guix/import/egg.scm +++ b/guix/import/egg.scm @@ -171,7 +171,8 @@ FILE is specified, return the package metadata in FILE." ;;; Egg importer. ;;; -(define* (egg->guix-package name version #:key (file #f) (source #f)) +(define* (egg->guix-package name version #:key (file #f) (source #f) + #:allow-other-keys) "Import a CHICKEN egg called NAME from either the given .egg FILE, or from the latest NAME metadata downloaded from the official repository if FILE is #f. Return a <package> record or #f on failure. If VERSION is specified, import diff --git a/guix/import/elm.scm b/guix/import/elm.scm index 74902b8617..c8fb15343f 100644 --- a/guix/import/elm.scm +++ b/guix/import/elm.scm @@ -190,7 +190,7 @@ given NAME and VERSION, and a list of Elm packages it depends on." (define elm->guix-package (memoize - (lambda* (package-name #:key repo version) + (lambda* (package-name #:key version #:allow-other-keys) "Fetch the metadata for PACKAGE-NAME, an Elm package registered at package.elm.org, and return two values: the `package' s-expression corresponding to that package (or #f on failure) and a list of Elm diff --git a/guix/import/gem.scm b/guix/import/gem.scm index 8ad0662628..c8d6cd4d2d 100644 --- a/guix/import/gem.scm +++ b/guix/import/gem.scm @@ -124,7 +124,8 @@ VERSION, HASH, HOME-PAGE, DESCRIPTION, DEPENDENCIES, and LICENSES." ((license) (license->symbol license)) (_ `(list ,@(map license->symbol licenses))))))) -(define* (gem->guix-package package-name #:key (repo 'rubygems) version) +(define* (gem->guix-package package-name #:key (repo 'rubygems) version + #:allow-other-keys) "Fetch the metadata for PACKAGE-NAME from rubygems.org, and return the `package' s-expression corresponding to that package, or #f on failure. Optionally include a VERSION string to fetch a specific version gem." diff --git a/guix/import/gnu.scm b/guix/import/gnu.scm index 139c32a545..cff088f423 100644 --- a/guix/import/gnu.scm +++ b/guix/import/gnu.scm @@ -109,7 +109,8 @@ download policy (see 'download-tarball' for details.)" #f)))) (define* (gnu->guix-package name - #:key (key-download 'interactive)) + #:key (key-download 'interactive) + #:allow-other-keys) "Return the package declaration for NAME as an s-expression. Use KEY-DOWNLOAD as the OpenPGP key download policy (see 'download-tarball' for details.)" diff --git a/guix/import/go.scm b/guix/import/go.scm index d00c13475a..90d4c8931d 100644 --- a/guix/import/go.scm +++ b/guix/import/go.scm @@ -602,7 +602,8 @@ available versions:~{ ~a~}.") (define* (go-module->guix-package module-path #:key (goproxy "https://proxy.golang.org") version - pin-versions?) + pin-versions? + #:allow-other-keys) "Return the package S-expression corresponding to MODULE-PATH at VERSION, a Go package. The meta-data is fetched from the GOPROXY server and https://pkg.go.dev/. When VERSION is unspecified, the latest version available is used." @@ -687,7 +688,7 @@ This package and its dependencies won't be imported.~%") package-name #:repo->guix-package (memoize - (lambda* (name #:key version repo) + (lambda* (name #:key version repo #:allow-other-keys) (receive (package-sexp dependencies) (go-module->guix-package* name #:goproxy goproxy #:version version diff --git a/guix/import/hackage.scm b/guix/import/hackage.scm index 3c2cd75db4..7bc2908405 100644 --- a/guix/import/hackage.scm +++ b/guix/import/hackage.scm @@ -326,7 +326,8 @@ the hash of the Cabal file." (define* (hackage->guix-package package-name #:key (include-test-dependencies? #t) (port #f) - (cabal-environment '())) + (cabal-environment '()) + #:allow-other-keys) "Fetch the Cabal file for PACKAGE-NAME from hackage.haskell.org, or, if the called with keyword parameter PORT, from PORT. Return the `package' S-expression corresponding to that package, or #f on failure. @@ -353,7 +354,7 @@ respectively." (define* (hackage-recursive-import package-name . args) (recursive-import package-name - #:repo->guix-package (lambda* (name #:key repo version) + #:repo->guix-package (lambda* (name #:key version #:allow-other-keys) (apply hackage->guix-package/m (cons name args))) #:guix-name hackage-name->package-name)) diff --git a/guix/import/hexpm.scm b/guix/import/hexpm.scm index 8a009fd245..dac5d1756f 100644 --- a/guix/import/hexpm.scm +++ b/guix/import/hexpm.scm @@ -234,7 +234,7 @@ build-system, and DEPENDENCIES the inputs for the package." (fold (lambda (a b) (if (version>? a b) a b)) (car versions) versions))))) -(define* (hexpm->guix-package package-name #:key repo version) +(define* (hexpm->guix-package package-name #:key version #:allow-other-keys) "Fetch the metadata for PACKAGE-NAME from hexpms.io, and return the `package' s-expression corresponding to that package, or #f on failure. When VERSION is specified, attempt to fetch that version; otherwise fetch the diff --git a/guix/import/minetest.scm b/guix/import/minetest.scm index 1f1cfc834d..e5775e2fa9 100644 --- a/guix/import/minetest.scm +++ b/guix/import/minetest.scm @@ -441,7 +441,8 @@ DEPENDENCIES as a list of AUTHOR/NAME strings." #f))))) dependency-list)) -(define* (%minetest->guix-package author/name #:key (sort %default-sort-key)) +(define* (%minetest->guix-package author/name #:key (sort %default-sort-key) + #:allow-other-keys) "Fetch the metadata for AUTHOR/NAME from https://content.minetest.net, and return the 'package' S-expression corresponding to that package, or raise an exception on failure. On success, also return the upstream dependencies as a @@ -477,7 +478,7 @@ list of AUTHOR/NAME strings." (memoize %minetest->guix-package)) (define* (minetest-recursive-import author/name #:key (sort %default-sort-key)) - (define* (minetest->guix-package* author/name #:key repo version) + (define* (minetest->guix-package* author/name #:key version #:allow-other-keys) (minetest->guix-package author/name #:sort sort)) (recursive-import author/name #:repo->guix-package minetest->guix-package* diff --git a/guix/import/opam.scm b/guix/import/opam.scm index 59dbb7cb8b..29b2b886bf 100644 --- a/guix/import/opam.scm +++ b/guix/import/opam.scm @@ -340,7 +340,7 @@ path to the repository." (sha256 (base32 ,(guix-hash-url temp))))))) 'no-source-information))) -(define* (opam->guix-package name #:key (repo 'opam) version) +(define* (opam->guix-package name #:key (repo 'opam) version #:allow-other-keys) "Import OPAM package NAME from REPOSITORY (a directory name) or, if REPOSITORY is #f, from the official OPAM repository. Return a 'package' sexp or #f on failure." diff --git a/guix/import/pypi.scm b/guix/import/pypi.scm index 0e5998b36e..c9aaacbc3f 100644 --- a/guix/import/pypi.scm +++ b/guix/import/pypi.scm @@ -492,7 +492,7 @@ VERSION, SOURCE-URL, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE." (define pypi->guix-package (memoize - (lambda* (package-name #:key repo version) + (lambda* (package-name #:key version #:allow-other-keys) "Fetch the metadata for PACKAGE-NAME from pypi.org, and return the `package' s-expression corresponding to that package, or #f on failure." (let* ((project (pypi-fetch package-name)) diff --git a/guix/import/stackage.scm b/guix/import/stackage.scm index e54df95985..70d3e271f4 100644 --- a/guix/import/stackage.scm +++ b/guix/import/stackage.scm @@ -109,7 +109,8 @@ (lts-version %default-lts-version) (packages (stackage-lts-packages - (stackage-lts-info-fetch lts-version)))) + (stackage-lts-info-fetch lts-version))) + #:allow-other-keys) "Fetch Cabal file for PACKAGE-NAME from hackage.haskell.org. The retrieved version corresponds to the version of PACKAGE-NAME specified in the LTS-VERSION release at stackage.org. Return the `package' S-expression corresponding to @@ -126,7 +127,7 @@ included in the Stackage LTS release." (define (stackage-recursive-import package-name . args) (recursive-import package-name - #:repo->guix-package (lambda* (name #:key repo version) + #:repo->guix-package (lambda* (name #:key version #:allow-other-keys) (apply stackage->guix-package (cons name args))) #:guix-name hackage-name->package-name)) diff --git a/guix/import/texlive.scm b/guix/import/texlive.scm index 116bd1f66a..6bf7f92e60 100644 --- a/guix/import/texlive.scm +++ b/guix/import/texlive.scm @@ -303,9 +303,9 @@ of those files are returned that are unexpectedly installed." (define texlive->guix-package (memoize (lambda* (name #:key - repo (version (number->string %texlive-revision)) - (package-database tlpdb)) + (package-database tlpdb) + #:allow-other-keys) "Find the metadata for NAME in the tlpdb and return the `package' s-expression corresponding to that package, or #f on failure." (tlpdb->package name version (package-database))))) diff --git a/guix/import/utils.scm b/guix/import/utils.scm index d6b179b57c..41311cb86e 100644 --- a/guix/import/utils.scm +++ b/guix/import/utils.scm @@ -580,11 +580,11 @@ obtain a node's uniquely identifying \"key\"." (set-insert (node-name head) visited)))))))) (define* (recursive-import package-name - #:key repo->guix-package guix-name version repo - #:allow-other-keys) + #:key repo->guix-package guix-name version + #:allow-other-keys #:rest rest) "Return a list of package expressions for PACKAGE-NAME and all its dependencies, sorted in topological order. For each package, -call (REPO->GUIX-PACKAGE NAME :KEYS version repo), which should return a +call (REPO->GUIX-PACKAGE NAME :KEYS version), which should return a package expression and a list of dependencies; call (GUIX-NAME PACKAGE-NAME) to obtain the Guix package name corresponding to the upstream name." (define-record-type <node> @@ -599,9 +599,12 @@ to obtain the Guix package name corresponding to the upstream name." (not (null? (find-packages-by-name (guix-name name) version)))) (define (lookup-node name version) - (let* ((package dependencies (repo->guix-package name - #:version version - #:repo repo)) + (let* ((pre post (break (cut eq? #:version <>) rest)) + (post* (match post + ((#:version v . more) more) + (_ post))) + (args (append pre (list #:version version) post*)) + (package dependencies (apply repo->guix-package (cons* name args))) (normalized-deps (map (match-lambda ((name version) (list name version)) (name (list name #f))) dependencies))) diff --git a/guix/scripts/import/cran.scm b/guix/scripts/import/cran.scm index 2934d4300a..5298f059f2 100644 --- a/guix/scripts/import/cran.scm +++ b/guix/scripts/import/cran.scm @@ -53,6 +53,9 @@ Import and convert the CRAN package for PACKAGE-NAME.\n")) (display (G_ " -s, --style=STYLE choose output style, either specification or variable")) (display (G_ " + -p, --license-prefix=PREFIX + add custom prefix to licenses")) + (display (G_ " -V, --version display version information and exit")) (newline) (show-bug-report-information)) @@ -74,6 +77,10 @@ Import and convert the CRAN package for PACKAGE-NAME.\n")) (lambda (opt name arg result) (alist-cons 'style (string->symbol arg) (alist-delete 'style result)))) + (option '(#\p "license-prefix") #t #f + (lambda (opt name arg result) + (alist-cons 'license-prefix arg + (alist-delete 'license-prefix result)))) (option '(#\r "recursive") #f #f (lambda (opt name arg result) (alist-cons 'recursive #t result))) @@ -95,7 +102,13 @@ Import and convert the CRAN package for PACKAGE-NAME.\n")) (('argument . value) value) (_ #f)) - (reverse opts)))) + (reverse opts))) + (prefix (assoc-ref opts 'license-prefix)) + (prefix-proc (if (string? prefix) + (lambda (symbol) + (string->symbol + (string-append prefix (symbol->string symbol)))) + identity))) (parameterize ((%input-style (assoc-ref opts 'style))) (match args ((spec) @@ -107,11 +120,13 @@ Import and convert the CRAN package for PACKAGE-NAME.\n")) (filter identity (cran-recursive-import name #:version version - #:repo (or (assoc-ref opts 'repo) 'cran))))) + #:repo (or (assoc-ref opts 'repo) 'cran) + #:license-prefix prefix-proc)))) ;; Single import (let ((sexp (cran->guix-package name #:version version - #:repo (or (assoc-ref opts 'repo) 'cran)))) + #:repo (or (assoc-ref opts 'repo) 'cran) + #:license-prefix prefix-proc))) (unless sexp (leave (G_ "failed to download description for package '~a'~%") name)) diff --git a/guix/scripts/refresh.scm b/guix/scripts/refresh.scm index e0b94ce48d..6498d73c2b 100644 --- a/guix/scripts/refresh.scm +++ b/guix/scripts/refresh.scm @@ -183,9 +183,31 @@ specified with `--select'.\n")) (newline) (show-bug-report-information)) + +;;; +;;; Utilities. +;;; + +(define-record-type <update-spec> + (%update-spec package version) + update? + (package update-spec-package) + (version update-spec-version)) + +(define* (update-spec package #:optional version) + (%update-spec package version)) + +(define (update-specification->update-spec spec) + "Given SPEC, a package name like \"guile@2.0=2.0.8\", return a <update> +record with two fields: the package to upgrade, and the target version." + (match (string-rindex spec #\=) + (#f (update-spec (specification->package spec) #f)) + (idx (update-spec (specification->package (substring spec 0 idx)) + (substring spec (1+ idx)))))) + (define (options->update-specs opts) - "Return the list of packages requested by OPTS, honoring options like -'--recursive'." + "Return the list of <update-spec> records requested by OPTS, honoring +options like '--recursive'." (define core-package? (let* ((input->package (match-lambda ((name (? package? package) _ ...) package) @@ -220,60 +242,43 @@ update would trigger a complete rebuild." (_ (cons package lst))))) - (define args-packages - ;; Packages explicitly passed as command-line arguments. - (match (filter-map (match-lambda + (define update-specs + ;; Update specs explicitly passed as command-line arguments. + (match (append-map (match-lambda (('argument . spec) ;; Take either the specified version or the ;; latest one. - (update-specification->update-spec spec)) + (list (update-specification->update-spec spec))) (('expression . exp) - (read/eval-package-expression exp)) - (_ #f)) + (list (update-spec (read/eval-package-expression exp)))) + (('manifest . manifest) + (map update-spec (packages-from-manifest manifest))) + (_ + '())) opts) (() ;default to all packages (let ((select? (match (assoc-ref opts 'select) ('core core-package?) ('non-core (negate core-package?)) (_ (const #t))))) - (fold-packages (lambda (package result) - (if (select? package) - (keep-newest package result) - result)) - '()))) + (map update-spec + (fold-packages (lambda (package result) + (if (select? package) + (keep-newest package result) + result)) + '())))) (some ;user-specified packages some))) - (define packages - (match (assoc-ref opts 'manifest) - (#f args-packages) - ((? string? file) (packages-from-manifest file)))) - (if (assoc-ref opts 'recursive?) - (mlet %store-monad ((edges (node-edges %bag-node-type - (all-packages)))) - (return (node-transitive-edges packages edges))) + (mlet* %store-monad ((edges (node-edges %bag-node-type (all-packages))) + (packages -> (node-transitive-edges + (map update-spec-package update-specs) + edges))) + ;; FIXME: The 'version' field of each update spec is lost. + (return (map update-spec packages))) (with-monad %store-monad - (return packages)))) - - -;;; -;;; Utilities. -;;; - -(define-record-type <update-spec> - (update-spec package version) - update? - (package update-spec-package) - (version update-spec-version)) - -(define (update-specification->update-spec spec) - "Given SPEC, a package name like \"guile@2.0=2.0.8\", return a <update> -record with two fields: the package to upgrade, and the target version." - (match (string-rindex spec #\=) - (#f (update-spec (specification->package spec) #f)) - (idx (update-spec (specification->package (substring spec 0 idx)) - (substring spec (1+ idx)))))) + (return update-specs)))) ;;; @@ -382,10 +387,15 @@ downloaded and authenticated; not updating~%") (when warn? (warn-no-updater package)))) -(define* (check-for-package-update package updaters #:key warn?) - "Check whether an update is available for PACKAGE and print a message. When -WARN? is true and no updater exists for PACKAGE, print a warning." - (match (package-latest-release package updaters) +(define* (check-for-package-update update-spec updaters #:key warn?) + "Check whether UPDATE-SPEC is feasible, and print a message. +When WARN? is true and no updater exists for PACKAGE, print a warning." + (define package + (update-spec-package update-spec)) + + (match (package-latest-release package updaters + #:version + (update-spec-version update-spec)) ((? upstream-source? source) (let ((loc (or (package-field-location package 'version) (package-location package)))) @@ -403,23 +413,34 @@ WARN? is true and no updater exists for PACKAGE, print a warning." (package-version package) (package-name package)))) (else - (when warn? - (warning loc - (G_ "~a is greater than \ + (if (update-spec-version update-spec) + (info loc + (G_ "~a would be downgraded from ~a to ~a~%") + (package-name package) + (package-version package) + (upstream-source-version source)) + (when warn? + (warning loc + (G_ "~a is greater than \ the latest known version of ~a (~a)~%") - (package-version package) - (package-name package) - (upstream-source-version source))))))) + (package-version package) + (package-name package) + (upstream-source-version source)))))))) (#f (when warn? ;; Distinguish between "no updater" and "failing updater." (match (lookup-updater package updaters) ((? upstream-updater? updater) - (warning (package-location package) - (G_ "'~a' updater failed to determine available \ + (if (update-spec-version update-spec) + (warning (G_ "'~a' updater failed to find version ~a of '~a'~%") + (upstream-updater-name updater) + (update-spec-version update-spec) + (package-name package)) + (warning (package-location package) + (G_ "'~a' updater failed to determine available \ releases for ~a~%") - (upstream-updater-name updater) - (package-name package))) + (upstream-updater-name updater) + (package-name package)))) (#f (warn-no-updater package))))))) @@ -591,5 +612,5 @@ all are dependent packages: ~{~a~^ ~}~%") (else (for-each (cut check-for-package-update <> updaters #:warn? warn?) - (map update-spec-package update-specs)) + update-specs) (return #t))))))))) diff --git a/guix/ui.scm b/guix/ui.scm index 3bca3b1e40..f26c4534aa 100644 --- a/guix/ui.scm +++ b/guix/ui.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2022 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2012-2023 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2013, 2018 Mark H Weaver <mhw@netris.org> ;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org> ;;; Copyright © 2014 Cyril Roelandt <tipecaml@gmail.com> @@ -518,7 +518,7 @@ See the \"Application Setup\" section in the manual, for more info.\n")) "Display version information for COMMAND and `(exit 0)'." (simple-format #t "~a (~a) ~a~%" command %guix-package-name %guix-version) - (format #t "Copyright ~a 2022 ~a" + (format #t "Copyright ~a 2023 ~a" ;; TRANSLATORS: Translate "(C)" to the copyright symbol ;; (C-in-a-circle), if this symbol is available in the user's ;; locale. Otherwise, do not translate "(C)"; leave it as-is. */ diff --git a/guix/upstream.scm b/guix/upstream.scm index f3ab9ab78b..4c72388bf3 100644 --- a/guix/upstream.scm +++ b/guix/upstream.scm @@ -501,11 +501,22 @@ SOURCE, an <upstream-source>." changes for PACKAGE; return #f (three values) when PACKAGE is up-to-date; raise an error when the updater could not determine available releases. KEY-DOWNLOAD specifies a download policy for missing OpenPGP keys; allowed -values: 'always', 'never', and 'interactive' (default)." +values: 'always', 'never', and 'interactive' (default). + +When VERSION is specified, update PACKAGE to that version, even if that is a +downgrade." (match (package-latest-release package updaters #:version version) ((? upstream-source? source) - (if (version>? (upstream-source-version source) - (package-version package)) + (if (or (version>? (upstream-source-version source) + (package-version package)) + (and version + (begin + (warning (package-location package) + (G_ "downgrading '~a' from ~a to ~a~%") + (package-name package) + (package-version package) + (upstream-source-version source)) + #t))) (let ((method (match (package-source package) ((? origin? origin) (origin-method origin)) |