;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2019 Julien Lepiller ;;; ;;; This file is part of GNU Guix. ;;; ;;; GNU Guix is free software; you can redistribute it and/or modify it ;;; under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 3 of the License, or (at ;;; your option) any later version. ;;; ;;; GNU Guix is distributed in the hope that it will be useful, but ;;; WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with GNU Guix. If not, see . (define-module (guix 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 _ (display " $path) { $loader->set($namespace, $path); } foreach ($psr4map as $namespace => $path) { $loader->setPsr4($namespace, $path); } $loader->addClassMap($classmap); $loader->register(); "))) (let* ((package-data (read-package-data #:filename composer-file)) (autoload (match (assoc-ref package-data "autoload") (('@ autoload ...) autoload) (#f '()))) (autoload-dev (match (assoc-ref package-data "autoload-dev") (('@ autoload-dev ...) autoload-dev) (#f '()))) (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 '())))))) (with-output-to-file (string-append vendor "/autoload_conf.php") (lambda _ (format #t "