diff options
| -rw-r--r-- | Makefile.am | 3 | ||||
| -rw-r--r-- | build-aux/test-env.in | 7 | ||||
| -rw-r--r-- | configure.ac | 17 | ||||
| -rw-r--r-- | doc/guix.texi | 30 | ||||
| -rw-r--r-- | etc/completion/fish/guix.fish | 2 | ||||
| -rw-r--r-- | guix/import/snix.scm | 467 | ||||
| -rw-r--r-- | guix/scripts/import.scm | 4 | ||||
| -rw-r--r-- | guix/scripts/import/nix.scm | 90 | ||||
| -rw-r--r-- | tests/snix.scm | 73 |
9 files changed, 4 insertions, 689 deletions
diff --git a/Makefile.am b/Makefile.am index 062a7ba154f..04b4ed74ed0 100644 --- a/Makefile.am +++ b/Makefile.am | |||
| @@ -261,7 +261,6 @@ MODULES = \ | |||
| 261 | guix/import/opam.scm \ | 261 | guix/import/opam.scm \ |
| 262 | guix/import/print.scm \ | 262 | guix/import/print.scm \ |
| 263 | guix/import/pypi.scm \ | 263 | guix/import/pypi.scm \ |
| 264 | guix/import/snix.scm \ | ||
| 265 | guix/import/stackage.scm \ | 264 | guix/import/stackage.scm \ |
| 266 | guix/import/texlive.scm \ | 265 | guix/import/texlive.scm \ |
| 267 | guix/import/utils.scm \ | 266 | guix/import/utils.scm \ |
| @@ -300,7 +299,6 @@ MODULES = \ | |||
| 300 | guix/scripts/import/go.scm \ | 299 | guix/scripts/import/go.scm \ |
| 301 | guix/scripts/import/hackage.scm \ | 300 | guix/scripts/import/hackage.scm \ |
| 302 | guix/scripts/import/json.scm \ | 301 | guix/scripts/import/json.scm \ |
| 303 | guix/scripts/import/nix.scm \ | ||
| 304 | guix/scripts/import/opam.scm \ | 302 | guix/scripts/import/opam.scm \ |
| 305 | guix/scripts/import/pypi.scm \ | 303 | guix/scripts/import/pypi.scm \ |
| 306 | guix/scripts/import/stackage.scm \ | 304 | guix/scripts/import/stackage.scm \ |
| @@ -489,7 +487,6 @@ SCM_TESTS = \ | |||
| 489 | tests/services/linux.scm \ | 487 | tests/services/linux.scm \ |
| 490 | tests/sets.scm \ | 488 | tests/sets.scm \ |
| 491 | tests/size.scm \ | 489 | tests/size.scm \ |
| 492 | tests/snix.scm \ | ||
| 493 | tests/status.scm \ | 490 | tests/status.scm \ |
| 494 | tests/store-database.scm \ | 491 | tests/store-database.scm \ |
| 495 | tests/store-deduplication.scm \ | 492 | tests/store-deduplication.scm \ |
diff --git a/build-aux/test-env.in b/build-aux/test-env.in index 59ab58cc941..7efc43206c2 100644 --- a/build-aux/test-env.in +++ b/build-aux/test-env.in | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #!/bin/sh | 1 | #!/bin/sh |
| 2 | 2 | ||
| 3 | # GNU Guix --- Functional package management for GNU | 3 | # GNU Guix --- Functional package management for GNU |
| 4 | # Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org> | 4 | # Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2021 Ludovic Courtès <ludo@gnu.org> |
| 5 | # | 5 | # |
| 6 | # This file is part of GNU Guix. | 6 | # This file is part of GNU Guix. |
| 7 | # | 7 | # |
| @@ -91,14 +91,11 @@ then | |||
| 91 | # Place for the substituter's cache. | 91 | # Place for the substituter's cache. |
| 92 | XDG_CACHE_HOME="$GUIX_STATE_DIRECTORY/cache-$$" | 92 | XDG_CACHE_HOME="$GUIX_STATE_DIRECTORY/cache-$$" |
| 93 | 93 | ||
| 94 | # For the (guix import snix) tests. | ||
| 95 | NIXPKGS="@NIXPKGS@" | ||
| 96 | |||
| 97 | export NIX_IGNORE_SYMLINK_STORE NIX_STORE_DIR \ | 94 | export NIX_IGNORE_SYMLINK_STORE NIX_STORE_DIR \ |
| 98 | GUIX_LOG_DIRECTORY GUIX_STATE_DIRECTORY GUIX_DATABASE_DIRECTORY \ | 95 | GUIX_LOG_DIRECTORY GUIX_STATE_DIRECTORY GUIX_DATABASE_DIRECTORY \ |
| 99 | GUIX_BINARY_SUBSTITUTE_URL \ | 96 | GUIX_BINARY_SUBSTITUTE_URL \ |
| 100 | GUIX_ALLOW_UNAUTHENTICATED_SUBSTITUTES \ | 97 | GUIX_ALLOW_UNAUTHENTICATED_SUBSTITUTES \ |
| 101 | GUIX_CONFIGURATION_DIRECTORY XDG_CACHE_HOME NIXPKGS | 98 | GUIX_CONFIGURATION_DIRECTORY XDG_CACHE_HOME |
| 102 | 99 | ||
| 103 | # Launch the daemon without chroot support because is may be | 100 | # Launch the daemon without chroot support because is may be |
| 104 | # unavailable, for instance if we're not running as root. | 101 | # unavailable, for instance if we're not running as root. |
diff --git a/configure.ac b/configure.ac index 7c1b9ef8dd7..f8b9376c1f0 100644 --- a/configure.ac +++ b/configure.ac | |||
| @@ -202,23 +202,6 @@ AC_SUBST([GZIP]) | |||
| 202 | AC_SUBST([BZIP2]) | 202 | AC_SUBST([BZIP2]) |
| 203 | AC_SUBST([XZ]) | 203 | AC_SUBST([XZ]) |
| 204 | 204 | ||
| 205 | AC_ARG_WITH([nixpkgs], | ||
| 206 | [AS_HELP_STRING([--with-nixpkgs=DIR], | ||
| 207 | [search for Nixpkgs in DIR (for testing purposes only)])], | ||
| 208 | [case "$withval" in | ||
| 209 | yes|no) AC_MSG_ERROR([Please use `--with-nixpkgs=DIR'.]);; | ||
| 210 | *) NIXPKGS="$withval";; | ||
| 211 | esac], | ||
| 212 | []) | ||
| 213 | |||
| 214 | AC_MSG_CHECKING([for Nixpkgs source tree]) | ||
| 215 | if test -f "$NIXPKGS/default.nix"; then | ||
| 216 | AC_MSG_RESULT([$NIXPKGS]) | ||
| 217 | AC_SUBST([NIXPKGS]) | ||
| 218 | else | ||
| 219 | AC_MSG_RESULT([not found]) | ||
| 220 | fi | ||
| 221 | |||
| 222 | LIBGCRYPT_LIBDIR="no" | 205 | LIBGCRYPT_LIBDIR="no" |
| 223 | LIBGCRYPT_PREFIX="no" | 206 | LIBGCRYPT_PREFIX="no" |
| 224 | 207 | ||
diff --git a/doc/guix.texi b/doc/guix.texi index 58bcfbdbb5f..2fe7ad3a2aa 100644 --- a/doc/guix.texi +++ b/doc/guix.texi | |||
| @@ -11417,36 +11417,6 @@ and outputs a package expression: | |||
| 11417 | guix import json hello.json | 11417 | guix import json hello.json |
| 11418 | @end example | 11418 | @end example |
| 11419 | 11419 | ||
| 11420 | @item nix | ||
| 11421 | Import metadata from a local copy of the source of the | ||
| 11422 | @uref{https://nixos.org/nixpkgs/, Nixpkgs distribution}@footnote{This | ||
| 11423 | relies on the @command{nix-instantiate} command of | ||
| 11424 | @uref{https://nixos.org/nix/, Nix}.}. Package definitions in Nixpkgs are | ||
| 11425 | typically written in a mixture of Nix-language and Bash code. This | ||
| 11426 | command only imports the high-level package structure that is written in | ||
| 11427 | the Nix language. It normally includes all the basic fields of a | ||
| 11428 | package definition. | ||
| 11429 | |||
| 11430 | When importing a GNU package, the synopsis and descriptions are replaced | ||
| 11431 | by their canonical upstream variant. | ||
| 11432 | |||
| 11433 | Usually, you will first need to do: | ||
| 11434 | |||
| 11435 | @example | ||
| 11436 | export NIX_REMOTE=daemon | ||
| 11437 | @end example | ||
| 11438 | |||
| 11439 | @noindent | ||
| 11440 | so that @command{nix-instantiate} does not try to open the Nix database. | ||
| 11441 | |||
| 11442 | As an example, the command below imports the package definition of | ||
| 11443 | LibreOffice (more precisely, it imports the definition of the package | ||
| 11444 | bound to the @code{libreoffice} top-level attribute): | ||
| 11445 | |||
| 11446 | @example | ||
| 11447 | guix import nix ~/path/to/nixpkgs libreoffice | ||
| 11448 | @end example | ||
| 11449 | |||
| 11450 | @item hackage | 11420 | @item hackage |
| 11451 | @cindex hackage | 11421 | @cindex hackage |
| 11452 | Import metadata from the Haskell community's central package archive | 11422 | Import metadata from the Haskell community's central package archive |
diff --git a/etc/completion/fish/guix.fish b/etc/completion/fish/guix.fish index 422baab4bb1..8d1a1eb1e96 100644 --- a/etc/completion/fish/guix.fish +++ b/etc/completion/fish/guix.fish | |||
| @@ -322,8 +322,6 @@ complete -f -c guix -n '__fish_guix_needs_command' -a import -d 'Run IMPORTER wi | |||
| 322 | ##### import gnu | 322 | ##### import gnu |
| 323 | complete -f -c guix -n '__fish_guix_using_command import; and not __fish_seen_subcommand_from $remotecommands' -a gnu -d 'Return a package declaration template for PACKAGE, a GNU package.' | 323 | complete -f -c guix -n '__fish_guix_using_command import; and not __fish_seen_subcommand_from $remotecommands' -a gnu -d 'Return a package declaration template for PACKAGE, a GNU package.' |
| 324 | complete -f -c guix -n '__fish_guix_using_command import; and __fish_seen_subcommand_from gnu' -a "--key-download=" -d 'handle missing OpenPGP keys according to POLICY: "always", "never", and "interactive", which is also used when "key-download" is not specified.' | 324 | complete -f -c guix -n '__fish_guix_using_command import; and __fish_seen_subcommand_from gnu' -a "--key-download=" -d 'handle missing OpenPGP keys according to POLICY: "always", "never", and "interactive", which is also used when "key-download" is not specified.' |
| 325 | ##### import nix | ||
| 326 | complete -f -c guix -n '__fish_guix_using_command import; and not __fish_seen_subcommand_from $remotecommands' -a nix -d 'Import and convert the Nix expression ATTRIBUTE of NIXPKGS.' | ||
| 327 | ##### import pypi | 325 | ##### import pypi |
| 328 | complete -f -c guix -n '__fish_guix_using_command import; and not __fish_seen_subcommand_from $remotecommands' -a pypi -d 'Import and convert the PyPI package for PACKAGE-NAME.' | 326 | complete -f -c guix -n '__fish_guix_using_command import; and not __fish_seen_subcommand_from $remotecommands' -a pypi -d 'Import and convert the PyPI package for PACKAGE-NAME.' |
| 329 | ##### import cpan | 327 | ##### import cpan |
diff --git a/guix/import/snix.scm b/guix/import/snix.scm deleted file mode 100644 index 56934e8cf95..00000000000 --- a/guix/import/snix.scm +++ /dev/null | |||
| @@ -1,467 +0,0 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org> | ||
| 3 | ;;; | ||
| 4 | ;;; This file is part of GNU Guix. | ||
| 5 | ;;; | ||
| 6 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 7 | ;;; under the terms of the GNU General Public License as published by | ||
| 8 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 9 | ;;; your option) any later version. | ||
| 10 | ;;; | ||
| 11 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 12 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;;; GNU General Public License for more details. | ||
| 15 | ;;; | ||
| 16 | ;;; You should have received a copy of the GNU General Public License | ||
| 17 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | (define-module (guix import snix) | ||
| 20 | #:use-module (sxml ssax) | ||
| 21 | #:use-module (ice-9 popen) | ||
| 22 | #:use-module (ice-9 match) | ||
| 23 | #:use-module (ice-9 rdelim) | ||
| 24 | #:use-module (ice-9 format) | ||
| 25 | #:use-module (ice-9 regex) | ||
| 26 | #:use-module (ice-9 vlist) | ||
| 27 | #:use-module (srfi srfi-1) | ||
| 28 | #:use-module (srfi srfi-9) | ||
| 29 | #:use-module (srfi srfi-11) | ||
| 30 | #:use-module (srfi srfi-26) | ||
| 31 | #:use-module (srfi srfi-37) | ||
| 32 | #:use-module (system foreign) | ||
| 33 | #:use-module (rnrs bytevectors) | ||
| 34 | |||
| 35 | ;; Use the 'package-name->name+version' procedure that works with | ||
| 36 | ;; hyphen-separate name/version, not the one that works with '@'-separated | ||
| 37 | ;; name/version. Subtle! | ||
| 38 | #:use-module ((guix utils) #:hide (package-name->name+version)) | ||
| 39 | #:use-module ((guix build utils) #:select (package-name->name+version)) | ||
| 40 | |||
| 41 | #:use-module (guix import utils) | ||
| 42 | #:use-module (guix base16) | ||
| 43 | #:use-module (guix base32) | ||
| 44 | #:use-module (guix config) | ||
| 45 | #:use-module (guix gnu-maintenance) | ||
| 46 | #:export (open-nixpkgs | ||
| 47 | xml->snix | ||
| 48 | nixpkgs->guix-package)) | ||
| 49 | |||
| 50 | ;;; Commentary: | ||
| 51 | ;;; | ||
| 52 | ;;; Converting Nix code to s-expressions, and then to Guix `package' | ||
| 53 | ;;; declarations, using the XML output of `nix-instantiate'. | ||
| 54 | ;;; | ||
| 55 | ;;; Code: | ||
| 56 | |||
| 57 | |||
| 58 | ;;; | ||
| 59 | ;;; SNix. | ||
| 60 | ;;; | ||
| 61 | |||
| 62 | ;; Nix object types visible in the XML output of `nix-instantiate' and | ||
| 63 | ;; mapping to S-expressions (we map to sexps, not records, so that we | ||
| 64 | ;; can do pattern matching): | ||
| 65 | ;; | ||
| 66 | ;; at (at varpat attrspat) | ||
| 67 | ;; attr (attribute loc name value) | ||
| 68 | ;; attrs (attribute-set attributes) | ||
| 69 | ;; attrspat (attribute-set-pattern patterns) | ||
| 70 | ;; bool #f|#t | ||
| 71 | ;; derivation (derivation drv-path out-path attributes) | ||
| 72 | ;; ellipsis '... | ||
| 73 | ;; expr (snix loc body ...) | ||
| 74 | ;; function (function loc at|attrspat|varpat) | ||
| 75 | ;; int int | ||
| 76 | ;; list list | ||
| 77 | ;; null 'null | ||
| 78 | ;; path string | ||
| 79 | ;; string string | ||
| 80 | ;; unevaluated 'unevaluated | ||
| 81 | ;; varpat (varpat name) | ||
| 82 | ;; | ||
| 83 | ;; Initially ATTRIBUTES in `derivation' and `attribute-set' was a promise; | ||
| 84 | ;; however, handling `repeated' nodes makes it impossible to do anything | ||
| 85 | ;; lazily because the whole SXML tree has to be traversed to maintain the | ||
| 86 | ;; list of known derivations. | ||
| 87 | |||
| 88 | (define (xml-element->snix elem attributes body derivations) | ||
| 89 | "Return an SNix element corresponding to XML element ELEM." | ||
| 90 | |||
| 91 | (define (loc) | ||
| 92 | (location (assq-ref attributes 'path) | ||
| 93 | (assq-ref attributes 'line) | ||
| 94 | (assq-ref attributes 'column))) | ||
| 95 | |||
| 96 | (case elem | ||
| 97 | ((at) | ||
| 98 | (values `(at ,(car body) ,(cadr body)) derivations)) | ||
| 99 | ((attr) | ||
| 100 | (let ((name (assq-ref attributes 'name))) | ||
| 101 | (cond ((null? body) | ||
| 102 | (values `(attribute-pattern ,name) derivations)) | ||
| 103 | ((and (pair? body) (null? (cdr body))) | ||
| 104 | (values `(attribute ,(loc) ,name ,(car body)) | ||
| 105 | derivations)) | ||
| 106 | (else | ||
| 107 | (error "invalid attribute body" name (loc) body))))) | ||
| 108 | ((attrs) | ||
| 109 | (values `(attribute-set ,(reverse body)) derivations)) | ||
| 110 | ((attrspat) | ||
| 111 | (values `(attribute-set-pattern ,body) derivations)) | ||
| 112 | ((bool) | ||
| 113 | (values (string-ci=? "true" (assq-ref attributes 'value)) | ||
| 114 | derivations)) | ||
| 115 | ((derivation) | ||
| 116 | (let ((drv-path (assq-ref attributes 'drvPath)) | ||
| 117 | (out-path (assq-ref attributes 'outPath))) | ||
| 118 | (if (equal? body '(repeated)) | ||
| 119 | (let ((body (vhash-assoc drv-path derivations))) | ||
| 120 | (if (pair? body) | ||
| 121 | (values `(derivation ,drv-path ,out-path ,(cdr body)) | ||
| 122 | derivations) | ||
| 123 | |||
| 124 | ;; DRV-PATH hasn't been encountered yet but may be later | ||
| 125 | ;; (see <http://article.gmane.org/gmane.linux.distributions.nixos/5946>.) | ||
| 126 | ;; Return an `unresolved' node. | ||
| 127 | (values `(unresolved | ||
| 128 | ,(lambda (derivations) | ||
| 129 | (let ((body (vhash-assoc drv-path derivations))) | ||
| 130 | (if (pair? body) | ||
| 131 | `(derivation ,drv-path ,out-path | ||
| 132 | ,(cdr body)) | ||
| 133 | (error "no previous occurrence of derivation" | ||
| 134 | drv-path))))) | ||
| 135 | derivations))) | ||
| 136 | (values `(derivation ,drv-path ,out-path ,body) | ||
| 137 | (vhash-cons drv-path body derivations))))) | ||
| 138 | ((ellipsis) | ||
| 139 | (values '... derivations)) | ||
| 140 | ((expr) | ||
| 141 | (values `(snix ,(loc) ,@body) derivations)) | ||
| 142 | ((function) | ||
| 143 | (values `(function ,(loc) ,body) derivations)) | ||
| 144 | ((int) | ||
| 145 | (values (string->number (assq-ref attributes 'value)) | ||
| 146 | derivations)) | ||
| 147 | ((list) | ||
| 148 | (values body derivations)) | ||
| 149 | ((null) | ||
| 150 | (values 'null derivations)) | ||
| 151 | ((path) | ||
| 152 | (values (assq-ref attributes 'value) derivations)) | ||
| 153 | ((repeated) | ||
| 154 | (values 'repeated derivations)) | ||
| 155 | ((string) | ||
| 156 | (values (assq-ref attributes 'value) derivations)) | ||
| 157 | ((unevaluated) | ||
| 158 | (values 'unevaluated derivations)) | ||
| 159 | ((varpat) | ||
| 160 | (values `(varpat ,(assq-ref attributes 'name)) derivations)) | ||
| 161 | (else (error "unhandled Nix XML element" elem)))) | ||
| 162 | |||
| 163 | (define (resolve snix derivations) | ||
| 164 | "Return a new SNix tree where `unresolved' nodes from SNIX have been | ||
| 165 | replaced by the result of their application to DERIVATIONS, a vhash." | ||
| 166 | (let loop ((node snix) | ||
| 167 | (seen vlist-null)) | ||
| 168 | (if (vhash-assq node seen) | ||
| 169 | (values node seen) | ||
| 170 | (match node | ||
| 171 | (('unresolved proc) | ||
| 172 | (let ((n (proc derivations))) | ||
| 173 | (values n seen))) | ||
| 174 | ((tag body ...) | ||
| 175 | (let ((body+seen (fold (lambda (n body+seen) | ||
| 176 | (call-with-values | ||
| 177 | (lambda () | ||
| 178 | (loop n (cdr body+seen))) | ||
| 179 | (lambda (n* seen) | ||
| 180 | (cons (cons n* (car body+seen)) | ||
| 181 | (vhash-consq n #t seen))))) | ||
| 182 | (cons '() (vhash-consq node #t seen)) | ||
| 183 | body))) | ||
| 184 | (values (cons tag (reverse (car body+seen))) | ||
| 185 | (vhash-consq node #t (cdr body+seen))))) | ||
| 186 | (anything | ||
| 187 | (values anything seen)))))) | ||
| 188 | |||
| 189 | (define xml->snix | ||
| 190 | (let ((parse | ||
| 191 | (ssax:make-parser NEW-LEVEL-SEED | ||
| 192 | (lambda (elem-gi attributes namespaces expected-content | ||
| 193 | seed) | ||
| 194 | (cons '() (cdr seed))) | ||
| 195 | |||
| 196 | FINISH-ELEMENT | ||
| 197 | (lambda (elem-gi attributes namespaces parent-seed | ||
| 198 | seed) | ||
| 199 | (let ((snix (car seed)) | ||
| 200 | (derivations (cdr seed))) | ||
| 201 | (let-values (((snix derivations) | ||
| 202 | (xml-element->snix elem-gi | ||
| 203 | attributes | ||
| 204 | snix | ||
| 205 | derivations))) | ||
| 206 | (cons (cons snix (car parent-seed)) | ||
| 207 | derivations)))) | ||
| 208 | |||
| 209 | CHAR-DATA-HANDLER | ||
| 210 | (lambda (string1 string2 seed) | ||
| 211 | ;; Discard inter-node strings, which are blanks. | ||
| 212 | seed)))) | ||
| 213 | (lambda (port) | ||
| 214 | "Return the SNix represention of TREE, an SXML tree as returned by | ||
| 215 | parsing the XML output of `nix-instantiate' on Nixpkgs." | ||
| 216 | (match (parse port (cons '() vlist-null)) | ||
| 217 | (((snix) . derivations) | ||
| 218 | (resolve snix derivations)))))) | ||
| 219 | |||
| 220 | (define (attribute-value attribute) | ||
| 221 | "Return the value of ATTRIBUTE." | ||
| 222 | (match attribute | ||
| 223 | (('attribute _ _ value) value))) | ||
| 224 | |||
| 225 | (define (derivation-source derivation) | ||
| 226 | "Return the \"src\" attribute of DERIVATION or #f if not found." | ||
| 227 | (match derivation | ||
| 228 | (('derivation _ _ (attributes ...)) | ||
| 229 | (find-attribute-by-name "src" attributes)))) | ||
| 230 | |||
| 231 | (define (derivation-output-path derivation) | ||
| 232 | "Return the output path of DERIVATION." | ||
| 233 | (match derivation | ||
| 234 | (('derivation _ out-path _) | ||
| 235 | out-path) | ||
| 236 | (_ #f))) | ||
| 237 | |||
| 238 | (define (source-output-path src) | ||
| 239 | "Return the output path of SRC, the \"src\" attribute of a derivation." | ||
| 240 | (derivation-output-path (attribute-value src))) | ||
| 241 | |||
| 242 | (define (source-urls src) | ||
| 243 | "Return the URLs of SRC, the \"src\" attribute of a derivation." | ||
| 244 | (match src | ||
| 245 | (('attribute _ _ ('derivation _ _ (attributes ...))) | ||
| 246 | (match (find-attribute-by-name "urls" attributes) | ||
| 247 | (('attribute _ _ value) | ||
| 248 | value))) | ||
| 249 | (_ #f))) | ||
| 250 | |||
| 251 | (define (source-sha256 src) | ||
| 252 | "Return the sha256 of SRC, the \"src\" attribute of a derivation, as a | ||
| 253 | bytevector." | ||
| 254 | (match src | ||
| 255 | (('attribute _ _ ('derivation _ _ (attributes ...))) | ||
| 256 | (match (find-attribute-by-name "outputHash" attributes) | ||
| 257 | (('attribute _ _ value) | ||
| 258 | (match value | ||
| 259 | ((= string-length 52) | ||
| 260 | (nix-base32-string->bytevector value)) | ||
| 261 | ((= string-length 64) | ||
| 262 | (base16-string->bytevector value)) | ||
| 263 | (_ | ||
| 264 | (error "unsupported hash format" value)))))) | ||
| 265 | (_ #f))) | ||
| 266 | |||
| 267 | (define (derivation-source-output-path derivation) | ||
| 268 | "Return the output path of the \"src\" attribute of DERIVATION or #f | ||
| 269 | if DERIVATION lacks an \"src\" attribute." | ||
| 270 | (and=> (derivation-source derivation) source-output-path)) | ||
| 271 | |||
| 272 | (define* (open-nixpkgs nixpkgs #:optional attribute) | ||
| 273 | "Return an input pipe to the XML representation of Nixpkgs. When | ||
| 274 | ATTRIBUTE is true, only that attribute is considered." | ||
| 275 | (with-fluids ((%default-port-encoding "UTF-8")) | ||
| 276 | (let ((cross-system (format #f "{ | ||
| 277 | config = \"i686-guix-linux-gnu\"; | ||
| 278 | libc = \"glibc\"; | ||
| 279 | arch = \"guix\"; | ||
| 280 | withTLS = true; | ||
| 281 | float = \"hard\"; | ||
| 282 | openssl.system = \"linux-generic32\"; | ||
| 283 | platform = (import ~a/pkgs/top-level/platforms.nix).sheevaplug; | ||
| 284 | }" nixpkgs))) | ||
| 285 | (apply open-pipe* OPEN_READ | ||
| 286 | "nix-instantiate" "--strict" "--eval-only" "--xml" | ||
| 287 | |||
| 288 | ;; Pass a dummy `crossSystem' argument so that `buildInputs' and | ||
| 289 | ;; `nativeBuildInputs' are not coalesced. | ||
| 290 | ;; XXX: This is hacky and has other problems. | ||
| 291 | ;"--arg" "crossSystem" cross-system | ||
| 292 | |||
| 293 | `(,@(if attribute | ||
| 294 | `("-A" ,attribute) | ||
| 295 | '()) | ||
| 296 | ,nixpkgs))))) | ||
| 297 | |||
| 298 | (define (pipe-failed? pipe) | ||
| 299 | "Close pipe and return its status if it failed." | ||
| 300 | (let ((status (close-pipe pipe))) | ||
| 301 | (if (or (status:term-sig status) | ||
| 302 | (not (= (status:exit-val status) 0))) | ||
| 303 | status | ||
| 304 | #f))) | ||
| 305 | |||
| 306 | (define (find-attribute-by-name name attributes) | ||
| 307 | "Return attribute NAME in ATTRIBUTES, an attribute set or list of SNix | ||
| 308 | attributes, or #f if NAME cannot be found." | ||
| 309 | (find (lambda (a) | ||
| 310 | (match a | ||
| 311 | (('attribute _ (? (cut string=? <> name)) _) | ||
| 312 | a) | ||
| 313 | (_ #f))) | ||
| 314 | (match attributes | ||
| 315 | (('attribute-set (attributes ...)) | ||
| 316 | attributes) | ||
| 317 | (_ | ||
| 318 | attributes)))) | ||
| 319 | |||
| 320 | (define (license-variable license) | ||
| 321 | "Return the name of the (guix licenses) variable for LICENSE." | ||
| 322 | (match license | ||
| 323 | ("GPLv2+" 'gpl2+) | ||
| 324 | ("GPLv3+" 'gpl3+) | ||
| 325 | ("LGPLv2+" 'lgpl2.1+) | ||
| 326 | ("LGPLv2.1+" 'lgpl2.1+) | ||
| 327 | ("LGPLv3+" 'lgpl3+) | ||
| 328 | (('attribute-set _ ...) | ||
| 329 | ;; At some point in 2013, Nixpkgs switched to attribute sets to represent | ||
| 330 | ;; licenses. These are listed in lib/licenses.nix. | ||
| 331 | (match (and=> (find-attribute-by-name "shortName" license) | ||
| 332 | attribute-value) | ||
| 333 | ("agpl3Plus" 'agpl3+) | ||
| 334 | ("gpl2Plus" 'gpl2+) | ||
| 335 | ("gpl3Plus" 'gpl3+) | ||
| 336 | ("lgpl2Plus" 'lgpl2.0+) | ||
| 337 | ("lgpl21Plus" 'lgpl2.1+) | ||
| 338 | ("lgpl3Plus" 'lgpl3+) | ||
| 339 | ((? string? x) x) | ||
| 340 | (_ license))) | ||
| 341 | (_ license))) | ||
| 342 | |||
| 343 | (define (package-source-output-path package) | ||
| 344 | "Return the output path of the \"src\" derivation of PACKAGE." | ||
| 345 | (derivation-source-output-path (attribute-value package))) | ||
| 346 | |||
| 347 | |||
| 348 | ;;; | ||
| 349 | ;;; Conversion of "Nix expressions" to "Guix expressions". | ||
| 350 | ;;; | ||
| 351 | |||
| 352 | (define (snix-derivation->guix-package derivation) | ||
| 353 | "Return the `package' s-expression corresponding to SNix DERIVATION, a | ||
| 354 | Nixpkgs `stdenv.mkDerivation'-style derivation, and the original source | ||
| 355 | location of DERIVATION." | ||
| 356 | (match derivation | ||
| 357 | (('derivation _ _ (attributes ...)) | ||
| 358 | (let*-values (((full-name loc) | ||
| 359 | (match (find-attribute-by-name "name" attributes) | ||
| 360 | (('attribute loc _ value) | ||
| 361 | (values value loc)) | ||
| 362 | (_ | ||
| 363 | (values #f #f)))) | ||
| 364 | ((name version) | ||
| 365 | (package-name->name+version full-name))) | ||
| 366 | (define (convert-inputs type) | ||
| 367 | ;; Convert the derivation's input from a list of SNix derivations to | ||
| 368 | ;; a list of name/variable pairs. | ||
| 369 | (match (and=> (find-attribute-by-name type attributes) | ||
| 370 | attribute-value) | ||
| 371 | (#f | ||
| 372 | '()) | ||
| 373 | ((inputs ...) | ||
| 374 | ;; Inputs can be either derivations or the null value. | ||
| 375 | (filter-map (match-lambda | ||
| 376 | (('derivation _ _ (attributes ...)) | ||
| 377 | (let* ((full-name | ||
| 378 | (attribute-value | ||
| 379 | (find-attribute-by-name "name" attributes))) | ||
| 380 | (name (package-name->name+version full-name))) | ||
| 381 | (list name | ||
| 382 | (list 'unquote (string->symbol name))))) | ||
| 383 | ('null #f)) | ||
| 384 | inputs)))) | ||
| 385 | |||
| 386 | (define (maybe-inputs guix-name inputs) | ||
| 387 | (match inputs | ||
| 388 | (() | ||
| 389 | '()) | ||
| 390 | ((inputs ...) | ||
| 391 | (list (list guix-name | ||
| 392 | (list 'quasiquote inputs)))))) | ||
| 393 | |||
| 394 | (define (pretty-uri uri version) | ||
| 395 | (if version | ||
| 396 | (match (factorize-uri uri version) | ||
| 397 | ((items ...) | ||
| 398 | `(string-append ,@items)) | ||
| 399 | (x x)) | ||
| 400 | uri)) | ||
| 401 | |||
| 402 | (let* ((source (find-attribute-by-name "src" attributes)) | ||
| 403 | (urls (source-urls source)) | ||
| 404 | (sha256 (source-sha256 source)) | ||
| 405 | (meta (and=> (find-attribute-by-name "meta" attributes) | ||
| 406 | attribute-value))) | ||
| 407 | (values | ||
| 408 | `(package | ||
| 409 | (name ,name) | ||
| 410 | (version ,version) | ||
| 411 | (source (origin | ||
| 412 | (method url-fetch) | ||
| 413 | (uri ,(pretty-uri (car urls) version)) | ||
| 414 | (sha256 | ||
| 415 | (base32 | ||
| 416 | ,(bytevector->nix-base32-string sha256))))) | ||
| 417 | (build-system gnu-build-system) | ||
| 418 | |||
| 419 | ;; When doing a native Nixpkgs build, `buildInputs' is empty and | ||
| 420 | ;; everything is in `nativeBuildInputs'. So we can't distinguish | ||
| 421 | ;; between both, here. | ||
| 422 | ;; | ||
| 423 | ;; Note that `nativeBuildInputs' was renamed from | ||
| 424 | ;; `buildNativeInputs' in Nixpkgs sometime around March 2013. | ||
| 425 | ,@(maybe-inputs 'inputs | ||
| 426 | (convert-inputs "nativeBuildInputs")) | ||
| 427 | ,@(maybe-inputs 'propagated-inputs | ||
| 428 | (convert-inputs "propagatedNativeBuildInputs")) | ||
| 429 | |||
| 430 | (home-page ,(and=> (find-attribute-by-name "homepage" meta) | ||
| 431 | attribute-value)) | ||
| 432 | (synopsis | ||
| 433 | ;; For GNU packages, prefer the official synopsis. | ||
| 434 | ,(or (false-if-exception | ||
| 435 | (and=> (find (lambda (gnu-package) | ||
| 436 | (equal? (gnu-package-name gnu-package) | ||
| 437 | name)) | ||
| 438 | (official-gnu-packages)) | ||
| 439 | gnu-package-doc-summary)) | ||
| 440 | (and=> (find-attribute-by-name "description" meta) | ||
| 441 | attribute-value))) | ||
| 442 | (description | ||
| 443 | ;; Likewise, prefer the official description of GNU packages. | ||
| 444 | ,(or (false-if-exception | ||
| 445 | (and=> (find (lambda (gnu-package) | ||
| 446 | (equal? (gnu-package-name gnu-package) | ||
| 447 | name)) | ||
| 448 | (official-gnu-packages)) | ||
| 449 | gnu-package-doc-description)) | ||
| 450 | (and=> (find-attribute-by-name "longDescription" meta) | ||
| 451 | attribute-value))) | ||
| 452 | (license ,(and=> (find-attribute-by-name "license" meta) | ||
| 453 | (compose license-variable attribute-value)))) | ||
| 454 | loc)))))) | ||
| 455 | |||
| 456 | (define (nixpkgs->guix-package nixpkgs attribute) | ||
| 457 | "Evaluate ATTRIBUTE in NIXPKGS, the file name of a Nixpkgs checkout, | ||
| 458 | and return the `package' s-expression corresponding to that package." | ||
| 459 | (let ((port (open-nixpkgs nixpkgs attribute))) | ||
| 460 | (match (xml->snix port) | ||
| 461 | (('snix loc (and drv ('derivation _ ...))) | ||
| 462 | (and (not (pipe-failed? port)) | ||
| 463 | (snix-derivation->guix-package drv))) | ||
| 464 | (_ | ||
| 465 | (not (pipe-failed? port)))))) | ||
| 466 | |||
| 467 | ;;; snix.scm ends here | ||
diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm index 98554ef79bf..bbd9a3b1906 100644 --- a/guix/scripts/import.scm +++ b/guix/scripts/import.scm | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2012, 2013, 2014, 2020 Ludovic Courtès <ludo@gnu.org> | 2 | ;;; Copyright © 2012, 2013, 2014, 2020, 2021 Ludovic Courtès <ludo@gnu.org> |
| 3 | ;;; Copyright © 2014 David Thompson <davet@gnu.org> | 3 | ;;; Copyright © 2014 David Thompson <davet@gnu.org> |
| 4 | ;;; Copyright © 2018 Kyle Meyer <kyle@kyleam.com> | 4 | ;;; Copyright © 2018 Kyle Meyer <kyle@kyleam.com> |
| 5 | ;;; Copyright © 2019 Ricardo Wurmus <rekado@elephly.net> | 5 | ;;; Copyright © 2019 Ricardo Wurmus <rekado@elephly.net> |
| @@ -76,7 +76,7 @@ rather than \\n." | |||
| 76 | ;;; Entry point. | 76 | ;;; Entry point. |
| 77 | ;;; | 77 | ;;; |
| 78 | 78 | ||
| 79 | (define importers '("gnu" "nix" "pypi" "cpan" "hackage" "stackage" "elpa" "gem" | 79 | (define importers '("gnu" "pypi" "cpan" "hackage" "stackage" "elpa" "gem" |
| 80 | "go" "cran" "crate" "texlive" "json" "opam")) | 80 | "go" "cran" "crate" "texlive" "json" "opam")) |
| 81 | 81 | ||
| 82 | (define (resolve-importer name) | 82 | (define (resolve-importer name) |
diff --git a/guix/scripts/import/nix.scm b/guix/scripts/import/nix.scm deleted file mode 100644 index 45ca7e3fcf1..00000000000 --- a/guix/scripts/import/nix.scm +++ /dev/null | |||
| @@ -1,90 +0,0 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2012, 2013, 2016 Ludovic Courtès <ludo@gnu.org> | ||
| 3 | ;;; Copyright © 2014 David Thompson <davet@gnu.org> | ||
| 4 | ;;; | ||
| 5 | ;;; This file is part of GNU Guix. | ||
| 6 | ;;; | ||
| 7 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 8 | ;;; under the terms of the GNU General Public License as published by | ||
| 9 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 10 | ;;; your option) any later version. | ||
| 11 | ;;; | ||
| 12 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 13 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | ;;; GNU General Public License for more details. | ||
| 16 | ;;; | ||
| 17 | ;;; You should have received a copy of the GNU General Public License | ||
| 18 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | (define-module (guix scripts import nix) | ||
| 21 | #:use-module (guix ui) | ||
| 22 | #:use-module (guix utils) | ||
| 23 | #:use-module (guix scripts) | ||
| 24 | #:use-module (guix import snix) | ||
| 25 | #:use-module (guix scripts import) | ||
| 26 | #:use-module (srfi srfi-1) | ||
| 27 | #:use-module (srfi srfi-11) | ||
| 28 | #:use-module (srfi srfi-37) | ||
| 29 | #:use-module (ice-9 match) | ||
| 30 | #:export (guix-import-nix)) | ||
| 31 | |||
| 32 | |||
| 33 | ;;; | ||
| 34 | ;;; Command-line options. | ||
| 35 | ;;; | ||
| 36 | |||
| 37 | (define %default-options | ||
| 38 | '()) | ||
| 39 | |||
| 40 | (define (show-help) | ||
| 41 | (display (G_ "Usage: guix import nix NIXPKGS ATTRIBUTE | ||
| 42 | Import and convert the Nix expression ATTRIBUTE of NIXPKGS.\n")) | ||
| 43 | (display (G_ " | ||
| 44 | -h, --help display this help and exit")) | ||
| 45 | (display (G_ " | ||
| 46 | -V, --version display version information and exit")) | ||
| 47 | (newline) | ||
| 48 | (show-bug-report-information)) | ||
| 49 | |||
| 50 | (define %options | ||
| 51 | ;; Specification of the command-line options. | ||
| 52 | (cons* (option '(#\h "help") #f #f | ||
| 53 | (lambda args | ||
| 54 | (show-help) | ||
| 55 | (exit 0))) | ||
| 56 | (option '(#\V "version") #f #f | ||
| 57 | (lambda args | ||
| 58 | (show-version-and-exit "guix import nix"))) | ||
| 59 | %standard-import-options)) | ||
| 60 | |||
| 61 | |||
| 62 | ;;; | ||
| 63 | ;;; Entry point. | ||
| 64 | ;;; | ||
| 65 | |||
| 66 | (define (guix-import-nix . args) | ||
| 67 | (define (parse-options) | ||
| 68 | ;; Return the alist of option values. | ||
| 69 | (args-fold* args %options | ||
| 70 | (lambda (opt name arg result) | ||
| 71 | (leave (G_ "~A: unrecognized option~%") name)) | ||
| 72 | (lambda (arg result) | ||
| 73 | (alist-cons 'argument arg result)) | ||
| 74 | %default-options)) | ||
| 75 | |||
| 76 | (let* ((opts (parse-options)) | ||
| 77 | (args (filter-map (match-lambda | ||
| 78 | (('argument . value) | ||
| 79 | value) | ||
| 80 | (_ #f)) | ||
| 81 | (reverse opts)))) | ||
| 82 | (match args | ||
| 83 | ((nixpkgs attribute) | ||
| 84 | (let-values (((expr loc) | ||
| 85 | (nixpkgs->guix-package nixpkgs attribute))) | ||
| 86 | (format #t ";; converted from ~a:~a~%~%" | ||
| 87 | (location-file loc) (location-line loc)) | ||
| 88 | expr)) | ||
| 89 | (x | ||
| 90 | (leave (G_ "wrong number of arguments~%")))))) | ||
diff --git a/tests/snix.scm b/tests/snix.scm deleted file mode 100644 index 4c31e3389d9..00000000000 --- a/tests/snix.scm +++ /dev/null | |||
| @@ -1,73 +0,0 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2012, 2013, 2015 Ludovic Courtès <ludo@gnu.org> | ||
| 3 | ;;; | ||
| 4 | ;;; This file is part of GNU Guix. | ||
| 5 | ;;; | ||
| 6 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 7 | ;;; under the terms of the GNU General Public License as published by | ||
| 8 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 9 | ;;; your option) any later version. | ||
| 10 | ;;; | ||
| 11 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 12 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;;; GNU General Public License for more details. | ||
| 15 | ;;; | ||
| 16 | ;;; You should have received a copy of the GNU General Public License | ||
| 17 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | (define-module (test-snix) | ||
| 20 | #:use-module (guix import snix) | ||
| 21 | #:use-module (srfi srfi-1) | ||
| 22 | #:use-module (srfi srfi-64) | ||
| 23 | #:use-module (ice-9 match)) | ||
| 24 | |||
| 25 | (define %nixpkgs-directory | ||
| 26 | (getenv "NIXPKGS")) | ||
| 27 | |||
| 28 | (define factorize-uri | ||
| 29 | (@@ (guix import snix) factorize-uri)) | ||
| 30 | |||
| 31 | (define-syntax-rule (every? proc lists ...) | ||
| 32 | (not (not (every proc lists ...)))) | ||
| 33 | |||
| 34 | (test-begin "snix") | ||
| 35 | |||
| 36 | (test-assert "factorize-uri" | ||
| 37 | (every? (match-lambda | ||
| 38 | ((uri version '-> expected) | ||
| 39 | (equal? (factorize-uri uri version) | ||
| 40 | expected))) | ||
| 41 | '(("http://example.com/foo.tgz" "1.0" | ||
| 42 | -> "http://example.com/foo.tgz") | ||
| 43 | ("http://example.com/foo-2.8.tgz" "2.8" | ||
| 44 | -> ("http://example.com/foo-" version ".tgz")) | ||
| 45 | ("http://example.com/2.8/foo-2.8.tgz" "2.8" | ||
| 46 | -> ("http://example.com/" version "/foo-" version ".tgz"))))) | ||
| 47 | |||
| 48 | (test-skip (if (and %nixpkgs-directory | ||
| 49 | (file-exists? (string-append %nixpkgs-directory | ||
| 50 | "/default.nix"))) | ||
| 51 | 0 | ||
| 52 | 1)) | ||
| 53 | |||
| 54 | (test-assert "nixpkgs->guix-package" | ||
| 55 | (match (nixpkgs->guix-package %nixpkgs-directory "guile") | ||
| 56 | (('package | ||
| 57 | ('name "guile") | ||
| 58 | ('version (? string?)) | ||
| 59 | ('source ('origin _ ...)) | ||
| 60 | ('build-system _) | ||
| 61 | ('inputs ('quasiquote (inputs ...))) | ||
| 62 | ('propagated-inputs ('quasiquote (pinputs ...))) | ||
| 63 | ('home-page (? string?)) | ||
| 64 | ('synopsis (? string?)) | ||
| 65 | ('description (? string?)) | ||
| 66 | ('license (? symbol?))) | ||
| 67 | (and (member '("libffi" ,libffi) inputs) | ||
| 68 | (member '("gmp" ,gmp) pinputs) | ||
| 69 | #t)) | ||
| 70 | (x | ||
| 71 | (pk 'fail x #f)))) | ||
| 72 | |||
| 73 | (test-end "snix") | ||
