From patchwork Thu May 27 12:48:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Xinglu Chen X-Patchwork-Id: 29622 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id E267527BC81; Thu, 27 May 2021 14:12:50 +0100 (BST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS, T_DKIM_INVALID,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.2 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id 8B38827BC78 for ; Thu, 27 May 2021 14:12:49 +0100 (BST) Received: from localhost ([::1]:56072 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lmFoe-0002zo-L6 for patchwork@mira.cbaines.net; Thu, 27 May 2021 09:12:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35410) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lmFRj-0006tZ-Lk for guix-patches@gnu.org; Thu, 27 May 2021 08:49:08 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:39318) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lmFRe-0004ap-Ns for guix-patches@gnu.org; Thu, 27 May 2021 08:49:03 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1lmFRe-0006V2-JS for guix-patches@gnu.org; Thu, 27 May 2021 08:49:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#48697] [PATCH] import: Add CHICKEN egg importer. Resent-From: Xinglu Chen Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Thu, 27 May 2021 12:49:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 48697 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 48697@debbugs.gnu.org Cc: raingloom X-Debbugs-Original-To: guix-patches@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.162211973424967 (code B ref -1); Thu, 27 May 2021 12:49:02 +0000 Received: (at submit) by debbugs.gnu.org; 27 May 2021 12:48:54 +0000 Received: from localhost ([127.0.0.1]:50864 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lmFRU-0006Uc-La for submit@debbugs.gnu.org; Thu, 27 May 2021 08:48:53 -0400 Received: from lists.gnu.org ([209.51.188.17]:54362) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lmFRS-0006UT-40 for submit@debbugs.gnu.org; Thu, 27 May 2021 08:48:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35366) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lmFRO-0006o8-Gq for guix-patches@gnu.org; Thu, 27 May 2021 08:48:47 -0400 Received: from h87-96-130-155.cust.a3fiber.se ([87.96.130.155]:45932 helo=mail.yoctocell.xyz) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lmFRG-0004Of-Oe for guix-patches@gnu.org; Thu, 27 May 2021 08:48:43 -0400 From: Xinglu Chen DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=yoctocell.xyz; s=mail; t=1622119711; bh=pMI0Zk6pmdgMLyji5MXuyKAisFM7LLEc/zjjXN31Zxw=; h=From:To:Cc:Subject:Date; b=bKmE7NUKlZgfwwiIZvY/6ptVcHKsoIduAbYkpGZXhA9OpIfTNRV+4+xX29Dx+16Tv H9MdUwByHxvghL9BVg5v1klDhV9I2exqF0Y6eYVFpDXDufnksk12QTCvBC6IYLyMIb Dh/rSVqUfWa2henK+eJXEXsDZRJ8HSWjZNk1z8MY= Message-Id: Date: Thu, 27 May 2021 14:48:30 +0200 MIME-Version: 1.0 Received-SPF: pass client-ip=87.96.130.155; envelope-from=public@yoctocell.xyz; helo=mail.yoctocell.xyz X-Spam_score_int: 34 X-Spam_score: 3.4 X-Spam_bar: +++ X-Spam_report: (3.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FROM_SUSPICIOUS_NTLD=0.499, FROM_SUSPICIOUS_NTLD_FP=1.999, PDS_OTHER_BAD_TLD=1.999, RDNS_DYNAMIC=0.982, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: "Guix-patches" X-getmail-retrieved-from-mailbox: Patches * guix/import/egg.scm: New file. * guix/scripts/import/egg.scm: New file. * tests/egg.scm: New file. * Makefile.am (MODULES, SCM_TESTS): Register them. * guix/scripts/import.scm (importers): Add egg importer. * doc/guix.texi (Invoking guix import, Invoking guix refresh): Document it. --- [ Cc’ing raingloom since you wrote the CHICKEN build system ] This patch adds recursive importer for CHICKEN eggs, the generated packages aren’t entirely complete, though. It gets information from The PACKAGE.egg, which is just a Scheme file that contains a list of lists that specify the metadata for an egg. However, it doesn’t specify a description, so I have just set the ‘description’ field to #f for now. The licensing policy for eggs is also a bit vague[1], there is no strict naming format for licenses, and a lot of eggs just specify ‘BSD’ rather than ‘BSD-N-Clause’. The PACKAGE.egg file can also specify system dependencies, but there is no consistent format for this, sometimes strings are used, other times symbols are used, and sometimes the version of the package is also included. The user will have to double check the names and make sure they are correct. I am also unsure about whether the system dependencies should be ‘propagated-inputs’ or just ‘inputs’. [1]: https://wiki.call-cc.org/eggs-licensing Try it out! --8<---------------cut here---------------start------------->8--- ~/src/guix $ ./pre-inst-env guix import egg -r medea Starting download of /tmp/guix-file.nFumLb From https://code.call-cc.org/egg-tarballs/5/medea/medea-4.tar.gz... medea-4.tar.gz 7KiB 162KiB/s 00:00 [##################] 100.0% Starting download of /tmp/guix-file.8QWL6a From https://code.call-cc.org/egg-tarballs/5/comparse/comparse-3.tar.gz... …-3.tar.gz 7KiB 203KiB/s 00:00 [##################] 100.0% Starting download of /tmp/guix-file.hZPs19 From https://code.call-cc.org/egg-tarballs/5/srfi-13/srfi-13-0.3.1.tar.gz... …3.1.tar.gz 28KiB 328KiB/s 00:00 [##################] 100.0% Starting download of /tmp/guix-file.VMAPo7 From https://code.call-cc.org/egg-tarballs/5/lazy-seq/lazy-seq-2.tar.gz... …-2.tar.gz 3KiB 158KiB/s 00:00 [##################] 100.0% Starting download of /tmp/guix-file.6LM9K7 From https://code.call-cc.org/egg-tarballs/5/trie/trie-2.tar.gz... trie-2.tar.gz 1KiB 1.5MiB/s 00:00 [##################] 100.0% Starting download of /tmp/guix-file.8Yn8L7 From https://code.call-cc.org/egg-tarballs/5/matchable/matchable-1.1.tar.gz... …1.1.tar.gz 14KiB 370KiB/s 00:00 [##################] 100.0% (define-public chicken-srfi-13 (package (name "chicken-srfi-13") (version "0.3.1") (source (origin (method url-fetch) (uri "https://code.call-cc.org/egg-tarballs/5/srfi-13/srfi-13-0.3.1.tar.gz") (sha256 (base32 "1430grdp9d13rjp7asn5cs7cbcllbv89g49gx95zqlp07y9df6dm")))) (build-system chicken-build-system) (arguments `(#:egg-name "srfi-13")) (native-inputs `(("chicken-test" ,chicken-test))) (propagated-inputs `(("chicken-srfi-14" ,chicken-srfi-14))) (home-page "https://api.call-cc.org/5/doc/srfi-13") (synopsis "SRFI-13 string library") (description #f) (license license:bsd?))) [...] (define-public chicken-medea (package (name "chicken-medea") (version "4") (source (origin (method url-fetch) (uri "https://code.call-cc.org/egg-tarballs/5/medea/medea-4.tar.gz") (sha256 (base32 "1ad7x1sziynjjgxiv70ghbabc1mwa15mdx38wazfzn3nl7ma1hm6")))) (build-system chicken-build-system) (arguments `(#:egg-name "medea")) (native-inputs `(("chicken-test" ,chicken-test))) (propagated-inputs `(("chicken-comparse" ,chicken-comparse) ("chicken-srfi-1" ,chicken-srfi-1) ("chicken-srfi-13" ,chicken-srfi-13) ("chicken-srfi-14" ,chicken-srfi-14) ("chicken-srfi-69" ,chicken-srfi-69))) (home-page "https://api.call-cc.org/5/doc/medea") (synopsis "A JSON parser (and emitter) built with comparse") (description #f) (license license:bsd?))) --8<---------------cut here---------------end--------------->8--- Makefile.am | 3 + doc/guix.texi | 24 +++ guix/import/egg.scm | 363 ++++++++++++++++++++++++++++++++++++ guix/scripts/import.scm | 4 +- guix/scripts/import/egg.scm | 107 +++++++++++ tests/egg.scm | 90 +++++++++ 6 files changed, 589 insertions(+), 2 deletions(-) create mode 100644 guix/import/egg.scm create mode 100644 guix/scripts/import/egg.scm create mode 100644 tests/egg.scm base-commit: 23ab7067f32495a8a02710c08b7cfe0e21be7f3f diff --git a/Makefile.am b/Makefile.am index 8db7d6a320..3e72c3ebd0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -248,6 +248,7 @@ MODULES = \ guix/import/cpan.scm \ guix/import/cran.scm \ guix/import/crate.scm \ + guix/import/egg.scm \ guix/import/elpa.scm \ guix/import/gem.scm \ guix/import/github.scm \ @@ -293,6 +294,7 @@ MODULES = \ guix/scripts/challenge.scm \ guix/scripts/import/crate.scm \ guix/scripts/import/cran.scm \ + guix/scripts/import/egg.scm \ guix/scripts/import/elpa.scm \ guix/scripts/import/gem.scm \ guix/scripts/import/gnu.scm \ @@ -449,6 +451,7 @@ SCM_TESTS = \ tests/debug-link.scm \ tests/derivations.scm \ tests/discovery.scm \ + tests/egg.scm \ tests/elpa.scm \ tests/file-systems.scm \ tests/gem.scm \ diff --git a/doc/guix.texi b/doc/guix.texi index e8b0485f78..6a38ff707f 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -11594,6 +11594,28 @@ using this mode, the symbol of the package is made by appending the version to its name, so that multiple versions of the same package can coexist. @end table + +@item egg +@cindex egg +Import metadata for @uref{https://wiki.call-cc.org/eggs, CHICKEN eggs}. +The information is taken from @file{PACKAGE.egg} files found in the +@uref{git://code.call-cc.org/eggs-5-latest, eggs-5-latest} Git +repository. However, it does not provide all the information that we +need, there is no ``description'' field, and the licenses used are not +always precise (BSD is often used instead of BSD-N). + +@example +guix import egg sourcehut +@end example + +Additional options include: +@table @code +@item --recursive +@itemx -r +Traverse the dependency graph of the given upstream package recursively +and generate package expressions for all those packages that are not yet +in Guix. +@end table @end table The structure of the @command{guix import} code is modular. It would be @@ -11748,6 +11770,8 @@ the updater for KDE packages; the updater for X.org packages; @item kernel.org the updater for packages hosted on kernel.org; +@item egg +the updater for @uref{https://wiki.call-cc.org/eggs/, Egg} packages; @item elpa the updater for @uref{https://elpa.gnu.org/, ELPA} packages; @item cran diff --git a/guix/import/egg.scm b/guix/import/egg.scm new file mode 100644 index 0000000000..eb342dac32 --- /dev/null +++ b/guix/import/egg.scm @@ -0,0 +1,363 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2021 Xinglu Chen +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix import egg) + #:use-module (ice-9 ftw) + #:use-module (ice-9 match) + #:use-module (ice-9 string-fun) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (web uri) + #:use-module (sxml simple) + #:use-module ((sxml xpath) #:hide (filter)) + #:use-module (gcrypt hash) + #:use-module (guix git) + #:use-module (guix i18n) + #:use-module (guix http-client) + #:use-module (guix base32) + #:use-module (guix memoization) + #:use-module (guix packages) + #:use-module (guix upstream) + #:use-module (guix build-system) + #:use-module (guix store) + #:use-module ((guix download) #:select (download-to-store url-fetch)) + #:use-module (guix import utils) + #:use-module ((guix licenses) #:prefix license:) + #:export (egg->guix-package + egg-recursive-import + %egg-updater + + guix-package->egg-name)) + +;;; Commentary: +;;; +;;; (guix import egg) provides package importer for CHICKEN eggs. See the +;;; official specification format for eggs +;;; . +;;; +;;; The following happens under the hood: +;;; +;;; * is a Git repository that contains +;;; the latest version of all CHICKEN eggs. We look clone this repository +;;; and retrieve the latest version number, and the PACKAGE.egg file, which +;;; contains a list of lists containing metadata about the egg. +;;; +;;; * All the eggs are stored as tarballs at +;;; , so we grab the tarball for +;;; the egg from there. +;;; +;;; * The rest of the package fields will be parsed from the PACKAGE.egg file. +;;; +;;; Todos: +;;; +;;; * Support for CHICKEN 4? +;;; +;;; * Some packages will specify a specific version of a depencency in the +;;; PACKAGE.egg file, how should we handle this? +;;; +;;; Code: + + +;;; +;;; Egg metadata fetcher and helper functions. +;;; + +(define package-name-prefix "chicken-") + +(define %eggs-url + (make-parameter "https://code.call-cc.org/egg-tarballs/5")) + +(define %eggs-home-page + (make-parameter "https://api.call-cc.org/5/doc")) + +(define (egg-source-url name version) + "Return the URL to the source tarball for version VERSION of the CHICKEN egg +NAME." + (string-append (%eggs-url) "/" name "/" name "-" version ".tar.gz")) + +(define (egg-name->guix-name name) + "Return the package name for CHICKEN egg NAME." + (string-append package-name-prefix name)) + +(define (get-eggs-repository) + "Update or fetch the latest version of the eggs repository and return the path +to the repository." + (let*-values (((url) "git://code.call-cc.org/eggs-5-latest") + ((directory commit _) + (update-cached-checkout url))) + directory)) + +(define (egg-directory name) + "Return the directory containing the source code for the egg NAME." + (let ((eggs-directory (get-eggs-repository))) + (string-append eggs-directory "/" name))) + +(define (find-latest-version name) + "Get the latest version of the egg NAME." + (let ((directory (scandir (egg-directory name)))) + (if directory + (last directory) + (begin + (format #t (G_ "Package not found in eggs repository: ~a~%") name) + #f)))) + +(define (get-metadata port) + "Parse the egg metadata from PORT." + (let ((content (read port))) + (close-port port) + content)) + +(define (egg-metadata name) + "Return the package metadata file for the egg NAME." + (let ((version (find-latest-version name))) + (if version + (get-metadata (open-file + (string-append (egg-directory name) "/" + version "/" name ".egg") + "r")) + #f))) + +(define (guix-name->egg-name name) + "Return the CHICKEN egg name corresponding to the Guix package NAME." + (if (string-prefix? package-name-prefix name) + (substring name (string-length package-name-prefix)) + name)) + +(define (guix-package->egg-name package) + "Return the CHICKEN egg name of the Guix CHICKEN PACKAGE." + (let ((upstream-name (assoc-ref + (package-properties package) + 'upstream-name)) + (name (package-name package))) + (if upstream-name + upstream-name + (guix-name->egg-name name)))) + +(define (egg-package? package) + "Check if PACKAGE is an CHICKEN egg package." + (and (eq? (build-system-name (package-build-system package)) 'chicken) + (string-prefix? package-name-prefix (package-name package)))) + +(define string->license + ;; Doesn't seem to use a specific format. + ;; + (match-lambda + ("GPL-2" 'license:gpl2) + ("GPL-3" 'license:gpl3) + ("GPL" 'license:gpl?) + ("AGPL-3" 'license:agpl3) + ("AGPL" 'license:agpl?) + ("LGPL-2.1" 'license:lgpl2.1) + ("LGPL-3" 'license:lgpl3) + ("LGPL" 'license:lgpl?) + ("BSD-2" 'license:bsd-2) + ("BSD-3" 'license:bsd-3) + ("BSD" 'license:bsd?) + ("MIT" 'license:expat) + ("ISC" 'license:isc) + ("Artistic-2" 'license:artistic2.0) + ("Apache-2.0" 'license:asl2.0) + ("Public Domain" 'license:public-domain) + ((x) (string->license x)) + ((lst ...) `(list ,@(map string->license lst))) + (_ #f))) + + +;;; +;;; Egg importer. +;;; + +(define* (egg->guix-package name #:key (port #f) (source #f)) + "Import CHICKEN egg NAME from and return a @code{} record type for +the egg, or @code{#f} on failure. PORT is the port for the NAME.egg to read +from. SOURCE is the a ``file-like'' object containing the source code +corresonding to the egg. If SOURCE is not specified, the tarball for the egg +will be downloaded. + +Specifying the SOURCE argument is mainly useful for developing a CHICKEN egg +locally. Note that if PORT and SOURCE are specified, +recursive import will not work." + (define egg-content (if port + (get-metadata port) + (egg-metadata name))) + (if (not egg-content) + (values #f '()) ; egg doesn't exist + (let* ((version* (or (assoc-ref egg-content 'version) + (find-latest-version name))) + (version (if (list? version*) (first version*) version*)) + (source-url (if source #f (egg-source-url name version))) + (tarball (if source + #f + (with-store store + (download-to-store store source-url))))) + + (define (safe-append lst1 lst2) + (match (list lst1 lst2) + ((#f #f) #f) + ((lst1 #f) lst1) + ((#f lst2) lst2) + (_ (append lst1 lst2)))) + + (define egg-home-page + (string-append (%eggs-home-page) "/" name)) + + (define egg-synopsis + (let ((synopsis (assoc-ref egg-content 'synopsis))) + (if (list? synopsis) + (first synopsis) + #f))) + + (define egg-license + (let ((license (assoc-ref egg-content 'license))) + (if (list? license) + ;; Multiple licenses are separated by `/'. + (string->license (string-split (first license) #\/)) + #f))) + + (define (prettify-system-dependency name) + (let ((name* (if (symbol? name) + (symbol->string name) + name))) + ;; System dependecies sometimes have spaces and/or upper case + ;; letters in them. + ;; + ;; There will probably still be some weird edge cases. + (string-replace-substring (string-downcase name*) " " ""))) + + (define (maybe-string->symbol str) + (if (string? str) (string->symbol string) str)) + + (define (maybe-symbol->string sym) + (if (symbol? sym) (symbol->string sym) sym)) + + (define* (egg-parse-dependency name #:key (system? #f)) + (let* ((name* (if (list? name) + (first name) ; (name version) + name)) + (name (if system? + (prettify-system-dependency name*) + (maybe-symbol->string name*)))) + ;; Dependencies are sometimes specified as symbols and sometimes + ;; as strings + (list (string-append (if system? "" package-name-prefix) + name) + (list 'unquote + (string->symbol (string-append + (if system? "" package-name-prefix) + name)))))) + + (define egg-propagated-inputs + (let ((dependencies (assoc-ref egg-content 'dependencies))) + (if (list? dependencies) + (map egg-parse-dependency + dependencies) + '()))) + + ;; TODO: Or should these be propagated? + (define egg-inputs + (let ((dependencies (assoc-ref egg-content 'foreign-dependencies))) + (if (list? dependencies) + (map (lambda (name) + (egg-parse-dependency name #:system? #t)) + dependencies) + '()))) + + (define egg-native-inputs + (let* ((test-dependencies (assoc-ref egg-content + 'test-dependencies)) + (build-dependencies (assoc-ref egg-content + 'build-dependencies)) + (test+build-dependencies (safe-append + test-dependencies + build-dependencies))) + (if (list? test+build-dependencies) + (map egg-parse-dependency + test+build-dependencies) + '()))) + + ;; Copied from (guix import hackage). + (define (maybe-inputs input-type inputs) + (match inputs + (() + '()) + ((inputs ...) + (list (list input-type + (list 'quasiquote inputs)))))) + + (values + `(package + (name ,(egg-name->guix-name name)) + (version ,version) + (source + ,(if source + source + `(origin + (method url-fetch) + (uri ,source-url) + (sha256 + (base32 ,(if tarball + (bytevector->nix-base32-string + (file-sha256 tarball)) + "failed to download tar archive")))))) + (build-system chicken-build-system) + (arguments ,(list 'quasiquote (list #:egg-name name))) + ,@(maybe-inputs 'native-inputs egg-native-inputs) + ,@(maybe-inputs 'inputs egg-inputs) + ,@(maybe-inputs 'propagated-inputs egg-propagated-inputs) + (home-page ,egg-home-page) + (synopsis ,egg-synopsis) + (description #f) + (license ,egg-license)) + (filter (lambda (name) + (not (member name '("srfi-4")))) + (map (compose guix-name->egg-name first) + (append egg-propagated-inputs + egg-native-inputs))))))) + +(define egg->guix-package/m ;memoized variant + (memoize egg->guix-package)) + +(define (egg-recursive-import package-name) + (recursive-import package-name + #:repo->guix-package (lambda* (name #:key version repo) + (egg->guix-package/m name)) + #:guix-name egg-name->guix-name)) + + +;;; +;;; Updater. +;;; + +(define (latest-release package) + "Return an @code{} for the latest release of PACKAGE." + (let* ((egg-name (guix-package->egg-name package)) + (version (find-latest-version egg-name)) + (source-url (egg-source-url egg-name version))) + (upstream-source + (package (package-name package)) + (version version) + (urls (list source-url))))) + +(define %egg-updater + (upstream-updater + (name 'egg) + (description "Updater for CHICKEN egg packages") + (pred egg-package?) + (latest latest-release))) + +;;; egg.scm ends here diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm index bbd9a3b190..f53d1ac1f4 100644 --- a/guix/scripts/import.scm +++ b/guix/scripts/import.scm @@ -76,8 +76,8 @@ rather than \\n." ;;; Entry point. ;;; -(define importers '("gnu" "pypi" "cpan" "hackage" "stackage" "elpa" "gem" - "go" "cran" "crate" "texlive" "json" "opam")) +(define importers '("gnu" "pypi" "cpan" "hackage" "stackage" "egg" "elpa" + "gem" "go" "cran" "crate" "texlive" "json" "opam")) (define (resolve-importer name) (let ((module (resolve-interface diff --git a/guix/scripts/import/egg.scm b/guix/scripts/import/egg.scm new file mode 100644 index 0000000000..7dbd6fcd5a --- /dev/null +++ b/guix/scripts/import/egg.scm @@ -0,0 +1,107 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2021 Xinglu Chen +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix scripts import egg) + #:use-module (guix ui) + #:use-module (guix utils) + #:use-module (guix scripts) + #:use-module (guix import egg) + #:use-module (guix scripts import) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-37) + #:use-module (ice-9 match) + #:use-module (ice-9 format) + #:export (guix-import-egg)) + + +;;; +;;; Command-line options. +;;; + +(define %default-options + '()) + +(define (show-help) + (display (G_ "Usage: guix import egg PACKAGE-NAME +Import and convert the egg package for PACKAGE-NAME.\n")) + (display (G_ " + -h, --help display this help and exit")) + (display (G_ " + -r, --recursive import packages recursively")) + (display (G_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + +(define %options + ;; Specification of the command-line options. + (cons* (option '(#\h "help") #f #f + (lambda args + (show-help) + (exit 0))) + (option '(#\V "version") #f #f + (lambda args + (show-version-and-exit "guix import egg"))) + (option '(#\r "recursive") #f #f + (lambda (opt name arg result) + (alist-cons 'recursive #t result))) + %standard-import-options)) + + +;;; +;;; Entry point. +;;; + +(define (guix-import-egg . args) + (define (parse-options) + ;; Return the alist of option values. + (args-fold* args %options + (lambda (opt name arg result) + (leave (G_ "~A: unrecognized option~%") name)) + (lambda (arg result) + (alist-cons 'argument arg result)) + %default-options)) + + (let* ((opts (parse-options)) + (repo (and=> (assoc-ref opts 'repo) string->symbol)) + (args (filter-map (match-lambda + (('argument . value) + value) + (_ #f)) + (reverse opts)))) + (match args + ((package-name) + (if (assoc-ref opts 'recursive) + ;; Recursive import + (map (match-lambda + ((and ('package ('name name) . rest) pkg) + `(define-public ,(string->symbol name) + ,pkg)) + (_ #f)) + (egg-recursive-import package-name)) + ;; Single import + (let ((sexp (egg->guix-package package-name))) + (unless sexp + (leave (G_ "failed to download meta-data for package '~a'~%") + package-name)) + sexp))) + (() + (leave (G_ "too few arguments~%"))) + ((many ...) + (leave (G_ "too many arguments~%")))))) diff --git a/tests/egg.scm b/tests/egg.scm new file mode 100644 index 0000000000..b853f777c4 --- /dev/null +++ b/tests/egg.scm @@ -0,0 +1,90 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2021 Xinglu Chen +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (test-eggs) + #:use-module (guix import egg) + #:use-module (guix gexp) + #:use-module (guix base32) + #:use-module (gcrypt hash) + #:use-module (guix tests) + #:use-module ((guix build syscalls) #:select (mkdtemp!)) + #:use-module ((guix build utils) #:select (delete-file-recursively mkdir-p which)) + #:use-module ((guix utils) #:select (call-with-temporary-output-file)) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-64) + #:use-module (web uri) + #:use-module (ice-9 match)) + +(define test-egg-1 + "((synopsis \"Example egg\") + (license \"GPL-3/MIT\") + (version \"1.0.0\") + (test-dependencies test srfi-1) + (foreign-dependencies libgit2) + (build-dependencies begin-syntax) + (dependencies datatype) + (author \"John Doe\"))") + +(test-begin "egg") + +(test-equal "guix-package->egg-name" + "bar" + (guix-package->egg-name + (dummy-package "dummy" + (name "chicken-bar")))) + +;; Copied from tests/hackage.scm +(define-syntax-rule (define-package-matcher name pattern) + (define* (name obj) + (match obj + (pattern #t) + (x (pk 'fail x #f))))) + +(define (eval-test-with-egg-file egg-test matcher) + (define port (open-input-string egg-test)) + (matcher (egg->guix-package "foo" + #:port port + #:source (plain-file "foo-egg" "content")))) + +(define-package-matcher match-chicken-foo + ('package + ('name "chicken-foo") + ('version "1.0.0") + ('source (? file-like? source)) + ('build-system 'chicken-build-system) + ('arguments ('quasiquote ('#:egg-name "foo"))) + ('native-inputs + ('quasiquote + (("chicken-test" ('unquote chicken-test)) + ("chicken-srfi-1" ('unquote chicken-srfi-1)) + ("chicken-begin-syntax" ('unquote chicken-begin-syntax))))) + ('inputs + ('quasiquote + (("libgit2" ('unquote libgit2))))) + ('propagated-inputs + ('quasiquote + (("chicken-datatype" ('unquote chicken-datatype))))) + ('home-page "https://api.call-cc.org/5/doc/foo") + ('synopsis "Example egg") + ('description #f) + ('license (list 'license:gpl3 'license:expat)))) + +(test-assert "egg->guix-package local file" + (eval-test-with-egg-file test-egg-1 match-chicken-foo)) + +(test-end "egg")