~ruther/guix-local

5d4b411f8a3372455a8c92d10a28e88e9edba6eb — Ludovic Courtès 13 years ago 431a355
guix package: Add `--install-from-expression'.

* guix/scripts/package.scm (read/eval-package-expression): New
  procedure.
  (show-help): Add `-e'.
  (%options): Likewise.
  (guix-package)[process-actions]: Handle ('install . p) pairs, where P
  is a package.
* tests/guix-package.sh: Add `boot_make_drv'.  Use `-i $boot_make_drv'
  once, and then use `-e $boot_make'.
* doc/guix.texi (Invoking guix package): Document `-e'.
3 files changed, 67 insertions(+), 5 deletions(-)

M doc/guix.texi
M guix/scripts/package.scm
M tests/guix-package.sh
M doc/guix.texi => doc/guix.texi +13 -0
@@ 514,6 514,19 @@ Thus, when installing MPC, the MPFR and GMP libraries also get installed
in the profile; removing MPC also removes MPFR and GMP---unless they had
also been explicitly installed independently.

@item --install-from-expression=@var{exp}
@itemx -e @var{exp}
Install the package @var{exp} evaluates to.

@var{exp} must be a Scheme expression that evaluates to a
@code{<package>} object.  This option is notably useful to disambiguate
between same-named variants of a package, with expressions such as
@code{(@@ (gnu packages base) guile-final)}.

Note that this option installs the first output of the specified
package, which may be insufficient when needing a specific output of a
multiple-output package.

@item --remove=@var{package}
@itemx -r @var{package}
Remove @var{package}.

M guix/scripts/package.scm => guix/scripts/package.scm +44 -0
@@ 266,6 266,26 @@ matching packages."
                       (assoc-ref (derivation-outputs drv) sub-drv))))
         `(,name ,out))))))

(define (read/eval-package-expression str)
  "Read and evaluate STR and return the package it refers to, or exit an
error."
  (let ((exp (catch #t
               (lambda ()
                 (call-with-input-string str read))
               (lambda args
                 (leave (_ "failed to read expression ~s: ~s~%")
                        str args)))))
    (let ((p (catch #t
               (lambda ()
                 (eval exp the-scm-module))
               (lambda args
                 (leave (_ "failed to evaluate expression `~a': ~s~%")
                        exp args)))))
      (if (package? p)
          p
          (leave (_ "expression `~s' does not evaluate to a package~%")
                 exp)))))


;;;
;;; Command-line options.


@@ 281,6 301,9 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
  (display (_ "
  -i, --install=PACKAGE  install PACKAGE"))
  (display (_ "
  -e, --install-from-expression=EXP
                         install the package EXP evaluates to"))
  (display (_ "
  -r, --remove=PACKAGE   remove PACKAGE"))
  (display (_ "
  -u, --upgrade=REGEXP   upgrade all the installed packages matching REGEXP"))


@@ 325,6 348,10 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
        (option '(#\i "install") #t #f
                (lambda (opt name arg result)
                  (alist-cons 'install arg result)))
        (option '(#\e "install-from-expression") #t #f
                (lambda (opt name arg result)
                  (alist-cons 'install (read/eval-package-expression arg)
                              result)))
        (option '(#\r "remove") #t #f
                (lambda (opt name arg result)
                  (alist-cons 'remove arg result)))


@@ 490,6 517,19 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))

      (delete-duplicates (map input->name+path deps) same?))

    (define (package->tuple p)
      (let ((path (package-derivation (%store) p))
            (deps (package-transitive-propagated-inputs p)))
        `(,(package-name p)
          ,(package-version p)

          ;; When given a package via `-e', install the first of its
          ;; outputs (XXX).
          ,(car (package-outputs p))

          ,path
          ,(canonicalize-deps deps))))

    ;; First roll back if asked to.
    (if (and (assoc-ref opts 'roll-back?) (not dry-run?))
        (begin


@@ 515,6 555,8 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
               (install  (append
                          upgrade
                          (filter-map (match-lambda
                                       (('install . (? package? p))
                                        #f)
                                       (('install . (? store-path?))
                                        #f)
                                       (('install . package)


@@ 530,6 572,8 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
                                     install))
               (install* (append
                          (filter-map (match-lambda
                                       (('install . (? package? p))
                                        (package->tuple p))
                                       (('install . (? store-path? path))
                                        (let-values (((name version)
                                                      (package-name->name+version

M tests/guix-package.sh => tests/guix-package.sh +10 -5
@@ 33,6 33,10 @@ rm -f "$profile"

trap 'rm "$profile" "$profile-"[0-9]* ; rm -rf t-home-'"$$" EXIT

# Use `-e' with a non-package expression.
if guix package --bootstrap -e +;
then false; else true; fi

guix package --bootstrap -p "$profile" -i guile-bootstrap
test -L "$profile" && test -L "$profile-1-link"
test -f "$profile/bin/guile"


@@ 46,8 50,9 @@ test -f "$profile/bin/guile"
# Check whether we have network access.
if guile -c '(getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)' 2> /dev/null
then
    boot_make="`guix build -e '(@@ (gnu packages base) gnu-make-boot0)'`"
    guix package --bootstrap -p "$profile" -i "$boot_make"
    boot_make="(@@ (gnu packages base) gnu-make-boot0)"
    boot_make_drv="`guix build -e "$boot_make"`"
    guix package --bootstrap -p "$profile" -i "$boot_make_drv"
    test -L "$profile-2-link"
    test -f "$profile/bin/make" && test -f "$profile/bin/guile"



@@ 94,7 99,7 @@ then
    done

    # Reinstall after roll-back to the empty profile.
    guix package --bootstrap -p "$profile" -i "$boot_make"
    guix package --bootstrap -p "$profile" -e "$boot_make"
    test "`readlink_base "$profile"`" = "$profile-1-link"
    test -x "$profile/bin/guile" && ! test -x "$profile/bin/make"



@@ 104,7 109,7 @@ then
    test -x "$profile/bin/guile" && ! test -x "$profile/bin/make"

    # Install Make.
    guix package --bootstrap -p "$profile" -i "$boot_make"
    guix package --bootstrap -p "$profile" -e "$boot_make"
    test "`readlink_base "$profile"`" = "$profile-2-link"
    test -x "$profile/bin/guile" && test -x "$profile/bin/make"



@@ 145,7 150,7 @@ test -f "$HOME/.guix-profile/bin/guile"

if guile -c '(getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)' 2> /dev/null
then
    guix package --bootstrap -i "$boot_make"
    guix package --bootstrap -e "$boot_make"
    test -f "$HOME/.guix-profile/bin/make"
    first_environment="`cd $HOME/.guix-profile ; pwd`"