[PATCH] Add composer build system (PHP)

  • Open
  • quality assurance status badge
Details
10 participants
  • Adam Faiz
  • Charlie McMackin
  • db
  • Julien Lepiller
  • Ludovic Courtès
  • Maxim Cournoyer
  • Maxime Devos
  • Mája Tomášek
  • Nicolas Graves
  • Wilko Meyer
Owner
unassigned
Submitted by
Julien Lepiller
Severity
normal
J
J
Julien Lepiller wrote on 13 Jul 2020 00:20
(address . guix-patches@gnu.org)
20200713002055.1553f136@tachikoma.lepiller.eu
Hi Guix!

This patch series adds the composer-build-system, along with an
importer and an updater (first 3 patches).

The patch series also adds some php packages for phpunit and its
dependencies.

The patches are available in my composer branch at
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 01/34] guix: import: Add composer importer.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-1-julien@lepiller.eu
* guix/import/composer.scm: New file.
* guix/scripts/import/composer.scm: New file.
* Makefile.am: Add them.
* guix/scripts/import.scm: Add composer importer.
---
Makefile.am | 2 +
guix/import/composer.scm | 252 +++++++++++++++++++++++++++++++
guix/scripts/import.scm | 2 +-
guix/scripts/import/composer.scm | 107 +++++++++++++
4 files changed, 362 insertions(+), 1 deletion(-)
create mode 100644 guix/import/composer.scm
create mode 100644 guix/scripts/import/composer.scm

Toggle diff (406 lines)
diff --git a/Makefile.am b/Makefile.am
index 20d43cd130..623ddf32b2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -219,6 +219,7 @@ MODULES = \
guix/search-paths.scm \
guix/packages.scm \
guix/import/cabal.scm \
+ guix/import/composer.scm \
guix/import/cpan.scm \
guix/import/cran.scm \
guix/import/crate.scm \
@@ -265,6 +266,7 @@ MODULES = \
guix/scripts/system/reconfigure.scm \
guix/scripts/lint.scm \
guix/scripts/challenge.scm \
+ guix/scripts/import/composer.scm \
guix/scripts/import/crate.scm \
guix/scripts/import/cran.scm \
guix/scripts/import/elpa.scm \
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
new file mode 100644
index 0000000000..0e17eb0487
--- /dev/null
+++ b/guix/import/composer.scm
@@ -0,0 +1,252 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix import composer)
+ #:use-module (ice-9 match)
+ #:use-module (json)
+ #:use-module (gcrypt hash)
+ #:use-module (guix base32)
+ #:use-module (guix build git)
+ #:use-module (guix build utils)
+ #:use-module (guix build-system)
+ #:use-module (guix import json)
+ #:use-module (guix import utils)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (guix packages)
+ #:use-module (guix serialization)
+ #:use-module (guix upstream)
+ #:use-module (guix utils)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-11)
+ #:export (composer->guix-package
+ %composer-updater
+ composer-recursive-import))
+
+;; XXX adapted from (guix scripts hash)
+(define (file-hash file select? recursive?)
+ ;; Compute the hash of FILE.
+ (if recursive?
+ (let-values (((port get-hash) (open-sha256-port)))
+ (write-file file port #:select? select?)
+ (force-output port)
+ (get-hash))
+ (call-with-input-file file port-sha256)))
+
+;; XXX taken from (guix scripts hash)
+(define (vcs-file? file stat)
+ (case (stat:type stat)
+ ((directory)
+ (member (basename file) '(".bzr" ".git" ".hg" ".svn" "CVS")))
+ ((regular)
+ ;; Git sub-modules have a '.git' file that is a regular text file.
+ (string=? (basename file) ".git"))
+ (else
+ #f)))
+
+(define (latest-version versions)
+ (fold (lambda (a b) (if (version>? a b) a b)) (car versions) versions))
+
+(define (fix-version version)
+ "Return a fixed version from a version string. For instance, v10.1 -> 10.1"
+ (cond
+ ((string-prefix? "version" version)
+ (if (char-set-contains? char-set:digit (string-ref version 7))
+ (substring version 7)
+ (substring version 8)))
+ ((string-prefix? "v" version)
+ (substring version 1))
+ (else version)))
+
+(define* (composer-fetch name #:optional version)
+ "Return an alist representation of the Composer metadata for the package NAME,
+or #f on failure."
+ (let ((package (json-fetch
+ (string-append "https://repo.packagist.org/p/" name ".json"))))
+ (if package
+ (let* ((packages (assoc-ref package "packages"))
+ (package (assoc-ref packages name))
+ (versions (filter
+ (lambda (version)
+ (and (not (string-contains version "dev"))
+ (not (string-contains version "beta"))))
+ (map car package)))
+ (versions (map
+ (lambda (version)
+ (cons (fix-version version) version))
+ versions))
+ (version (or (if (null? version) #f version)
+ (latest-version (map car versions)))))
+ (assoc-ref package (assoc-ref versions version)))
+ #f)))
+
+(define (php-package-name name)
+ "Given the NAME of a package on Packagist, return a Guix-compliant name for
+the package."
+ (let ((name (string-join (string-split name #\/) "-")))
+ (if (string-prefix? "php-" name)
+ (snake-case name)
+ (string-append "php-" (snake-case name)))))
+
+(define (make-php-sexp name version home-page description dependencies
+ dev-dependencies licenses source)
+ "Return the `package' s-expression for a PHP package with the given NAME,
+VERSION, HOME-PAGE, DESCRIPTION, DEPENDENCIES, LICENSES and SOURCE."
+ (let ((git? (equal? (assoc-ref source "type") "git")))
+ ((if git? call-with-temporary-directory call-with-temporary-output-file)
+ (lambda* (temp #:optional port)
+ (and (if git?
+ (begin
+ (mkdir-p temp)
+ (git-fetch (assoc-ref source "url")
+ (assoc-ref source "reference")
+ temp))
+ (url-fetch (assoc-ref source "url") temp))
+ `(package
+ (name ,(php-package-name name))
+ (version ,version)
+ (source (origin
+ ,@(if git?
+ `((method git-fetch)
+ (uri (git-reference
+ (url ,(assoc-ref source "url"))
+ (commit ,(assoc-ref source "reference"))))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ ,(bytevector->nix-base32-string
+ (file-hash temp (negate vcs-file?) #t)))))
+ `((method url-fetch)
+ (uri ,(assoc-ref source "url"))
+ (sha256 (base32 ,(guix-hash-url temp)))))))
+ (build-system composer-build-system)
+ ,@(if (null? dependencies)
+ '()
+ `((inputs
+ (,'quasiquote
+ ,(map (lambda (name)
+ `(,name
+ (,'unquote
+ ,(string->symbol name))))
+ dependencies)))))
+ ,@(if (null? dev-dependencies)
+ '()
+ `((native-inputs
+ (,'quasiquote
+ ,(map (lambda (name)
+ `(,name
+ (,'unquote
+ ,(string->symbol name))))
+ dev-dependencies)))))
+ (synopsis "")
+ (description ,description)
+ (home-page ,home-page)
+ (license ,(match licenses
+ (() #f)
+ ((license) (license->symbol license))
+ (_ `(list ,@(map license->symbol licenses)))))))))))
+
+(define* (composer->guix-package package-name #:optional version)
+ "Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
+`package' s-expression corresponding to that package, or #f on failure."
+ (let ((package (composer-fetch package-name version)))
+ (and package
+ (let* ((name (assoc-ref package "name"))
+ (version (fix-version (assoc-ref package "version")))
+ (description (beautify-description
+ (assoc-ref package "description")))
+ (home-page (assoc-ref package "homepage"))
+ (dependencies-names (filter
+ (lambda (dep)
+ (string-contains dep "/"))
+ (map car (assoc-ref package "require"))))
+ (dependencies (map php-package-name dependencies-names))
+ (require-dev (assoc-ref package "require-dev"))
+ (dev-dependencies-names
+ (if require-dev
+ (filter
+ (lambda (dep)
+ (string-contains dep "/"))
+ (map car require-dev))
+ '()))
+ (dev-dependencies (map php-package-name dev-dependencies-names))
+ (licenses (map string->license
+ (vector->list
+ (assoc-ref package "license")))))
+ (values (make-php-sexp name version home-page description dependencies
+ dev-dependencies licenses (assoc-ref package "source"))
+ (append dependencies-names dev-dependencies-names))))))
+
+(define (guix-name->composer-name name)
+ "Given a guix package name, return the name of the package in Packagist."
+ (if (string-prefix? "php-" name)
+ (let ((components (string-split (substring name 4) #\-)))
+ (match components
+ ((namespace name ...)
+ (string-append namespace "/" (string-join name "-")))))
+ name))
+
+(define (guix-package->composer-name package)
+ "Given a Composer PACKAGE built from Packagist, return the name of the
+package in Packagist."
+ (let ((upstream-name (assoc-ref
+ (package-properties package)
+ 'upstream-name))
+ (name (package-name package)))
+ (if upstream-name
+ upstream-name
+ (guix-name->composer-name name))))
+
+(define (string->license str)
+ "Convert the string STR into a license object."
+ (match str
+ ("GNU LGPL" license:lgpl2.0)
+ ("GPL" license:gpl3)
+ ((or "BSD" "BSD License" "BSD-3-Clause") license:bsd-3)
+ ((or "MIT" "MIT license" "Expat license") license:expat)
+ ("Public domain" license:public-domain)
+ ((or "Apache License, Version 2.0" "Apache 2.0") license:asl2.0)
+ (_ #f)))
+
+(define (php-package? package)
+ "Return true if PACKAGE is a PHP package from Packagist."
+ (and
+ (eq? (build-system-name (package-build-system package)) 'composer)
+ (string-prefix? "php-" (package-name package))))
+
+(define (latest-release package)
+ "Return an <upstream-source> for the latest release of PACKAGE."
+ (let* ((php-name (guix-package->composer-name package))
+ (metadata (composer-fetch php-name))
+ (version (fix-version (assoc-ref metadata "version")))
+ (url (assoc-ref (assoc-ref metadata "source") "url")))
+ (upstream-source
+ (package (package-name package))
+ (version version)
+ (urls (list url)))))
+
+(define %composer-updater
+ (upstream-updater
+ (name 'composer)
+ (description "Updater for Composer packages")
+ (pred php-package?)
+ (latest latest-release)))
+
+(define* (composer-recursive-import package-name #:optional version)
+ (recursive-import package-name '()
+ #:repo->guix-package composer->guix-package
+ #:guix-name php-package-name))
diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm
index c6cc93fad8..4c91627283 100644
--- a/guix/scripts/import.scm
+++ b/guix/scripts/import.scm
@@ -76,7 +76,7 @@ rather than \\n."
;;;
(define importers '("gnu" "nix" "pypi" "cpan" "hackage" "stackage" "elpa" "gem"
- "cran" "crate" "texlive" "json" "opam"))
+ "cran" "crate" "texlive" "json" "opam" "composer"))
(define (resolve-importer name)
(let ((module (resolve-interface
diff --git a/guix/scripts/import/composer.scm b/guix/scripts/import/composer.scm
new file mode 100644
index 0000000000..412bae6318
--- /dev/null
+++ b/guix/scripts/import/composer.scm
@@ -0,0 +1,107 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2015 David Thompson <davet@gnu.org>
+;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix scripts import composer)
+ #:use-module (guix ui)
+ #:use-module (guix utils)
+ #:use-module (guix scripts)
+ #:use-module (guix import composer)
+ #:use-module (guix scripts import)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-11)
+ #:use-module (srfi srfi-37)
+ #:use-module (srfi srfi-41)
+ #:use-module (ice-9 match)
+ #:use-module (ice-9 format)
+ #:export (guix-import-composer))
+
+
+;;;
+;;; Command-line options.
+;;;
+
+(define %default-options
+ '())
+
+(define (show-help)
+ (display (G_ "Usage: guix import composer PACKAGE-NAME
+Import and convert the Composer package for PACKAGE-NAME.\n"))
+ (display (G_ "
+ -h, --help display this help and exit"))
+ (display (G_ "
+ -V, --version display version information and exit"))
+ (display (G_ "
+ -r, --recursive generate package expressions for all Composer packages\
+ that are not yet in Guix"))
+ (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 composer")))
+ (option '(#\r "recursive") #f #f
+ (lambda (opt name arg result)
+ (alist-cons 'recursive #t result)))
+ %standard-import-options))
+
+
+;;;
+;;; Entry point.
+;;;
+
+(define (guix-import-composer . 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))
+ (args (filter-map (match-lambda
+ (('argument . value)
+ value)
+ (_ #f))
+ (reverse opts))))
+ (match args
+ ((package-name)
+ (if (assoc-ref opts 'recursive)
+ (map (match-lambda
+ ((and ('package ('name name) . rest) pkg)
+ `(define-public ,(string->symbol name)
+ ,pkg))
+ (_ #f))
+ (composer-recursive-import package-name))
+ (let ((sexp (composer->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~%"))))))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 02/34] gnu: Add composer-classloader.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-2-julien@lepiller.eu
* gnu/packages/php-xyz.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
---
gnu/local.mk | 1 +
gnu/packages/php-xyz.scm | 61 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
create mode 100644 gnu/packages/php-xyz.scm

Toggle diff (81 lines)
diff --git a/gnu/local.mk b/gnu/local.mk
index 3046a840c9..90d1b1302b 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -424,6 +424,7 @@ GNU_SYSTEM_MODULES = \
%D%/packages/photo.scm \
%D%/packages/phabricator.scm \
%D%/packages/php.scm \
+ %D%/packages/php-xyz.scm \
%D%/packages/pkg-config.scm \
%D%/packages/plotutils.scm \
%D%/packages/poedit.scm \
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
new file mode 100644
index 0000000000..dab660f84f
--- /dev/null
+++ b/gnu/packages/php-xyz.scm
@@ -0,0 +1,61 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (gnu packages php-xyz)
+ #:use-module (gnu packages)
+ #:use-module (gnu packages php)
+ #:use-module (guix packages)
+ #:use-module (guix download)
+ #:use-module (guix git-download)
+ #:use-module (guix build-system composer)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix utils)
+ #:use-module ((guix licenses) #:prefix license:))
+
+(define-public composer-classloader
+ (package
+ (name "composer-classloader")
+ (version "1.9.0")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/composer/composer.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0127zmmg3yx84ljngfs86q7kjhyypybkf4d1ihfrfnzgynzxfxdf"))))
+ (build-system gnu-build-system)
+ (arguments
+ `(#:phases
+ (modify-phases %standard-phases
+ (delete 'configure)
+ (delete 'build)
+ (delete 'check)
+ (replace 'install
+ (lambda* (#:key outputs #:allow-other-keys)
+ (let* ((out (assoc-ref outputs "out"))
+ (install (string-append out "/share/web/composer/ClassLoader.php")))
+ (mkdir-p (dirname install))
+ (copy-file "src/Composer/Autoload/ClassLoader.php" install)))))))
+ (home-page "https://getcomposer.org")
+ (synopsis "PHP class loader extracted from the composer package")
+ (description "This package contains the class loader class used by Composer to
+build its autoloading feature. This package is used by the composer-build-system
+to build its own store-aware autoloading feature.")
+ (license license:expat)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 03/34] guix: Add composer-build-system.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-3-julien@lepiller.eu
* guix/build-system/composer.scm: New file.
* guix/build/composer-build-system.scm: New file.
* guix/build-system/findclass.php: New file.
* Makefile.am: Add them.
* doc/guix.texi (Build Systems): Document it.
---
Makefile.am | 2 +
doc/guix.texi | 14 ++
guix/build-system/composer.scm | 169 ++++++++++++++++++++
guix/build-system/findclass.php | 102 ++++++++++++
guix/build/composer-build-system.scm | 224 +++++++++++++++++++++++++++
5 files changed, 511 insertions(+)
create mode 100644 guix/build-system/composer.scm
create mode 100644 guix/build-system/findclass.php
create mode 100644 guix/build/composer-build-system.scm

Toggle diff (458 lines)
diff --git a/Makefile.am b/Makefile.am
index 623ddf32b2..363af872fa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -117,6 +117,7 @@ MODULES = \
guix/build-system/cargo.scm \
guix/build-system/clojure.scm \
guix/build-system/cmake.scm \
+ guix/build-system/composer.scm \
guix/build-system/dub.scm \
guix/build-system/dune.scm \
guix/build-system/emacs.scm \
@@ -164,6 +165,7 @@ MODULES = \
guix/build/cargo-build-system.scm \
guix/build/cargo-utils.scm \
guix/build/cmake-build-system.scm \
+ guix/build/composer-build-system.scm \
guix/build/dub-build-system.scm \
guix/build/dune-build-system.scm \
guix/build/emacs-build-system.scm \
diff --git a/doc/guix.texi b/doc/guix.texi
index 17338ed764..0613f669a0 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -6687,6 +6687,20 @@ debugging information''), which roughly means that code is compiled with
@code{-O2 -g}, as is the case for Autoconf-based packages by default.
@end defvr
+@defvr {Scheme Variable} composer-build-system
+This variable is exported by @code{(guix build-system composer)}. It
+implements the build procedure for packages using
+@url{https://getcomposer.org/, Composer}, the PHP package manager.
+
+It automatically adds the @code{php} package to the set of inputs. Which
+package is used can be specified with the @code{#:php} parameter.
+
+The @code{#:test-target} parameter is used to control which script is run
+for the tests. By default, the @code{test} script is run if it exists. If
+the script does not exist, the build system will run @code{phpunit} from the
+source directory, assuming there is a @file{phpunit.xml} file.
+@end defvr
+
@defvr {Scheme Variable} dune-build-system
This variable is exported by @code{(guix build-system dune)}. It
supports builds of packages using @uref{https://dune.build/, Dune}, a build
diff --git a/guix/build-system/composer.scm b/guix/build-system/composer.scm
new file mode 100644
index 0000000000..19455b1920
--- /dev/null
+++ b/guix/build-system/composer.scm
@@ -0,0 +1,169 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+(define-module (guix build-system composer)
+ #:use-module (guix store)
+ #:use-module (guix utils)
+ #:use-module (guix derivations)
+ #:use-module (guix search-paths)
+ #:use-module (guix build-system)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix gexp)
+ #:use-module (guix packages)
+ #:use-module (ice-9 match)
+ #:use-module (srfi srfi-1)
+ #:export (%composer-build-system-modules
+ lower
+ composer-build
+ composer-build-system))
+
+;; Commentary:
+;;
+;; Standard build procedure for PHP packages using Composer. This is implemented
+;; as an extension of `gnu-build-system'.
+;;
+;; Code:
+
+(define (default-php)
+ "Return the default PHP package."
+
+ ;; Do not use `@' to avoid introducing circular dependencies.
+ (let ((module (resolve-interface '(gnu packages php))))
+ (module-ref module 'php)))
+
+(define (default-findclass)
+ "Return the default findclass script."
+ (local-file (string-append (current-source-directory) "/findclass.php")))
+
+(define (default-composer-classloader)
+ "Return the default composer-classloader package."
+
+ ;; Do not use `@' to avoid introducing circular dependencies.
+ (let ((module (resolve-interface '(gnu packages php-xyz))))
+ (module-ref module 'composer-classloader)))
+
+(define %composer-build-system-modules
+ ;; Build-side modules imported by default.
+ `((guix build composer-build-system)
+ (guix build json)
+ (guix build union)
+ ,@%gnu-build-system-modules))
+
+(define* (lower name
+ #:key source inputs native-inputs outputs system target
+ (php (default-php))
+ (composer-classloader (default-composer-classloader))
+ (findclass (default-findclass))
+ #:allow-other-keys
+ #:rest arguments)
+ "Return a bag for NAME."
+ (define private-keywords
+ '(#:source #:target #:php #:composer-classloader #:findclass #:inputs #:native-inputs))
+
+ (and (not target) ;XXX: no cross-compilation
+ (bag
+ (name name)
+ (system system)
+ (host-inputs `(,@(if source
+ `(("source" ,source))
+ '())
+ ,@inputs
+
+ ;; Keep the standard inputs of 'gnu-build-system'.
+ ,@(standard-packages)))
+ (build-inputs `(("php" ,php)
+ ("findclass.php" ,findclass)
+ ("composer-classloader" ,composer-classloader)
+ ,@native-inputs))
+ (outputs outputs)
+ (build composer-build)
+ (arguments (strip-keyword-arguments private-keywords arguments)))))
+
+(define* (composer-build store name inputs
+ #:key (guile #f)
+ (outputs '("out")) (configure-flags ''())
+ (search-paths '())
+ (out-of-source? #t)
+ (composer-file "composer.json")
+ (tests? #t)
+ (test-target "test")
+ (install-target "install")
+ (validate-runpath? #t)
+ (patch-shebangs? #t)
+ (strip-binaries? #t)
+ (strip-flags ''("--strip-debug"))
+ (strip-directories ''("lib" "lib64" "libexec"
+ "bin" "sbin"))
+ (phases '(@ (guix build composer-build-system)
+ %standard-phases))
+ (system (%current-system))
+ (imported-modules %composer-build-system-modules)
+ (modules '((guix build composer-build-system)
+ (guix build json)
+ (guix build utils))))
+ "Build SOURCE using PHP, and with INPUTS. This assumes that SOURCE provides
+a 'composer.json' file as its build system."
+ (define builder
+ `(begin
+ (use-modules ,@modules)
+ (composer-build #:source ,(match (assoc-ref inputs "source")
+ (((? derivation? source))
+ (derivation->output-path source))
+ ((source)
+ source)
+ (source
+ source))
+ #:system ,system
+ #:outputs %outputs
+ #:inputs %build-inputs
+ #:search-paths ',(map search-path-specification->sexp
+ search-paths)
+ #:phases ,phases
+ #:out-of-source? ,out-of-source?
+ #:composer-file ,composer-file
+ #:tests? ,tests?
+ #:test-target ,test-target
+ #:install-target ,install-target
+ #:validate-runpath? ,validate-runpath?
+ #:patch-shebangs? ,patch-shebangs?
+ #:strip-binaries? ,strip-binaries?
+ #:strip-flags ,strip-flags
+ #:strip-directories ,strip-directories)))
+
+ (define guile-for-build
+ (match guile
+ ((? package?)
+ (package-derivation store guile system #:graft? #f))
+ (#f ; the default
+ (let* ((distro (resolve-interface '(gnu packages commencement)))
+ (guile (module-ref distro 'guile-final)))
+ (package-derivation store guile system #:graft? #f)))))
+
+ (build-expression->derivation store name builder
+ #:system system
+ #:inputs inputs
+ #:modules imported-modules
+ #:outputs outputs
+ #:guile-for-build guile-for-build))
+
+(define composer-build-system
+ (build-system
+ (name 'composer)
+ (description "The standard Composer build system")
+ (lower lower)))
+
+;;; composer.scm ends here
diff --git a/guix/build-system/findclass.php b/guix/build-system/findclass.php
new file mode 100644
index 0000000000..a9704f809c
--- /dev/null
+++ b/guix/build-system/findclass.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Extract the classes in the given file
+ *
+ * @param string $path The file to check
+ * @throws \RuntimeException
+ * @return array The found classes
+ */
+function findClasses($path)
+{
+ $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
+ if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
+ $extraTypes .= '|enum';
+ }
+ // Use @ here instead of Silencer to actively suppress 'unhelpful' output
+ // @link https://github.com/composer/composer/pull/4886
+ $contents = @php_strip_whitespace($path);
+ if (!$contents) {
+ if (!file_exists($path)) {
+ $message = 'File at "%s" does not exist, check your classmap definitions';
+ } elseif (!is_readable($path)) {
+ $message = 'File at "%s" is not readable, check its permissions';
+ } elseif ('' === trim(file_get_contents($path))) {
+ // The input file was really empty and thus contains no classes
+ return array();
+ } else {
+ $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
+ }
+ $error = error_get_last();
+ if (isset($error['message'])) {
+ $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
+ }
+ throw new \RuntimeException(sprintf($message, $path));
+ }
+ // return early if there is no chance of matching anything in this file
+ if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
+ return array();
+ }
+ // strip heredocs/nowdocs
+ $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
+ // strip strings
+ $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
+ // strip leading non-php code if needed
+ if (substr($contents, 0, 2) !== '<?') {
+ $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
+ if ($replacements === 0) {
+ return array();
+ }
+ }
+ // strip non-php blocks in the file
+ $contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
+ // strip trailing non-php code if needed
+ $pos = strrpos($contents, '?>');
+ if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
+ $contents = substr($contents, 0, $pos);
+ }
+ // strip comments if short open tags are in the file
+ if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
+ $contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
+ }
+ preg_match_all('{
+ (?:
+ \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
+ | \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;]
+ )
+ }ix', $contents, $matches);
+ $classes = array();
+ $namespace = '';
+ for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
+ if (!empty($matches['ns'][$i])) {
+ $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
+ } else {
+ $name = $matches['name'][$i];
+ // skip anon classes extending/implementing
+ if ($name === 'extends' || $name === 'implements') {
+ continue;
+ }
+ if ($name[0] === ':') {
+ // This is an XHP class, https://github.com/facebook/xhp
+ $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
+ } elseif ($matches['type'][$i] === 'enum') {
+ // In Hack, something like:
+ // enum Foo: int { HERP = '123'; }
+ // The regex above captures the colon, which isn't part of
+ // the class name.
+ $name = rtrim($name, ':');
+ }
+ $classes[] = ltrim($namespace . $name, '\\');
+ }
+ }
+ return $classes;
+}
+
+$options = getopt('i:f:', []);
+$file = $options["f"];
+$input = $options["i"];
+
+$classes = findClasses($file);
+foreach($classes as $class) {
+ echo '$classmap[\''.$class.'\'] = \''.$input.'/'.$file.'\';';
+ echo "\n";
+}
diff --git a/guix/build/composer-build-system.scm b/guix/build/composer-build-system.scm
new file mode 100644
index 0000000000..3578b91954
--- /dev/null
+++ b/guix/build/composer-build-system.scm
@@ -0,0 +1,224 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix build composer-build-system)
+ #:use-module ((guix build gnu-build-system) #:prefix gnu:)
+ #:use-module (guix build json)
+ #:use-module (guix build utils)
+ #:use-module (ice-9 match)
+ #:export (%standard-phases
+ composer-build))
+
+;; Commentary:
+;;
+;; Builder-side code of the standard composer build procedure.
+;;
+;; Code:
+
+(define* (read-package-data #:key (filename "composer.json"))
+ (call-with-input-file filename
+ (lambda (port)
+ (read-json port))))
+
+(define* (check #:key composer-file inputs outputs tests? test-target #:allow-other-keys)
+ "Install the given package."
+ (when tests?
+ (mkdir-p "vendor")
+ (create-autoload (string-append (getcwd) "/vendor") composer-file
+ (append inputs outputs) #:dev-dependencies? #t)
+ (let* ((package-data (read-package-data #:filename composer-file))
+ (scripts (match (assoc-ref package-data "scripts")
+ (('@ script ...) script)
+ (#f '())))
+ (test-script
+ (assoc-ref scripts test-target))
+ (dependencies (filter (lambda (dep) (string-contains dep "/"))
+ (map car
+ (match (assoc-ref package-data "require")
+ (('@ dependency ...) dependency)
+ (#f '())))))
+ (dependencies-dev
+ (filter (lambda (dep) (string-contains dep "/"))
+ (map car
+ (match (assoc-ref package-data "require-dev")
+ (('@ dependency ...) dependency)
+ (#f '())))))
+ (name (assoc-ref package-data "name")))
+ (for-each
+ (lambda (input)
+ (let ((bin (find-php-bin (cdr input))))
+ (when bin
+ (copy-recursively bin "vendor/bin"))))
+ inputs)
+ (match test-script
+ ((? string? command)
+ (unless (equal? (system command) 0)
+ (throw 'failed-command command)))
+ (('@ (? string? command) ...)
+ (for-each
+ (lambda (c)
+ (unless (equal? (system c) 0)
+ (throw 'failed-command c)))
+ command))
+ (#f (invoke "vendor/bin/phpunit")))))
+ #t)
+
+(define (find-php-bin input)
+ (let* ((web-dir (string-append input "/share/web"))
+ (vendors (if (file-exists? web-dir)
+ (find-files web-dir "^vendor$" #:directories? #t)
+ #f)))
+ (match vendors
+ ((vendor)
+ (let ((bin (string-append vendor "/bin")))
+ (and (file-exists? bin) bin)))
+ (_ #f))))
+
+(define (find-php-dep inputs dependency)
+ (let loop ((inputs (map cdr inputs)))
+ (if (null? inputs)
+ (throw 'unsatisfied-dependency "Unsatisfied dependency: required " dependency)
+ (let ((autoload (string-append (car inputs) "/share/web/" dependency "/vendor/autoload_conf.php")))
+ (if (file-exists? autoload)
+ autoload
+ (loop (cdr inputs)))))))
+
+(define* (create-autoload vendor composer-file inputs #:key dev-dependencies?)
+ (with-output-to-file (string-append vendor "/autoload.php")
+ (lambda _
+ (format #t "<?php~%")
+ (format #t "// autoload.php @generated by Guix~%")
+ (format #t "$map = $psr4map = $classmap = array();~%")
+ (format #t "require_once '~a/autoload_conf.php';~%" vendor)
+ (format #t "require_once '~a/share/web/composer/ClassLoader.php';~%"
+ (assoc-ref inputs "composer-classloader"))
+ (format #t "$loader = new \\Composer\\Autoload\\ClassLoader();~%")
+ (format #t "foreach ($map as $namespace => $path) {~%")
+ (format #t " $loader->set($namespace, $path);~%")
+ (format #t "}~%")
+ (format #t "foreach ($psr4map as $namespace => $path) {~%")
+ (format #t " $loader->setPsr4($namespace, $path);~%")
+ (format #t "}~%")
+ (format #t "$loader->addClassMap($classmap);~%")
+ (format #t "$loader->register();~%")))
+ (let* ((package-data (read-package-data #:filename composer-file))
+ (autoload
+ (match (assoc-ref package-data "autoload")
+ (('@ autoload ...) autoload)
+ (#f '())))
+
This message was truncated. Download the full message here.
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 04/34] gnu: Add php-doctrine-instantiator.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-4-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-doctrine-instantiator): New variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index dab660f84f..28d8909dad 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -59,3 +59,26 @@
build its autoloading feature. This package is used by the composer-build-system
to build its own store-aware autoloading feature.")
(license license:expat)))
+
+(define-public php-doctrine-instantiator
+ (package
+ (name "php-doctrine-instantiator")
+ (version "1.3.1")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/doctrine/instantiator.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "17c72j29p77gdgh06b9qc0nivmav0k5yc22z4ryygj7dhr1h65nq"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Utility for instantiating PHP objects")
+ (description "This package provides a small, lightweight utility to
+instantiate objects in PHP without invoking their constructors")
+ (home-page "https://www.doctrine-project.org/projects/instantiator.html")
+ (license license:expat)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 05/34] gnu: Add php-sebastian-recursion-context.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-5-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-recursion-context): New variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 28d8909dad..b04b8e0859 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -82,3 +82,26 @@ to build its own store-aware autoloading feature.")
instantiate objects in PHP without invoking their constructors")
(home-page "https://www.doctrine-project.org/projects/instantiator.html")
(license license:expat)))
+
+(define-public php-sebastian-recursion-context
+ (package
+ (name "php-sebastian-recursion-context")
+ (version "4.0.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/recursion-context.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0glpydmvr95f9xbmh76vgid2nz7rf6lxwfz1j7ksvgmf4m1dniyz"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Process PHP variables recursively")
+ (description "This package provides functionality to recursively process
+PHP variables")
+ (home-page "http://www.github.com/sebastianbergmann/recursion-context")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 06/34] gnu: Add php-sebastian-exporter.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-6-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-exporter): New variable.
---
gnu/packages/php-xyz.scm | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

Toggle diff (35 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index b04b8e0859..ae7d7ff6b2 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -105,3 +105,28 @@ instantiate objects in PHP without invoking their constructors")
PHP variables")
(home-page "http://www.github.com/sebastianbergmann/recursion-context")
(license license:bsd-3)))
+
+(define-public php-sebastian-exporter
+ (package
+ (name "php-sebastian-exporter")
+ (version "4.0.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/exporter.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "03xj9gbi8ifnbj5n72gfpwyg65l71gg1r8yvzpbg6d3yxbqaa8f6"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (inputs
+ `(("php-sebastian-recursion-context" ,php-sebastian-recursion-context)))
+ (synopsis "Visualize PHP variables")
+ (description "This package provides the functionality to export PHP
+variables for visualization")
+ (home-page "http://www.github.com/sebastianbergmann/exporter")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 07/34] gnu: Add php-myclabs-deep-copy.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-7-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-myclabs-deep-copy): New variable.
---
gnu/packages/php-xyz.scm | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

Toggle diff (35 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index ae7d7ff6b2..a45726a484 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -130,3 +130,28 @@ PHP variables")
variables for visualization")
(home-page "http://www.github.com/sebastianbergmann/exporter")
(license license:bsd-3)))
+
+(define-public php-myclabs-deep-copy
+ (package
+ (name "php-myclabs-deep-copy")
+ (version "1.10.1")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/myclabs/DeepCopy.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1ms4qhx5cf19ggdicnd7qjrigwam206py6mj6nw8bz71mafq9nbi"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Create copies of PHP objects")
+ (description "This package contains a facility to create deep copies (clones)
+of PHP objects. This package not only creates a new copy of an object, it
+recursively create new copies of any object referenced by the object. It is
+designed to work even in the presence of cycles in the association graph.")
+ (home-page "https://github.com/myclabs/DeepCopy.git")
+ (license license:expat)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 08/34] gnu: Add php-phar-io-version.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-8-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phar-io-version): New variable.
---
gnu/packages/php-xyz.scm | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

Toggle diff (35 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index a45726a484..0b64efe6ca 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -155,3 +155,28 @@ recursively create new copies of any object referenced by the object. It is
designed to work even in the presence of cycles in the association graph.")
(home-page "https://github.com/myclabs/DeepCopy.git")
(license license:expat)))
+
+(define-public php-phar-io-version
+ (package
+ (name "php-phar-io-version")
+ (version "3.0.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/phar-io/version.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0r9470p0azw7l0x2wbn7kh0zhpswvjnm32vc8vml5v5nskmnqz4c"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (properties
+ `((upstream-name . "phar-io/version")))
+ (synopsis "Library for handling version information and constraints")
+ (description "This package contains a library for handling version information
+and constraints.")
+ (home-page "https://phar.io")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 09/34] gnu: Add php-phar-io-manifest.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-9-julien@lepiller.eu
* qnu/packages/php-xyz.scm (php-phar-io-manifest): New variable.
---
gnu/packages/php-xyz.scm | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)

Toggle diff (37 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 0b64efe6ca..f0f4fe650a 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -180,3 +180,30 @@ designed to work even in the presence of cycles in the association graph.")
and constraints.")
(home-page "https://phar.io")
(license license:bsd-3)))
+
+(define-public php-phar-io-manifest
+ (package
+ (name "php-phar-io-manifest")
+ (version "2.0.1")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/phar-io/manifest.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0r2s1qdkhn7782g1y6skxvp5w397vmwb496fymsnik2818w0q469"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (inputs
+ `(("php-phar-io-version" ,php-phar-io-version)))
+ (properties
+ `((upstream-name . "phar-io/manifest")))
+ (synopsis "PHP Archive information reader")
+ (description "This package contains a component for reading phar.io manifest
+information from a PHP Archive (PHAR)")
+ (home-page "https://phar.io")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 10/34] gnu: Add php-symfony-polyfill-ctype.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-10-julien@lepiller.eu
* gnu/packages/php.scm (php-symfony-polyfill-ctype): New variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index f0f4fe650a..51e51ac51b 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -207,3 +207,26 @@ and constraints.")
information from a PHP Archive (PHAR)")
(home-page "https://phar.io")
(license license:bsd-3)))
+
+(define-public php-symfony-polyfill-ctype
+ (package
+ (name "php-symfony-polyfill-ctype")
+ (version "1.17.1")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/symfony/polyfill-ctype.git")
+ (commit (string-append "v" version))))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0bh22vwq2idy7fi8ajm6aggjdvds64s98y9854b5gl9s84dk9pz8"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Ctype functions for older PHP versions")
+ (description "This component provides @code{ctype_*} functions to users
+who run php versions without the ctype extension.")
+ (home-page "https://symfony.com")
+ (license license:expat)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 11/34] gnu: Add php-webmozart-assert.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-11-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-webmozart-assert): New variable.
---
gnu/packages/php-xyz.scm | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

Toggle diff (35 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 51e51ac51b..ffc2eb7b11 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -230,3 +230,28 @@ information from a PHP Archive (PHAR)")
who run php versions without the ctype extension.")
(home-page "https://symfony.com")
(license license:expat)))
+
+(define-public php-webmozart-assert
+ (package
+ (name "php-webmozart-assert")
+ (version "1.9.1")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/webmozart/assert.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1q9bp4sp11r8ghdzr0qswdf1k5bf9b5s525im3kspar6y8019sh9"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (inputs
+ `(("php-symfony-polyfill-ctype" ,php-symfony-polyfill-ctype)))
+ (synopsis "Assertions to validate method input/output with nice error messages.")
+ (description "This library contains efficient assertions to test the input
+and output of PHP methods.")
+ (home-page "https://github.com/webmozart/assert")
+ (license license:expat)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 13/34] gnu: Add php-phpdocumentor-type-resolver.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-13-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phpdocumentor-type-resolver): New
variable.
---
gnu/packages/php-xyz.scm | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

Toggle diff (35 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 9b604c46f0..93d8649bee 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -279,3 +279,28 @@ the code structure")
to analyze the code structure.")
(home-page "http://www.phpdoc.org")
(license license:expat)))
+
+(define-public php-phpdocumentor-type-resolver
+ (package
+ (name "php-phpdocumentor-type-resolver")
+ (version "1.3.0")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/phpDocumentor/TypeResolver.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0wshv49z4hxraygg2vhzn0s9ih2y9ymzpcnyjfk14vcfq5yx53l9"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (inputs
+ `(("php-phpdocumentor-reflection-common" ,php-phpdocumentor-reflection-common)))
+ (synopsis "Resolver of class names, types and structural element names")
+ (description "This package provides a PSR-5 based resolver of class names,
+types and structural element names.")
+ (home-page "http://www.phpdoc.org")
+ (license license:expat)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 12/34] gnu: Add php-phpdocumentor-reflection-common.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-12-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phpdocumentor-reflection-common): New
variable.
---
gnu/packages/php-xyz.scm | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)

Toggle diff (34 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index ffc2eb7b11..9b604c46f0 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -255,3 +255,27 @@ who run php versions without the ctype extension.")
and output of PHP methods.")
(home-page "https://github.com/webmozart/assert")
(license license:expat)))
+
+(define-public php-phpdocumentor-reflection-common
+ (package
+ (name "php-phpdocumentor-reflection-common")
+ (version "2.2.0")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/phpDocumentor/ReflectionCommon.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1q685cpwbfxqy42iz61xxv6zbcc1qskn07nkipflj6c5s935l8jy"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Common reflection classes used by phpdocumentor to reflect
+the code structure")
+ (description "This package contains common classes used by phpdocumentor
+to analyze the code structure.")
+ (home-page "http://www.phpdoc.org")
+ (license license:expat)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 14/34] gnu: Add php-phpdocumentor-reflection-docblock.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-14-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phpdocumentor-reflection-docblock): New
variable.
---
gnu/packages/php-xyz.scm | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)

Toggle diff (38 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 93d8649bee..df9c490bbf 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -304,3 +304,31 @@ to analyze the code structure.")
types and structural element names.")
(home-page "http://www.phpdoc.org")
(license license:expat)))
+
+(define-public php-phpdocumentor-reflection-docblock
+ (package
+ (name "php-phpdocumentor-reflection-docblock")
+ (version "5.1.0")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/phpDocumentor/ReflectionDocBlock.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1bsqwcq5ix7f5p56kc92pl1nqpjdpfc92pjvwyshp1syrrspa3rr"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (inputs
+ `(("php-webmozart-assert" ,php-webmozart-assert)
+ ("php-phpdocumentor-reflection-common" ,php-phpdocumentor-reflection-common)
+ ("php-phpdocumentor-type-resolver" ,php-phpdocumentor-type-resolver)))
+ (synopsis "Library for retrieving documentation in code fro the code")
+ (description "With this component, a library can provide support for
+annotations via DocBlocks or otherwise retrieve information that is embedded
+in a DocBlock.")
+ (home-page "https://github.com/phpDocumentor/ReflectionDocBlock")
+ (license license:expat)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 15/34] gnu: Add php-theseer-tokenizer.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-15-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-theseer-tokenizer): New variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index df9c490bbf..f54b875d92 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -332,3 +332,26 @@ annotations via DocBlocks or otherwise retrieve information that is embedded
in a DocBlock.")
(home-page "https://github.com/phpDocumentor/ReflectionDocBlock")
(license license:expat)))
+
+(define-public php-theseer-tokenizer
+ (package
+ (name "php-theseer-tokenizer")
+ (version "1.1.3")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/theseer/tokenizer.git")
+ (commit "11336f6f84e16a720dae9d8e6ed5019efa85a0f9")))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0j436a3jpynnlqrvd7la7a7smj78aklkragwa9l8p91973xra18l"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Convert PHP to XML")
+ (description "This package provides a small library for converting tokenized
+PHP source code into XML and potentially other formats.")
+ (home-page "https://github.com/theseer/tokenizer")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 16/34] gnu: Add php-sebastian-code-unit-reverse-lookup.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-16-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-code-unit-reverse-lookup): New
variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index f54b875d92..13584273f9 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -355,3 +355,26 @@ in a DocBlock.")
PHP source code into XML and potentially other formats.")
(home-page "https://github.com/theseer/tokenizer")
(license license:bsd-3)))
+
+(define-public php-sebastian-code-unit-reverse-lookup
+ (package
+ (name "php-sebastian-code-unit-reverse-lookup")
+ (version "2.0.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0lppni3qcd6gx50jf16y3n71ldj12xjd06kl9ml78zd5p2s6z4qc"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Look up function name from location")
+ (description "This package provides a facility to look up which function or
+method a line of code belongs to.")
+ (home-page "https://github.com/sebastianbergmann/code-unit-reverse-lookup/")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 17/34] gnu: Add php-phpunit-php-token-stream.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-17-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phpunit-php-token-stream): New variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 13584273f9..344c413d2c 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -378,3 +378,26 @@ PHP source code into XML and potentially other formats.")
method a line of code belongs to.")
(home-page "https://github.com/sebastianbergmann/code-unit-reverse-lookup/")
(license license:bsd-3)))
+
+(define-public php-phpunit-php-token-stream
+ (package
+ (name "php-phpunit-php-token-stream")
+ (version "4.0.3")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/php-token-stream.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0iv8ssvyjhgxa1qpp5s8i0j409w49s2kc9qwv1c27qgdhv7yhf7h"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Wrapper around PHP's tokenizer extension")
+ (description "This library provides a wrapper around PHP's tokenizer
+extension.")
+ (home-page "https://github.com/sebastianbergmann/php-token-stream/")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 18/34] gnu: Add php-sebastian-version.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-18-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-version): New variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 344c413d2c..906a88d49e 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -401,3 +401,26 @@ method a line of code belongs to.")
extension.")
(home-page "https://github.com/sebastianbergmann/php-token-stream/")
(license license:bsd-3)))
+
+(define-public php-sebastian-version
+ (package
+ (name "php-sebastian-version")
+ (version "3.0.1")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/version.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1kr2i6s7y4k18bz09cqj4pc4bqzph9n6ncgpqq4p4fg790h5i5ym"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "PHP versionning library")
+ (description "This package is a library that helps with managing the version
+number of Git-hosted PHP projects.")
+ (home-page "https://github.com/sebastianbergmann/version")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 19/34] gnu: Add php-phpunit-php-file-iterator.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-19-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phpunit-php-file-iterator): New
variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 906a88d49e..5d06bea0cb 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -424,3 +424,26 @@ extension.")
number of Git-hosted PHP projects.")
(home-page "https://github.com/sebastianbergmann/version")
(license license:bsd-3)))
+
+(define-public php-phpunit-php-file-iterator
+ (package
+ (name "php-phpunit-php-file-iterator")
+ (version "3.0.4")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/php-file-iterator.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1pglbp8m4iv5w16gshlp49k4ngpsx28mhwip761kyvvd5w27ysr2"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Filter file by extension")
+ (description "This package contains a @code{FilterIterator} implementation
+that filters files based on a list of suffixes.")
+ (home-page "https://github.com/sebastianbergmann/php-file-iterator/")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 20/34] gnu: Add php-phpunit-php-text-template.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-20-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phpunit-php-text-template): New
variable.
---
gnu/packages/php-xyz.scm | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

Toggle diff (32 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 5d06bea0cb..b5abcaae36 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -447,3 +447,25 @@ number of Git-hosted PHP projects.")
that filters files based on a list of suffixes.")
(home-page "https://github.com/sebastianbergmann/php-file-iterator/")
(license license:bsd-3)))
+
+(define-public php-phpunit-php-text-template
+ (package
+ (name "php-phpunit-php-text-template")
+ (version "2.0.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/php-text-template.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0x38kj1xlnysg9xgad560k361l93vh32mvkyfn7rss3p2r319jhx"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Simple template engine")
+ (description "This package contains a library for a simple templating engine.")
+ (home-page "https://github.com/sebastianbergmann/php-text-template/")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 21/34] gnu: Add php-sebastian-diff.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-21-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-diff): New variable.
---
gnu/packages/php-xyz.scm | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

Toggle diff (32 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index b5abcaae36..ccc613baaf 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -469,3 +469,25 @@ that filters files based on a list of suffixes.")
(description "This package contains a library for a simple templating engine.")
(home-page "https://github.com/sebastianbergmann/php-text-template/")
(license license:bsd-3)))
+
+(define-public php-sebastian-diff
+ (package
+ (name "php-sebastian-diff")
+ (version "4.0.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/diff.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0fr5vrmz3d1wwpf59y16fin5lgi55sjd7dqfkx0zqmsqadbjrjxq"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Diff implementation")
+ (description "This package contains a PHP implementation of a diff function.")
+ (home-page "https://github.com/sebastianbergmann/diff")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 22/34] gnu: Add php-sebastian-comparator.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-22-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-comparator): New variable.
---
gnu/packages/php-xyz.scm | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

Toggle diff (36 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index ccc613baaf..aff2ed79a7 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -491,3 +491,29 @@ that filters files based on a list of suffixes.")
(description "This package contains a PHP implementation of a diff function.")
(home-page "https://github.com/sebastianbergmann/diff")
(license license:bsd-3)))
+
+(define-public php-sebastian-comparator
+ (package
+ (name "php-sebastian-comparator")
+ (version "4.0.3")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/comparator.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1scw7vm26layqh5mzvdhjiil520fj6ipixkjnmwm036xr925iww0"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (inputs
+ `(("php-sebastian-exporter" ,php-sebastian-exporter)
+ ("php-sebastian-diff" ,php-sebastian-diff)))
+ (synopsis "PHP value comparison")
+ (description "This package provides the functionality to compare PHP values
+for equality.")
+ (home-page "https://github.com/sebastianbergmann/comparator")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 23/34] gnu: Add php-sebastian-environment.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-23-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-environment): New variable.
---
gnu/packages/php-xyz.scm | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

Toggle diff (32 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index aff2ed79a7..9ee823bcda 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -517,3 +517,25 @@ that filters files based on a list of suffixes.")
for equality.")
(home-page "https://github.com/sebastianbergmann/comparator")
(license license:bsd-3)))
+
+(define-public php-sebastian-environment
+ (package
+ (name "php-sebastian-environment")
+ (version "5.1.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/environment.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0lhaiwk6dbwii9kmjaq3gjl2x5s1rikmxkvmy4mjvjcbi7imp38s"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Handle HHVM and PHP environments")
+ (description "This package provides functionality to handle HHVM/PHP environments")
+ (home-page "http://www.github.com/sebastianbergmann/environment")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 24/34] gnu: Add php-phpspec-prophecy.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-24-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phpspec-prophecy): New variable.
---
gnu/packages/php-xyz.scm | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)

Toggle diff (39 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 9ee823bcda..8c96d9aabc 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -539,3 +539,32 @@ for equality.")
(description "This package provides functionality to handle HHVM/PHP environments")
(home-page "http://www.github.com/sebastianbergmann/environment")
(license license:bsd-3)))
+
+(define-public php-phpspec-prophecy
+ (package
+ (name "php-phpspec-prophecy")
+ (version "1.11.1")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/phpspec/prophecy.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1pd6iz6pbfpaz5rqa36q01l569zgiqpjgqmzw3rra2qdh1jrwdy1"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (inputs
+ `(("php-sebastian-recursion-context" ,php-sebastian-recursion-context)
+ ("php-doctrine-instantiator" ,php-doctrine-instantiator)
+ ("php-sebastian-comparator" ,php-sebastian-comparator)
+ ("php-phpdocumentor-reflection-docblock"
+ ,php-phpdocumentor-reflection-docblock)))
+ (synopsis "Mocking framework for PHP 5.3+")
+ (description "This package contains a mocking framework for testing PHP
+5.3+ projects.")
+ (home-page "https://github.com/phpspec/prophecy")
+ (license license:expat)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 26/34] gnu: Add php-sebastian-global-state.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-26-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-global-state): New variable.
---
gnu/packages/php-xyz.scm | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)

Toggle diff (37 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 899f6a3f69..4872523b31 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -591,3 +591,30 @@ for equality.")
inherited and non-public ones.")
(home-page "https://github.com/sebastianbergmann/object-reflector/")
(license license:bsd-3)))
+
+(define-public php-sebastian-global-state
+ (package
+ (name "php-sebastian-global-state")
+ (version "4.0.0")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/global-state.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0x6sfw353px5y7azipn2mb15w7w7zxbbpbv3dbhhkryrhad8w064"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (inputs
+ `(("php-sebastian-recursion-context" ,php-sebastian-recursion-context)
+ ("php-sebastian-object-reflector" ,php-sebastian-object-reflector)))
+ (synopsis "Snapshotting of global state")
+ (description "This package contains a stand-alone component originally part
+of PHPUnit. It provides support for creating a snapshot of the global state
+of a PHP program.")
+ (home-page "http://www.github.com/sebastianbergmann/global-state")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 28/34] gnu: Add php-sebastian-resource-operations.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-28-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-resource-operations): New
variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 8cf5668030..aee08c0878 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -644,3 +644,26 @@ of a PHP program.")
and object graphs to enumerate all referenced objects.")
(home-page "https://github.com/sebastianbergmann/object-enumerator/")
(license license:bsd-3)))
+
+(define-public php-sebastian-resource-operations
+ (package
+ (name "php-sebastian-resource-operations")
+ (version "3.0.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/resource-operations.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "09s2gsmx6fg8sx64yyz2dszy22dcsspazlhskv3d9mflpmrk0d9y"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "List built-in PHP functions")
+ (description "This package provides a list of PHP built-in functions that
+operate on resources.")
+ (home-page "https://www.github.com/sebastianbergmann/resource-operations")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 25/34] gnu: Add php-sebastian-object-reflector.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-25-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-object-reflector): New
variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 8c96d9aabc..899f6a3f69 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -568,3 +568,26 @@ for equality.")
5.3+ projects.")
(home-page "https://github.com/phpspec/prophecy")
(license license:expat)))
+
+(define-public php-sebastian-object-reflector
+ (package
+ (name "php-sebastian-object-reflector")
+ (version "2.0.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/object-reflector.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1qkvp2s932h53f161l30qlnxicw4fklirmnds173wgmavms1b5yb"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "PHP reflexion library")
+ (description "This package allows reflection of object attributes, including
+inherited and non-public ones.")
+ (home-page "https://github.com/sebastianbergmann/object-reflector/")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 32/34] gnu: Add php-phpunit-php-invoker.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-32-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phpunit-php-invoker): New variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 1b6669abcc..484fb17790 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -745,3 +745,26 @@ processing, and rendering functionality for PHP code coverage information.")
of PHPUnit. It provides a utility class for timing.")
(home-page "https://github.com/sebastianbergmann/php-timer/")
(license license:bsd-3)))
+
+(define-public php-phpunit-php-invoker
+ (package
+ (name "php-phpunit-php-invoker")
+ (version "3.0.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/php-invoker.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1xs7m0wiminnhkd400glmixyhrx1ir710j6fds9i03dhicfcj7db"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "PHP library for invoking functions")
+ (description "This package contains a library to invoke callables with a
+timeout.")
+ (home-page "https://github.com/sebastianbergmann/php-invoker/")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 30/34] gnu: Add php-phpunit-php-code-coverage.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-30-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phpunit-php-code-coverage): New
variable.
---
gnu/packages/php-xyz.scm | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)

Toggle diff (42 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 9a50c431b7..2d186c5190 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -690,3 +690,35 @@ operate on resources.")
the types of the PHP type system.")
(home-page "https://github.com/sebastianbergmann/type")
(license license:bsd-3)))
+
+(define-public php-phpunit-php-code-coverage
+ (package
+ (name "php-phpunit-php-code-coverage")
+ (version "8.0.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/php-code-coverage.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1qr7x9y8636bvv0fk8hl0kl9d2y8fy6qw65kpi4yb1yyqhfddkgh"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (inputs
+ `(("php-theseer-tokenizer" ,php-theseer-tokenizer)
+ ("php-sebastian-version" ,php-sebastian-version)
+ ("php-sebastian-environment" ,php-sebastian-environment)
+ ("php-sebastian-code-unit-reverse-lookup"
+ ,php-sebastian-code-unit-reverse-lookup)
+ ("php-phpunit-php-text-template" ,php-phpunit-php-text-template)
+ ("php-phpunit-php-token-stream" ,php-phpunit-php-token-stream)
+ ("php-phpunit-php-file-iterator" ,php-phpunit-php-file-iterator)))
+ (synopsis "Code coverage information library")
+ (description "This package is a library that provides collection,
+processing, and rendering functionality for PHP code coverage information.")
+ (home-page "https://github.com/sebastianbergmann/php-code-coverage")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 31/34] gnu: Add php-phpunit-php-timer.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-31-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phpunit-php-timer): New variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 2d186c5190..1b6669abcc 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -722,3 +722,26 @@ the types of the PHP type system.")
processing, and rendering functionality for PHP code coverage information.")
(home-page "https://github.com/sebastianbergmann/php-code-coverage")
(license license:bsd-3)))
+
+(define-public php-phpunit-php-timer
+ (package
+ (name "php-phpunit-php-timer")
+ (version "5.0.1")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/php-timer.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0hyy5c8b22zki6836a7fhzr3s6dpvga33r2rzfrsbv1arh19ay60"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "Utility class for timing")
+ (description "This package contains a stand-alone component originally part
+of PHPUnit. It provides a utility class for timing.")
+ (home-page "https://github.com/sebastianbergmann/php-timer/")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 33/34] gnu: Add php-sebastian-code-unit.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-33-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-code-unit): New variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 484fb17790..0ae92c4600 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -768,3 +768,26 @@ of PHPUnit. It provides a utility class for timing.")
timeout.")
(home-page "https://github.com/sebastianbergmann/php-invoker/")
(license license:bsd-3)))
+
+(define-public php-sebastian-code-unit
+ (package
+ (name "php-sebastian-code-unit")
+ (version "1.0.5")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/code-unit.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "058ykqcmzm900c513j2qvi189bgn0scxsrhbrik5xycrr620krxc"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "PHP collection of value objects for code units")
+ (description "This package contains a collection of value objects that
+represent the PHP code units.")
+ (home-page "https://github.com/sebastianbergmann/code-unit")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 29/34] gnu: Add php-sebastian-type.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-29-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-type): New variable.
---
gnu/packages/php-xyz.scm | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

Toggle diff (33 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index aee08c0878..9a50c431b7 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -667,3 +667,26 @@ and object graphs to enumerate all referenced objects.")
operate on resources.")
(home-page "https://www.github.com/sebastianbergmann/resource-operations")
(license license:bsd-3)))
+
+(define-public php-sebastian-type
+ (package
+ (name "php-sebastian-type")
+ (version "2.2.1")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/type.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0gvdb9188a4903q0dnhhdcm9qd67is5pns8jbccxr7hxv8w7d7h3"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (synopsis "PHP type system representation")
+ (description "This package is a collection of value objects that represent
+the types of the PHP type system.")
+ (home-page "https://github.com/sebastianbergmann/type")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 27/34] gnu: Add php-sebastian-object-enumerator.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-27-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-sebastian-object-enumerator): New
variable.
---
gnu/packages/php-xyz.scm | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

Toggle diff (36 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 4872523b31..8cf5668030 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -618,3 +618,29 @@ of PHPUnit. It provides support for creating a snapshot of the global state
of a PHP program.")
(home-page "http://www.github.com/sebastianbergmann/global-state")
(license license:bsd-3)))
+
+(define-public php-sebastian-object-enumerator
+ (package
+ (name "php-sebastian-object-enumerator")
+ (version "4.0.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/object-enumerator.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1qx28r0ncbh0x9i0jplyg870paxxsy7g1ibgbdqq11176101aj6q"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; We do not have phpunit yet
+ `(#:tests? #f))
+ (inputs
+ `(("php-sebastian-recursion-context" ,php-sebastian-recursion-context)
+ ("php-sebastian-object-reflector" ,php-sebastian-object-reflector)))
+ (synopsis "Enumerate PHP objects")
+ (description "This package allows PHP programs to traverse array structures
+and object graphs to enumerate all referenced objects.")
+ (home-page "https://github.com/sebastianbergmann/object-enumerator/")
+ (license license:bsd-3)))
--
2.27.0
J
J
Julien Lepiller wrote on 13 Jul 2020 00:25
[PATCH 34/34] gnu: Add phpunit.
(address . 42338@debbugs.gnu.org)
20200712222538.18092-34-julien@lepiller.eu
* gnu/packages/php-xyz.scm (php-phpunit-phpunit): New variable.
---
gnu/packages/php-xyz.scm | 45 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)

Toggle diff (55 lines)
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
index 0ae92c4600..eebf64c1a3 100644
--- a/gnu/packages/php-xyz.scm
+++ b/gnu/packages/php-xyz.scm
@@ -791,3 +791,48 @@ timeout.")
represent the PHP code units.")
(home-page "https://github.com/sebastianbergmann/code-unit")
(license license:bsd-3)))
+
+(define-public php-phpunit-phpunit
+ (package
+ (name "phpunit")
+ (version "9.2.5")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sebastianbergmann/phpunit.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1ck41faxkqr6painsqirklzsl08k8biadi2ksnpsmpjf3dp5p5gl"))))
+ (build-system composer-build-system)
+ (arguments
+ ;; Requires phpspec/prophecy-phpunit, which in turns requires phpunit.
+ `(#:tests? #f))
+ (inputs
+ `(("php-sebastian-version" ,php-sebastian-version)
+ ("php-sebastian-type" ,php-sebastian-type)
+ ("php-sebastian-resource-operations" ,php-sebastian-resource-operations)
+ ("php-sebastian-object-enumerator" ,php-sebastian-object-enumerator)
+ ("php-sebastian-global-state" ,php-sebastian-global-state)
+ ("php-sebastian-exporter" ,php-sebastian-exporter)
+ ("php-sebastian-environment" ,php-sebastian-environment)
+ ("php-sebastian-diff" ,php-sebastian-diff)
+ ("php-sebastian-comparator" ,php-sebastian-comparator)
+ ("php-sebastian-code-unit" ,php-sebastian-code-unit)
+ ("php-phpunit-php-timer" ,php-phpunit-php-timer)
+ ("php-phpunit-php-text-template" ,php-phpunit-php-text-template)
+ ("php-phpunit-php-invoker" ,php-phpunit-php-invoker)
+ ("php-phpunit-php-file-iterator" ,php-phpunit-php-file-iterator)
+ ("php-phpunit-php-code-coverage" ,php-phpunit-php-code-coverage)
+ ("php-phpspec-prophecy" ,php-phpspec-prophecy)
+ ("php-phar-io-version" ,php-phar-io-version)
+ ("php-phar-io-manifest" ,php-phar-io-manifest)
+ ("php-myclabs-deep-copy" ,php-myclabs-deep-copy)
+ ("php-doctrine-instantiator" ,php-doctrine-instantiator)))
+ (properties `((upstream-name . "phpunit/phpunit")))
+ (synopsis "PHP Unit Testing framework")
+ (description "PHPUnit is a testing framework for PHP. It is an instance of
+the xUnit architecture for unit testing frameworks.")
+ (home-page "https://phpunit.de/")
+ (license license:bsd-3)))
--
2.27.0
L
L
Ludovic Courtès wrote on 7 Sep 2020 16:06
Re: [bug#42338] [PATCH 01/34] guix: import: Add composer importer.
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 42338@debbugs.gnu.org)
87mu21heay.fsf@gnu.org
Hi Julien,

There’s a lot of interesting work in here! I’m not familiar with PHP;
I’ll just make a bird’s eye review.

Julien Lepiller <julien@lepiller.eu> skribis:

Toggle quote (5 lines)
> * guix/import/composer.scm: New file.
> * guix/scripts/import/composer.scm: New file.
> * Makefile.am: Add them.
> * guix/scripts/import.scm: Add composer importer.

Please add tests and a mention in “Invoking guix import” in the manual.

For tests, a strategy that I think works well is that used in
tests/cpan.scm, where we spawn an HTTP server to mock the real one.

Toggle quote (22 lines)
> +(define* (composer-fetch name #:optional version)
> + "Return an alist representation of the Composer metadata for the package NAME,
> +or #f on failure."
> + (let ((package (json-fetch
> + (string-append "https://repo.packagist.org/p/" name ".json"))))
> + (if package
> + (let* ((packages (assoc-ref package "packages"))
> + (package (assoc-ref packages name))
> + (versions (filter
> + (lambda (version)
> + (and (not (string-contains version "dev"))
> + (not (string-contains version "beta"))))
> + (map car package)))
> + (versions (map
> + (lambda (version)
> + (cons (fix-version version) version))
> + versions))
> + (version (or (if (null? version) #f version)
> + (latest-version (map car versions)))))
> + (assoc-ref package (assoc-ref versions version)))
> + #f)))

I recommend using ‘define-json-mapping’ instead of browsing alists: it’s
less error-prone, hides the JSON details away, and leads to more
readable code. The pypi, crates, cpan importers use it.

Thanks!

Ludo’.
L
L
Ludovic Courtès wrote on 7 Sep 2020 16:09
Re: [bug#42338] [PATCH 03/34] guix: Add composer-build-system.
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 42338@debbugs.gnu.org)
87imcphe6a.fsf@gnu.org
Julien Lepiller <julien@lepiller.eu> skribis:

Toggle quote (6 lines)
> * guix/build-system/composer.scm: New file.
> * guix/build/composer-build-system.scm: New file.
> * guix/build-system/findclass.php: New file.
> * Makefile.am: Add them.
> * doc/guix.texi (Build Systems): Document it.

[...]

Toggle quote (11 lines)
> +++ b/guix/build-system/findclass.php
> @@ -0,0 +1,102 @@
> +<?php
> +/**
> + * Extract the classes in the given file
> + *
> + * @param string $path The file to check
> + * @throws \RuntimeException
> + * @return array The found classes
> + */

This should rather be under gnu/packages/aux-files IMO. Also, could you
add a copyright header and possibly info as to where it originates?

Toggle quote (19 lines)
> +(define* (create-autoload vendor composer-file inputs #:key dev-dependencies?)
> + (with-output-to-file (string-append vendor "/autoload.php")
> + (lambda _
> + (format #t "<?php~%")
> + (format #t "// autoload.php @generated by Guix~%")
> + (format #t "$map = $psr4map = $classmap = array();~%")
> + (format #t "require_once '~a/autoload_conf.php';~%" vendor)
> + (format #t "require_once '~a/share/web/composer/ClassLoader.php';~%"
> + (assoc-ref inputs "composer-classloader"))
> + (format #t "$loader = new \\Composer\\Autoload\\ClassLoader();~%")
> + (format #t "foreach ($map as $namespace => $path) {~%")
> + (format #t " $loader->set($namespace, $path);~%")
> + (format #t "}~%")
> + (format #t "foreach ($psr4map as $namespace => $path) {~%")
> + (format #t " $loader->setPsr4($namespace, $path);~%")
> + (format #t "}~%")
> + (format #t "$loader->addClassMap($classmap);~%")
> + (format #t "$loader->register();~%")))

I think it’d be clearer as a single string:

(display "\
<?php
// autoload.php …")

Ludo’.
J
J
Julien Lepiller wrote on 18 Sep 2020 00:43
Re: [bug#42338] [PATCH 01/34] guix: import: Add composer importer.
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 42338@debbugs.gnu.org)
20200918004333.127aa5da@tachikoma.lepiller.eu
Le Mon, 07 Sep 2020 16:06:13 +0200,
Ludovic Courtès <ludo@gnu.org> a écrit :

Toggle quote (51 lines)
> Hi Julien,
>
> There’s a lot of interesting work in here! I’m not familiar with PHP;
> I’ll just make a bird’s eye review.
>
> Julien Lepiller <julien@lepiller.eu> skribis:
>
> > * guix/import/composer.scm: New file.
> > * guix/scripts/import/composer.scm: New file.
> > * Makefile.am: Add them.
> > * guix/scripts/import.scm: Add composer importer.
>
> Please add tests and a mention in “Invoking guix import” in the
> manual.
>
> For tests, a strategy that I think works well is that used in
> tests/cpan.scm, where we spawn an HTTP server to mock the real one.
>
> > +(define* (composer-fetch name #:optional version)
> > + "Return an alist representation of the Composer metadata for the
> > package NAME, +or #f on failure."
> > + (let ((package (json-fetch
> > + (string-append "https://repo.packagist.org/p/"
> > name ".json"))))
> > + (if package
> > + (let* ((packages (assoc-ref package "packages"))
> > + (package (assoc-ref packages name))
> > + (versions (filter
> > + (lambda (version)
> > + (and (not (string-contains version
> > "dev"))
> > + (not (string-contains version
> > "beta"))))
> > + (map car package)))
> > + (versions (map
> > + (lambda (version)
> > + (cons (fix-version version) version))
> > + versions))
> > + (version (or (if (null? version) #f version)
> > + (latest-version (map car versions)))))
> > + (assoc-ref package (assoc-ref versions version)))
> > + #f)))
>
> I recommend using ‘define-json-mapping’ instead of browsing alists:
> it’s less error-prone, hides the JSON details away, and leads to more
> readable code. The pypi, crates, cpan importers use it.
>
> Thanks!
>
> Ludo’.

Thanks, here's a new version
J
J
Julien Lepiller wrote on 18 Sep 2020 00:44
Re: [bug#42338] [PATCH 03/34] guix: Add composer-build-system.
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 42338@debbugs.gnu.org)
20200918004403.0d755d60@tachikoma.lepiller.eu
Le Mon, 07 Sep 2020 16:09:01 +0200,
Ludovic Courtès <ludo@gnu.org> a écrit :

Toggle quote (55 lines)
> Julien Lepiller <julien@lepiller.eu> skribis:
>
> > * guix/build-system/composer.scm: New file.
> > * guix/build/composer-build-system.scm: New file.
> > * guix/build-system/findclass.php: New file.
> > * Makefile.am: Add them.
> > * doc/guix.texi (Build Systems): Document it.
>
> [...]
>
> > +++ b/guix/build-system/findclass.php
> > @@ -0,0 +1,102 @@
> > +<?php
> > +/**
> > + * Extract the classes in the given file
> > + *
> > + * @param string $path The file to check
> > + * @throws \RuntimeException
> > + * @return array The found classes
> > + */
>
> This should rather be under gnu/packages/aux-files IMO. Also, could
> you add a copyright header and possibly info as to where it
> originates?
>
> > +(define* (create-autoload vendor composer-file inputs #:key
> > dev-dependencies?)
> > + (with-output-to-file (string-append vendor "/autoload.php")
> > + (lambda _
> > + (format #t "<?php~%")
> > + (format #t "// autoload.php @generated by Guix~%")
> > + (format #t "$map = $psr4map = $classmap = array();~%")
> > + (format #t "require_once '~a/autoload_conf.php';~%" vendor)
> > + (format #t "require_once
> > '~a/share/web/composer/ClassLoader.php';~%"
> > + (assoc-ref inputs "composer-classloader"))
> > + (format #t "$loader = new
> > \\Composer\\Autoload\\ClassLoader();~%")
> > + (format #t "foreach ($map as $namespace => $path) {~%")
> > + (format #t " $loader->set($namespace, $path);~%")
> > + (format #t "}~%")
> > + (format #t "foreach ($psr4map as $namespace => $path) {~%")
> > + (format #t " $loader->setPsr4($namespace, $path);~%")
> > + (format #t "}~%")
> > + (format #t "$loader->addClassMap($classmap);~%")
> > + (format #t "$loader->register();~%")))
>
> I think it’d be clearer as a single string:
>
> (display "\
> <?php
> // autoload.php …")
>
> Ludo’.

Thanks, here's a new version
L
L
Ludovic Courtès wrote on 18 Sep 2020 10:31
Re: [bug#42338] [PATCH 01/34] guix: import: Add composer importer.
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 42338@debbugs.gnu.org)
87sgbf1o5w.fsf@gnu.org
Hi!

Julien Lepiller <julien@lepiller.eu> skribis:

Toggle quote (12 lines)
> From 6d521ca9f066f82488abefd5d3630e38305c0fd1 Mon Sep 17 00:00:00 2001
> From: Julien Lepiller <julien@lepiller.eu>
> Date: Tue, 29 Oct 2019 08:07:38 +0100
> Subject: [PATCH 01/34] guix: import: Add composer importer.
>
> * guix/import/composer.scm: New file.
> * guix/scripts/import/composer.scm: New file.
> * guix/tests/composer.scm: New file.
> * Makefile.am: Add them.
> * guix/scripts/import.scm: Add composer importer.
> * doc/guix.texi (Invoking guix import): Mention it.

[...]

Toggle quote (3 lines)
> +@item composer
> +@cindex COMPOSER

s/COMPOSER/Composer/ ?

Toggle quote (1 lines)
> +Import metadat from the @uref{https://getcomposer.org/,Composer} package
^
metadata

Toggle quote (2 lines)
> +archive used by the PHP community.

Could you add an example command line like we have for some of the other
importers? (It’s also useful for us as a test against the actual servers…)

Toggle quote (11 lines)
> + (let ((package (json-fetch
> + (string-append (%composer-base-url) "/p/" name ".json"))))
> + (if package
> + (let* ((packages (assoc-ref package "packages"))
> + (package (assoc-ref packages name))
> + (versions (filter
> + (lambda (version)
> + (and (not (string-contains version "dev"))
> + (not (string-contains version "beta"))))
> + (map car package)))

Like I wrote before, I recommend ‘define-json-mapping’. If you prefer
you can make that change later on once you’ve pushed this first version,
but I really think it’ll help maintainability.

This should also help avoid (map car …), which is frowned upon in Guix.
:-)

Toggle quote (3 lines)
> + (versions (map
> + (lambda (version)

Rather indent as: (map (lambda (version)

Otherwise LGTM!

Ludo’.
L
L
Ludovic Courtès wrote on 18 Sep 2020 10:45
Re: [bug#42338] [PATCH 03/34] guix: Add composer-build-system.
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 42338@debbugs.gnu.org)
87eemz1nib.fsf@gnu.org
Hi,

Julien Lepiller <julien@lepiller.eu> skribis:

Toggle quote (11 lines)
> From bb5d102b6ea5e6b5c06bbf90a58927c6180e23bc Mon Sep 17 00:00:00 2001
> From: Julien Lepiller <julien@lepiller.eu>
> Date: Tue, 29 Oct 2019 20:58:51 +0100
> Subject: [PATCH 03/34] guix: Add composer-build-system.
>
> * guix/build-system/composer.scm: New file.
> * guix/build/composer-build-system.scm: New file.
> * gnu/packages/aux-files/findclass.php: New file.
> * Makefile.am: Add them.
> * doc/guix.texi (Build Systems): Document it.

[...]

Toggle quote (3 lines)
> --- /dev/null
> +++ b/gnu/packages/aux-files/findclass.php

I can’t believe we’ll have PHP in our code base. :-)

Toggle quote (4 lines)
> +;;; You should have received a copy of the GNU General Public License
> +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
> +(define-module (guix build-system composer)

Missing newline.

Toggle quote (19 lines)
> + (let* ((package-data (read-package-data #:filename composer-file))
> + (scripts (match (assoc-ref package-data "scripts")
> + (('@ script ...) script)
> + (#f '())))
> + (test-script
> + (assoc-ref scripts test-target))
> + (dependencies (filter (lambda (dep) (string-contains dep "/"))
> + (map car
> + (match (assoc-ref package-data "require")
> + (('@ dependency ...) dependency)
> + (#f '())))))
> + (dependencies-dev
> + (filter (lambda (dep) (string-contains dep "/"))
> + (map car
> + (match (assoc-ref package-data "require-dev")
> + (('@ dependency ...) dependency)
> + (#f '())))))
> + (name (assoc-ref package-data "name")))

This is also a case for ‘define-json-mapping’. I suppose we could use
Guile-JSON instead of (guix build json), no?

I think this code and similar occurrences would be less intimidating if
we used ‘define-json-mapping’; it would make the data structures
clearer, unlike here where one has to keep in mind what the list/tree
looks like so they can map car/cdr around.

Toggle quote (3 lines)
> + (for-each
> + (lambda (input)

Like for ‘map’, please indent on the same line:

(for-each (lambda (input)

Toggle quote (11 lines)
> + (match test-script
> + ((? string? command)
> + (unless (equal? (system command) 0)
> + (throw 'failed-command command)))
> + (('@ (? string? command) ...)
> + (for-each
> + (lambda (c)
> + (unless (equal? (system c) 0)
> + (throw 'failed-command c)))
> + command))

Use (zero? x) instead of (equal? 0 x).

Also, why not use ‘invoke’? I this because these commands are really
shell commands and expect things like glob patterns and tilde expansion?
If these are not shell commands, I recommend ‘invoke’, which will report
failures more nicely.

Toggle quote (9 lines)
> +(define (find-php-dep inputs dependency)
> + (let loop ((inputs (map cdr inputs)))
> + (if (null? inputs)
> + (throw 'unsatisfied-dependency "Unsatisfied dependency: required " dependency)
> + (let ((autoload (string-append (car inputs) "/share/web/" dependency "/vendor/autoload_conf.php")))
> + (if (file-exists? autoload)
> + autoload
> + (loop (cdr inputs)))))))

Please use ‘match’ instead of car/cdr.

Toggle quote (21 lines)
> +(define* (create-autoload vendor composer-file inputs #:key dev-dependencies?)
> + (with-output-to-file (string-append vendor "/autoload.php")
> + (lambda _
> + (display "<?php
> +// autoload.php @generated by Guix
> +$map = $psr4map = $classmap = array();
> +")
> + (format #t "require_once '~a/autoload_conf.php'~%" vendor)
> + (format #t "require_once '~a/share/web/composer/ClassLoader.php'~%"
> + (assoc-ref inputs "composer-classloader"))
> + (display "$loader = new \\Composer\\Autoload\\ClassLoader();
> +foreach ($map as $namespace => $path) {
> + $loader->set($namespace, $path);
> +}
> +foreach ($psr4map as $namespace => $path) {
> + $loader->setPsr4($namespace, $path);
> +}
> +$loader->addClassMap($classmap);
> +$loader->register();
> +")))

Please add a docstring explaining what’s happening here. Also, perhaps
use ‘string-append’ instead of ‘format’ so we don’t end up generating
things like:

require_once '#f/autoload_conf.php'

:-)

In short, I think we must pay attention to the style to facilitate
maintainability.

Could you send an updated patch?

Thanks!

Ludo’.
J
J
Julien Lepiller wrote on 19 Sep 2020 01:20
Re: [bug#42338] [PATCH 01/34] guix: import: Add composer importer.
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 42338@debbugs.gnu.org)
20200919012055.1b2e686f@tachikoma.lepiller.eu
Le Fri, 18 Sep 2020 10:31:39 +0200,
Ludovic Courtès <ludo@gnu.org> a écrit :

Toggle quote (64 lines)
> Hi!
>
> Julien Lepiller <julien@lepiller.eu> skribis:
>
> > From 6d521ca9f066f82488abefd5d3630e38305c0fd1 Mon Sep 17 00:00:00
> > 2001 From: Julien Lepiller <julien@lepiller.eu>
> > Date: Tue, 29 Oct 2019 08:07:38 +0100
> > Subject: [PATCH 01/34] guix: import: Add composer importer.
> >
> > * guix/import/composer.scm: New file.
> > * guix/scripts/import/composer.scm: New file.
> > * guix/tests/composer.scm: New file.
> > * Makefile.am: Add them.
> > * guix/scripts/import.scm: Add composer importer.
> > * doc/guix.texi (Invoking guix import): Mention it.
>
> [...]
>
> > +@item composer
> > +@cindex COMPOSER
>
> s/COMPOSER/Composer/ ?
>
> > +Import metadat from the @uref{https://getcomposer.org/, Composer}
> > package
> ^
> metadata
>
> > +archive used by the PHP community.
>
> Could you add an example command line like we have for some of the
> other importers? (It’s also useful for us as a test against the
> actual servers…)
>
> > + (let ((package (json-fetch
> > + (string-append (%composer-base-url) "/p/" name
> > ".json"))))
> > + (if package
> > + (let* ((packages (assoc-ref package "packages"))
> > + (package (assoc-ref packages name))
> > + (versions (filter
> > + (lambda (version)
> > + (and (not (string-contains version
> > "dev"))
> > + (not (string-contains version
> > "beta"))))
> > + (map car package)))
>
> Like I wrote before, I recommend ‘define-json-mapping’. If you prefer
> you can make that change later on once you’ve pushed this first
> version, but I really think it’ll help maintainability.
>
> This should also help avoid (map car …), which is frowned upon in
> Guix. :-)
>
> > + (versions (map
> > + (lambda (version)
>
> Rather indent as: (map (lambda (version)
>
> Otherwise LGTM!
>
> Ludo’.

Thanks, here's a new version
J
J
Julien Lepiller wrote on 19 Sep 2020 01:24
Re: [bug#42338] [PATCH 03/34] guix: Add composer-build-system.
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 42338@debbugs.gnu.org)
20200919012420.301201e8@tachikoma.lepiller.eu
Le Fri, 18 Sep 2020 10:45:48 +0200,
Ludovic Courtès <ludo@gnu.org> a écrit :

Toggle quote (36 lines)
> Hi,
>
> Julien Lepiller <julien@lepiller.eu> skribis:
>
> > + (let* ((package-data (read-package-data #:filename
> > composer-file))
> > + (scripts (match (assoc-ref package-data "scripts")
> > + (('@ script ...) script)
> > + (#f '())))
> > + (test-script
> > + (assoc-ref scripts test-target))
> > + (dependencies (filter (lambda (dep) (string-contains
> > dep "/"))
> > + (map car
> > + (match (assoc-ref
> > package-data "require")
> > + (('@ dependency ...)
> > dependency)
> > + (#f '())))))
> > + (dependencies-dev
> > + (filter (lambda (dep) (string-contains dep "/"))
> > + (map car
> > + (match (assoc-ref package-data
> > "require-dev")
> > + (('@ dependency ...) dependency)
> > + (#f '())))))
> > + (name (assoc-ref package-data "name")))
>
> This is also a case for ‘define-json-mapping’. I suppose we could use
> Guile-JSON instead of (guix build json), no?
>
> I think this code and similar occurrences would be less intimidating
> if we used ‘define-json-mapping’; it would make the data structures
> clearer, unlike here where one has to keep in mind what the list/tree
> looks like so they can map car/cdr around.

I think we already tried that with the node build system, but we had to
revert, because we were importing guile-json from the host side. I
don't remember the details though, so if you think it's OK now, I'll
gladly make the code look nicer :)

Toggle quote (26 lines)
>
> > + (for-each
> > + (lambda (input)
>
> Like for ‘map’, please indent on the same line:
>
> (for-each (lambda (input)
>
> > + (match test-script
> > + ((? string? command)
> > + (unless (equal? (system command) 0)
> > + (throw 'failed-command command)))
> > + (('@ (? string? command) ...)
> > + (for-each
> > + (lambda (c)
> > + (unless (equal? (system c) 0)
> > + (throw 'failed-command c)))
> > + command))
>
> Use (zero? x) instead of (equal? 0 x).
>
> Also, why not use ‘invoke’? I this because these commands are really
> shell commands and expect things like glob patterns and tilde
> expansion? If these are not shell commands, I recommend ‘invoke’,
> which will report failures more nicely.

Here I have a single string that contains shell commands, so I don't
think I can use invoke.
L
L
Ludovic Courtès wrote on 25 Sep 2020 12:27
Re: [bug#42338] [PATCH 01/34] guix: import: Add composer importer.
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 42338@debbugs.gnu.org)
87lfgy179m.fsf@gnu.org
Hi Julien,

Julien Lepiller <julien@lepiller.eu> skribis:

Toggle quote (12 lines)
> From 70b9cb2bb389f3e5f9dcc75a44d7d60c28f997bc Mon Sep 17 00:00:00 2001
> From: Julien Lepiller <julien@lepiller.eu>
> Date: Tue, 29 Oct 2019 08:07:38 +0100
> Subject: [PATCH 01/34] guix: import: Add composer importer.
>
> * guix/import/composer.scm: New file.
> * guix/scripts/import/composer.scm: New file.
> * guix/tests/composer.scm: New file.
> * Makefile.am: Add them.
> * guix/scripts/import.scm: Add composer importer.
> * doc/guix.texi (Invoking guix import): Mention it.

[...]

Toggle quote (2 lines)
> +@cindex PHP
> +Import metadat from the @uref{https://getcomposer.org/, Composer} package
^
Typo.

Toggle quote (18 lines)
> +(define* (composer-fetch name #:optional version)
> + "Return an alist representation of the Composer metadata for the package NAME,
> +or #f on failure."
> + (let ((package (json-fetch
> + (string-append (%composer-base-url) "/p/" name ".json"))))
> + (if package
> + (let* ((packages (assoc-ref package "packages"))
> + (package (or (assoc-ref packages name) package))
> + (versions (filter
> + (lambda (version)
> + (and (not (string-contains version "dev"))
> + (not (string-contains version "beta"))))
> + (map car package)))
> + (version (or (if (null? version) #f version)
> + (latest-version versions))))
> + (assoc-ref package version))
> + #f)))

I think this should directly return a <composer-package> since the all
the callers pass the alist through ‘json->composer-package’. The idea
is that alists should be converted to records as soon as they enter the
process.

Also it’s weird that ‘package’ above has a “packages” (plural) entry.
Perhaps we’re missing another JSON mapping?

[...]

Toggle quote (6 lines)
> +++ b/guix/scripts/import/composer.scm
> @@ -0,0 +1,107 @@
> +;;; GNU Guix --- Functional package management for GNU
> +;;; Copyright © 2015 David Thompson <davet@gnu.org>
> +;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>

You can preserve these two lines if you think it’s relevant, but I’d
suggest adding one for yourself.

OK to push with changes along these lines.

Thanks for taking the time to convert to ‘define-json-mapping’ and all!

Ludo’.
L
L
Ludovic Courtès wrote on 25 Sep 2020 12:33
Re: [bug#42338] [PATCH 03/34] guix: Add composer-build-system.
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 42338@debbugs.gnu.org)
87eemq16y3.fsf@gnu.org
Hi,

Julien Lepiller <julien@lepiller.eu> skribis:

Toggle quote (44 lines)
> Le Fri, 18 Sep 2020 10:45:48 +0200,
> Ludovic Courtès <ludo@gnu.org> a écrit :
>
>> Hi,
>>
>> Julien Lepiller <julien@lepiller.eu> skribis:
>>
>> > + (let* ((package-data (read-package-data #:filename
>> > composer-file))
>> > + (scripts (match (assoc-ref package-data "scripts")
>> > + (('@ script ...) script)
>> > + (#f '())))
>> > + (test-script
>> > + (assoc-ref scripts test-target))
>> > + (dependencies (filter (lambda (dep) (string-contains
>> > dep "/"))
>> > + (map car
>> > + (match (assoc-ref
>> > package-data "require")
>> > + (('@ dependency ...)
>> > dependency)
>> > + (#f '())))))
>> > + (dependencies-dev
>> > + (filter (lambda (dep) (string-contains dep "/"))
>> > + (map car
>> > + (match (assoc-ref package-data
>> > "require-dev")
>> > + (('@ dependency ...) dependency)
>> > + (#f '())))))
>> > + (name (assoc-ref package-data "name")))
>>
>> This is also a case for ‘define-json-mapping’. I suppose we could use
>> Guile-JSON instead of (guix build json), no?
>>
>> I think this code and similar occurrences would be less intimidating
>> if we used ‘define-json-mapping’; it would make the data structures
>> clearer, unlike here where one has to keep in mind what the list/tree
>> looks like so they can map car/cdr around.
>
> I think we already tried that with the node build system, but we had to
> revert, because we were importing guile-json from the host side. I
> don't remember the details though, so if you think it's OK now, I'll
> gladly make the code look nicer :)

Yes please. :-) I think code full of alists/dictionaries would be hard
to read and to maintain since mistakes could end up being silently
ignored or lead to a wrong-type-#f error far down the road.

Also please remember to avoid car/cdr:


As for Guile-JSON: perhaps you can post a draft that we can play with to
see if there’s anything wrong, but off the top of my head I don’t see
why it wouldn’t work.

Toggle quote (21 lines)
>> > + (match test-script
>> > + ((? string? command)
>> > + (unless (equal? (system command) 0)
>> > + (throw 'failed-command command)))
>> > + (('@ (? string? command) ...)
>> > + (for-each
>> > + (lambda (c)
>> > + (unless (equal? (system c) 0)
>> > + (throw 'failed-command c)))
>> > + command))
>>
>> Use (zero? x) instead of (equal? 0 x).
>>
>> Also, why not use ‘invoke’? I this because these commands are really
>> shell commands and expect things like glob patterns and tilde
>> expansion? If these are not shell commands, I recommend ‘invoke’,
>> which will report failures more nicely.
>
> Here I have a single string that contains shell commands, so I don't
> think I can use invoke.

‘system’ passes the string to “sh -c”, which means the string is subject
to shelly things: glob expansion, semicolon interpretation, string
quotation, etc.

If those strings are meant to be shell-interpreted, then passing them to
‘system’ is the right thing. Otherwise, it should be avoided IMO.

Thanks,
Ludo’.
J
J
Julien Lepiller wrote on 29 Sep 2020 16:49
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 42338@debbugs.gnu.org)
20200929164920.0684be42@tachikoma.lepiller.eu
Le Fri, 25 Sep 2020 12:33:56 +0200,
Ludovic Courtès <ludo@gnu.org> a écrit :

Toggle quote (9 lines)
> Hi,
>
> As for Guile-JSON: perhaps you can post a draft that we can play with
> to see if there’s anything wrong, but off the top of my head I don’t
> see why it wouldn’t work.
>
> Thanks,
> Ludo’.

Here's a new version, hopefully this addresses all your remarks. I'm
still not sure how (json) is pulled in to the build side though... How
does guix know it needs to use guile-json-3 instead of guile-json-1 for
instance? How does it work with inferiors?
L
L
Ludovic Courtès wrote on 30 Sep 2020 11:24
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 42338@debbugs.gnu.org)
87blhn39dz.fsf@gnu.org
Hi,

Julien Lepiller <julien@lepiller.eu> skribis:

Toggle quote (5 lines)
> Here's a new version, hopefully this addresses all your remarks. I'm
> still not sure how (json) is pulled in to the build side though... How
> does guix know it needs to use guile-json-3 instead of guile-json-1 for
> instance?

Ah, see below.

Toggle quote (2 lines)
> How does it work with inferiors?

I think inferiors have nothing to do with it.

Toggle quote (11 lines)
> From 432f57aeeb3b2e48591288e6491d66ab299661f0 Mon Sep 17 00:00:00 2001
> From: Julien Lepiller <julien@lepiller.eu>
> Date: Tue, 29 Oct 2019 20:58:51 +0100
> Subject: [PATCH 03/34] guix: Add composer-build-system.
>
> * guix/build-system/composer.scm: New file.
> * guix/build/composer-build-system.scm: New file.
> * gnu/packages/aux-files/findclass.php: New file.
> * Makefile.am: Add them.
> * doc/guix.texi (Build Systems): Document it.

[...]

Toggle quote (9 lines)
> +(define %composer-build-system-modules
> + ;; Build-side modules imported by default.
> + `((guix build composer-build-system)
> + (guix build union)
> + (json)
> + (json builder)
> + (json parser)
> + (json record)

Here, as the comment says, you’re importing (json …) from the host side
to the build side. That’s why it works.

The problem is that it’s just picking whatever (json …) modules are on
your load path on the host side: if you have Guile-JSON 3.x, it’ll use
that, if you have 4.x, that’ll be 4.x, and if you have nothing, it’ll
fail to build.

So the fix is to remove those modules from this list. You should only
ever import Guix modules.

Now you need to bring Guile-JSON into the environment. When using gexp,
we do that with ‘with-extensions’, but here it’s a bit clunky…

Toggle quote (4 lines)
> + (modules '((guix build composer-build-system)
> + (guix build utils)
> + (json))))

I think you don’t need (json) here. (This is the list of modules in
scope.)

Toggle quote (27 lines)
> + (define builder
> + `(begin
> + (use-modules ,@modules)
> + (composer-build #:source ,(match (assoc-ref inputs "source")
> + (((? derivation? source))
> + (derivation->output-path source))
> + ((source)
> + source)
> + (source
> + source))
> + #:system ,system
> + #:outputs %outputs
> + #:inputs %build-inputs
> + #:search-paths ',(map search-path-specification->sexp
> + search-paths)
> + #:phases ,phases
> + #:out-of-source? ,out-of-source?
> + #:composer-file ,composer-file
> + #:tests? ,tests?
> + #:test-target ,test-target
> + #:install-target ,install-target
> + #:validate-runpath? ,validate-runpath?
> + #:patch-shebangs? ,patch-shebangs?
> + #:strip-binaries? ,strip-binaries?
> + #:strip-flags ,strip-flags
> + #:strip-directories ,strip-directories)))

To bring in Guile-JSON, you need to do something similar to what
‘gexp->file’ does with ‘load-path-expression’, along these lines
(untested):

(define guile-json-drv
(package-derivation store
(module-ref (resolve-interface '(gnu packages guile))
'guile-json)
system))

(define builder
`(begin
(add-to-load-path (string-append ,(derivation->output-path guile-json-drv)
"/share/guile/site/"
(effective-version)))
(use-modules ,@modules)
…))

;; …

(build-expression->derivation store name builder
;; …
#:inputs (append inputs
`(("guile-json" ,guile-json-drv))))

I guess clunkiness is the reason why we didn’t do it last time…

HTH!

Ludo’.
J
J
Julien Lepiller wrote on 19 Dec 2020 00:43
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 42338@debbugs.gnu.org)
20201219004318.2c94830d@tachikoma.lepiller.eu
Le Wed, 30 Sep 2020 11:24:08 +0200,
Ludovic Courtès <ludo@gnu.org> a écrit :
Toggle quote (33 lines)
>
> To bring in Guile-JSON, you need to do something similar to what
> ‘gexp->file’ does with ‘load-path-expression’, along these lines
> (untested):
>
> (define guile-json-drv
> (package-derivation store
> (module-ref (resolve-interface '(gnu packages
> guile)) 'guile-json)
> system))
>
> (define builder
> `(begin
> (add-to-load-path (string-append ,(derivation->output-path
> guile-json-drv) "/share/guile/site/"
> (effective-version)))
> (use-modules ,@modules)
> …))
>
> ;; …
>
> (build-expression->derivation store name builder
> ;; …
> #:inputs (append inputs
> `(("guile-json"
> ,guile-json-drv))))
>
> I guess clunkiness is the reason why we didn’t do it last time…
>
> HTH!
>
> Ludo’.

Hi Ludo, sorry for the delay!

I tried that (replacing 'guile-json with 'guile-json-4), but it doesn't
work: when building the package, guix first builds a modules-compiled
that fails because it can't find (json). It seems to be related to the
compilation of (guix build composer-build-system) which uses the (json)
module: when removing the import, it's modules-compiled works (with a
lot of warnings), but obviously guix can't build the php package.
L
L
Ludovic Courtès wrote on 21 Dec 2020 15:51
(name . Julien Lepiller)(address . julien@lepiller.eu)(address . 42338@debbugs.gnu.org)
877dpb6wkw.fsf@gnu.org
Hi,

Julien Lepiller <julien@lepiller.eu> skribis:

Toggle quote (7 lines)
> I tried that (replacing 'guile-json with 'guile-json-4), but it doesn't
> work: when building the package, guix first builds a modules-compiled
> that fails because it can't find (json). It seems to be related to the
> compilation of (guix build composer-build-system) which uses the (json)
> module: when removing the import, it's modules-compiled works (with a
> lot of warnings), but obviously guix can't build the php package.

Ah OK. Well, maybe you can sidestep the issue and use a custom JSON
module instead. Sorry for the broken piece of advice!

Ludo’.
D
(address . 42338@debbugs.gnu.org)
000a01d79803$cbd95220$638bf660$@minikn.xyz
Hello. Is this feature still being worked on? I'd love to make use of it!

Cheers,

Demis.
Attachment: file
M
M
Maxim Cournoyer wrote on 16 Oct 2021 06:15
(name . Ludovic Courtès)(address . ludo@gnu.org)
87zgr9k3lg.fsf_-_@gmail.com
Hey Julien,

That's a pretty interesting series you have there.

Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (62 lines)
> Hi Julien,
>
> Julien Lepiller <julien@lepiller.eu> skribis:
>
>> From 70b9cb2bb389f3e5f9dcc75a44d7d60c28f997bc Mon Sep 17 00:00:00 2001
>> From: Julien Lepiller <julien@lepiller.eu>
>> Date: Tue, 29 Oct 2019 08:07:38 +0100
>> Subject: [PATCH 01/34] guix: import: Add composer importer.
>>
>> * guix/import/composer.scm: New file.
>> * guix/scripts/import/composer.scm: New file.
>> * guix/tests/composer.scm: New file.
>> * Makefile.am: Add them.
>> * guix/scripts/import.scm: Add composer importer.
>> * doc/guix.texi (Invoking guix import): Mention it.
>
> [...]
>
>> +@cindex PHP
>> +Import metadat from the @uref{https://getcomposer.org/, Composer} package
> ^
> Typo.
>
>> +(define* (composer-fetch name #:optional version)
>> + "Return an alist representation of the Composer metadata for the package NAME,
>> +or #f on failure."
>> + (let ((package (json-fetch
>> + (string-append (%composer-base-url) "/p/" name ".json"))))
>> + (if package
>> + (let* ((packages (assoc-ref package "packages"))
>> + (package (or (assoc-ref packages name) package))
>> + (versions (filter
>> + (lambda (version)
>> + (and (not (string-contains version "dev"))
>> + (not (string-contains version "beta"))))
>> + (map car package)))
>> + (version (or (if (null? version) #f version)
>> + (latest-version versions))))
>> + (assoc-ref package version))
>> + #f)))
>
> I think this should directly return a <composer-package> since the all
> the callers pass the alist through ‘json->composer-package’. The idea
> is that alists should be converted to records as soon as they enter the
> process.
>
> Also it’s weird that ‘package’ above has a “packages” (plural) entry.
> Perhaps we’re missing another JSON mapping?
>
> [...]
>
>> +++ b/guix/scripts/import/composer.scm
>> @@ -0,0 +1,107 @@
>> +;;; GNU Guix --- Functional package management for GNU
>> +;;; Copyright © 2015 David Thompson <davet@gnu.org>
>> +;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
>
> You can preserve these two lines if you think it’s relevant, but I’d
> suggest adding one for yourself.
>
> OK to push with changes along these lines.

Seems you were almost ready to roll. Consider this a very gentle ping
:-).

Maxim
J
J
Julien Lepiller wrote on 13 Aug 2022 22:38
Re: Ping about php composer
A9377C37-B79F-4498-B737-AF94B05DBFD3@lepiller.eu
Hi Mája

You're more than welcome to take the patch series to the finish line! I don't think I'm able to work on it, but I can answer questions if you have any.

Le 13 août 2022 22:30:47 GMT+02:00, "Mája Tomášek" <maya.tomasek@disroot.org> a écrit :
Toggle quote (9 lines)
>Hi,
>
>I wanted to ask, would you be interested in finishing your php composer
>patch to get it pushed? Or if not, can I take you code to the finish
>line appyling those last few requests?
>
>Regards,
>
>Maya
Attachment: file
M
M
Mája Tomášek wrote on 13 Aug 2022 22:30
Ping about php composer
87r11jevig.fsf@disroot.org
Hi,

I wanted to ask, would you be interested in finishing your php composer
patch to get it pushed? Or if not, can I take you code to the finish
line appyling those last few requests?

Regards,

Maya
M
M
Maxime Devos wrote on 6 Oct 2022 18:27
Re: [PATCH] Add composer build system (PHP)
898f609e-c396-5015-ce7f-93ef284c383d@telenet.be
Hi,
I think I'll have some time to finish this, but first I'd like to ask if
someone else had taken / is taking a stab at this.
Greetings,
Maxime.
Attachment: OpenPGP_signature
M
M
Mája Tomášek wrote on 11 Oct 2022 20:07
878rlmgro3.fsf@disroot.org
Maxime Devos <maximedevos@telenet.be> writes:

Toggle quote (8 lines)
> Hi,
>
> I think I'll have some time to finish this, but first I'd like to ask if
> someone else had taken / is taking a stab at this.
>
> Greetings,
> Maxime.

Hi,

I have not managed to rebase these patches and sadly I don't have the time
for this right now. :/

Maya
A
A
Adam Faiz wrote on 21 Apr 2023 02:23
[PATCH] Add composer build system (PHP)
(address . 42338@debbugs.gnu.org)
099bcd2b-ed5b-6d5d-b7cf-c5aeef255c6d@disroot.org
Hi,

I'm interested in this composer build system so that I can start packaging the NextCloud server and its dependencies.
I've rebased the patches and modified them a bit:

1. The composer importer now uses the new inputs style for importing
2. The composer build system uses gexps

However, there are a few bugs that I don't know how to fix.

The --recursive option of the importer doesn't work:

===
In guix/scripts/import.scm:
89:11 4 (guix-import . _)
In guix/scripts/import/composer.scm:ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Throw to key `match-error' with args `("match" "no matching pattern" #<unspecified>)'.

98:17 3 (guix-import-composer . _)
In guix/import/utils.scm:
638:27 2 (recursive-import "psr/http-client" # _ #:guix-name _ . #)
630:33 1 (lookup-node "psr/http-client" #f)
In ice-9/eval.scm:
423:17 0 (_ . _)

ice-9/eval.scm:423:17: In procedure eval: Wrong number of arguments
===


I think there's something wrong with (define-json-mapping <composer-autoload>:

===
error: in phase 'install': uncaught exception:
match-error "match" "no matching pattern" #<unspecified>

In guix/build/gnu-build-system.scm:
927:23 6 (_)
In guix/build/composer-build-system.scm:
200:23 5 (install #:inputs _ #:outputs _ #:composer-file _)
In ice-9/ports.scm:
433:17 4 (call-with-input-file _ _ #:binary _ #:encoding _ # _)
In guix/build/composer-build-system.scm:
56:0 3 (json->composer-package (("config" ("allow-plug…" …)) …))
52:12 2 (json->composer-autoload (("psr-4" ("Doctrine\\…" . #))))
In ice-9/boot-9.scm:
1685:16 1 (raise-exception _ #:continuable? _)
1685:16 0 (raise-exception _ #:continuable? _)

ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Throw to key `match-error' with args `("match" "no matching pattern" #<unspecified>)'.
===
From d8814cc803f26c63c1c1ac55c45132324b1446a4 Mon Sep 17 00:00:00 2001
Message-Id: <d8814cc803f26c63c1c1ac55c45132324b1446a4.1682034341.git.adam.faiz@disroot.org>
In-Reply-To: <0d44f8f1e66c4141d0c97aa2b633091a0bb753e5.1682034340.git.adam.faiz@disroot.org>
References: <0d44f8f1e66c4141d0c97aa2b633091a0bb753e5.1682034340.git.adam.faiz@disroot.org>
From: Julien Lepiller <julien@lepiller.eu>
Date: Thu, 20 Apr 2023 07:22:37 +0800
Subject: [PATCH 2/3] gnu: Add composer-classloader.

* gnu/packages/php-xyz.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
---
gnu/local.mk | 1 +
gnu/packages/php-xyz.scm | 61 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
create mode 100644 gnu/packages/php-xyz.scm

Toggle diff (81 lines)
diff --git a/gnu/local.mk b/gnu/local.mk
index 7f6ea08b93..025fd5e09b 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -495,6 +495,7 @@ GNU_SYSTEM_MODULES = \
%D%/packages/photo.scm \
%D%/packages/phabricator.scm \
%D%/packages/php.scm \
+ %D%/packages/php-xyz.scm \
%D%/packages/piet.scm \
%D%/packages/pikchr.scm \
%D%/packages/pkg-config.scm \
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
new file mode 100644
index 0000000000..dab660f84f
--- /dev/null
+++ b/gnu/packages/php-xyz.scm
@@ -0,0 +1,61 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (gnu packages php-xyz)
+ #:use-module (gnu packages)
+ #:use-module (gnu packages php)
+ #:use-module (guix packages)
+ #:use-module (guix download)
+ #:use-module (guix git-download)
+ #:use-module (guix build-system composer)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix utils)
+ #:use-module ((guix licenses) #:prefix license:))
+
+(define-public composer-classloader
+ (package
+ (name "composer-classloader")
+ (version "1.9.0")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/composer/composer.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0127zmmg3yx84ljngfs86q7kjhyypybkf4d1ihfrfnzgynzxfxdf"))))
+ (build-system gnu-build-system)
+ (arguments
+ `(#:phases
+ (modify-phases %standard-phases
+ (delete 'configure)
+ (delete 'build)
+ (delete 'check)
+ (replace 'install
+ (lambda* (#:key outputs #:allow-other-keys)
+ (let* ((out (assoc-ref outputs "out"))
+ (install (string-append out "/share/web/composer/ClassLoader.php")))
+ (mkdir-p (dirname install))
+ (copy-file "src/Composer/Autoload/ClassLoader.php" install)))))))
+ (home-page "https://getcomposer.org")
+ (synopsis "PHP class loader extracted from the composer package")
+ (description "This package contains the class loader class used by Composer to
+build its autoloading feature. This package is used by the composer-build-system
+to build its own store-aware autoloading feature.")
+ (license license:expat)))
--
2.39.2
N
N
Nicolas Graves wrote on 26 Sep 2023 12:31
[PATCH v3 2/7] gnu: Add composer-classloader.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
a2045c10b011d77cb507b0d965cb1ab3c8ad2383.1695724304.git.ngraves@ngraves.fr
* gnu/packages/php-xyz.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
---
gnu/local.mk | 1 +
gnu/packages/php-xyz.scm | 61 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
create mode 100644 gnu/packages/php-xyz.scm

Toggle diff (81 lines)
diff --git a/gnu/local.mk b/gnu/local.mk
index bfa816d717..8cd0e0537b 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -501,6 +501,7 @@ GNU_SYSTEM_MODULES = \
%D%/packages/photo.scm \
%D%/packages/phabricator.scm \
%D%/packages/php.scm \
+ %D%/packages/php-xyz.scm \
%D%/packages/piet.scm \
%D%/packages/pikchr.scm \
%D%/packages/pkg-config.scm \
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
new file mode 100644
index 0000000000..dab660f84f
--- /dev/null
+++ b/gnu/packages/php-xyz.scm
@@ -0,0 +1,61 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (gnu packages php-xyz)
+ #:use-module (gnu packages)
+ #:use-module (gnu packages php)
+ #:use-module (guix packages)
+ #:use-module (guix download)
+ #:use-module (guix git-download)
+ #:use-module (guix build-system composer)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix utils)
+ #:use-module ((guix licenses) #:prefix license:))
+
+(define-public composer-classloader
+ (package
+ (name "composer-classloader")
+ (version "1.9.0")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/composer/composer.git")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0127zmmg3yx84ljngfs86q7kjhyypybkf4d1ihfrfnzgynzxfxdf"))))
+ (build-system gnu-build-system)
+ (arguments
+ `(#:phases
+ (modify-phases %standard-phases
+ (delete 'configure)
+ (delete 'build)
+ (delete 'check)
+ (replace 'install
+ (lambda* (#:key outputs #:allow-other-keys)
+ (let* ((out (assoc-ref outputs "out"))
+ (install (string-append out "/share/web/composer/ClassLoader.php")))
+ (mkdir-p (dirname install))
+ (copy-file "src/Composer/Autoload/ClassLoader.php" install)))))))
+ (home-page "https://getcomposer.org")
+ (synopsis "PHP class loader extracted from the composer package")
+ (description "This package contains the class loader class used by Composer to
+build its autoloading feature. This package is used by the composer-build-system
+to build its own store-aware autoloading feature.")
+ (license license:expat)))
--
2.41.0
N
N
Nicolas Graves wrote on 26 Sep 2023 12:31
[PATCH v3 1/7] guix: import: Add composer importer.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
6abfbb4d4d57642fea6bae5835ff0d365de7e24a.1695724304.git.ngraves@ngraves.fr
* guix/import/composer.scm: New file.
* guix/scripts/import/composer.scm: New file.
* guix/tests/composer.scm: New file.
* Makefile.am: Add them.
* guix/scripts/import.scm: Add composer importer.
* doc/guix.texi (Invoking guix import): Mention it.
---
Makefile.am | 3 +
doc/guix.texi | 20 +++
guix/import/composer.scm | 270 +++++++++++++++++++++++++++++++
guix/scripts/import.scm | 2 +-
guix/scripts/import/composer.scm | 107 ++++++++++++
tests/composer.scm | 92 +++++++++++
6 files changed, 493 insertions(+), 1 deletion(-)
create mode 100644 guix/import/composer.scm
create mode 100644 guix/scripts/import/composer.scm
create mode 100644 tests/composer.scm

Toggle diff (508 lines)
diff --git a/Makefile.am b/Makefile.am
index 8924974e8a..3ce7ee832e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -274,6 +274,7 @@ MODULES = \
guix/search-paths.scm \
guix/packages.scm \
guix/import/cabal.scm \
+ guix/import/composer.scm \
guix/import/cpan.scm \
guix/import/cran.scm \
guix/import/crate.scm \
@@ -332,6 +333,7 @@ MODULES = \
guix/scripts/home/import.scm \
guix/scripts/lint.scm \
guix/scripts/challenge.scm \
+ guix/scripts/import/composer.scm \
guix/scripts/import/crate.scm \
guix/scripts/import/cpan.scm \
guix/scripts/import/cran.scm \
@@ -500,6 +502,7 @@ SCM_TESTS = \
tests/challenge.scm \
tests/channels.scm \
tests/combinators.scm \
+ tests/composer.scm \
tests/containers.scm \
tests/cpan.scm \
tests/cpio.scm \
diff --git a/doc/guix.texi b/doc/guix.texi
index 46591b2f64..4d2fc11cd7 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -14530,6 +14530,26 @@ Invoking guix import
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
+
+@item composer
+@cindex Composer
+@cindex PHP
+Import metadat from the @uref{https://getcomposer.org/, Composer} package
+archive used by the PHP community, as in this example:
+
+@example
+guix import composer phpunit/phpunit
+@end example
+
+Additional options include:
+
@table @code
@item --recursive
@itemx -r
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
new file mode 100644
index 0000000000..c152f402bb
--- /dev/null
+++ b/guix/import/composer.scm
@@ -0,0 +1,270 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix import composer)
+ #:use-module (ice-9 match)
+ #:use-module (json)
+ #:use-module (gcrypt hash)
+ #:use-module (guix base32)
+ #:use-module (guix build git)
+ #:use-module (guix build utils)
+ #:use-module (guix build-system)
+ #:use-module (guix import json)
+ #:use-module (guix import utils)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (guix packages)
+ #:use-module (guix serialization)
+ #:use-module (guix upstream)
+ #:use-module (guix utils)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-11)
+ #:use-module (srfi srfi-26)
+ #:export (composer->guix-package
+ %composer-updater
+ composer-recursive-import
+
+ %composer-base-url))
+
+(define %composer-base-url
+ (make-parameter "https://repo.packagist.org"))
+
+;; XXX adapted from (guix scripts hash)
+(define (file-hash file select? recursive?)
+ ;; Compute the hash of FILE.
+ (if recursive?
+ (let-values (((port get-hash) (open-sha256-port)))
+ (write-file file port #:select? select?)
+ (force-output port)
+ (get-hash))
+ (call-with-input-file file port-sha256)))
+
+;; XXX taken from (guix scripts hash)
+(define (vcs-file? file stat)
+ (case (stat:type stat)
+ ((directory)
+ (member (basename file) '(".bzr" ".git" ".hg" ".svn" "CVS")))
+ ((regular)
+ ;; Git sub-modules have a '.git' file that is a regular text file.
+ (string=? (basename file) ".git"))
+ (else
+ #f)))
+
+(define (fix-version version)
+ "Return a fixed version from a version string. For instance, v10.1 -> 10.1"
+ (cond
+ ((string-prefix? "version" version)
+ (if (char-set-contains? char-set:digit (string-ref version 7))
+ (substring version 7)
+ (substring version 8)))
+ ((string-prefix? "v" version)
+ (substring version 1))
+ (else version)))
+
+(define (latest-version versions)
+ (fold (lambda (a b) (if (version>? (fix-version a) (fix-version b)) a b))
+ (car versions) versions))
+
+(define (json->require dict)
+ (if dict
+ (let loop ((result '()) (require dict))
+ (match require
+ (() result)
+ ((((? (cut string-contains <> "/") name) . _)
+ require ...)
+ (loop (cons name result) require))
+ ((_ require ...) (loop result require))))
+ '()))
+
+(define-json-mapping <composer-source> make-composer-source composer-source?
+ json->composer-source
+ (type composer-source-type)
+ (url composer-source-url)
+ (reference composer-source-reference))
+
+(define-json-mapping <composer-package> make-composer-package composer-package?
+ json->composer-package
+ (description composer-package-description)
+ (homepage composer-package-homepage)
+ (source composer-package-source "source" json->composer-source)
+ (name composer-package-name "name" php-package-name)
+ (version composer-package-version "version" fix-version)
+ (require composer-package-require "require" json->require)
+ (dev-require composer-package-dev-require "require-dev" json->require)
+ (license composer-package-license "license"
+ (lambda (vector)
+ (map string->license (vector->list vector)))))
+
+(define* (composer-fetch name #:optional version)
+ "Return an alist representation of the Composer metadata for the package NAME,
+or #f on failure."
+ (let ((package (json-fetch
+ (string-append (%composer-base-url) "/p/" name ".json"))))
+ (if package
+ (let* ((packages (assoc-ref package "packages"))
+ (package (or (assoc-ref packages name) package))
+ (versions (filter
+ (lambda (version)
+ (and (not (string-contains version "dev"))
+ (not (string-contains version "beta"))))
+ (map car package)))
+ (version (or (if (null? version) #f version)
+ (latest-version versions))))
+ (assoc-ref package version))
+ #f)))
+
+(define (php-package-name name)
+ "Given the NAME of a package on Packagist, return a Guix-compliant name for
+the package."
+ (let ((name (string-join (string-split name #\/) "-")))
+ (if (string-prefix? "php-" name)
+ (snake-case name)
+ (string-append "php-" (snake-case name)))))
+
+(define (make-php-sexp composer-package)
+ "Return the `package' s-expression for a PHP package for the given
+COMPOSER-PACKAGE."
+ (let* ((source (composer-package-source composer-package))
+ (dependencies (map php-package-name
+ (composer-package-require composer-package)))
+ (dev-dependencies (map php-package-name
+ (composer-package-dev-require composer-package)))
+ (git? (equal? (composer-source-type source) "git")))
+ ((if git? call-with-temporary-directory call-with-temporary-output-file)
+ (lambda* (temp #:optional port)
+ (and (if git?
+ (begin
+ (mkdir-p temp)
+ (git-fetch (composer-source-url source)
+ (composer-source-reference source)
+ temp))
+ (url-fetch (composer-source-url source) temp))
+ `(package
+ (name ,(composer-package-name composer-package))
+ (version ,(composer-package-version composer-package))
+ (source (origin
+ ,@(if git?
+ `((method git-fetch)
+ (uri (git-reference
+ (url ,(composer-source-url source))
+ (commit ,(composer-source-reference source))))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ ,(bytevector->nix-base32-string
+ (file-hash temp (negate vcs-file?) #t)))))
+ `((method url-fetch)
+ (uri ,(composer-source-url source))
+ (sha256 (base32 ,(guix-hash-url temp)))))))
+ (build-system composer-build-system)
+ ,@(if (null? dependencies)
+ '()
+ `((inputs
+ (,'quasiquote
+ ,(map (lambda (name)
+ `(,name
+ (,'unquote
+ ,(string->symbol name))))
+ dependencies)))))
+ ,@(if (null? dev-dependencies)
+ '()
+ `((native-inputs
+ (,'quasiquote
+ ,(map (lambda (name)
+ `(,name
+ (,'unquote
+ ,(string->symbol name))))
+ dev-dependencies)))))
+ (synopsis "")
+ (description ,(composer-package-description composer-package))
+ (home-page ,(composer-package-homepage composer-package))
+ (license ,(match (composer-package-license composer-package)
+ (() #f)
+ ((license) license)
+ (_ license)))))))))
+
+(define* (composer->guix-package package-name #:optional version)
+ "Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
+`package' s-expression corresponding to that package, or #f on failure."
+ (let ((package (composer-fetch package-name version)))
+ (and package
+ (let* ((package (json->composer-package package))
+ (dependencies-names (composer-package-require package))
+ (dev-dependencies-names (composer-package-dev-require package)))
+ (values (make-php-sexp package)
+ (append dependencies-names dev-dependencies-names))))))
+
+(define (guix-name->composer-name name)
+ "Given a guix package name, return the name of the package in Packagist."
+ (if (string-prefix? "php-" name)
+ (let ((components (string-split (substring name 4) #\-)))
+ (match components
+ ((namespace name ...)
+ (string-append namespace "/" (string-join name "-")))))
+ name))
+
+(define (guix-package->composer-name package)
+ "Given a Composer PACKAGE built from Packagist, return the name of the
+package in Packagist."
+ (let ((upstream-name (assoc-ref
+ (package-properties package)
+ 'upstream-name))
+ (name (package-name package)))
+ (if upstream-name
+ upstream-name
+ (guix-name->composer-name name))))
+
+(define (string->license str)
+ "Convert the string STR into a license object."
+ (match str
+ ("GNU LGPL" 'license:lgpl2.0)
+ ("GPL" 'license:gpl3)
+ ((or "BSD" "BSD License" "BSD-3-Clause") 'license:bsd-3)
+ ((or "MIT" "MIT license" "Expat license") 'license:expat)
+ ("Public domain" 'license:public-domain)
+ ((or "Apache License, Version 2.0" "Apache 2.0") 'license:asl2.0)
+ (_ #f)))
+
+(define (php-package? package)
+ "Return true if PACKAGE is a PHP package from Packagist."
+ (and
+ (eq? (build-system-name (package-build-system package)) 'composer)
+ (string-prefix? "php-" (package-name package))))
+
+(define (latest-release package)
+ "Return an <upstream-source> for the latest release of PACKAGE."
+ (let* ((php-name (guix-package->composer-name package))
+ (metadata (composer-fetch php-name))
+ (package (json->composer-package metadata))
+ (version (composer-package-version package))
+ (url (composer-source-url (composer-package-source package))))
+ (upstream-source
+ (package (package-name package))
+ (version version)
+ (urls (list url)))))
+
+(define %composer-updater
+ (upstream-updater
+ (name 'composer)
+ (description "Updater for Composer packages")
+ (pred php-package?)
+ (import latest-release)))
+
+(define* (composer-recursive-import package-name #:optional version)
+ (recursive-import package-name '()
+ #:repo->guix-package composer->guix-package
+ #:guix-name php-package-name))
diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm
index 4ddd8d46a1..8c58dd35e2 100644
--- a/guix/scripts/import.scm
+++ b/guix/scripts/import.scm
@@ -47,7 +47,7 @@ (define %standard-import-options '())
(define importers '("gnu" "pypi" "cpan" "hackage" "stackage" "egg" "elpa"
"gem" "go" "cran" "crate" "texlive" "json" "opam"
- "minetest" "elm" "hexpm"))
+ "minetest" "elm" "hexpm" "composer"))
(define (resolve-importer name)
(let ((module (resolve-interface
diff --git a/guix/scripts/import/composer.scm b/guix/scripts/import/composer.scm
new file mode 100644
index 0000000000..412bae6318
--- /dev/null
+++ b/guix/scripts/import/composer.scm
@@ -0,0 +1,107 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2015 David Thompson <davet@gnu.org>
+;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix scripts import composer)
+ #:use-module (guix ui)
+ #:use-module (guix utils)
+ #:use-module (guix scripts)
+ #:use-module (guix import composer)
+ #:use-module (guix scripts import)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-11)
+ #:use-module (srfi srfi-37)
+ #:use-module (srfi srfi-41)
+ #:use-module (ice-9 match)
+ #:use-module (ice-9 format)
+ #:export (guix-import-composer))
+
+
+;;;
+;;; Command-line options.
+;;;
+
+(define %default-options
+ '())
+
+(define (show-help)
+ (display (G_ "Usage: guix import composer PACKAGE-NAME
+Import and convert the Composer package for PACKAGE-NAME.\n"))
+ (display (G_ "
+ -h, --help display this help and exit"))
+ (display (G_ "
+ -V, --version display version information and exit"))
+ (display (G_ "
+ -r, --recursive generate package expressions for all Composer packages\
+ that are not yet in Guix"))
+ (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 composer")))
+ (option '(#\r "recursive") #f #f
+ (lambda (opt name arg result)
+ (alist-cons 'recursive #t result)))
+ %standard-import-options))
+
+
+;;;
+;;; Entry point.
+;;;
+
+(define (guix-import-composer . 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))
+ (args (filter-map (match-lambda
+ (('argument . value)
+ value)
+ (_ #f))
+ (reverse opts))))
+ (match args
+ ((package-name)
+ (if (assoc-ref opts 'recursive)
+ (map (match-lambda
+ ((and ('package ('name name) . rest) pkg)
+ `(define-public ,(string->symbol name)
+ ,pkg))
+ (_ #f))
+ (composer-recursive-import package-name))
+ (let ((sexp (composer->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/composer.scm b/tests/composer.scm
new file mode 100644
index 0000000000..cefaf9f434
--- /dev/null
+++ b/tests/composer.scm
@@ -0,0 +1,92 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (test-composer)
+ #:use-module (guix import composer)
+ #:use-module (guix base32)
+ #:use-module (gcrypt hash)
+ #:use-module (guix tests http)
+ #:use-module (guix grafts)
+ #:use-module (srfi srfi-64)
+ #:use-module (web client)
+ #:use-module (ice-9 match))
+
+;; Globally disable grafts because they can trigger early builds.
+(%graft? #f)
+
+(define test-json
+ "{
+ \"packages\": {
+ \"foo/bar\": {
+ \"0.1\": {
+ \"name\": \"foo/bar\",
+ \"description\": \"description\",
+ \"keywords\": [\"testing\"],
+ \"homepage\": \"http://example.com\",
+
This message was truncated. Download the full message here.
N
N
Nicolas Graves wrote on 26 Sep 2023 12:31
[PATCH v3 4/7] guix: import: composer: Use memoization.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
7fa9b1098369b75b162944d5db9a6d646af115ad.1695724304.git.ngraves@ngraves.fr
---
guix/import/composer.scm | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)

Toggle diff (51 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index c152f402bb..177dc63092 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -27,6 +27,7 @@ (define-module (guix import composer)
#:use-module (guix import json)
#:use-module (guix import utils)
#:use-module ((guix licenses) #:prefix license:)
+ #:use-module (guix memoization)
#:use-module (guix packages)
#:use-module (guix serialization)
#:use-module (guix upstream)
@@ -197,16 +198,18 @@ (define (make-php-sexp composer-package)
((license) license)
(_ license)))))))))
-(define* (composer->guix-package package-name #:optional version)
- "Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
+(define composer->guix-package
+ (memoize
+ (lambda* (package-name #:key version #:allow-other-keys)
+ "Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
`package' s-expression corresponding to that package, or #f on failure."
- (let ((package (composer-fetch package-name version)))
- (and package
- (let* ((package (json->composer-package package))
- (dependencies-names (composer-package-require package))
- (dev-dependencies-names (composer-package-dev-require package)))
- (values (make-php-sexp package)
- (append dependencies-names dev-dependencies-names))))))
+ (let ((package (composer-fetch package-name version)))
+ (and package
+ (let* ((package (json->composer-package package))
+ (dependencies-names (composer-package-require package))
+ (dev-dependencies-names (composer-package-dev-require package)))
+ (values (make-php-sexp package)
+ (append dependencies-names dev-dependencies-names))))))))
(define (guix-name->composer-name name)
"Given a guix package name, return the name of the package in Packagist."
@@ -265,6 +268,7 @@ (define %composer-updater
(import latest-release)))
(define* (composer-recursive-import package-name #:optional version)
- (recursive-import package-name '()
+ (recursive-import package-name
+ #:version version
#:repo->guix-package composer->guix-package
#:guix-name php-package-name))
--
2.41.0
N
N
Nicolas Graves wrote on 26 Sep 2023 12:31
[PATCH v3 3/7] guix: Add composer-build-system.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
1b5d97a0fdbc7ee0fb031e7488f4ca6ab8c28544.1695724304.git.ngraves@ngraves.fr
* guix/build-system/composer.scm: New file.
* guix/build/composer-build-system.scm: New file.
* gnu/packages/aux-files/findclass.php: New file.
* Makefile.am: Add them.
* doc/guix.texi (Build Systems): Document it.
---
Makefile.am | 3 +
doc/guix.texi | 14 ++
gnu/packages/aux-files/findclass.php | 125 ++++++++++++++
guix/build-system/composer.scm | 162 ++++++++++++++++++
guix/build/composer-build-system.scm | 239 +++++++++++++++++++++++++++
5 files changed, 543 insertions(+)
create mode 100644 gnu/packages/aux-files/findclass.php
create mode 100644 guix/build-system/composer.scm
create mode 100644 guix/build/composer-build-system.scm

Toggle diff (483 lines)
diff --git a/Makefile.am b/Makefile.am
index 3ce7ee832e..903fc42afa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -149,6 +149,7 @@ MODULES = \
guix/build-system/chicken.scm \
guix/build-system/clojure.scm \
guix/build-system/cmake.scm \
+ guix/build-system/composer.scm \
guix/build-system/dub.scm \
guix/build-system/dune.scm \
guix/build-system/elm.scm \
@@ -206,6 +207,7 @@ MODULES = \
guix/build/cargo-utils.scm \
guix/build/chicken-build-system.scm \
guix/build/cmake-build-system.scm \
+ guix/build/composer-build-system.scm \
guix/build/dub-build-system.scm \
guix/build/dune-build-system.scm \
guix/build/elm-build-system.scm \
@@ -411,6 +413,7 @@ dist_noinst_DATA = \
AUX_FILES = \
gnu/packages/aux-files/chromium/master-preferences.json \
gnu/packages/aux-files/emacs/guix-emacs.el \
+ gnu/packages/aux-files/findclass.php \
gnu/packages/aux-files/guix.vim \
gnu/packages/aux-files/linux-libre/6.4-arm.conf \
gnu/packages/aux-files/linux-libre/6.4-arm64.conf \
diff --git a/doc/guix.texi b/doc/guix.texi
index 4d2fc11cd7..d133e43773 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -9545,6 +9545,20 @@ Build Systems
@code{-O2 -g}, as is the case for Autoconf-based packages by default.
@end defvar
+@defvar {Scheme Variable} composer-build-system
+This variable is exported by @code{(guix build-system composer)}. It
+implements the build procedure for packages using
+@url{https://getcomposer.org/, Composer}, the PHP package manager.
+
+It automatically adds the @code{php} package to the set of inputs. Which
+package is used can be specified with the @code{#:php} parameter.
+
+The @code{#:test-target} parameter is used to control which script is run
+for the tests. By default, the @code{test} script is run if it exists. If
+the script does not exist, the build system will run @code{phpunit} from the
+source directory, assuming there is a @file{phpunit.xml} file.
+@end defvar
+
@defvar dune-build-system
This variable is exported by @code{(guix build-system dune)}. It
supports builds of packages using @uref{https://dune.build/, Dune}, a build
diff --git a/gnu/packages/aux-files/findclass.php b/gnu/packages/aux-files/findclass.php
new file mode 100644
index 0000000000..d0b250c8e1
--- /dev/null
+++ b/gnu/packages/aux-files/findclass.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * The content of this file is copied from composer's src/Composer/Autoload/ClassMapGenerator.php
+ * the findClasses method was extracted, to prevent using any dependency.
+ *
+ * Composer (and thus this file) is distributed under the expat license, and
+ * ClassMapGenerator.php also contains this notice:
+ *
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * This file is copied from the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * To the extent to wich it makes sense, as the author of the extract:
+ * Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
+ */
+
+/**
+ * Extract the classes in the given file
+ *
+ * @param string $path The file to check
+ * @throws \RuntimeException
+ * @return array The found classes
+ */
+function findClasses($path)
+{
+ $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
+ if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
+ $extraTypes .= '|enum';
+ }
+ // Use @ here instead of Silencer to actively suppress 'unhelpful' output
+ // @link https://github.com/composer/composer/pull/4886
+ $contents = @php_strip_whitespace($path);
+ if (!$contents) {
+ if (!file_exists($path)) {
+ $message = 'File at "%s" does not exist, check your classmap definitions';
+ } elseif (!is_readable($path)) {
+ $message = 'File at "%s" is not readable, check its permissions';
+ } elseif ('' === trim(file_get_contents($path))) {
+ // The input file was really empty and thus contains no classes
+ return array();
+ } else {
+ $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
+ }
+ $error = error_get_last();
+ if (isset($error['message'])) {
+ $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
+ }
+ throw new \RuntimeException(sprintf($message, $path));
+ }
+ // return early if there is no chance of matching anything in this file
+ if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
+ return array();
+ }
+ // strip heredocs/nowdocs
+ $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
+ // strip strings
+ $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
+ // strip leading non-php code if needed
+ if (substr($contents, 0, 2) !== '<?') {
+ $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
+ if ($replacements === 0) {
+ return array();
+ }
+ }
+ // strip non-php blocks in the file
+ $contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
+ // strip trailing non-php code if needed
+ $pos = strrpos($contents, '?>');
+ if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
+ $contents = substr($contents, 0, $pos);
+ }
+ // strip comments if short open tags are in the file
+ if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
+ $contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
+ }
+ preg_match_all('{
+ (?:
+ \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
+ | \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;]
+ )
+ }ix', $contents, $matches);
+ $classes = array();
+ $namespace = '';
+ for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
+ if (!empty($matches['ns'][$i])) {
+ $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
+ } else {
+ $name = $matches['name'][$i];
+ // skip anon classes extending/implementing
+ if ($name === 'extends' || $name === 'implements') {
+ continue;
+ }
+ if ($name[0] === ':') {
+ // This is an XHP class, https://github.com/facebook/xhp
+ $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
+ } elseif ($matches['type'][$i] === 'enum') {
+ // In Hack, something like:
+ // enum Foo: int { HERP = '123'; }
+ // The regex above captures the colon, which isn't part of
+ // the class name.
+ $name = rtrim($name, ':');
+ }
+ $classes[] = ltrim($namespace . $name, '\\');
+ }
+ }
+ return $classes;
+}
+
+$options = getopt('i:f:', []);
+$file = $options["f"];
+$input = $options["i"];
+
+$classes = findClasses($file);
+foreach($classes as $class) {
+ echo '$classmap[\''.$class.'\'] = \''.$input.'/'.$file.'\';';
+ echo "\n";
+}
diff --git a/guix/build-system/composer.scm b/guix/build-system/composer.scm
new file mode 100644
index 0000000000..8bf99ff9c5
--- /dev/null
+++ b/guix/build-system/composer.scm
@@ -0,0 +1,162 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+(define-module (guix build-system composer)
+ #:use-module (guix store)
+ #:use-module (guix utils)
+ #:use-module (guix derivations)
+ #:use-module (guix search-paths)
+ #:use-module (guix build-system)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix gexp)
+ #:use-module (guix packages)
+ #:use-module (gnu packages)
+ #:use-module (ice-9 match)
+ #:use-module (srfi srfi-1)
+ #:export (%composer-build-system-modules
+ lower
+ composer-build
+ composer-build-system))
+
+;; Commentary:
+;;
+;; Standard build procedure for PHP packages using Composer. This is implemented
+;; as an extension of `gnu-build-system'.
+;;
+;; Code:
+
+(define (default-php)
+ "Return the default PHP package."
+
+ ;; Do not use `@' to avoid introducing circular dependencies.
+ (let ((module (resolve-interface '(gnu packages php))))
+ (module-ref module 'php)))
+
+(define (default-findclass)
+ "Return the default findclass script."
+ (search-auxiliary-file "findclass.php"))
+
+(define (default-composer-classloader)
+ "Return the default composer-classloader package."
+
+ ;; Do not use `@' to avoid introducing circular dependencies.
+ (let ((module (resolve-interface '(gnu packages php-xyz))))
+ (module-ref module 'composer-classloader)))
+
+(define %composer-build-system-modules
+ ;; Build-side modules imported by default.
+ `((guix build composer-build-system)
+ (guix build union)
+ (json)
+ (json builder)
+ (json parser)
+ (json record)
+ ,@%gnu-build-system-modules))
+
+(define* (lower name
+ #:key source inputs native-inputs outputs system target
+ (php (default-php))
+ (composer-classloader (default-composer-classloader))
+ (findclass (default-findclass))
+ #:allow-other-keys
+ #:rest arguments)
+ "Return a bag for NAME."
+ (define private-keywords
+ '(#:target #:php #:composer-classloader #:findclass #:inputs #:native-inputs))
+
+ (and (not target) ;XXX: no cross-compilation
+ (bag
+ (name name)
+ (system system)
+ (host-inputs `(,@(if source
+ `(("source" ,source))
+ '())
+ ,@inputs
+
+ ;; Keep the standard inputs of 'gnu-build-system'.
+ ,@(standard-packages)))
+ (build-inputs `(("php" ,php)
+ ("findclass.php" ,findclass)
+ ("composer-classloader" ,composer-classloader)
+ ,@native-inputs))
+ (outputs outputs)
+ (build composer-build)
+ (arguments (strip-keyword-arguments private-keywords arguments)))))
+
+(define* (composer-build name inputs
+ #:key
+ guile source
+ (outputs '("out"))
+ (configure-flags ''())
+ (search-paths '())
+ (out-of-source? #t)
+ (composer-file "composer.json")
+ (tests? #t)
+ (test-target "test")
+ (install-target "install")
+ (validate-runpath? #t)
+ (patch-shebangs? #t)
+ (strip-binaries? #t)
+ (strip-flags #~'("--strip-debug"))
+ (strip-directories #~'("lib" "lib64" "libexec"
+ "bin" "sbin"))
+ (phases '(@ (guix build composer-build-system)
+ %standard-phases))
+ (system (%current-system))
+ (imported-modules %composer-build-system-modules)
+ (modules '((guix build composer-build-system)
+ (guix build utils))))
+ "Build SOURCE using PHP, and with INPUTS. This assumes that SOURCE provides
+a 'composer.json' file as its build system."
+ (define builder
+ (with-imported-modules imported-modules
+ #~(begin
+ (use-modules #$@(sexp->gexp modules))
+
+ #$(with-build-variables inputs outputs
+ #~(composer-build
+ #:source #$source
+ #:system #$system
+ #:outputs %outputs
+ #:inputs %build-inputs
+ #:search-paths '#$(map search-path-specification->sexp
+ search-paths)
+ #:phases #$phases
+ #:out-of-source? #$out-of-source?
+ #:composer-file #$composer-file
+ #:tests? #$tests?
+ #:test-target #$test-target
+ #:install-target #$install-target
+ #:validate-runpath? #$validate-runpath?
+ #:patch-shebangs? #$patch-shebangs?
+ #:strip-binaries? #$strip-binaries?
+ #:strip-flags #$strip-flags
+ #:strip-directories #$strip-directories)))))
+
+ (gexp->derivation name builder
+ #:system system
+ #:target #f
+ #:graft? #f
+ #:guile-for-build guile))
+
+(define composer-build-system
+ (build-system
+ (name 'composer)
+ (description "The standard Composer build system")
+ (lower lower)))
+
+;;; composer.scm ends here
diff --git a/guix/build/composer-build-system.scm b/guix/build/composer-build-system.scm
new file mode 100644
index 0000000000..7df2b7c400
--- /dev/null
+++ b/guix/build/composer-build-system.scm
@@ -0,0 +1,239 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix build composer-build-system)
+ #:use-module ((guix build gnu-build-system) #:prefix gnu:)
+ #:use-module (guix build utils)
+ #:use-module (ice-9 match)
+ #:use-module (json)
+ #:use-module (srfi srfi-26)
+ #:export (%standard-phases
+ composer-build))
+
+;; Commentary:
+;;
+;; Builder-side code of the standard composer build procedure.
+;;
+;; Code:
+
+(define (json->require dict)
+ (if dict
+ (let loop ((result '()) (require dict))
+ (match require
+ (() result)
+ ((((? (cut string-contains <> "/") name) . _)
+ require ...)
+ (loop (cons name result) require))
+ ((_ require ...) (loop result require))))
+ '()))
+
+(define-json-mapping <composer-autoload> make-composer-autoload composer-autoload?
+ json->composer-autoload
+ (psr-4 composer-autoload-psr-4 "psr-4"
+ (match-lambda
+ (#f '())
+ (psr-4 psr-4)))
+ (classmap composer-autoload-classmap "classmap"
+ (match-lambda
+ (#f '())
+ (#(lst ...) lst))))
+
+(define-json-mapping <composer-package> make-composer-package composer-package?
+ json->composer-package
+ (name composer-package-name)
+ (autoload composer-package-autoload "autoload" json->composer-autoload)
+ (autoload-dev composer-package-autoload-dev "autoload-dev" json->composer-autoload)
+ (require composer-package-require "require" json->require)
+ (dev-require composer-package-dev-require "require-dev" json->require)
+ (scripts composer-package-scripts "scripts"
+ (match-lambda
+ (#f '())
+ ((scripts ...) scripts)))
+ (binaries composer-package-binaries "bin"
+ (match-lambda
+ (#f '())
+ (#(lst ...) lst))))
+
+(define* (read-package-data #:key (filename "composer.json"))
+ (call-with-input-file filename
+ (lambda (port)
+ (json->composer-package (json->scm port)))))
+
+(define* (check #:key composer-file inputs outputs tests? test-target #:allow-other-keys)
+ "Test the given package."
+ (when tests?
+ (mkdir-p "vendor")
+ (create-autoload (string-append (getcwd) "/vendor") composer-file
+ (append inputs outputs) #:dev-dependencies? #t)
+ (let* ((package-data (read-package-data #:filename composer-file))
+ (scripts (composer-package-scripts package-data))
+ (test-script (assoc-ref scripts test-target))
+ (dependencies (composer-package-require package-data))
+ (dependencies-dev (composer-package-dev-require package-data))
+ (name (composer-package-name package-data)))
+ (for-each
+ (match-lambda
+ ((_ . input)
+ (let ((bin (find-php-bin input)))
+ (when bin
+ (copy-recursively bin "vendor/bin")))))
+ inputs)
+ (match test-script
+ ((? string? command)
+ (unless (zero? (system command))
+ (throw 'failed-command command)))
+ (('@ (? string? command) ...)
+ (for-each
+ (lambda (c)
+ (unless (zero? (system c))
+ (throw 'failed-command c)))
+ command))
+ (#f (invoke "vendor/bin/phpunit"))))))
+
+(define (find-php-bin input)
+ (let* ((web-dir (string-append input "/share/web"))
+ (vendors (if (file-exists? web-dir)
+ (find-files web-dir "^vendor$" #:directories? #t)
+ #f)))
+ (match vendors
+ ((vendor)
+ (let ((bin (string-append vendor "/bin")))
+ (and (file-exists? bin) bin)))
+ (_ #f))))
+
+(define (find-php-dep inputs dependency)
+ (let loop ((inputs inputs))
+ (match inputs
+ (() (throw 'unsatisfied-dependency "Unsatisfied dependency: required "
+ dependency))
+ (((_ . input) inputs ...)
+ (let ((autoload (string-append input "/share/web
This message was truncated. Download the full message here.
N
N
Nicolas Graves wrote on 26 Sep 2023 12:31
[PATCH v3 5/7] guix: import: composer: Fix json->require.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
5e275b0faafb6897f995d2c37d39984fca5eb9e1.1695724304.git.ngraves@ngraves.fr
---
guix/import/composer.scm | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

Toggle diff (16 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index 177dc63092..3acbbecf82 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -88,7 +88,8 @@ (define (json->require dict)
((((? (cut string-contains <> "/") name) . _)
require ...)
(loop (cons name result) require))
- ((_ require ...) (loop result require))))
+ ((_ require ...) (loop result require))
+ (_ result)))
'()))
(define-json-mapping <composer-source> make-composer-source composer-source?
--
2.41.0
N
N
Nicolas Graves wrote on 26 Sep 2023 12:31
[PATCH v3 6/7] guix: import: composer: More robust string->license.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
ea519115fce9bd5788fb476d59bf4a2f42b66334.1695724304.git.ngraves@ngraves.fr
* guix/import/composer.scm (string->license): Use spdx-string->license. Fall
back to unknown-license!.
---
guix/import/composer.scm | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)

Toggle diff (43 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index 3acbbecf82..2ce7206ef9 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -194,10 +194,8 @@ (define (make-php-sexp composer-package)
(synopsis "")
(description ,(composer-package-description composer-package))
(home-page ,(composer-package-homepage composer-package))
- (license ,(match (composer-package-license composer-package)
- (() #f)
- ((license) license)
- (_ license)))))))))
+ (license ,(or (composer-package-license composer-package)
+ 'unknown-license!))))))))
(define composer->guix-package
(memoize
@@ -234,14 +232,15 @@ (define (guix-package->composer-name package)
(define (string->license str)
"Convert the string STR into a license object."
- (match str
- ("GNU LGPL" 'license:lgpl2.0)
- ("GPL" 'license:gpl3)
- ((or "BSD" "BSD License" "BSD-3-Clause") 'license:bsd-3)
- ((or "MIT" "MIT license" "Expat license") 'license:expat)
- ("Public domain" 'license:public-domain)
- ((or "Apache License, Version 2.0" "Apache 2.0") 'license:asl2.0)
- (_ #f)))
+ (or (spdx-string->license str)
+ (match str
+ ("GNU LGPL" 'license:lgpl2.0)
+ ("GPL" 'license:gpl3)
+ ((or "BSD" "BSD License") 'license:bsd-3)
+ ((or "MIT" "MIT license" "Expat license") 'license:expat)
+ ("Public domain" 'license:public-domain)
+ ((or "Apache License, Version 2.0" "Apache 2.0") 'license:asl2.0)
+ (_ 'unknown-license!))))
(define (php-package? package)
"Return true if PACKAGE is a PHP package from Packagist."
--
2.41.0
N
N
Nicolas Graves wrote on 26 Sep 2023 12:31
[PATCH v3 7/7] guix: import: composer: Modern inputs formatting.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
810bc98dafaceec34fb584732fc19b7f836ae110.1695724304.git.ngraves@ngraves.fr
* guix/import/composer.scm (make-php-sexp): Update inputs formatting.
---
guix/import/composer.scm | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)

Toggle diff (30 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index 2ce7206ef9..b4710c6fb9 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -176,21 +176,11 @@ (define (make-php-sexp composer-package)
,@(if (null? dependencies)
'()
`((inputs
- (,'quasiquote
- ,(map (lambda (name)
- `(,name
- (,'unquote
- ,(string->symbol name))))
- dependencies)))))
+ (list ,(map string->symbol dependencies)))))
,@(if (null? dev-dependencies)
'()
`((native-inputs
- (,'quasiquote
- ,(map (lambda (name)
- `(,name
- (,'unquote
- ,(string->symbol name))))
- dev-dependencies)))))
+ (list ,(map string->symbol dev-dependencies)))))
(synopsis "")
(description ,(composer-package-description composer-package))
(home-page ,(composer-package-homepage composer-package))
--
2.41.0
N
N
Nicolas Graves wrote on 26 Sep 2023 12:43
Re: [PATCH v3 1/7] guix: import: Add composer importer.
(address . 42338@debbugs.gnu.org)
87jzsdtdt0.fsf@ngraves.fr
I've just added some modernizations and fixes ontop of the :
- first patch which is the latest provided in the discussion between
Ludo' and Julien, with minimal fixes.
- second and third patch which are the versions from Adam Faiz.

The recursive import should work with these patches but often fails,
probably because it loops and we eventually get a gnu-tls error probably
from when github refuses to serve, because it doesn't stop on a specific
package. This probably will stop looping so much one phpunit is added,
with the later patches from Julien adding phpunit. In any case, it's
definitely a more robust recursive import, and the error Adam
experienced has been solved in the fifth patch. The sixth patch also
avoids some licensing-related failures.

On 2023-09-26 12:31, Nicolas Graves wrote:

Toggle quote (474 lines)
> * guix/import/composer.scm: New file.
> * guix/scripts/import/composer.scm: New file.
> * guix/tests/composer.scm: New file.
> * Makefile.am: Add them.
> * guix/scripts/import.scm: Add composer importer.
> * doc/guix.texi (Invoking guix import): Mention it.
> ---
> Makefile.am | 3 +
> doc/guix.texi | 20 +++
> guix/import/composer.scm | 270 +++++++++++++++++++++++++++++++
> guix/scripts/import.scm | 2 +-
> guix/scripts/import/composer.scm | 107 ++++++++++++
> tests/composer.scm | 92 +++++++++++
> 6 files changed, 493 insertions(+), 1 deletion(-)
> create mode 100644 guix/import/composer.scm
> create mode 100644 guix/scripts/import/composer.scm
> create mode 100644 tests/composer.scm
>
> diff --git a/Makefile.am b/Makefile.am
> index 8924974e8a..3ce7ee832e 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -274,6 +274,7 @@ MODULES = \
> guix/search-paths.scm \
> guix/packages.scm \
> guix/import/cabal.scm \
> + guix/import/composer.scm \
> guix/import/cpan.scm \
> guix/import/cran.scm \
> guix/import/crate.scm \
> @@ -332,6 +333,7 @@ MODULES = \
> guix/scripts/home/import.scm \
> guix/scripts/lint.scm \
> guix/scripts/challenge.scm \
> + guix/scripts/import/composer.scm \
> guix/scripts/import/crate.scm \
> guix/scripts/import/cpan.scm \
> guix/scripts/import/cran.scm \
> @@ -500,6 +502,7 @@ SCM_TESTS = \
> tests/challenge.scm \
> tests/channels.scm \
> tests/combinators.scm \
> + tests/composer.scm \
> tests/containers.scm \
> tests/cpan.scm \
> tests/cpio.scm \
> diff --git a/doc/guix.texi b/doc/guix.texi
> index 46591b2f64..4d2fc11cd7 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -14530,6 +14530,26 @@ Invoking guix import
>
> 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
> +
> +@item composer
> +@cindex Composer
> +@cindex PHP
> +Import metadat from the @uref{https://getcomposer.org/, Composer} package
> +archive used by the PHP community, as in this example:
> +
> +@example
> +guix import composer phpunit/phpunit
> +@end example
> +
> +Additional options include:
> +
> @table @code
> @item --recursive
> @itemx -r
> diff --git a/guix/import/composer.scm b/guix/import/composer.scm
> new file mode 100644
> index 0000000000..c152f402bb
> --- /dev/null
> +++ b/guix/import/composer.scm
> @@ -0,0 +1,270 @@
> +;;; GNU Guix --- Functional package management for GNU
> +;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
> +;;;
> +;;; 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 <http://www.gnu.org/licenses/>.
> +
> +(define-module (guix import composer)
> + #:use-module (ice-9 match)
> + #:use-module (json)
> + #:use-module (gcrypt hash)
> + #:use-module (guix base32)
> + #:use-module (guix build git)
> + #:use-module (guix build utils)
> + #:use-module (guix build-system)
> + #:use-module (guix import json)
> + #:use-module (guix import utils)
> + #:use-module ((guix licenses) #:prefix license:)
> + #:use-module (guix packages)
> + #:use-module (guix serialization)
> + #:use-module (guix upstream)
> + #:use-module (guix utils)
> + #:use-module (srfi srfi-1)
> + #:use-module (srfi srfi-11)
> + #:use-module (srfi srfi-26)
> + #:export (composer->guix-package
> + %composer-updater
> + composer-recursive-import
> +
> + %composer-base-url))
> +
> +(define %composer-base-url
> + (make-parameter "https://repo.packagist.org"))
> +
> +;; XXX adapted from (guix scripts hash)
> +(define (file-hash file select? recursive?)
> + ;; Compute the hash of FILE.
> + (if recursive?
> + (let-values (((port get-hash) (open-sha256-port)))
> + (write-file file port #:select? select?)
> + (force-output port)
> + (get-hash))
> + (call-with-input-file file port-sha256)))
> +
> +;; XXX taken from (guix scripts hash)
> +(define (vcs-file? file stat)
> + (case (stat:type stat)
> + ((directory)
> + (member (basename file) '(".bzr" ".git" ".hg" ".svn" "CVS")))
> + ((regular)
> + ;; Git sub-modules have a '.git' file that is a regular text file.
> + (string=? (basename file) ".git"))
> + (else
> + #f)))
> +
> +(define (fix-version version)
> + "Return a fixed version from a version string. For instance, v10.1 -> 10.1"
> + (cond
> + ((string-prefix? "version" version)
> + (if (char-set-contains? char-set:digit (string-ref version 7))
> + (substring version 7)
> + (substring version 8)))
> + ((string-prefix? "v" version)
> + (substring version 1))
> + (else version)))
> +
> +(define (latest-version versions)
> + (fold (lambda (a b) (if (version>? (fix-version a) (fix-version b)) a b))
> + (car versions) versions))
> +
> +(define (json->require dict)
> + (if dict
> + (let loop ((result '()) (require dict))
> + (match require
> + (() result)
> + ((((? (cut string-contains <> "/") name) . _)
> + require ...)
> + (loop (cons name result) require))
> + ((_ require ...) (loop result require))))
> + '()))
> +
> +(define-json-mapping <composer-source> make-composer-source composer-source?
> + json->composer-source
> + (type composer-source-type)
> + (url composer-source-url)
> + (reference composer-source-reference))
> +
> +(define-json-mapping <composer-package> make-composer-package composer-package?
> + json->composer-package
> + (description composer-package-description)
> + (homepage composer-package-homepage)
> + (source composer-package-source "source" json->composer-source)
> + (name composer-package-name "name" php-package-name)
> + (version composer-package-version "version" fix-version)
> + (require composer-package-require "require" json->require)
> + (dev-require composer-package-dev-require "require-dev" json->require)
> + (license composer-package-license "license"
> + (lambda (vector)
> + (map string->license (vector->list vector)))))
> +
> +(define* (composer-fetch name #:optional version)
> + "Return an alist representation of the Composer metadata for the package NAME,
> +or #f on failure."
> + (let ((package (json-fetch
> + (string-append (%composer-base-url) "/p/" name ".json"))))
> + (if package
> + (let* ((packages (assoc-ref package "packages"))
> + (package (or (assoc-ref packages name) package))
> + (versions (filter
> + (lambda (version)
> + (and (not (string-contains version "dev"))
> + (not (string-contains version "beta"))))
> + (map car package)))
> + (version (or (if (null? version) #f version)
> + (latest-version versions))))
> + (assoc-ref package version))
> + #f)))
> +
> +(define (php-package-name name)
> + "Given the NAME of a package on Packagist, return a Guix-compliant name for
> +the package."
> + (let ((name (string-join (string-split name #\/) "-")))
> + (if (string-prefix? "php-" name)
> + (snake-case name)
> + (string-append "php-" (snake-case name)))))
> +
> +(define (make-php-sexp composer-package)
> + "Return the `package' s-expression for a PHP package for the given
> +COMPOSER-PACKAGE."
> + (let* ((source (composer-package-source composer-package))
> + (dependencies (map php-package-name
> + (composer-package-require composer-package)))
> + (dev-dependencies (map php-package-name
> + (composer-package-dev-require composer-package)))
> + (git? (equal? (composer-source-type source) "git")))
> + ((if git? call-with-temporary-directory call-with-temporary-output-file)
> + (lambda* (temp #:optional port)
> + (and (if git?
> + (begin
> + (mkdir-p temp)
> + (git-fetch (composer-source-url source)
> + (composer-source-reference source)
> + temp))
> + (url-fetch (composer-source-url source) temp))
> + `(package
> + (name ,(composer-package-name composer-package))
> + (version ,(composer-package-version composer-package))
> + (source (origin
> + ,@(if git?
> + `((method git-fetch)
> + (uri (git-reference
> + (url ,(composer-source-url source))
> + (commit ,(composer-source-reference source))))
> + (file-name (git-file-name name version))
> + (sha256
> + (base32
> + ,(bytevector->nix-base32-string
> + (file-hash temp (negate vcs-file?) #t)))))
> + `((method url-fetch)
> + (uri ,(composer-source-url source))
> + (sha256 (base32 ,(guix-hash-url temp)))))))
> + (build-system composer-build-system)
> + ,@(if (null? dependencies)
> + '()
> + `((inputs
> + (,'quasiquote
> + ,(map (lambda (name)
> + `(,name
> + (,'unquote
> + ,(string->symbol name))))
> + dependencies)))))
> + ,@(if (null? dev-dependencies)
> + '()
> + `((native-inputs
> + (,'quasiquote
> + ,(map (lambda (name)
> + `(,name
> + (,'unquote
> + ,(string->symbol name))))
> + dev-dependencies)))))
> + (synopsis "")
> + (description ,(composer-package-description composer-package))
> + (home-page ,(composer-package-homepage composer-package))
> + (license ,(match (composer-package-license composer-package)
> + (() #f)
> + ((license) license)
> + (_ license)))))))))
> +
> +(define* (composer->guix-package package-name #:optional version)
> + "Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
> +`package' s-expression corresponding to that package, or #f on failure."
> + (let ((package (composer-fetch package-name version)))
> + (and package
> + (let* ((package (json->composer-package package))
> + (dependencies-names (composer-package-require package))
> + (dev-dependencies-names (composer-package-dev-require package)))
> + (values (make-php-sexp package)
> + (append dependencies-names dev-dependencies-names))))))
> +
> +(define (guix-name->composer-name name)
> + "Given a guix package name, return the name of the package in Packagist."
> + (if (string-prefix? "php-" name)
> + (let ((components (string-split (substring name 4) #\-)))
> + (match components
> + ((namespace name ...)
> + (string-append namespace "/" (string-join name "-")))))
> + name))
> +
> +(define (guix-package->composer-name package)
> + "Given a Composer PACKAGE built from Packagist, return the name of the
> +package in Packagist."
> + (let ((upstream-name (assoc-ref
> + (package-properties package)
> + 'upstream-name))
> + (name (package-name package)))
> + (if upstream-name
> + upstream-name
> + (guix-name->composer-name name))))
> +
> +(define (string->license str)
> + "Convert the string STR into a license object."
> + (match str
> + ("GNU LGPL" 'license:lgpl2.0)
> + ("GPL" 'license:gpl3)
> + ((or "BSD" "BSD License" "BSD-3-Clause") 'license:bsd-3)
> + ((or "MIT" "MIT license" "Expat license") 'license:expat)
> + ("Public domain" 'license:public-domain)
> + ((or "Apache License, Version 2.0" "Apache 2.0") 'license:asl2.0)
> + (_ #f)))
> +
> +(define (php-package? package)
> + "Return true if PACKAGE is a PHP package from Packagist."
> + (and
> + (eq? (build-system-name (package-build-system package)) 'composer)
> + (string-prefix? "php-" (package-name package))))
> +
> +(define (latest-release package)
> + "Return an <upstream-source> for the latest release of PACKAGE."
> + (let* ((php-name (guix-package->composer-name package))
> + (metadata (composer-fetch php-name))
> + (package (json->composer-package metadata))
> + (version (composer-package-version package))
> + (url (composer-source-url (composer-package-source package))))
> + (upstream-source
> + (package (package-name package))
> + (version version)
> + (urls (list url)))))
> +
> +(define %composer-updater
> + (upstream-updater
> + (name 'composer)
> + (description "Updater for Composer packages")
> + (pred php-package?)
> + (import latest-release)))
> +
> +(define* (composer-recursive-import package-name #:optional version)
> + (recursive-import package-name '()
> + #:repo->guix-package composer->guix-package
> + #:guix-name php-package-name))
> diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm
> index 4ddd8d46a1..8c58dd35e2 100644
> --- a/guix/scripts/import.scm
> +++ b/guix/scripts/import.scm
> @@ -47,7 +47,7 @@ (define %standard-import-options '())
>
> (define importers '("gnu" "pypi" "cpan" "hackage" "stackage" "egg" "elpa"
> "gem" "go" "cran" "crate" "texlive" "json" "opam"
> - "minetest" "elm" "hexpm"))
> + "minetest" "elm" "hexpm" "composer"))
>
> (define (resolve-importer name)
> (let ((module (resolve-interface
> diff --git a/guix/scripts/import/composer.scm b/guix/scripts/import/composer.scm
> new file mode 100644
> index 0000000000..412bae6318
> --- /dev/null
> +++ b/guix/scripts/import/composer.scm
> @@ -0,0 +1,107 @@
> +;;; GNU Guix --- Functional package management for GNU
> +;;; Copyright © 2015 David Thompson <davet@gnu.org>
> +;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
> +;;;
> +;;; 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 <http://www.gnu.org/licenses/>.
> +
> +(define-module (guix scripts import composer)
> + #:use-module (guix ui)
> + #:use-module (guix utils)
> + #:use-module (guix scripts)
> + #:use-module (guix import composer)
> + #:use-module (guix scripts import)
> + #:use-module (srfi srfi-1)
> + #:use-module (srfi srfi-11)
> + #:use-module (srfi srfi-37)
> + #:use-module (srfi srfi-41)
> + #:use-module (ice-9 match)
> + #:use-module (ice-9 format)
> + #:export (guix-import-composer))
> +
> +
> +;;;
> +;;; Command-line options.
> +;;;
> +
> +(define %default-options
> + '())
> +
> +(define (show-help)
> + (display (G_ "Usage: guix import composer PACKAGE-NAME
> +Import and convert the Composer package for PACKAGE-NAME.\n"))
> + (display (G_ "
> + -h, --help display this help and exit"))
> + (display (G_ "
> + -V, --version display version information and exit"))
> + (display (G_ "
> + -r, --recursive generate package expressions for all Composer packages\
> + that are not yet in Guix"))
> + (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 composer")))
> + (option '(#\r "recursive") #f #f
> + (lambda (opt name arg result)
> + (alist-cons 'recursive #t result)))
> + %standard-import-options))
> +
> +
> +;;;
> +;;; Entry point.
> +;;;
> +
> +(define (guix-import-composer . 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))
> + (args (filter-map (match-lambda
> + (('argument . value)
> + value)
> + (_ #f))
> + (reverse opts))))
> + (match args
> + ((package-name)
> + (if (assoc-ref opts 'recursive)
> + (map (match-lambda
> + ((and ('package ('name name) . rest) pkg)
> + `(define-public ,(string->symbol name)
> + ,pkg))
> + (_ #f))
> + (composer-recursive-import package-name))
> + (let ((sexp (composer->guix-package package-name)))
> + (unless sexp
> + (leave (G_ "failed to download meta-data for package '~a'~%")
> + package-name
This message was truncated. Download the full message here.
N
N
Nicolas Graves wrote on 26 Sep 2023 13:25
[PATCH v3] guix: import: composer: Fix match-lambda with a default fallback.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
24918b74efadc1bd47c7cf90aedf3ce821ab7048.1695727516.git.ngraves@ngraves.fr
* guix/import/composer.scm:
(composer-package): Fix match-lambda with a default fallback.
(composer-autoload): Fix match-lambda with a default fallback.
---
guix/build/composer-build-system.scm | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

Toggle diff (165 lines)
diff --git a/guix/build/composer-build-system.scm b/guix/build/composer-build-system.scm
index 7df2b7c400..d891ea3a6d 100644
--- a/guix/build/composer-build-system.scm
+++ b/guix/build/composer-build-system.scm
@@ -46,12 +46,12 @@ (define-json-mapping <composer-autoload> make-composer-autoload composer-autoloa
json->composer-autoload
(psr-4 composer-autoload-psr-4 "psr-4"
(match-lambda
- (#f '())
- (psr-4 psr-4)))
+ (psr-4 psr-4)
+ (_ '())))
(classmap composer-autoload-classmap "classmap"
(match-lambda
- (#f '())
- (#(lst ...) lst))))
+ (#(lst ...) lst)
+ (_ '()))))
(define-json-mapping <composer-package> make-composer-package composer-package?
json->composer-package
@@ -62,12 +62,12 @@ (define-json-mapping <composer-package> make-composer-package composer-package?
(dev-require composer-package-dev-require "require-dev" json->require)
(scripts composer-package-scripts "scripts"
(match-lambda
- (#f '())
- ((scripts ...) scripts)))
+ ((scripts ...) scripts)
+ (_ '())))
(binaries composer-package-binaries "bin"
(match-lambda
- (#f '())
- (#(lst ...) lst))))
+ (#(lst ...) lst)
+ (_ '()))))
(define* (read-package-data #:key (filename "composer.json"))
(call-with-input-file filename

base-commit: fafd3caef0d51811a5da81d6061789e2908b0dac
prerequisite-patch-id: eb618ab7b10483d917c308a38792af98baa517e2
prerequisite-patch-id: c12968d02d99c253f858586a86b16fa32d41f1c1
prerequisite-patch-id: 09d995d48139f8e61183d5634cda13a01cdb50f7
prerequisite-patch-id: 86baa45ec2aad977c8c8135f7613aa391155de6d
prerequisite-patch-id: 3425fbbff6a603d60b4e143ea2141aabf4ddc92c
prerequisite-patch-id: c373c01aab5dcba3503a97d51c62a595147a041c
prerequisite-patch-id: cda857c790b88c681c4e713c5f71e40291970daf
prerequisite-patch-id: 8e234d0f4d93d2aad499eec8842be3d28da98707
prerequisite-patch-id: 5f664cb2fd995a53765c5ffc19a708ac795cc0c4
prerequisite-patch-id: ed447cba9cf9b7e1a1b47aa27acb14f8f2da0a8e
prerequisite-patch-id: 9f80c5bbbfb8cd3347951c4d57634e93ffa79924
prerequisite-patch-id: 1aaa9f0d466e2d6837f75844df48a98beb70ff24
prerequisite-patch-id: 34502820d8c0355b3ed2638c457084edeaba029d
prerequisite-patch-id: a96258da9e78cfb9ac9893cdcdeb38b69b75f134
prerequisite-patch-id: 4a2da4ee89dbbdb2244845149ce6da967ddd5268
prerequisite-patch-id: 9f9c4205781d1f0e2bb7af2d21875de08ee3ecd5
prerequisite-patch-id: 9697db9b50cab8f7974c32383e0a9a786ecbd8f9
prerequisite-patch-id: ebbd089a3313232347273c723d3deb1bf8c9bf81
prerequisite-patch-id: e93360d66936b9efd70a6ffd41f6ecda177ad7b8
prerequisite-patch-id: 19d76f45db1c59bd9ccd2e4e1125ffd698e9d6ce
prerequisite-patch-id: 929b39ded7ad095e9f768f7d484bbd3b7a486a3c
prerequisite-patch-id: 5e1262f77d55c91eadca113223faa84935bffd60
prerequisite-patch-id: ad370d41983418fa704215aa3458f97c75d5d128
prerequisite-patch-id: f179c922613390d249a365625c2ee545a908029d
prerequisite-patch-id: 03b0aaa382ddda0819ddb62479cd1885c930ddea
prerequisite-patch-id: 83b8b3a072520705dcba4b67712a29553bea1548
prerequisite-patch-id: 9308fa06526d9bacdbcdd347cc225f6f3f87811a
prerequisite-patch-id: a017243a1a4b406caed9cec048d194cdc33d1a25
prerequisite-patch-id: e8d5b2e787904b0dd1a650d7a0012b91a430cb03
prerequisite-patch-id: 1cc872245864ace22db43cf2d268a87190b333b6
prerequisite-patch-id: c277dcca77f3acde51bdffe932b9250e454086ad
prerequisite-patch-id: ea926073e68d5af7f6c76a6333520cc5f42c9789
prerequisite-patch-id: 10008b9b34ccc8f87f2fcd8391075fe57244ac72
prerequisite-patch-id: 443d7e3eb85f36848c2120979f9f1d3a78f8bf38
prerequisite-patch-id: 6414c2d65c1806942d7f834e9300a8ecf8fd743f
prerequisite-patch-id: 8c6dec06b716c39ca7fada0f2872078612917779
prerequisite-patch-id: 62e28252e9b7ab11edb03609b68369feb499f883
prerequisite-patch-id: 84c9361c4c6d7662cfb3235cc4a6640a53e00622
prerequisite-patch-id: 0f27045bc50089a9a88da7818448a50cd28dd295
prerequisite-patch-id: 500413da3a81e75c5fbca62a21d9457d7b1ad8a8
prerequisite-patch-id: 6f48169f4d69da277bcdecb8f40d2f608941d9f9
prerequisite-patch-id: fc8b43573cc6b90033769de63ca235b16159190d
prerequisite-patch-id: ae749fc3fa0ab1768841ffb4633847b5b2233881
prerequisite-patch-id: 46b8490d2b338229a2f3c5e39427275cf46982ba
prerequisite-patch-id: b1bb7dfb35069a2b30f5b2714bc19a249be3e1b5
prerequisite-patch-id: 94848222eb08beb53530ba6ce626e9d8bcffecd4
prerequisite-patch-id: f8181365677e68d8628013c7636e9ff56214ac9e
prerequisite-patch-id: aebc0f8156c409599cc7aced4b708bb5ea08a2b2
prerequisite-patch-id: 4ce416249f6d3176a51d7e4cbbd2c6bf2982bab6
prerequisite-patch-id: 5e14463dcc090e497bb1d29c1b4c822b43d5fdca
prerequisite-patch-id: 89306b41386cb29db7c147e8c4468a3b4d8d292d
prerequisite-patch-id: 29e414b1ede9108047ff224e1e24a3adb2c44c52
prerequisite-patch-id: 7e15edfd04cd291f54284d13dcdbebcfb456b752
prerequisite-patch-id: b8c18091929e58b49847ab510d3d75a8a934cad0
prerequisite-patch-id: 7a607a1659b22afb0c21dec3d8eb1e2ed51e47a9
prerequisite-patch-id: 89fbd04f11e5bef5703ba7ea4c2064d5ba63c4d4
prerequisite-patch-id: b421048677352ea536dd93a61d6de987fb95d60b
prerequisite-patch-id: 25a03298bdfd6a691bb8cf68690009f8e46447e0
prerequisite-patch-id: 3924163576eafdac47ac06de311ac317730e6631
prerequisite-patch-id: 69b1d81677b507242f556c3e2fcf5290aeca445c
prerequisite-patch-id: a378fa79002001da51ae91eb026769eddb8a593b
prerequisite-patch-id: 86bb35c89ec3cc1b6ec47f238c84a154d5e9a1aa
prerequisite-patch-id: f8d0709d94ed99b1530bad1908ca27b1b56ea84e
prerequisite-patch-id: dcb65983aa914b8f1d1a8fbdfba34714ddb7f6fa
prerequisite-patch-id: 89752146a063d0706885819e244b4179196538b8
prerequisite-patch-id: 1f9e7627d0b23302159cdab3d939fcec52f7ca70
prerequisite-patch-id: f706bfa95ba0e5e72c206537ed207feb95daa888
prerequisite-patch-id: 9b60c519b0df65eeacd5779808e0d75b011ebf7f
prerequisite-patch-id: cd6cd74eca502ebce581c223cd0d2ac4278912e8
prerequisite-patch-id: b86e08404ef83877dfa3b76a80a12b02c61b1326
prerequisite-patch-id: 9417f8d92995cf417bb3c4afa0786b05a756d48a
prerequisite-patch-id: 59dda13243375b013396981a4f9e17abd694d734
prerequisite-patch-id: 89be058d0605cb8278d5d3384bb44911b188dd90
prerequisite-patch-id: 70c26fde2fde34c031a95ef74a3321710dc4961e
prerequisite-patch-id: 38a27cdf8cbe03fdf5f9bafa5ba53f3ba644a5ad
prerequisite-patch-id: 40a6d2e51dff2531c40a38087a8aea1be7108792
prerequisite-patch-id: 024d1bba9bcd449d2b8196b2f1a64a197cafaed8
prerequisite-patch-id: e83d54aa767ebab267530fca74d60366160a5253
prerequisite-patch-id: c34734661161c27224316dc519609db5c6d87a1e
prerequisite-patch-id: a58d739146fe46f6c7f203e5d2e0f114bd3f7834
prerequisite-patch-id: 1ff8499f5ec69b737d77053e6809ec3a0b599ebc
prerequisite-patch-id: 498e5608bca9b5ebcb3592a556e75f5dcc2b7076
prerequisite-patch-id: df6dfdea7c3d9db4649d857ce55fbeb99d4febca
prerequisite-patch-id: 453b66b1faaaebaa1666954185de327298aa0578
prerequisite-patch-id: f98da1de781c203a53cae73c5bb707240d21cb0a
prerequisite-patch-id: 14b1718dbc4fb9cd94e1094a4d44ebfcfe6ad869
prerequisite-patch-id: 3b68944fa8fb2fab0c21d6ff73f649f53dd6f551
prerequisite-patch-id: 82d1e6bcd221f982b6ab1ed0e9a90d46a39562c4
prerequisite-patch-id: c9cce20b146f955b715d15c0c384c9acc6176493
prerequisite-patch-id: c204491c1db4f5056711768265f101e881e4e415
prerequisite-patch-id: e66e13fbde027e99552fc6d80ff8d48c110a18f2
prerequisite-patch-id: 3c313f0a20730c653c8f5ec4f318e2485a8ef60f
prerequisite-patch-id: 925c466172c01c4b5976ac019961cbe240f0cddd
prerequisite-patch-id: e81e0aded80adf18c861f67624a179a15ef68906
prerequisite-patch-id: 001675f7da57d25731c7c71f6f2dcaa7409e5664
prerequisite-patch-id: d65bf6ef5f51da0acba72d332d60167b34e193e1
prerequisite-patch-id: fc7c9a5024037363319b58520480a6c4a8a5dcff
prerequisite-patch-id: 5aae8c77d028459d944021f4943558411deb0662
prerequisite-patch-id: 71fa80813ad36528e8a737249424d90827933c16
prerequisite-patch-id: 65dc75b8e1ddb45542480a8867ecd7a63ab3112e
prerequisite-patch-id: 8619aa1dec17409d9b5ecb6ed0a2cc7d1563c174
prerequisite-patch-id: 6473142746dc5b448ec9698d577f47b4da6cd1d5
prerequisite-patch-id: eb6689695d5d1b6c650de0c86a805a45b80ab88d
prerequisite-patch-id: 7d50679dad38c9f859ec231da2db78919818b40e
prerequisite-patch-id: faeb97c5f9c07754bd0bf0be59254091470978c2
prerequisite-patch-id: 56e31c3ab9ed9ff19aca25d5ffb9655c6515b692
prerequisite-patch-id: 8d7418e017eec3c6e56b55f9ff6181cc3dcc1a17
prerequisite-patch-id: 84f58e5a274c980ae6905e764d479e1c960149ca
prerequisite-patch-id: ada6a2d9427bff9dd7fd115a91300a1f7379995c
prerequisite-patch-id: 108161d5500b39b3ac55d202b5b9af817d829724
prerequisite-patch-id: c89b0fc7dadc53facc45ccf9991503430b7e7799
prerequisite-patch-id: d62e2be8f9fd6a1d9ac8dfa2cdc4db6d4a4327ac
prerequisite-patch-id: f8f4375b2b16ffae596d416607c00b374f485299
prerequisite-patch-id: 36b1a9c3e0e9f91b7172e1211231759a6cb81473
prerequisite-patch-id: 8cb6ac6a5188c817bb3a6a86920001de75bb7225
prerequisite-patch-id: 17ef87336a8c664e0109a7466c9f7d37f5901167
prerequisite-patch-id: a2c72266baec1b3eb5706d43157d93ae8db5e42d
prerequisite-patch-id: 27503579f8bdfadb95847b8dd5bf3732f5149cfb
prerequisite-patch-id: 50d6d9c6ff0734705ae384ede694b547f4973249
prerequisite-patch-id: 81cd72752ab376d459dceff93f71715e55a55846
prerequisite-patch-id: 922cec7ef3d21275f5933968f5b704e0bed64ce5
prerequisite-patch-id: 1f0903e8846cd59d0d5a3dcbf9a5a82ad4dcb5cd
prerequisite-patch-id: 69d839b9d5b794ef1b7dee9c592ed20300f8539f
--
2.41.0
N
N
Nicolas Graves wrote on 26 Sep 2023 13:27
(address . 42338@debbugs.gnu.org)
87h6nhtbs1.fsf@ngraves.fr
I haven't tested building packages, and it seemed that there still was
the same issue as the importer (no fallback for a match). With this
additional patch, packages seem to build well.


On 2023-09-26 13:25, Nicolas Graves wrote:

Toggle quote (171 lines)
> * guix/import/composer.scm:
> (composer-package): Fix match-lambda with a default fallback.
> (composer-autoload): Fix match-lambda with a default fallback.
> ---
> guix/build/composer-build-system.scm | 16 ++++++++--------
> 1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/guix/build/composer-build-system.scm b/guix/build/composer-build-system.scm
> index 7df2b7c400..d891ea3a6d 100644
> --- a/guix/build/composer-build-system.scm
> +++ b/guix/build/composer-build-system.scm
> @@ -46,12 +46,12 @@ (define-json-mapping <composer-autoload> make-composer-autoload composer-autoloa
> json->composer-autoload
> (psr-4 composer-autoload-psr-4 "psr-4"
> (match-lambda
> - (#f '())
> - (psr-4 psr-4)))
> + (psr-4 psr-4)
> + (_ '())))
> (classmap composer-autoload-classmap "classmap"
> (match-lambda
> - (#f '())
> - (#(lst ...) lst))))
> + (#(lst ...) lst)
> + (_ '()))))
>
> (define-json-mapping <composer-package> make-composer-package composer-package?
> json->composer-package
> @@ -62,12 +62,12 @@ (define-json-mapping <composer-package> make-composer-package composer-package?
> (dev-require composer-package-dev-require "require-dev" json->require)
> (scripts composer-package-scripts "scripts"
> (match-lambda
> - (#f '())
> - ((scripts ...) scripts)))
> + ((scripts ...) scripts)
> + (_ '())))
> (binaries composer-package-binaries "bin"
> (match-lambda
> - (#f '())
> - (#(lst ...) lst))))
> + (#(lst ...) lst)
> + (_ '()))))
>
> (define* (read-package-data #:key (filename "composer.json"))
> (call-with-input-file filename
>
> base-commit: fafd3caef0d51811a5da81d6061789e2908b0dac
> prerequisite-patch-id: eb618ab7b10483d917c308a38792af98baa517e2
> prerequisite-patch-id: c12968d02d99c253f858586a86b16fa32d41f1c1
> prerequisite-patch-id: 09d995d48139f8e61183d5634cda13a01cdb50f7
> prerequisite-patch-id: 86baa45ec2aad977c8c8135f7613aa391155de6d
> prerequisite-patch-id: 3425fbbff6a603d60b4e143ea2141aabf4ddc92c
> prerequisite-patch-id: c373c01aab5dcba3503a97d51c62a595147a041c
> prerequisite-patch-id: cda857c790b88c681c4e713c5f71e40291970daf
> prerequisite-patch-id: 8e234d0f4d93d2aad499eec8842be3d28da98707
> prerequisite-patch-id: 5f664cb2fd995a53765c5ffc19a708ac795cc0c4
> prerequisite-patch-id: ed447cba9cf9b7e1a1b47aa27acb14f8f2da0a8e
> prerequisite-patch-id: 9f80c5bbbfb8cd3347951c4d57634e93ffa79924
> prerequisite-patch-id: 1aaa9f0d466e2d6837f75844df48a98beb70ff24
> prerequisite-patch-id: 34502820d8c0355b3ed2638c457084edeaba029d
> prerequisite-patch-id: a96258da9e78cfb9ac9893cdcdeb38b69b75f134
> prerequisite-patch-id: 4a2da4ee89dbbdb2244845149ce6da967ddd5268
> prerequisite-patch-id: 9f9c4205781d1f0e2bb7af2d21875de08ee3ecd5
> prerequisite-patch-id: 9697db9b50cab8f7974c32383e0a9a786ecbd8f9
> prerequisite-patch-id: ebbd089a3313232347273c723d3deb1bf8c9bf81
> prerequisite-patch-id: e93360d66936b9efd70a6ffd41f6ecda177ad7b8
> prerequisite-patch-id: 19d76f45db1c59bd9ccd2e4e1125ffd698e9d6ce
> prerequisite-patch-id: 929b39ded7ad095e9f768f7d484bbd3b7a486a3c
> prerequisite-patch-id: 5e1262f77d55c91eadca113223faa84935bffd60
> prerequisite-patch-id: ad370d41983418fa704215aa3458f97c75d5d128
> prerequisite-patch-id: f179c922613390d249a365625c2ee545a908029d
> prerequisite-patch-id: 03b0aaa382ddda0819ddb62479cd1885c930ddea
> prerequisite-patch-id: 83b8b3a072520705dcba4b67712a29553bea1548
> prerequisite-patch-id: 9308fa06526d9bacdbcdd347cc225f6f3f87811a
> prerequisite-patch-id: a017243a1a4b406caed9cec048d194cdc33d1a25
> prerequisite-patch-id: e8d5b2e787904b0dd1a650d7a0012b91a430cb03
> prerequisite-patch-id: 1cc872245864ace22db43cf2d268a87190b333b6
> prerequisite-patch-id: c277dcca77f3acde51bdffe932b9250e454086ad
> prerequisite-patch-id: ea926073e68d5af7f6c76a6333520cc5f42c9789
> prerequisite-patch-id: 10008b9b34ccc8f87f2fcd8391075fe57244ac72
> prerequisite-patch-id: 443d7e3eb85f36848c2120979f9f1d3a78f8bf38
> prerequisite-patch-id: 6414c2d65c1806942d7f834e9300a8ecf8fd743f
> prerequisite-patch-id: 8c6dec06b716c39ca7fada0f2872078612917779
> prerequisite-patch-id: 62e28252e9b7ab11edb03609b68369feb499f883
> prerequisite-patch-id: 84c9361c4c6d7662cfb3235cc4a6640a53e00622
> prerequisite-patch-id: 0f27045bc50089a9a88da7818448a50cd28dd295
> prerequisite-patch-id: 500413da3a81e75c5fbca62a21d9457d7b1ad8a8
> prerequisite-patch-id: 6f48169f4d69da277bcdecb8f40d2f608941d9f9
> prerequisite-patch-id: fc8b43573cc6b90033769de63ca235b16159190d
> prerequisite-patch-id: ae749fc3fa0ab1768841ffb4633847b5b2233881
> prerequisite-patch-id: 46b8490d2b338229a2f3c5e39427275cf46982ba
> prerequisite-patch-id: b1bb7dfb35069a2b30f5b2714bc19a249be3e1b5
> prerequisite-patch-id: 94848222eb08beb53530ba6ce626e9d8bcffecd4
> prerequisite-patch-id: f8181365677e68d8628013c7636e9ff56214ac9e
> prerequisite-patch-id: aebc0f8156c409599cc7aced4b708bb5ea08a2b2
> prerequisite-patch-id: 4ce416249f6d3176a51d7e4cbbd2c6bf2982bab6
> prerequisite-patch-id: 5e14463dcc090e497bb1d29c1b4c822b43d5fdca
> prerequisite-patch-id: 89306b41386cb29db7c147e8c4468a3b4d8d292d
> prerequisite-patch-id: 29e414b1ede9108047ff224e1e24a3adb2c44c52
> prerequisite-patch-id: 7e15edfd04cd291f54284d13dcdbebcfb456b752
> prerequisite-patch-id: b8c18091929e58b49847ab510d3d75a8a934cad0
> prerequisite-patch-id: 7a607a1659b22afb0c21dec3d8eb1e2ed51e47a9
> prerequisite-patch-id: 89fbd04f11e5bef5703ba7ea4c2064d5ba63c4d4
> prerequisite-patch-id: b421048677352ea536dd93a61d6de987fb95d60b
> prerequisite-patch-id: 25a03298bdfd6a691bb8cf68690009f8e46447e0
> prerequisite-patch-id: 3924163576eafdac47ac06de311ac317730e6631
> prerequisite-patch-id: 69b1d81677b507242f556c3e2fcf5290aeca445c
> prerequisite-patch-id: a378fa79002001da51ae91eb026769eddb8a593b
> prerequisite-patch-id: 86bb35c89ec3cc1b6ec47f238c84a154d5e9a1aa
> prerequisite-patch-id: f8d0709d94ed99b1530bad1908ca27b1b56ea84e
> prerequisite-patch-id: dcb65983aa914b8f1d1a8fbdfba34714ddb7f6fa
> prerequisite-patch-id: 89752146a063d0706885819e244b4179196538b8
> prerequisite-patch-id: 1f9e7627d0b23302159cdab3d939fcec52f7ca70
> prerequisite-patch-id: f706bfa95ba0e5e72c206537ed207feb95daa888
> prerequisite-patch-id: 9b60c519b0df65eeacd5779808e0d75b011ebf7f
> prerequisite-patch-id: cd6cd74eca502ebce581c223cd0d2ac4278912e8
> prerequisite-patch-id: b86e08404ef83877dfa3b76a80a12b02c61b1326
> prerequisite-patch-id: 9417f8d92995cf417bb3c4afa0786b05a756d48a
> prerequisite-patch-id: 59dda13243375b013396981a4f9e17abd694d734
> prerequisite-patch-id: 89be058d0605cb8278d5d3384bb44911b188dd90
> prerequisite-patch-id: 70c26fde2fde34c031a95ef74a3321710dc4961e
> prerequisite-patch-id: 38a27cdf8cbe03fdf5f9bafa5ba53f3ba644a5ad
> prerequisite-patch-id: 40a6d2e51dff2531c40a38087a8aea1be7108792
> prerequisite-patch-id: 024d1bba9bcd449d2b8196b2f1a64a197cafaed8
> prerequisite-patch-id: e83d54aa767ebab267530fca74d60366160a5253
> prerequisite-patch-id: c34734661161c27224316dc519609db5c6d87a1e
> prerequisite-patch-id: a58d739146fe46f6c7f203e5d2e0f114bd3f7834
> prerequisite-patch-id: 1ff8499f5ec69b737d77053e6809ec3a0b599ebc
> prerequisite-patch-id: 498e5608bca9b5ebcb3592a556e75f5dcc2b7076
> prerequisite-patch-id: df6dfdea7c3d9db4649d857ce55fbeb99d4febca
> prerequisite-patch-id: 453b66b1faaaebaa1666954185de327298aa0578
> prerequisite-patch-id: f98da1de781c203a53cae73c5bb707240d21cb0a
> prerequisite-patch-id: 14b1718dbc4fb9cd94e1094a4d44ebfcfe6ad869
> prerequisite-patch-id: 3b68944fa8fb2fab0c21d6ff73f649f53dd6f551
> prerequisite-patch-id: 82d1e6bcd221f982b6ab1ed0e9a90d46a39562c4
> prerequisite-patch-id: c9cce20b146f955b715d15c0c384c9acc6176493
> prerequisite-patch-id: c204491c1db4f5056711768265f101e881e4e415
> prerequisite-patch-id: e66e13fbde027e99552fc6d80ff8d48c110a18f2
> prerequisite-patch-id: 3c313f0a20730c653c8f5ec4f318e2485a8ef60f
> prerequisite-patch-id: 925c466172c01c4b5976ac019961cbe240f0cddd
> prerequisite-patch-id: e81e0aded80adf18c861f67624a179a15ef68906
> prerequisite-patch-id: 001675f7da57d25731c7c71f6f2dcaa7409e5664
> prerequisite-patch-id: d65bf6ef5f51da0acba72d332d60167b34e193e1
> prerequisite-patch-id: fc7c9a5024037363319b58520480a6c4a8a5dcff
> prerequisite-patch-id: 5aae8c77d028459d944021f4943558411deb0662
> prerequisite-patch-id: 71fa80813ad36528e8a737249424d90827933c16
> prerequisite-patch-id: 65dc75b8e1ddb45542480a8867ecd7a63ab3112e
> prerequisite-patch-id: 8619aa1dec17409d9b5ecb6ed0a2cc7d1563c174
> prerequisite-patch-id: 6473142746dc5b448ec9698d577f47b4da6cd1d5
> prerequisite-patch-id: eb6689695d5d1b6c650de0c86a805a45b80ab88d
> prerequisite-patch-id: 7d50679dad38c9f859ec231da2db78919818b40e
> prerequisite-patch-id: faeb97c5f9c07754bd0bf0be59254091470978c2
> prerequisite-patch-id: 56e31c3ab9ed9ff19aca25d5ffb9655c6515b692
> prerequisite-patch-id: 8d7418e017eec3c6e56b55f9ff6181cc3dcc1a17
> prerequisite-patch-id: 84f58e5a274c980ae6905e764d479e1c960149ca
> prerequisite-patch-id: ada6a2d9427bff9dd7fd115a91300a1f7379995c
> prerequisite-patch-id: 108161d5500b39b3ac55d202b5b9af817d829724
> prerequisite-patch-id: c89b0fc7dadc53facc45ccf9991503430b7e7799
> prerequisite-patch-id: d62e2be8f9fd6a1d9ac8dfa2cdc4db6d4a4327ac
> prerequisite-patch-id: f8f4375b2b16ffae596d416607c00b374f485299
> prerequisite-patch-id: 36b1a9c3e0e9f91b7172e1211231759a6cb81473
> prerequisite-patch-id: 8cb6ac6a5188c817bb3a6a86920001de75bb7225
> prerequisite-patch-id: 17ef87336a8c664e0109a7466c9f7d37f5901167
> prerequisite-patch-id: a2c72266baec1b3eb5706d43157d93ae8db5e42d
> prerequisite-patch-id: 27503579f8bdfadb95847b8dd5bf3732f5149cfb
> prerequisite-patch-id: 50d6d9c6ff0734705ae384ede694b547f4973249
> prerequisite-patch-id: 81cd72752ab376d459dceff93f71715e55a55846
> prerequisite-patch-id: 922cec7ef3d21275f5933968f5b704e0bed64ce5
> prerequisite-patch-id: 1f0903e8846cd59d0d5a3dcbf9a5a82ad4dcb5cd
> prerequisite-patch-id: 69d839b9d5b794ef1b7dee9c592ed20300f8539f

--
Best regards,
Nicolas Graves
N
N
Nicolas Graves wrote on 26 Sep 2023 13:29
[PATCH v4] guix: composer-build-system: Fix match-lambda with a fallback.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
0cfb53602b5fddfab305d55573ed36910dba379a.1695727762.git.ngraves@ngraves.fr
* guix/build/composer-build-system.scm:
(composer-package): Fix match-lambda with a default fallback.
(composer-autoload): Fix match-lambda with a default fallback.
---
guix/build/composer-build-system.scm | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

Toggle diff (165 lines)
diff --git a/guix/build/composer-build-system.scm b/guix/build/composer-build-system.scm
index 7df2b7c400..d891ea3a6d 100644
--- a/guix/build/composer-build-system.scm
+++ b/guix/build/composer-build-system.scm
@@ -46,12 +46,12 @@ (define-json-mapping <composer-autoload> make-composer-autoload composer-autoloa
json->composer-autoload
(psr-4 composer-autoload-psr-4 "psr-4"
(match-lambda
- (#f '())
- (psr-4 psr-4)))
+ (psr-4 psr-4)
+ (_ '())))
(classmap composer-autoload-classmap "classmap"
(match-lambda
- (#f '())
- (#(lst ...) lst))))
+ (#(lst ...) lst)
+ (_ '()))))
(define-json-mapping <composer-package> make-composer-package composer-package?
json->composer-package
@@ -62,12 +62,12 @@ (define-json-mapping <composer-package> make-composer-package composer-package?
(dev-require composer-package-dev-require "require-dev" json->require)
(scripts composer-package-scripts "scripts"
(match-lambda
- (#f '())
- ((scripts ...) scripts)))
+ ((scripts ...) scripts)
+ (_ '())))
(binaries composer-package-binaries "bin"
(match-lambda
- (#f '())
- (#(lst ...) lst))))
+ (#(lst ...) lst)
+ (_ '()))))
(define* (read-package-data #:key (filename "composer.json"))
(call-with-input-file filename

base-commit: fafd3caef0d51811a5da81d6061789e2908b0dac
prerequisite-patch-id: eb618ab7b10483d917c308a38792af98baa517e2
prerequisite-patch-id: c12968d02d99c253f858586a86b16fa32d41f1c1
prerequisite-patch-id: 09d995d48139f8e61183d5634cda13a01cdb50f7
prerequisite-patch-id: 86baa45ec2aad977c8c8135f7613aa391155de6d
prerequisite-patch-id: 3425fbbff6a603d60b4e143ea2141aabf4ddc92c
prerequisite-patch-id: c373c01aab5dcba3503a97d51c62a595147a041c
prerequisite-patch-id: cda857c790b88c681c4e713c5f71e40291970daf
prerequisite-patch-id: 8e234d0f4d93d2aad499eec8842be3d28da98707
prerequisite-patch-id: 5f664cb2fd995a53765c5ffc19a708ac795cc0c4
prerequisite-patch-id: ed447cba9cf9b7e1a1b47aa27acb14f8f2da0a8e
prerequisite-patch-id: 9f80c5bbbfb8cd3347951c4d57634e93ffa79924
prerequisite-patch-id: 1aaa9f0d466e2d6837f75844df48a98beb70ff24
prerequisite-patch-id: 34502820d8c0355b3ed2638c457084edeaba029d
prerequisite-patch-id: a96258da9e78cfb9ac9893cdcdeb38b69b75f134
prerequisite-patch-id: 4a2da4ee89dbbdb2244845149ce6da967ddd5268
prerequisite-patch-id: 9f9c4205781d1f0e2bb7af2d21875de08ee3ecd5
prerequisite-patch-id: 9697db9b50cab8f7974c32383e0a9a786ecbd8f9
prerequisite-patch-id: ebbd089a3313232347273c723d3deb1bf8c9bf81
prerequisite-patch-id: e93360d66936b9efd70a6ffd41f6ecda177ad7b8
prerequisite-patch-id: 19d76f45db1c59bd9ccd2e4e1125ffd698e9d6ce
prerequisite-patch-id: 929b39ded7ad095e9f768f7d484bbd3b7a486a3c
prerequisite-patch-id: 5e1262f77d55c91eadca113223faa84935bffd60
prerequisite-patch-id: ad370d41983418fa704215aa3458f97c75d5d128
prerequisite-patch-id: f179c922613390d249a365625c2ee545a908029d
prerequisite-patch-id: 03b0aaa382ddda0819ddb62479cd1885c930ddea
prerequisite-patch-id: 83b8b3a072520705dcba4b67712a29553bea1548
prerequisite-patch-id: 9308fa06526d9bacdbcdd347cc225f6f3f87811a
prerequisite-patch-id: a017243a1a4b406caed9cec048d194cdc33d1a25
prerequisite-patch-id: e8d5b2e787904b0dd1a650d7a0012b91a430cb03
prerequisite-patch-id: 1cc872245864ace22db43cf2d268a87190b333b6
prerequisite-patch-id: c277dcca77f3acde51bdffe932b9250e454086ad
prerequisite-patch-id: ea926073e68d5af7f6c76a6333520cc5f42c9789
prerequisite-patch-id: 10008b9b34ccc8f87f2fcd8391075fe57244ac72
prerequisite-patch-id: 443d7e3eb85f36848c2120979f9f1d3a78f8bf38
prerequisite-patch-id: 6414c2d65c1806942d7f834e9300a8ecf8fd743f
prerequisite-patch-id: 8c6dec06b716c39ca7fada0f2872078612917779
prerequisite-patch-id: 62e28252e9b7ab11edb03609b68369feb499f883
prerequisite-patch-id: 84c9361c4c6d7662cfb3235cc4a6640a53e00622
prerequisite-patch-id: 0f27045bc50089a9a88da7818448a50cd28dd295
prerequisite-patch-id: 500413da3a81e75c5fbca62a21d9457d7b1ad8a8
prerequisite-patch-id: 6f48169f4d69da277bcdecb8f40d2f608941d9f9
prerequisite-patch-id: fc8b43573cc6b90033769de63ca235b16159190d
prerequisite-patch-id: ae749fc3fa0ab1768841ffb4633847b5b2233881
prerequisite-patch-id: 46b8490d2b338229a2f3c5e39427275cf46982ba
prerequisite-patch-id: b1bb7dfb35069a2b30f5b2714bc19a249be3e1b5
prerequisite-patch-id: 94848222eb08beb53530ba6ce626e9d8bcffecd4
prerequisite-patch-id: f8181365677e68d8628013c7636e9ff56214ac9e
prerequisite-patch-id: aebc0f8156c409599cc7aced4b708bb5ea08a2b2
prerequisite-patch-id: 4ce416249f6d3176a51d7e4cbbd2c6bf2982bab6
prerequisite-patch-id: 5e14463dcc090e497bb1d29c1b4c822b43d5fdca
prerequisite-patch-id: 89306b41386cb29db7c147e8c4468a3b4d8d292d
prerequisite-patch-id: 29e414b1ede9108047ff224e1e24a3adb2c44c52
prerequisite-patch-id: 7e15edfd04cd291f54284d13dcdbebcfb456b752
prerequisite-patch-id: b8c18091929e58b49847ab510d3d75a8a934cad0
prerequisite-patch-id: 7a607a1659b22afb0c21dec3d8eb1e2ed51e47a9
prerequisite-patch-id: 89fbd04f11e5bef5703ba7ea4c2064d5ba63c4d4
prerequisite-patch-id: b421048677352ea536dd93a61d6de987fb95d60b
prerequisite-patch-id: 25a03298bdfd6a691bb8cf68690009f8e46447e0
prerequisite-patch-id: 3924163576eafdac47ac06de311ac317730e6631
prerequisite-patch-id: 69b1d81677b507242f556c3e2fcf5290aeca445c
prerequisite-patch-id: a378fa79002001da51ae91eb026769eddb8a593b
prerequisite-patch-id: 86bb35c89ec3cc1b6ec47f238c84a154d5e9a1aa
prerequisite-patch-id: f8d0709d94ed99b1530bad1908ca27b1b56ea84e
prerequisite-patch-id: dcb65983aa914b8f1d1a8fbdfba34714ddb7f6fa
prerequisite-patch-id: 89752146a063d0706885819e244b4179196538b8
prerequisite-patch-id: 1f9e7627d0b23302159cdab3d939fcec52f7ca70
prerequisite-patch-id: f706bfa95ba0e5e72c206537ed207feb95daa888
prerequisite-patch-id: 9b60c519b0df65eeacd5779808e0d75b011ebf7f
prerequisite-patch-id: cd6cd74eca502ebce581c223cd0d2ac4278912e8
prerequisite-patch-id: b86e08404ef83877dfa3b76a80a12b02c61b1326
prerequisite-patch-id: 9417f8d92995cf417bb3c4afa0786b05a756d48a
prerequisite-patch-id: 59dda13243375b013396981a4f9e17abd694d734
prerequisite-patch-id: 89be058d0605cb8278d5d3384bb44911b188dd90
prerequisite-patch-id: 70c26fde2fde34c031a95ef74a3321710dc4961e
prerequisite-patch-id: 38a27cdf8cbe03fdf5f9bafa5ba53f3ba644a5ad
prerequisite-patch-id: 40a6d2e51dff2531c40a38087a8aea1be7108792
prerequisite-patch-id: 024d1bba9bcd449d2b8196b2f1a64a197cafaed8
prerequisite-patch-id: e83d54aa767ebab267530fca74d60366160a5253
prerequisite-patch-id: c34734661161c27224316dc519609db5c6d87a1e
prerequisite-patch-id: a58d739146fe46f6c7f203e5d2e0f114bd3f7834
prerequisite-patch-id: 1ff8499f5ec69b737d77053e6809ec3a0b599ebc
prerequisite-patch-id: 498e5608bca9b5ebcb3592a556e75f5dcc2b7076
prerequisite-patch-id: df6dfdea7c3d9db4649d857ce55fbeb99d4febca
prerequisite-patch-id: 453b66b1faaaebaa1666954185de327298aa0578
prerequisite-patch-id: f98da1de781c203a53cae73c5bb707240d21cb0a
prerequisite-patch-id: 14b1718dbc4fb9cd94e1094a4d44ebfcfe6ad869
prerequisite-patch-id: 3b68944fa8fb2fab0c21d6ff73f649f53dd6f551
prerequisite-patch-id: 82d1e6bcd221f982b6ab1ed0e9a90d46a39562c4
prerequisite-patch-id: c9cce20b146f955b715d15c0c384c9acc6176493
prerequisite-patch-id: c204491c1db4f5056711768265f101e881e4e415
prerequisite-patch-id: e66e13fbde027e99552fc6d80ff8d48c110a18f2
prerequisite-patch-id: 3c313f0a20730c653c8f5ec4f318e2485a8ef60f
prerequisite-patch-id: 925c466172c01c4b5976ac019961cbe240f0cddd
prerequisite-patch-id: e81e0aded80adf18c861f67624a179a15ef68906
prerequisite-patch-id: 001675f7da57d25731c7c71f6f2dcaa7409e5664
prerequisite-patch-id: d65bf6ef5f51da0acba72d332d60167b34e193e1
prerequisite-patch-id: fc7c9a5024037363319b58520480a6c4a8a5dcff
prerequisite-patch-id: 5aae8c77d028459d944021f4943558411deb0662
prerequisite-patch-id: 71fa80813ad36528e8a737249424d90827933c16
prerequisite-patch-id: 65dc75b8e1ddb45542480a8867ecd7a63ab3112e
prerequisite-patch-id: 8619aa1dec17409d9b5ecb6ed0a2cc7d1563c174
prerequisite-patch-id: 6473142746dc5b448ec9698d577f47b4da6cd1d5
prerequisite-patch-id: eb6689695d5d1b6c650de0c86a805a45b80ab88d
prerequisite-patch-id: 7d50679dad38c9f859ec231da2db78919818b40e
prerequisite-patch-id: faeb97c5f9c07754bd0bf0be59254091470978c2
prerequisite-patch-id: 56e31c3ab9ed9ff19aca25d5ffb9655c6515b692
prerequisite-patch-id: 8d7418e017eec3c6e56b55f9ff6181cc3dcc1a17
prerequisite-patch-id: 84f58e5a274c980ae6905e764d479e1c960149ca
prerequisite-patch-id: ada6a2d9427bff9dd7fd115a91300a1f7379995c
prerequisite-patch-id: 108161d5500b39b3ac55d202b5b9af817d829724
prerequisite-patch-id: c89b0fc7dadc53facc45ccf9991503430b7e7799
prerequisite-patch-id: d62e2be8f9fd6a1d9ac8dfa2cdc4db6d4a4327ac
prerequisite-patch-id: f8f4375b2b16ffae596d416607c00b374f485299
prerequisite-patch-id: 36b1a9c3e0e9f91b7172e1211231759a6cb81473
prerequisite-patch-id: 8cb6ac6a5188c817bb3a6a86920001de75bb7225
prerequisite-patch-id: 17ef87336a8c664e0109a7466c9f7d37f5901167
prerequisite-patch-id: a2c72266baec1b3eb5706d43157d93ae8db5e42d
prerequisite-patch-id: 27503579f8bdfadb95847b8dd5bf3732f5149cfb
prerequisite-patch-id: 50d6d9c6ff0734705ae384ede694b547f4973249
prerequisite-patch-id: 81cd72752ab376d459dceff93f71715e55a55846
prerequisite-patch-id: 922cec7ef3d21275f5933968f5b704e0bed64ce5
prerequisite-patch-id: 1f0903e8846cd59d0d5a3dcbf9a5a82ad4dcb5cd
prerequisite-patch-id: 69d839b9d5b794ef1b7dee9c592ed20300f8539f
--
2.41.0
L
L
Ludovic Courtès wrote on 14 Oct 2023 17:48
Re: [bug#42338] [PATCH v3 1/7] guix: import: Add composer importer.
(name . Nicolas Graves)(address . ngraves@ngraves.fr)
87edhxfbnh.fsf@gnu.org
Hi Nicolas,

Nicolas Graves <ngraves@ngraves.fr> skribis:

Toggle quote (7 lines)
> * guix/import/composer.scm: New file.
> * guix/scripts/import/composer.scm: New file.
> * guix/tests/composer.scm: New file.
> * Makefile.am: Add them.
> * guix/scripts/import.scm: Add composer importer.
> * doc/guix.texi (Invoking guix import): Mention it.

I’m a bit at loss with this patch series because there are two v3
threads, one v4 thread that contains a single patch, and the original
versions contained many more patches.

I think it’s OK to separate out the “gnu: Add php-*” patches, it’s
probably clearer. However, could you come up with a v5 that includes
all the ‘guix import composer’ changes that we would need to apply?
How does that sound?

I have a couple of comments:

Toggle quote (4 lines)
> +@item composer
> +@cindex Composer
> +@cindex PHP
> +Import metadat from the @uref{https://getcomposer.org/, Composer} package
^
Typo.

Toggle quote (5 lines)
> +++ b/guix/import/composer.scm
> @@ -0,0 +1,270 @@
> +;;; GNU Guix --- Functional package management for GNU
> +;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>

Maybe add yourself too?

Toggle quote (13 lines)
> +;; XXX adapted from (guix scripts hash)
> +(define (file-hash file select? recursive?)
> + ;; Compute the hash of FILE.
> + (if recursive?
> + (let-values (((port get-hash) (open-sha256-port)))
> + (write-file file port #:select? select?)
> + (force-output port)
> + (get-hash))
> + (call-with-input-file file port-sha256)))
> +
> +;; XXX taken from (guix scripts hash)
> +(define (vcs-file? file stat)

These two procedures are now exported from (guix hash), so you can
remove them and #:use-module (guix hash) instead.

Toggle quote (17 lines)
> +(define* (composer-fetch name #:optional version)
> + "Return an alist representation of the Composer metadata for the package NAME,
> +or #f on failure."
> + (let ((package (json-fetch
> + (string-append (%composer-base-url) "/p/" name ".json"))))
> + (if package
> + (let* ((packages (assoc-ref package "packages"))
> + (package (or (assoc-ref packages name) package))
> + (versions (filter
> + (lambda (version)
> + (and (not (string-contains version "dev"))
> + (not (string-contains version "beta"))))
> + (map car package)))
> + (version (or (if (null? version) #f version)
> + (latest-version versions))))
> + (assoc-ref package version))

Instead of returning an alist, directly return a <composer-package>
record.

Toggle quote (5 lines)
> +(define (php-package? package)
> + "Return true if PACKAGE is a PHP package from Packagist."
> + (and
> + (eq? (build-system-name (package-build-system package)) 'composer)

Rather: (eq? (package-build-system package) composer-build-system).

(The ‘name’ field is for debugging purposes only.)

Toggle quote (12 lines)
> +(define (latest-release package)
> + "Return an <upstream-source> for the latest release of PACKAGE."
> + (let* ((php-name (guix-package->composer-name package))
> + (metadata (composer-fetch php-name))
> + (package (json->composer-package metadata))
> + (version (composer-package-version package))
> + (url (composer-source-url (composer-package-source package))))
> + (upstream-source
> + (package (package-name package))
> + (version version)
> + (urls (list url)))))

Maybe we can do that later, but note that <upstream-source> has an
‘inputs’ field nowadays; if you feel it in, ‘guix refresh -u’ is able to
update dependencies in addition to version/hash.

(If you leave it for later, please add a TODO.)

Toggle quote (3 lines)
> +;; Avoid collisions with other tests.
> +(%http-server-port 10450)

This is now unnecessary: by default a random unused port is chosen and
everything’s fine.

Toggle quote (13 lines)
> +(test-begin "composer")
> +
> +(test-assert "composer->guix-package"
> + ;; Replace network resources with sample data.
> + (with-http-server `((200 ,test-json)
> + (200 ,test-source))
> + (parameterize ((%composer-base-url (%local-url))
> + (current-http-proxy (%local-url)))
> + (match (composer->guix-package "foo/bar")
> + (('package
> + ('name "php-foo-bar")
> + ('version "0.1")

For clarity, you can write:

(match …
(`(package
(name "php-foo-bar")
(version "0.1")
…) …))

See commit 654fcf9971bb01389d577be07c6ec0f68940c743.

Toggle quote (4 lines)
> + ('native-inputs
> + ('quasiquote
> + (("php-phpunit-phpunit" ('unquote 'php-phpunit-phpunit)))))

Please change the importer so that it emits inputs without labels:

(native-inputs (list php-phpunit-phpunit))

One last thing: consider adding an ‘etc/news.scm’ entry so people can
learn about the new importer.

Thanks in advance!

Ludo’.
N
N
Nicolas Graves wrote on 2 Nov 2023 16:04
[PATCH 1/9] guix: import: Add composer importer.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151523.30581-2-ngraves@ngraves.fr
* guix/import/composer.scm: New file.
* guix/scripts/import/composer.scm: New file.
* guix/tests/composer.scm: New file.
* Makefile.am: Add them.
* guix/scripts/import.scm: Add composer importer.
* doc/guix.texi (Invoking guix import): Mention it.
---
Makefile.am | 3 +
doc/guix.texi | 20 +++
guix/import/composer.scm | 270 +++++++++++++++++++++++++++++++
guix/scripts/import.scm | 2 +-
guix/scripts/import/composer.scm | 107 ++++++++++++
tests/composer.scm | 92 +++++++++++
6 files changed, 493 insertions(+), 1 deletion(-)
create mode 100644 guix/import/composer.scm
create mode 100644 guix/scripts/import/composer.scm
create mode 100644 tests/composer.scm

Toggle diff (507 lines)
diff --git a/Makefile.am b/Makefile.am
index 310a231259..3fec98f064 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -274,6 +274,7 @@ MODULES = \
guix/search-paths.scm \
guix/packages.scm \
guix/import/cabal.scm \
+ guix/import/composer.scm \
guix/import/cpan.scm \
guix/import/cran.scm \
guix/import/crate.scm \
@@ -332,6 +333,7 @@ MODULES = \
guix/scripts/home/import.scm \
guix/scripts/lint.scm \
guix/scripts/challenge.scm \
+ guix/scripts/import/composer.scm \
guix/scripts/import/crate.scm \
guix/scripts/import/cpan.scm \
guix/scripts/import/cran.scm \
@@ -504,6 +506,7 @@ SCM_TESTS = \
tests/challenge.scm \
tests/channels.scm \
tests/combinators.scm \
+ tests/composer.scm \
tests/containers.scm \
tests/cpan.scm \
tests/cpio.scm \
diff --git a/doc/guix.texi b/doc/guix.texi
index 8c5697589f..0e64654715 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -14539,6 +14539,26 @@ guix import hexpm cf@@0.3.0
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
+
+@item composer
+@cindex Composer
+@cindex PHP
+Import metadat from the @uref{https://getcomposer.org/, Composer} package
+archive used by the PHP community, as in this example:
+
+@example
+guix import composer phpunit/phpunit
+@end example
+
+Additional options include:
+
@table @code
@item --recursive
@itemx -r
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
new file mode 100644
index 0000000000..c152f402bb
--- /dev/null
+++ b/guix/import/composer.scm
@@ -0,0 +1,270 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix import composer)
+ #:use-module (ice-9 match)
+ #:use-module (json)
+ #:use-module (gcrypt hash)
+ #:use-module (guix base32)
+ #:use-module (guix build git)
+ #:use-module (guix build utils)
+ #:use-module (guix build-system)
+ #:use-module (guix import json)
+ #:use-module (guix import utils)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (guix packages)
+ #:use-module (guix serialization)
+ #:use-module (guix upstream)
+ #:use-module (guix utils)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-11)
+ #:use-module (srfi srfi-26)
+ #:export (composer->guix-package
+ %composer-updater
+ composer-recursive-import
+
+ %composer-base-url))
+
+(define %composer-base-url
+ (make-parameter "https://repo.packagist.org"))
+
+;; XXX adapted from (guix scripts hash)
+(define (file-hash file select? recursive?)
+ ;; Compute the hash of FILE.
+ (if recursive?
+ (let-values (((port get-hash) (open-sha256-port)))
+ (write-file file port #:select? select?)
+ (force-output port)
+ (get-hash))
+ (call-with-input-file file port-sha256)))
+
+;; XXX taken from (guix scripts hash)
+(define (vcs-file? file stat)
+ (case (stat:type stat)
+ ((directory)
+ (member (basename file) '(".bzr" ".git" ".hg" ".svn" "CVS")))
+ ((regular)
+ ;; Git sub-modules have a '.git' file that is a regular text file.
+ (string=? (basename file) ".git"))
+ (else
+ #f)))
+
+(define (fix-version version)
+ "Return a fixed version from a version string. For instance, v10.1 -> 10.1"
+ (cond
+ ((string-prefix? "version" version)
+ (if (char-set-contains? char-set:digit (string-ref version 7))
+ (substring version 7)
+ (substring version 8)))
+ ((string-prefix? "v" version)
+ (substring version 1))
+ (else version)))
+
+(define (latest-version versions)
+ (fold (lambda (a b) (if (version>? (fix-version a) (fix-version b)) a b))
+ (car versions) versions))
+
+(define (json->require dict)
+ (if dict
+ (let loop ((result '()) (require dict))
+ (match require
+ (() result)
+ ((((? (cut string-contains <> "/") name) . _)
+ require ...)
+ (loop (cons name result) require))
+ ((_ require ...) (loop result require))))
+ '()))
+
+(define-json-mapping <composer-source> make-composer-source composer-source?
+ json->composer-source
+ (type composer-source-type)
+ (url composer-source-url)
+ (reference composer-source-reference))
+
+(define-json-mapping <composer-package> make-composer-package composer-package?
+ json->composer-package
+ (description composer-package-description)
+ (homepage composer-package-homepage)
+ (source composer-package-source "source" json->composer-source)
+ (name composer-package-name "name" php-package-name)
+ (version composer-package-version "version" fix-version)
+ (require composer-package-require "require" json->require)
+ (dev-require composer-package-dev-require "require-dev" json->require)
+ (license composer-package-license "license"
+ (lambda (vector)
+ (map string->license (vector->list vector)))))
+
+(define* (composer-fetch name #:optional version)
+ "Return an alist representation of the Composer metadata for the package NAME,
+or #f on failure."
+ (let ((package (json-fetch
+ (string-append (%composer-base-url) "/p/" name ".json"))))
+ (if package
+ (let* ((packages (assoc-ref package "packages"))
+ (package (or (assoc-ref packages name) package))
+ (versions (filter
+ (lambda (version)
+ (and (not (string-contains version "dev"))
+ (not (string-contains version "beta"))))
+ (map car package)))
+ (version (or (if (null? version) #f version)
+ (latest-version versions))))
+ (assoc-ref package version))
+ #f)))
+
+(define (php-package-name name)
+ "Given the NAME of a package on Packagist, return a Guix-compliant name for
+the package."
+ (let ((name (string-join (string-split name #\/) "-")))
+ (if (string-prefix? "php-" name)
+ (snake-case name)
+ (string-append "php-" (snake-case name)))))
+
+(define (make-php-sexp composer-package)
+ "Return the `package' s-expression for a PHP package for the given
+COMPOSER-PACKAGE."
+ (let* ((source (composer-package-source composer-package))
+ (dependencies (map php-package-name
+ (composer-package-require composer-package)))
+ (dev-dependencies (map php-package-name
+ (composer-package-dev-require composer-package)))
+ (git? (equal? (composer-source-type source) "git")))
+ ((if git? call-with-temporary-directory call-with-temporary-output-file)
+ (lambda* (temp #:optional port)
+ (and (if git?
+ (begin
+ (mkdir-p temp)
+ (git-fetch (composer-source-url source)
+ (composer-source-reference source)
+ temp))
+ (url-fetch (composer-source-url source) temp))
+ `(package
+ (name ,(composer-package-name composer-package))
+ (version ,(composer-package-version composer-package))
+ (source (origin
+ ,@(if git?
+ `((method git-fetch)
+ (uri (git-reference
+ (url ,(composer-source-url source))
+ (commit ,(composer-source-reference source))))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ ,(bytevector->nix-base32-string
+ (file-hash temp (negate vcs-file?) #t)))))
+ `((method url-fetch)
+ (uri ,(composer-source-url source))
+ (sha256 (base32 ,(guix-hash-url temp)))))))
+ (build-system composer-build-system)
+ ,@(if (null? dependencies)
+ '()
+ `((inputs
+ (,'quasiquote
+ ,(map (lambda (name)
+ `(,name
+ (,'unquote
+ ,(string->symbol name))))
+ dependencies)))))
+ ,@(if (null? dev-dependencies)
+ '()
+ `((native-inputs
+ (,'quasiquote
+ ,(map (lambda (name)
+ `(,name
+ (,'unquote
+ ,(string->symbol name))))
+ dev-dependencies)))))
+ (synopsis "")
+ (description ,(composer-package-description composer-package))
+ (home-page ,(composer-package-homepage composer-package))
+ (license ,(match (composer-package-license composer-package)
+ (() #f)
+ ((license) license)
+ (_ license)))))))))
+
+(define* (composer->guix-package package-name #:optional version)
+ "Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
+`package' s-expression corresponding to that package, or #f on failure."
+ (let ((package (composer-fetch package-name version)))
+ (and package
+ (let* ((package (json->composer-package package))
+ (dependencies-names (composer-package-require package))
+ (dev-dependencies-names (composer-package-dev-require package)))
+ (values (make-php-sexp package)
+ (append dependencies-names dev-dependencies-names))))))
+
+(define (guix-name->composer-name name)
+ "Given a guix package name, return the name of the package in Packagist."
+ (if (string-prefix? "php-" name)
+ (let ((components (string-split (substring name 4) #\-)))
+ (match components
+ ((namespace name ...)
+ (string-append namespace "/" (string-join name "-")))))
+ name))
+
+(define (guix-package->composer-name package)
+ "Given a Composer PACKAGE built from Packagist, return the name of the
+package in Packagist."
+ (let ((upstream-name (assoc-ref
+ (package-properties package)
+ 'upstream-name))
+ (name (package-name package)))
+ (if upstream-name
+ upstream-name
+ (guix-name->composer-name name))))
+
+(define (string->license str)
+ "Convert the string STR into a license object."
+ (match str
+ ("GNU LGPL" 'license:lgpl2.0)
+ ("GPL" 'license:gpl3)
+ ((or "BSD" "BSD License" "BSD-3-Clause") 'license:bsd-3)
+ ((or "MIT" "MIT license" "Expat license") 'license:expat)
+ ("Public domain" 'license:public-domain)
+ ((or "Apache License, Version 2.0" "Apache 2.0") 'license:asl2.0)
+ (_ #f)))
+
+(define (php-package? package)
+ "Return true if PACKAGE is a PHP package from Packagist."
+ (and
+ (eq? (build-system-name (package-build-system package)) 'composer)
+ (string-prefix? "php-" (package-name package))))
+
+(define (latest-release package)
+ "Return an <upstream-source> for the latest release of PACKAGE."
+ (let* ((php-name (guix-package->composer-name package))
+ (metadata (composer-fetch php-name))
+ (package (json->composer-package metadata))
+ (version (composer-package-version package))
+ (url (composer-source-url (composer-package-source package))))
+ (upstream-source
+ (package (package-name package))
+ (version version)
+ (urls (list url)))))
+
+(define %composer-updater
+ (upstream-updater
+ (name 'composer)
+ (description "Updater for Composer packages")
+ (pred php-package?)
+ (import latest-release)))
+
+(define* (composer-recursive-import package-name #:optional version)
+ (recursive-import package-name '()
+ #:repo->guix-package composer->guix-package
+ #:guix-name php-package-name))
diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm
index 4ddd8d46a1..8c58dd35e2 100644
--- a/guix/scripts/import.scm
+++ b/guix/scripts/import.scm
@@ -47,7 +47,7 @@ (define %standard-import-options '())
(define importers '("gnu" "pypi" "cpan" "hackage" "stackage" "egg" "elpa"
"gem" "go" "cran" "crate" "texlive" "json" "opam"
- "minetest" "elm" "hexpm"))
+ "minetest" "elm" "hexpm" "composer"))
(define (resolve-importer name)
(let ((module (resolve-interface
diff --git a/guix/scripts/import/composer.scm b/guix/scripts/import/composer.scm
new file mode 100644
index 0000000000..412bae6318
--- /dev/null
+++ b/guix/scripts/import/composer.scm
@@ -0,0 +1,107 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2015 David Thompson <davet@gnu.org>
+;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix scripts import composer)
+ #:use-module (guix ui)
+ #:use-module (guix utils)
+ #:use-module (guix scripts)
+ #:use-module (guix import composer)
+ #:use-module (guix scripts import)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-11)
+ #:use-module (srfi srfi-37)
+ #:use-module (srfi srfi-41)
+ #:use-module (ice-9 match)
+ #:use-module (ice-9 format)
+ #:export (guix-import-composer))
+
+
+;;;
+;;; Command-line options.
+;;;
+
+(define %default-options
+ '())
+
+(define (show-help)
+ (display (G_ "Usage: guix import composer PACKAGE-NAME
+Import and convert the Composer package for PACKAGE-NAME.\n"))
+ (display (G_ "
+ -h, --help display this help and exit"))
+ (display (G_ "
+ -V, --version display version information and exit"))
+ (display (G_ "
+ -r, --recursive generate package expressions for all Composer packages\
+ that are not yet in Guix"))
+ (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 composer")))
+ (option '(#\r "recursive") #f #f
+ (lambda (opt name arg result)
+ (alist-cons 'recursive #t result)))
+ %standard-import-options))
+
+
+;;;
+;;; Entry point.
+;;;
+
+(define (guix-import-composer . 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))
+ (args (filter-map (match-lambda
+ (('argument . value)
+ value)
+ (_ #f))
+ (reverse opts))))
+ (match args
+ ((package-name)
+ (if (assoc-ref opts 'recursive)
+ (map (match-lambda
+ ((and ('package ('name name) . rest) pkg)
+ `(define-public ,(string->symbol name)
+ ,pkg))
+ (_ #f))
+ (composer-recursive-import package-name))
+ (let ((sexp (composer->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/composer.scm b/tests/composer.scm
new file mode 100644
index 0000000000..cefaf9f434
--- /dev/null
+++ b/tests/composer.scm
@@ -0,0 +1,92 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (test-composer)
+ #:use-module (guix import composer)
+ #:use-module (guix base32)
+ #:use-module (gcrypt hash)
+ #:use-module (guix tests http)
+ #:use-module (guix grafts)
+ #:use-module (srfi srfi-64)
+ #:use-module (web client)
+ #:use-module (ice-9 match))
+
+;; Globally disable grafts because they can trigger early builds.
+(%graft? #f)
+
+(define test-json
+ "{
+ \"packages\": {
+ \"foo/bar\": {
+ \"0.1\": {
+ \"name\": \"foo/bar\",
+ \"description\": \"description\",
+ \"keywords\": [\"testing\"],
+ \"homepage\": \"http://example.com
This message was truncated. Download the full message here.
N
N
Nicolas Graves wrote on 2 Nov 2023 16:04
[PATCH 0/9] Composer build system
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151523.30581-1-ngraves@ngraves.fr
This is the result of my further rework of the composer import and
build-system. The `guix: import: composer` commits can be squashed
easily.

This is now tested on 94 php packages with all testing enabled except
for 3 packages. I will submit these packages as a whole in the
alphabetical order (the bootstrap order is not worth it IMO) in a new
guix issue.

Before accepting it, I also would like to propose a change of
names. If me make an analogy with python:
tool: pip <-> composer
package hub: pypi <-> packagist
build-system: python/pyproject <-> php

Since we only take about 90 lines of real composer code, I would
rather call the build-system php-build-system.
Same thing: instead of `guix import composer` we should rather call
`guix import packagist`.

If that's OK, I'll change it with the next (and hopefully last!)
version of this build system.

Nicolas Graves (9):
guix: import: Add composer importer.
gnu: Add composer-classloader.
guix: Add composer-build-system.
guix: import: composer: Use memoization.
guix: import: composer: Fix json->require.
guix: import: composer: More robust string->license.
guix: import: composer: Modern inputs formatting.
guix: import: composer: Full rewrite composer-fetch.
gnu: composer-build-system: Full check phase rewrite.

Makefile.am | 6 +
doc/guix.texi | 34 +++
gnu/local.mk | 1 +
gnu/packages/aux-files/findclass.php | 125 +++++++++++
gnu/packages/php-xyz.scm | 60 ++++++
guix/build-system/composer.scm | 164 +++++++++++++++
guix/build/composer-build-system.scm | 300 +++++++++++++++++++++++++++
guix/import/composer.scm | 267 ++++++++++++++++++++++++
guix/scripts/import.scm | 2 +-
guix/scripts/import/composer.scm | 107 ++++++++++
tests/composer.scm | 88 ++++++++
11 files changed, 1153 insertions(+), 1 deletion(-)
create mode 100644 gnu/packages/aux-files/findclass.php
create mode 100644 gnu/packages/php-xyz.scm
create mode 100644 guix/build-system/composer.scm
create mode 100644 guix/build/composer-build-system.scm
create mode 100644 guix/import/composer.scm
create mode 100644 guix/scripts/import/composer.scm
create mode 100644 tests/composer.scm

--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:04
[PATCH 2/9] gnu: Add composer-classloader.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151523.30581-3-ngraves@ngraves.fr
* gnu/packages/php-xyz.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
---
gnu/local.mk | 1 +
gnu/packages/php-xyz.scm | 60 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+)
create mode 100644 gnu/packages/php-xyz.scm

Toggle diff (80 lines)
diff --git a/gnu/local.mk b/gnu/local.mk
index 83b5268c7e..f1d16f873c 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -502,6 +502,7 @@ GNU_SYSTEM_MODULES = \
%D%/packages/photo.scm \
%D%/packages/phabricator.scm \
%D%/packages/php.scm \
+ %D%/packages/php-xyz.scm \
%D%/packages/piet.scm \
%D%/packages/pikchr.scm \
%D%/packages/pkg-config.scm \
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
new file mode 100644
index 0000000000..ac90ee3c25
--- /dev/null
+++ b/gnu/packages/php-xyz.scm
@@ -0,0 +1,60 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (gnu packages php-xyz)
+ #:use-module (gnu packages)
+ #:use-module (gnu packages php)
+ #:use-module (guix packages)
+ #:use-module (guix download)
+ #:use-module (guix git-download)
+ #:use-module (guix build-system composer)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix utils)
+ #:use-module ((guix licenses) #:prefix license:))
+
+(define-public composer-classloader
+ (package
+ (name "composer-classloader")
+ (version "1.9.0")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/composer/composer")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32 "0127zmmg3yx84ljngfs86q7kjhyypybkf4d1ihfrfnzgynzxfxdf"))))
+ (build-system gnu-build-system)
+ (arguments
+ `(#:phases
+ (modify-phases %standard-phases
+ (delete 'configure)
+ (delete 'build)
+ (delete 'check)
+ (replace 'install
+ (lambda* (#:key outputs #:allow-other-keys)
+ (let* ((out (assoc-ref outputs "out")))
+ (install-file "src/Composer/Autoload/ClassLoader.php"
+ (string-append out "/share/web/composer/"))))))))
+ (home-page "https://getcomposer.org")
+ (synopsis "PHP class loader extracted from the composer package")
+ (description "This package contains the class loader class used by Composer to
+build its autoloading feature. This package is used by the composer-build-system
+to build its own store-aware autoloading feature.")
+ (license license:expat)))
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:04
[PATCH 3/9] guix: Add composer-build-system.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151523.30581-4-ngraves@ngraves.fr
* guix/build-system/composer.scm: New file.
* guix/build/composer-build-system.scm: New file.
* gnu/packages/aux-files/findclass.php: New file.
* Makefile.am: Add them.
* doc/guix.texi (Build Systems): Document it.
---
Makefile.am | 3 +
doc/guix.texi | 16 +-
gnu/packages/aux-files/findclass.php | 125 ++++++++++++++
guix/build-system/composer.scm | 162 ++++++++++++++++++
guix/build/composer-build-system.scm | 247 +++++++++++++++++++++++++++
tests/composer.scm | 36 ++--
6 files changed, 568 insertions(+), 21 deletions(-)
create mode 100644 gnu/packages/aux-files/findclass.php
create mode 100644 guix/build-system/composer.scm
create mode 100644 guix/build/composer-build-system.scm

Toggle diff (480 lines)
diff --git a/Makefile.am b/Makefile.am
index 3fec98f064..47d1cb19ed 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -149,6 +149,7 @@ MODULES = \
guix/build-system/chicken.scm \
guix/build-system/clojure.scm \
guix/build-system/cmake.scm \
+ guix/build-system/composer.scm \
guix/build-system/dub.scm \
guix/build-system/dune.scm \
guix/build-system/elm.scm \
@@ -206,6 +207,7 @@ MODULES = \
guix/build/cargo-utils.scm \
guix/build/chicken-build-system.scm \
guix/build/cmake-build-system.scm \
+ guix/build/composer-build-system.scm \
guix/build/dub-build-system.scm \
guix/build/dune-build-system.scm \
guix/build/elm-build-system.scm \
@@ -411,6 +413,7 @@ dist_noinst_DATA = \
AUX_FILES = \
gnu/packages/aux-files/chromium/master-preferences.json \
gnu/packages/aux-files/emacs/guix-emacs.el \
+ gnu/packages/aux-files/findclass.php \
gnu/packages/aux-files/guix.vim \
gnu/packages/aux-files/linux-libre/6.5-arm.conf \
gnu/packages/aux-files/linux-libre/6.5-arm64.conf \
diff --git a/doc/guix.texi b/doc/guix.texi
index 0e64654715..6a1c0aeaa5 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -9554,6 +9554,20 @@ debugging information''), which roughly means that code is compiled with
@code{-O2 -g}, as is the case for Autoconf-based packages by default.
@end defvar
+@defvar {Scheme Variable} composer-build-system
+This variable is exported by @code{(guix build-system composer)}. It
+implements the build procedure for packages using
+@url{https://getcomposer.org/, Composer}, the PHP package manager.
+
+It automatically adds the @code{php} package to the set of inputs. Which
+package is used can be specified with the @code{#:php} parameter.
+
+The @code{#:test-target} parameter is used to control which script is run
+for the tests. By default, the @code{test} script is run if it exists. If
+the script does not exist, the build system will run @code{phpunit} from the
+source directory, assuming there is a @file{phpunit.xml} file.
+@end defvar
+
@defvar dune-build-system
This variable is exported by @code{(guix build-system dune)}. It
supports builds of packages using @uref{https://dune.build/, Dune}, a build
@@ -14550,7 +14564,7 @@ in Guix.
@item composer
@cindex Composer
@cindex PHP
-Import metadat from the @uref{https://getcomposer.org/, Composer} package
+Import metadata from the @uref{https://getcomposer.org/, Composer} package
archive used by the PHP community, as in this example:
@example
diff --git a/gnu/packages/aux-files/findclass.php b/gnu/packages/aux-files/findclass.php
new file mode 100644
index 0000000000..d0b250c8e1
--- /dev/null
+++ b/gnu/packages/aux-files/findclass.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * The content of this file is copied from composer's src/Composer/Autoload/ClassMapGenerator.php
+ * the findClasses method was extracted, to prevent using any dependency.
+ *
+ * Composer (and thus this file) is distributed under the expat license, and
+ * ClassMapGenerator.php also contains this notice:
+ *
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * This file is copied from the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * To the extent to wich it makes sense, as the author of the extract:
+ * Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
+ */
+
+/**
+ * Extract the classes in the given file
+ *
+ * @param string $path The file to check
+ * @throws \RuntimeException
+ * @return array The found classes
+ */
+function findClasses($path)
+{
+ $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
+ if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
+ $extraTypes .= '|enum';
+ }
+ // Use @ here instead of Silencer to actively suppress 'unhelpful' output
+ // @link https://github.com/composer/composer/pull/4886
+ $contents = @php_strip_whitespace($path);
+ if (!$contents) {
+ if (!file_exists($path)) {
+ $message = 'File at "%s" does not exist, check your classmap definitions';
+ } elseif (!is_readable($path)) {
+ $message = 'File at "%s" is not readable, check its permissions';
+ } elseif ('' === trim(file_get_contents($path))) {
+ // The input file was really empty and thus contains no classes
+ return array();
+ } else {
+ $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
+ }
+ $error = error_get_last();
+ if (isset($error['message'])) {
+ $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
+ }
+ throw new \RuntimeException(sprintf($message, $path));
+ }
+ // return early if there is no chance of matching anything in this file
+ if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
+ return array();
+ }
+ // strip heredocs/nowdocs
+ $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
+ // strip strings
+ $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
+ // strip leading non-php code if needed
+ if (substr($contents, 0, 2) !== '<?') {
+ $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
+ if ($replacements === 0) {
+ return array();
+ }
+ }
+ // strip non-php blocks in the file
+ $contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
+ // strip trailing non-php code if needed
+ $pos = strrpos($contents, '?>');
+ if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
+ $contents = substr($contents, 0, $pos);
+ }
+ // strip comments if short open tags are in the file
+ if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
+ $contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
+ }
+ preg_match_all('{
+ (?:
+ \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
+ | \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;]
+ )
+ }ix', $contents, $matches);
+ $classes = array();
+ $namespace = '';
+ for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
+ if (!empty($matches['ns'][$i])) {
+ $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
+ } else {
+ $name = $matches['name'][$i];
+ // skip anon classes extending/implementing
+ if ($name === 'extends' || $name === 'implements') {
+ continue;
+ }
+ if ($name[0] === ':') {
+ // This is an XHP class, https://github.com/facebook/xhp
+ $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
+ } elseif ($matches['type'][$i] === 'enum') {
+ // In Hack, something like:
+ // enum Foo: int { HERP = '123'; }
+ // The regex above captures the colon, which isn't part of
+ // the class name.
+ $name = rtrim($name, ':');
+ }
+ $classes[] = ltrim($namespace . $name, '\\');
+ }
+ }
+ return $classes;
+}
+
+$options = getopt('i:f:', []);
+$file = $options["f"];
+$input = $options["i"];
+
+$classes = findClasses($file);
+foreach($classes as $class) {
+ echo '$classmap[\''.$class.'\'] = \''.$input.'/'.$file.'\';';
+ echo "\n";
+}
diff --git a/guix/build-system/composer.scm b/guix/build-system/composer.scm
new file mode 100644
index 0000000000..8bf99ff9c5
--- /dev/null
+++ b/guix/build-system/composer.scm
@@ -0,0 +1,162 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+(define-module (guix build-system composer)
+ #:use-module (guix store)
+ #:use-module (guix utils)
+ #:use-module (guix derivations)
+ #:use-module (guix search-paths)
+ #:use-module (guix build-system)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix gexp)
+ #:use-module (guix packages)
+ #:use-module (gnu packages)
+ #:use-module (ice-9 match)
+ #:use-module (srfi srfi-1)
+ #:export (%composer-build-system-modules
+ lower
+ composer-build
+ composer-build-system))
+
+;; Commentary:
+;;
+;; Standard build procedure for PHP packages using Composer. This is implemented
+;; as an extension of `gnu-build-system'.
+;;
+;; Code:
+
+(define (default-php)
+ "Return the default PHP package."
+
+ ;; Do not use `@' to avoid introducing circular dependencies.
+ (let ((module (resolve-interface '(gnu packages php))))
+ (module-ref module 'php)))
+
+(define (default-findclass)
+ "Return the default findclass script."
+ (search-auxiliary-file "findclass.php"))
+
+(define (default-composer-classloader)
+ "Return the default composer-classloader package."
+
+ ;; Do not use `@' to avoid introducing circular dependencies.
+ (let ((module (resolve-interface '(gnu packages php-xyz))))
+ (module-ref module 'composer-classloader)))
+
+(define %composer-build-system-modules
+ ;; Build-side modules imported by default.
+ `((guix build composer-build-system)
+ (guix build union)
+ (json)
+ (json builder)
+ (json parser)
+ (json record)
+ ,@%gnu-build-system-modules))
+
+(define* (lower name
+ #:key source inputs native-inputs outputs system target
+ (php (default-php))
+ (composer-classloader (default-composer-classloader))
+ (findclass (default-findclass))
+ #:allow-other-keys
+ #:rest arguments)
+ "Return a bag for NAME."
+ (define private-keywords
+ '(#:target #:php #:composer-classloader #:findclass #:inputs #:native-inputs))
+
+ (and (not target) ;XXX: no cross-compilation
+ (bag
+ (name name)
+ (system system)
+ (host-inputs `(,@(if source
+ `(("source" ,source))
+ '())
+ ,@inputs
+
+ ;; Keep the standard inputs of 'gnu-build-system'.
+ ,@(standard-packages)))
+ (build-inputs `(("php" ,php)
+ ("findclass.php" ,findclass)
+ ("composer-classloader" ,composer-classloader)
+ ,@native-inputs))
+ (outputs outputs)
+ (build composer-build)
+ (arguments (strip-keyword-arguments private-keywords arguments)))))
+
+(define* (composer-build name inputs
+ #:key
+ guile source
+ (outputs '("out"))
+ (configure-flags ''())
+ (search-paths '())
+ (out-of-source? #t)
+ (composer-file "composer.json")
+ (tests? #t)
+ (test-target "test")
+ (install-target "install")
+ (validate-runpath? #t)
+ (patch-shebangs? #t)
+ (strip-binaries? #t)
+ (strip-flags #~'("--strip-debug"))
+ (strip-directories #~'("lib" "lib64" "libexec"
+ "bin" "sbin"))
+ (phases '(@ (guix build composer-build-system)
+ %standard-phases))
+ (system (%current-system))
+ (imported-modules %composer-build-system-modules)
+ (modules '((guix build composer-build-system)
+ (guix build utils))))
+ "Build SOURCE using PHP, and with INPUTS. This assumes that SOURCE provides
+a 'composer.json' file as its build system."
+ (define builder
+ (with-imported-modules imported-modules
+ #~(begin
+ (use-modules #$@(sexp->gexp modules))
+
+ #$(with-build-variables inputs outputs
+ #~(composer-build
+ #:source #$source
+ #:system #$system
+ #:outputs %outputs
+ #:inputs %build-inputs
+ #:search-paths '#$(map search-path-specification->sexp
+ search-paths)
+ #:phases #$phases
+ #:out-of-source? #$out-of-source?
+ #:composer-file #$composer-file
+ #:tests? #$tests?
+ #:test-target #$test-target
+ #:install-target #$install-target
+ #:validate-runpath? #$validate-runpath?
+ #:patch-shebangs? #$patch-shebangs?
+ #:strip-binaries? #$strip-binaries?
+ #:strip-flags #$strip-flags
+ #:strip-directories #$strip-directories)))))
+
+ (gexp->derivation name builder
+ #:system system
+ #:target #f
+ #:graft? #f
+ #:guile-for-build guile))
+
+(define composer-build-system
+ (build-system
+ (name 'composer)
+ (description "The standard Composer build system")
+ (lower lower)))
+
+;;; composer.scm ends here
diff --git a/guix/build/composer-build-system.scm b/guix/build/composer-build-system.scm
new file mode 100644
index 0000000000..bcbae27021
--- /dev/null
+++ b/guix/build/composer-build-system.scm
@@ -0,0 +1,247 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;; Copyright © 2023 Nicolas Graves <ngraves@ngraves.fr>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix build composer-build-system)
+ #:use-module ((guix build gnu-build-system) #:prefix gnu:)
+ #:use-module (guix build utils)
+ #:use-module (ice-9 match)
+ #:use-module (json)
+ #:use-module (srfi srfi-26)
+ #:export (%standard-phases
+ composer-build))
+
+;; Commentary:
+;;
+;; Builder-side code of the standard composer build procedure.
+;;
+;; Code:
+
+(define (json->require dict)
+ (if dict
+ (let loop ((result '()) (require dict))
+ (match require
+ (() result)
+ ((((? (cut string-contains <> "/") name) . _)
+ require ...)
+ (loop (cons name result) require))
+ ((_ require ...) (loop result require))
+ (_ result)))
+ '()))
+
+(define (if-specified-to-list fn)
+ (match-lambda
+ ((? unspecified?) '())
+ (arg (fn arg))
+ (_ '())))
+
+(define-json-mapping <composer-autoload> make-composer-autoload
+ composer-autoload?
+ json->composer-autoload
+ (psr-4 composer-autoload-psr-4 "psr-4" (if-specified-to-list identity))
+ (classmap composer-autoload-classmap "classmap"
+ (if-specified-to-list vector->list)))
+
+(define-json-mapping <composer-package> make-composer-package composer-package?
+ json->composer-package
+ (name composer-package-name)
+ (autoload composer-package-autoload "autoload"
+ (if-specified-to-list json->composer-autoload))
+ (autoload-dev composer-package-autoload-dev "autoload-dev"
+ (if-specified-to-list json->composer-autoload))
+ (require composer-package-require "require" json->require)
+ (dev-require composer-package-dev-require "require-dev" json->require)
+ (scripts composer-package-scripts "scripts"
+ (if-specified-to-list identity))
+ (binaries composer-package-binaries "bin"
+ (if-specified-to-list vector->list)))
+
+(define* (read-package-data #:key (filename "composer.json"))
+ (call-with-input-file filename
+ (lambda (port)
+ (json->composer-package (json->scm port)))))
+
+(define* (check #:key composer-file inputs outputs tests? test-target #:allow-other-keys)
+ "Test the given package."
+ (when tests?
+ (mkdir-p "vendor")
+ (create-autoload (string-append (getcwd) "/vendor") composer-file
+ (append inputs outputs) #:dev-dependencies? #t)
+ (let* ((package-data (read-package-data #:filename composer-file))
+ (scripts (composer-package-scripts package-data))
+ (test-script (assoc-ref scripts test-target))
+ (dependencies (composer-package-require package-data))
+ (dependencies-dev (composer-package-dev-require package-data))
+ (name (composer-package-name package-data)))
+ (for-each
+ (match-lambda
+ ((_ . input)
+ (let ((bin (find-php-bin input)))
+ (when bin
+ (copy-recursively bin "vendor/bin")))))
+ inputs)
+ (match test-script
+ ((? string? command)
+ (unless (zero? (system command))
+ (throw 'failed-command command)))
+ (('@ (? string? command) ...)
+ (for-each
+ (lambda (c)
+ (unless (zero? (system c))
+ (throw 'failed-command c)))
+ command))
+ (#f (invoke "vendor/bin/phpunit"))))))
+
+(define (find-php-bin input)
+ (let* ((web-dir (string-append input "/share/web"))
+ (vendors (if (file-exists? web-dir)
+ (find-
This message was truncated. Download the full message here.
N
N
Nicolas Graves wrote on 2 Nov 2023 16:04
[PATCH 5/9] guix: import: composer: Fix json->require.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151523.30581-6-ngraves@ngraves.fr
---
guix/import/composer.scm | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

Toggle diff (16 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index 177dc63092..3acbbecf82 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -88,7 +88,8 @@ (define (json->require dict)
((((? (cut string-contains <> "/") name) . _)
require ...)
(loop (cons name result) require))
- ((_ require ...) (loop result require))))
+ ((_ require ...) (loop result require))
+ (_ result)))
'()))
(define-json-mapping <composer-source> make-composer-source composer-source?
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:04
[PATCH 4/9] guix: import: composer: Use memoization.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151523.30581-5-ngraves@ngraves.fr
---
guix/import/composer.scm | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)

Toggle diff (51 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index c152f402bb..177dc63092 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -27,6 +27,7 @@ (define-module (guix import composer)
#:use-module (guix import json)
#:use-module (guix import utils)
#:use-module ((guix licenses) #:prefix license:)
+ #:use-module (guix memoization)
#:use-module (guix packages)
#:use-module (guix serialization)
#:use-module (guix upstream)
@@ -197,16 +198,18 @@ (define (make-php-sexp composer-package)
((license) license)
(_ license)))))))))
-(define* (composer->guix-package package-name #:optional version)
- "Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
+(define composer->guix-package
+ (memoize
+ (lambda* (package-name #:key version #:allow-other-keys)
+ "Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
`package' s-expression corresponding to that package, or #f on failure."
- (let ((package (composer-fetch package-name version)))
- (and package
- (let* ((package (json->composer-package package))
- (dependencies-names (composer-package-require package))
- (dev-dependencies-names (composer-package-dev-require package)))
- (values (make-php-sexp package)
- (append dependencies-names dev-dependencies-names))))))
+ (let ((package (composer-fetch package-name version)))
+ (and package
+ (let* ((package (json->composer-package package))
+ (dependencies-names (composer-package-require package))
+ (dev-dependencies-names (composer-package-dev-require package)))
+ (values (make-php-sexp package)
+ (append dependencies-names dev-dependencies-names))))))))
(define (guix-name->composer-name name)
"Given a guix package name, return the name of the package in Packagist."
@@ -265,6 +268,7 @@ (define %composer-updater
(import latest-release)))
(define* (composer-recursive-import package-name #:optional version)
- (recursive-import package-name '()
+ (recursive-import package-name
+ #:version version
#:repo->guix-package composer->guix-package
#:guix-name php-package-name))
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:04
[PATCH 6/9] guix: import: composer: More robust string->license.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151523.30581-7-ngraves@ngraves.fr
* guix/import/composer.scm (string->license): Use spdx-string->license. Fall
back to unknown-license!.
---
guix/import/composer.scm | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)

Toggle diff (55 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index 3acbbecf82..49f16caedf 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -109,7 +109,10 @@ (define-json-mapping <composer-package> make-composer-package composer-package?
(dev-require composer-package-dev-require "require-dev" json->require)
(license composer-package-license "license"
(lambda (vector)
- (map string->license (vector->list vector)))))
+ (let ((l (map string->license (vector->list vector))))
+ (if (eq? (length l) 1)
+ (car l)
+ `(list ,@l))))))
(define* (composer-fetch name #:optional version)
"Return an alist representation of the Composer metadata for the package NAME,
@@ -194,10 +197,8 @@ (define (make-php-sexp composer-package)
(synopsis "")
(description ,(composer-package-description composer-package))
(home-page ,(composer-package-homepage composer-package))
- (license ,(match (composer-package-license composer-package)
- (() #f)
- ((license) license)
- (_ license)))))))))
+ (license ,(or (composer-package-license composer-package)
+ 'unknown-license!))))))))
(define composer->guix-package
(memoize
@@ -234,14 +235,15 @@ (define (guix-package->composer-name package)
(define (string->license str)
"Convert the string STR into a license object."
- (match str
- ("GNU LGPL" 'license:lgpl2.0)
- ("GPL" 'license:gpl3)
- ((or "BSD" "BSD License" "BSD-3-Clause") 'license:bsd-3)
- ((or "MIT" "MIT license" "Expat license") 'license:expat)
- ("Public domain" 'license:public-domain)
- ((or "Apache License, Version 2.0" "Apache 2.0") 'license:asl2.0)
- (_ #f)))
+ (or (spdx-string->license str)
+ (match str
+ ("GNU LGPL" 'license:lgpl2.0)
+ ("GPL" 'license:gpl3)
+ ((or "BSD" "BSD License") 'license:bsd-3)
+ ((or "MIT" "MIT license" "Expat license") 'license:expat)
+ ("Public domain" 'license:public-domain)
+ ((or "Apache License, Version 2.0" "Apache 2.0") 'license:asl2.0)
+ (_ 'unknown-license!))))
(define (php-package? package)
"Return true if PACKAGE is a PHP package from Packagist."
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:04
[PATCH 7/9] guix: import: composer: Modern inputs formatting.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151523.30581-8-ngraves@ngraves.fr
* guix/import/composer.scm (make-php-sexp): Update inputs formatting.
---
guix/import/composer.scm | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)

Toggle diff (30 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index 49f16caedf..89c8ea9113 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -179,21 +179,11 @@ (define (make-php-sexp composer-package)
,@(if (null? dependencies)
'()
`((inputs
- (,'quasiquote
- ,(map (lambda (name)
- `(,name
- (,'unquote
- ,(string->symbol name))))
- dependencies)))))
+ (list ,@(map string->symbol dependencies)))))
,@(if (null? dev-dependencies)
'()
`((native-inputs
- (,'quasiquote
- ,(map (lambda (name)
- `(,name
- (,'unquote
- ,(string->symbol name))))
- dev-dependencies)))))
+ (list ,@(map string->symbol dev-dependencies)))))
(synopsis "")
(description ,(composer-package-description composer-package))
(home-page ,(composer-package-homepage composer-package))
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:04
[PATCH 8/9] guix: import: composer: Full rewrite composer-fetch.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151523.30581-9-ngraves@ngraves.fr
Change-Id: I1c01c242cefe0bc4cfc9bd9a5717d10a61dd575e
---
guix/import/composer.scm | 154 +++++++++++++++++++--------------------
1 file changed, 77 insertions(+), 77 deletions(-)

Toggle diff (205 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index 89c8ea9113..2cc8861bdd 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -19,7 +19,7 @@
(define-module (guix import composer)
#:use-module (ice-9 match)
#:use-module (json)
- #:use-module (gcrypt hash)
+ #:use-module (guix hash)
#:use-module (guix base32)
#:use-module (guix build git)
#:use-module (guix build utils)
@@ -44,27 +44,6 @@ (define-module (guix import composer)
(define %composer-base-url
(make-parameter "https://repo.packagist.org"))
-;; XXX adapted from (guix scripts hash)
-(define (file-hash file select? recursive?)
- ;; Compute the hash of FILE.
- (if recursive?
- (let-values (((port get-hash) (open-sha256-port)))
- (write-file file port #:select? select?)
- (force-output port)
- (get-hash))
- (call-with-input-file file port-sha256)))
-
-;; XXX taken from (guix scripts hash)
-(define (vcs-file? file stat)
- (case (stat:type stat)
- ((directory)
- (member (basename file) '(".bzr" ".git" ".hg" ".svn" "CVS")))
- ((regular)
- ;; Git sub-modules have a '.git' file that is a regular text file.
- (string=? (basename file) ".git"))
- (else
- #f)))
-
(define (fix-version version)
"Return a fixed version from a version string. For instance, v10.1 -> 10.1"
(cond
@@ -114,22 +93,36 @@ (define-json-mapping <composer-package> make-composer-package composer-package?
(car l)
`(list ,@l))))))
-(define* (composer-fetch name #:optional version)
- "Return an alist representation of the Composer metadata for the package NAME,
-or #f on failure."
- (let ((package (json-fetch
- (string-append (%composer-base-url) "/p/" name ".json"))))
- (if package
- (let* ((packages (assoc-ref package "packages"))
- (package (or (assoc-ref packages name) package))
- (versions (filter
- (lambda (version)
- (and (not (string-contains version "dev"))
- (not (string-contains version "beta"))))
- (map car package)))
- (version (or (if (null? version) #f version)
- (latest-version versions))))
- (assoc-ref package version))
+(define (valid-version? v)
+ (let ((d (string-downcase v)))
+ (and (not (string-contains d "dev"))
+ (not (string-contains d "beta"))
+ (not (string-contains d "rc")))))
+
+(define* (composer-fetch name #:key (version #f))
+ "Return a composer-package representation of the Composer metadata for the
+package NAME with optional VERSION, or #f on failure."
+ (let* ((url (string-append (%composer-base-url) "/p/" name ".json"))
+ (packages (and=> (json-fetch url)
+ (lambda (pkg)
+ (let ((pkgs (assoc-ref pkg "packages")))
+ (or (assoc-ref pkgs name) pkg))))))
+ (if packages
+ (json->composer-package
+ (if version
+ (assoc-ref packages version)
+ (cdr
+ (reduce
+ (lambda (new cur-max)
+ (match new
+ (((? valid-version? version) . tail)
+ (if (version>? (fix-version version)
+ (fix-version (car cur-max)))
+ (cons* version tail)
+ cur-max))
+ (_ cur-max)))
+ (cons* "0.0.0" #f)
+ packages))))
#f)))
(define (php-package-name name)
@@ -158,47 +151,55 @@ (define (make-php-sexp composer-package)
(composer-source-reference source)
temp))
(url-fetch (composer-source-url source) temp))
- `(package
- (name ,(composer-package-name composer-package))
- (version ,(composer-package-version composer-package))
- (source (origin
- ,@(if git?
- `((method git-fetch)
- (uri (git-reference
- (url ,(composer-source-url source))
- (commit ,(composer-source-reference source))))
- (file-name (git-file-name name version))
- (sha256
- (base32
- ,(bytevector->nix-base32-string
- (file-hash temp (negate vcs-file?) #t)))))
- `((method url-fetch)
- (uri ,(composer-source-url source))
- (sha256 (base32 ,(guix-hash-url temp)))))))
- (build-system composer-build-system)
- ,@(if (null? dependencies)
- '()
- `((inputs
- (list ,@(map string->symbol dependencies)))))
- ,@(if (null? dev-dependencies)
- '()
- `((native-inputs
- (list ,@(map string->symbol dev-dependencies)))))
- (synopsis "")
- (description ,(composer-package-description composer-package))
- (home-page ,(composer-package-homepage composer-package))
- (license ,(or (composer-package-license composer-package)
- 'unknown-license!))))))))
+ `(define-public ,(string->symbol
+ (composer-package-name composer-package))
+ (package
+ (name ,(composer-package-name composer-package))
+ (version ,(composer-package-version composer-package))
+ (source
+ (origin
+ ,@(if git?
+ `((method git-fetch)
+ (uri (git-reference
+ (url ,(if (string-suffix?
+ ".git"
+ (composer-source-url source))
+ (string-drop-right
+ (composer-source-url source)
+ (string-length ".git"))
+ (composer-source-url source)))
+ (commit ,(composer-source-reference source))))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ ,(bytevector->nix-base32-string
+ (file-hash* temp)))))
+ `((method url-fetch)
+ (uri ,(composer-source-url source))
+ (sha256 (base32 ,(guix-hash-url temp)))))))
+ (build-system composer-build-system)
+ ,@(if (null? dependencies)
+ '()
+ `((inputs
+ (list ,@(map string->symbol dependencies)))))
+ ,@(if (null? dev-dependencies)
+ '()
+ `((native-inputs
+ (list ,@(map string->symbol dev-dependencies)))))
+ (synopsis "")
+ (description ,(composer-package-description composer-package))
+ (home-page ,(composer-package-homepage composer-package))
+ (license ,(or (composer-package-license composer-package)
+ 'unknown-license!)))))))))
(define composer->guix-package
(memoize
- (lambda* (package-name #:key version #:allow-other-keys)
+ (lambda* (package-name #:key (version #f) #:allow-other-keys)
"Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
`package' s-expression corresponding to that package, or #f on failure."
- (let ((package (composer-fetch package-name version)))
+ (let ((package (composer-fetch package-name #:version version)))
(and package
- (let* ((package (json->composer-package package))
- (dependencies-names (composer-package-require package))
+ (let* ((dependencies-names (composer-package-require package))
(dev-dependencies-names (composer-package-dev-require package)))
(values (make-php-sexp package)
(append dependencies-names dev-dependencies-names))))))))
@@ -238,14 +239,13 @@ (define (string->license str)
(define (php-package? package)
"Return true if PACKAGE is a PHP package from Packagist."
(and
- (eq? (build-system-name (package-build-system package)) 'composer)
- (string-prefix? "php-" (package-name package))))
+ (eq? (package-build-system package) composer-build-system)
+ (string-prefix? "php-" (package-name package))))
(define (latest-release package)
"Return an <upstream-source> for the latest release of PACKAGE."
(let* ((php-name (guix-package->composer-name package))
- (metadata (composer-fetch php-name))
- (package (json->composer-package metadata))
+ (package (composer-fetch php-name))
(version (composer-package-version package))
(url (composer-source-url (composer-package-source package))))
(upstream-source
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:04
[PATCH 9/9] gnu: composer-build-system: Full check phase rewrite.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151523.30581-10-ngraves@ngraves.fr
Change-Id: I824b27b925cd718ee83ef6b2ee4a8a1e69455de6
---
guix/build-system/composer.scm | 2 +
guix/build/composer-build-system.scm | 239 ++++++++++++++++-----------
2 files changed, 148 insertions(+), 93 deletions(-)

Toggle diff (310 lines)
diff --git a/guix/build-system/composer.scm b/guix/build-system/composer.scm
index 8bf99ff9c5..7d2ad2b398 100644
--- a/guix/build-system/composer.scm
+++ b/guix/build-system/composer.scm
@@ -107,6 +107,7 @@ (define* (composer-build name inputs
(composer-file "composer.json")
(tests? #t)
(test-target "test")
+ (test-flags ''())
(install-target "install")
(validate-runpath? #t)
(patch-shebangs? #t)
@@ -140,6 +141,7 @@ (define builder
#:composer-file #$composer-file
#:tests? #$tests?
#:test-target #$test-target
+ #:test-flags #$test-flags
#:install-target #$install-target
#:validate-runpath? #$validate-runpath?
#:patch-shebangs? #$patch-shebangs?
diff --git a/guix/build/composer-build-system.scm b/guix/build/composer-build-system.scm
index bcbae27021..6f05801ad1 100644
--- a/guix/build/composer-build-system.scm
+++ b/guix/build/composer-build-system.scm
@@ -53,9 +53,22 @@ (define (if-specified-to-list fn)
(define-json-mapping <composer-autoload> make-composer-autoload
composer-autoload?
json->composer-autoload
- (psr-4 composer-autoload-psr-4 "psr-4" (if-specified-to-list identity))
+ (psr-4 composer-autoload-psr-4 "psr-4"
+ (match-lambda
+ ((? unspecified?) '())
+ ((? (lambda (al)
+ (and (list? al) (pair? (car al)) (vector? (cdar al)))) al)
+ (append-map
+ (lambda (vect-el)
+ (list (cons (caar al) vect-el)))
+ (vector->list (cdar al))))
+ ((? list? l) l)
+ (_ '())))
+ (psr-0 composer-autoload-psr-0 "psr-0" (if-specified-to-list identity))
(classmap composer-autoload-classmap "classmap"
- (if-specified-to-list vector->list)))
+ (if-specified-to-list vector->list))
+ (files composer-autoload-files "files"
+ (if-specified-to-list vector->list)))
(define-json-mapping <composer-package> make-composer-package composer-package?
json->composer-package
@@ -76,65 +89,57 @@ (define* (read-package-data #:key (filename "composer.json"))
(lambda (port)
(json->composer-package (json->scm port)))))
-(define* (check #:key composer-file inputs outputs tests? test-target #:allow-other-keys)
- "Test the given package."
+(define* (create-test-autoload #:key composer-file inputs outputs tests?
+ #:allow-other-keys)
+ "Create the autoload.php file for tests. This is a standalone phase so that
+the autoload.php file can be edited before the check phase."
(when tests?
(mkdir-p "vendor")
(create-autoload (string-append (getcwd) "/vendor") composer-file
- (append inputs outputs) #:dev-dependencies? #t)
- (let* ((package-data (read-package-data #:filename composer-file))
- (scripts (composer-package-scripts package-data))
- (test-script (assoc-ref scripts test-target))
- (dependencies (composer-package-require package-data))
- (dependencies-dev (composer-package-dev-require package-data))
- (name (composer-package-name package-data)))
- (for-each
- (match-lambda
- ((_ . input)
- (let ((bin (find-php-bin input)))
- (when bin
- (copy-recursively bin "vendor/bin")))))
- inputs)
- (match test-script
- ((? string? command)
- (unless (zero? (system command))
- (throw 'failed-command command)))
- (('@ (? string? command) ...)
- (for-each
- (lambda (c)
- (unless (zero? (system c))
- (throw 'failed-command c)))
- command))
- (#f (invoke "vendor/bin/phpunit"))))))
+ inputs #:dev-dependencies? #t)))
-(define (find-php-bin input)
- (let* ((web-dir (string-append input "/share/web"))
- (vendors (if (file-exists? web-dir)
- (find-files web-dir "^vendor$" #:directories? #t)
- #f)))
- (match vendors
- ((vendor)
- (let ((bin (string-append vendor "/bin")))
- (and (file-exists? bin) bin)))
- (_ #f))))
+(define (find-bin script inputs)
+ (search-input-file inputs
+ (string-append
+ "bin/"
+ (string-drop script (string-length "vendor/bin/")))))
-(define (find-php-dep inputs dependency)
- (let loop ((inputs inputs))
- (match inputs
- (() (throw 'unsatisfied-dependency "Unsatisfied dependency: required "
- dependency))
- (((_ . input) inputs ...)
- (let ((autoload (string-append input "/share/web/" dependency
- "/vendor/autoload_conf.php")))
- (if (file-exists? autoload)
- autoload
- (loop inputs))))
- ((input inputs ...)
- (let ((autoload (string-append input "/share/web/" dependency
- "/vendor/autoload_conf.php")))
- (if (file-exists? autoload)
- autoload
- (loop inputs)))))))
+(define* (check #:key composer-file inputs
+ tests? test-target test-flags #:allow-other-keys)
+ "Test the given package.
+Please note that none of the PHP packages at the time of the rewrite of the
+build-system did use the test-script field. This means that the @code{match
+test-script} part is not tested on a real example and relies on the original
+implementation."
+ (if tests?
+ (let* ((package-data (read-package-data #:filename composer-file))
+ (scripts (composer-package-scripts package-data))
+ (test-script (assoc-ref scripts test-target)))
+ (match test-script
+ ((? string? bin)
+ (let ((command (find-bin bin inputs)))
+ (unless (zero? (apply system command test-flags))
+ (throw 'failed-command command))))
+ (('@ (? string? bins) ...)
+ (for-each
+ (lambda (c)
+ (let ((command (find-bin bin inputs)))
+ (unless (zero? (apply system command test-flags))
+ (throw 'failed-command command))))
+ bins))
+ (_ (if (file-exists? "phpunit.xml.dist")
+ (apply invoke
+ (with-exception-handler
+ (lambda (exn)
+ (if (search-error? exn)
+ (error "\
+Missing php-phpunit-phpunit native input.~%")
+ (raise exn)))
+ (lambda ()
+ (search-input-file (or inputs '()) "bin/phpunit")))
+ test-flags))
+ (format #t "No test suite found.~%"))))
+ (format #t "Test suite not run.~%")))
(define* (create-autoload vendor composer-file inputs #:key dev-dependencies?)
"creates an autoload.php file that sets up the class locations for this package,
@@ -144,15 +149,14 @@ (define* (create-autoload vendor composer-file inputs #:key dev-dependencies?)
(display (string-append
"<?php
// autoload.php @generated by Guix
-$map = $psr4map = $classmap = array();
-require_once '" vendor "/autoload_conf.php'
-require_once '" (assoc-ref inputs "composer-classloader") "/share/web/composer/ClassLoader.php'
+$psr4map = $classmap = array();
+require_once '" vendor "/autoload_conf.php';
+require_once '" (assoc-ref inputs "composer-classloader") "/share/web/composer/ClassLoader.php';
$loader = new \\Composer\\Autoload\\ClassLoader();
-foreach ($map as $namespace => $path) {
- $loader->set($namespace, $path);
-}
-foreach ($psr4map as $namespace => $path) {
- $loader->setPsr4($namespace, $path);
+foreach ($psr4map as $namespace => $paths) {
+ foreach ($paths as $path) {
+ $loader->addPsr4($namespace, $path);
+ }
}
$loader->addClassMap($classmap);
$loader->register();
@@ -170,37 +174,85 @@ (define* (create-autoload vendor composer-file inputs #:key dev-dependencies?)
(format #t "// autoload_conf.php @generated by Guix~%")
(force-output)
(for-each
- (lambda (psr4)
- (match psr4
- ((key . value)
- (format #t "$psr4map['~a'] = '~a/../~a';~%"
- (string-join (string-split key #\\) "\\\\")
- vendor value))))
+ (match-lambda
+ ((key . value)
+ (let ((vals (if (list? value)
+ (reverse value)
+ (list value))))
+ (apply
+ format
+ #t
+ (string-append
+ "$psr4map['~a'][] = ["
+ (string-join
+ (make-list (length vals) "'~a/../~a'") ",")
+ "];~%")
+ (cons* (string-join (string-split key #\\) "\\\\")
+ (append-map (lambda (v) (list vendor v)) vals)))))
+ (_ (format #t "")))
+ (merge-duplicates
(append
- (composer-autoload-psr-4 autoload)
- (if dev-dependencies?
- (composer-autoload-psr-4 autoload-dev)
- '())))
+ (composer-autoload-psr-4 autoload)
+ (if (and dev-dependencies? (not (null? autoload-dev)))
+ (composer-autoload-psr-4 autoload-dev)
+ '()))
+ '()))
(for-each
- (lambda (classmap)
- (for-each
- (lambda (file)
- (invoke "php" (assoc-ref inputs "findclass.php")
- "-i" (string-append vendor "/..") "-f" file))
- (find-files classmap ".(php|hh|inc)$")))
- (append
- (composer-autoload-classmap autoload)
- (if dev-dependencies?
- (composer-autoload-classmap autoload-dev)
- '())))
+ (lambda (psr0)
+ (match psr0
+ ((key . value)
+ (format #t "$psr4map['~a'][] = ['~a/../~a/~a'];~%"
+ (string-join (string-split key #\\) "\\\\")
+ vendor
+ value
+ (string-join (string-split key #\\) "/")))
+ (_ (format #t ""))))
+ (append
+ (composer-autoload-psr-0 autoload)
+ (if (and dev-dependencies? (not (null? autoload-dev)))
+ (composer-autoload-psr-0 autoload-dev)
+ '())))
(for-each
- (lambda (dep)
- (format #t "require_once '~a';~%" (find-php-dep inputs dep)))
- (append
- dependencies
- (if dev-dependencies?
- dependencies-dev
- '())))))))
+ (lambda (classmap)
+ (for-each
+ (lambda (file)
+ (invoke "php" (assoc-ref inputs "findclass.php")
+ "-i" (string-append vendor "/..") "-f" file))
+ (find-files classmap ".(php|hh|inc)$")))
+ (append
+ (composer-autoload-classmap autoload)
+ (if (and dev-dependencies? (not (null? autoload-dev)))
+ (composer-autoload-classmap autoload-dev)
+ '())))
+ (for-each
+ (lambda (file)
+ (format #t "require_once '~a/../~a';~%" vendor file))
+ (append
+ (composer-autoload-files autoload)
+ (if (and dev-dependencies? (not (null? autoload-dev)))
+ (composer-autoload-files autoload-dev)
+ '())))
+ (for-each
+ (lambda (dep)
+ (format
+ #t "require_once '~a';~%"
+ (search-input-file
+ inputs
+ (string-append "/share/web/" dep "/vendor/autoload_conf.php"))))
+ dependencies)
+ ;; Also add native-inputs that are not necessarily given in the
+ ;; composer.json. This allows to simply add a package in tests by
+ ;; adding it in native-inputs, without the need to patch composer.json.
+ (for-each
+ (match-lambda
+ ((name . loc)
+ (match (find-files loc "autoload_conf\\.php$")
+ (() #t)
+ (((? string? conf) . ())
+ (format #t "require_once '~a';~%" conf))
+ (_ #t)))
+ (_ #t))
+ (or inputs '()))))))
(define* (install #:key inputs outputs composer-file #:allow-other-keys)
"Install the given package."
@@ -237,7 +289,8 @@ (define %standard-phases
(delete 'build)
(delete 'check)
(replace 'install install)
- (add-after 'install 'check check)))
+ (add-after 'install 'check check)
+ (add-after 'install 'create-test-autoload create-test-autoload)))
(define* (composer-build #:key inputs (phases %standard-phases)
#:allow-other-keys #:rest args)
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:16
[PATCH v5 0/9] Composer build-system
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151725.31362-1-ngraves@ngraves.fr
This is the result of my further rework of the composer import and
build-system. The `guix: import: composer` commits can be squashed
easily.

This is now tested on 94 php packages with all testing enabled except
for 3 packages. I will submit these packages as a whole in the
alphabetical order (the bootstrap order is not worth it IMO) in a new
guix issue.

Before accepting it, I also would like to propose a change of
names. If me make an analogy with python:
tool: pip <-> composer
package hub: pypi <-> packagist
build-system: python/pyproject <-> php

Since we only take about 90 lines of real composer code, I would
rather call the build-system php-build-system.
Same thing: instead of `guix import composer` we should rather call
`guix import packagist`.

If that's OK, I'll change it with the next (and hopefully last!)
version of this build system.

Nicolas Graves (9):
guix: import: Add composer importer.
gnu: Add composer-classloader.
guix: Add composer-build-system.
guix: import: composer: Use memoization.
guix: import: composer: Fix json->require.
guix: import: composer: More robust string->license.
guix: import: composer: Modern inputs formatting.
guix: import: composer: Full rewrite composer-fetch.
gnu: composer-build-system: Full check phase rewrite.

Makefile.am | 6 +
doc/guix.texi | 34 +++
gnu/local.mk | 1 +
gnu/packages/aux-files/findclass.php | 125 +++++++++++
gnu/packages/php-xyz.scm | 60 ++++++
guix/build-system/composer.scm | 164 +++++++++++++++
guix/build/composer-build-system.scm | 300 +++++++++++++++++++++++++++
guix/import/composer.scm | 267 ++++++++++++++++++++++++
guix/scripts/import.scm | 2 +-
guix/scripts/import/composer.scm | 107 ++++++++++
tests/composer.scm | 88 ++++++++
11 files changed, 1153 insertions(+), 1 deletion(-)
create mode 100644 gnu/packages/aux-files/findclass.php
create mode 100644 gnu/packages/php-xyz.scm
create mode 100644 guix/build-system/composer.scm
create mode 100644 guix/build/composer-build-system.scm
create mode 100644 guix/import/composer.scm
create mode 100644 guix/scripts/import/composer.scm
create mode 100644 tests/composer.scm

--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:16
[PATCH v5 1/9] guix: import: Add composer importer.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151725.31362-2-ngraves@ngraves.fr
* guix/import/composer.scm: New file.
* guix/scripts/import/composer.scm: New file.
* guix/tests/composer.scm: New file.
* Makefile.am: Add them.
* guix/scripts/import.scm: Add composer importer.
* doc/guix.texi (Invoking guix import): Mention it.
---
Makefile.am | 3 +
doc/guix.texi | 20 +++
guix/import/composer.scm | 270 +++++++++++++++++++++++++++++++
guix/scripts/import.scm | 2 +-
guix/scripts/import/composer.scm | 107 ++++++++++++
tests/composer.scm | 92 +++++++++++
6 files changed, 493 insertions(+), 1 deletion(-)
create mode 100644 guix/import/composer.scm
create mode 100644 guix/scripts/import/composer.scm
create mode 100644 tests/composer.scm

Toggle diff (507 lines)
diff --git a/Makefile.am b/Makefile.am
index 310a231259..3fec98f064 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -274,6 +274,7 @@ MODULES = \
guix/search-paths.scm \
guix/packages.scm \
guix/import/cabal.scm \
+ guix/import/composer.scm \
guix/import/cpan.scm \
guix/import/cran.scm \
guix/import/crate.scm \
@@ -332,6 +333,7 @@ MODULES = \
guix/scripts/home/import.scm \
guix/scripts/lint.scm \
guix/scripts/challenge.scm \
+ guix/scripts/import/composer.scm \
guix/scripts/import/crate.scm \
guix/scripts/import/cpan.scm \
guix/scripts/import/cran.scm \
@@ -504,6 +506,7 @@ SCM_TESTS = \
tests/challenge.scm \
tests/channels.scm \
tests/combinators.scm \
+ tests/composer.scm \
tests/containers.scm \
tests/cpan.scm \
tests/cpio.scm \
diff --git a/doc/guix.texi b/doc/guix.texi
index 8c5697589f..0e64654715 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -14539,6 +14539,26 @@ guix import hexpm cf@@0.3.0
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
+
+@item composer
+@cindex Composer
+@cindex PHP
+Import metadat from the @uref{https://getcomposer.org/, Composer} package
+archive used by the PHP community, as in this example:
+
+@example
+guix import composer phpunit/phpunit
+@end example
+
+Additional options include:
+
@table @code
@item --recursive
@itemx -r
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
new file mode 100644
index 0000000000..c152f402bb
--- /dev/null
+++ b/guix/import/composer.scm
@@ -0,0 +1,270 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix import composer)
+ #:use-module (ice-9 match)
+ #:use-module (json)
+ #:use-module (gcrypt hash)
+ #:use-module (guix base32)
+ #:use-module (guix build git)
+ #:use-module (guix build utils)
+ #:use-module (guix build-system)
+ #:use-module (guix import json)
+ #:use-module (guix import utils)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (guix packages)
+ #:use-module (guix serialization)
+ #:use-module (guix upstream)
+ #:use-module (guix utils)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-11)
+ #:use-module (srfi srfi-26)
+ #:export (composer->guix-package
+ %composer-updater
+ composer-recursive-import
+
+ %composer-base-url))
+
+(define %composer-base-url
+ (make-parameter "https://repo.packagist.org"))
+
+;; XXX adapted from (guix scripts hash)
+(define (file-hash file select? recursive?)
+ ;; Compute the hash of FILE.
+ (if recursive?
+ (let-values (((port get-hash) (open-sha256-port)))
+ (write-file file port #:select? select?)
+ (force-output port)
+ (get-hash))
+ (call-with-input-file file port-sha256)))
+
+;; XXX taken from (guix scripts hash)
+(define (vcs-file? file stat)
+ (case (stat:type stat)
+ ((directory)
+ (member (basename file) '(".bzr" ".git" ".hg" ".svn" "CVS")))
+ ((regular)
+ ;; Git sub-modules have a '.git' file that is a regular text file.
+ (string=? (basename file) ".git"))
+ (else
+ #f)))
+
+(define (fix-version version)
+ "Return a fixed version from a version string. For instance, v10.1 -> 10.1"
+ (cond
+ ((string-prefix? "version" version)
+ (if (char-set-contains? char-set:digit (string-ref version 7))
+ (substring version 7)
+ (substring version 8)))
+ ((string-prefix? "v" version)
+ (substring version 1))
+ (else version)))
+
+(define (latest-version versions)
+ (fold (lambda (a b) (if (version>? (fix-version a) (fix-version b)) a b))
+ (car versions) versions))
+
+(define (json->require dict)
+ (if dict
+ (let loop ((result '()) (require dict))
+ (match require
+ (() result)
+ ((((? (cut string-contains <> "/") name) . _)
+ require ...)
+ (loop (cons name result) require))
+ ((_ require ...) (loop result require))))
+ '()))
+
+(define-json-mapping <composer-source> make-composer-source composer-source?
+ json->composer-source
+ (type composer-source-type)
+ (url composer-source-url)
+ (reference composer-source-reference))
+
+(define-json-mapping <composer-package> make-composer-package composer-package?
+ json->composer-package
+ (description composer-package-description)
+ (homepage composer-package-homepage)
+ (source composer-package-source "source" json->composer-source)
+ (name composer-package-name "name" php-package-name)
+ (version composer-package-version "version" fix-version)
+ (require composer-package-require "require" json->require)
+ (dev-require composer-package-dev-require "require-dev" json->require)
+ (license composer-package-license "license"
+ (lambda (vector)
+ (map string->license (vector->list vector)))))
+
+(define* (composer-fetch name #:optional version)
+ "Return an alist representation of the Composer metadata for the package NAME,
+or #f on failure."
+ (let ((package (json-fetch
+ (string-append (%composer-base-url) "/p/" name ".json"))))
+ (if package
+ (let* ((packages (assoc-ref package "packages"))
+ (package (or (assoc-ref packages name) package))
+ (versions (filter
+ (lambda (version)
+ (and (not (string-contains version "dev"))
+ (not (string-contains version "beta"))))
+ (map car package)))
+ (version (or (if (null? version) #f version)
+ (latest-version versions))))
+ (assoc-ref package version))
+ #f)))
+
+(define (php-package-name name)
+ "Given the NAME of a package on Packagist, return a Guix-compliant name for
+the package."
+ (let ((name (string-join (string-split name #\/) "-")))
+ (if (string-prefix? "php-" name)
+ (snake-case name)
+ (string-append "php-" (snake-case name)))))
+
+(define (make-php-sexp composer-package)
+ "Return the `package' s-expression for a PHP package for the given
+COMPOSER-PACKAGE."
+ (let* ((source (composer-package-source composer-package))
+ (dependencies (map php-package-name
+ (composer-package-require composer-package)))
+ (dev-dependencies (map php-package-name
+ (composer-package-dev-require composer-package)))
+ (git? (equal? (composer-source-type source) "git")))
+ ((if git? call-with-temporary-directory call-with-temporary-output-file)
+ (lambda* (temp #:optional port)
+ (and (if git?
+ (begin
+ (mkdir-p temp)
+ (git-fetch (composer-source-url source)
+ (composer-source-reference source)
+ temp))
+ (url-fetch (composer-source-url source) temp))
+ `(package
+ (name ,(composer-package-name composer-package))
+ (version ,(composer-package-version composer-package))
+ (source (origin
+ ,@(if git?
+ `((method git-fetch)
+ (uri (git-reference
+ (url ,(composer-source-url source))
+ (commit ,(composer-source-reference source))))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ ,(bytevector->nix-base32-string
+ (file-hash temp (negate vcs-file?) #t)))))
+ `((method url-fetch)
+ (uri ,(composer-source-url source))
+ (sha256 (base32 ,(guix-hash-url temp)))))))
+ (build-system composer-build-system)
+ ,@(if (null? dependencies)
+ '()
+ `((inputs
+ (,'quasiquote
+ ,(map (lambda (name)
+ `(,name
+ (,'unquote
+ ,(string->symbol name))))
+ dependencies)))))
+ ,@(if (null? dev-dependencies)
+ '()
+ `((native-inputs
+ (,'quasiquote
+ ,(map (lambda (name)
+ `(,name
+ (,'unquote
+ ,(string->symbol name))))
+ dev-dependencies)))))
+ (synopsis "")
+ (description ,(composer-package-description composer-package))
+ (home-page ,(composer-package-homepage composer-package))
+ (license ,(match (composer-package-license composer-package)
+ (() #f)
+ ((license) license)
+ (_ license)))))))))
+
+(define* (composer->guix-package package-name #:optional version)
+ "Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
+`package' s-expression corresponding to that package, or #f on failure."
+ (let ((package (composer-fetch package-name version)))
+ (and package
+ (let* ((package (json->composer-package package))
+ (dependencies-names (composer-package-require package))
+ (dev-dependencies-names (composer-package-dev-require package)))
+ (values (make-php-sexp package)
+ (append dependencies-names dev-dependencies-names))))))
+
+(define (guix-name->composer-name name)
+ "Given a guix package name, return the name of the package in Packagist."
+ (if (string-prefix? "php-" name)
+ (let ((components (string-split (substring name 4) #\-)))
+ (match components
+ ((namespace name ...)
+ (string-append namespace "/" (string-join name "-")))))
+ name))
+
+(define (guix-package->composer-name package)
+ "Given a Composer PACKAGE built from Packagist, return the name of the
+package in Packagist."
+ (let ((upstream-name (assoc-ref
+ (package-properties package)
+ 'upstream-name))
+ (name (package-name package)))
+ (if upstream-name
+ upstream-name
+ (guix-name->composer-name name))))
+
+(define (string->license str)
+ "Convert the string STR into a license object."
+ (match str
+ ("GNU LGPL" 'license:lgpl2.0)
+ ("GPL" 'license:gpl3)
+ ((or "BSD" "BSD License" "BSD-3-Clause") 'license:bsd-3)
+ ((or "MIT" "MIT license" "Expat license") 'license:expat)
+ ("Public domain" 'license:public-domain)
+ ((or "Apache License, Version 2.0" "Apache 2.0") 'license:asl2.0)
+ (_ #f)))
+
+(define (php-package? package)
+ "Return true if PACKAGE is a PHP package from Packagist."
+ (and
+ (eq? (build-system-name (package-build-system package)) 'composer)
+ (string-prefix? "php-" (package-name package))))
+
+(define (latest-release package)
+ "Return an <upstream-source> for the latest release of PACKAGE."
+ (let* ((php-name (guix-package->composer-name package))
+ (metadata (composer-fetch php-name))
+ (package (json->composer-package metadata))
+ (version (composer-package-version package))
+ (url (composer-source-url (composer-package-source package))))
+ (upstream-source
+ (package (package-name package))
+ (version version)
+ (urls (list url)))))
+
+(define %composer-updater
+ (upstream-updater
+ (name 'composer)
+ (description "Updater for Composer packages")
+ (pred php-package?)
+ (import latest-release)))
+
+(define* (composer-recursive-import package-name #:optional version)
+ (recursive-import package-name '()
+ #:repo->guix-package composer->guix-package
+ #:guix-name php-package-name))
diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm
index 4ddd8d46a1..8c58dd35e2 100644
--- a/guix/scripts/import.scm
+++ b/guix/scripts/import.scm
@@ -47,7 +47,7 @@ (define %standard-import-options '())
(define importers '("gnu" "pypi" "cpan" "hackage" "stackage" "egg" "elpa"
"gem" "go" "cran" "crate" "texlive" "json" "opam"
- "minetest" "elm" "hexpm"))
+ "minetest" "elm" "hexpm" "composer"))
(define (resolve-importer name)
(let ((module (resolve-interface
diff --git a/guix/scripts/import/composer.scm b/guix/scripts/import/composer.scm
new file mode 100644
index 0000000000..412bae6318
--- /dev/null
+++ b/guix/scripts/import/composer.scm
@@ -0,0 +1,107 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2015 David Thompson <davet@gnu.org>
+;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix scripts import composer)
+ #:use-module (guix ui)
+ #:use-module (guix utils)
+ #:use-module (guix scripts)
+ #:use-module (guix import composer)
+ #:use-module (guix scripts import)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-11)
+ #:use-module (srfi srfi-37)
+ #:use-module (srfi srfi-41)
+ #:use-module (ice-9 match)
+ #:use-module (ice-9 format)
+ #:export (guix-import-composer))
+
+
+;;;
+;;; Command-line options.
+;;;
+
+(define %default-options
+ '())
+
+(define (show-help)
+ (display (G_ "Usage: guix import composer PACKAGE-NAME
+Import and convert the Composer package for PACKAGE-NAME.\n"))
+ (display (G_ "
+ -h, --help display this help and exit"))
+ (display (G_ "
+ -V, --version display version information and exit"))
+ (display (G_ "
+ -r, --recursive generate package expressions for all Composer packages\
+ that are not yet in Guix"))
+ (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 composer")))
+ (option '(#\r "recursive") #f #f
+ (lambda (opt name arg result)
+ (alist-cons 'recursive #t result)))
+ %standard-import-options))
+
+
+;;;
+;;; Entry point.
+;;;
+
+(define (guix-import-composer . 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))
+ (args (filter-map (match-lambda
+ (('argument . value)
+ value)
+ (_ #f))
+ (reverse opts))))
+ (match args
+ ((package-name)
+ (if (assoc-ref opts 'recursive)
+ (map (match-lambda
+ ((and ('package ('name name) . rest) pkg)
+ `(define-public ,(string->symbol name)
+ ,pkg))
+ (_ #f))
+ (composer-recursive-import package-name))
+ (let ((sexp (composer->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/composer.scm b/tests/composer.scm
new file mode 100644
index 0000000000..cefaf9f434
--- /dev/null
+++ b/tests/composer.scm
@@ -0,0 +1,92 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (test-composer)
+ #:use-module (guix import composer)
+ #:use-module (guix base32)
+ #:use-module (gcrypt hash)
+ #:use-module (guix tests http)
+ #:use-module (guix grafts)
+ #:use-module (srfi srfi-64)
+ #:use-module (web client)
+ #:use-module (ice-9 match))
+
+;; Globally disable grafts because they can trigger early builds.
+(%graft? #f)
+
+(define test-json
+ "{
+ \"packages\": {
+ \"foo/bar\": {
+ \"0.1\": {
+ \"name\": \"foo/bar\",
+ \"description\": \"description\",
+ \"keywords\": [\"testing\"],
+ \"homepage\": \"http://example.com
This message was truncated. Download the full message here.
N
N
Nicolas Graves wrote on 2 Nov 2023 16:16
[PATCH v5 2/9] gnu: Add composer-classloader.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151725.31362-3-ngraves@ngraves.fr
* gnu/packages/php-xyz.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
---
gnu/local.mk | 1 +
gnu/packages/php-xyz.scm | 60 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+)
create mode 100644 gnu/packages/php-xyz.scm

Toggle diff (80 lines)
diff --git a/gnu/local.mk b/gnu/local.mk
index 83b5268c7e..f1d16f873c 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -502,6 +502,7 @@ GNU_SYSTEM_MODULES = \
%D%/packages/photo.scm \
%D%/packages/phabricator.scm \
%D%/packages/php.scm \
+ %D%/packages/php-xyz.scm \
%D%/packages/piet.scm \
%D%/packages/pikchr.scm \
%D%/packages/pkg-config.scm \
diff --git a/gnu/packages/php-xyz.scm b/gnu/packages/php-xyz.scm
new file mode 100644
index 0000000000..ac90ee3c25
--- /dev/null
+++ b/gnu/packages/php-xyz.scm
@@ -0,0 +1,60 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (gnu packages php-xyz)
+ #:use-module (gnu packages)
+ #:use-module (gnu packages php)
+ #:use-module (guix packages)
+ #:use-module (guix download)
+ #:use-module (guix git-download)
+ #:use-module (guix build-system composer)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix utils)
+ #:use-module ((guix licenses) #:prefix license:))
+
+(define-public composer-classloader
+ (package
+ (name "composer-classloader")
+ (version "1.9.0")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/composer/composer")
+ (commit version)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32 "0127zmmg3yx84ljngfs86q7kjhyypybkf4d1ihfrfnzgynzxfxdf"))))
+ (build-system gnu-build-system)
+ (arguments
+ `(#:phases
+ (modify-phases %standard-phases
+ (delete 'configure)
+ (delete 'build)
+ (delete 'check)
+ (replace 'install
+ (lambda* (#:key outputs #:allow-other-keys)
+ (let* ((out (assoc-ref outputs "out")))
+ (install-file "src/Composer/Autoload/ClassLoader.php"
+ (string-append out "/share/web/composer/"))))))))
+ (home-page "https://getcomposer.org")
+ (synopsis "PHP class loader extracted from the composer package")
+ (description "This package contains the class loader class used by Composer to
+build its autoloading feature. This package is used by the composer-build-system
+to build its own store-aware autoloading feature.")
+ (license license:expat)))
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:16
[PATCH v5 3/9] guix: Add composer-build-system.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151725.31362-4-ngraves@ngraves.fr
* guix/build-system/composer.scm: New file.
* guix/build/composer-build-system.scm: New file.
* gnu/packages/aux-files/findclass.php: New file.
* Makefile.am: Add them.
* doc/guix.texi (Build Systems): Document it.
---
Makefile.am | 3 +
doc/guix.texi | 16 +-
gnu/packages/aux-files/findclass.php | 125 ++++++++++++++
guix/build-system/composer.scm | 162 ++++++++++++++++++
guix/build/composer-build-system.scm | 247 +++++++++++++++++++++++++++
tests/composer.scm | 36 ++--
6 files changed, 568 insertions(+), 21 deletions(-)
create mode 100644 gnu/packages/aux-files/findclass.php
create mode 100644 guix/build-system/composer.scm
create mode 100644 guix/build/composer-build-system.scm

Toggle diff (480 lines)
diff --git a/Makefile.am b/Makefile.am
index 3fec98f064..47d1cb19ed 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -149,6 +149,7 @@ MODULES = \
guix/build-system/chicken.scm \
guix/build-system/clojure.scm \
guix/build-system/cmake.scm \
+ guix/build-system/composer.scm \
guix/build-system/dub.scm \
guix/build-system/dune.scm \
guix/build-system/elm.scm \
@@ -206,6 +207,7 @@ MODULES = \
guix/build/cargo-utils.scm \
guix/build/chicken-build-system.scm \
guix/build/cmake-build-system.scm \
+ guix/build/composer-build-system.scm \
guix/build/dub-build-system.scm \
guix/build/dune-build-system.scm \
guix/build/elm-build-system.scm \
@@ -411,6 +413,7 @@ dist_noinst_DATA = \
AUX_FILES = \
gnu/packages/aux-files/chromium/master-preferences.json \
gnu/packages/aux-files/emacs/guix-emacs.el \
+ gnu/packages/aux-files/findclass.php \
gnu/packages/aux-files/guix.vim \
gnu/packages/aux-files/linux-libre/6.5-arm.conf \
gnu/packages/aux-files/linux-libre/6.5-arm64.conf \
diff --git a/doc/guix.texi b/doc/guix.texi
index 0e64654715..6a1c0aeaa5 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -9554,6 +9554,20 @@ debugging information''), which roughly means that code is compiled with
@code{-O2 -g}, as is the case for Autoconf-based packages by default.
@end defvar
+@defvar {Scheme Variable} composer-build-system
+This variable is exported by @code{(guix build-system composer)}. It
+implements the build procedure for packages using
+@url{https://getcomposer.org/, Composer}, the PHP package manager.
+
+It automatically adds the @code{php} package to the set of inputs. Which
+package is used can be specified with the @code{#:php} parameter.
+
+The @code{#:test-target} parameter is used to control which script is run
+for the tests. By default, the @code{test} script is run if it exists. If
+the script does not exist, the build system will run @code{phpunit} from the
+source directory, assuming there is a @file{phpunit.xml} file.
+@end defvar
+
@defvar dune-build-system
This variable is exported by @code{(guix build-system dune)}. It
supports builds of packages using @uref{https://dune.build/, Dune}, a build
@@ -14550,7 +14564,7 @@ in Guix.
@item composer
@cindex Composer
@cindex PHP
-Import metadat from the @uref{https://getcomposer.org/, Composer} package
+Import metadata from the @uref{https://getcomposer.org/, Composer} package
archive used by the PHP community, as in this example:
@example
diff --git a/gnu/packages/aux-files/findclass.php b/gnu/packages/aux-files/findclass.php
new file mode 100644
index 0000000000..d0b250c8e1
--- /dev/null
+++ b/gnu/packages/aux-files/findclass.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * The content of this file is copied from composer's src/Composer/Autoload/ClassMapGenerator.php
+ * the findClasses method was extracted, to prevent using any dependency.
+ *
+ * Composer (and thus this file) is distributed under the expat license, and
+ * ClassMapGenerator.php also contains this notice:
+ *
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * This file is copied from the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * To the extent to wich it makes sense, as the author of the extract:
+ * Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
+ */
+
+/**
+ * Extract the classes in the given file
+ *
+ * @param string $path The file to check
+ * @throws \RuntimeException
+ * @return array The found classes
+ */
+function findClasses($path)
+{
+ $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
+ if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
+ $extraTypes .= '|enum';
+ }
+ // Use @ here instead of Silencer to actively suppress 'unhelpful' output
+ // @link https://github.com/composer/composer/pull/4886
+ $contents = @php_strip_whitespace($path);
+ if (!$contents) {
+ if (!file_exists($path)) {
+ $message = 'File at "%s" does not exist, check your classmap definitions';
+ } elseif (!is_readable($path)) {
+ $message = 'File at "%s" is not readable, check its permissions';
+ } elseif ('' === trim(file_get_contents($path))) {
+ // The input file was really empty and thus contains no classes
+ return array();
+ } else {
+ $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
+ }
+ $error = error_get_last();
+ if (isset($error['message'])) {
+ $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
+ }
+ throw new \RuntimeException(sprintf($message, $path));
+ }
+ // return early if there is no chance of matching anything in this file
+ if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
+ return array();
+ }
+ // strip heredocs/nowdocs
+ $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
+ // strip strings
+ $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
+ // strip leading non-php code if needed
+ if (substr($contents, 0, 2) !== '<?') {
+ $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
+ if ($replacements === 0) {
+ return array();
+ }
+ }
+ // strip non-php blocks in the file
+ $contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
+ // strip trailing non-php code if needed
+ $pos = strrpos($contents, '?>');
+ if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
+ $contents = substr($contents, 0, $pos);
+ }
+ // strip comments if short open tags are in the file
+ if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
+ $contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
+ }
+ preg_match_all('{
+ (?:
+ \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
+ | \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;]
+ )
+ }ix', $contents, $matches);
+ $classes = array();
+ $namespace = '';
+ for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
+ if (!empty($matches['ns'][$i])) {
+ $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
+ } else {
+ $name = $matches['name'][$i];
+ // skip anon classes extending/implementing
+ if ($name === 'extends' || $name === 'implements') {
+ continue;
+ }
+ if ($name[0] === ':') {
+ // This is an XHP class, https://github.com/facebook/xhp
+ $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
+ } elseif ($matches['type'][$i] === 'enum') {
+ // In Hack, something like:
+ // enum Foo: int { HERP = '123'; }
+ // The regex above captures the colon, which isn't part of
+ // the class name.
+ $name = rtrim($name, ':');
+ }
+ $classes[] = ltrim($namespace . $name, '\\');
+ }
+ }
+ return $classes;
+}
+
+$options = getopt('i:f:', []);
+$file = $options["f"];
+$input = $options["i"];
+
+$classes = findClasses($file);
+foreach($classes as $class) {
+ echo '$classmap[\''.$class.'\'] = \''.$input.'/'.$file.'\';';
+ echo "\n";
+}
diff --git a/guix/build-system/composer.scm b/guix/build-system/composer.scm
new file mode 100644
index 0000000000..8bf99ff9c5
--- /dev/null
+++ b/guix/build-system/composer.scm
@@ -0,0 +1,162 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+(define-module (guix build-system composer)
+ #:use-module (guix store)
+ #:use-module (guix utils)
+ #:use-module (guix derivations)
+ #:use-module (guix search-paths)
+ #:use-module (guix build-system)
+ #:use-module (guix build-system gnu)
+ #:use-module (guix gexp)
+ #:use-module (guix packages)
+ #:use-module (gnu packages)
+ #:use-module (ice-9 match)
+ #:use-module (srfi srfi-1)
+ #:export (%composer-build-system-modules
+ lower
+ composer-build
+ composer-build-system))
+
+;; Commentary:
+;;
+;; Standard build procedure for PHP packages using Composer. This is implemented
+;; as an extension of `gnu-build-system'.
+;;
+;; Code:
+
+(define (default-php)
+ "Return the default PHP package."
+
+ ;; Do not use `@' to avoid introducing circular dependencies.
+ (let ((module (resolve-interface '(gnu packages php))))
+ (module-ref module 'php)))
+
+(define (default-findclass)
+ "Return the default findclass script."
+ (search-auxiliary-file "findclass.php"))
+
+(define (default-composer-classloader)
+ "Return the default composer-classloader package."
+
+ ;; Do not use `@' to avoid introducing circular dependencies.
+ (let ((module (resolve-interface '(gnu packages php-xyz))))
+ (module-ref module 'composer-classloader)))
+
+(define %composer-build-system-modules
+ ;; Build-side modules imported by default.
+ `((guix build composer-build-system)
+ (guix build union)
+ (json)
+ (json builder)
+ (json parser)
+ (json record)
+ ,@%gnu-build-system-modules))
+
+(define* (lower name
+ #:key source inputs native-inputs outputs system target
+ (php (default-php))
+ (composer-classloader (default-composer-classloader))
+ (findclass (default-findclass))
+ #:allow-other-keys
+ #:rest arguments)
+ "Return a bag for NAME."
+ (define private-keywords
+ '(#:target #:php #:composer-classloader #:findclass #:inputs #:native-inputs))
+
+ (and (not target) ;XXX: no cross-compilation
+ (bag
+ (name name)
+ (system system)
+ (host-inputs `(,@(if source
+ `(("source" ,source))
+ '())
+ ,@inputs
+
+ ;; Keep the standard inputs of 'gnu-build-system'.
+ ,@(standard-packages)))
+ (build-inputs `(("php" ,php)
+ ("findclass.php" ,findclass)
+ ("composer-classloader" ,composer-classloader)
+ ,@native-inputs))
+ (outputs outputs)
+ (build composer-build)
+ (arguments (strip-keyword-arguments private-keywords arguments)))))
+
+(define* (composer-build name inputs
+ #:key
+ guile source
+ (outputs '("out"))
+ (configure-flags ''())
+ (search-paths '())
+ (out-of-source? #t)
+ (composer-file "composer.json")
+ (tests? #t)
+ (test-target "test")
+ (install-target "install")
+ (validate-runpath? #t)
+ (patch-shebangs? #t)
+ (strip-binaries? #t)
+ (strip-flags #~'("--strip-debug"))
+ (strip-directories #~'("lib" "lib64" "libexec"
+ "bin" "sbin"))
+ (phases '(@ (guix build composer-build-system)
+ %standard-phases))
+ (system (%current-system))
+ (imported-modules %composer-build-system-modules)
+ (modules '((guix build composer-build-system)
+ (guix build utils))))
+ "Build SOURCE using PHP, and with INPUTS. This assumes that SOURCE provides
+a 'composer.json' file as its build system."
+ (define builder
+ (with-imported-modules imported-modules
+ #~(begin
+ (use-modules #$@(sexp->gexp modules))
+
+ #$(with-build-variables inputs outputs
+ #~(composer-build
+ #:source #$source
+ #:system #$system
+ #:outputs %outputs
+ #:inputs %build-inputs
+ #:search-paths '#$(map search-path-specification->sexp
+ search-paths)
+ #:phases #$phases
+ #:out-of-source? #$out-of-source?
+ #:composer-file #$composer-file
+ #:tests? #$tests?
+ #:test-target #$test-target
+ #:install-target #$install-target
+ #:validate-runpath? #$validate-runpath?
+ #:patch-shebangs? #$patch-shebangs?
+ #:strip-binaries? #$strip-binaries?
+ #:strip-flags #$strip-flags
+ #:strip-directories #$strip-directories)))))
+
+ (gexp->derivation name builder
+ #:system system
+ #:target #f
+ #:graft? #f
+ #:guile-for-build guile))
+
+(define composer-build-system
+ (build-system
+ (name 'composer)
+ (description "The standard Composer build system")
+ (lower lower)))
+
+;;; composer.scm ends here
diff --git a/guix/build/composer-build-system.scm b/guix/build/composer-build-system.scm
new file mode 100644
index 0000000000..bcbae27021
--- /dev/null
+++ b/guix/build/composer-build-system.scm
@@ -0,0 +1,247 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;; Copyright © 2023 Nicolas Graves <ngraves@ngraves.fr>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(define-module (guix build composer-build-system)
+ #:use-module ((guix build gnu-build-system) #:prefix gnu:)
+ #:use-module (guix build utils)
+ #:use-module (ice-9 match)
+ #:use-module (json)
+ #:use-module (srfi srfi-26)
+ #:export (%standard-phases
+ composer-build))
+
+;; Commentary:
+;;
+;; Builder-side code of the standard composer build procedure.
+;;
+;; Code:
+
+(define (json->require dict)
+ (if dict
+ (let loop ((result '()) (require dict))
+ (match require
+ (() result)
+ ((((? (cut string-contains <> "/") name) . _)
+ require ...)
+ (loop (cons name result) require))
+ ((_ require ...) (loop result require))
+ (_ result)))
+ '()))
+
+(define (if-specified-to-list fn)
+ (match-lambda
+ ((? unspecified?) '())
+ (arg (fn arg))
+ (_ '())))
+
+(define-json-mapping <composer-autoload> make-composer-autoload
+ composer-autoload?
+ json->composer-autoload
+ (psr-4 composer-autoload-psr-4 "psr-4" (if-specified-to-list identity))
+ (classmap composer-autoload-classmap "classmap"
+ (if-specified-to-list vector->list)))
+
+(define-json-mapping <composer-package> make-composer-package composer-package?
+ json->composer-package
+ (name composer-package-name)
+ (autoload composer-package-autoload "autoload"
+ (if-specified-to-list json->composer-autoload))
+ (autoload-dev composer-package-autoload-dev "autoload-dev"
+ (if-specified-to-list json->composer-autoload))
+ (require composer-package-require "require" json->require)
+ (dev-require composer-package-dev-require "require-dev" json->require)
+ (scripts composer-package-scripts "scripts"
+ (if-specified-to-list identity))
+ (binaries composer-package-binaries "bin"
+ (if-specified-to-list vector->list)))
+
+(define* (read-package-data #:key (filename "composer.json"))
+ (call-with-input-file filename
+ (lambda (port)
+ (json->composer-package (json->scm port)))))
+
+(define* (check #:key composer-file inputs outputs tests? test-target #:allow-other-keys)
+ "Test the given package."
+ (when tests?
+ (mkdir-p "vendor")
+ (create-autoload (string-append (getcwd) "/vendor") composer-file
+ (append inputs outputs) #:dev-dependencies? #t)
+ (let* ((package-data (read-package-data #:filename composer-file))
+ (scripts (composer-package-scripts package-data))
+ (test-script (assoc-ref scripts test-target))
+ (dependencies (composer-package-require package-data))
+ (dependencies-dev (composer-package-dev-require package-data))
+ (name (composer-package-name package-data)))
+ (for-each
+ (match-lambda
+ ((_ . input)
+ (let ((bin (find-php-bin input)))
+ (when bin
+ (copy-recursively bin "vendor/bin")))))
+ inputs)
+ (match test-script
+ ((? string? command)
+ (unless (zero? (system command))
+ (throw 'failed-command command)))
+ (('@ (? string? command) ...)
+ (for-each
+ (lambda (c)
+ (unless (zero? (system c))
+ (throw 'failed-command c)))
+ command))
+ (#f (invoke "vendor/bin/phpunit"))))))
+
+(define (find-php-bin input)
+ (let* ((web-dir (string-append input "/share/web"))
+ (vendors (if (file-exists? web-dir)
+ (find-
This message was truncated. Download the full message here.
N
N
Nicolas Graves wrote on 2 Nov 2023 16:16
[PATCH v5 5/9] guix: import: composer: Fix json->require.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151725.31362-6-ngraves@ngraves.fr
---
guix/import/composer.scm | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

Toggle diff (16 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index 177dc63092..3acbbecf82 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -88,7 +88,8 @@ (define (json->require dict)
((((? (cut string-contains <> "/") name) . _)
require ...)
(loop (cons name result) require))
- ((_ require ...) (loop result require))))
+ ((_ require ...) (loop result require))
+ (_ result)))
'()))
(define-json-mapping <composer-source> make-composer-source composer-source?
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:16
[PATCH v5 4/9] guix: import: composer: Use memoization.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151725.31362-5-ngraves@ngraves.fr
---
guix/import/composer.scm | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)

Toggle diff (51 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index c152f402bb..177dc63092 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -27,6 +27,7 @@ (define-module (guix import composer)
#:use-module (guix import json)
#:use-module (guix import utils)
#:use-module ((guix licenses) #:prefix license:)
+ #:use-module (guix memoization)
#:use-module (guix packages)
#:use-module (guix serialization)
#:use-module (guix upstream)
@@ -197,16 +198,18 @@ (define (make-php-sexp composer-package)
((license) license)
(_ license)))))))))
-(define* (composer->guix-package package-name #:optional version)
- "Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
+(define composer->guix-package
+ (memoize
+ (lambda* (package-name #:key version #:allow-other-keys)
+ "Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
`package' s-expression corresponding to that package, or #f on failure."
- (let ((package (composer-fetch package-name version)))
- (and package
- (let* ((package (json->composer-package package))
- (dependencies-names (composer-package-require package))
- (dev-dependencies-names (composer-package-dev-require package)))
- (values (make-php-sexp package)
- (append dependencies-names dev-dependencies-names))))))
+ (let ((package (composer-fetch package-name version)))
+ (and package
+ (let* ((package (json->composer-package package))
+ (dependencies-names (composer-package-require package))
+ (dev-dependencies-names (composer-package-dev-require package)))
+ (values (make-php-sexp package)
+ (append dependencies-names dev-dependencies-names))))))))
(define (guix-name->composer-name name)
"Given a guix package name, return the name of the package in Packagist."
@@ -265,6 +268,7 @@ (define %composer-updater
(import latest-release)))
(define* (composer-recursive-import package-name #:optional version)
- (recursive-import package-name '()
+ (recursive-import package-name
+ #:version version
#:repo->guix-package composer->guix-package
#:guix-name php-package-name))
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:16
[PATCH v5 7/9] guix: import: composer: Modern inputs formatting.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151725.31362-8-ngraves@ngraves.fr
* guix/import/composer.scm (make-php-sexp): Update inputs formatting.
---
guix/import/composer.scm | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)

Toggle diff (30 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index 49f16caedf..89c8ea9113 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -179,21 +179,11 @@ (define (make-php-sexp composer-package)
,@(if (null? dependencies)
'()
`((inputs
- (,'quasiquote
- ,(map (lambda (name)
- `(,name
- (,'unquote
- ,(string->symbol name))))
- dependencies)))))
+ (list ,@(map string->symbol dependencies)))))
,@(if (null? dev-dependencies)
'()
`((native-inputs
- (,'quasiquote
- ,(map (lambda (name)
- `(,name
- (,'unquote
- ,(string->symbol name))))
- dev-dependencies)))))
+ (list ,@(map string->symbol dev-dependencies)))))
(synopsis "")
(description ,(composer-package-description composer-package))
(home-page ,(composer-package-homepage composer-package))
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:16
[PATCH v5 6/9] guix: import: composer: More robust string->license.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151725.31362-7-ngraves@ngraves.fr
* guix/import/composer.scm (string->license): Use spdx-string->license. Fall
back to unknown-license!.
---
guix/import/composer.scm | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)

Toggle diff (55 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index 3acbbecf82..49f16caedf 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -109,7 +109,10 @@ (define-json-mapping <composer-package> make-composer-package composer-package?
(dev-require composer-package-dev-require "require-dev" json->require)
(license composer-package-license "license"
(lambda (vector)
- (map string->license (vector->list vector)))))
+ (let ((l (map string->license (vector->list vector))))
+ (if (eq? (length l) 1)
+ (car l)
+ `(list ,@l))))))
(define* (composer-fetch name #:optional version)
"Return an alist representation of the Composer metadata for the package NAME,
@@ -194,10 +197,8 @@ (define (make-php-sexp composer-package)
(synopsis "")
(description ,(composer-package-description composer-package))
(home-page ,(composer-package-homepage composer-package))
- (license ,(match (composer-package-license composer-package)
- (() #f)
- ((license) license)
- (_ license)))))))))
+ (license ,(or (composer-package-license composer-package)
+ 'unknown-license!))))))))
(define composer->guix-package
(memoize
@@ -234,14 +235,15 @@ (define (guix-package->composer-name package)
(define (string->license str)
"Convert the string STR into a license object."
- (match str
- ("GNU LGPL" 'license:lgpl2.0)
- ("GPL" 'license:gpl3)
- ((or "BSD" "BSD License" "BSD-3-Clause") 'license:bsd-3)
- ((or "MIT" "MIT license" "Expat license") 'license:expat)
- ("Public domain" 'license:public-domain)
- ((or "Apache License, Version 2.0" "Apache 2.0") 'license:asl2.0)
- (_ #f)))
+ (or (spdx-string->license str)
+ (match str
+ ("GNU LGPL" 'license:lgpl2.0)
+ ("GPL" 'license:gpl3)
+ ((or "BSD" "BSD License") 'license:bsd-3)
+ ((or "MIT" "MIT license" "Expat license") 'license:expat)
+ ("Public domain" 'license:public-domain)
+ ((or "Apache License, Version 2.0" "Apache 2.0") 'license:asl2.0)
+ (_ 'unknown-license!))))
(define (php-package? package)
"Return true if PACKAGE is a PHP package from Packagist."
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:16
[PATCH v5 8/9] guix: import: composer: Full rewrite composer-fetch.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151725.31362-9-ngraves@ngraves.fr
Change-Id: I1c01c242cefe0bc4cfc9bd9a5717d10a61dd575e
---
guix/import/composer.scm | 154 +++++++++++++++++++--------------------
1 file changed, 77 insertions(+), 77 deletions(-)

Toggle diff (205 lines)
diff --git a/guix/import/composer.scm b/guix/import/composer.scm
index 89c8ea9113..2cc8861bdd 100644
--- a/guix/import/composer.scm
+++ b/guix/import/composer.scm
@@ -19,7 +19,7 @@
(define-module (guix import composer)
#:use-module (ice-9 match)
#:use-module (json)
- #:use-module (gcrypt hash)
+ #:use-module (guix hash)
#:use-module (guix base32)
#:use-module (guix build git)
#:use-module (guix build utils)
@@ -44,27 +44,6 @@ (define-module (guix import composer)
(define %composer-base-url
(make-parameter "https://repo.packagist.org"))
-;; XXX adapted from (guix scripts hash)
-(define (file-hash file select? recursive?)
- ;; Compute the hash of FILE.
- (if recursive?
- (let-values (((port get-hash) (open-sha256-port)))
- (write-file file port #:select? select?)
- (force-output port)
- (get-hash))
- (call-with-input-file file port-sha256)))
-
-;; XXX taken from (guix scripts hash)
-(define (vcs-file? file stat)
- (case (stat:type stat)
- ((directory)
- (member (basename file) '(".bzr" ".git" ".hg" ".svn" "CVS")))
- ((regular)
- ;; Git sub-modules have a '.git' file that is a regular text file.
- (string=? (basename file) ".git"))
- (else
- #f)))
-
(define (fix-version version)
"Return a fixed version from a version string. For instance, v10.1 -> 10.1"
(cond
@@ -114,22 +93,36 @@ (define-json-mapping <composer-package> make-composer-package composer-package?
(car l)
`(list ,@l))))))
-(define* (composer-fetch name #:optional version)
- "Return an alist representation of the Composer metadata for the package NAME,
-or #f on failure."
- (let ((package (json-fetch
- (string-append (%composer-base-url) "/p/" name ".json"))))
- (if package
- (let* ((packages (assoc-ref package "packages"))
- (package (or (assoc-ref packages name) package))
- (versions (filter
- (lambda (version)
- (and (not (string-contains version "dev"))
- (not (string-contains version "beta"))))
- (map car package)))
- (version (or (if (null? version) #f version)
- (latest-version versions))))
- (assoc-ref package version))
+(define (valid-version? v)
+ (let ((d (string-downcase v)))
+ (and (not (string-contains d "dev"))
+ (not (string-contains d "beta"))
+ (not (string-contains d "rc")))))
+
+(define* (composer-fetch name #:key (version #f))
+ "Return a composer-package representation of the Composer metadata for the
+package NAME with optional VERSION, or #f on failure."
+ (let* ((url (string-append (%composer-base-url) "/p/" name ".json"))
+ (packages (and=> (json-fetch url)
+ (lambda (pkg)
+ (let ((pkgs (assoc-ref pkg "packages")))
+ (or (assoc-ref pkgs name) pkg))))))
+ (if packages
+ (json->composer-package
+ (if version
+ (assoc-ref packages version)
+ (cdr
+ (reduce
+ (lambda (new cur-max)
+ (match new
+ (((? valid-version? version) . tail)
+ (if (version>? (fix-version version)
+ (fix-version (car cur-max)))
+ (cons* version tail)
+ cur-max))
+ (_ cur-max)))
+ (cons* "0.0.0" #f)
+ packages))))
#f)))
(define (php-package-name name)
@@ -158,47 +151,55 @@ (define (make-php-sexp composer-package)
(composer-source-reference source)
temp))
(url-fetch (composer-source-url source) temp))
- `(package
- (name ,(composer-package-name composer-package))
- (version ,(composer-package-version composer-package))
- (source (origin
- ,@(if git?
- `((method git-fetch)
- (uri (git-reference
- (url ,(composer-source-url source))
- (commit ,(composer-source-reference source))))
- (file-name (git-file-name name version))
- (sha256
- (base32
- ,(bytevector->nix-base32-string
- (file-hash temp (negate vcs-file?) #t)))))
- `((method url-fetch)
- (uri ,(composer-source-url source))
- (sha256 (base32 ,(guix-hash-url temp)))))))
- (build-system composer-build-system)
- ,@(if (null? dependencies)
- '()
- `((inputs
- (list ,@(map string->symbol dependencies)))))
- ,@(if (null? dev-dependencies)
- '()
- `((native-inputs
- (list ,@(map string->symbol dev-dependencies)))))
- (synopsis "")
- (description ,(composer-package-description composer-package))
- (home-page ,(composer-package-homepage composer-package))
- (license ,(or (composer-package-license composer-package)
- 'unknown-license!))))))))
+ `(define-public ,(string->symbol
+ (composer-package-name composer-package))
+ (package
+ (name ,(composer-package-name composer-package))
+ (version ,(composer-package-version composer-package))
+ (source
+ (origin
+ ,@(if git?
+ `((method git-fetch)
+ (uri (git-reference
+ (url ,(if (string-suffix?
+ ".git"
+ (composer-source-url source))
+ (string-drop-right
+ (composer-source-url source)
+ (string-length ".git"))
+ (composer-source-url source)))
+ (commit ,(composer-source-reference source))))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ ,(bytevector->nix-base32-string
+ (file-hash* temp)))))
+ `((method url-fetch)
+ (uri ,(composer-source-url source))
+ (sha256 (base32 ,(guix-hash-url temp)))))))
+ (build-system composer-build-system)
+ ,@(if (null? dependencies)
+ '()
+ `((inputs
+ (list ,@(map string->symbol dependencies)))))
+ ,@(if (null? dev-dependencies)
+ '()
+ `((native-inputs
+ (list ,@(map string->symbol dev-dependencies)))))
+ (synopsis "")
+ (description ,(composer-package-description composer-package))
+ (home-page ,(composer-package-homepage composer-package))
+ (license ,(or (composer-package-license composer-package)
+ 'unknown-license!)))))))))
(define composer->guix-package
(memoize
- (lambda* (package-name #:key version #:allow-other-keys)
+ (lambda* (package-name #:key (version #f) #:allow-other-keys)
"Fetch the metadata for PACKAGE-NAME from packagist.org, and return the
`package' s-expression corresponding to that package, or #f on failure."
- (let ((package (composer-fetch package-name version)))
+ (let ((package (composer-fetch package-name #:version version)))
(and package
- (let* ((package (json->composer-package package))
- (dependencies-names (composer-package-require package))
+ (let* ((dependencies-names (composer-package-require package))
(dev-dependencies-names (composer-package-dev-require package)))
(values (make-php-sexp package)
(append dependencies-names dev-dependencies-names))))))))
@@ -238,14 +239,13 @@ (define (string->license str)
(define (php-package? package)
"Return true if PACKAGE is a PHP package from Packagist."
(and
- (eq? (build-system-name (package-build-system package)) 'composer)
- (string-prefix? "php-" (package-name package))))
+ (eq? (package-build-system package) composer-build-system)
+ (string-prefix? "php-" (package-name package))))
(define (latest-release package)
"Return an <upstream-source> for the latest release of PACKAGE."
(let* ((php-name (guix-package->composer-name package))
- (metadata (composer-fetch php-name))
- (package (json->composer-package metadata))
+ (package (composer-fetch php-name))
(version (composer-package-version package))
(url (composer-source-url (composer-package-source package))))
(upstream-source
--
2.41.0
N
N
Nicolas Graves wrote on 2 Nov 2023 16:16
[PATCH v5 9/9] gnu: composer-build-system: Full check phase rewrite.
(address . 42338@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20231102151725.31362-10-ngraves@ngraves.fr
Change-Id: I824b27b925cd718ee83ef6b2ee4a8a1e69455de6
---
guix/build-system/composer.scm | 2 +
guix/build/composer-build-system.scm | 239 ++++++++++++++++-----------
2 files changed, 148 insertions(+), 93 deletions(-)

Toggle diff (310 lines)
diff --git a/guix/build-system/composer.scm b/guix/build-system/composer.scm
index 8bf99ff9c5..7d2ad2b398 100644
--- a/guix/build-system/composer.scm
+++ b/guix/build-system/composer.scm
@@ -107,6 +107,7 @@ (define* (composer-build name inputs
(composer-file "composer.json")
(tests? #t)
(test-target "test")
+ (test-flags ''())
(install-target "install")
(validate-runpath? #t)
(patch-shebangs? #t)
@@ -140,6 +141,7 @@ (define builder
#:composer-file #$composer-file
#:tests? #$tests?
#:test-target #$test-target
+ #:test-flags #$test-flags
#:install-target #$install-target
#:validate-runpath? #$validate-runpath?
#:patch-shebangs? #$patch-shebangs?
diff --git a/guix/build/composer-build-system.scm b/guix/build/composer-build-system.scm
index bcbae27021..6f05801ad1 100644
--- a/guix/build/composer-build-system.scm
+++ b/guix/build/composer-build-system.scm
@@ -53,9 +53,22 @@ (define (if-specified-to-list fn)
(define-json-mapping <composer-autoload> make-composer-autoload
composer-autoload?
json->composer-autoload
- (psr-4 composer-autoload-psr-4 "psr-4" (if-specified-to-list identity))
+ (psr-4 composer-autoload-psr-4 "psr-4"
+ (match-lambda
+ ((? unspecified?) '())
+ ((? (lambda (al)
+ (and (list? al) (pair? (car al)) (vector? (cdar al)))) al)
+ (append-map
+ (lambda (vect-el)
+ (list (cons (caar al) vect-el)))
+ (vector->list (cdar al))))
+ ((? list? l) l)
+ (_ '())))
+ (psr-0 composer-autoload-psr-0 "psr-0" (if-specified-to-list identity))
(classmap composer-autoload-classmap "classmap"
- (if-specified-to-list vector->list)))
+ (if-specified-to-list vector->list))
+ (files composer-autoload-files "files"
+ (if-specified-to-list vector->list)))
(define-json-mapping <composer-package> make-composer-package composer-package?
json->composer-package
@@ -76,65 +89,57 @@ (define* (read-package-data #:key (filename "composer.json"))
(lambda (port)
(json->composer-package (json->scm port)))))
-(define* (check #:key composer-file inputs outputs tests? test-target #:allow-other-keys)
- "Test the given package."
+(define* (create-test-autoload #:key composer-file inputs outputs tests?
+ #:allow-other-keys)
+ "Create the autoload.php file for tests. This is a standalone phase so that
+the autoload.php file can be edited before the check phase."
(when tests?
(mkdir-p "vendor")
(create-autoload (string-append (getcwd) "/vendor") composer-file
- (append inputs outputs) #:dev-dependencies? #t)
- (let* ((package-data (read-package-data #:filename composer-file))
- (scripts (composer-package-scripts package-data))
- (test-script (assoc-ref scripts test-target))
- (dependencies (composer-package-require package-data))
- (dependencies-dev (composer-package-dev-require package-data))
- (name (composer-package-name package-data)))
- (for-each
- (match-lambda
- ((_ . input)
- (let ((bin (find-php-bin input)))
- (when bin
- (copy-recursively bin "vendor/bin")))))
- inputs)
- (match test-script
- ((? string? command)
- (unless (zero? (system command))
- (throw 'failed-command command)))
- (('@ (? string? command) ...)
- (for-each
- (lambda (c)
- (unless (zero? (system c))
- (throw 'failed-command c)))
- command))
- (#f (invoke "vendor/bin/phpunit"))))))
+ inputs #:dev-dependencies? #t)))
-(define (find-php-bin input)
- (let* ((web-dir (string-append input "/share/web"))
- (vendors (if (file-exists? web-dir)
- (find-files web-dir "^vendor$" #:directories? #t)
- #f)))
- (match vendors
- ((vendor)
- (let ((bin (string-append vendor "/bin")))
- (and (file-exists? bin) bin)))
- (_ #f))))
+(define (find-bin script inputs)
+ (search-input-file inputs
+ (string-append
+ "bin/"
+ (string-drop script (string-length "vendor/bin/")))))
-(define (find-php-dep inputs dependency)
- (let loop ((inputs inputs))
- (match inputs
- (() (throw 'unsatisfied-dependency "Unsatisfied dependency: required "
- dependency))
- (((_ . input) inputs ...)
- (let ((autoload (string-append input "/share/web/" dependency
- "/vendor/autoload_conf.php")))
- (if (file-exists? autoload)
- autoload
- (loop inputs))))
- ((input inputs ...)
- (let ((autoload (string-append input "/share/web/" dependency
- "/vendor/autoload_conf.php")))
- (if (file-exists? autoload)
- autoload
- (loop inputs)))))))
+(define* (check #:key composer-file inputs
+ tests? test-target test-flags #:allow-other-keys)
+ "Test the given package.
+Please note that none of the PHP packages at the time of the rewrite of the
+build-system did use the test-script field. This means that the @code{match
+test-script} part is not tested on a real example and relies on the original
+implementation."
+ (if tests?
+ (let* ((package-data (read-package-data #:filename composer-file))
+ (scripts (composer-package-scripts package-data))
+ (test-script (assoc-ref scripts test-target)))
+ (match test-script
+ ((? string? bin)
+ (let ((command (find-bin bin inputs)))
+ (unless (zero? (apply system command test-flags))
+ (throw 'failed-command command))))
+ (('@ (? string? bins) ...)
+ (for-each
+ (lambda (c)
+ (let ((command (find-bin bin inputs)))
+ (unless (zero? (apply system command test-flags))
+ (throw 'failed-command command))))
+ bins))
+ (_ (if (file-exists? "phpunit.xml.dist")
+ (apply invoke
+ (with-exception-handler
+ (lambda (exn)
+ (if (search-error? exn)
+ (error "\
+Missing php-phpunit-phpunit native input.~%")
+ (raise exn)))
+ (lambda ()
+ (search-input-file (or inputs '()) "bin/phpunit")))
+ test-flags))
+ (format #t "No test suite found.~%"))))
+ (format #t "Test suite not run.~%")))
(define* (create-autoload vendor composer-file inputs #:key dev-dependencies?)
"creates an autoload.php file that sets up the class locations for this package,
@@ -144,15 +149,14 @@ (define* (create-autoload vendor composer-file inputs #:key dev-dependencies?)
(display (string-append
"<?php
// autoload.php @generated by Guix
-$map = $psr4map = $classmap = array();
-require_once '" vendor "/autoload_conf.php'
-require_once '" (assoc-ref inputs "composer-classloader") "/share/web/composer/ClassLoader.php'
+$psr4map = $classmap = array();
+require_once '" vendor "/autoload_conf.php';
+require_once '" (assoc-ref inputs "composer-classloader") "/share/web/composer/ClassLoader.php';
$loader = new \\Composer\\Autoload\\ClassLoader();
-foreach ($map as $namespace => $path) {
- $loader->set($namespace, $path);
-}
-foreach ($psr4map as $namespace => $path) {
- $loader->setPsr4($namespace, $path);
+foreach ($psr4map as $namespace => $paths) {
+ foreach ($paths as $path) {
+ $loader->addPsr4($namespace, $path);
+ }
}
$loader->addClassMap($classmap);
$loader->register();
@@ -170,37 +174,85 @@ (define* (create-autoload vendor composer-file inputs #:key dev-dependencies?)
(format #t "// autoload_conf.php @generated by Guix~%")
(force-output)
(for-each
- (lambda (psr4)
- (match psr4
- ((key . value)
- (format #t "$psr4map['~a'] = '~a/../~a';~%"
- (string-join (string-split key #\\) "\\\\")
- vendor value))))
+ (match-lambda
+ ((key . value)
+ (let ((vals (if (list? value)
+ (reverse value)
+ (list value))))
+ (apply
+ format
+ #t
+ (string-append
+ "$psr4map['~a'][] = ["
+ (string-join
+ (make-list (length vals) "'~a/../~a'") ",")
+ "];~%")
+ (cons* (string-join (string-split key #\\) "\\\\")
+ (append-map (lambda (v) (list vendor v)) vals)))))
+ (_ (format #t "")))
+ (merge-duplicates
(append
- (composer-autoload-psr-4 autoload)
- (if dev-dependencies?
- (composer-autoload-psr-4 autoload-dev)
- '())))
+ (composer-autoload-psr-4 autoload)
+ (if (and dev-dependencies? (not (null? autoload-dev)))
+ (composer-autoload-psr-4 autoload-dev)
+ '()))
+ '()))
(for-each
- (lambda (classmap)
- (for-each
- (lambda (file)
- (invoke "php" (assoc-ref inputs "findclass.php")
- "-i" (string-append vendor "/..") "-f" file))
- (find-files classmap ".(php|hh|inc)$")))
- (append
- (composer-autoload-classmap autoload)
- (if dev-dependencies?
- (composer-autoload-classmap autoload-dev)
- '())))
+ (lambda (psr0)
+ (match psr0
+ ((key . value)
+ (format #t "$psr4map['~a'][] = ['~a/../~a/~a'];~%"
+ (string-join (string-split key #\\) "\\\\")
+ vendor
+ value
+ (string-join (string-split key #\\) "/")))
+ (_ (format #t ""))))
+ (append
+ (composer-autoload-psr-0 autoload)
+ (if (and dev-dependencies? (not (null? autoload-dev)))
+ (composer-autoload-psr-0 autoload-dev)
+ '())))
(for-each
- (lambda (dep)
- (format #t "require_once '~a';~%" (find-php-dep inputs dep)))
- (append
- dependencies
- (if dev-dependencies?
- dependencies-dev
- '())))))))
+ (lambda (classmap)
+ (for-each
+ (lambda (file)
+ (invoke "php" (assoc-ref inputs "findclass.php")
+ "-i" (string-append vendor "/..") "-f" file))
+ (find-files classmap ".(php|hh|inc)$")))
+ (append
+ (composer-autoload-classmap autoload)
+ (if (and dev-dependencies? (not (null? autoload-dev)))
+ (composer-autoload-classmap autoload-dev)
+ '())))
+ (for-each
+ (lambda (file)
+ (format #t "require_once '~a/../~a';~%" vendor file))
+ (append
+ (composer-autoload-files autoload)
+ (if (and dev-dependencies? (not (null? autoload-dev)))
+ (composer-autoload-files autoload-dev)
+ '())))
+ (for-each
+ (lambda (dep)
+ (format
+ #t "require_once '~a';~%"
+ (search-input-file
+ inputs
+ (string-append "/share/web/" dep "/vendor/autoload_conf.php"))))
+ dependencies)
+ ;; Also add native-inputs that are not necessarily given in the
+ ;; composer.json. This allows to simply add a package in tests by
+ ;; adding it in native-inputs, without the need to patch composer.json.
+ (for-each
+ (match-lambda
+ ((name . loc)
+ (match (find-files loc "autoload_conf\\.php$")
+ (() #t)
+ (((? string? conf) . ())
+ (format #t "require_once '~a';~%" conf))
+ (_ #t)))
+ (_ #t))
+ (or inputs '()))))))
(define* (install #:key inputs outputs composer-file #:allow-other-keys)
"Install the given package."
@@ -237,7 +289,8 @@ (define %standard-phases
(delete 'build)
(delete 'check)
(replace 'install install)
- (add-after 'install 'check check)))
+ (add-after 'install 'check check)
+ (add-after 'install 'create-test-autoload create-test-autoload)))
(define* (composer-build #:key inputs (phases %standard-phases)
#:allow-other-keys #:rest args)
--
2.41.0
N
N
Nicolas Graves wrote on 7 Dec 2023 13:36
Re: [Nicolas Graves via Guix-patches via] [bug#42338] [PATCH v5 0/9] Composer build-system
(name . Ludovic Courtès)(address . ludo@gnu.org)
87o7f2xk8h.fsf@ngraves.fr
Just a quick reminder for this patch series. ;)

The right version is the v5 now, and I was asking for opinions on a
change of names too ;)

Cheers,

Nicolas


On 2023-11-02 22:51, Nicolas Graves wrote:

Toggle quote (82 lines)
> Sorry I did send the patch series twice because I forgot the v5 in the
> first.
>
> You can find the packages attached if useful for testing, but I will
> commit only after we agree on the proper renaming of the import and
> build-system, so that I can do it in a sole patch series.
>
>
>
> -------------------- Start of forwarded message --------------------
> Subject: [bug#42338] [PATCH v5 0/9] Composer build-system
> To: 42338@debbugs.gnu.org
> Cc: ngraves@ngraves.fr
> Date: Thu, 2 Nov 2023 16:16:47 +0100
> From: Nicolas Graves via Guix-patches via <guix-patches@gnu.org>
>
> This is the result of my further rework of the composer import and
> build-system. The `guix: import: composer` commits can be squashed
> easily.
>
> This is now tested on 94 php packages with all testing enabled except
> for 3 packages. I will submit these packages as a whole in the
> alphabetical order (the bootstrap order is not worth it IMO) in a new
> guix issue.
>
> Before accepting it, I also would like to propose a change of
> names. If me make an analogy with python:
> tool: pip <-> composer
> package hub: pypi <-> packagist
> build-system: python/pyproject <-> php
>
> Since we only take about 90 lines of real composer code, I would
> rather call the build-system php-build-system.
> Same thing: instead of `guix import composer` we should rather call
> `guix import packagist`.
>
> If that's OK, I'll change it with the next (and hopefully last!)
> version of this build system.
>
> Nicolas Graves (9):
> guix: import: Add composer importer.
> gnu: Add composer-classloader.
> guix: Add composer-build-system.
> guix: import: composer: Use memoization.
> guix: import: composer: Fix json->require.
> guix: import: composer: More robust string->license.
> guix: import: composer: Modern inputs formatting.
> guix: import: composer: Full rewrite composer-fetch.
> gnu: composer-build-system: Full check phase rewrite.
>
> Makefile.am | 6 +
> doc/guix.texi | 34 +++
> gnu/local.mk | 1 +
> gnu/packages/aux-files/findclass.php | 125 +++++++++++
> gnu/packages/php-xyz.scm | 60 ++++++
> guix/build-system/composer.scm | 164 +++++++++++++++
> guix/build/composer-build-system.scm | 300 +++++++++++++++++++++++++++
> guix/import/composer.scm | 267 ++++++++++++++++++++++++
> guix/scripts/import.scm | 2 +-
> guix/scripts/import/composer.scm | 107 ++++++++++
> tests/composer.scm | 88 ++++++++
> 11 files changed, 1153 insertions(+), 1 deletion(-)
> create mode 100644 gnu/packages/aux-files/findclass.php
> create mode 100644 gnu/packages/php-xyz.scm
> create mode 100644 guix/build-system/composer.scm
> create mode 100644 guix/build/composer-build-system.scm
> create mode 100644 guix/import/composer.scm
> create mode 100644 guix/scripts/import/composer.scm
> create mode 100644 tests/composer.scm
>
> --
> 2.41.0
>
>
>
>
> -------------------- End of forwarded message --------------------
>
> --
> Best regards,
> Nicolas Graves

--
Best regards,
Nicolas Graves
C
C
Charlie McMackin wrote on 9 Dec 2023 23:00
[PATCH] Add composer build system (PHP)
(address . 42338@debbugs.gnu.org)
CAO6UgkSO6wuQaXeyN9FsBtRqmxq661gV5CZSBt=vXizYJJuAWQ@mail.gmail.com
Hello,

I'm another user interested in this patch series. Thanks for carrying
it forward. I thought I would try it out myself and give feedback if I
discovered anything but I'm running into issues with the v5 patch
series:

1. When I run `git am -3` on the archive mbox for this patch series, I
have to skip patch 0 (empty) and then it fails on patch 0004 with;

Applying: guix: Add composer-build-system.
error: sha1 information is lacking or useless (Makefile.am).
error: could not build fake ancestor
Patch failed at 0004 guix: Add composer-build-system.

I'm trying to apply to a branch with HEAD at 61f2d84e75.

2. I am a bit new to applying patches from mail but I thought I could
resolve the problem if I knew where the branch began and applied
there. However, I am not able to find where this patch series branches
from. Should that information (the ancestor SHA1) be in the PATCH 0?
Is there something I'm missing with `git am` style patches?

3. Without any authority, making it `guix import packagist` sounds
reasonable to me given the existing patterns with other importers like
pypi and crate.

4. Do you plan to add a news.scm entry in the next patch series as
suggested by Ludovic?

I look forward to testing this out! Thanks,
Charlie
L
L
Ludovic Courtès wrote on 18 Dec 2023 23:33
Re: [bug#42338] [PATCH v5 0/9] Composer build-system
(name . Nicolas Graves)(address . ngraves@ngraves.fr)
87sf3zi1jc.fsf@gnu.org
Hi,

Nicolas Graves <ngraves@ngraves.fr> skribis:

Toggle quote (34 lines)
> This is the result of my further rework of the composer import and
> build-system. The `guix: import: composer` commits can be squashed
> easily.
>
> This is now tested on 94 php packages with all testing enabled except
> for 3 packages. I will submit these packages as a whole in the
> alphabetical order (the bootstrap order is not worth it IMO) in a new
> guix issue.
>
> Before accepting it, I also would like to propose a change of
> names. If me make an analogy with python:
> tool: pip <-> composer
> package hub: pypi <-> packagist
> build-system: python/pyproject <-> php
>
> Since we only take about 90 lines of real composer code, I would
> rather call the build-system php-build-system.
> Same thing: instead of `guix import composer` we should rather call
> `guix import packagist`.
>
> If that's OK, I'll change it with the next (and hopefully last!)
> version of this build system.
>
> Nicolas Graves (9):
> guix: import: Add composer importer.
> gnu: Add composer-classloader.
> guix: Add composer-build-system.
> guix: import: composer: Use memoization.
> guix: import: composer: Fix json->require.
> guix: import: composer: More robust string->license.
> guix: import: composer: Modern inputs formatting.
> guix: import: composer: Full rewrite composer-fetch.
> gnu: composer-build-system: Full check phase rewrite.

In the interest of moving forward, I pushed this:

6454788a5c build-system/composer: Do not import host-side Guile-JSON modules.
9dab758791 build-system: Add ‘composer-build-system’.
e8fd78d54e gnu: Add composer-classloader.
b7e3945283 guix: import: Add composer importer.

I squashed the importer commits.

However, I also add to make way too many fixes to my taste: adding
missing #:use-module, fixing unbound variables (guessing…), fixing
typos, untangling and build system commit that was fixing things in the
importer, fixing ‘tests/composer.scm’ which wouldn’t pass, fixing a case
where the importer would return a single value instead of two (breaking
recursive imports), and probably others that I forgot. Not great.

Could you please take a closer look and see whether anything is amiss at
this point?

Next, which PHP packages do we add? Julien initially submitted 30ish of
them, should we take those? Or are you planning to submit a separate
set?

It would also be nice if the updater would fill in the ‘inputs’ fields
of <upstream-source>: that would allow ‘guix refresh -u’ to
automatically update inputs.

Thanks in advance!

Ludo’.
N
N
Nicolas Graves wrote on 19 Dec 2023 08:43
(name . Ludovic Courtès)(address . ludo@gnu.org)
87plz24oy1.fsf@ngraves.fr
On 2023-12-18 23:33, Ludovic Courtès wrote:

Toggle quote (25 lines)
> Hi,
>
> Nicolas Graves <ngraves@ngraves.fr> skribis:
>
>> This is the result of my further rework of the composer import and
>> build-system. The `guix: import: composer` commits can be squashed
>> easily.
>>
>> This is now tested on 94 php packages with all testing enabled except
>> for 3 packages. I will submit these packages as a whole in the
>> alphabetical order (the bootstrap order is not worth it IMO) in a new
>> guix issue.
>>
>> Before accepting it, I also would like to propose a change of
>> names. If me make an analogy with python:
>> tool: pip <-> composer
>> package hub: pypi <-> packagist
>> build-system: python/pyproject <-> php

>>
>> Since we only take about 90 lines of real composer code, I would
>> rather call the build-system php-build-system.
>> Same thing: instead of `guix import composer` we should rather call
>> `guix import packagist`.

Do you have an opinion on this? I guess now that's in the code, we can
keep it as is, but that's sad we didn't get to discuss on this.

Toggle quote (34 lines)
>>
>> If that's OK, I'll change it with the next (and hopefully last!)
>> version of this build system.
>>
>> Nicolas Graves (9):
>> guix: import: Add composer importer.
>> gnu: Add composer-classloader.
>> guix: Add composer-build-system.
>> guix: import: composer: Use memoization.
>> guix: import: composer: Fix json->require.
>> guix: import: composer: More robust string->license.
>> guix: import: composer: Modern inputs formatting.
>> guix: import: composer: Full rewrite composer-fetch.
>> gnu: composer-build-system: Full check phase rewrite.
>
> In the interest of moving forward, I pushed this:
>
> 6454788a5c build-system/composer: Do not import host-side Guile-JSON modules.
> 9dab758791 build-system: Add ‘composer-build-system’.
> e8fd78d54e gnu: Add composer-classloader.
> b7e3945283 guix: import: Add composer importer.
>
> I squashed the importer commits.
>
> However, I also add to make way too many fixes to my taste: adding
> missing #:use-module, fixing unbound variables (guessing…), fixing
> typos, untangling and build system commit that was fixing things in the
> importer, fixing ‘tests/composer.scm’ which wouldn’t pass, fixing a case
> where the importer would return a single value instead of two (breaking
> recursive imports), and probably others that I forgot. Not great.
>
> Could you please take a closer look and see whether anything is amiss at
> this point?

Not great indeed, seemed to work fine on my end, will take a look. I
hope I didn't send a different patch series than intended.

Toggle quote (5 lines)
>
> Next, which PHP packages do we add? Julien initially submitted 30ish of
> them, should we take those? Or are you planning to submit a separate
> set?

I have a set of 94-97 packages, I've sent them in an email to you and
Julien (an email from ngraves@ngraves.fr on november 2nd), these should
work with this set of commits. Will cut that in commits and submit them
quickly.

Toggle quote (5 lines)
>
> It would also be nice if the updater would fill in the ‘inputs’ fields
> of <upstream-source>: that would allow ‘guix refresh -u’ to
> automatically update inputs.

I will first focus on fixes and packages.

Toggle quote (5 lines)
>
> Thanks in advance!
>
> Ludo’.

--
Best regards,
Nicolas Graves
W
W
Wilko Meyer wrote on 20 Dec 2023 11:41
[PATCH] Add composer build system (PHP)
(address . 42338@debbugs.gnu.org)
87il4t9m8u.fsf@wmeyer.eu
Hi,

Just wanted to say thanks for all this work, was really surprised to see
a composer-build-system in Guix and a handy packagist importer!

As far as I'm aware, there's not a structure in gnu/packages yet for
composer packages. Hope this is the right place to ask, I'm considering
packaging my more used dependencies for Guix, do they go into
php.scm/php-xyz.scm? a yet-to-be-created packagist.scm? Should there be
a more thematic grouping (e.g. how python*.scm is currently structured)?

Thanks for this great work!

--
Kind regards,

Wilko Meyer
w@wmeyer.eu
J
J
Julien Lepiller wrote on 20 Dec 2023 12:31
6DF3CCBA-7B74-4B1F-B2DD-98800C3D3C80@lepiller.eu
Hi,

I would put them in php-xyz.scm. php.scm would be for the compiler and language tools. If we start having a lot of php packages, we could start creating more modules.

I don't think packagist.scm would work, similar to how we have python.scm, not pypi.scm :)

Le 20 décembre 2023 11:41:55 GMT+01:00, Wilko Meyer <w@wmeyer.eu> a écrit :
Toggle quote (13 lines)
>Hi,
>
>Just wanted to say thanks for all this work, was really surprised to see
>a composer-build-system in Guix and a handy packagist importer!
>
>As far as I'm aware, there's not a structure in gnu/packages yet for
>composer packages. Hope this is the right place to ask, I'm considering
>packaging my more used dependencies for Guix, do they go into
>php.scm/php-xyz.scm? a yet-to-be-created packagist.scm? Should there be
>a more thematic grouping (e.g. how python*.scm is currently structured)?
>
>Thanks for this great work!
>
W
W
Wilko Meyer wrote on 20 Dec 2023 12:40
(name . Julien Lepiller)(address . julien@lepiller.eu)
87edfh9juy.fsf@wmeyer.eu
Hi Julien,

Julien Lepiller <julien@lepiller.eu> writes:

Toggle quote (2 lines)
> I would put them in php-xyz.scm. php.scm would be for the compiler and language tools. If we start having a lot of php packages, we could start creating more modules.

Sounds good!

Toggle quote (3 lines)
> I don't think packagist.scm would work, similar to how we have
> python.scm, not pypi.scm :)

We do have crates-io.scm and rust{,-apps}.scm for rust, which is why I
was asking (though I don't know the background of why crates-io.scm was
chosen for rust crates). But that may be more of an outlier then in the
structure of gnu/packages.

--
Kind regards,

Wilko Meyer
w@wmeyer.eu
?