aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Bakke <mbakke@fastmail.com>2019-07-07 01:18:18 +0200
committerMarius Bakke <mbakke@fastmail.com>2019-07-07 01:18:18 +0200
commit36175a3a9eb5bd4096de4e06e1f6b0e8cd895d84 (patch)
tree7c2d8dd2267b2dc533d5f59acc137641e2325e52
parent42dcfca4cc424aa790d8fb62eb327782fd08aad7 (diff)
parentc72647fbae675654e32e17a6891980a7b9272a71 (diff)
downloadpatches-36175a3a9eb5bd4096de4e06e1f6b0e8cd895d84.tar
patches-36175a3a9eb5bd4096de4e06e1f6b0e8cd895d84.tar.gz
Merge branch 'master' into staging
-rw-r--r--Makefile.am3
-rw-r--r--doc/guix.texi114
-rw-r--r--gnu/build/linux-container.scm7
-rw-r--r--gnu/ci.scm6
-rw-r--r--gnu/local.mk6
-rw-r--r--gnu/machine.scm107
-rw-r--r--gnu/machine/ssh.scm369
-rw-r--r--gnu/packages/bioinformatics.scm6
-rw-r--r--gnu/packages/dictionaries.scm4
-rw-r--r--gnu/packages/gnome.scm2
-rw-r--r--gnu/packages/guile-xyz.scm2
-rw-r--r--gnu/packages/image.scm30
-rw-r--r--gnu/packages/lisp.scm501
-rw-r--r--gnu/packages/logo.scm71
-rw-r--r--gnu/packages/patchutils.scm4
-rw-r--r--gnu/packages/photo.scm8
-rw-r--r--gnu/packages/pulseaudio.scm58
-rw-r--r--gnu/packages/python-xyz.scm118
-rw-r--r--gnu/packages/serialization.scm14
-rw-r--r--gnu/packages/wine.scm6
-rw-r--r--gnu/tests/docker.scm18
-rw-r--r--gnu/tests/install.scm2
-rw-r--r--gnu/tests/singularity.scm18
-rw-r--r--guix/channels.scm43
-rw-r--r--guix/derivations.scm115
-rw-r--r--guix/docker.scm17
-rw-r--r--guix/gexp.scm240
-rw-r--r--guix/inferior.scm9
-rw-r--r--guix/remote.scm134
-rw-r--r--guix/repl.scm86
-rw-r--r--guix/scripts/deploy.scm84
-rw-r--r--guix/scripts/pack.scm64
-rw-r--r--guix/scripts/repl.scm56
-rw-r--r--guix/ssh.scm10
-rw-r--r--guix/store.scm11
-rw-r--r--guix/ui.scm15
-rw-r--r--po/guix/POTFILES.in2
-rw-r--r--tests/derivations.scm29
-rw-r--r--tests/gexp.scm37
39 files changed, 2148 insertions, 278 deletions
diff --git a/Makefile.am b/Makefile.am
index 8adf23c699..c5dcf4113e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -90,6 +90,7 @@ MODULES = \
guix/nar.scm \
guix/derivations.scm \
guix/grafts.scm \
+ guix/repl.scm \
guix/inferior.scm \
guix/describe.scm \
guix/channels.scm \
@@ -266,6 +267,7 @@ MODULES = \
guix/scripts/weather.scm \
guix/scripts/container.scm \
guix/scripts/container/exec.scm \
+ guix/scripts/deploy.scm \
guix.scm \
$(GNU_SYSTEM_MODULES)
@@ -273,6 +275,7 @@ if HAVE_GUILE_SSH
MODULES += \
guix/ssh.scm \
+ guix/remote.scm \
guix/scripts/copy.scm \
guix/store/ssh.scm
diff --git a/doc/guix.texi b/doc/guix.texi
index 1794c6cd5a..0b50482530 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -65,6 +65,7 @@ Copyright @copyright{} 2018 Alex Vong@*
Copyright @copyright{} 2019 Josh Holland@*
Copyright @copyright{} 2019 Diego Nicola Barbato@*
Copyright @copyright{} 2019 Ivan Petkov@*
+Copyright @copyright{} 2019 Jakob L. Kreuze@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -81,6 +82,7 @@ Documentation License''.
* guix gc: (guix)Invoking guix gc. Reclaiming unused disk space.
* guix pull: (guix)Invoking guix pull. Update the list of available packages.
* guix system: (guix)Invoking guix system. Manage the operating system configuration.
+* guix deploy: (guix)Invoking guix deploy. Manage operating system configurations for remote hosts.
@end direntry
@dircategory Software development
@@ -269,6 +271,7 @@ System Configuration
* Initial RAM Disk:: Linux-Libre bootstrapping.
* Bootloader Configuration:: Configuring the boot loader.
* Invoking guix system:: Instantiating a system configuration.
+* Invoking guix deploy:: Deploying a system configuration to a remote host.
* Running Guix in a VM:: How to run Guix System in a virtual machine.
* Defining Services:: Adding new service definitions.
@@ -10296,6 +10299,7 @@ instance to support new system services.
* Initial RAM Disk:: Linux-Libre bootstrapping.
* Bootloader Configuration:: Configuring the boot loader.
* Invoking guix system:: Instantiating a system configuration.
+* Invoking guix deploy:: Deploying a system configuration to a remote host.
* Running Guix in a VM:: How to run Guix System in a virtual machine.
* Defining Services:: Adding new service definitions.
@end menu
@@ -25392,6 +25396,116 @@ example graph.
@end table
+@node Invoking guix deploy
+@section Invoking @code{guix deploy}
+
+We've already seen @code{operating-system} declarations used to manage a
+machine's configuration locally. Suppose you need to configure multiple
+machines, though---perhaps you're managing a service on the web that's
+comprised of several servers. @command{guix deploy} enables you to use those
+same @code{operating-system} declarations to manage multiple remote hosts at
+once as a logical ``deployment''.
+
+@quotation Note
+The functionality described in this section is still under development
+and is subject to change. Get in touch with us on
+@email{guix-devel@@gnu.org}!
+@end quotation
+
+@example
+guix deploy @var{file}
+@end example
+
+Such an invocation will deploy the machines that the code within @var{file}
+evaluates to. As an example, @var{file} might contain a definition like this:
+
+@example
+;; This is a Guix deployment of a "bare bones" setup, with
+;; no X11 display server, to a machine with an SSH daemon
+;; listening on localhost:2222. A configuration such as this
+;; may be appropriate for virtual machine with ports
+;; forwarded to the host's loopback interface.
+
+(use-service-modules networking ssh)
+(use-package-modules bootloaders)
+
+(define %system
+ (operating-system
+ (host-name "gnu-deployed")
+ (timezone "Etc/UTC")
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (target "/dev/vda")
+ (terminal-outputs '(console))))
+ (file-systems (cons (file-system
+ (mount-point "/")
+ (device "/dev/vda1")
+ (type "ext4"))
+ %base-file-systems))
+ (services
+ (append (list (service dhcp-client-service-type)
+ (service openssh-service-type
+ (openssh-configuration
+ (permit-root-login #t)
+ (allow-empty-passwords? #t))))
+ %base-services))))
+
+(list (machine
+ (system %system)
+ (environment managed-host-environment-type)
+ (configuration (machine-ssh-configuration
+ (host-name "localhost")
+ (identity "./id_rsa")
+ (port 2222)))))
+@end example
+
+The file should evaluate to a list of @var{machine} objects. This example,
+upon being deployed, will create a new generation on the remote system
+realizing the @code{operating-system} declaration @var{%system}.
+@var{environment} and @var{configuration} specify how the machine should be
+provisioned---that is, how the computing resources should be created and
+managed. The above example does not create any resources, as a
+@code{'managed-host} is a machine that is already running the Guix system and
+available over the network. This is a particularly simple case; a more
+complex deployment may involve, for example, starting virtual machines through
+a Virtual Private Server (VPS) provider. In such a case, a different
+@var{environment} type would be used.
+
+@deftp {Data Type} machine
+This is the data type representing a single machine in a heterogeneous Guix
+deployment.
+
+@table @asis
+@item @code{system}
+The object of the operating system configuration to deploy.
+
+@item @code{environment}
+An @code{environment-type} describing how the machine should be provisioned.
+At the moment, the only supported value is
+@code{managed-host-environment-type}.
+
+@item @code{configuration} (default: @code{#f})
+An object describing the configuration for the machine's @code{environment}.
+If the @code{environment} has a default configuration, @code{#f} maybe used.
+If @code{#f} is used for an environment with no default configuration,
+however, an error will be thrown.
+@end table
+@end deftp
+
+@deftp {Data Type} machine-ssh-configuration
+This is the data type representing the SSH client parameters for a machine
+with an @code{environment} of @code{managed-host-environment-type}.
+
+@table @asis
+@item @code{host-name}
+@item @code{port} (default: @code{22})
+@item @code{user} (default: @code{"root"})
+@item @code{identity} (default: @code{#f})
+If specified, the path to the SSH private key to use to authenticate with the
+remote host.
+@end table
+@end deftp
+
@node Running Guix in a VM
@section Running Guix in a Virtual Machine
diff --git a/gnu/build/linux-container.scm b/gnu/build/linux-container.scm
index e86ac606c0..6ccb924861 100644
--- a/gnu/build/linux-container.scm
+++ b/gnu/build/linux-container.scm
@@ -130,9 +130,14 @@ for the process."
"/dev/random"
"/dev/urandom"
"/dev/tty"
- "/dev/ptmx"
"/dev/fuse"))
+ ;; Mount a new devpts instance on /dev/pts.
+ (when (file-exists? "/dev/ptmx")
+ (mount* "none" (scope "/dev/pts") "devpts" 0
+ "newinstance,mode=0620")
+ (symlink "/dev/pts/ptmx" (scope "/dev/ptmx")))
+
;; Setup the container's /dev/console by bind mounting the pseudo-terminal
;; associated with standard input when there is one.
(let* ((in (current-input-port))
diff --git a/gnu/ci.scm b/gnu/ci.scm
index e108b4b15b..4885870e16 100644
--- a/gnu/ci.scm
+++ b/gnu/ci.scm
@@ -193,9 +193,11 @@ system.")
(define channel-build-system
;; Build system used to "convert" a channel instance to a package.
(let* ((build (lambda* (store name inputs
- #:key instance #:allow-other-keys)
+ #:key instance system
+ #:allow-other-keys)
(run-with-store store
- (channel-instances->derivation (list instance)))))
+ (channel-instances->derivation (list instance))
+ #:system system)))
(lower (lambda* (name #:key system instance #:allow-other-keys)
(bag
(name name)
diff --git a/gnu/local.mk b/gnu/local.mk
index 6e90d88689..68a43330c4 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -299,6 +299,7 @@ GNU_SYSTEM_MODULES = \
%D%/packages/llvm.scm \
%D%/packages/lout.scm \
%D%/packages/logging.scm \
+ %D%/packages/logo.scm \
%D%/packages/lolcode.scm \
%D%/packages/lsof.scm \
%D%/packages/lua.scm \
@@ -564,6 +565,9 @@ GNU_SYSTEM_MODULES = \
%D%/system/uuid.scm \
%D%/system/vm.scm \
\
+ %D%/machine.scm \
+ %D%/machine/ssh.scm \
+ \
%D%/build/accounts.scm \
%D%/build/activation.scm \
%D%/build/bootloader.scm \
@@ -629,7 +633,7 @@ INSTALLER_MODULES = \
%D%/installer/newt/user.scm \
%D%/installer/newt/utils.scm \
%D%/installer/newt/welcome.scm \
- %D%/installer/newt/wifi.scm
+ %D%/installer/newt/wifi.scm
# Always ship the installer modules but compile them only when
# ENABLE_INSTALLER is true.
diff --git a/gnu/machine.scm b/gnu/machine.scm
new file mode 100644
index 0000000000..0b79402b0a
--- /dev/null
+++ b/gnu/machine.scm
@@ -0,0 +1,107 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 David Thompson <davet@gnu.org>
+;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
+;;;
+;;; 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 machine)
+ #:use-module (gnu system)
+ #:use-module (guix derivations)
+ #:use-module (guix monads)
+ #:use-module (guix records)
+ #:use-module (guix store)
+ #:use-module ((guix utils) #:select (source-properties->location))
+ #:export (environment-type
+ environment-type?
+ environment-type-name
+ environment-type-description
+ environment-type-location
+
+ machine
+ machine?
+ this-machine
+
+ machine-system
+ machine-environment
+ machine-configuration
+ machine-display-name
+
+ deploy-machine
+ machine-remote-eval))
+
+;;; Commentary:
+;;;
+;;; This module provides the types used to declare individual machines in a
+;;; heterogeneous Guix deployment. The interface allows users of specify system
+;;; configurations and the means by which resources should be provisioned on a
+;;; per-host basis.
+;;;
+;;; Code:
+
+
+;;;
+;;; Declarations for resources that can be provisioned.
+;;;
+
+(define-record-type* <environment-type> environment-type
+ make-environment-type
+ environment-type?
+
+ ;; Interface to the environment type's deployment code. Each procedure
+ ;; should take the same arguments as the top-level procedure of this file
+ ;; that shares the same name. For example, 'machine-remote-eval' should be
+ ;; of the form '(machine-remote-eval machine exp)'.
+ (machine-remote-eval environment-type-machine-remote-eval) ; procedure
+ (deploy-machine environment-type-deploy-machine) ; procedure
+
+ ;; Metadata.
+ (name environment-type-name) ; symbol
+ (description environment-type-description ; string
+ (default #f))
+ (location environment-type-location ; <location>
+ (default (and=> (current-source-location)
+ source-properties->location))
+ (innate)))
+
+
+;;;
+;;; Declarations for machines in a deployment.
+;;;
+
+(define-record-type* <machine> machine
+ make-machine
+ machine?
+ this-machine
+ (system machine-system) ; <operating-system>
+ (environment machine-environment) ; symbol
+ (configuration machine-configuration ; configuration object
+ (default #f))) ; specific to environment
+
+(define (machine-display-name machine)
+ "Return the host-name identifying MACHINE."
+ (operating-system-host-name (machine-system machine)))
+
+(define (machine-remote-eval machine exp)
+ "Evaluate EXP, a gexp, on MACHINE. Ensure that all the elements EXP refers to
+are built and deployed to MACHINE beforehand."
+ (let ((environment (machine-environment machine)))
+ ((environment-type-machine-remote-eval environment) machine exp)))
+
+(define (deploy-machine machine)
+ "Monadic procedure transferring the new system's OS closure to the remote
+MACHINE, activating it on MACHINE and switching MACHINE to the new generation."
+ (let ((environment (machine-environment machine)))
+ ((environment-type-deploy-machine environment) machine)))
diff --git a/gnu/machine/ssh.scm b/gnu/machine/ssh.scm
new file mode 100644
index 0000000000..a7d1a967ae
--- /dev/null
+++ b/gnu/machine/ssh.scm
@@ -0,0 +1,369 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
+;;;
+;;; 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 machine ssh)
+ #:use-module (gnu bootloader)
+ #:use-module (gnu machine)
+ #:autoload (gnu packages gnupg) (guile-gcrypt)
+ #:use-module (gnu services)
+ #:use-module (gnu services shepherd)
+ #:use-module (gnu system)
+ #:use-module (guix derivations)
+ #:use-module (guix gexp)
+ #:use-module (guix i18n)
+ #:use-module (guix modules)
+ #:use-module (guix monads)
+ #:use-module (guix records)
+ #:use-module (guix remote)
+ #:use-module (guix ssh)
+ #:use-module (guix store)
+ #:use-module (ice-9 match)
+ #:use-module (srfi srfi-19)
+ #:use-module (srfi srfi-35)
+ #:export (managed-host-environment-type
+
+ machine-ssh-configuration
+ machine-ssh-configuration?
+ machine-ssh-configuration
+
+ machine-ssh-configuration-host-name
+ machine-ssh-configuration-port
+ machine-ssh-configuration-user
+ machine-ssh-configuration-session))
+
+;;; Commentary:
+;;;
+;;; This module implements remote evaluation and system deployment for
+;;; machines that are accessable over SSH and have a known host-name. In the
+;;; sense of the broader "machine" interface, we describe the environment for
+;;; such machines as 'managed-host.
+;;;
+;;; Code:
+
+
+;;;
+;;; Parameters for the SSH client.
+;;;
+
+(define-record-type* <machine-ssh-configuration> machine-ssh-configuration
+ make-machine-ssh-configuration
+ machine-ssh-configuration?
+ this-machine-ssh-configuration
+ (host-name machine-ssh-configuration-host-name) ; string
+ (port machine-ssh-configuration-port ; integer
+ (default 22))
+ (user machine-ssh-configuration-user ; string
+ (default "root"))
+ (identity machine-ssh-configuration-identity ; path to a private key
+ (default #f))
+ (session machine-ssh-configuration-session ; session
+ (default #f)))
+
+(define (machine-ssh-session machine)
+ "Return the SSH session that was given in MACHINE's configuration, or create
+one from the configuration's parameters if one was not provided."
+ (maybe-raise-unsupported-configuration-error machine)
+ (let ((config (machine-configuration machine)))
+ (or (machine-ssh-configuration-session config)
+ (let ((host-name (machine-ssh-configuration-host-name config))
+ (user (machine-ssh-configuration-user config))
+ (port (machine-ssh-configuration-port config))
+ (identity (machine-ssh-configuration-identity config)))
+ (open-ssh-session host-name
+ #:user user
+ #:port port
+ #:identity identity)))))
+
+
+;;;
+;;; Remote evaluation.
+;;;
+
+(define (managed-host-remote-eval machine exp)
+ "Internal implementation of 'machine-remote-eval' for MACHINE instances with
+an environment type of 'managed-host."
+ (maybe-raise-unsupported-configuration-error machine)
+ (remote-eval exp (machine-ssh-session machine)))
+
+
+;;;
+;;; System deployment.
+;;;
+
+(define (switch-to-system machine)
+ "Monadic procedure creating a new generation on MACHINE and execute the
+activation script for the new system configuration."
+ (define (remote-exp drv script)
+ (with-extensions (list guile-gcrypt)
+ (with-imported-modules (source-module-closure '((guix config)
+ (guix profiles)
+ (guix utils)))
+ #~(begin
+ (use-modules (guix config)
+ (guix profiles)
+ (guix utils))
+
+ (define %system-profile
+ (string-append %state-directory "/profiles/system"))
+
+ (let* ((system #$drv)
+ (number (1+ (generation-number %system-profile)))
+ (generation (generation-file-name %system-profile number)))
+ (switch-symlinks generation system)
+ (switch-symlinks %system-profile generation)
+ ;; The implementation of 'guix system reconfigure' saves the
+ ;; load path and environment here. This is unnecessary here
+ ;; because each invocation of 'remote-eval' runs in a distinct
+ ;; Guile REPL.
+ (setenv "GUIX_NEW_SYSTEM" system)
+ ;; The activation script may write to stdout, which confuses
+ ;; 'remote-eval' when it attempts to read a result from the
+ ;; remote REPL. We work around this by forcing the output to a
+ ;; string.
+ (with-output-to-string
+ (lambda ()
+ (primitive-load #$script))))))))
+
+ (let* ((os (machine-system machine))
+ (script (operating-system-activation-script os)))
+ (mlet* %store-monad ((drv (operating-system-derivation os)))
+ (machine-remote-eval machine (remote-exp drv script)))))
+
+;; XXX: Currently, this does NOT attempt to restart running services. This is
+;; also the case with 'guix system reconfigure'.
+;;
+;; See <https://issues.guix.info/issue/33508>.
+(define (upgrade-shepherd-services machine)
+ "Monadic procedure unloading and starting services on the remote as needed
+to realize the MACHINE's system configuration."
+ (define target-services
+ ;; Monadic expression evaluating to a list of (name output-path) pairs for
+ ;; all of MACHINE's services.
+ (mapm %store-monad
+ (lambda (service)
+ (mlet %store-monad ((file ((compose lower-object
+ shepherd-service-file)
+ service)))
+ (return (list (shepherd-service-canonical-name service)
+ (derivation->output-path file)))))
+ (service-value
+ (fold-services (operating-system-services (machine-system machine))
+ #:target-type shepherd-root-service-type))))
+
+ (define (remote-exp target-services)
+ (with-imported-modules '((gnu services herd))
+ #~(begin
+ (use-modules (gnu services herd)
+ (srfi srfi-1))
+
+ (define running
+ (filter live-service-running (current-services)))
+
+ (define (essential? service)
+ ;; Return #t if SERVICE is essential and should not be unloaded
+ ;; under any circumstance.
+ (memq (first (live-service-provision service))
+ '(root shepherd)))
+
+ (define (obsolete? service)
+ ;; Return #t if SERVICE can be safely unloaded.
+ (and (not (essential? service))
+ (every (lambda (requirements)
+ (not (memq (first (live-service-provision service))
+ requirements)))
+ (map live-service-requirement running))))
+
+ (define to-unload
+ (filter obsolete?
+ (remove (lambda (service)
+ (memq (first (live-service-provision service))
+ (map first '#$target-services)))
+ running)))
+
+ (define to-start
+ (remove (lambda (service-pair)
+ (memq (first service-pair)
+ (map (compose first live-service-provision)
+ running)))
+ '#$target-services))
+
+ ;; Unload obsolete services.
+ (for-each (lambda (service)
+ (false-if-exception
+ (unload-service service)))
+ to-unload)
+
+ ;; Load the service files for any new services and start them.
+ (load-services/safe (map second to-start))
+ (for-each start-service (map first to-start))
+
+ #t)))
+
+ (mlet %store-monad ((target-services target-services))
+ (machine-remote-eval machine (remote-exp target-services))))
+
+(define (machine-boot-parameters machine)
+ "Monadic procedure returning a list of 'boot-parameters' for the generations
+of MACHINE's system profile, ordered from most recent to oldest."
+ (define bootable-kernel-arguments
+ (@@ (gnu system) bootable-kernel-arguments))
+
+ (define remote-exp
+ (with-extensions (list guile-gcrypt)
+ (with-imported-modules (source-module-closure '((guix config)
+ (guix profiles)))
+ #~(begin
+ (use-modules (guix config)
+ (guix profiles)
+ (ice-9 textual-ports))
+
+ (define %system-profile
+ (string-append %state-directory "/profiles/system"))
+
+ (define (read-file path)
+ (call-with-input-file path
+ (lambda (port)
+ (get-string-all port))))
+
+ (map (lambda (generation)
+ (let* ((system-path (generation-file-name %system-profile
+ generation))
+ (boot-parameters-path (string-append system-path
+ "/parameters"))
+ (time (stat:mtime (lstat system-path))))
+ (list generation
+ system-path
+ time
+ (read-file boot-parameters-path))))
+ (reverse (generation-numbers %system-profile)))))))
+
+ (mlet* %store-monad ((generations (machine-remote-eval machine remote-exp)))
+ (return
+ (map (lambda (generation)
+ (match generation
+ ((generation system-path time serialized-params)
+ (let* ((params (call-with-input-string serialized-params
+ read-boot-parameters))
+ (root (boot-parameters-root-device params))
+ (label (boot-parameters-label params)))
+ (boot-parameters
+ (inherit params)
+ (label
+ (string-append label " (#"
+ (number->string generation) ", "
+ (let ((time (make-time time-utc 0 time)))
+ (date->string (time-utc->date time)
+ "~Y-~m-~d ~H:~M"))
+ ")"))
+ (kernel-arguments
+ (append (bootable-kernel-arguments system-path root)
+ (boot-parameters-kernel-arguments params))))))))
+ generations))))
+
+(define (install-bootloader machine)
+ "Create a bootloader entry for the new system generation on MACHINE, and
+configure the bootloader to boot that generation by default."
+ (define bootloader-installer-script
+ (@@ (guix scripts system) bootloader-installer-script))
+
+ (define (remote-exp installer bootcfg bootcfg-file)
+ (with-extensions (list guile-gcrypt)
+ (with-imported-modules (source-module-closure '((gnu build install)
+ (guix store)
+ (guix utils)))
+ #~(begin
+ (use-modules (gnu build install)
+ (guix store)
+ (guix utils))
+ (let* ((gc-root (string-append "/" %gc-roots-directory "/bootcfg"))
+ (temp-gc-root (string-append gc-root ".new")))
+
+ (switch-symlinks temp-gc-root gc-root)
+
+ (unless (false-if-exception
+ (begin
+ ;; The implementation of 'guix system reconfigure'
+ ;; saves the load path here. This is unnecessary here
+ ;; because each invocation of 'remote-eval' runs in a
+ ;; distinct Guile REPL.
+ (install-boot-config #$bootcfg #$bootcfg-file "/")
+ ;; The installation script may write to stdout, which
+ ;; confuses 'remote-eval' when it attempts to read a
+ ;; result from the remote REPL. We work around this
+ ;; by forcing the output to a string.
+ (with-output-to-string
+ (lambda ()
+ (primitive-load #$installer)))))
+ (delete-file temp-gc-root)
+ (error "failed to install bootloader"))
+
+ (rename-file temp-gc-root gc-root)
+ #t)))))
+
+ (mlet* %store-monad ((boot-parameters (machine-boot-parameters machine)))
+ (let* ((os (machine-system machine))
+ (bootloader ((compose bootloader-configuration-bootloader
+ operating-system-bootloader)
+ os))
+ (bootloader-target (bootloader-configuration-target
+ (operating-system-bootloader os)))
+ (installer (bootloader-installer-script
+ (bootloader-installer bootloader)
+ (bootloader-package bootloader)
+ bootloader-target
+ "/"))
+ (menu-entries (map boot-parameters->menu-entry boot-parameters))
+ (bootcfg (operating-system-bootcfg os menu-entries))
+ (bootcfg-file (bootloader-configuration-file bootloader)))
+ (machine-remote-eval machine (remote-exp installer bootcfg bootcfg-file)))))
+
+(define (deploy-managed-host machine)
+ "Internal implementation of 'deploy-machine' for MACHINE instances with an
+environment type of 'managed-host."
+ (maybe-raise-unsupported-configuration-error machine)
+ (mbegin %store-monad
+ (switch-to-system machine)
+ (upgrade-shepherd-services machine)
+ (install-bootloader machine)))
+
+
+;;;
+;;; Environment type.
+;;;
+
+(define managed-host-environment-type
+ (environment-type
+ (machine-remote-eval managed-host-remote-eval)
+ (deploy-machine deploy-managed-host)
+ (name 'managed-host-environment-type)
+ (description "Provisioning for machines that are accessable over SSH
+and have a known host-name. This entails little more than maintaining an SSH
+connection to the host.")))
+
+(define (maybe-raise-unsupported-configuration-error machine)
+ "Raise an error if MACHINE's configuration is not an instance of
+<machine-ssh-configuration>."
+ (let ((config (machine-configuration machine))
+ (environment (environment-type-name (machine-environment machine))))
+ (unless (and config (machine-ssh-configuration? config))
+ (raise (condition
+ (&message
+ (message (format #f (G_ "unsupported machine configuration '~a'
+for environment of type '~a'")
+ config
+ environment))))))))
diff --git a/gnu/packages/bioinformatics.scm b/gnu/packages/bioinformatics.scm
index 9a30a0eaff..f8ac41c249 100644
--- a/gnu/packages/bioinformatics.scm
+++ b/gnu/packages/bioinformatics.scm
@@ -14069,11 +14069,11 @@ choosing which reads pass the filter.")
;; <https://github.com/jts/nanopolish#installing-a-particular-release>.
;; Also, the differences between release and current version seem to be
;; significant.
- (let ((commit "50e8b5cc62f9b46f5445f5c5e8c5ab7263ea6d9d")
+ (let ((commit "6331dc4f15b9dfabb954ba3fae9d76b6c3ca6377")
(revision "1"))
(package
(name "nanopolish")
- (version (git-version "0.10.2" revision commit))
+ (version (git-version "0.11.1" revision commit))
(source
(origin
(method git-fetch)
@@ -14083,7 +14083,7 @@ choosing which reads pass the filter.")
(recursive? #t)))
(file-name (git-file-name name version))
(sha256
- (base32 "09j5gz57yr9i34a27vbl72i4g8syv2zzgmsfyjq02yshmnrvkjs6"))
+ (base32 "15ikl3d37y49pwd7vx36xksgsqajhf24q7qqsnpl15dqqyy5qgbc"))
(modules '((guix build utils)))
(snippet
'(begin
diff --git a/gnu/packages/dictionaries.scm b/gnu/packages/dictionaries.scm
index 9f4dc59cc8..d3a3f8d832 100644
--- a/gnu/packages/dictionaries.scm
+++ b/gnu/packages/dictionaries.scm
@@ -218,7 +218,7 @@ It comes with a German-English dictionary with approximately 270,000 entries.")
(define-public grammalecte
(package
(name "grammalecte")
- (version "1.1.1")
+ (version "1.2")
(source
(origin
(method url-fetch/zipbomb)
@@ -226,7 +226,7 @@ It comes with a German-English dictionary with approximately 270,000 entries.")
"Grammalecte-fr-v" version ".zip"))
(sha256
(base32
- "1al4c3976wgxijxghxqb1banarj82hwad51kln87xj2r5kwcfm05"))))
+ "0dwizai6w9yn617y7cnqdiwv77vn22p18s9sypypbl1bl695cnma"))))
(build-system python-build-system)
(home-page "https://grammalecte.net")
(synopsis "French spelling and grammar checker")
diff --git a/gnu/packages/gnome.scm b/gnu/packages/gnome.scm
index 2820be0022..88d293ee9f 100644
--- a/gnu/packages/gnome.scm
+++ b/gnu/packages/gnome.scm
@@ -7232,7 +7232,7 @@ is suitable as a default application in a Desktop environment.")
("intltool" ,intltool)
("pkg-config" ,pkg-config)))
(inputs
- `(("gtksourceview" ,gtksourceview)
+ `(("gtksourceview" ,gtksourceview-3)
("libsm" ,libsm)))
(home-page "https://wiki.gnome.org/Apps/Xpad")
(synopsis "Virtual sticky note")
diff --git a/gnu/packages/guile-xyz.scm b/gnu/packages/guile-xyz.scm
index f652a94d2e..d479fb6ea9 100644
--- a/gnu/packages/guile-xyz.scm
+++ b/gnu/packages/guile-xyz.scm
@@ -2348,7 +2348,7 @@ more expressive and flexible than the traditional @code{format} procedure.")
("perl" ,perl)
("pkg-config" ,pkg-config)
("texinfo" ,texinfo)
- ("texlive" ,texlive)))
+ ("texlive" ,(texlive-union (list texlive-generic-epsf)))))
(propagated-inputs
`(("dbus-glib" ,dbus-glib)
("guile" ,guile-2.2)
diff --git a/gnu/packages/image.scm b/gnu/packages/image.scm
index ef477fa6f1..fabc2fb2d1 100644
--- a/gnu/packages/image.scm
+++ b/gnu/packages/image.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2017 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2017, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2013, 2015, 2016 Andreas Enge <andreas@enge.fr>
;;; Copyright © 2014, 2015, 2016 Mark H Weaver <mhw@netris.org>
;;; Copyright © 2014, 2015 Alex Kost <alezost@gmail.com>
@@ -1066,6 +1066,34 @@ and XMP metadata of images in various formats.")
;; <https://launchpad.net/ubuntu/precise/+source/exiv2/+copyright>.
(license license:gpl2+)))
+(define-public exiv2-0.26
+ (package
+ (inherit exiv2)
+ (version "0.26")
+ (source (origin
+ (method url-fetch)
+ (uri (list (string-append "https://www.exiv2.org/builds/exiv2-"
+ version "-trunk.tar.gz")
+ (string-append "https://www.exiv2.org/exiv2-"
+ version ".tar.gz")
+ (string-append "https://fossies.org/linux/misc/exiv2-"
+ version ".tar.gz")))
+ (patches (search-patches "exiv2-CVE-2017-14860.patch"
+ "exiv2-CVE-2017-14859-14862-14864.patch"))
+ (sha256
+ (base32
+ "1yza317qxd8yshvqnay164imm0ks7cvij8y8j86p1gqi1153qpn7"))))
+ (build-system gnu-build-system)
+ (arguments '(#:tests? #f)) ; no `check' target
+ (propagated-inputs
+ `(("expat" ,expat)
+ ("zlib" ,zlib)))
+ (native-inputs
+ `(("intltool" ,intltool)))
+
+ ;; People should rely on the newer version, so don't expose it.
+ (properties `((hidden? . #t)))))
+
(define-public devil
(package
(name "devil")
diff --git a/gnu/packages/lisp.scm b/gnu/packages/lisp.scm
index 8250340467..3aa2429595 100644
--- a/gnu/packages/lisp.scm
+++ b/gnu/packages/lisp.scm
@@ -5863,11 +5863,12 @@ and @code{kqueue(2)}), a pathname library and file-system utilities.")
`(("iolib.asdf" ,sbcl-iolib.asdf)
("iolib.conf" ,sbcl-iolib.conf)
("iolib.grovel" ,sbcl-iolib.grovel)
- ("iolib.base", sbcl-iolib.base)
- ("bordeaux-threads", sbcl-bordeaux-threads)
- ("idna", sbcl-idna)
- ("swap-bytes", sbcl-swap-bytes)
- ("libfixposix", libfixposix)))
+ ("iolib.base" ,sbcl-iolib.base)
+ ("bordeaux-threads" ,sbcl-bordeaux-threads)
+ ("idna" ,sbcl-idna)
+ ("swap-bytes" ,sbcl-swap-bytes)
+ ("libfixposix" ,libfixposix)
+ ("cffi" ,sbcl-cffi)))
(native-inputs
`(("fiveam" ,sbcl-fiveam)))
(arguments
@@ -5953,12 +5954,12 @@ floating point values to IEEE 754 binary representation.")
(name "sbcl-closure-common")
(build-system asdf-build-system/sbcl)
(version (git-version "20101006" revision commit))
- (home-page "https://github.com/sharplispers/closure-common")
+ (home-page "https://common-lisp.net/project/cxml/")
(source
(origin
(method git-fetch)
(uri (git-reference
- (url home-page)
+ (url "https://github.com/sharplispers/closure-common")
(commit commit)))
(file-name (git-file-name name version))
(sha256
@@ -5973,6 +5974,111 @@ Closure is a reference to the web browser it was originally written for.")
;; TODO: License?
(license #f))))
+(define-public sbcl-cxml+xml
+ (let ((commit "00b22bf4c4cf11c993d5866fae284f95ab18e6bf")
+ (revision "1"))
+ (package
+ (name "sbcl-cxml+xml")
+ (build-system asdf-build-system/sbcl)
+ (version (git-version "0.0.0" revision commit))
+ (home-page "https://common-lisp.net/project/cxml/")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/sharplispers/cxml")
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "13kif7rf3gqdycsk9zq0d7y0g9y81krkl0z87k0p2fkbjfgrph37"))))
+ (inputs
+ `(("closure-common" ,sbcl-closure-common)
+ ("puri" ,sbcl-puri)
+ ("trivial-gray-streams" ,sbcl-trivial-gray-streams)))
+ (arguments
+ `(#:asd-file "cxml.asd"
+ #:asd-system-name "cxml/xml"))
+ (synopsis "Common Lisp XML parser")
+ (description "CXML implements a namespace-aware, validating XML 1.0
+parser as well as the DOM Level 2 Core interfaces. Two parser interfaces are
+offered, one SAX-like, the other similar to StAX.")
+ (license license:llgpl))))
+
+(define sbcl-cxml+dom
+ (package
+ (inherit sbcl-cxml+xml)
+ (name "sbcl-cxml+dom")
+ (inputs
+ `(("closure-common" ,sbcl-closure-common)
+ ("puri" ,sbcl-puri)
+ ("cxml+xml" ,sbcl-cxml+xml)))
+ (arguments
+ `(#:asd-file "cxml.asd"
+ #:asd-system-name "cxml/dom"))))
+
+(define sbcl-cxml+klacks
+ (package
+ (inherit sbcl-cxml+xml)
+ (name "sbcl-cxml+klacks")
+ (inputs
+ `(("closure-common" ,sbcl-closure-common)
+ ("puri" ,sbcl-puri)
+ ("cxml+xml" ,sbcl-cxml+xml)))
+ (arguments
+ `(#:asd-file "cxml.asd"
+ #:asd-system-name "cxml/klacks"))))
+
+(define sbcl-cxml+test
+ (package
+ (inherit sbcl-cxml+xml)
+ (name "sbcl-cxml+test")
+ (inputs
+ `(("closure-common" ,sbcl-closure-common)
+ ("puri" ,sbcl-puri)
+ ("cxml+xml" ,sbcl-cxml+xml)))
+ (arguments
+ `(#:asd-file "cxml.asd"
+ #:asd-system-name "cxml/test"))))
+
+(define-public sbcl-cxml
+ (package
+ (inherit sbcl-cxml+xml)
+ (name "sbcl-cxml")
+ (inputs
+ `(("closure-common" ,sbcl-closure-common)
+ ("puri" ,sbcl-puri)
+ ("trivial-gray-streams" ,sbcl-trivial-gray-streams)
+ ("cxml+dom" ,sbcl-cxml+dom)
+ ("cxml+klacks" ,sbcl-cxml+klacks)
+ ("cxml+test" ,sbcl-cxml+test)))
+ (arguments
+ `(#:asd-file "cxml.asd"
+ #:asd-system-name "cxml"
+ #:phases
+ (modify-phases %standard-phases
+ (add-after 'build 'install-dtd
+ (lambda* (#:key outputs #:allow-other-keys)
+ (install-file "catalog.dtd"
+ (string-append
+ (assoc-ref outputs "out")
+ "/lib/" (%lisp-type)))))
+ (add-after 'create-asd 'remove-component
+ ;; XXX: The original .asd has no components, but our build system
+ ;; creates an entry nonetheless. We need to remove it for the
+ ;; generated .asd to load properly. See trivia.trivial for a
+ ;; similar problem.
+ (lambda* (#:key outputs #:allow-other-keys)
+ (let* ((out (assoc-ref outputs "out"))
+ (asd (string-append out "/lib/sbcl/cxml.asd")))
+ (substitute* asd
+ ((" :components
+")
+ ""))
+ (substitute* asd
+ ((" *\\(\\(:compiled-file \"cxml--system\"\\)\\)")
+ ""))))))))))
+
(define-public sbcl-cl-reexport
(let ((commit "312f3661bbe187b5f28536cd7ec2956e91366c3b")
(revision "1"))
@@ -6092,3 +6198,384 @@ cookie headers, cookie creation, cookie jar creation and more.")
(description "Dexador is yet another HTTP client for Common Lisp with
neat APIs and connection-pooling. It is meant to supersede Drakma.")
(license license:expat))))
+
+(define-public sbcl-lisp-namespace
+ (let ((commit "28107cafe34e4c1c67490fde60c7f92dc610b2e0")
+ (revision "1"))
+ (package
+ (name "sbcl-lisp-namespace")
+ (build-system asdf-build-system/sbcl)
+ (version (git-version "0.1" revision commit))
+ (home-page "https://github.com/guicho271828/lisp-namespace")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url home-page)
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1jw2wykp06z2afb9nm1lgfzll5cjlj36pnknjx614057zkkxq4iy"))))
+ (inputs
+ `(("alexandria" ,sbcl-alexandria)))
+ (native-inputs
+ `(("fiveam" ,sbcl-fiveam)))
+ (arguments
+ `(#:test-asd-file "lisp-namespace.test.asd"
+ ;; XXX: Component LISP-NAMESPACE-ASD::LISP-NAMESPACE.TEST not found
+ #:tests? #f))
+ (synopsis "LISP-N, or extensible namespaces in Common Lisp")
+ (description "Common Lisp already has major 2 namespaces, function
+namespace and value namespace (or variable namespace), but there are actually
+more — e.g., class namespace.
+This library offers macros to deal with symbols from any namespace.")
+ (license license:llgpl))))
+
+(define-public sbcl-trivial-cltl2
+ (let ((commit "8eec8407df833e8f27df8a388bc10913f16d9e83")
+ (revision "1"))
+ (package
+ (name "sbcl-trivial-cltl2")
+ (build-system asdf-build-system/sbcl)
+ (version (git-version "0.1.1" revision commit))
+ (home-page "https://github.com/Zulu-Inuoe/trivial-cltl2")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url home-page)
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1dyyxz17vqv8hlfwq287gl8xxbvcnq798ajb7p5jdjz91wqf4bgk"))))
+ (synopsis "Simple CLtL2 compatibility layer for Common Lisp")
+ (description "This library is a portable compatibility layer around
+\"Common Lisp the Language, 2nd
+Edition\" (@url{https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node102.html})
+and it exports symbols from implementation-specific packages.")
+ (license license:llgpl))))
+
+(define-public sbcl-introspect-environment
+ (let ((commit "fff42f8f8fd0d99db5ad6c5812e53de7d660020b")
+ (revision "1"))
+ (package
+ (name "sbcl-introspect-environment")
+ (build-system asdf-build-system/sbcl)
+ (version (git-version "0.1" revision commit))
+ (home-page "https://github.com/Bike/introspect-environment")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url home-page)
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1i305n0wfmpac63ni4i3vixnnkl8daw5ncxy0k3dv92krgx6qzhp"))))
+ (native-inputs
+ `(("fiveam" ,sbcl-fiveam)))
+ (synopsis "Common Lisp environment introspection portability layer")
+ (description "This library is a small interface to portable but
+nonstandard introspection of Common Lisp environments. It is intended to
+allow a bit more compile-time introspection of environments in Common Lisp.
+
+Quite a bit of information is available at the time a macro or compiler-macro
+runs; inlining info, type declarations, that sort of thing. This information
+is all standard - any Common Lisp program can @code{(declare (integer x))} and
+such.
+
+This info ought to be accessible through the standard @code{&environment}
+parameters, but it is not. Several implementations keep the information for
+their own purposes but do not make it available to user programs, because
+there is no standard mechanism to do so.
+
+This library uses implementation-specific hooks to make information available
+to users. This is currently supported on SBCL, CCL, and CMUCL. Other
+implementations have implementations of the functions that do as much as they
+can and/or provide reasonable defaults.")
+ (license license:wtfpl2))))
+
+(define-public sbcl-type-i
+ (let ((commit "dea233f45f94064105ec09f0767de338f67dcbe2")
+ (revision "1"))
+ (package
+ (name "sbcl-type-i")
+ (build-system asdf-build-system/sbcl)
+ (version (git-version "0.1" revision commit))
+ (home-page "https://github.com/guicho271828/type-i")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url home-page)
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "039g5pbrhh65s0bhr9314gmd2nwc2y5lp2377c5qrc2lxky89qs3"))))
+ (inputs
+ `(("alexandria" ,sbcl-alexandria)
+ ("introspect-environment" ,sbcl-introspect-environment)
+ ("trivia.trivial" ,sbcl-trivia.trivial)))
+ (native-inputs
+ `(("fiveam" ,sbcl-fiveam)))
+ (arguments
+ `(#:test-asd-file "type-i.test.asd"))
+ (synopsis "Type inference utility on unary predicates for Common Lisp")
+ (description "This library tries to provide a way to detect what kind of
+type the given predicate is trying to check. This is different from inferring
+the return type of a function.")
+ (license license:llgpl))))
+
+(define-public sbcl-optima
+ (let ((commit "373b245b928c1a5cce91a6cb5bfe5dd77eb36195")
+ (revision "1"))
+ (package
+ (name "sbcl-optima")
+ (build-system asdf-build-system/sbcl)
+ (version (git-version "0.1" revision commit))
+ (home-page "https://github.com/m2ym/optima")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url home-page)
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1yw4ymq7ms89342kkvb3aqxgv0w38m9kd8ikdqxxzyybnkjhndal"))))
+ (inputs
+ `(("alexandria" ,sbcl-alexandria)
+ ("closer-mop" ,sbcl-closer-mop)))
+ (native-inputs
+ `(("eos" ,sbcl-eos)))
+ (arguments
+ ;; XXX: Circular dependencies: tests depend on optima.ppcre which depends on optima.
+ `(#:tests? #f
+ #:test-asd-file "optima.test.asd"))
+ (synopsis "Optimized pattern matching library for Common Lisp")
+ (description "Optima is a fast pattern matching library which uses
+optimizing techniques widely used in the functional programming world.")
+ (license license:expat))))
+
+(define-public sbcl-fare-quasiquote
+ (package
+ (name "sbcl-fare-quasiquote")
+ (build-system asdf-build-system/sbcl)
+ (version "20171130")
+ (home-page "http://common-lisp.net/project/fare-quasiquote")
+ (source
+ (origin
+ (method url-fetch)
+ (uri (string-append "http://beta.quicklisp.org/archive/fare-quasiquote/"
+ (date->string (string->date version "~Y~m~d") "~Y-~m-~d")
+ "/fare-quasiquote-"
+ version
+ "-git.tgz"))
+ (sha256
+ (base32
+ "00brmh7ndsi0c97nibi8cy10j3l4gmkyrfrr5jr5lzkfb7ngyfqa"))))
+ (inputs
+ `(("fare-utils" ,sbcl-fare-utils)))
+ (arguments
+ ;; XXX: Circular dependencies: Tests depend on subsystems, which depend on the main systems.
+ `(#:tests? #f
+ #:phases
+ (modify-phases %standard-phases
+ ;; XXX: Require 1.0.0 version of fare-utils, and we package some
+ ;; commits after 1.0.0.5, but ASDF fails to read the
+ ;; "-REVISION-COMMIT" part generated by Guix.
+ (add-after 'unpack 'patch-requirement
+ (lambda _
+ (substitute* "fare-quasiquote.asd"
+ (("\\(:version \"fare-utils\" \"1.0.0\"\\)") "\"fare-utils\"")))))))
+ (synopsis "Pattern-matching friendly implementation of quasiquote for Common Lisp")
+ (description "The main purpose of this n+2nd reimplementation of
+quasiquote is enable matching of quasiquoted patterns, using Optima or
+Trivia.")
+ (license license:expat)))
+
+(define-public sbcl-fare-quasiquote-readtable
+ (package
+ (inherit sbcl-fare-quasiquote)
+ (name "sbcl-fare-quasiquote-readtable")
+ (inputs
+ `(("fare-quasiquote" ,sbcl-fare-quasiquote)
+ ("named-readtables" ,sbcl-named-readtables)))
+ (description "The main purpose of this n+2nd reimplementation of
+quasiquote is enable matching of quasiquoted patterns, using Optima or
+Trivia.
+
+This packages uses fare-quasiquote with named-readtable.")))
+
+(define-public sbcl-trivia.level0
+ (let ((commit "902e0c65602bbfe96ae82e679330b3771ddc7603")
+ (revision "1"))
+ (package
+ (name "sbcl-trivia.level0")
+ (build-system asdf-build-system/sbcl)
+ (version (git-version "0.0.0" revision commit))
+ (home-page "https://github.com/guicho271828/trivia")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url home-page)
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "11qbab30qqnfy9mx3x9fvgcw1jbvh1qn2cqv3p8xdn2m8981jvhr"))))
+ (inputs
+ `(("alexandria" ,sbcl-alexandria)))
+ (synopsis "Pattern matching in Common Lisp")
+ (description "Trivia is a pattern matching compiler that is compatible
+with Optima, another pattern matching library for Common Lisp. It is meant to
+be faster and more extensible than Optima.")
+ (license license:llgpl))))
+
+(define-public sbcl-trivia.level1
+ (package
+ (inherit sbcl-trivia.level0)
+ (name "sbcl-trivia.level1")
+ (inputs
+ `(("trivia.level0" ,sbcl-trivia.level0)))
+ (description "Trivia is a pattern matching compiler that is compatible
+with Optima, another pattern matching library for Common Lisp. It is meant to
+be faster and more extensible than Optima.
+
+This system contains the core patterns of Trivia.")))
+
+(define-public sbcl-trivia.level2
+ (package
+ (inherit sbcl-trivia.level0)
+ (name "sbcl-trivia.level2")
+ (inputs
+ `(("trivia.level1" ,sbcl-trivia.level1)
+ ("lisp-namespace" ,sbcl-lisp-namespace)
+ ("trivial-cltl2" ,sbcl-trivial-cltl2)
+ ("closer-mop" ,sbcl-closer-mop)))
+ (description "Trivia is a pattern matching compiler that is compatible
+with Optima, another pattern matching library for Common Lisp. It is meant to
+be faster and more extensible than Optima.
+
+This system contains a non-optimized pattern matcher compatible with Optima,
+with extensible optimizer interface.")))
+
+(define-public sbcl-trivia.trivial
+ (package
+ (inherit sbcl-trivia.level0)
+ (name "sbcl-trivia.trivial")
+ (inputs
+ `(("trivia.level2" ,sbcl-trivia.level2)))
+ (arguments
+ `(#:phases
+ (modify-phases %standard-phases
+ (replace 'create-asd-file
+ (lambda* (#:key outputs inputs #:allow-other-keys)
+ (let* ((out (assoc-ref outputs "out"))
+ (lib (string-append out "/lib/" (%lisp-type)))
+ (level2 (assoc-ref inputs "trivia.level2")))
+ (mkdir-p lib)
+ (install-file "trivia.trivial.asd" lib)
+ ;; XXX: This .asd does not have any component and the build
+ ;; system fails to work in this case. We should update the
+ ;; build system to handle component-less .asd.
+ ;; TODO: How do we append to file in Guile? It seems that
+ ;; (open-file ... "a") gets a "Permission denied".
+ (substitute* (string-append lib "/trivia.trivial.asd")
+ (("\"\\)")
+ (string-append "\")
+
+(progn (asdf/source-registry:ensure-source-registry)
+ (setf (gethash
+ \"trivia.level2\"
+ asdf/source-registry:*source-registry*)
+ #p\""
+ level2
+ "/share/common-lisp/sbcl-bundle-systems/trivia.level2.asd\"))")))))))))
+ (description "Trivia is a pattern matching compiler that is compatible
+with Optima, another pattern matching library for Common Lisp. It is meant to
+be faster and more extensible than Optima.
+
+This system contains the base level system of Trivia with a trivial optimizer.")))
+
+(define-public sbcl-trivia.balland2006
+ (package
+ (inherit sbcl-trivia.level0)
+ (name "sbcl-trivia.balland2006")
+ (inputs
+ `(("trivia.trivial" ,sbcl-trivia.trivial)
+ ("iterate" ,sbcl-iterate)
+ ("type-i" ,sbcl-type-i)
+ ("alexandria" ,sbcl-alexandria)))
+ (arguments
+ ;; Tests are done in trivia itself.
+ `(#:tests? #f))
+ (description "Trivia is a pattern matching compiler that is compatible
+with Optima, another pattern matching library for Common Lisp. It is meant to
+be faster and more extensible than Optima.
+
+This system contains the base level system of Trivia with a trivial optimizer.")))
+
+(define-public sbcl-trivia.ppcre
+ (package
+ (inherit sbcl-trivia.level0)
+ (name "sbcl-trivia.ppcre")
+ (inputs
+ `(("trivia.trivial" ,sbcl-trivia.trivial)
+ ("cl-ppcre" ,sbcl-cl-ppcre)))
+ (description "Trivia is a pattern matching compiler that is compatible
+with Optima, another pattern matching library for Common Lisp. It is meant to
+be faster and more extensible than Optima.
+
+This system contains the PPCRE extention.")))
+
+(define-public sbcl-trivia.quasiquote
+ (package
+ (inherit sbcl-trivia.level0)
+ (name "sbcl-trivia.quasiquote")
+ (inputs
+ `(("trivia.trivial" ,sbcl-trivia.trivial)
+ ("fare-quasiquote" ,sbcl-fare-quasiquote)
+ ("fare-quasiquote-readtable" ,sbcl-fare-quasiquote-readtable)))
+ (description "Trivia is a pattern matching compiler that is compatible
+with Optima, another pattern matching library for Common Lisp. It is meant to
+be faster and more extensible than Optima.
+
+This system contains the fare-quasiquote extension.")))
+
+(define-public sbcl-trivia.cffi
+ (package
+ (inherit sbcl-trivia.level0)
+ (name "sbcl-trivia.cffi")
+ (inputs
+ `(("cffi" ,sbcl-cffi)
+ ("trivia.trivial" ,sbcl-trivia.trivial)))
+ (description "Trivia is a pattern matching compiler that is compatible
+with Optima, another pattern matching library for Common Lisp. It is meant to
+be faster and more extensible than Optima.
+
+This system contains the CFFI foreign slot access extension.")))
+
+(define-public sbcl-trivia
+ (package
+ (inherit sbcl-trivia.level0)
+ (name "sbcl-trivia")
+ (inputs
+ `(("trivia.balland2006" ,sbcl-trivia.balland2006)))
+ (native-inputs
+ `(("fiveam" ,sbcl-fiveam)
+ ("trivia.ppcre" ,sbcl-trivia.ppcre)
+ ("trivia.quasiquote" ,sbcl-trivia.quasiquote)
+ ("trivia.cffi" ,sbcl-trivia.cffi)
+ ("optima" ,sbcl-optima)))
+ (arguments
+ `(#:test-asd-file "trivia.test.asd"))
+ (description "Trivia is a pattern matching compiler that is compatible
+with Optima, another pattern matching library for Common Lisp. It is meant to
+be faster and more extensible than Optima.")))
diff --git a/gnu/packages/logo.scm b/gnu/packages/logo.scm
new file mode 100644
index 0000000000..17c3990a94
--- /dev/null
+++ b/gnu/packages/logo.scm
@@ -0,0 +1,71 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Arun Isaac <arunisaac@systemreboot.net>
+;;;
+;;; 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 logo)
+ #:use-module (gnu packages qt)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (guix download)
+ #:use-module (guix packages)
+ #:use-module (guix build-system gnu))
+
+(define-public qlogo
+ (package
+ (name "qlogo")
+ (version "0.92")
+ (source
+ (origin
+ (method url-fetch)
+ (uri (string-append "https://qlogo.org/assets/sources/QLogo-"
+ version ".tgz"))
+ (sha256
+ (base32
+ "0cpyj1ji6hjy7zzz05672f0j6fr0mwpc1y3sq36hhkv2fkpidw22"))))
+ (build-system gnu-build-system)
+ (inputs
+ `(("qtbase" ,qtbase)))
+ (arguments
+ `(#:phases
+ (modify-phases %standard-phases
+ (replace 'configure
+ (lambda* (#:key outputs #:allow-other-keys)
+ (substitute* "QLogo.pro"
+ (("target\\.path = /usr/bin")
+ (string-append "target.path = "
+ (assoc-ref outputs "out") "/bin")))
+ (invoke "qmake" "QLogo.pro")))
+ ;; The check phase rebuilds the source for tests. So, it needs to be
+ ;; run after the install phase has installed the outputs of the build
+ ;; phase.
+ (delete 'check)
+ (add-after 'install 'check
+ (lambda _
+ ;; Clean files created by the build phase.
+ (invoke "make" "clean")
+ ;; QLogo tries to create its "dribble file" in the home
+ ;; directory. So, set HOME.
+ (setenv "HOME" "/tmp")
+ ;; Build and run tests.
+ (invoke "qmake" "TestQLogo.pro")
+ (invoke "make" "-j" (number->string (parallel-job-count)))
+ (invoke "./testqlogo"))))))
+ (home-page "https://qlogo.org")
+ (synopsis "Logo interpreter using Qt and OpenGL")
+ (description "QLogo is an interpreter for the Logo language written in C++
+using Qt and OpenGL. Specifically, it mimics, as reasonably as possible, the
+UCBLogo interpreter.")
+ (license license:gpl2+)))
diff --git a/gnu/packages/patchutils.scm b/gnu/packages/patchutils.scm
index 687864c008..a63d889cff 100644
--- a/gnu/packages/patchutils.scm
+++ b/gnu/packages/patchutils.scm
@@ -307,7 +307,7 @@ you to figure out what is going on in that merge you keep avoiding.")
(define-public patchwork
(package
(name "patchwork")
- (version "2.1.2")
+ (version "2.1.4")
(source (origin
(method git-fetch)
(uri (git-reference
@@ -316,7 +316,7 @@ you to figure out what is going on in that merge you keep avoiding.")
(file-name (git-file-name name version))
(sha256
(base32
- "06ng5pv6744w98zkyfm0ldkmpdgnsql3gbbbh6awq61sr2ndr3qw"))))
+ "0zi1hcqb0pi2diyznbv0c1631qk4rx02zl8ghyrr59g3ljlyr18y"))))
(build-system python-build-system)
(arguments
`(;; TODO: Tests require a running database
diff --git a/gnu/packages/photo.scm b/gnu/packages/photo.scm
index b2e3edca18..cf7da80642 100644
--- a/gnu/packages/photo.scm
+++ b/gnu/packages/photo.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2014, 2015, 2017 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2014, 2015, 2017, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2015, 2017 Andreas Enge <andreas@enge.fr>
;;; Copyright © 2016, 2017, 2018 Efraim Flashner <efraim@flashner.co.il>
@@ -70,14 +70,14 @@
(define-public libraw
(package
(name "libraw")
- (version "0.19.2")
+ (version "0.19.3")
(source (origin
(method url-fetch)
(uri (string-append "https://www.libraw.org/data/LibRaw-"
version ".tar.gz"))
(sha256
(base32
- "0i4nhjm5556xgn966x0i503ygk2wafq6z83kg0lisacjjab4f3a0"))))
+ "0xs1qb6pcvc4c43fy5xi3nkqxcif77gakkw99irf0fc5iccdd5px"))))
(build-system gnu-build-system)
(native-inputs
`(("pkg-config" ,pkg-config)))
@@ -445,7 +445,7 @@ and enhance them.")
(inputs
`(("boost" ,boost)
("enblend-enfuse" ,enblend-enfuse)
- ("exiv2" ,exiv2)
+ ("exiv2" ,exiv2-0.26)
("fftw" ,fftw)
("flann" ,flann)
("freeglut" ,freeglut)
diff --git a/gnu/packages/pulseaudio.scm b/gnu/packages/pulseaudio.scm
index 96d15bdf9c..fa48d8a7a6 100644
--- a/gnu/packages/pulseaudio.scm
+++ b/gnu/packages/pulseaudio.scm
@@ -8,6 +8,7 @@
;;; Copyright © 2017 Stefan Reichör <stefan@xsteve.at>
;;; Copyright © 2017 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2018 Pierre Langlois <pierre.langlois@gmx.com>
+;;; Copyright © 2019 Alex Griffin <a@ajgrf.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -27,6 +28,7 @@
(define-module (gnu packages pulseaudio)
#:use-module (guix packages)
#:use-module (guix download)
+ #:use-module (guix git-download)
#:use-module ((guix licenses) #:prefix l:)
#:use-module (guix build-system gnu)
#:use-module (guix build-system python)
@@ -43,6 +45,10 @@
#:use-module (gnu packages web)
#:use-module (gnu packages linux)
#:use-module (gnu packages m4)
+ #:use-module (gnu packages protobuf)
+ #:use-module (gnu packages python)
+ #:use-module (gnu packages python-xyz)
+ #:use-module (gnu packages python-web)
#:use-module (gnu packages pkg-config)
#:use-module (gnu packages xiph))
@@ -303,3 +309,55 @@ sinks.")
(description "Pulsemixer is a PulseAudio mixer with command-line and
curses-style interfaces.")
(license l:expat)))
+
+(define-public pulseaudio-dlna
+ ;; The last release was in 2016; use a more recent commit.
+ (let ((commit "4472928dd23f274193f14289f59daec411023ab0")
+ (revision "1"))
+ (package
+ (name "pulseaudio-dlna")
+ (version (git-version "0.5.2" revision commit))
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/masmu/pulseaudio-dlna.git")
+ (commit commit)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1dfn7036vrq49kxv4an7rayypnm5dlawsf02pfsldw877hzdamqk"))))
+ (build-system python-build-system)
+ (arguments `(#:python ,python-2))
+ (inputs
+ `(("python2-chardet" ,python2-chardet)
+ ("python2-dbus" ,python2-dbus)
+ ("python2-docopt" ,python2-docopt)
+ ("python2-futures" ,python2-futures)
+ ("python2-pygobject" ,python2-pygobject)
+ ("python2-lxml" ,python2-lxml)
+ ("python2-netifaces" ,python2-netifaces)
+ ("python2-notify2" ,python2-notify2)
+ ("python2-protobuf" ,python2-protobuf)
+ ("python2-psutil" ,python2-psutil)
+ ("python2-requests" ,python2-requests)
+ ("python2-pyroute2" ,python2-pyroute2)
+ ("python2-setproctitle" ,python2-setproctitle)
+ ("python2-zeroconf" ,python2-zeroconf)))
+ (home-page "https://github.com/masmu/pulseaudio-dlna")
+ (synopsis "Stream audio to DLNA/UPnP and Chromecast devices")
+ (description "This lightweight streaming server brings DLNA/UPnP and
+Chromecast support to PulseAudio. It can stream your current PulseAudio
+playback to different UPnP devices (UPnP Media Renderers, including Sonos
+devices and some Smart TVs) or Chromecasts in your network. You should also
+install one or more of the following packages alongside pulseaudio-dlna:
+
+@itemize
+@item ffmpeg - transcoding support for multiple codecs
+@item flac - FLAC transcoding support
+@item lame - MP3 transcoding support
+@item opus-tools - Opus transcoding support
+@item sox - WAV transcoding support
+@item vorbis-tools - Vorbis transcoding support
+@end itemize")
+ (license l:gpl3+))))
diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index e9cf681cde..2273f1ce74 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -61,6 +61,7 @@
;;; Copyright © 2019 Sam <smbaines8@gmail.com>
;;; Copyright © 2019 Jack Hill <jackhill@jackhill.us>
;;; Copyright © 2019 Guillaume Le Vaillant <glv@posteo.net>
+;;; Copyright © 2019 Alex Griffin <a@ajgrf.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -660,14 +661,14 @@ other machines, such as over the network.")
(define-public python-setuptools
(package
(name "python-setuptools")
- (version "40.0.0")
+ (version "41.0.1")
(source
(origin
(method url-fetch)
(uri (pypi-uri "setuptools" version ".zip"))
(sha256
(base32
- "0pq116lr14gnc62v76nk0npkm6krb2mpp7p9ab369zgv4n7dnah1"))
+ "04sns22y2hhsrwfy1mha2lgslvpjsjsz8xws7h2rh5a7ylkd28m2"))
(modules '((guix build utils)))
(snippet
'(begin
@@ -4331,19 +4332,18 @@ services for your Python modules and applications.")
(define-public python-olefile
(package
(name "python-olefile")
- (version "0.45.1")
+ (version "0.46")
(source
(origin
(method url-fetch)
- (uri (string-append "https://github.com/decalage2/olefile/archive/v"
- version ".tar.gz"))
+ (uri (string-append "https://github.com/decalage2/olefile/releases/"
+ "download/v" version "/olefile-" version ".tar.gz"))
(file-name (string-append name "-" version ".tar.gz"))
(sha256
(base32
- "18ai19zwagm6nli14k8bii31ipbab2rp7plrvsm6gmfql551a8ai"))))
+ "1kjxh4gr651hpqkjfv89cfzr40hyvf3vjlda7mifiail83j7j07m"))))
(build-system python-build-system)
- (home-page
- "https://www.decalage.info/python/olefileio")
+ (home-page "https://www.decalage.info/python/olefileio")
(synopsis "Read and write Microsoft OLE2 files.")
(description
"@code{olefile} can parse, read and write Microsoft OLE2 files (Structured
@@ -5632,6 +5632,33 @@ implementation of D-Bus.")
;; "ValueError: unichr() arg not in range(0x10000) (narrow Python build)"
(arguments `(#:tests? #f))))
+(define-public python-notify2
+ (package
+ (name "python-notify2")
+ (version "0.3.1")
+ (source
+ (origin
+ (method url-fetch)
+ (uri (pypi-uri "notify2" version))
+ (sha256
+ (base32
+ "0z8rrv9rsg1r2qgh2dxj3dfj5xnki98kgi3w839kqby4a26i1yik"))))
+ (build-system python-build-system)
+ (arguments `(#:tests? #f)) ; tests depend on system state
+ (native-inputs
+ `(("python-dbus" ,python-dbus)))
+ (home-page "https://bitbucket.org/takluyver/pynotify2")
+ (synopsis "Python interface to D-Bus notifications")
+ (description
+ "Pynotify2 provides a Python interface for sending D-Bus notifications.
+It is a reimplementation of pynotify in pure Python, and an alternative to
+the GObject Introspection bindings to libnotify for non-GTK applications.")
+ (license (list license:bsd-2
+ license:lgpl2.1+))))
+
+(define-public python2-notify2
+ (package-with-python2 python-notify2))
+
(define-public python-lxml
(package
(name "python-lxml")
@@ -5706,14 +5733,14 @@ converts incoming documents to Unicode and outgoing documents to UTF-8.")
(define-public python-soupsieve
(package
(name "python-soupsieve")
- (version "1.9.1")
+ (version "1.9.2")
(source
(origin
(method url-fetch)
(uri (pypi-uri "soupsieve" version))
(sha256
(base32
- "1jnzkiwmjl6yvqckc9mf689g87b6yz07sv868hap2aa5arggy3mj"))))
+ "0in9rc9q3h8w5b4qf7kvl3qxcvw6vrz35ckblchgf70hm6pg3dbj"))))
(build-system python-build-system)
(arguments `(#:tests? #f))
;;XXX: 2 tests fail currently despite claming they were to be
@@ -6904,6 +6931,41 @@ and MAC network addresses.")
(define-public python2-netaddr
(package-with-python2 python-netaddr))
+(define-public python2-pyroute2
+ (package
+ (name "python2-pyroute2")
+ (version "0.5.6")
+ (source
+ (origin
+ (method url-fetch)
+ (uri (pypi-uri "pyroute2" version))
+ (sha256
+ (base32
+ "1gmz4r1w0yzj6fjjypnalmfyy0lnfznydyn62gi3wk50j5hhxbny"))))
+ (build-system python-build-system)
+ (arguments
+ `(#:python ,python-2)) ;Python 3.x is not supported
+ (home-page "https://github.com/svinota/pyroute2")
+ (synopsis "Python netlink library")
+ (description
+ "Pyroute2 is a pure Python netlink library with minimal dependencies.
+Supported netlink families and protocols include:
+@itemize
+@item rtnl, network settings - addresses, routes, traffic controls
+@item nfnetlink - netfilter API: ipset, nftables, ...
+@item ipq - simplest userspace packet filtering, iptables QUEUE target
+@item devlink - manage and monitor devlink-enabled hardware
+@item generic - generic netlink families
+ @itemize
+ @item nl80211 - wireless functions API (basic support)
+ @item taskstats - extended process statistics
+ @item acpi_events - ACPI events monitoring
+ @item thermal_events - thermal events monitoring
+ @item VFS_DQUOT - disk quota events monitoring
+ @end itemize
+@end itemize")
+ (license license:gpl2+)))
+
(define-public python-wrapt
(package
(name "python-wrapt")
@@ -15798,6 +15860,42 @@ by Igor Pavlov.")
(define-public python2-pylzma
(package-with-python2 python-pylzma))
+(define-public python2-zeroconf
+ (package
+ (name "python2-zeroconf")
+
+ ;; This is the last version that supports Python 2.x.
+ (version "0.19.1")
+ (source
+ (origin
+ (method url-fetch)
+ (uri (pypi-uri "zeroconf" version))
+ (sha256
+ (base32
+ "0ykzg730n915qbrq9bn5pn06bv6rb5zawal4sqjyfnjjm66snkj3"))))
+ (build-system python-build-system)
+ (arguments
+ `(#:python ,python-2
+ #:phases
+ (modify-phases %standard-phases
+ (add-after 'unpack 'patch-requires
+ (lambda* (#:key inputs #:allow-other-keys)
+ (substitute* "setup.py"
+ (("enum-compat")
+ "enum34"))
+ #t)))))
+ (native-inputs
+ `(("python2-six" ,python2-six)
+ ("python2-enum32" ,python2-enum34)
+ ("python2-netifaces" ,python2-netifaces)
+ ("python2-typing" ,python2-typing)))
+ (home-page "https://github.com/jstasiak/python-zeroconf")
+ (synopsis "Pure Python mDNS service discovery")
+ (description
+ "Pure Python multicast DNS (mDNS) service discovery library (Bonjour/Avahi
+compatible).")
+ (license license:lgpl2.1+)))
+
(define-public python-bsddb3
(package
(name "python-bsddb3")
diff --git a/gnu/packages/serialization.scm b/gnu/packages/serialization.scm
index ae1ef9749b..505c196abd 100644
--- a/gnu/packages/serialization.scm
+++ b/gnu/packages/serialization.scm
@@ -297,18 +297,16 @@ that implements both the msgpack and msgpack-rpc specifications.")
(define-public jsoncpp
(package
(name "jsoncpp")
- (version "1.8.4")
+ (version "1.9.0")
+ (home-page "https://github.com/open-source-parsers/jsoncpp")
(source (origin
- (method url-fetch)
- (uri (string-append
- "https://github.com/open-source-parsers/jsoncpp/archive/"
- version ".tar.gz"))
- (file-name (string-append name "-" version ".tar.gz"))
+ (method git-fetch)
+ (uri (git-reference (url home-page) (commit version)))
+ (file-name (git-file-name name version))
(sha256
(base32
- "1dpxk8hkni5dq4mdw8qbaj40jmid3a31d1gh8iqcnfwkw34ym7f4"))))
+ "10wnwlq92gp32f5p55kjcc12jfsl0yq6f2y4abb0si6wym12krw9"))))
(build-system cmake-build-system)
- (home-page "https://github.com/open-source-parsers/jsoncpp")
(arguments
`(#:configure-flags '("-DBUILD_SHARED_LIBS:BOOL=YES")))
(synopsis "C++ library for interacting with JSON")
diff --git a/gnu/packages/wine.scm b/gnu/packages/wine.scm
index 72f0e1fd55..b76c9d18b9 100644
--- a/gnu/packages/wine.scm
+++ b/gnu/packages/wine.scm
@@ -310,7 +310,7 @@ integrate Windows applications into your desktop.")
(define-public wine-staging-patchset-data
(package
(name "wine-staging-patchset-data")
- (version "4.11")
+ (version "4.12")
(source
(origin
(method git-fetch)
@@ -320,7 +320,7 @@ integrate Windows applications into your desktop.")
(file-name (git-file-name name version))
(sha256
(base32
- "0h8qldqr9w1kwn48qgg5m1cs2xqkv8xxg2c66cvfka91hy886jcf"))))
+ "1drsrps6bd5gcafzcfrr9pzajhh5s6qg5la7q4qpwzlng9969f3r"))))
(build-system trivial-build-system)
(native-inputs
`(("bash" ,bash)
@@ -366,7 +366,7 @@ integrate Windows applications into your desktop.")
(file-name (string-append name "-" version ".tar.xz"))
(sha256
(base32
- "1rmyfwlynzs2niz7l2lwjs2axm6in6gb43ldbzyzsflxsmk5fl9f"))))
+ "1az5pcczq2zl1cvfdggzf89n0sf77m3fjkc8rnna8qr3n585q4h0"))))
(inputs `(("autoconf" ,autoconf) ; for autoreconf
("faudio" ,faudio)
("ffmpeg" ,ffmpeg)
diff --git a/gnu/tests/docker.scm b/gnu/tests/docker.scm
index f2674cdbe8..3ec5c3d6ee 100644
--- a/gnu/tests/docker.scm
+++ b/gnu/tests/docker.scm
@@ -27,7 +27,6 @@
#:use-module (gnu services networking)
#:use-module (gnu services docker)
#:use-module (gnu services desktop)
- #:use-module (gnu packages bootstrap) ; %bootstrap-guile
#:use-module (gnu packages docker)
#:use-module (gnu packages guile)
#:use-module (guix gexp)
@@ -101,7 +100,7 @@ inside %DOCKER-OS."
marionette))
(test-equal "Load docker image and run it"
- '("hello world" "hi!")
+ '("hello world" "hi!" "JSON!")
(marionette-eval
`(begin
(define slurp
@@ -125,8 +124,15 @@ inside %DOCKER-OS."
(response2 (slurp ;default entry point
,(string-append #$docker-cli "/bin/docker")
"run" repository&tag
- "-c" "(display \"hi!\")")))
- (list response1 response2)))
+ "-c" "(display \"hi!\")"))
+
+ ;; Check whether (json) is in $GUILE_LOAD_PATH.
+ (response3 (slurp ;default entry point + environment
+ ,(string-append #$docker-cli "/bin/docker")
+ "run" repository&tag
+ "-c" "(use-modules (json))
+ (display (json-string->scm (scm->json-string \"JSON!\")))")))
+ (list response1 response2 response3)))
marionette))
(test-end)
@@ -144,7 +150,7 @@ inside %DOCKER-OS."
(version "0")
(source #f)
(build-system trivial-build-system)
- (arguments `(#:guile ,%bootstrap-guile
+ (arguments `(#:guile ,guile-2.2
#:builder
(let ((out (assoc-ref %outputs "out")))
(mkdir out)
@@ -158,7 +164,7 @@ standard output device and then enters a new line.")
(home-page #f)
(license license:public-domain)))
(profile (profile-derivation (packages->manifest
- (list %bootstrap-guile
+ (list guile-2.2 guile-json
guest-script-package))
#:hooks '()
#:locales? #f))
diff --git a/gnu/tests/install.scm b/gnu/tests/install.scm
index 9f6baa1a48..124d176181 100644
--- a/gnu/tests/install.scm
+++ b/gnu/tests/install.scm
@@ -661,7 +661,7 @@ export GUIX_BUILD_OPTIONS=--no-grafts
ls -l /run/current-system/gc-roots
parted --script /dev/vdb mklabel gpt \\
mkpart primary ext2 1M 3M \\
- mkpart primary ext2 3M 1.2G \\
+ mkpart primary ext2 3M 1.4G \\
set 1 boot on \\
set 1 bios_grub on
echo -n thepassphrase | \\
diff --git a/gnu/tests/singularity.scm b/gnu/tests/singularity.scm
index 668043a0bc..2f3a6f289d 100644
--- a/gnu/tests/singularity.scm
+++ b/gnu/tests/singularity.scm
@@ -111,6 +111,21 @@
"run" #$image "-c" "(exit 42)"))
marionette))
+ ;; FIXME: Singularity 2.x doesn't directly honor
+ ;; /.singularity.d/env/*.sh. Instead, you have to load those files
+ ;; manually, which we don't do. Remove 'test-skip' call once we've
+ ;; switch to Singularity 3.x.
+ (test-skip 1)
+ (test-equal "singularity run, with environment"
+ 0
+ (marionette-eval
+ ;; Check whether GUILE_LOAD_PATH is properly set, allowing us to
+ ;; find the (json) module.
+ `(status:exit-val
+ (system* #$(file-append singularity "/bin/singularity")
+ "--debug" "run" #$image "-c" "(use-modules (json))"))
+ marionette))
+
(test-end)
(exit (= (test-runner-fail-count (test-runner-current)) 0)))))
@@ -122,7 +137,8 @@
(guile (set-guile-for-build (default-guile)))
;; 'singularity exec' insists on having /bin/sh in the image.
(profile (profile-derivation (packages->manifest
- (list bash-minimal guile-2.2))
+ (list bash-minimal
+ guile-2.2 guile-json))
#:hooks '()
#:locales? #f))
(tarball (squashfs-image "singularity-pack" profile
diff --git a/guix/channels.scm b/guix/channels.scm
index e7278c6060..fcf9fed829 100644
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -429,32 +429,27 @@ derivation."
(define (channel-instances->manifest instances)
"Return a profile manifest with entries for all of INSTANCES, a list of
channel instances."
- (define instance->entry
- (match-lambda
- ((instance drv)
- (let ((commit (channel-instance-commit instance))
- (channel (channel-instance-channel instance)))
- (with-monad %store-monad
- (return (manifest-entry
- (name (symbol->string (channel-name channel)))
- (version (string-take commit 7))
- (item (if (guix-channel? channel)
- (if (old-style-guix? drv)
- (whole-package-for-legacy
- (string-append name "-" version)
- drv)
- drv)
- drv))
- (properties
- `((source (repository
- (version 0)
- (url ,(channel-url channel))
- (branch ,(channel-branch channel))
- (commit ,commit))))))))))))
+ (define (instance->entry instance drv)
+ (let ((commit (channel-instance-commit instance))
+ (channel (channel-instance-channel instance)))
+ (manifest-entry
+ (name (symbol->string (channel-name channel)))
+ (version (string-take commit 7))
+ (item (if (guix-channel? channel)
+ (if (old-style-guix? drv)
+ (whole-package-for-legacy (string-append name "-" version)
+ drv)
+ drv)
+ drv))
+ (properties
+ `((source (repository
+ (version 0)
+ (url ,(channel-url channel))
+ (branch ,(channel-branch channel))
+ (commit ,commit))))))))
(mlet* %store-monad ((derivations (channel-instance-derivations instances))
- (entries (mapm %store-monad instance->entry
- (zip instances derivations))))
+ (entries -> (map instance->entry instances derivations)))
(return (manifest entries))))
(define (package-cache-file manifest)
diff --git a/guix/derivations.scm b/guix/derivations.scm
index 186d7a3f8f..731f1f698f 100644
--- a/guix/derivations.scm
+++ b/guix/derivations.scm
@@ -293,74 +293,78 @@ result is the set of prerequisites of DRV not already in valid."
(derivation-output-path (assoc-ref outputs sub-drv)))
sub-drvs))))
-(define* (substitution-oracle store drv
+(define* (substitution-oracle store inputs-or-drv
#:key (mode (build-mode normal)))
"Return a one-argument procedure that, when passed a store file name,
returns a 'substitutable?' if it's substitutable and #f otherwise.
-The returned procedure
-knows about all substitutes for all the derivations listed in DRV, *except*
-those that are already valid (that is, it won't bother checking whether an
-item is substitutable if it's already on disk); it also knows about their
-prerequisites, unless they are themselves substitutable.
+
+The returned procedure knows about all substitutes for all the derivation
+inputs or derivations listed in INPUTS-OR-DRV, *except* those that are already
+valid (that is, it won't bother checking whether an item is substitutable if
+it's already on disk); it also knows about their prerequisites, unless they
+are themselves substitutable.
Creating a single oracle (thus making a single 'substitutable-path-info' call) and
reusing it is much more efficient than calling 'has-substitutes?' or similar
repeatedly, because it avoids the costs associated with launching the
substituter many times."
- (define valid?
- (cut valid-path? store <>))
-
(define valid-input?
(cut valid-derivation-input? store <>))
- (define (dependencies drv)
- ;; Skip prerequisite sub-trees of DRV whose root is valid. This allows us
- ;; to ask the substituter for just as much as needed, instead of asking it
- ;; for the whole world, which can be significantly faster when substitute
- ;; info is not already in cache.
- ;; Also, skip derivations marked as non-substitutable.
- (append-map (lambda (input)
+ (define (closure inputs)
+ (let loop ((inputs inputs)
+ (closure '())
+ (visited (set)))
+ (match inputs
+ (()
+ (reverse closure))
+ ((input rest ...)
+ (let ((key (derivation-input-key input)))
+ (cond ((set-contains? visited key)
+ (loop rest closure visited))
+ ((valid-input? input)
+ (loop rest closure (set-insert key visited)))
+ (else
(let ((drv (derivation-input-derivation input)))
- (if (substitutable-derivation? drv)
- (derivation-input-output-paths input)
- '())))
- (derivation-prerequisites drv valid-input?)))
-
- (let* ((paths (delete-duplicates
- (concatenate
- (fold (lambda (drv result)
- (let ((self (match (derivation->output-paths drv)
- (((names . paths) ...)
- paths))))
- (cond ((eqv? mode (build-mode check))
- (cons (dependencies drv) result))
- ((not (substitutable-derivation? drv))
- (cons (dependencies drv) result))
- ((every valid? self)
- result)
- (else
- (cons* self (dependencies drv) result)))))
- '()
- drv))))
- (subst (fold (lambda (subst vhash)
- (vhash-cons (substitutable-path subst) subst
- vhash))
- vlist-null
- (substitutable-path-info store paths))))
+ (loop (append (derivation-inputs drv) rest)
+ (if (substitutable-derivation? drv)
+ (cons input closure)
+ closure)
+ (set-insert key visited))))))))))
+
+ (let* ((inputs (closure (map (match-lambda
+ ((? derivation-input? input)
+ input)
+ ((? derivation? drv)
+ (derivation-input drv)))
+ inputs-or-drv)))
+ (items (append-map derivation-input-output-paths inputs))
+ (subst (fold (lambda (subst vhash)
+ (vhash-cons (substitutable-path subst) subst
+ vhash))
+ vlist-null
+ (substitutable-path-info store items))))
(lambda (item)
(match (vhash-assoc item subst)
(#f #f)
((key . value) value)))))
+(define (dependencies-of-substitutables substitutables inputs)
+ "Return the subset of INPUTS whose output file names is among the references
+of SUBSTITUTABLES."
+ (let ((items (fold set-insert (set)
+ (append-map substitutable-references substitutables))))
+ (filter (lambda (input)
+ (any (cut set-contains? items <>)
+ (derivation-input-output-paths input)))
+ inputs)))
+
(define* (derivation-build-plan store inputs
#:key
(mode (build-mode normal))
(substitutable-info
(substitution-oracle
- store
- (map derivation-input-derivation
- inputs)
- #:mode mode)))
+ store inputs #:mode mode)))
"Given INPUTS, a list of derivation-inputs, return two values: the list of
derivation to build, and the list of substitutable items that, together,
allows INPUTS to be realized.
@@ -391,7 +395,9 @@ by 'substitution-oracle'."
(()
(values build substitute))
((input rest ...)
- (let ((key (derivation-input-key input)))
+ (let ((key (derivation-input-key input))
+ (deps (derivation-inputs
+ (derivation-input-derivation input))))
(cond ((set-contains? visited key)
(loop rest build substitute visited))
((input-built? input)
@@ -400,16 +406,17 @@ by 'substitution-oracle'."
((input-substitutable-info input)
=>
(lambda (substitutables)
- (loop rest build
+ (loop (append (dependencies-of-substitutables substitutables
+ deps)
+ rest)
+ build
(append substitutables substitute)
(set-insert key visited))))
(else
- (let ((deps (derivation-inputs
- (derivation-input-derivation input))))
- (loop (append deps rest)
- (cons (derivation-input-derivation input) build)
- substitute
- (set-insert key visited))))))))))
+ (loop (append deps rest)
+ (cons (derivation-input-derivation input) build)
+ substitute
+ (set-insert key visited)))))))))
(define-deprecated (derivation-prerequisites-to-build store drv #:rest rest)
derivation-build-plan
diff --git a/guix/docker.scm b/guix/docker.scm
index 7fe83d9797..b1bd226fa1 100644
--- a/guix/docker.scm
+++ b/guix/docker.scm
@@ -73,7 +73,7 @@
`((,(generate-tag path) . ((latest . ,id)))))
;; See https://github.com/opencontainers/image-spec/blob/master/config.md
-(define* (config layer time arch #:key entry-point)
+(define* (config layer time arch #:key entry-point (environment '()))
"Generate a minimal image configuration for the given LAYER file."
;; "architecture" must be values matching "platform.arch" in the
;; runtime-spec at
@@ -81,9 +81,13 @@
`((architecture . ,arch)
(comment . "Generated by GNU Guix")
(created . ,time)
- (config . ,(if entry-point
- `((entrypoint . ,entry-point))
- #nil))
+ (config . ,`((env . ,(map (match-lambda
+ ((name . value)
+ (string-append name "=" value)))
+ environment))
+ ,@(if entry-point
+ `((entrypoint . ,entry-point))
+ '())))
(container_config . #nil)
(os . "linux")
(rootfs . ((type . "layers")
@@ -113,6 +117,7 @@ return \"a\"."
(system (utsname:machine (uname)))
database
entry-point
+ (environment '())
compressor
(creation-time (current-time time-utc)))
"Write to IMAGE a Docker image archive containing the given PATHS. PREFIX
@@ -124,6 +129,9 @@ When DATABASE is true, copy it to /var/guix/db in the image and create
When ENTRY-POINT is true, it must be a list of strings; it is stored as the
entry point in the Docker image JSON structure.
+ENVIRONMENT must be a list of name/value pairs. It specifies the environment
+variables that must be defined in the resulting image.
+
SYMLINKS must be a list of (SOURCE -> TARGET) tuples describing symlinks to be
created in the image, where each TARGET is relative to PREFIX.
TRANSFORMATIONS must be a list of (OLD -> NEW) tuples describing how to
@@ -234,6 +242,7 @@ SRFI-19 time-utc object, as the creation time in metadata."
(lambda ()
(scm->json (config (string-append id "/layer.tar")
time arch
+ #:environment environment
#:entry-point entry-point))))
(with-output-to-file "manifest.json"
(lambda ()
diff --git a/guix/gexp.scm b/guix/gexp.scm
index 4f2adba90a..ce48d8d001 100644
--- a/guix/gexp.scm
+++ b/guix/gexp.scm
@@ -39,6 +39,9 @@
gexp-input
gexp-input?
+ gexp-input-thing
+ gexp-input-output
+ gexp-input-native?
local-file
local-file?
@@ -78,6 +81,14 @@
load-path-expression
gexp-modules
+ lower-gexp
+ lowered-gexp?
+ lowered-gexp-sexp
+ lowered-gexp-inputs
+ lowered-gexp-guile
+ lowered-gexp-load-path
+ lowered-gexp-load-compiled-path
+
gexp->derivation
gexp->file
gexp->script
@@ -566,15 +577,20 @@ list."
"Turn any package from INPUTS into a derivation for SYSTEM; return the
corresponding input list as a monadic value. When TARGET is true, use it as
the cross-compilation target triplet."
+ (define (store-item? obj)
+ (and (string? obj) (store-path? obj)))
+
(with-monad %store-monad
(mapm %store-monad
(match-lambda
(((? struct? thing) sub-drv ...)
(mlet %store-monad ((drv (lower-object
thing system #:target target)))
- (return `(,drv ,@sub-drv))))
+ (return (apply gexp-input drv sub-drv))))
+ (((? store-item? item))
+ (return (gexp-input item)))
(input
- (return input)))
+ (return (gexp-input input))))
inputs)))
(define* (lower-reference-graphs graphs #:key system target)
@@ -586,7 +602,9 @@ corresponding derivation."
(mlet %store-monad ((inputs (lower-inputs inputs
#:system system
#:target target)))
- (return (map cons file-names inputs))))))
+ (return (map (lambda (file input)
+ (cons file (gexp-input->tuple input)))
+ file-names inputs))))))
(define* (lower-references lst #:key system target)
"Based on LST, a list of output names and packages, return a list of output
@@ -618,6 +636,130 @@ names and file names suitable for the #:allowed-references argument to
(lambda (system)
((force proc) system))))
+;; Representation of a gexp instantiated for a given target and system.
+(define-record-type <lowered-gexp>
+ (lowered-gexp sexp inputs guile load-path load-compiled-path)
+ lowered-gexp?
+ (sexp lowered-gexp-sexp) ;sexp
+ (inputs lowered-gexp-inputs) ;list of <gexp-input>
+ (guile lowered-gexp-guile) ;<derivation> | #f
+ (load-path lowered-gexp-load-path) ;list of store items
+ (load-compiled-path lowered-gexp-load-compiled-path)) ;list of store items
+
+(define* (lower-gexp exp
+ #:key
+ (module-path %load-path)
+ (system (%current-system))
+ (target 'current)
+ (graft? (%graft?))
+ (guile-for-build (%guile-for-build))
+ (effective-version "2.2")
+
+ deprecation-warnings
+ (pre-load-modules? #t)) ;transitional
+ "*Note: This API is subject to change; use at your own risk!*
+
+Lower EXP, a gexp, instantiating it for SYSTEM and TARGET. Return a
+<lowered-gexp> ready to be used.
+
+Lowered gexps are an intermediate representation that's useful for
+applications that deal with gexps outside in a way that is disconnected from
+derivations--e.g., code evaluated for its side effects."
+ (define %modules
+ (delete-duplicates (gexp-modules exp)))
+
+ (define (search-path modules extensions suffix)
+ (append (match modules
+ ((? derivation? drv)
+ (list (derivation->output-path drv)))
+ (#f
+ '())
+ ((? store-path? item)
+ (list item)))
+ (map (lambda (extension)
+ (string-append (match extension
+ ((? derivation? drv)
+ (derivation->output-path drv))
+ ((? store-path? item)
+ item))
+ suffix))
+ extensions)))
+
+ (mlet* %store-monad ( ;; The following binding forces '%current-system' and
+ ;; '%current-target-system' to be looked up at >>=
+ ;; time.
+ (graft? (set-grafting graft?))
+
+ (system -> (or system (%current-system)))
+ (target -> (if (eq? target 'current)
+ (%current-target-system)
+ target))
+ (guile (if guile-for-build
+ (return guile-for-build)
+ (default-guile-derivation system)))
+ (normals (lower-inputs (gexp-inputs exp)
+ #:system system
+ #:target target))
+ (natives (lower-inputs (gexp-native-inputs exp)
+ #:system system
+ #:target #f))
+ (inputs -> (append normals natives))
+ (sexp (gexp->sexp exp
+ #:system system
+ #:target target))
+ (extensions -> (gexp-extensions exp))
+ (exts (mapm %store-monad
+ (lambda (obj)
+ (lower-object obj system))
+ extensions))
+ (modules (if (pair? %modules)
+ (imported-modules %modules
+ #:system system
+ #:module-path module-path)
+ (return #f)))
+ (compiled (if (pair? %modules)
+ (compiled-modules %modules
+ #:system system
+ #:module-path module-path
+ #:extensions extensions
+ #:guile guile
+ #:pre-load-modules?
+ pre-load-modules?
+ #:deprecation-warnings
+ deprecation-warnings)
+ (return #f))))
+ (define load-path
+ (search-path modules exts
+ (string-append "/share/guile/site/" effective-version)))
+
+ (define load-compiled-path
+ (search-path compiled exts
+ (string-append "/lib/guile/" effective-version
+ "/site-ccache")))
+
+ (mbegin %store-monad
+ (set-grafting graft?) ;restore the initial setting
+ (return (lowered-gexp sexp
+ `(,@(if modules
+ (list (gexp-input modules))
+ '())
+ ,@(if compiled
+ (list (gexp-input compiled))
+ '())
+ ,@(map gexp-input exts)
+ ,@inputs)
+ guile
+ load-path
+ load-compiled-path)))))
+
+(define (gexp-input->tuple input)
+ "Given INPUT, a <gexp-input> record, return the corresponding input tuple
+suitable for the 'derivation' procedure."
+ (match (gexp-input-output input)
+ ("out" `(,(gexp-input-thing input)))
+ (output `(,(gexp-input-thing input)
+ ,(gexp-input-output input)))))
+
(define* (gexp->derivation name exp
#:key
system (target 'current)
@@ -682,10 +824,8 @@ DEPRECATION-WARNINGS determines whether to show deprecation warnings while
compiling modules. It can be #f, #t, or 'detailed.
The other arguments are as for 'derivation'."
- (define %modules
- (delete-duplicates
- (append modules (gexp-modules exp))))
(define outputs (gexp-outputs exp))
+ (define requested-graft? graft?)
(define (graphs-file-names graphs)
;; Return a list of (FILE-NAME . STORE-PATH) pairs made from GRAPHS.
@@ -699,11 +839,13 @@ The other arguments are as for 'derivation'."
(cons file-name thing)))
graphs))
- (define (extension-flags extension)
- `("-L" ,(string-append (derivation->output-path extension)
- "/share/guile/site/" effective-version)
- "-C" ,(string-append (derivation->output-path extension)
- "/lib/guile/" effective-version "/site-ccache")))
+ (define (add-modules exp modules)
+ (if (null? modules)
+ exp
+ (make-gexp (gexp-references exp)
+ (append modules (gexp-self-modules exp))
+ (gexp-self-extensions exp)
+ (gexp-proc exp))))
(mlet* %store-monad ( ;; The following binding forces '%current-system' and
;; '%current-target-system' to be looked up at >>=
@@ -714,40 +856,21 @@ The other arguments are as for 'derivation'."
(target -> (if (eq? target 'current)
(%current-target-system)
target))
- (normals (lower-inputs (gexp-inputs exp)
- #:system system
- #:target target))
- (natives (lower-inputs (gexp-native-inputs exp)
- #:system system
- #:target #f))
- (inputs -> (append normals natives))
- (sexp (gexp->sexp exp
- #:system system
- #:target target))
- (builder (text-file script-name
- (object->string sexp)))
- (extensions -> (gexp-extensions exp))
- (exts (mapm %store-monad
- (lambda (obj)
- (lower-object obj system))
- extensions))
- (modules (if (pair? %modules)
- (imported-modules %modules
- #:system system
- #:module-path module-path
- #:guile guile-for-build)
- (return #f)))
- (compiled (if (pair? %modules)
- (compiled-modules %modules
- #:system system
- #:module-path module-path
- #:extensions extensions
- #:guile guile-for-build
- #:pre-load-modules?
- pre-load-modules?
- #:deprecation-warnings
- deprecation-warnings)
- (return #f)))
+ (exp -> (add-modules exp modules))
+ (lowered (lower-gexp exp
+ #:module-path module-path
+ #:system system
+ #:target target
+ #:graft? requested-graft?
+ #:guile-for-build
+ guile-for-build
+ #:effective-version
+ effective-version
+ #:deprecation-warnings
+ deprecation-warnings
+ #:pre-load-modules?
+ pre-load-modules?))
+
(graphs (if references-graphs
(lower-reference-graphs references-graphs
#:system system
@@ -763,32 +886,30 @@ The other arguments are as for 'derivation'."
#:system system
#:target target)
(return #f)))
- (guile (if guile-for-build
- (return guile-for-build)
- (default-guile-derivation system))))
+ (guile -> (lowered-gexp-guile lowered))
+ (builder (text-file script-name
+ (object->string
+ (lowered-gexp-sexp lowered)))))
(mbegin %store-monad
(set-grafting graft?) ;restore the initial setting
(raw-derivation name
(string-append (derivation->output-path guile)
"/bin/guile")
`("--no-auto-compile"
- ,@(if (pair? %modules)
- `("-L" ,(if (derivation? modules)
- (derivation->output-path modules)
- modules)
- "-C" ,(derivation->output-path compiled))
- '())
- ,@(append-map extension-flags exts)
+ ,@(append-map (lambda (directory)
+ `("-L" ,directory))
+ (lowered-gexp-load-path lowered))
+ ,@(append-map (lambda (directory)
+ `("-C" ,directory))
+ (lowered-gexp-load-compiled-path lowered))
,builder)
#:outputs outputs
#:env-vars env-vars
#:system system
#:inputs `((,guile)
(,builder)
- ,@(if modules
- `((,modules) (,compiled) ,@inputs)
- inputs)
- ,@(map list exts)
+ ,@(map gexp-input->tuple
+ (lowered-gexp-inputs lowered))
,@(match graphs
(((_ . inputs) ...) inputs)
(_ '())))
@@ -804,6 +925,7 @@ The other arguments are as for 'derivation'."
(define* (gexp-inputs exp #:key native?)
"Return the input list for EXP. When NATIVE? is true, return only native
references; otherwise, return only non-native references."
+ ;; TODO: Return <gexp-input> records instead of tuples.
(define (add-reference-inputs ref result)
(match ref
(($ <gexp-input> (? gexp? exp) _ #t)
diff --git a/guix/inferior.scm b/guix/inferior.scm
index 63c95141d7..fee97750b6 100644
--- a/guix/inferior.scm
+++ b/guix/inferior.scm
@@ -59,6 +59,7 @@
inferior-eval
inferior-eval-with-store
inferior-object?
+ read-repl-response
inferior-packages
inferior-available-packages
@@ -183,7 +184,8 @@ equivalent. Return #f if the inferior could not be launched."
(set-record-type-printer! <inferior-object> write-inferior-object)
-(define (read-inferior-response inferior)
+(define (read-repl-response port)
+ "Read a (guix repl) response from PORT and return it as a Scheme object."
(define sexp->object
(match-lambda
(('value value)
@@ -191,12 +193,15 @@ equivalent. Return #f if the inferior could not be launched."
(('non-self-quoting address string)
(inferior-object address string))))
- (match (read (inferior-socket inferior))
+ (match (read port)
(('values objects ...)
(apply values (map sexp->object objects)))
(('exception key objects ...)
(apply throw key (map sexp->object objects)))))
+(define (read-inferior-response inferior)
+ (read-repl-response (inferior-socket inferior)))
+
(define (send-inferior-request exp inferior)
(write exp (inferior-socket inferior))
(newline (inferior-socket inferior)))
diff --git a/guix/remote.scm b/guix/remote.scm
new file mode 100644
index 0000000000..e503c76167
--- /dev/null
+++ b/guix/remote.scm
@@ -0,0 +1,134 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
+;;;
+;;; 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 remote)
+ #:use-module (guix ssh)
+ #:use-module (guix gexp)
+ #:use-module (guix inferior)
+ #:use-module (guix store)
+ #:use-module (guix monads)
+ #:use-module (guix modules)
+ #:use-module (guix derivations)
+ #:use-module (ssh popen)
+ #:use-module (srfi srfi-1)
+ #:use-module (ice-9 match)
+ #:export (remote-eval))
+
+;;; Commentary:
+;;;
+;;; Note: This API is experimental and subject to change!
+;;;
+;;; Evaluate a gexp on a remote machine, over SSH, ensuring that all the
+;;; elements the gexp refers to are deployed beforehand. This is useful for
+;;; expressions that have side effects; for pure expressions, you would rather
+;;; build a derivation remotely or offload it.
+;;;
+;;; Code:
+
+(define (remote-pipe-for-gexp lowered session)
+ "Return a remote pipe for the given SESSION to evaluate LOWERED."
+ (define shell-quote
+ (compose object->string object->string))
+
+ (apply open-remote-pipe* session OPEN_READ
+ (string-append (derivation->output-path
+ (lowered-gexp-guile lowered))
+ "/bin/guile")
+ "--no-auto-compile"
+ (append (append-map (lambda (directory)
+ `("-L" ,directory))
+ (lowered-gexp-load-path lowered))
+ (append-map (lambda (directory)
+ `("-C" ,directory))
+ (lowered-gexp-load-path lowered))
+ `("-c"
+ ,(shell-quote (lowered-gexp-sexp lowered))))))
+
+(define (%remote-eval lowered session)
+ "Evaluate LOWERED, a lowered gexp, in SESSION. This assumes that all the
+prerequisites of EXP are already available on the host at SESSION."
+ (let* ((pipe (remote-pipe-for-gexp lowered session))
+ (result (read-repl-response pipe)))
+ (close-port pipe)
+ result))
+
+(define (trampoline exp)
+ "Return a \"trampoline\" gexp that evaluates EXP and writes the evaluation
+result to the current output port using the (guix repl) protocol."
+ (define program
+ (scheme-file "remote-exp.scm" exp))
+
+ (with-imported-modules (source-module-closure '((guix repl)))
+ #~(begin
+ (use-modules (guix repl))
+ (send-repl-response '(primitive-load #$program)
+ (current-output-port))
+ (force-output))))
+
+(define* (remote-eval exp session
+ #:key
+ (build-locally? #t)
+ (module-path %load-path)
+ (socket-name "/var/guix/daemon-socket/socket"))
+ "Evaluate EXP, a gexp, on the host at SESSION, an SSH session. Ensure that
+all the elements EXP refers to are built and deployed to SESSION beforehand.
+When BUILD-LOCALLY? is true, said dependencies are built locally and sent to
+the remote store afterwards; otherwise, dependencies are built directly on the
+remote store."
+ (mlet %store-monad ((lowered (lower-gexp (trampoline exp)
+ #:module-path %load-path))
+ (remote -> (connect-to-remote-daemon session
+ socket-name)))
+ (define inputs
+ (cons (gexp-input (lowered-gexp-guile lowered))
+ (lowered-gexp-inputs lowered)))
+
+ (define to-build
+ (map (lambda (input)
+ (if (derivation? (gexp-input-thing input))
+ (cons (gexp-input-thing input)
+ (gexp-input-output input))
+ (gexp-input-thing input)))
+ inputs))
+
+ (if build-locally?
+ (let ((to-send (map (lambda (input)
+ (match (gexp-input-thing input)
+ ((? derivation? drv)
+ (derivation->output-path
+ drv (gexp-input-output input)))
+ ((? store-path? item)
+ item)))
+ inputs)))
+ (mbegin %store-monad
+ (built-derivations to-build)
+ ((store-lift send-files) to-send remote #:recursive? #t)
+ (return (close-connection remote))
+ (return (%remote-eval lowered session))))
+ (let ((to-send (map (lambda (input)
+ (match (gexp-input-thing input)
+ ((? derivation? drv)
+ (derivation-file-name drv))
+ ((? store-path? item)
+ item)))
+ inputs)))
+ (mbegin %store-monad
+ ((store-lift send-files) to-send remote #:recursive? #t)
+ (return (build-derivations remote to-build))
+ (return (close-connection remote))
+ (return (%remote-eval lowered session)))))))
diff --git a/guix/repl.scm b/guix/repl.scm
new file mode 100644
index 0000000000..5cff5c71e9
--- /dev/null
+++ b/guix/repl.scm
@@ -0,0 +1,86 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2018, 2019 Ludovic Courtès <ludo@gnu.org>
+;;;
+;;; 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 repl)
+ #:use-module (rnrs bytevectors)
+ #:use-module (ice-9 match)
+ #:export (send-repl-response
+ machine-repl))
+
+;;; Commentary:
+;;;
+;;; This module implements the "machine-readable" REPL provided by
+;;; 'guix repl -t machine'. It's a lightweight module meant to be
+;;; embedded in any Guile process providing REPL functionality.
+;;;
+;;; Code:
+
+(define (self-quoting? x)
+ "Return #t if X is self-quoting."
+ (letrec-syntax ((one-of (syntax-rules ()
+ ((_) #f)
+ ((_ pred rest ...)
+ (or (pred x)
+ (one-of rest ...))))))
+ (one-of symbol? string? pair? null? vector?
+ bytevector? number? boolean?)))
+
+
+(define (send-repl-response exp output)
+ "Write the response corresponding to the evaluation of EXP to PORT, an
+output port."
+ (define (value->sexp value)
+ (if (self-quoting? value)
+ `(value ,value)
+ `(non-self-quoting ,(object-address value)
+ ,(object->string value))))
+
+ (catch #t
+ (lambda ()
+ (let ((results (call-with-values
+ (lambda ()
+ (primitive-eval exp))
+ list)))
+ (write `(values ,@(map value->sexp results))
+ output)
+ (newline output)
+ (force-output output)))
+ (lambda (key . args)
+ (write `(exception ,key ,@(map value->sexp args)))
+ (newline output)
+ (force-output output))))
+
+(define* (machine-repl #:optional
+ (input (current-input-port))
+ (output (current-output-port)))
+ "Run a machine-usable REPL over ports INPUT and OUTPUT.
+
+The protocol of this REPL is meant to be machine-readable and provides proper
+support to represent multiple-value returns, exceptions, objects that lack a
+read syntax, and so on. As such it is more convenient and robust than parsing
+Guile's REPL prompt."
+ (write `(repl-version 0 0) output)
+ (newline output)
+ (force-output output)
+
+ (let loop ()
+ (match (read input)
+ ((? eof-object?) #t)
+ (exp
+ (send-repl-response exp output)
+ (loop)))))
diff --git a/guix/scripts/deploy.scm b/guix/scripts/deploy.scm
new file mode 100644
index 0000000000..978cfb2a81
--- /dev/null
+++ b/guix/scripts/deploy.scm
@@ -0,0 +1,84 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 David Thompson <davet@gnu.org>
+;;; Copyright © 2019 Jakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>
+;;;
+;;; 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 deploy)
+ #:use-module (gnu machine)
+ #:use-module (guix scripts)
+ #:use-module (guix scripts build)
+ #:use-module (guix store)
+ #:use-module (guix ui)
+ #:use-module (ice-9 format)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-37)
+ #:export (guix-deploy))
+
+;;; Commentary:
+;;;
+;;; This program provides a command-line interface to (gnu machine), allowing
+;;; users to perform remote deployments through specification files.
+;;;
+;;; Code:
+
+
+
+(define (show-help)
+ (display (G_ "Usage: guix deploy [OPTION] FILE...
+Perform the deployment specified by FILE.\n"))
+ (show-build-options-help)
+ (newline)
+ (display (G_ "
+ -h, --help display this help and exit"))
+ (display (G_ "
+ -V, --version display version information and exit"))
+ (newline)
+ (show-bug-report-information))
+
+(define %options
+ (cons* (option '(#\h "help") #f #f
+ (lambda args
+ (show-help)
+ (exit 0)))
+ %standard-build-options))
+
+(define %default-options
+ '((system . ,(%current-system))
+ (substitutes? . #t)
+ (build-hook? . #t)
+ (graft? . #t)
+ (debug . 0)
+ (verbosity . 1)))
+
+(define (load-source-file file)
+ "Load FILE as a user module."
+ (let ((module (make-user-module '((gnu) (gnu machine) (gnu machine ssh)))))
+ (load* file module)))
+
+(define (guix-deploy . args)
+ (define (handle-argument arg result)
+ (alist-cons 'file arg result))
+ (let* ((opts (parse-command-line args %options (list %default-options)
+ #:argument-handler handle-argument))
+ (file (assq-ref opts 'file))
+ (machines (or (and file (load-source-file file)) '())))
+ (with-store store
+ (set-build-options-from-command-line store opts)
+ (for-each (lambda (machine)
+ (info (G_ "deploying to ~a...") (machine-display-name machine))
+ (run-with-store store (deploy-machine machine)))
+ machines))))
diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
index c90b777222..4ac5dfc896 100644
--- a/guix/scripts/pack.scm
+++ b/guix/scripts/pack.scm
@@ -27,6 +27,7 @@
#:use-module (guix utils)
#:use-module (guix store)
#:use-module ((guix status) #:select (with-status-verbosity))
+ #:use-module ((guix self) #:select (make-config.scm))
#:use-module (guix grafts)
#:autoload (guix inferior) (inferior-package?)
#:use-module (guix monads)
@@ -285,6 +286,32 @@ added to the pack."
build
#:references-graphs `(("profile" ,profile))))
+(define (singularity-environment-file profile)
+ "Return a shell script that defines the environment variables corresponding
+to the search paths of PROFILE."
+ (define build
+ (with-extensions (list guile-gcrypt)
+ (with-imported-modules `(((guix config) => ,(make-config.scm))
+ ,@(source-module-closure
+ `((guix profiles)
+ (guix search-paths))
+ #:select? not-config?))
+ #~(begin
+ (use-modules (guix profiles) (guix search-paths)
+ (ice-9 match))
+
+ (call-with-output-file #$output
+ (lambda (port)
+ (for-each (match-lambda
+ ((spec . value)
+ (format port "~a=~a~%export ~a~%"
+ (search-path-specification-variable spec)
+ value
+ (search-path-specification-variable spec))))
+ (profile-search-paths #$profile))))))))
+
+ (computed-file "singularity-environment.sh" build))
+
(define* (squashfs-image name profile
#:key target
(profile-name "guix-profile")
@@ -304,6 +331,9 @@ added to the pack."
(file-append (store-database (list profile))
"/db/db.sqlite")))
+ (define environment
+ (singularity-environment-file profile))
+
(define build
(with-imported-modules (source-module-closure
'((guix build utils)
@@ -338,6 +368,7 @@ added to the pack."
`(,@(map store-info-item
(call-with-input-file "profile"
read-reference-graph))
+ #$environment
,#$output
;; Do not perform duplicate checking because we
@@ -378,10 +409,19 @@ added to the pack."
target)))))))
'#$symlinks)
+ "-p" "/.singularity.d d 555 0 0"
+
+ ;; Create the environment file.
+ "-p" "/.singularity.d/env d 555 0 0"
+ "-p" ,(string-append
+ "/.singularity.d/env/90-environment.sh s 777 0 0 "
+ (relative-file-name "/.singularity.d/env"
+ #$environment))
+
;; Create /.singularity.d/actions, and optionally the 'run'
;; script, used by 'singularity run'.
- "-p" "/.singularity.d d 555 0 0"
"-p" "/.singularity.d/actions d 555 0 0"
+
,@(if entry-point
`(;; This one if for Singularity 2.x.
"-p"
@@ -440,11 +480,24 @@ the image."
(define build
;; Guile-JSON and Guile-Gcrypt are required by (guix docker).
(with-extensions (list guile-json guile-gcrypt)
- (with-imported-modules (source-module-closure '((guix docker)
- (guix build store-copy))
- #:select? not-config?)
+ (with-imported-modules `(((guix config) => ,(make-config.scm))
+ ,@(source-module-closure
+ `((guix docker)
+ (guix build store-copy)
+ (guix profiles)
+ (guix search-paths))
+ #:select? not-config?))
#~(begin
- (use-modules (guix docker) (srfi srfi-19) (guix build store-copy))
+ (use-modules (guix docker) (guix build store-copy)
+ (guix profiles) (guix search-paths)
+ (srfi srfi-19) (ice-9 match))
+
+ (define environment
+ (map (match-lambda
+ ((spec . value)
+ (cons (search-path-specification-variable spec)
+ value)))
+ (profile-search-paths #$profile)))
(setenv "PATH" (string-append #$archiver "/bin"))
@@ -455,6 +508,7 @@ the image."
#$profile
#:database #+database
#:system (or #$target (utsname:machine (uname)))
+ #:environment environment
#:entry-point #$(and entry-point
#~(string-append #$profile "/"
#$entry-point))
diff --git a/guix/scripts/repl.scm b/guix/scripts/repl.scm
index 02169e8004..e1cc759fc8 100644
--- a/guix/scripts/repl.scm
+++ b/guix/scripts/repl.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2018 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -19,6 +19,7 @@
(define-module (guix scripts repl)
#:use-module (guix ui)
#:use-module (guix scripts)
+ #:use-module (guix repl)
#:use-module (guix utils)
#:use-module (guix packages)
#:use-module (gnu packages)
@@ -29,8 +30,7 @@
#:autoload (system repl repl) (start-repl)
#:autoload (system repl server)
(make-tcp-server-socket make-unix-domain-server-socket)
- #:export (machine-repl
- guix-repl))
+ #:export (guix-repl))
;;; Commentary:
;;;
@@ -68,62 +68,12 @@ Start a Guile REPL in the Guix execution environment.\n"))
(newline)
(show-bug-report-information))
-(define (self-quoting? x)
- "Return #t if X is self-quoting."
- (letrec-syntax ((one-of (syntax-rules ()
- ((_) #f)
- ((_ pred rest ...)
- (or (pred x)
- (one-of rest ...))))))
- (one-of symbol? string? pair? null? vector?
- bytevector? number? boolean?)))
-
(define user-module
;; Module where we execute user code.
(let ((module (resolve-module '(guix-user) #f #f #:ensure #t)))
(beautify-user-module! module)
module))
-(define* (machine-repl #:optional
- (input (current-input-port))
- (output (current-output-port)))
- "Run a machine-usable REPL over ports INPUT and OUTPUT.
-
-The protocol of this REPL is meant to be machine-readable and provides proper
-support to represent multiple-value returns, exceptions, objects that lack a
-read syntax, and so on. As such it is more convenient and robust than parsing
-Guile's REPL prompt."
- (define (value->sexp value)
- (if (self-quoting? value)
- `(value ,value)
- `(non-self-quoting ,(object-address value)
- ,(object->string value))))
-
- (write `(repl-version 0 0) output)
- (newline output)
- (force-output output)
-
- (let loop ()
- (match (read input)
- ((? eof-object?) #t)
- (exp
- (catch #t
- (lambda ()
- (let ((results (call-with-values
- (lambda ()
-
- (primitive-eval exp))
- list)))
- (write `(values ,@(map value->sexp results))
- output)
- (newline output)
- (force-output output)))
- (lambda (key . args)
- (write `(exception ,key ,@(map value->sexp args)))
- (newline output)
- (force-output output)))
- (loop)))))
-
(define (call-with-connection spec thunk)
"Dynamically-bind the current input and output ports according to SPEC and
call THUNK."
diff --git a/guix/ssh.scm b/guix/ssh.scm
index 9b9baf54ea..ede00133c8 100644
--- a/guix/ssh.scm
+++ b/guix/ssh.scm
@@ -57,12 +57,14 @@
(define %compression
"zlib@openssh.com,zlib")
-(define* (open-ssh-session host #:key user port
+(define* (open-ssh-session host #:key user port identity
(compression %compression))
- "Open an SSH session for HOST and return it. When USER and PORT are #f, use
-default values or whatever '~/.ssh/config' specifies; otherwise use them.
-Throw an error on failure."
+ "Open an SSH session for HOST and return it. IDENTITY specifies the file
+name of a private key to use for authenticating with the host. When USER,
+PORT, or IDENTITY are #f, use default values or whatever '~/.ssh/config'
+specifies; otherwise use them. Throw an error on failure."
(let ((session (make-session #:user user
+ #:identity identity
#:host host
#:port port
#:timeout 10 ;seconds
diff --git a/guix/store.scm b/guix/store.scm
index 52940ff751..d7c603898c 100644
--- a/guix/store.scm
+++ b/guix/store.scm
@@ -1802,11 +1802,12 @@ connection, and return the result."
(call-with-values (lambda ()
(run-with-state mval store))
(lambda (result new-store)
- ;; Copy the object cache from NEW-STORE so we don't fully discard the
- ;; state.
- (let ((cache (store-connection-object-cache new-store)))
- (set-store-connection-object-cache! store cache)
- result)))))
+ (when (and store new-store)
+ ;; Copy the object cache from NEW-STORE so we don't fully discard
+ ;; the state.
+ (let ((cache (store-connection-object-cache new-store)))
+ (set-store-connection-object-cache! store cache)))
+ result))))
;;;
diff --git a/guix/ui.scm b/guix/ui.scm
index 6d243ef041..7d6ab9a2a7 100644
--- a/guix/ui.scm
+++ b/guix/ui.scm
@@ -835,8 +835,7 @@ check and report what is prerequisites are available for download."
;; substituter many times. This makes a big difference, especially when
;; DRV is a long list as is the case with 'guix environment'.
(if use-substitutes?
- (substitution-oracle store (map derivation-input-derivation inputs)
- #:mode mode)
+ (substitution-oracle store inputs #:mode mode)
(const #f)))
(let*-values (((build download)
@@ -844,18 +843,6 @@ check and report what is prerequisites are available for download."
#:mode mode
#:substitutable-info
substitutable-info))
- ((download) ; add the references of DOWNLOAD
- (if use-substitutes?
- (delete-duplicates
- (append download
- (filter-map (lambda (item)
- (if (valid-path? store item)
- #f
- (substitutable-info item)))
- (append-map
- substitutable-references
- download))))
- download))
((graft hook build)
(match (fold (lambda (drv acc)
(let ((file (derivation-file-name drv)))
diff --git a/po/guix/POTFILES.in b/po/guix/POTFILES.in
index ceee589b2e..f5fc4956b4 100644
--- a/po/guix/POTFILES.in
+++ b/po/guix/POTFILES.in
@@ -36,6 +36,7 @@ gnu/installer/steps.scm
gnu/installer/timezone.scm
gnu/installer/user.scm
gnu/installer/utils.scm
+gnu/machine/ssh.scm
guix/scripts.scm
guix/scripts/build.scm
guix/discovery.scm
@@ -66,6 +67,7 @@ guix/scripts/pack.scm
guix/scripts/weather.scm
guix/scripts/describe.scm
guix/scripts/processes.scm
+guix/scripts/deploy.scm
guix/gnu-maintenance.scm
guix/scripts/container.scm
guix/scripts/container/exec.scm
diff --git a/tests/derivations.scm b/tests/derivations.scm
index d173a78906..7be7726163 100644
--- a/tests/derivations.scm
+++ b/tests/derivations.scm
@@ -896,6 +896,35 @@
(((= derivation-file-name build))
(string=? build (derivation-file-name drv)))))))))
+(test-assert "derivation-build-plan and substitutes, non-substitutable dep"
+ (with-store store
+ (let* ((drv1 (build-expression->derivation store "prereq-no-subst"
+ (random 1000)
+ #:substitutable? #f))
+ (drv2 (build-expression->derivation store "substitutable"
+ (random 1000)
+ #:inputs `(("dep" ,drv1)))))
+
+ ;; Make sure substitutes are usable.
+ (set-build-options store #:use-substitutes? #t
+ #:substitute-urls (%test-substitute-urls))
+
+ (with-derivation-narinfo drv2
+ (sha256 => (make-bytevector 32 0))
+ (references => (list (derivation->output-path drv1)))
+
+ (let-values (((build download)
+ (derivation-build-plan store
+ (list (derivation-input drv2)))))
+ ;; Although DRV2 is available as a substitute, we must build its
+ ;; dependency, DRV1, due to #:substitutable? #f.
+ (and (match download
+ (((= substitutable-path item))
+ (string=? item (derivation->output-path drv2))))
+ (match build
+ (((= derivation-file-name build))
+ (string=? build (derivation-file-name drv1))))))))))
+
(test-assert "derivation-build-plan and substitutes, local build"
(with-store store
(let* ((drv (build-expression->derivation store "prereq-subst-local"
diff --git a/tests/gexp.scm b/tests/gexp.scm
index cee2c96610..23904fce2e 100644
--- a/tests/gexp.scm
+++ b/tests/gexp.scm
@@ -832,6 +832,43 @@
(built-derivations (list drv))
(return (equal? '(42 84) (call-with-input-file out read))))))
+(test-assertm "lower-gexp"
+ (mlet* %store-monad
+ ((extension -> %extension-package)
+ (extension-drv (package->derivation %extension-package))
+ (coreutils-drv (package->derivation coreutils))
+ (exp -> (with-extensions (list extension)
+ (with-imported-modules `((guix build utils))
+ #~(begin
+ (use-modules (guix build utils)
+ (hg2g))
+ #$coreutils:debug
+ mkdir-p
+ the-answer))))
+ (lexp (lower-gexp exp
+ #:effective-version "2.0")))
+ (define (matching-input drv output)
+ (lambda (input)
+ (and (eq? (gexp-input-thing input) drv)
+ (string=? (gexp-input-output input) output))))
+
+ (mbegin %store-monad
+ (return (and (find (matching-input extension-drv "out")
+ (lowered-gexp-inputs (pk 'lexp lexp)))
+ (find (matching-input coreutils-drv "debug")
+ (lowered-gexp-inputs lexp))
+ (member (string-append
+ (derivation->output-path extension-drv)
+ "/share/guile/site/2.0")
+ (lowered-gexp-load-path lexp))
+ (= 2 (length (lowered-gexp-load-path lexp)))
+ (member (string-append
+ (derivation->output-path extension-drv)
+ "/lib/guile/2.0/site-ccache")
+ (lowered-gexp-load-compiled-path lexp))
+ (= 2 (length (lowered-gexp-load-compiled-path lexp)))
+ (eq? (lowered-gexp-guile lexp) (%guile-for-build)))))))
+
(test-assertm "gexp->derivation #:references-graphs"
(mlet* %store-monad
((one (text-file "one" (random-text)))