From 8c3c896dbebe022f5372dffaee9ad3f00c71180f Mon Sep 17 00:00:00 2001 From: Nikita Karetnikov Date: Wed, 13 Feb 2013 02:18:46 +0000 Subject: gnu: Add GNU Wdiff. * gnu/packages/wdiff.scm: New file. * Makefile.am (MODULES): Add it. --- Makefile.am | 1 + 1 file changed, 1 insertion(+) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 3a84812ba..e44753d59 100644 --- a/Makefile.am +++ b/Makefile.am @@ -152,6 +152,7 @@ MODULES = \ gnu/packages/time.scm \ gnu/packages/tmux.scm \ gnu/packages/tor.scm \ + gnu/packages/wdiff.scm \ gnu/packages/wget.scm \ gnu/packages/which.scm \ gnu/packages/xml.scm \ -- cgit v1.3 From 250b0404d7bc6bb6b911d58585df41e876ee42de Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Wed, 13 Feb 2013 16:09:29 +0100 Subject: gnu: Add missing patch for mcron. * gnu/packages/patches/mcron-install.patch: New file. * Makefile.am (dist_patch_DATA): Add it. --- Makefile.am | 1 + gnu/packages/patches/mcron-install.patch | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 gnu/packages/patches/mcron-install.patch (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index e44753d59..7b0613d27 100644 --- a/Makefile.am +++ b/Makefile.am @@ -196,6 +196,7 @@ dist_patch_DATA = \ gnu/packages/patches/m4-readlink-EINVAL.patch \ gnu/packages/patches/m4-s_isdir.patch \ gnu/packages/patches/make-impure-dirs.patch \ + gnu/packages/patches/mcron-install.patch \ gnu/packages/patches/perl-no-sys-dirs.patch \ gnu/packages/patches/procps-make-3.82.patch \ gnu/packages/patches/readline-link-ncurses.patch \ diff --git a/gnu/packages/patches/mcron-install.patch b/gnu/packages/patches/mcron-install.patch new file mode 100644 index 000000000..3cd291f57 --- /dev/null +++ b/gnu/packages/patches/mcron-install.patch @@ -0,0 +1,22 @@ +This patch allows us to install the Vixie-compatible binaries as +non-root without creating /var/run, etc. + +--- mcron-1.0.6/makefile.in 2010-06-19 20:44:17.000000000 +0200 ++++ mcron-1.0.6/makefile.in 2010-07-04 16:16:25.000000000 +0200 +@@ -1004,15 +1004,11 @@ mcron.c : main.scm crontab.scm makefile. + @rm -f mcron.escaped.scm > /dev/null 2>&1 + + install-exec-hook: +- @if [ "x@NO_VIXIE_CLOBBER@" != "xyes" -a "`id -u`" -eq "0" ]; then \ ++ @if [ "x@NO_VIXIE_CLOBBER@" != "xyes" ]; then \ + rm -f $(fpp)cron$(EXEEXT) > /dev/null 2>&1; \ + $(INSTALL) --mode='u=rwx' mcron$(EXEEXT) $(fpp)cron$(EXEEXT); \ + rm -f $(fpp)crontab$(EXEEXT) > /dev/null 2>&1; \ + $(INSTALL) --mode='u=rwxs,og=rx' mcron$(EXEEXT) $(fpp)crontab$(EXEEXT); \ +- $(INSTALL) -d --mode='u=rwx' $(DESTDIR)/var/cron; \ +- $(INSTALL) -d --mode='u=rwx,og=rx' $(DESTDIR)/var/run; \ +- $(INSTALL) -d --mode='u=rwx,og=rx' $(DESTDIR)@GUILE_SITE@; \ +- $(INSTALL) -d --mode='u=rwx,og=rx' $(DESTDIR)@GUILE_SITE@/mcron; \ + elif [ "x@NO_VIXIE_CLOBBER@" = "xyes" ]; then \ + echo "Not installing Vixie-style programs"; \ + else \ -- cgit v1.3 From eb4908581cae8b787c63b39fa524adf764ae8c25 Mon Sep 17 00:00:00 2001 From: Cyril Roelandt Date: Wed, 13 Feb 2013 23:20:11 +0100 Subject: gnu: Add vim. * gnu/packages/vim.scm: New file. * Makefile.am (MODULES): Add it. --- Makefile.am | 1 + gnu/packages/vim.scm | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 gnu/packages/vim.scm (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 7b0613d27..739b75e43 100644 --- a/Makefile.am +++ b/Makefile.am @@ -152,6 +152,7 @@ MODULES = \ gnu/packages/time.scm \ gnu/packages/tmux.scm \ gnu/packages/tor.scm \ + gnu/packages/vim.scm \ gnu/packages/wdiff.scm \ gnu/packages/wget.scm \ gnu/packages/which.scm \ diff --git a/gnu/packages/vim.scm b/gnu/packages/vim.scm new file mode 100644 index 000000000..a80f50a4a --- /dev/null +++ b/gnu/packages/vim.scm @@ -0,0 +1,74 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2013 Cyril Roelandt +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu packages vim) + #:use-module ((guix licenses) #:renamer (symbol-prefix-proc 'license:)) + #:use-module (guix packages) + #:use-module (guix download) + #:use-module (guix build-system gnu) + #:use-module (gnu packages) + #:use-module (gnu packages gawk) + #:use-module (gnu packages ncurses) + #:use-module (gnu packages perl) + #:use-module (gnu packages system) ; For GNU hostname + #:use-module (gnu packages tcsh)) + +(define-public vim + (package + (name "vim") + (version "7.3") + (source (origin + (method url-fetch) + (uri (string-append "ftp://ftp.vim.org/pub/vim/unix/vim-" + version ".tar.bz2")) + (sha256 + (base32 + "079201qk8g9yisrrb0dn52ch96z3lzw6z473dydw9fzi0xp5spaw")))) + (build-system gnu-build-system) + (arguments + `(#:test-target "test" + #:parallel-tests? #f + #:phases + (alist-replace + 'configure + (lambda* (#:key #:allow-other-keys #:rest args) + (let ((configure (assoc-ref %standard-phases 'configure))) + (apply configure args) + (substitute* "runtime/tools/mve.awk" + (("/usr/bin/nawk") (which "gawk"))) + (substitute* "src/testdir/Makefile" + (("/bin/sh") (which "sh"))))) + %standard-phases))) + (inputs + `(("gawk", gawk) + ("inetutils", inetutils) + ("ncurses", ncurses) + ("perl", perl) + ("tcsh" ,tcsh))) ; For runtime/tools/vim32 + (home-page "http://www.vim.org/") + (synopsis "VIM 7.3, a text editor based on vi.") + (description + "Vim is a highly configurable text editor built to enable efficient text +editing. It is an improved version of the vi editor distributed with most UNIX +systems. + +Vim is often called a \"programmer's editor,\" and so useful for programming +that many consider it an entire IDE. It's not just for programmers, though. Vim +is perfect for all kinds of text editing, from composing email to editing +configuration files. ") + (license license:vim))) -- cgit v1.3 From 6956067b04269ecf666b3b4b1e63ce00bc1944c8 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 15 Feb 2013 00:29:28 +0100 Subject: gnu: guile-static: Add bindings for low-level Linux syscalls. * gnu/packages/make-bootstrap.scm (%guile-static): Add `guile-linux-syscalls.patch' as an input, and use it. * gnu/packages/patches/guile-linux-syscalls.patch: New file. * Makefile.am (dist_patch_DATA): Add it. --- Makefile.am | 1 + gnu/packages/make-bootstrap.scm | 5 +- gnu/packages/patches/guile-linux-syscalls.patch | 234 ++++++++++++++++++++++++ 3 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 gnu/packages/patches/guile-linux-syscalls.patch (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 739b75e43..9ab0709c6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -186,6 +186,7 @@ dist_patch_DATA = \ gnu/packages/patches/grub-gets-undeclared.patch \ gnu/packages/patches/guile-1.8-cpp-4.5.patch \ gnu/packages/patches/guile-default-utf8.patch \ + gnu/packages/patches/guile-linux-syscalls.patch \ gnu/packages/patches/guile-relocatable.patch \ gnu/packages/patches/libapr-skip-getservbyname-test.patch \ gnu/packages/patches/libevent-dns-tests.patch \ diff --git a/gnu/packages/make-bootstrap.scm b/gnu/packages/make-bootstrap.scm index 9e9ba939d..218f5a8e2 100644 --- a/gnu/packages/make-bootstrap.scm +++ b/gnu/packages/make-bootstrap.scm @@ -412,6 +412,8 @@ ,(search-patch "guile-relocatable.patch")) ("patch/utf8" ,(search-patch "guile-default-utf8.patch")) + ("patch/syscalls" + ,(search-patch "guile-linux-syscalls.patch")) ,@(package-inputs guile-2.0))) (propagated-inputs `(("bdw-gc" ,libgc) @@ -443,7 +445,8 @@ ;; bootstrap. #:patches (list (assoc-ref %build-inputs "patch/relocatable") - (assoc-ref %build-inputs "patch/utf8")) + (assoc-ref %build-inputs "patch/utf8") + (assoc-ref %build-inputs "patch/syscalls")) ;; There are uses of `dynamic-link' in ;; {foreign,coverage}.test that don't fly here. diff --git a/gnu/packages/patches/guile-linux-syscalls.patch b/gnu/packages/patches/guile-linux-syscalls.patch new file mode 100644 index 000000000..c0cb0f6d7 --- /dev/null +++ b/gnu/packages/patches/guile-linux-syscalls.patch @@ -0,0 +1,234 @@ +This patch adds bindings to Linux syscalls for which glibc has symbols. + +diff --git a/libguile/posix.c b/libguile/posix.c +index 324f21b..ace5211 100644 +--- a/libguile/posix.c ++++ b/libguile/posix.c +@@ -2286,6 +2286,227 @@ scm_init_popen (void) + } + #endif + ++ ++/* Linux! */ ++ ++#include ++#include "libguile/foreign.h" ++#include "libguile/bytevectors.h" ++ ++SCM_DEFINE (scm_mount, "mount", 3, 2, 0, ++ (SCM source, SCM target, SCM type, SCM flags, SCM data), ++ "Mount file system of @var{type} specified by @var{source} " ++ "on @var{target}.") ++#define FUNC_NAME s_scm_mount ++{ ++ int err; ++ char *c_source, *c_target, *c_type; ++ unsigned long c_flags; ++ void *c_data; ++ ++ c_source = scm_to_locale_string (source); ++ c_target = scm_to_locale_string (target); ++ c_type = scm_to_locale_string (type); ++ c_flags = SCM_UNBNDP (flags) ? 0 : scm_to_ulong (flags); ++ c_data = SCM_UNBNDP (data) ? NULL : scm_to_pointer (data); ++ ++ err = mount (c_source, c_target, c_type, c_flags, c_data); ++ if (err != 0) ++ err = errno; ++ ++ free (c_source); ++ free (c_target); ++ free (c_type); ++ ++ if (err != 0) ++ { ++ errno = err; ++ SCM_SYSERROR; ++ } ++ ++ return SCM_UNSPECIFIED; ++} ++#undef FUNC_NAME ++ ++/* Linux's module installation syscall. See `kernel/module.c' in Linux; ++ the function itself is part of the GNU libc. ++ ++ Load the LEN bytes at MODULE as a kernel module, with arguments from ++ ARGS, a space-separated list of options. */ ++extern long init_module (void *module, unsigned long len, const char *args); ++ ++SCM_DEFINE (scm_load_linux_module, "load-linux-module", 1, 1, 0, ++ (SCM data, SCM options), ++ "Load the Linux kernel module whose contents are in bytevector " ++ "DATA (the contents of a @code{.ko} file), with the arguments " ++ "from the OPTIONS string.") ++#define FUNC_NAME s_scm_load_linux_module ++{ ++ long err; ++ void *c_data; ++ unsigned long c_len; ++ char *c_options; ++ ++ SCM_VALIDATE_BYTEVECTOR (SCM_ARG1, data); ++ ++ c_data = SCM_BYTEVECTOR_CONTENTS (data); ++ c_len = SCM_BYTEVECTOR_LENGTH (data); ++ c_options = ++ scm_to_locale_string (SCM_UNBNDP (options) ? scm_nullstr : options); ++ ++ err = init_module (c_data, c_len, c_options); ++ ++ free (c_options); ++ ++ if (err != 0) ++ { ++ /* XXX: `insmod' actually provides better translation of some of ++ the error codes. */ ++ errno = err; ++ SCM_SYSERROR; ++ } ++ ++ return SCM_UNSPECIFIED; ++} ++#undef FUNC_NAME ++ ++/* Linux network interfaces. See . */ ++ ++#include ++#include ++#include "libguile/socket.h" ++ ++SCM_VARIABLE_INIT (flag_IFF_UP, "IFF_UP", ++ scm_from_int (IFF_UP)); ++SCM_VARIABLE_INIT (flag_IFF_BROADCAST, "IFF_BROADCAST", ++ scm_from_int (IFF_BROADCAST)); ++SCM_VARIABLE_INIT (flag_IFF_DEBUG, "IFF_DEBUG", ++ scm_from_int (IFF_DEBUG)); ++SCM_VARIABLE_INIT (flag_IFF_LOOPBACK, "IFF_LOOPBACK", ++ scm_from_int (IFF_LOOPBACK)); ++SCM_VARIABLE_INIT (flag_IFF_POINTOPOINT, "IFF_POINTOPOINT", ++ scm_from_int (IFF_POINTOPOINT)); ++SCM_VARIABLE_INIT (flag_IFF_NOTRAILERS, "IFF_NOTRAILERS", ++ scm_from_int (IFF_NOTRAILERS)); ++SCM_VARIABLE_INIT (flag_IFF_RUNNING, "IFF_RUNNING", ++ scm_from_int (IFF_RUNNING)); ++SCM_VARIABLE_INIT (flag_IFF_NOARP, "IFF_NOARP", ++ scm_from_int (IFF_NOARP)); ++SCM_VARIABLE_INIT (flag_IFF_PROMISC, "IFF_PROMISC", ++ scm_from_int (IFF_PROMISC)); ++SCM_VARIABLE_INIT (flag_IFF_ALLMULTI, "IFF_ALLMULTI", ++ scm_from_int (IFF_ALLMULTI)); ++ ++SCM_DEFINE (scm_set_network_interface_address, "set-network-interface-address", ++ 3, 0, 0, ++ (SCM socket, SCM name, SCM address), ++ "Configure network interface @var{name}.") ++#define FUNC_NAME s_scm_set_network_interface_address ++{ ++ char *c_name; ++ struct ifreq ifr; ++ struct sockaddr *c_address; ++ size_t sa_len; ++ int fd, err; ++ ++ socket = SCM_COERCE_OUTPORT (socket); ++ SCM_VALIDATE_OPFPORT (1, socket); ++ fd = SCM_FPORT_FDES (socket); ++ ++ memset (&ifr, 0, sizeof ifr); ++ c_name = scm_to_locale_string (name); ++ c_address = scm_to_sockaddr (address, &sa_len); ++ ++ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1); ++ memcpy (&ifr.ifr_addr, c_address, sa_len); ++ ++ err = ioctl (fd, SIOCSIFADDR, &ifr); ++ if (err != 0) ++ err = errno; ++ ++ free (c_name); ++ free (c_address); ++ ++ if (err != 0) ++ { ++ errno = err; ++ SCM_SYSERROR; ++ } ++ ++ return SCM_UNSPECIFIED; ++} ++#undef FUNC_NAME ++ ++SCM_DEFINE (scm_set_network_interface_flags, "set-network-interface-flags", ++ 3, 0, 0, ++ (SCM socket, SCM name, SCM flags), ++ "Change the flags of network interface @var{name} to " ++ "@var{flags}.") ++#define FUNC_NAME s_scm_set_network_interface_flags ++{ ++ struct ifreq ifr; ++ char *c_name; ++ int fd, err; ++ ++ socket = SCM_COERCE_OUTPORT (socket); ++ SCM_VALIDATE_OPFPORT (1, socket); ++ fd = SCM_FPORT_FDES (socket); ++ ++ memset (&ifr, 0, sizeof ifr); ++ c_name = scm_to_locale_string (name); ++ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1); ++ ifr.ifr_flags = scm_to_short (flags); ++ ++ err = ioctl (fd, SIOCSIFFLAGS, &ifr); ++ if (err != 0) ++ err = errno; ++ ++ free (c_name); ++ ++ if (err != 0) ++ { ++ errno = err; ++ SCM_SYSERROR; ++ } ++ ++ return SCM_UNSPECIFIED; ++} ++#undef FUNC_NAME ++ ++SCM_DEFINE (scm_network_interface_flags, "network-interface-flags", ++ 2, 0, 0, ++ (SCM socket, SCM name), ++ "Return the flags of network interface @var{name}.") ++#define FUNC_NAME s_scm_network_interface_flags ++{ ++ struct ifreq ifr; ++ char *c_name; ++ int fd, err; ++ ++ socket = SCM_COERCE_OUTPORT (socket); ++ SCM_VALIDATE_OPFPORT (1, socket); ++ fd = SCM_FPORT_FDES (socket); ++ ++ memset (&ifr, 0, sizeof ifr); ++ c_name = scm_to_locale_string (name); ++ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1); ++ ++ err = ioctl (fd, SIOCGIFFLAGS, &ifr); ++ if (err != 0) ++ err = errno; ++ ++ free (c_name); ++ ++ if (err != 0) ++ { ++ errno = err; ++ SCM_SYSERROR; ++ } ++ ++ return scm_from_short (ifr.ifr_flags); ++} ++#undef FUNC_NAME ++ + void + scm_init_posix () + { -- cgit v1.3 From e04f30e02307fb7660e3fb36ada8d5bcd53977f1 Mon Sep 17 00:00:00 2001 From: Nikita Karetnikov Date: Fri, 15 Feb 2013 10:46:29 +0000 Subject: gnu: Add GNU Parted. * gnu/packages/parted.scm: New file. * Makefile.am (MODULES): Add it. --- Makefile.am | 1 + gnu/packages/parted.scm | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 gnu/packages/parted.scm (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 9ab0709c6..84277ddc1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -124,6 +124,7 @@ MODULES = \ gnu/packages/oggvorbis.scm \ gnu/packages/openldap.scm \ gnu/packages/openssl.scm \ + gnu/packages/parted.scm \ gnu/packages/patchelf.scm \ gnu/packages/pcre.scm \ gnu/packages/pdf.scm \ diff --git a/gnu/packages/parted.scm b/gnu/packages/parted.scm new file mode 100644 index 000000000..b99c52e45 --- /dev/null +++ b/gnu/packages/parted.scm @@ -0,0 +1,71 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2013 Nikita Karetnikov +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu packages parted) + #:use-module (guix licenses) + #:use-module (guix packages) + #:use-module (guix download) + #:use-module (guix build-system gnu) + #:use-module (gnu packages check) + #:use-module ((gnu packages gettext) + #:renamer (symbol-prefix-proc 'guix:)) + #:use-module (gnu packages linux) + #:use-module (gnu packages readline)) + +(define-public parted + (package + (name "parted") + (version "3.1") + (source + (origin + (method url-fetch) + (uri (string-append "mirror://gnu/parted/parted-" + version ".tar.xz")) + (sha256 + (base32 + "05fa4m1bky9d13hqv91jlnngzlyn7y4rnnyq6d86w0dg3vww372y")))) + (build-system gnu-build-system) + (arguments `(#:configure-flags '("--disable-device-mapper") + #:phases (alist-cons-before + 'configure 'fix-mkswap + (lambda* (#:key inputs #:allow-other-keys) + (let ((util-linux (assoc-ref inputs + "util-linux"))) + (substitute* + "tests/t9050-partition-table-types.sh" + (("mkswap") + (string-append util-linux "/sbin/mkswap"))))) + %standard-phases))) + (inputs + ;; XXX: add 'lvm2'. + `(("check" ,check) + ("gettext" ,guix:gettext) + ("readline" ,readline) + ("util-linux" ,util-linux))) + (home-page "http://www.gnu.org/software/parted/") + (synopsis + "GNU Parted, a tool to manipulate partitions") + (description + "GNU Parted is an industrial-strength package for creating, destroying, +resizing, checking and copying partitions, and the file systems on them. This +is useful for creating space for new operating systems, reorganising disk +usage, copying data on hard disks and disk imaging. + +It contains a library, libparted, and a command-line frontend, parted, which +also serves as a sample implementation and script backend.") + (license gpl3+))) \ No newline at end of file -- cgit v1.3 From 161ed5476d27a69bbb940fd4a76f67976bd1d91e Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sat, 16 Feb 2013 02:09:10 +0100 Subject: gnu: qemu-kvm: Add patch to have multiple SMB shares. * gnu/packages/qemu.scm (qemu-kvm/smb-shares): New variable. * gnu/packages/patches/qemu-multiple-smb-shares.patch: New file. * Makefile.am (dist_patch_DATA): Add it. --- Makefile.am | 1 + gnu/packages/patches/qemu-multiple-smb-shares.patch | 20 ++++++++++++++++++++ gnu/packages/qemu.scm | 13 +++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 gnu/packages/patches/qemu-multiple-smb-shares.patch (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 84277ddc1..c9e3ca92f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -202,6 +202,7 @@ dist_patch_DATA = \ gnu/packages/patches/mcron-install.patch \ gnu/packages/patches/perl-no-sys-dirs.patch \ gnu/packages/patches/procps-make-3.82.patch \ + gnu/packages/patches/qemu-multiple-smb-shares.patch \ gnu/packages/patches/readline-link-ncurses.patch \ gnu/packages/patches/shishi-gets-undeclared.patch \ gnu/packages/patches/tar-gets-undeclared.patch \ diff --git a/gnu/packages/patches/qemu-multiple-smb-shares.patch b/gnu/packages/patches/qemu-multiple-smb-shares.patch new file mode 100644 index 000000000..c20066cbf --- /dev/null +++ b/gnu/packages/patches/qemu-multiple-smb-shares.patch @@ -0,0 +1,20 @@ +This file extends `-smb' to add a share for the Nix store, and changes +the name of the default share. + +--- a/net/slirp.c ++++ b/net/slirp.c +@@ -515,8 +515,12 @@ static int slirp_smb(SlirpState* s, const char *exported_dir, + "log file=%s/log.smbd\n" + "smb passwd file=%s/smbpasswd\n" + "security = share\n" +- "[qemu]\n" +- "path=%s\n" ++ "[store]\n" ++ "path=/nix/store\n" ++ "read only=yes\n" ++ "guest ok=yes\n" ++ "[xchg]\n" ++ "path=%s/xchg\n" + "read only=no\n" + "guest ok=yes\n", + s->smb_dir, diff --git a/gnu/packages/qemu.scm b/gnu/packages/qemu.scm index 785d47007..b10935ce0 100644 --- a/gnu/packages/qemu.scm +++ b/gnu/packages/qemu.scm @@ -22,6 +22,7 @@ #:use-module (guix utils) #:use-module ((guix licenses) #:select (gpl2)) #:use-module (guix build-system gnu) + #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages pkg-config) #:use-module (gnu packages glib) @@ -96,6 +97,18 @@ underway to get the required changes upstream.") ;; Many files are GPLv2+, but some are GPLv2-only---e.g., `memory.c'. (license gpl2))) +(define-public qemu-kvm/smb-shares + ;; A patched QEMU-KVM where `-net smb' yields two shares instead of one: one + ;; for the store, and another one for exchanges with the host. + (package (inherit qemu-kvm) + (name "qemu-kvm-with-multiple-smb-shares") + (inputs `(,@(package-inputs qemu-kvm) + ("patch/smb-shares" + ,(search-patch "qemu-multiple-smb-shares.patch")))) + (arguments + `(#:patches (list (assoc-ref %build-inputs "patch/smb-shares")) + ,@(package-arguments qemu-kvm))))) + (define-public qemu ;; The real one, with a complete target list. (package (inherit qemu-kvm) -- cgit v1.3 From f09d925b1632d5a8dd0999651dab6424847deeea Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sat, 16 Feb 2013 03:25:59 +0100 Subject: gnu: Add support for Guile in Linux initrd. * gnu/packages/linux-initrd.scm: New file. --- Makefile.am | 1 + gnu/packages/linux-initrd.scm | 288 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 gnu/packages/linux-initrd.scm (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index c9e3ca92f..f81516c22 100644 --- a/Makefile.am +++ b/Makefile.am @@ -107,6 +107,7 @@ MODULES = \ gnu/packages/libusb.scm \ gnu/packages/libunwind.scm \ gnu/packages/linux.scm \ + gnu/packages/linux-initrd.scm \ gnu/packages/lout.scm \ gnu/packages/lsh.scm \ gnu/packages/m4.scm \ diff --git a/gnu/packages/linux-initrd.scm b/gnu/packages/linux-initrd.scm new file mode 100644 index 000000000..348e411d0 --- /dev/null +++ b/gnu/packages/linux-initrd.scm @@ -0,0 +1,288 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2013 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu packages linux-initrd) + #:use-module (guix utils) + #:use-module (guix licenses) + #:use-module (gnu packages) + #:use-module (gnu packages cpio) + #:use-module (gnu packages compression) + #:use-module (gnu packages linux) + #:use-module ((gnu packages make-bootstrap) + #:select (%guile-static-stripped)) + #:use-module (guix packages) + #:use-module (guix download) + #:use-module (guix build-system trivial)) + + +;;; Commentary: +;;; +;;; Tools to build initial RAM disks (initrd's) for Linux-Libre, and in +;;; particular initrd's that run Guile. +;;; +;;; Code: + + +(define* (expression->initrd exp + #:key + (guile %guile-static-stripped) + (cpio cpio) + (gzip gzip) + (name "guile-initrd") + (system (%current-system)) + (linux #f) + (linux-modules '())) + "Return a package that contains a Linux initrd (a gzipped cpio archive) +containing GUILE and that evaluates EXP upon booting. LINUX-MODULES is a list +of `.ko' file names to be copied from LINUX into the initrd." + ;; TODO: Add a `modules' parameter. + + ;; General Linux overview in `Documentation/early-userspace/README' and + ;; `Documentation/filesystems/ramfs-rootfs-initramfs.txt'. + + (define builder + `(begin + (use-modules (guix build utils) + (ice-9 pretty-print) + (ice-9 popen) + (ice-9 match) + (ice-9 ftw) + (srfi srfi-26) + (system base compile) + (rnrs bytevectors) + ((system foreign) #:select (sizeof))) + + (let ((guile (assoc-ref %build-inputs "guile")) + (cpio (string-append (assoc-ref %build-inputs "cpio") + "/bin/cpio")) + (gzip (string-append (assoc-ref %build-inputs "gzip") + "/bin/gzip")) + (out (assoc-ref %outputs "out"))) + (mkdir out) + (mkdir "contents") + (with-directory-excursion "contents" + (copy-recursively guile ".") + (call-with-output-file "init" + (lambda (p) + (format p "#!/bin/guile -ds~%!#~%" guile) + (pretty-print ',exp p))) + (chmod "init" #o555) + (chmod "bin/guile" #o555) + + ;; Compile `init'. + (let ((go-dir (format #f ".cache/guile/ccache/~a-~a-~a-~a" + (effective-version) + (if (eq? (native-endianness) (endianness little)) + "LE" + "BE") + (sizeof '*) + (effective-version)))) + (mkdir-p go-dir) + (compile-file "init" + #:opts %auto-compilation-options + #:output-file (string-append go-dir "/init.go"))) + + (let* ((linux (assoc-ref %build-inputs "linux")) + (module-dir (and linux + (string-append linux "/lib/modules")))) + (mkdir "modules") + ,@(map (lambda (module) + `(match (find-files module-dir ,module) + ((file) + (format #t "copying '~a'...~%" file) + (copy-file file (string-append "modules/" + ,module))) + (() + (error "module not found" ,module module-dir)) + ((_ ...) + (error "several modules by that name" + ,module module-dir)))) + linux-modules)) + + ;; Reset the timestamps of all the files that will make it in the + ;; initrd. + (for-each (cut utime <> 0 0 0 0) + (find-files "." ".*")) + + (system* cpio "--version") + (let ((pipe (open-pipe* OPEN_WRITE cpio "-o" + "-O" (string-append out "/initrd") + "-H" "newc" "--null"))) + (define print0 + (let ((len (string-length "./"))) + (lambda (file) + (format pipe "~a\0" (string-drop file len))))) + + ;; Note: as per `ramfs-rootfs-initramfs.txt', always add + ;; directory entries before the files that are inside of it: "The + ;; Linux kernel cpio extractor won't create files in a directory + ;; that doesn't exist, so the directory entries must go before + ;; the files that go in those directories." + (file-system-fold (const #t) + (lambda (file stat result) ; leaf + (print0 file)) + (lambda (dir stat result) ; down + (unless (string=? dir ".") + (print0 dir))) + (const #f) ; up + (const #f) ; skip + (const #f) + #f + ".") + + (and (zero? (close-pipe pipe)) + (with-directory-excursion out + (and (zero? (system* gzip "--best" "initrd")) + (rename-file "initrd.gz" "initrd"))))))))) + + (let ((name* name)) + (package + (name name*) + (version "0") + (source #f) + (build-system trivial-build-system) + (arguments `(#:modules ((guix build utils)) + #:builder ,builder)) + (inputs `(("guile" ,guile) + ("cpio" ,cpio) + ("gzip" ,gzip) + ,@(if linux + `(("linux" ,linux)) + '()))) + (synopsis "An initial RAM disk (initrd) for the Linux kernel") + (description + "An initial RAM disk (initrd), really a gzipped cpio archive, for use by +the Linux kernel.") + (license gpl3+) + (home-page "http://www.gnu.org/software/guix/")))) + +(define-public qemu-initrd + (expression->initrd + '(begin + (use-modules (rnrs io ports) + (srfi srfi-1) + (srfi srfi-26) + (ice-9 match) + ((system foreign) #:select (string->pointer)) + ((system base compile) #:select (compile-file))) + + (display "Welcome, this is GNU/Guile!\n") + (display "Use '--repl' for an initrd REPL.\n\n") + + (mkdir "/proc") + (mount "none" "/proc" "proc") + + (mkdir "/sys") + (mount "none" "/sys" "sysfs") + + (let* ((command (string-trim-both + (call-with-input-file "/proc/cmdline" + get-string-all))) + (args (string-split command char-set:blank)) + (option (lambda (opt) + (let ((opt (string-append opt "="))) + (and=> (find (cut string-prefix? opt <>) + args) + (lambda (arg) + (substring arg (+ 1 (string-index arg #\=)))))))) + (to-load (option "--load")) + (root (option "--root"))) + + (when (member "--repl" args) + ((@ (system repl repl) start-repl))) + + (let ((slurp (lambda (module) + (call-with-input-file + (string-append "/modules/" module) + get-bytevector-all)))) + (display "loading CIFS and companion modules...\n") + (for-each (compose load-linux-module slurp) + (list "md4.ko" "ecb.ko" "cifs.ko"))) + + ;; See net/slirp.c for default QEMU networking values. + (display "configuring network...\n") + (let* ((sock (socket AF_INET SOCK_STREAM 0)) + (address (make-socket-address AF_INET + (inet-pton AF_INET + "10.0.2.10") + 0)) + (flags (network-interface-flags sock "eth0"))) + (set-network-interface-address sock "eth0" address) + (set-network-interface-flags sock "eth0" + (logior flags IFF_UP)) + (if (logand (network-interface-flags sock "eth0") IFF_UP) + (display "network interface is up\n") + (display "network interface is DOWN\n")) + + (mkdir "/etc") + (call-with-output-file "/etc/resolv.conf" + (lambda (p) + (display "nameserver 10.0.2.3\n" p))) + (sleep 1)) + + ;; Prepare the real root file system under /root. + (unless (file-exists? "/root") + (mkdir "/root")) + (if root + (mount root "/root" "ext3") + (mount "none" "/root" "tmpfs")) + (mkdir "/root/proc") + (mount "none" "/root/proc" "proc") + (mkdir "/root/sys") + (mount "none" "/root/sys" "sysfs") + (mkdir "/root/xchg") + (mkdir "/root/nix") + (mkdir "/root/nix/store") + + (mkdir "/root/dev") + (let ((makedev (lambda (major minor) + (+ (* major 256) minor)))) + (mknod "/root/dev/null" 'char-special #o666 (makedev 1 3)) + (mknod "/root/dev/zero" 'char-special #o666 (makedev 1 5))) + + ;; Mount the host's store and exchange directory. + (display "mounting QEMU's SMB shares...\n") + (let ((server "10.0.2.4")) + (mount (string-append "//" server "/store") "/root/nix/store" "cifs" 0 + (string->pointer "guest,sec=none")) + (mount (string-append "//" server "/xchg") "/root/xchg" "cifs" 0 + (string->pointer "guest,sec=none"))) + + (if to-load + (begin + (format #t "loading boot file '~a'...\n" to-load) + (compile-file (string-append "/root/" to-load) + #:output-file "/root/loader.go" + #:opts %auto-compilation-options) + (match (primitive-fork) + (0 + (chroot "/root") + (load-compiled "/loader.go")) + (pid + (format #t "boot file loaded under PID ~a~%" pid) + (let ((status (waitpid pid))) + (reboot))))) + (begin + (display "no boot file passed via '--load'\n") + (display "entering a warm and cozy REPL\n") + ((@ (system repl repl) start-repl)))))) + #:name "qemu-initrd" + #:linux linux-libre + #:linux-modules '("cifs.ko" "md4.ko" "ecb.ko"))) + +;;; linux-initrd.scm ends here -- cgit v1.3 From 040860152e63bbafb2eb3e93619e18d107c96b55 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sat, 16 Feb 2013 03:28:26 +0100 Subject: Add (gnu system vm). * gnu/system/vm.scm: New file. * Makefile.am (MODULES): Add it. --- Makefile.am | 3 +- gnu/system/vm.scm | 263 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 gnu/system/vm.scm (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index f81516c22..7a1b6ad16 100644 --- a/Makefile.am +++ b/Makefile.am @@ -160,7 +160,8 @@ MODULES = \ gnu/packages/which.scm \ gnu/packages/xml.scm \ gnu/packages/zile.scm \ - gnu/packages/zip.scm + gnu/packages/zip.scm \ + gnu/system/vm.scm GOBJECTS = $(MODULES:%.scm=%.go) guix/config.go diff --git a/gnu/system/vm.scm b/gnu/system/vm.scm new file mode 100644 index 000000000..3dae35d77 --- /dev/null +++ b/gnu/system/vm.scm @@ -0,0 +1,263 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2013 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu system vm) + #:use-module (guix store) + #:use-module (guix derivations) + #:use-module (guix packages) + #:use-module ((gnu packages base) #:select (%final-inputs guile-final)) + #:use-module (gnu packages qemu) + #:use-module (gnu packages parted) + #:use-module (gnu packages grub) + #:use-module (gnu packages linux) + #:use-module (gnu packages linux-initrd) + #:use-module ((gnu packages make-bootstrap) + #:select (%guile-static-stripped)) + #:use-module (srfi srfi-26) + #:use-module (ice-9 match) + #:export (expression->derivation-in-linux-vm + qemu-image)) + + +;;; Commentary: +;;; +;;; Tools to evaluate build expressions within virtual machines. +;;; +;;; Code: + +(define* (expression->derivation-in-linux-vm store name system exp inputs + #:key + (linux linux-libre) + (initrd qemu-initrd) + (qemu qemu-kvm/smb-shares) + (env-vars '()) + (modules '()) + (guile-for-build + (%guile-for-build)) + + (make-disk-image? #f) + (disk-image-size + (* 100 (expt 2 20)))) + "Evaluate EXP in a QEMU virtual machine running LINUX with INITRD. In the +virtual machine, EXP has access to all of INPUTS from the store; it should put +its output files in the `/xchg' directory, which is copied to the derivation's +output when the VM terminates. + +When MAKE-DISK-IMAGE? is true, then create a QEMU disk image of +DISK-IMAGE-SIZE bytes and return it." + (define input-alist + (map (match-lambda + ((input package) + `(,input . ,(package-output store package "out" system))) + ((input package sub-drv) + `(,input . ,(package-output store package sub-drv system)))) + inputs)) + + (define exp* + ;; EXP, but with INPUTS available. + `(let ((%build-inputs ',input-alist)) + ,exp)) + + (define builder + ;; Code that launches the VM that evaluates EXP. + `(begin + (use-modules (guix build utils)) + + (let ((out (assoc-ref %outputs "out")) + (cu (string-append (assoc-ref %build-inputs "coreutils") + "/bin")) + (qemu (string-append (assoc-ref %build-inputs "qemu") + "/bin/qemu-system-" + (car (string-split ,system #\-)))) + (img (string-append (assoc-ref %build-inputs "qemu") + "/bin/qemu-img")) + (linux (string-append (assoc-ref %build-inputs "linux") + "/bzImage")) + (initrd (string-append (assoc-ref %build-inputs "initrd") + "/initrd")) + (builder (assoc-ref %build-inputs "builder"))) + + ;; XXX: QEMU uses "rm -rf" when it's done to remove the temporary SMB + ;; directory, so it really needs `rm' in $PATH. + (setenv "PATH" cu) + + ,(if make-disk-image? + `(zero? (system* img "create" "image.qcow2" + ,(number->string disk-image-size))) + '(begin)) + + (mkdir "xchg") + (and (zero? + (system* qemu "-nographic" "-no-reboot" + "-net" "nic,model=e1000" + "-net" (string-append "user,smb=" (getcwd)) + "-kernel" linux + "-initrd" initrd + "-append" (string-append "console=ttyS0 --load=" + builder) + ,@(if make-disk-image? + '("-hda" "image.qcow2") + '()))) + ,(if make-disk-image? + '(copy-file "image.qcow2" ; XXX: who mkdir'd OUT? + out) + '(begin + (mkdir out) + (copy-recursively "xchg" out))))))) + + (let ((user-builder (add-text-to-store store "builder-in-linux-vm" + (object->string exp*) + '())) + (->drv (cut package-derivation store <> system)) + (coreutils (car (assoc-ref %final-inputs "coreutils")))) + (build-expression->derivation store name system builder + `(("qemu" ,(->drv qemu)) + ("linux" ,(->drv linux)) + ("initrd" ,(->drv initrd)) + ("coreutils" ,(->drv coreutils)) + ("builder" ,user-builder) + ,@(map (match-lambda + ((name package sub-drv ...) + `(,name ,(->drv package) + ,@sub-drv))) + inputs)) + #:env-vars env-vars + #:modules `((guix build utils) + ,@modules) + #:guile-for-build guile-for-build))) + +(define* (qemu-image store #:key + (name "qemu-image") + (system (%current-system)) + (disk-image-size (* 100 (expt 2 20))) + (linux linux-libre) + (initrd qemu-initrd) + (inputs '())) + "Return a bootable, stand-alone QEMU image." + (expression->derivation-in-linux-vm + store "qemu-image" system + `(let ((parted (string-append (assoc-ref %build-inputs "parted") + "/sbin/parted")) + (mkfs (string-append (assoc-ref %build-inputs "e2fsprogs") + "/sbin/mkfs.ext3")) + (grub (string-append (assoc-ref %build-inputs "grub") + "/sbin/grub-install")) + (umount (string-append (assoc-ref %build-inputs "util-linux") + "/bin/umount")) ; XXX: add to Guile + (initrd (string-append (assoc-ref %build-inputs "initrd") + "/initrd")) + (linux (string-append (assoc-ref %build-inputs "linux") + "/bzImage")) + (makedev (lambda (major minor) + (+ (* major 256) minor)))) + + ;; GRUB is full of shell scripts. + (setenv "PATH" + (string-append (dirname grub) ":" + (assoc-ref %build-inputs "coreutils") "/bin:" + (assoc-ref %build-inputs "findutils") "/bin:" + (assoc-ref %build-inputs "sed") "/bin:" + (assoc-ref %build-inputs "grep") "/bin:" + (assoc-ref %build-inputs "gawk") "/bin")) + + (display "creating partition table...\n") + (mknod "/dev/vda" 'block-special #o644 (makedev 8 0)) + (and (zero? (system* parted "/dev/vda" "mklabel" "msdos" + "mkpart" "primary" "ext2" "1MiB" + ,(format #f "~aB" + (- disk-image-size + (* 5 (expt 2 20)))))) + (begin + (display "creating ext3 partition...\n") + (mknod "/dev/vda1" 'block-special #o644 (makedev 8 1)) + (and (zero? (system* mkfs "-F" "/dev/vda1")) + (begin + (display "mounting partition...\n") + (mkdir "/fs") + (mount "/dev/vda1" "/fs" "ext3") + (mkdir "/fs/boot") + (mkdir "/fs/boot/grub") + (copy-file linux "/fs/boot/bzImage") + (copy-file initrd "/fs/boot/initrd") + (call-with-output-file "/fs/boot/grub/grub.cfg" + (lambda (p) + (display " +set timeout=10 +search.file /boot/bzImage + +menuentry \"Boot-to-Guile! Happy Birthday Guile 2.0! (Guile, Guix & co.)\" { + linux /boot/bzImage --repl + initrd /boot/initrd +}" p))) + (and (zero? + (system* grub "--no-floppy" + "--boot-directory" "/fs/boot" + "/dev/vda")) + (zero? + (system* umount "/fs")))))))) + `(("parted" ,parted) + ("grub" ,grub) + ("e2fsprogs" ,e2fsprogs) + ("linux" ,linux-libre) + ("initrd" ,qemu-initrd) + + ;; For shell scripts. + ("sed" ,(car (assoc-ref %final-inputs "sed"))) + ("grep" ,(car (assoc-ref %final-inputs "grep"))) + ("coreutils" ,(car (assoc-ref %final-inputs "coreutils"))) + ("findutils" ,(car (assoc-ref %final-inputs "findutils"))) + ("gawk" ,(car (assoc-ref %final-inputs "gawk"))) + ("util-linux" ,util-linux)) + #:make-disk-image? #t + #:disk-image-size disk-image-size)) + + +;;; +;;; Guile 2.0 potluck examples. +;;; + +(define (example1) + (let ((store #f)) + (dynamic-wind + (lambda () + (set! store (open-connection))) + (lambda () + (parameterize ((%guile-for-build (package-derivation store guile-final))) + (expression->derivation-in-linux-vm + store "vm-test" (%current-system) + '(begin + (display "hello from boot!\n") + (call-with-output-file "/xchg/hello" + (lambda (p) + (display "world" p)))) + '()))) + (lambda () + (close-connection store))))) + +(define (example2) + (let ((store #f)) + (dynamic-wind + (lambda () + (set! store (open-connection))) + (lambda () + (parameterize ((%guile-for-build (package-derivation store guile-final))) + (qemu-image store #:disk-image-size (* 30 (expt 2 20))))) + (lambda () + (close-connection store))))) + +;;; vm.scm ends here -- cgit v1.3 From e49951eb3e1e1a8e7bad6d7471483e70b0865352 Mon Sep 17 00:00:00 2001 From: Mark H Weaver Date: Thu, 14 Feb 2013 04:15:25 -0500 Subject: Replace individual scripts with master 'guix' script. * scripts/guix.in: New script. * Makefile.am (bin_SCRIPTS): Add 'scripts/guix'. Remove 'guix-build', 'guix-download', 'guix-import', 'guix-package', and 'guix-gc'. (MODULES): Add 'guix/scripts/build.scm', 'guix/scripts/download.scm', 'guix/scripts/import.scm', 'guix/scripts/package.scm', and 'guix/scripts/gc.scm'. * configure.ac (AC_CONFIG_FILES): Add 'scripts/guix'. Remove 'guix-build', 'guix-download', 'guix-import', 'guix-package', and 'guix-gc'. * guix-build.in, guix-download.in, guix-gc.in, guix-import.in, guix-package.in: Remove shell script boilerplate. Move to guix-COMMAND.in to guix/scripts/COMMAND.scm. Rename module from (guix-COMMAND) to (guix scripts COMMAND). Change "guix-COMMAND" to "guix COMMAND" in usage help string. * pre-inst-env.in: Add "@abs_top_builddir@/scripts" to the front of $PATH. Export $GUIX_UNINSTALLED. * tests/guix-build.sh, tests/guix-daemon.sh, tests/guix-download.sh, tests/guix-gc.sh, tests/guix-package.sh: Use "guix COMMAND" instead of "guix-COMMAND". * doc/guix.texi: Replace all occurrences of "guix-COMMAND" with "guix COMMAND". * po/POTFILES.in: Update. --- .gitignore | 6 +- Makefile.am | 11 +- configure.ac | 9 +- doc/guix.texi | 82 +++--- guix-build.in | 317 --------------------- guix-download.in | 164 ----------- guix-gc.in | 183 ------------ guix-import.in | 137 --------- guix-package.in | 706 ---------------------------------------------- guix/scripts/build.scm | 304 ++++++++++++++++++++ guix/scripts/download.scm | 151 ++++++++++ guix/scripts/gc.scm | 165 +++++++++++ guix/scripts/import.scm | 124 ++++++++ guix/scripts/package.scm | 693 +++++++++++++++++++++++++++++++++++++++++++++ guix/ui.scm | 38 ++- po/POTFILES.in | 8 +- pre-inst-env.in | 11 +- scripts/guix.in | 56 ++++ tests/guix-build.sh | 26 +- tests/guix-daemon.sh | 6 +- tests/guix-download.sh | 12 +- tests/guix-gc.sh | 24 +- tests/guix-package.sh | 56 ++-- 23 files changed, 1654 insertions(+), 1635 deletions(-) delete mode 100644 guix-build.in delete mode 100644 guix-download.in delete mode 100644 guix-gc.in delete mode 100644 guix-import.in delete mode 100644 guix-package.in create mode 100644 guix/scripts/build.scm create mode 100644 guix/scripts/download.scm create mode 100644 guix/scripts/gc.scm create mode 100644 guix/scripts/import.scm create mode 100644 guix/scripts/package.scm create mode 100644 scripts/guix.in (limited to 'Makefile.am') diff --git a/.gitignore b/.gitignore index ecdaed2ef..302e473fd 100644 --- a/.gitignore +++ b/.gitignore @@ -34,7 +34,6 @@ config.cache /po/remove-potcdate.sin /po/stamp-po /po/guix.pot -/guix-build /tests/*.trs /INSTALL /m4/* @@ -44,12 +43,9 @@ config.cache /doc/guix.pdf /doc/stamp-vti /doc/version.texi -/guix-download /gnu/packages/bootstrap/x86_64-linux/guile-2.0.7.tar.xz /gnu/packages/bootstrap/i686-linux/guile-2.0.7.tar.xz -/guix-package /guix/config.scm -/guix-import /nix/nix-daemon/nix-daemon.cc /nix/config.h /nix/config.h.in @@ -64,7 +60,7 @@ stamp-h[0-9] /nix/scripts/list-runtime-roots /test-env /nix/nix-setuid-helper/nix-setuid-helper.cc -/guix-gc +/scripts/guix /doc/guix.aux /doc/guix.cp /doc/guix.cps diff --git a/Makefile.am b/Makefile.am index 7a1b6ad16..5932e1350 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,17 +18,18 @@ # along with GNU Guix. If not, see . bin_SCRIPTS = \ - guix-build \ - guix-download \ - guix-import \ - guix-package \ - guix-gc + scripts/guix nodist_noinst_SCRIPTS = \ pre-inst-env \ test-env MODULES = \ + guix/scripts/build.scm \ + guix/scripts/download.scm \ + guix/scripts/import.scm \ + guix/scripts/package.scm \ + guix/scripts/gc.scm \ guix/base32.scm \ guix/utils.scm \ guix/derivations.scm \ diff --git a/configure.ac b/configure.ac index a9cf17ac5..dd1f843af 100644 --- a/configure.ac +++ b/configure.ac @@ -117,14 +117,9 @@ AC_CONFIG_FILES([Makefile po/Makefile.in guix/config.scm]) -AC_CONFIG_FILES([guix-build - guix-download - guix-import - guix-package - guix-gc +AC_CONFIG_FILES([scripts/guix pre-inst-env test-env], - [chmod +x guix-build guix-download guix-import guix-package guix-gc \ - pre-inst-env test-env]) + [chmod +x scripts/guix pre-inst-env test-env]) AC_OUTPUT diff --git a/doc/guix.texi b/doc/guix.texi index 80149326c..f84b37686 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -13,9 +13,9 @@ @dircategory Package management @direntry * guix: (guix). Guix, the functional package manager. -* guix-package: (guix)Invoking guix-package +* guix package: (guix)Invoking guix package Managing packages with Guix. -* guix-build: (guix)Invoking guix-build +* guix build: (guix)Invoking guix build Building packages with Guix. @end direntry @@ -196,7 +196,7 @@ are all performed by a specialized process, the @dfn{Guix daemon}, on behalf of clients. Only the daemon may access the store and its associated database. Thus, any operation that manipulates the store goes through the daemon. For instance, command-line tools such as -@command{guix-package} and @command{guix-build} communicate with the +@command{guix package} and @command{guix build} communicate with the daemon (@i{via} remote procedure calls) to instruct it what to do. In a standard multi-user setup, Guix and its daemon---the @@ -302,8 +302,8 @@ Use @var{n} CPU cores to build each derivation; @code{0} means as many as available. The default value is @code{1}, but it may be overridden by clients, such -as the @code{--cores} option of @command{guix-build} (@pxref{Invoking -guix-build}). +as the @code{--cores} option of @command{guix build} (@pxref{Invoking +guix build}). The effect is to define the @code{NIX_BUILD_CORES} environment variable in the build process, which can then use it to exploit internal @@ -319,7 +319,7 @@ Produce debugging output. This is useful to debug daemon start-up issues, but then it may be overridden by clients, for example the @code{--verbosity} option of -@command{guix-build} (@pxref{Invoking guix-build}). +@command{guix build} (@pxref{Invoking guix build}). @item --chroot-directory=@var{dir} Add @var{dir} to the build chroot. @@ -384,8 +384,8 @@ management tools it provides. @menu * Features:: How Guix will make your life brighter. -* Invoking guix-package:: Package installation, removal, etc. -* Invoking guix-gc:: Running the garbage collector. +* Invoking guix package:: Package installation, removal, etc. +* Invoking guix gc:: Running the garbage collector. @end menu @node Features @@ -408,14 +408,14 @@ simply continues to point to @file{/nix/store/@dots{}-gcc-4.8.0/bin/gcc}---i.e., both versions of GCC coexist on the same system without any interference. -The @command{guix-package} command is the central tool to manage -packages (@pxref{Invoking guix-package}). It operates on those per-user +The @command{guix package} command is the central tool to manage +packages (@pxref{Invoking guix package}). It operates on those per-user profiles, and can be used @emph{with normal user privileges}. The command provides the obvious install, remove, and upgrade operations. Each invocation is actually a @emph{transaction}: either the specified operation succeeds, or nothing happens. Thus, if the -@command{guix-package} process is terminated during the transaction, +@command{guix package} process is terminated during the transaction, or if a power outage occurs during the transaction, then the user's profile remains in its previous state, and remains usable. @@ -427,7 +427,7 @@ of their profile, which was known to work well. All those packages in the package store may be @emph{garbage-collected}. Guix can determine which packages are still referenced by the user profiles, and remove those that are provably no longer referenced -(@pxref{Invoking guix-gc}). Users may also explicitly remove old +(@pxref{Invoking guix gc}). Users may also explicitly remove old generations of their profile so that the packages they refer to can be collected. @@ -447,17 +447,17 @@ details.}. When a pre-built binary for a @file{/nix/store} path is available from an external source, Guix just downloads it; otherwise, it builds the package from source, locally. -@node Invoking guix-package -@section Invoking @command{guix-package} +@node Invoking guix package +@section Invoking @command{guix package} -The @command{guix-package} command is the tool that allows users to +The @command{guix package} command is the tool that allows users to install, upgrade, and remove packages, as well as rolling back to previous configurations. It operates only on the user's own profile, and works with normal user privileges (@pxref{Features}). Its syntax is: @example -guix-package @var{options} +guix package @var{options} @end example Primarily, @var{options} specifies the operations to be performed during @@ -473,13 +473,13 @@ variable, and so on. In a multi-user setup, user profiles must be stored in a place registered as a @dfn{garbage-collector root}, which -@file{$HOME/.guix-profile} points to (@pxref{Invoking guix-gc}). That +@file{$HOME/.guix-profile} points to (@pxref{Invoking guix gc}). That directory is normally @code{@var{localstatedir}/profiles/per-user/@var{user}}, where @var{localstatedir} is the value passed to @code{configure} as @code{--localstatedir}, and @var{user} is the user name. It must be created by @code{root}, with @var{user} as the owner. When it does not -exist, @command{guix-package} emits an error about it. +exist, @command{guix package} emits an error about it. The @var{options} can be among the following: @@ -548,7 +548,7 @@ useful to distribution developers. @end table -In addition to these actions @command{guix-package} supports the +In addition to these actions @command{guix package} supports the following options to query the current state of a profile, or the availability of packages: @@ -565,7 +565,7 @@ This allows specific fields to be extracted using the @command{recsel} command, for instance: @example -$ guix-package -s malloc | recsel -p name,version +$ guix package -s malloc | recsel -p name,version name: glibc version: 2.17 @@ -599,22 +599,22 @@ source location of its definition. @end table -@node Invoking guix-gc -@section Invoking @command{guix-gc} +@node Invoking guix gc +@section Invoking @command{guix gc} @cindex garbage collector Packages that are installed but not used may be @dfn{garbage-collected}. -The @command{guix-gc} command allows users to explicitly run the garbage +The @command{guix gc} command allows users to explicitly run the garbage collector to reclaim space from the @file{/nix/store} directory. The garbage collector has a set of known @dfn{roots}: any file under @file{/nix/store} reachable from a root is considered @dfn{live} and cannot be deleted; any other file is considered @dfn{dead} and may be deleted. The set of garbage collector roots includes default user -profiles, and may be augmented with @command{guix-build --root}, for -example (@pxref{Invoking guix-build}). +profiles, and may be augmented with @command{guix build --root}, for +example (@pxref{Invoking guix build}). -The @command{guix-gc} command has three modes of operation: it can be +The @command{guix gc} command has three modes of operation: it can be used to garbage-collect any dead files (the default), to delete specific files (the @code{--delete} option), or to print garbage-collector information. The available options are listed below: @@ -737,7 +737,7 @@ The @code{sha256} field specifies the expected SHA256 hash of the file being downloaded. It is mandatory, and allows Guix to check the integrity of the file. The @code{(base32 @dots{})} form introduces the base32 representation of the hash. A convenient way to obtain this -information is with the @code{guix-download} tool. +information is with the @code{guix download} tool. @item @cindex GNU Build System @@ -795,9 +795,9 @@ Guile process launched by the daemon (@pxref{Derivations}). Once a package definition is in place@footnote{Simple package definitions like the one above may be automatically converted from the -Nixpkgs distribution using the @command{guix-import} command.}, the -package may actually be built using the @code{guix-build} command-line -tool (@pxref{Invoking guix-build}). +Nixpkgs distribution using the @command{guix import} command.}, the +package may actually be built using the @code{guix build} command-line +tool (@pxref{Invoking guix build}). Behind the scenes, a derivation corresponding to the @code{} object is first computed by the @code{package-derivation} procedure. @@ -1015,22 +1015,22 @@ space. @chapter Utilities @menu -* Invoking guix-build:: Building packages from the command line. +* Invoking guix build:: Building packages from the command line. @end menu -@node Invoking guix-build -@section Invoking @command{guix-build} +@node Invoking guix build +@section Invoking @command{guix build} -The @command{guix-build} command builds packages or derivations and +The @command{guix build} command builds packages or derivations and their dependencies, and prints the resulting store paths. Note that it does not modify the user's profile---this is the job of the -@command{guix-package} command (@pxref{Invoking guix-package}). Thus, +@command{guix package} command (@pxref{Invoking guix package}). Thus, it is mainly useful for distribution developers. The general syntax is: @example -guix-build @var{options} @var{package-or-derivation}@dots{} +guix build @var{options} @var{package-or-derivation}@dots{} @end example @var{package-or-derivation} may be either the name of a package found in @@ -1058,7 +1058,7 @@ version 1.8 of Guile. Build the packages' source derivations, rather than the packages themselves. -For instance, @code{guix-build -S gcc} returns something like +For instance, @code{guix build -S gcc} returns something like @file{/nix/store/@dots{}-gcc-4.7.2.tar.bz2}, which is GCC's source tarball. @item --system=@var{system} @@ -1106,7 +1106,7 @@ may be helpful when debugging setup issues with the build daemon. @end table -Behind the scenes, @command{guix-build} is essentially an interface to +Behind the scenes, @command{guix build} is essentially an interface to the @code{package-derivation} procedure of the @code{(guix packages)} module, and to the @code{build-derivations} procedure of the @code{(guix store)} module. @@ -1121,11 +1121,11 @@ Guix comes with a distribution of free software@footnote{The term users of that software}.} that form the basis of the GNU system. This includes core GNU packages such as GNU libc, GCC, and Binutils, as well as many GNU and non-GNU applications. The complete list of available -packages can be seen by running @command{guix-package} (@pxref{Invoking -guix-package}): +packages can be seen by running @command{guix package} (@pxref{Invoking +guix package}): @example -guix-package --list-available +guix package --list-available @end example The package definitions of the distribution may are provided by Guile diff --git a/guix-build.in b/guix-build.in deleted file mode 100644 index 35ddb0086..000000000 --- a/guix-build.in +++ /dev/null @@ -1,317 +0,0 @@ -#!/bin/sh -# aside from this initial boilerplate, this is actually -*- scheme -*- code - -prefix="@prefix@" -datarootdir="@datarootdir@" - -GUILE_LOAD_COMPILED_PATH="@guilemoduledir@:$GUILE_LOAD_COMPILED_PATH" -export GUILE_LOAD_COMPILED_PATH - -main='(module-ref (resolve-interface '\''(guix-build)) '\'guix-build')' -exec ${GUILE-@GUILE@} -L "@guilemoduledir@" -l "$0" \ - -c "(apply $main (cdr (command-line)))" "$@" -!# -;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013 Ludovic Courtès -;;; Copyright © 2013 Mark H Weaver -;;; -;;; This file is part of GNU Guix. -;;; -;;; GNU Guix is free software; you can redistribute it and/or modify it -;;; under the terms of the GNU General Public License as published by -;;; the Free Software Foundation; either version 3 of the License, or (at -;;; your option) any later version. -;;; -;;; GNU Guix is distributed in the hope that it will be useful, but -;;; WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;;; GNU General Public License for more details. -;;; -;;; You should have received a copy of the GNU General Public License -;;; along with GNU Guix. If not, see . - -(define-module (guix-build) - #:use-module (guix ui) - #:use-module (guix store) - #:use-module (guix derivations) - #:use-module (guix packages) - #:use-module (guix utils) - #:use-module (ice-9 format) - #:use-module (ice-9 match) - #:use-module (ice-9 vlist) - #:use-module (srfi srfi-1) - #:use-module (srfi srfi-11) - #:use-module (srfi srfi-26) - #:use-module (srfi srfi-34) - #:use-module (srfi srfi-37) - #:autoload (gnu packages) (find-packages-by-name - find-newest-available-packages) - #:export (guix-build)) - -(define %store - (make-parameter #f)) - -(define (derivations-from-package-expressions exp system source?) - "Eval EXP and return the corresponding derivation path for SYSTEM. -When SOURCE? is true, return the derivations of the package sources." - (let ((p (eval exp (current-module)))) - (if (package? p) - (if source? - (let ((source (package-source p)) - (loc (package-location p))) - (if source - (package-source-derivation (%store) source) - (leave (_ "~a: error: package `~a' has no source~%") - (location->string loc) (package-name p)))) - (package-derivation (%store) p system)) - (leave (_ "expression `~s' does not evaluate to a package~%") - exp)))) - - -;;; -;;; Command-line options. -;;; - -(define %default-options - ;; Alist of default option values. - `((system . ,(%current-system)) - (substitutes? . #t) - (verbosity . 0))) - -(define (show-help) - (display (_ "Usage: guix-build [OPTION]... PACKAGE-OR-DERIVATION... -Build the given PACKAGE-OR-DERIVATION and return their output paths.\n")) - (display (_ " - -e, --expression=EXPR build the package EXPR evaluates to")) - (display (_ " - -S, --source build the packages' source derivations")) - (display (_ " - -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\"")) - (display (_ " - -d, --derivations return the derivation paths of the given packages")) - (display (_ " - -K, --keep-failed keep build tree of failed builds")) - (display (_ " - -n, --dry-run do not build the derivations")) - (display (_ " - --no-substitutes build instead of resorting to pre-built substitutes")) - (display (_ " - -c, --cores=N allow the use of up to N CPU cores for the build")) - (display (_ " - -r, --root=FILE make FILE a symlink to the result, and register it - as a garbage collector root")) - (display (_ " - --verbosity=LEVEL use the given verbosity LEVEL")) - (newline) - (display (_ " - -h, --help display this help and exit")) - (display (_ " - -V, --version display version information and exit")) - (newline) - (show-bug-report-information)) - -(define %options - ;; Specifications of the command-line options. - (list (option '(#\h "help") #f #f - (lambda args - (show-help) - (exit 0))) - (option '(#\V "version") #f #f - (lambda args - (show-version-and-exit "guix-build"))) - - (option '(#\S "source") #f #f - (lambda (opt name arg result) - (alist-cons 'source? #t result))) - (option '(#\s "system") #t #f - (lambda (opt name arg result) - (alist-cons 'system arg - (alist-delete 'system result eq?)))) - (option '(#\d "derivations") #f #f - (lambda (opt name arg result) - (alist-cons 'derivations-only? #t result))) - (option '(#\e "expression") #t #f - (lambda (opt name arg result) - (alist-cons 'expression - (call-with-input-string arg read) - result))) - (option '(#\K "keep-failed") #f #f - (lambda (opt name arg result) - (alist-cons 'keep-failed? #t result))) - (option '(#\c "cores") #t #f - (lambda (opt name arg result) - (let ((c (false-if-exception (string->number arg)))) - (if c - (alist-cons 'cores c result) - (leave (_ "~a: not a number~%") arg))))) - (option '(#\n "dry-run") #f #f - (lambda (opt name arg result) - (alist-cons 'dry-run? #t result))) - (option '("no-substitutes") #f #f - (lambda (opt name arg result) - (alist-cons 'substitutes? #f - (alist-delete 'substitutes? result)))) - (option '(#\r "root") #t #f - (lambda (opt name arg result) - (alist-cons 'gc-root arg result))) - (option '("verbosity") #t #f - (lambda (opt name arg result) - (let ((level (string->number arg))) - (alist-cons 'verbosity level - (alist-delete 'verbosity result))))))) - - -;;; -;;; Entry point. -;;; - -(define (guix-build . args) - (define (parse-options) - ;; Return the alist of option values. - (args-fold args %options - (lambda (opt name arg result) - (leave (_ "~A: unrecognized option~%") name)) - (lambda (arg result) - (alist-cons 'argument arg result)) - %default-options)) - - (define (register-root paths root) - ;; Register ROOT as an indirect GC root for all of PATHS. - (let* ((root (string-append (canonicalize-path (dirname root)) - "/" root))) - (catch 'system-error - (lambda () - (match paths - ((path) - (symlink path root) - (add-indirect-root (%store) root)) - ((paths ...) - (fold (lambda (path count) - (let ((root (string-append root "-" (number->string count)))) - (symlink path root) - (add-indirect-root (%store) root)) - (+ 1 count)) - 0 - paths)))) - (lambda args - (format (current-error-port) - (_ "failed to create GC root `~a': ~a~%") - root (strerror (system-error-errno args))) - (exit 1))))) - - (define newest-available-packages - (memoize find-newest-available-packages)) - - (define (find-best-packages-by-name name version) - (if version - (find-packages-by-name name version) - (match (vhash-assoc name (newest-available-packages)) - ((_ version pkgs ...) pkgs) - (#f '())))) - - (define (find-package request) - ;; Return a package matching REQUEST. REQUEST may be a package - ;; name, or a package name followed by a hyphen and a version - ;; number. If the version number is not present, return the - ;; preferred newest version. - (let-values (((name version) - (package-name->name+version request))) - (match (find-best-packages-by-name name version) - ((p) ; one match - p) - ((p x ...) ; several matches - (format (current-error-port) - (_ "warning: ambiguous package specification `~a'~%") - request) - (format (current-error-port) - (_ "warning: choosing ~a from ~a~%") - (package-full-name p) - (location->string (package-location p))) - p) - (_ ; no matches - (if version - (leave (_ "~A: package not found for version ~a~%") - name version) - (leave (_ "~A: unknown package~%") name)))))) - - (install-locale) - (textdomain "guix") - (setvbuf (current-output-port) _IOLBF) - (setvbuf (current-error-port) _IOLBF) - - (with-error-handling - (let ((opts (parse-options))) - (parameterize ((%store (open-connection))) - (let* ((src? (assoc-ref opts 'source?)) - (sys (assoc-ref opts 'system)) - (drv (filter-map (match-lambda - (('expression . exp) - (derivations-from-package-expressions exp sys - src?)) - (('argument . (? derivation-path? drv)) - drv) - (('argument . (? string? x)) - (let ((p (find-package x))) - (if src? - (let ((s (package-source p))) - (package-source-derivation - (%store) s)) - (package-derivation (%store) p sys)))) - (_ #f)) - opts)) - (req (append-map (lambda (drv-path) - (let ((d (call-with-input-file drv-path - read-derivation))) - (derivation-prerequisites-to-build (%store) d))) - drv)) - (req* (delete-duplicates - (append (remove (compose (cut valid-path? (%store) <>) - derivation-path->output-path) - drv) - (map derivation-input-path req)))) - (roots (filter-map (match-lambda - (('gc-root . root) root) - (_ #f)) - opts))) - (if (assoc-ref opts 'dry-run?) - (format (current-error-port) - (N_ "~:[the following derivation would be built:~%~{ ~a~%~}~;~]" - "~:[the following derivations would be built:~%~{ ~a~%~}~;~]" - (length req*)) - (null? req*) req*) - (format (current-error-port) - (N_ "~:[the following derivation will be built:~%~{ ~a~%~}~;~]" - "~:[the following derivations will be built:~%~{ ~a~%~}~;~]" - (length req*)) - (null? req*) req*)) - - ;; TODO: Add more options. - (set-build-options (%store) - #:keep-failed? (assoc-ref opts 'keep-failed?) - #:build-cores (or (assoc-ref opts 'cores) 0) - #:use-substitutes? (assoc-ref opts 'substitutes?) - #:verbosity (assoc-ref opts 'verbosity)) - - (if (assoc-ref opts 'derivations-only?) - (begin - (format #t "~{~a~%~}" drv) - (for-each (cut register-root <> <>) - (map list drv) roots)) - (or (assoc-ref opts 'dry-run?) - (and (build-derivations (%store) drv) - (for-each (lambda (d) - (let ((drv (call-with-input-file d - read-derivation))) - (format #t "~{~a~%~}" - (map (match-lambda - ((out-name . out) - (derivation-path->output-path - d out-name))) - (derivation-outputs drv))))) - drv) - (for-each (cut register-root <> <>) - (map (lambda (drv) - (map cdr - (derivation-path->output-paths drv))) - drv) - roots))))))))) diff --git a/guix-download.in b/guix-download.in deleted file mode 100644 index ea62b09a7..000000000 --- a/guix-download.in +++ /dev/null @@ -1,164 +0,0 @@ -#!/bin/sh -# aside from this initial boilerplate, this is actually -*- scheme -*- code - -prefix="@prefix@" -datarootdir="@datarootdir@" - -GUILE_LOAD_COMPILED_PATH="@guilemoduledir@:$GUILE_LOAD_COMPILED_PATH" -export GUILE_LOAD_COMPILED_PATH - -main='(module-ref (resolve-interface '\''(guix-download)) '\'guix-download')' -exec ${GUILE-@GUILE@} -L "@guilemoduledir@" -l "$0" \ - -c "(apply $main (cdr (command-line)))" "$@" -!# -;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013 Ludovic Courtès -;;; -;;; This file is part of GNU Guix. -;;; -;;; GNU Guix is free software; you can redistribute it and/or modify it -;;; under the terms of the GNU General Public License as published by -;;; the Free Software Foundation; either version 3 of the License, or (at -;;; your option) any later version. -;;; -;;; GNU Guix is distributed in the hope that it will be useful, but -;;; WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;;; GNU General Public License for more details. -;;; -;;; You should have received a copy of the GNU General Public License -;;; along with GNU Guix. If not, see . - -(define-module (guix-download) - #:use-module (guix ui) - #:use-module (guix store) - #:use-module (guix utils) - #:use-module (guix base32) - #:use-module ((guix download) #:select (%mirrors)) - #:use-module (guix build download) - #:use-module (web uri) - #:use-module (ice-9 match) - #:use-module (srfi srfi-1) - #:use-module (srfi srfi-11) - #:use-module (srfi srfi-26) - #:use-module (srfi srfi-37) - #:use-module (rnrs bytevectors) - #:use-module (rnrs io ports) - #:export (guix-download)) - -(define (call-with-temporary-output-file proc) - (let* ((template (string-copy "guix-download.XXXXXX")) - (out (mkstemp! template))) - (dynamic-wind - (lambda () - #t) - (lambda () - (proc template out)) - (lambda () - (false-if-exception (delete-file template)))))) - -(define (fetch-and-store store fetch name) - "Call FETCH for URI, and pass it the name of a file to write to; eventually, -copy data from that port to STORE, under NAME. Return the resulting -store path." - (call-with-temporary-output-file - (lambda (temp port) - (let ((result - (parameterize ((current-output-port (current-error-port))) - (fetch temp)))) - (close port) - (and result - (add-to-store store name #f "sha256" temp)))))) - -;;; -;;; Command-line options. -;;; - -(define %default-options - ;; Alist of default option values. - `((format . ,bytevector->nix-base32-string))) - -(define (show-help) - (display (_ "Usage: guix-download [OPTION]... URL -Download the file at URL, add it to the store, and print its store path -and the hash of its contents.\n")) - (format #t (_ " - -f, --format=FMT write the hash in the given format (default: `nix-base32')")) - (newline) - (display (_ " - -h, --help display this help and exit")) - (display (_ " - -V, --version display version information and exit")) - (newline) - (show-bug-report-information)) - -(define %options - ;; Specifications of the command-line options. - (list (option '(#\f "format") #t #f - (lambda (opt name arg result) - (define fmt-proc - (match arg - ("nix-base32" - bytevector->nix-base32-string) - ("base32" - bytevector->base32-string) - ((or "base16" "hex" "hexadecimal") - bytevector->base16-string) - (x - (format (current-error-port) - "unsupported hash format: ~a~%" arg)))) - - (alist-cons 'format fmt-proc - (alist-delete 'format result)))) - - (option '(#\h "help") #f #f - (lambda args - (show-help) - (exit 0))) - (option '(#\V "version") #f #f - (lambda args - (show-version-and-exit "guix-download"))))) - - -;;; -;;; Entry point. -;;; - -(define (guix-download . args) - (define (parse-options) - ;; Return the alist of option values. - (args-fold args %options - (lambda (opt name arg result) - (leave (_ "~A: unrecognized option~%") name)) - (lambda (arg result) - (alist-cons 'argument arg result)) - %default-options)) - - (install-locale) - (textdomain "guix") - (setvbuf (current-output-port) _IOLBF) - (setvbuf (current-error-port) _IOLBF) - - (let* ((opts (parse-options)) - (store (open-connection)) - (arg (assq-ref opts 'argument)) - (uri (or (string->uri arg) - (leave (_ "guix-download: ~a: failed to parse URI~%") - arg))) - (path (case (uri-scheme uri) - ((file) - (add-to-store store (basename (uri-path uri)) - #f "sha256" (uri-path uri))) - (else - (fetch-and-store store - (cut url-fetch arg <> - #:mirrors %mirrors) - (basename (uri-path uri)))))) - (hash (call-with-input-file - (or path - (leave (_ "guix-download: ~a: download failed~%") - arg)) - (compose sha256 get-bytevector-all))) - (fmt (assq-ref opts 'format))) - (format #t "~a~%~a~%" path (fmt hash)) - #t)) diff --git a/guix-gc.in b/guix-gc.in deleted file mode 100644 index 1a4a5413d..000000000 --- a/guix-gc.in +++ /dev/null @@ -1,183 +0,0 @@ -#!/bin/sh -# aside from this initial boilerplate, this is actually -*- scheme -*- code - -prefix="@prefix@" -datarootdir="@datarootdir@" - -GUILE_LOAD_COMPILED_PATH="@guilemoduledir@:$GUILE_LOAD_COMPILED_PATH" -export GUILE_LOAD_COMPILED_PATH - -main='(module-ref (resolve-interface '\''(guix-gc)) '\'guix-gc')' -exec ${GUILE-@GUILE@} -L "@guilemoduledir@" -l "$0" \ - -c "(apply $main (cdr (command-line)))" "$@" -!# -;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013 Ludovic Courtès -;;; -;;; This file is part of GNU Guix. -;;; -;;; GNU Guix is free software; you can redistribute it and/or modify it -;;; under the terms of the GNU General Public License as published by -;;; the Free Software Foundation; either version 3 of the License, or (at -;;; your option) any later version. -;;; -;;; GNU Guix is distributed in the hope that it will be useful, but -;;; WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;;; GNU General Public License for more details. -;;; -;;; You should have received a copy of the GNU General Public License -;;; along with GNU Guix. If not, see . - -(define-module (guix-gc) - #:use-module (guix ui) - #:use-module (guix store) - #:use-module (ice-9 match) - #:use-module (srfi srfi-1) - #:use-module (srfi srfi-26) - #:use-module (srfi srfi-37) - #:export (guix-gc)) - - -;;; -;;; Command-line options. -;;; - -(define %default-options - ;; Alist of default option values. - `((action . collect-garbage))) - -(define (show-help) - (display (_ "Usage: guix-gc [OPTION]... PATHS... -Invoke the garbage collector.\n")) - (display (_ " - -C, --collect-garbage[=MIN] - collect at least MIN bytes of garbage")) - (display (_ " - -d, --delete attempt to delete PATHS")) - (display (_ " - --list-dead list dead paths")) - (display (_ " - --list-live list live paths")) - (newline) - (display (_ " - -h, --help display this help and exit")) - (display (_ " - -V, --version display version information and exit")) - (newline) - (show-bug-report-information)) - -(define (size->number str) - "Convert STR, a storage measurement representation such as \"1024\" or -\"1MiB\", to a number of bytes. Raise an error if STR could not be -interpreted." - (define unit-pos - (string-rindex str char-set:digit)) - - (define unit - (and unit-pos (substring str (+ 1 unit-pos)))) - - (let* ((numstr (if unit-pos - (substring str 0 (+ 1 unit-pos)) - str)) - (num (string->number numstr))) - (if num - (* num - (match unit - ("KiB" (expt 2 10)) - ("MiB" (expt 2 20)) - ("GiB" (expt 2 30)) - ("TiB" (expt 2 40)) - ("KB" (expt 10 3)) - ("MB" (expt 10 6)) - ("GB" (expt 10 9)) - ("TB" (expt 10 12)) - ("" 1) - (_ - (format (current-error-port) (_ "error: unknown unit: ~a~%") - unit) - (exit 1)))) - (begin - (format (current-error-port) - (_ "error: invalid number: ~a") numstr) - (exit 1))))) - -(define %options - ;; Specification of the command-line options. - (list (option '(#\h "help") #f #f - (lambda args - (show-help) - (exit 0))) - (option '(#\V "version") #f #f - (lambda args - (show-version-and-exit "guix-gc"))) - - (option '(#\C "collect-garbage") #f #t - (lambda (opt name arg result) - (let ((result (alist-cons 'action 'collect-garbage - (alist-delete 'action result)))) - (match arg - ((? string?) - (let ((amount (size->number arg))) - (if arg - (alist-cons 'min-freed amount result) - (begin - (format (current-error-port) - (_ "error: invalid amount of storage: ~a~%") - arg) - (exit 1))))) - (#f result))))) - (option '(#\d "delete") #f #f - (lambda (opt name arg result) - (alist-cons 'action 'delete - (alist-delete 'action result)))) - (option '("list-dead") #f #f - (lambda (opt name arg result) - (alist-cons 'action 'list-dead - (alist-delete 'action result)))) - (option '("list-live") #f #f - (lambda (opt name arg result) - (alist-cons 'action 'list-live - (alist-delete 'action result)))))) - - -;;; -;;; Entry point. -;;; - -(define (guix-gc . args) - (define (parse-options) - ;; Return the alist of option values. - (args-fold args %options - (lambda (opt name arg result) - (leave (_ "~A: unrecognized option~%") name)) - (lambda (arg result) - (alist-cons 'argument arg result)) - %default-options)) - - (install-locale) - (textdomain "guix") - (setvbuf (current-output-port) _IOLBF) - (setvbuf (current-error-port) _IOLBF) - - (with-error-handling - (let ((opts (parse-options)) - (store (open-connection))) - (case (assoc-ref opts 'action) - ((collect-garbage) - (let ((min-freed (assoc-ref opts 'min-freed))) - (if min-freed - (collect-garbage store min-freed) - (collect-garbage store)))) - ((delete) - (let ((paths (filter-map (match-lambda - (('argument . arg) arg) - (_ #f)) - opts))) - (delete-paths store paths))) - ((list-dead) - (for-each (cut simple-format #t "~a~%" <>) - (dead-paths store))) - ((list-live) - (for-each (cut simple-format #t "~a~%" <>) - (live-paths store))))))) diff --git a/guix-import.in b/guix-import.in deleted file mode 100644 index 97619a9a5..000000000 --- a/guix-import.in +++ /dev/null @@ -1,137 +0,0 @@ -#!/bin/sh -# aside from this initial boilerplate, this is actually -*- scheme -*- code - -prefix="@prefix@" -datarootdir="@datarootdir@" - -GUILE_LOAD_COMPILED_PATH="@guilemoduledir@:$GUILE_LOAD_COMPILED_PATH" -export GUILE_LOAD_COMPILED_PATH - -main='(module-ref (resolve-interface '\''(guix-import)) '\'guix-import')' -exec ${GUILE-@GUILE@} -L "@guilemoduledir@" -l "$0" \ - -c "(apply $main (cdr (command-line)))" "$@" -!# -;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013 Ludovic Courtès -;;; -;;; This file is part of GNU Guix. -;;; -;;; GNU Guix is free software; you can redistribute it and/or modify it -;;; under the terms of the GNU General Public License as published by -;;; the Free Software Foundation; either version 3 of the License, or (at -;;; your option) any later version. -;;; -;;; GNU Guix is distributed in the hope that it will be useful, but -;;; WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;;; GNU General Public License for more details. -;;; -;;; You should have received a copy of the GNU General Public License -;;; along with GNU Guix. If not, see . - -(define-module (guix-import) - #:use-module (guix ui) - #:use-module (guix snix) - #:use-module (guix utils) - #:use-module (srfi srfi-1) - #:use-module (srfi srfi-11) - #:use-module (srfi srfi-26) - #:use-module (srfi srfi-37) - #:use-module (ice-9 match) - #:use-module (ice-9 pretty-print) - #:export (guix-import)) - - -;;; -;;; Helper. -;;; - -(define (newline-rewriting-port output) - "Return an output port that rewrites strings containing the \\n escape -to an actual newline. This works around the behavior of `pretty-print' -and `write', which output these as \\n instead of actual newlines, -whereas we want the `description' field to contain actual newlines -rather than \\n." - (define (write-string str) - (let loop ((chars (string->list str))) - (match chars - (() - #t) - ((#\\ #\n rest ...) - (newline output) - (loop rest)) - ((chr rest ...) - (write-char chr output) - (loop rest))))) - - (make-soft-port (vector (cut write-char <>) - write-string - (lambda _ #t) ; flush - #f - (lambda _ #t) ; close - #f) - "w")) - - -;;; -;;; Command-line options. -;;; - -(define %default-options - '()) - -(define (show-help) - (display (_ "Usage: guix-import NIXPKGS ATTRIBUTE -Import and convert the Nix expression ATTRIBUTE of NIXPKGS.\n")) - (display (_ " - -h, --help display this help and exit")) - (display (_ " - -V, --version display version information and exit")) - (newline) - (show-bug-report-information)) - -(define %options - ;; Specification of the command-line options. - (list (option '(#\h "help") #f #f - (lambda args - (show-help) - (exit 0))) - (option '(#\V "version") #f #f - (lambda args - (show-version-and-exit "guix-import"))))) - - -;;; -;;; Entry point. -;;; - -(define (guix-import . args) - (define (parse-options) - ;; Return the alist of option values. - (args-fold args %options - (lambda (opt name arg result) - (leave (_ "~A: unrecognized option~%") name)) - (lambda (arg result) - (alist-cons 'argument arg result)) - %default-options)) - - (install-locale) - (textdomain "guix") - (setvbuf (current-output-port) _IOLBF) - (setvbuf (current-error-port) _IOLBF) - - (let* ((opts (parse-options)) - (args (filter-map (match-lambda - (('argument . value) - value) - (_ #f)) - (reverse opts)))) - (match args - ((nixpkgs attribute) - (let-values (((expr loc) - (nixpkgs->guix-package nixpkgs attribute))) - (format #t ";; converted from ~a:~a~%~%" - (location-file loc) (location-line loc)) - (pretty-print expr (newline-rewriting-port (current-output-port))))) - (_ - (leave (_ "wrong number of arguments~%")))))) diff --git a/guix-package.in b/guix-package.in deleted file mode 100644 index 584481acd..000000000 --- a/guix-package.in +++ /dev/null @@ -1,706 +0,0 @@ -#!/bin/sh -# aside from this initial boilerplate, this is actually -*- scheme -*- code - -prefix="@prefix@" -datarootdir="@datarootdir@" - -GUILE_LOAD_COMPILED_PATH="@guilemoduledir@:$GUILE_LOAD_COMPILED_PATH" -export GUILE_LOAD_COMPILED_PATH - -main='(module-ref (resolve-interface '\''(guix-package)) '\'guix-package')' -exec ${GUILE-@GUILE@} -L "@guilemoduledir@" -l "$0" \ - -c "(apply $main (cdr (command-line)))" "$@" -!# -;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013 Ludovic Courtès -;;; Copyright © 2013 Nikita Karetnikov -;;; Copyright © 2013 Mark H Weaver -;;; -;;; This file is part of GNU Guix. -;;; -;;; GNU Guix is free software; you can redistribute it and/or modify it -;;; under the terms of the GNU General Public License as published by -;;; the Free Software Foundation; either version 3 of the License, or (at -;;; your option) any later version. -;;; -;;; GNU Guix is distributed in the hope that it will be useful, but -;;; WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;;; GNU General Public License for more details. -;;; -;;; You should have received a copy of the GNU General Public License -;;; along with GNU Guix. If not, see . - -(define-module (guix-package) - #:use-module (guix ui) - #:use-module (guix store) - #:use-module (guix derivations) - #:use-module (guix packages) - #:use-module (guix utils) - #:use-module (guix config) - #:use-module ((guix build utils) #:select (directory-exists? mkdir-p)) - #:use-module (ice-9 ftw) - #:use-module (ice-9 format) - #:use-module (ice-9 match) - #:use-module (ice-9 regex) - #:use-module (ice-9 vlist) - #:use-module (srfi srfi-1) - #:use-module (srfi srfi-11) - #:use-module (srfi srfi-26) - #:use-module (srfi srfi-34) - #:use-module (srfi srfi-37) - #:use-module (gnu packages) - #:use-module ((gnu packages base) #:select (guile-final)) - #:use-module ((gnu packages bootstrap) #:select (%bootstrap-guile)) - #:export (guix-package)) - -(define %store - (make-parameter #f)) - - -;;; -;;; User environment. -;;; - -(define %user-environment-directory - (and=> (getenv "HOME") - (cut string-append <> "/.guix-profile"))) - -(define %profile-directory - (string-append (or (getenv "NIX_STATE_DIR") %state-directory) "/profiles/" - (or (and=> (getenv "USER") - (cut string-append "per-user/" <>)) - "default"))) - -(define %current-profile - ;; Call it `guix-profile', not `profile', to allow Guix profiles to - ;; coexist with Nix profiles. - (string-append %profile-directory "/guix-profile")) - -(define (profile-manifest profile) - "Return the PROFILE's manifest." - (let ((manifest (string-append profile "/manifest"))) - (if (file-exists? manifest) - (call-with-input-file manifest read) - '(manifest (version 1) (packages ()))))) - -(define (manifest-packages manifest) - "Return the packages listed in MANIFEST." - (match manifest - (('manifest ('version 0) - ('packages ((name version output path) ...))) - (zip name version output path - (make-list (length name) '()))) - - ;; Version 1 adds a list of propagated inputs to the - ;; name/version/output/path tuples. - (('manifest ('version 1) - ('packages (packages ...))) - packages) - - (_ - (error "unsupported manifest format" manifest)))) - -(define (profile-regexp profile) - "Return a regular expression that matches PROFILE's name and number." - (make-regexp (string-append "^" (regexp-quote (basename profile)) - "-([0-9]+)"))) - -(define (profile-numbers profile) - "Return the list of generation numbers of PROFILE, or '(0) if no -former profiles were found." - (define* (scandir name #:optional (select? (const #t)) - (entry (file-system-fold enter? leaf down up skip error #f name lstat) - (lambda (files) - (sort files entry)) - (#f ; no profile directory - '(0)) - (() ; no profiles - '(0)) - ((profiles ...) ; former profiles around - (map (compose string->number - (cut match:substring <> 1) - (cute regexp-exec (profile-regexp profile) <>)) - profiles)))) - -(define (previous-profile-number profile number) - "Return the number of the generation before generation NUMBER of -PROFILE, or 0 if none exists. It could be NUMBER - 1, but it's not the -case when generations have been deleted (there are \"holes\")." - (fold (lambda (candidate highest) - (if (and (< candidate number) (> candidate highest)) - candidate - highest)) - 0 - (profile-numbers profile))) - -(define (profile-derivation store packages) - "Return a derivation that builds a profile (a user environment) with -all of PACKAGES, a list of name/version/output/path/deps tuples." - (define builder - `(begin - (use-modules (ice-9 pretty-print) - (guix build union)) - - (setvbuf (current-output-port) _IOLBF) - (setvbuf (current-error-port) _IOLBF) - - (let ((output (assoc-ref %outputs "out")) - (inputs (map cdr %build-inputs))) - (format #t "building user environment `~a' with ~a packages...~%" - output (length inputs)) - (union-build output inputs) - (call-with-output-file (string-append output "/manifest") - (lambda (p) - (pretty-print '(manifest (version 1) - (packages ,packages)) - p)))))) - - (build-expression->derivation store "user-environment" - (%current-system) - builder - (append-map (match-lambda - ((name version output path deps) - `((,name ,path) - ,@deps))) - packages) - #:modules '((guix build union)))) - -(define (profile-number profile) - "Return PROFILE's number or 0. An absolute file name must be used." - (or (and=> (false-if-exception (regexp-exec (profile-regexp profile) - (basename (readlink profile)))) - (compose string->number (cut match:substring <> 1))) - 0)) - -(define (switch-symlinks link target) - "Atomically switch LINK, a symbolic link, to point to TARGET. Works -both when LINK already exists and when it does not." - (let ((pivot (string-append link ".new"))) - (symlink target pivot) - (rename-file pivot link))) - -(define (roll-back profile) - "Roll back to the previous generation of PROFILE." - (let* ((number (profile-number profile)) - (previous-number (previous-profile-number profile number)) - (previous-profile (format #f "~a-~a-link" - profile previous-number)) - (manifest (string-append previous-profile "/manifest"))) - - (define (switch-link) - ;; Atomically switch PROFILE to the previous profile. - (format #t (_ "switching from generation ~a to ~a~%") - number previous-number) - (switch-symlinks profile previous-profile)) - - (cond ((not (file-exists? profile)) ; invalid profile - (format (current-error-port) - (_ "error: profile `~a' does not exist~%") - profile)) - ((zero? number) ; empty profile - (format (current-error-port) - (_ "nothing to do: already at the empty profile~%"))) - ((or (zero? previous-number) ; going to emptiness - (not (file-exists? previous-profile))) - (let*-values (((drv-path drv) - (profile-derivation (%store) '())) - ((prof) - (derivation-output-path - (assoc-ref (derivation-outputs drv) "out")))) - (when (not (build-derivations (%store) (list drv-path))) - (leave (_ "failed to build the empty profile~%"))) - - (switch-symlinks previous-profile prof) - (switch-link))) - (else (switch-link))))) ; anything else - -(define (find-packages-by-description rx) - "Search in SYNOPSIS and DESCRIPTION using RX. Return a list of -matching packages." - (define (same-location? p1 p2) - ;; Compare locations of two packages. - (equal? (package-location p1) (package-location p2))) - - (delete-duplicates - (sort - (fold-packages (lambda (package result) - (define matches? - (cut regexp-exec rx <>)) - - (if (or (and=> (package-synopsis package) - (compose matches? gettext)) - (and=> (package-description package) - (compose matches? gettext))) - (cons package result) - result)) - '()) - (lambda (p1 p2) - (stringname+path input) - "Convert the name/package/sub-drv tuple INPUT to a name/store-path tuple." - (let loop ((input input)) - (match input - ((name package) - (loop `(,name ,package "out"))) - ((name package sub-drv) - (let*-values (((_ drv) - (package-derivation (%store) package)) - ((out) - (derivation-output-path - (assoc-ref (derivation-outputs drv) sub-drv)))) - `(,name ,out)))))) - - -;;; -;;; Command-line options. -;;; - -(define %default-options - ;; Alist of default option values. - `((profile . ,%current-profile))) - -(define (show-help) - (display (_ "Usage: guix-package [OPTION]... PACKAGES... -Install, remove, or upgrade PACKAGES in a single transaction.\n")) - (display (_ " - -i, --install=PACKAGE install PACKAGE")) - (display (_ " - -r, --remove=PACKAGE remove PACKAGE")) - (display (_ " - -u, --upgrade=REGEXP upgrade all the installed packages matching REGEXP")) - (display (_ " - --roll-back roll back to the previous generation")) - (newline) - (display (_ " - -p, --profile=PROFILE use PROFILE instead of the user's default profile")) - (display (_ " - -n, --dry-run show what would be done without actually doing it")) - (display (_ " - --bootstrap use the bootstrap Guile to build the profile")) - (display (_ " - --verbose produce verbose output")) - (newline) - (display (_ " - -s, --search=REGEXP search in synopsis and description using REGEXP")) - (display (_ " - -I, --list-installed[=REGEXP] - list installed packages matching REGEXP")) - (display (_ " - -A, --list-available[=REGEXP] - list available packages matching REGEXP")) - (newline) - (display (_ " - -h, --help display this help and exit")) - (display (_ " - -V, --version display version information and exit")) - (newline) - (show-bug-report-information)) - -(define %options - ;; Specification of the command-line options. - (list (option '(#\h "help") #f #f - (lambda args - (show-help) - (exit 0))) - (option '(#\V "version") #f #f - (lambda args - (show-version-and-exit "guix-package"))) - - (option '(#\i "install") #t #f - (lambda (opt name arg result) - (alist-cons 'install arg result))) - (option '(#\r "remove") #t #f - (lambda (opt name arg result) - (alist-cons 'remove arg result))) - (option '(#\u "upgrade") #t #f - (lambda (opt name arg result) - (alist-cons 'upgrade arg result))) - (option '("roll-back") #f #f - (lambda (opt name arg result) - (alist-cons 'roll-back? #t result))) - (option '(#\p "profile") #t #f - (lambda (opt name arg result) - (alist-cons 'profile arg - (alist-delete 'profile result)))) - (option '(#\n "dry-run") #f #f - (lambda (opt name arg result) - (alist-cons 'dry-run? #t result))) - (option '("bootstrap") #f #f - (lambda (opt name arg result) - (alist-cons 'bootstrap? #t result))) - (option '("verbose") #f #f - (lambda (opt name arg result) - (alist-cons 'verbose? #t result))) - (option '(#\s "search") #t #f - (lambda (opt name arg result) - (cons `(query search ,(or arg "")) - result))) - (option '(#\I "list-installed") #f #t - (lambda (opt name arg result) - (cons `(query list-installed ,(or arg "")) - result))) - (option '(#\A "list-available") #f #t - (lambda (opt name arg result) - (cons `(query list-available ,(or arg "")) - result))))) - - -;;; -;;; Entry point. -;;; - -(define (guix-package . args) - (define (parse-options) - ;; Return the alist of option values. - (args-fold args %options - (lambda (opt name arg result) - (leave (_ "~A: unrecognized option~%") name)) - (lambda (arg result) - (leave (_ "~A: extraneous argument~%") arg)) - %default-options)) - - (define (guile-missing?) - ;; Return #t if %GUILE-FOR-BUILD is not available yet. - (let ((out (derivation-path->output-path (%guile-for-build)))) - (not (valid-path? (%store) out)))) - - (define (show-what-to-build drv dry-run?) - ;; Show what will/would be built in realizing the derivations listed - ;; in DRV. - (let* ((req (append-map (lambda (drv-path) - (let ((d (call-with-input-file drv-path - read-derivation))) - (derivation-prerequisites-to-build - (%store) d))) - drv)) - (req* (delete-duplicates - (append (remove (compose (cute valid-path? (%store) <>) - derivation-path->output-path) - drv) - (map derivation-input-path req))))) - (if dry-run? - (format (current-error-port) - (N_ "~:[the following derivation would be built:~%~{ ~a~%~}~;~]" - "~:[the following derivations would be built:~%~{ ~a~%~}~;~]" - (length req*)) - (null? req*) req*) - (format (current-error-port) - (N_ "~:[the following derivation will be built:~%~{ ~a~%~}~;~]" - "~:[the following derivations will be built:~%~{ ~a~%~}~;~]" - (length req*)) - (null? req*) req*)))) - - (define newest-available-packages - (memoize find-newest-available-packages)) - - (define (find-best-packages-by-name name version) - (if version - (find-packages-by-name name version) - (match (vhash-assoc name (newest-available-packages)) - ((_ version pkgs ...) pkgs) - (#f '())))) - - (define (find-package name) - ;; Find the package NAME; NAME may contain a version number and a - ;; sub-derivation name. If the version number is not present, - ;; return the preferred newest version. - (define request name) - - (define (ensure-output p sub-drv) - (if (member sub-drv (package-outputs p)) - p - (leave (_ "~a: error: package `~a' lacks output `~a'~%") - (location->string (package-location p)) - (package-full-name p) - sub-drv))) - - (let*-values (((name sub-drv) - (match (string-rindex name #\:) - (#f (values name "out")) - (colon (values (substring name 0 colon) - (substring name (+ 1 colon)))))) - ((name version) - (package-name->name+version name))) - (match (find-best-packages-by-name name version) - ((p) - (list name (package-version p) sub-drv (ensure-output p sub-drv) - (package-transitive-propagated-inputs p))) - ((p p* ...) - (format (current-error-port) - (_ "warning: ambiguous package specification `~a'~%") - request) - (format (current-error-port) - (_ "warning: choosing ~a from ~a~%") - (package-full-name p) - (location->string (package-location p))) - (list name (package-version p) sub-drv (ensure-output p sub-drv) - (package-transitive-propagated-inputs p))) - (() - (leave (_ "~a: package not found~%") request))))) - - (define (upgradeable? name current-version current-path) - ;; Return #t if there's a version of package NAME newer than - ;; CURRENT-VERSION, or if the newest available version is equal to - ;; CURRENT-VERSION but would have an output path different than - ;; CURRENT-PATH. - (match (vhash-assoc name (newest-available-packages)) - ((_ candidate-version pkg . rest) - (case (version-compare candidate-version current-version) - ((>) #t) - ((<) #f) - ((=) (let ((candidate-path (derivation-path->output-path - (package-derivation (%store) pkg)))) - (not (string=? current-path candidate-path)))))) - (#f #f))) - - (define (ensure-default-profile) - ;; Ensure the default profile symlink and directory exist. - - ;; Create ~/.guix-profile if it doesn't exist yet. - (when (and %user-environment-directory - %current-profile - (not (false-if-exception - (lstat %user-environment-directory)))) - (symlink %current-profile %user-environment-directory)) - - ;; Attempt to create /…/profiles/per-user/$USER if needed. - (unless (directory-exists? %profile-directory) - (catch 'system-error - (lambda () - (mkdir-p %profile-directory)) - (lambda args - ;; Often, we cannot create %PROFILE-DIRECTORY because its - ;; parent directory is root-owned and we're running - ;; unprivileged. - (format (current-error-port) - (_ "error: while creating directory `~a': ~a~%") - %profile-directory - (strerror (system-error-errno args))) - (format (current-error-port) - (_ "Please create the `~a' directory, with you as the owner.~%") - %profile-directory) - (exit 1))))) - - (define (process-actions opts) - ;; Process any install/remove/upgrade action from OPTS. - - (define dry-run? (assoc-ref opts 'dry-run?)) - (define verbose? (assoc-ref opts 'verbose?)) - (define profile (assoc-ref opts 'profile)) - - (define (canonicalize-deps deps) - ;; Remove duplicate entries from DEPS, a list of propagated inputs, - ;; where each input is a name/path tuple. - (define (same? d1 d2) - (match d1 - ((_ path1) - (match d2 - ((_ path2) - (string=? path1 path2)))))) - - (delete-duplicates (map input->name+path deps) same?)) - - ;; First roll back if asked to. - (if (and (assoc-ref opts 'roll-back?) (not dry-run?)) - (begin - (roll-back profile) - (process-actions (alist-delete 'roll-back? opts))) - (let* ((installed (manifest-packages (profile-manifest profile))) - (upgrade-regexps (filter-map (match-lambda - (('upgrade . regexp) - (make-regexp regexp)) - (_ #f)) - opts)) - (upgrade (if (null? upgrade-regexps) - '() - (let ((newest (find-newest-available-packages))) - (filter-map (match-lambda - ((name version output path _) - (and (any (cut regexp-exec <> name) - upgrade-regexps) - (upgradeable? name version path) - (find-package name))) - (_ #f)) - installed)))) - (install (append - upgrade - (filter-map (match-lambda - (('install . (? store-path?)) - #f) - (('install . package) - (find-package package)) - (_ #f)) - opts))) - (drv (filter-map (match-lambda - ((name version sub-drv - (? package? package) - (deps ...)) - (package-derivation (%store) package)) - (_ #f)) - install)) - (install* (append - (filter-map (match-lambda - (('install . (? store-path? path)) - (let-values (((name version) - (package-name->name+version - (store-path-package-name - path)))) - `(,name ,version #f ,path ()))) - (_ #f)) - opts) - (map (lambda (tuple drv) - (match tuple - ((name version sub-drv _ (deps ...)) - (let ((output-path - (derivation-path->output-path - drv sub-drv))) - `(,name ,version ,sub-drv ,output-path - ,(canonicalize-deps deps)))))) - install drv))) - (remove (filter-map (match-lambda - (('remove . package) - package) - (_ #f)) - opts)) - (packages (append install* - (fold (lambda (package result) - (match package - ((name _ ...) - (alist-delete name result)))) - (fold alist-delete installed remove) - install*)))) - - (when (equal? profile %current-profile) - (ensure-default-profile)) - - (show-what-to-build drv dry-run?) - - (or dry-run? - (and (build-derivations (%store) drv) - (let* ((prof-drv (profile-derivation (%store) packages)) - (prof (derivation-path->output-path prof-drv)) - (old-drv (profile-derivation - (%store) (manifest-packages - (profile-manifest profile)))) - (old-prof (derivation-path->output-path old-drv)) - (number (profile-number profile)) - - ;; Always use NUMBER + 1 for the new profile, - ;; possibly overwriting a "previous future - ;; generation". - (name (format #f "~a-~a-link" - profile (+ 1 number)))) - (if (string=? old-prof prof) - (when (or (pair? install) (pair? remove)) - (format (current-error-port) - (_ "nothing to be done~%"))) - (and (parameterize ((current-build-output-port - ;; Output something when Guile - ;; needs to be built. - (if (or verbose? (guile-missing?)) - (current-error-port) - (%make-void-port "w")))) - (build-derivations (%store) (list prof-drv))) - (begin - (switch-symlinks name prof) - (switch-symlinks profile name)))))))))) - - (define (process-query opts) - ;; Process any query specified by OPTS. Return #t when a query was - ;; actually processed, #f otherwise. - (let ((profile (assoc-ref opts 'profile))) - (match (assoc-ref opts 'query) - (('list-installed regexp) - (let* ((regexp (and regexp (make-regexp regexp))) - (manifest (profile-manifest profile)) - (installed (manifest-packages manifest))) - (for-each (match-lambda - ((name version output path _) - (when (or (not regexp) - (regexp-exec regexp name)) - (format #t "~a\t~a\t~a\t~a~%" - name (or version "?") output path)))) - installed) - #t)) - - (('list-available regexp) - (let* ((regexp (and regexp (make-regexp regexp))) - (available (fold-packages - (lambda (p r) - (let ((n (package-name p))) - (if regexp - (if (regexp-exec regexp n) - (cons p r) - r) - (cons p r)))) - '()))) - (for-each (lambda (p) - (format #t "~a\t~a\t~a\t~a~%" - (package-name p) - (package-version p) - (string-join (package-outputs p) ",") - (location->string (package-location p)))) - (sort available - (lambda (p1 p2) - (stringrecutils <> (current-output-port)) - (find-packages-by-description regexp)) - #t)) - (_ #f)))) - - (install-locale) - (textdomain "guix") - (setvbuf (current-output-port) _IOLBF) - (setvbuf (current-error-port) _IOLBF) - - (let ((opts (parse-options))) - (or (process-query opts) - (parameterize ((%store (open-connection))) - (with-error-handling - (parameterize ((%guile-for-build - (package-derivation (%store) - (if (assoc-ref opts 'bootstrap?) - %bootstrap-guile - guile-final)))) - (process-actions opts))))))) diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm new file mode 100644 index 000000000..bad04418f --- /dev/null +++ b/guix/scripts/build.scm @@ -0,0 +1,304 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2012, 2013 Ludovic Courtès +;;; Copyright © 2013 Mark H Weaver +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix scripts build) + #:use-module (guix ui) + #:use-module (guix store) + #:use-module (guix derivations) + #:use-module (guix packages) + #:use-module (guix utils) + #:use-module (ice-9 format) + #:use-module (ice-9 match) + #:use-module (ice-9 vlist) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-26) + #:use-module (srfi srfi-34) + #:use-module (srfi srfi-37) + #:autoload (gnu packages) (find-packages-by-name + find-newest-available-packages) + #:export (guix-build)) + +(define %store + (make-parameter #f)) + +(define (derivations-from-package-expressions exp system source?) + "Eval EXP and return the corresponding derivation path for SYSTEM. +When SOURCE? is true, return the derivations of the package sources." + (let ((p (eval exp (current-module)))) + (if (package? p) + (if source? + (let ((source (package-source p)) + (loc (package-location p))) + (if source + (package-source-derivation (%store) source) + (leave (_ "~a: error: package `~a' has no source~%") + (location->string loc) (package-name p)))) + (package-derivation (%store) p system)) + (leave (_ "expression `~s' does not evaluate to a package~%") + exp)))) + + +;;; +;;; Command-line options. +;;; + +(define %default-options + ;; Alist of default option values. + `((system . ,(%current-system)) + (substitutes? . #t) + (verbosity . 0))) + +(define (show-help) + (display (_ "Usage: guix build [OPTION]... PACKAGE-OR-DERIVATION... +Build the given PACKAGE-OR-DERIVATION and return their output paths.\n")) + (display (_ " + -e, --expression=EXPR build the package EXPR evaluates to")) + (display (_ " + -S, --source build the packages' source derivations")) + (display (_ " + -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\"")) + (display (_ " + -d, --derivations return the derivation paths of the given packages")) + (display (_ " + -K, --keep-failed keep build tree of failed builds")) + (display (_ " + -n, --dry-run do not build the derivations")) + (display (_ " + --no-substitutes build instead of resorting to pre-built substitutes")) + (display (_ " + -c, --cores=N allow the use of up to N CPU cores for the build")) + (display (_ " + -r, --root=FILE make FILE a symlink to the result, and register it + as a garbage collector root")) + (display (_ " + --verbosity=LEVEL use the given verbosity LEVEL")) + (newline) + (display (_ " + -h, --help display this help and exit")) + (display (_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + +(define %options + ;; Specifications of the command-line options. + (list (option '(#\h "help") #f #f + (lambda args + (show-help) + (exit 0))) + (option '(#\V "version") #f #f + (lambda args + (show-version-and-exit "guix-build"))) + + (option '(#\S "source") #f #f + (lambda (opt name arg result) + (alist-cons 'source? #t result))) + (option '(#\s "system") #t #f + (lambda (opt name arg result) + (alist-cons 'system arg + (alist-delete 'system result eq?)))) + (option '(#\d "derivations") #f #f + (lambda (opt name arg result) + (alist-cons 'derivations-only? #t result))) + (option '(#\e "expression") #t #f + (lambda (opt name arg result) + (alist-cons 'expression + (call-with-input-string arg read) + result))) + (option '(#\K "keep-failed") #f #f + (lambda (opt name arg result) + (alist-cons 'keep-failed? #t result))) + (option '(#\c "cores") #t #f + (lambda (opt name arg result) + (let ((c (false-if-exception (string->number arg)))) + (if c + (alist-cons 'cores c result) + (leave (_ "~a: not a number~%") arg))))) + (option '(#\n "dry-run") #f #f + (lambda (opt name arg result) + (alist-cons 'dry-run? #t result))) + (option '("no-substitutes") #f #f + (lambda (opt name arg result) + (alist-cons 'substitutes? #f + (alist-delete 'substitutes? result)))) + (option '(#\r "root") #t #f + (lambda (opt name arg result) + (alist-cons 'gc-root arg result))) + (option '("verbosity") #t #f + (lambda (opt name arg result) + (let ((level (string->number arg))) + (alist-cons 'verbosity level + (alist-delete 'verbosity result))))))) + + +;;; +;;; Entry point. +;;; + +(define (guix-build . args) + (define (parse-options) + ;; Return the alist of option values. + (args-fold args %options + (lambda (opt name arg result) + (leave (_ "~A: unrecognized option~%") name)) + (lambda (arg result) + (alist-cons 'argument arg result)) + %default-options)) + + (define (register-root paths root) + ;; Register ROOT as an indirect GC root for all of PATHS. + (let* ((root (string-append (canonicalize-path (dirname root)) + "/" root))) + (catch 'system-error + (lambda () + (match paths + ((path) + (symlink path root) + (add-indirect-root (%store) root)) + ((paths ...) + (fold (lambda (path count) + (let ((root (string-append root "-" (number->string count)))) + (symlink path root) + (add-indirect-root (%store) root)) + (+ 1 count)) + 0 + paths)))) + (lambda args + (format (current-error-port) + (_ "failed to create GC root `~a': ~a~%") + root (strerror (system-error-errno args))) + (exit 1))))) + + (define newest-available-packages + (memoize find-newest-available-packages)) + + (define (find-best-packages-by-name name version) + (if version + (find-packages-by-name name version) + (match (vhash-assoc name (newest-available-packages)) + ((_ version pkgs ...) pkgs) + (#f '())))) + + (define (find-package request) + ;; Return a package matching REQUEST. REQUEST may be a package + ;; name, or a package name followed by a hyphen and a version + ;; number. If the version number is not present, return the + ;; preferred newest version. + (let-values (((name version) + (package-name->name+version request))) + (match (find-best-packages-by-name name version) + ((p) ; one match + p) + ((p x ...) ; several matches + (format (current-error-port) + (_ "warning: ambiguous package specification `~a'~%") + request) + (format (current-error-port) + (_ "warning: choosing ~a from ~a~%") + (package-full-name p) + (location->string (package-location p))) + p) + (_ ; no matches + (if version + (leave (_ "~A: package not found for version ~a~%") + name version) + (leave (_ "~A: unknown package~%") name)))))) + + (install-locale) + (textdomain "guix") + (setvbuf (current-output-port) _IOLBF) + (setvbuf (current-error-port) _IOLBF) + + (with-error-handling + (let ((opts (parse-options))) + (parameterize ((%store (open-connection))) + (let* ((src? (assoc-ref opts 'source?)) + (sys (assoc-ref opts 'system)) + (drv (filter-map (match-lambda + (('expression . exp) + (derivations-from-package-expressions exp sys + src?)) + (('argument . (? derivation-path? drv)) + drv) + (('argument . (? string? x)) + (let ((p (find-package x))) + (if src? + (let ((s (package-source p))) + (package-source-derivation + (%store) s)) + (package-derivation (%store) p sys)))) + (_ #f)) + opts)) + (req (append-map (lambda (drv-path) + (let ((d (call-with-input-file drv-path + read-derivation))) + (derivation-prerequisites-to-build (%store) d))) + drv)) + (req* (delete-duplicates + (append (remove (compose (cut valid-path? (%store) <>) + derivation-path->output-path) + drv) + (map derivation-input-path req)))) + (roots (filter-map (match-lambda + (('gc-root . root) root) + (_ #f)) + opts))) + (if (assoc-ref opts 'dry-run?) + (format (current-error-port) + (N_ "~:[the following derivation would be built:~%~{ ~a~%~}~;~]" + "~:[the following derivations would be built:~%~{ ~a~%~}~;~]" + (length req*)) + (null? req*) req*) + (format (current-error-port) + (N_ "~:[the following derivation will be built:~%~{ ~a~%~}~;~]" + "~:[the following derivations will be built:~%~{ ~a~%~}~;~]" + (length req*)) + (null? req*) req*)) + + ;; TODO: Add more options. + (set-build-options (%store) + #:keep-failed? (assoc-ref opts 'keep-failed?) + #:build-cores (or (assoc-ref opts 'cores) 0) + #:use-substitutes? (assoc-ref opts 'substitutes?) + #:verbosity (assoc-ref opts 'verbosity)) + + (if (assoc-ref opts 'derivations-only?) + (begin + (format #t "~{~a~%~}" drv) + (for-each (cut register-root <> <>) + (map list drv) roots)) + (or (assoc-ref opts 'dry-run?) + (and (build-derivations (%store) drv) + (for-each (lambda (d) + (let ((drv (call-with-input-file d + read-derivation))) + (format #t "~{~a~%~}" + (map (match-lambda + ((out-name . out) + (derivation-path->output-path + d out-name))) + (derivation-outputs drv))))) + drv) + (for-each (cut register-root <> <>) + (map (lambda (drv) + (map cdr + (derivation-path->output-paths drv))) + drv) + roots))))))))) diff --git a/guix/scripts/download.scm b/guix/scripts/download.scm new file mode 100644 index 000000000..1098e6714 --- /dev/null +++ b/guix/scripts/download.scm @@ -0,0 +1,151 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2012, 2013 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix scripts download) + #:use-module (guix ui) + #:use-module (guix store) + #:use-module (guix utils) + #:use-module (guix base32) + #:use-module ((guix download) #:select (%mirrors)) + #:use-module (guix build download) + #:use-module (web uri) + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-26) + #:use-module (srfi srfi-37) + #:use-module (rnrs bytevectors) + #:use-module (rnrs io ports) + #:export (guix-download)) + +(define (call-with-temporary-output-file proc) + (let* ((template (string-copy "guix-download.XXXXXX")) + (out (mkstemp! template))) + (dynamic-wind + (lambda () + #t) + (lambda () + (proc template out)) + (lambda () + (false-if-exception (delete-file template)))))) + +(define (fetch-and-store store fetch name) + "Call FETCH for URI, and pass it the name of a file to write to; eventually, +copy data from that port to STORE, under NAME. Return the resulting +store path." + (call-with-temporary-output-file + (lambda (temp port) + (let ((result + (parameterize ((current-output-port (current-error-port))) + (fetch temp)))) + (close port) + (and result + (add-to-store store name #f "sha256" temp)))))) + +;;; +;;; Command-line options. +;;; + +(define %default-options + ;; Alist of default option values. + `((format . ,bytevector->nix-base32-string))) + +(define (show-help) + (display (_ "Usage: guix download [OPTION]... URL +Download the file at URL, add it to the store, and print its store path +and the hash of its contents.\n")) + (format #t (_ " + -f, --format=FMT write the hash in the given format (default: `nix-base32')")) + (newline) + (display (_ " + -h, --help display this help and exit")) + (display (_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + +(define %options + ;; Specifications of the command-line options. + (list (option '(#\f "format") #t #f + (lambda (opt name arg result) + (define fmt-proc + (match arg + ("nix-base32" + bytevector->nix-base32-string) + ("base32" + bytevector->base32-string) + ((or "base16" "hex" "hexadecimal") + bytevector->base16-string) + (x + (format (current-error-port) + "unsupported hash format: ~a~%" arg)))) + + (alist-cons 'format fmt-proc + (alist-delete 'format result)))) + + (option '(#\h "help") #f #f + (lambda args + (show-help) + (exit 0))) + (option '(#\V "version") #f #f + (lambda args + (show-version-and-exit "guix-download"))))) + + +;;; +;;; Entry point. +;;; + +(define (guix-download . args) + (define (parse-options) + ;; Return the alist of option values. + (args-fold args %options + (lambda (opt name arg result) + (leave (_ "~A: unrecognized option~%") name)) + (lambda (arg result) + (alist-cons 'argument arg result)) + %default-options)) + + (install-locale) + (textdomain "guix") + (setvbuf (current-output-port) _IOLBF) + (setvbuf (current-error-port) _IOLBF) + + (let* ((opts (parse-options)) + (store (open-connection)) + (arg (assq-ref opts 'argument)) + (uri (or (string->uri arg) + (leave (_ "guix-download: ~a: failed to parse URI~%") + arg))) + (path (case (uri-scheme uri) + ((file) + (add-to-store store (basename (uri-path uri)) + #f "sha256" (uri-path uri))) + (else + (fetch-and-store store + (cut url-fetch arg <> + #:mirrors %mirrors) + (basename (uri-path uri)))))) + (hash (call-with-input-file + (or path + (leave (_ "guix-download: ~a: download failed~%") + arg)) + (compose sha256 get-bytevector-all))) + (fmt (assq-ref opts 'format))) + (format #t "~a~%~a~%" path (fmt hash)) + #t)) diff --git a/guix/scripts/gc.scm b/guix/scripts/gc.scm new file mode 100644 index 000000000..8e2587186 --- /dev/null +++ b/guix/scripts/gc.scm @@ -0,0 +1,165 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2012, 2013 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix scripts gc) + #:use-module (guix ui) + #:use-module (guix store) + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) + #:use-module (srfi srfi-37) + #:export (guix-gc)) + + +;;; +;;; Command-line options. +;;; + +(define %default-options + ;; Alist of default option values. + `((action . collect-garbage))) + +(define (show-help) + (display (_ "Usage: guix gc [OPTION]... PATHS... +Invoke the garbage collector.\n")) + (display (_ " + -C, --collect-garbage[=MIN] + collect at least MIN bytes of garbage")) + (display (_ " + -d, --delete attempt to delete PATHS")) + (display (_ " + --list-dead list dead paths")) + (display (_ " + --list-live list live paths")) + (newline) + (display (_ " + -h, --help display this help and exit")) + (display (_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + +(define (size->number str) + "Convert STR, a storage measurement representation such as \"1024\" or +\"1MiB\", to a number of bytes. Raise an error if STR could not be +interpreted." + (define unit-pos + (string-rindex str char-set:digit)) + + (define unit + (and unit-pos (substring str (+ 1 unit-pos)))) + + (let* ((numstr (if unit-pos + (substring str 0 (+ 1 unit-pos)) + str)) + (num (string->number numstr))) + (if num + (* num + (match unit + ("KiB" (expt 2 10)) + ("MiB" (expt 2 20)) + ("GiB" (expt 2 30)) + ("TiB" (expt 2 40)) + ("KB" (expt 10 3)) + ("MB" (expt 10 6)) + ("GB" (expt 10 9)) + ("TB" (expt 10 12)) + ("" 1) + (_ + (format (current-error-port) (_ "error: unknown unit: ~a~%") + unit) + (exit 1)))) + (begin + (format (current-error-port) + (_ "error: invalid number: ~a") numstr) + (exit 1))))) + +(define %options + ;; Specification of the command-line options. + (list (option '(#\h "help") #f #f + (lambda args + (show-help) + (exit 0))) + (option '(#\V "version") #f #f + (lambda args + (show-version-and-exit "guix-gc"))) + + (option '(#\C "collect-garbage") #f #t + (lambda (opt name arg result) + (let ((result (alist-cons 'action 'collect-garbage + (alist-delete 'action result)))) + (match arg + ((? string?) + (let ((amount (size->number arg))) + (if arg + (alist-cons 'min-freed amount result) + (begin + (format (current-error-port) + (_ "error: invalid amount of storage: ~a~%") + arg) + (exit 1))))) + (#f result))))) + (option '(#\d "delete") #f #f + (lambda (opt name arg result) + (alist-cons 'action 'delete + (alist-delete 'action result)))) + (option '("list-dead") #f #f + (lambda (opt name arg result) + (alist-cons 'action 'list-dead + (alist-delete 'action result)))) + (option '("list-live") #f #f + (lambda (opt name arg result) + (alist-cons 'action 'list-live + (alist-delete 'action result)))))) + + +;;; +;;; Entry point. +;;; + +(define (guix-gc . args) + (define (parse-options) + ;; Return the alist of option values. + (args-fold args %options + (lambda (opt name arg result) + (leave (_ "~A: unrecognized option~%") name)) + (lambda (arg result) + (alist-cons 'argument arg result)) + %default-options)) + + (with-error-handling + (let ((opts (parse-options)) + (store (open-connection))) + (case (assoc-ref opts 'action) + ((collect-garbage) + (let ((min-freed (assoc-ref opts 'min-freed))) + (if min-freed + (collect-garbage store min-freed) + (collect-garbage store)))) + ((delete) + (let ((paths (filter-map (match-lambda + (('argument . arg) arg) + (_ #f)) + opts))) + (delete-paths store paths))) + ((list-dead) + (for-each (cut simple-format #t "~a~%" <>) + (dead-paths store))) + ((list-live) + (for-each (cut simple-format #t "~a~%" <>) + (live-paths store))))))) diff --git a/guix/scripts/import.scm b/guix/scripts/import.scm new file mode 100644 index 000000000..0bc6926c6 --- /dev/null +++ b/guix/scripts/import.scm @@ -0,0 +1,124 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2012, 2013 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix scripts import) + #:use-module (guix ui) + #:use-module (guix snix) + #:use-module (guix utils) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-26) + #:use-module (srfi srfi-37) + #:use-module (ice-9 match) + #:use-module (ice-9 pretty-print) + #:export (guix-import)) + + +;;; +;;; Helper. +;;; + +(define (newline-rewriting-port output) + "Return an output port that rewrites strings containing the \\n escape +to an actual newline. This works around the behavior of `pretty-print' +and `write', which output these as \\n instead of actual newlines, +whereas we want the `description' field to contain actual newlines +rather than \\n." + (define (write-string str) + (let loop ((chars (string->list str))) + (match chars + (() + #t) + ((#\\ #\n rest ...) + (newline output) + (loop rest)) + ((chr rest ...) + (write-char chr output) + (loop rest))))) + + (make-soft-port (vector (cut write-char <>) + write-string + (lambda _ #t) ; flush + #f + (lambda _ #t) ; close + #f) + "w")) + + +;;; +;;; Command-line options. +;;; + +(define %default-options + '()) + +(define (show-help) + (display (_ "Usage: guix import NIXPKGS ATTRIBUTE +Import and convert the Nix expression ATTRIBUTE of NIXPKGS.\n")) + (display (_ " + -h, --help display this help and exit")) + (display (_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + +(define %options + ;; Specification of the command-line options. + (list (option '(#\h "help") #f #f + (lambda args + (show-help) + (exit 0))) + (option '(#\V "version") #f #f + (lambda args + (show-version-and-exit "guix-import"))))) + + +;;; +;;; Entry point. +;;; + +(define (guix-import . args) + (define (parse-options) + ;; Return the alist of option values. + (args-fold args %options + (lambda (opt name arg result) + (leave (_ "~A: unrecognized option~%") name)) + (lambda (arg result) + (alist-cons 'argument arg result)) + %default-options)) + + (install-locale) + (textdomain "guix") + (setvbuf (current-output-port) _IOLBF) + (setvbuf (current-error-port) _IOLBF) + + (let* ((opts (parse-options)) + (args (filter-map (match-lambda + (('argument . value) + value) + (_ #f)) + (reverse opts)))) + (match args + ((nixpkgs attribute) + (let-values (((expr loc) + (nixpkgs->guix-package nixpkgs attribute))) + (format #t ";; converted from ~a:~a~%~%" + (location-file loc) (location-line loc)) + (pretty-print expr (newline-rewriting-port (current-output-port))))) + (_ + (leave (_ "wrong number of arguments~%")))))) diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm new file mode 100644 index 000000000..4935837d3 --- /dev/null +++ b/guix/scripts/package.scm @@ -0,0 +1,693 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2012, 2013 Ludovic Courtès +;;; Copyright © 2013 Nikita Karetnikov +;;; Copyright © 2013 Mark H Weaver +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix scripts package) + #:use-module (guix ui) + #:use-module (guix store) + #:use-module (guix derivations) + #:use-module (guix packages) + #:use-module (guix utils) + #:use-module (guix config) + #:use-module ((guix build utils) #:select (directory-exists? mkdir-p)) + #:use-module (ice-9 ftw) + #:use-module (ice-9 format) + #:use-module (ice-9 match) + #:use-module (ice-9 regex) + #:use-module (ice-9 vlist) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-26) + #:use-module (srfi srfi-34) + #:use-module (srfi srfi-37) + #:use-module (gnu packages) + #:use-module ((gnu packages base) #:select (guile-final)) + #:use-module ((gnu packages bootstrap) #:select (%bootstrap-guile)) + #:export (guix-package)) + +(define %store + (make-parameter #f)) + + +;;; +;;; User environment. +;;; + +(define %user-environment-directory + (and=> (getenv "HOME") + (cut string-append <> "/.guix-profile"))) + +(define %profile-directory + (string-append (or (getenv "NIX_STATE_DIR") %state-directory) "/profiles/" + (or (and=> (getenv "USER") + (cut string-append "per-user/" <>)) + "default"))) + +(define %current-profile + ;; Call it `guix-profile', not `profile', to allow Guix profiles to + ;; coexist with Nix profiles. + (string-append %profile-directory "/guix-profile")) + +(define (profile-manifest profile) + "Return the PROFILE's manifest." + (let ((manifest (string-append profile "/manifest"))) + (if (file-exists? manifest) + (call-with-input-file manifest read) + '(manifest (version 1) (packages ()))))) + +(define (manifest-packages manifest) + "Return the packages listed in MANIFEST." + (match manifest + (('manifest ('version 0) + ('packages ((name version output path) ...))) + (zip name version output path + (make-list (length name) '()))) + + ;; Version 1 adds a list of propagated inputs to the + ;; name/version/output/path tuples. + (('manifest ('version 1) + ('packages (packages ...))) + packages) + + (_ + (error "unsupported manifest format" manifest)))) + +(define (profile-regexp profile) + "Return a regular expression that matches PROFILE's name and number." + (make-regexp (string-append "^" (regexp-quote (basename profile)) + "-([0-9]+)"))) + +(define (profile-numbers profile) + "Return the list of generation numbers of PROFILE, or '(0) if no +former profiles were found." + (define* (scandir name #:optional (select? (const #t)) + (entry (file-system-fold enter? leaf down up skip error #f name lstat) + (lambda (files) + (sort files entry)) + (#f ; no profile directory + '(0)) + (() ; no profiles + '(0)) + ((profiles ...) ; former profiles around + (map (compose string->number + (cut match:substring <> 1) + (cute regexp-exec (profile-regexp profile) <>)) + profiles)))) + +(define (previous-profile-number profile number) + "Return the number of the generation before generation NUMBER of +PROFILE, or 0 if none exists. It could be NUMBER - 1, but it's not the +case when generations have been deleted (there are \"holes\")." + (fold (lambda (candidate highest) + (if (and (< candidate number) (> candidate highest)) + candidate + highest)) + 0 + (profile-numbers profile))) + +(define (profile-derivation store packages) + "Return a derivation that builds a profile (a user environment) with +all of PACKAGES, a list of name/version/output/path/deps tuples." + (define builder + `(begin + (use-modules (ice-9 pretty-print) + (guix build union)) + + (setvbuf (current-output-port) _IOLBF) + (setvbuf (current-error-port) _IOLBF) + + (let ((output (assoc-ref %outputs "out")) + (inputs (map cdr %build-inputs))) + (format #t "building user environment `~a' with ~a packages...~%" + output (length inputs)) + (union-build output inputs) + (call-with-output-file (string-append output "/manifest") + (lambda (p) + (pretty-print '(manifest (version 1) + (packages ,packages)) + p)))))) + + (build-expression->derivation store "user-environment" + (%current-system) + builder + (append-map (match-lambda + ((name version output path deps) + `((,name ,path) + ,@deps))) + packages) + #:modules '((guix build union)))) + +(define (profile-number profile) + "Return PROFILE's number or 0. An absolute file name must be used." + (or (and=> (false-if-exception (regexp-exec (profile-regexp profile) + (basename (readlink profile)))) + (compose string->number (cut match:substring <> 1))) + 0)) + +(define (switch-symlinks link target) + "Atomically switch LINK, a symbolic link, to point to TARGET. Works +both when LINK already exists and when it does not." + (let ((pivot (string-append link ".new"))) + (symlink target pivot) + (rename-file pivot link))) + +(define (roll-back profile) + "Roll back to the previous generation of PROFILE." + (let* ((number (profile-number profile)) + (previous-number (previous-profile-number profile number)) + (previous-profile (format #f "~a-~a-link" + profile previous-number)) + (manifest (string-append previous-profile "/manifest"))) + + (define (switch-link) + ;; Atomically switch PROFILE to the previous profile. + (format #t (_ "switching from generation ~a to ~a~%") + number previous-number) + (switch-symlinks profile previous-profile)) + + (cond ((not (file-exists? profile)) ; invalid profile + (format (current-error-port) + (_ "error: profile `~a' does not exist~%") + profile)) + ((zero? number) ; empty profile + (format (current-error-port) + (_ "nothing to do: already at the empty profile~%"))) + ((or (zero? previous-number) ; going to emptiness + (not (file-exists? previous-profile))) + (let*-values (((drv-path drv) + (profile-derivation (%store) '())) + ((prof) + (derivation-output-path + (assoc-ref (derivation-outputs drv) "out")))) + (when (not (build-derivations (%store) (list drv-path))) + (leave (_ "failed to build the empty profile~%"))) + + (switch-symlinks previous-profile prof) + (switch-link))) + (else (switch-link))))) ; anything else + +(define (find-packages-by-description rx) + "Search in SYNOPSIS and DESCRIPTION using RX. Return a list of +matching packages." + (define (same-location? p1 p2) + ;; Compare locations of two packages. + (equal? (package-location p1) (package-location p2))) + + (delete-duplicates + (sort + (fold-packages (lambda (package result) + (define matches? + (cut regexp-exec rx <>)) + + (if (or (and=> (package-synopsis package) + (compose matches? gettext)) + (and=> (package-description package) + (compose matches? gettext))) + (cons package result) + result)) + '()) + (lambda (p1 p2) + (stringname+path input) + "Convert the name/package/sub-drv tuple INPUT to a name/store-path tuple." + (let loop ((input input)) + (match input + ((name package) + (loop `(,name ,package "out"))) + ((name package sub-drv) + (let*-values (((_ drv) + (package-derivation (%store) package)) + ((out) + (derivation-output-path + (assoc-ref (derivation-outputs drv) sub-drv)))) + `(,name ,out)))))) + + +;;; +;;; Command-line options. +;;; + +(define %default-options + ;; Alist of default option values. + `((profile . ,%current-profile))) + +(define (show-help) + (display (_ "Usage: guix package [OPTION]... PACKAGES... +Install, remove, or upgrade PACKAGES in a single transaction.\n")) + (display (_ " + -i, --install=PACKAGE install PACKAGE")) + (display (_ " + -r, --remove=PACKAGE remove PACKAGE")) + (display (_ " + -u, --upgrade=REGEXP upgrade all the installed packages matching REGEXP")) + (display (_ " + --roll-back roll back to the previous generation")) + (newline) + (display (_ " + -p, --profile=PROFILE use PROFILE instead of the user's default profile")) + (display (_ " + -n, --dry-run show what would be done without actually doing it")) + (display (_ " + --bootstrap use the bootstrap Guile to build the profile")) + (display (_ " + --verbose produce verbose output")) + (newline) + (display (_ " + -s, --search=REGEXP search in synopsis and description using REGEXP")) + (display (_ " + -I, --list-installed[=REGEXP] + list installed packages matching REGEXP")) + (display (_ " + -A, --list-available[=REGEXP] + list available packages matching REGEXP")) + (newline) + (display (_ " + -h, --help display this help and exit")) + (display (_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + +(define %options + ;; Specification of the command-line options. + (list (option '(#\h "help") #f #f + (lambda args + (show-help) + (exit 0))) + (option '(#\V "version") #f #f + (lambda args + (show-version-and-exit "guix-package"))) + + (option '(#\i "install") #t #f + (lambda (opt name arg result) + (alist-cons 'install arg result))) + (option '(#\r "remove") #t #f + (lambda (opt name arg result) + (alist-cons 'remove arg result))) + (option '(#\u "upgrade") #t #f + (lambda (opt name arg result) + (alist-cons 'upgrade arg result))) + (option '("roll-back") #f #f + (lambda (opt name arg result) + (alist-cons 'roll-back? #t result))) + (option '(#\p "profile") #t #f + (lambda (opt name arg result) + (alist-cons 'profile arg + (alist-delete 'profile result)))) + (option '(#\n "dry-run") #f #f + (lambda (opt name arg result) + (alist-cons 'dry-run? #t result))) + (option '("bootstrap") #f #f + (lambda (opt name arg result) + (alist-cons 'bootstrap? #t result))) + (option '("verbose") #f #f + (lambda (opt name arg result) + (alist-cons 'verbose? #t result))) + (option '(#\s "search") #t #f + (lambda (opt name arg result) + (cons `(query search ,(or arg "")) + result))) + (option '(#\I "list-installed") #f #t + (lambda (opt name arg result) + (cons `(query list-installed ,(or arg "")) + result))) + (option '(#\A "list-available") #f #t + (lambda (opt name arg result) + (cons `(query list-available ,(or arg "")) + result))))) + + +;;; +;;; Entry point. +;;; + +(define (guix-package . args) + (define (parse-options) + ;; Return the alist of option values. + (args-fold args %options + (lambda (opt name arg result) + (leave (_ "~A: unrecognized option~%") name)) + (lambda (arg result) + (leave (_ "~A: extraneous argument~%") arg)) + %default-options)) + + (define (guile-missing?) + ;; Return #t if %GUILE-FOR-BUILD is not available yet. + (let ((out (derivation-path->output-path (%guile-for-build)))) + (not (valid-path? (%store) out)))) + + (define (show-what-to-build drv dry-run?) + ;; Show what will/would be built in realizing the derivations listed + ;; in DRV. + (let* ((req (append-map (lambda (drv-path) + (let ((d (call-with-input-file drv-path + read-derivation))) + (derivation-prerequisites-to-build + (%store) d))) + drv)) + (req* (delete-duplicates + (append (remove (compose (cute valid-path? (%store) <>) + derivation-path->output-path) + drv) + (map derivation-input-path req))))) + (if dry-run? + (format (current-error-port) + (N_ "~:[the following derivation would be built:~%~{ ~a~%~}~;~]" + "~:[the following derivations would be built:~%~{ ~a~%~}~;~]" + (length req*)) + (null? req*) req*) + (format (current-error-port) + (N_ "~:[the following derivation will be built:~%~{ ~a~%~}~;~]" + "~:[the following derivations will be built:~%~{ ~a~%~}~;~]" + (length req*)) + (null? req*) req*)))) + + (define newest-available-packages + (memoize find-newest-available-packages)) + + (define (find-best-packages-by-name name version) + (if version + (find-packages-by-name name version) + (match (vhash-assoc name (newest-available-packages)) + ((_ version pkgs ...) pkgs) + (#f '())))) + + (define (find-package name) + ;; Find the package NAME; NAME may contain a version number and a + ;; sub-derivation name. If the version number is not present, + ;; return the preferred newest version. + (define request name) + + (define (ensure-output p sub-drv) + (if (member sub-drv (package-outputs p)) + p + (leave (_ "~a: error: package `~a' lacks output `~a'~%") + (location->string (package-location p)) + (package-full-name p) + sub-drv))) + + (let*-values (((name sub-drv) + (match (string-rindex name #\:) + (#f (values name "out")) + (colon (values (substring name 0 colon) + (substring name (+ 1 colon)))))) + ((name version) + (package-name->name+version name))) + (match (find-best-packages-by-name name version) + ((p) + (list name (package-version p) sub-drv (ensure-output p sub-drv) + (package-transitive-propagated-inputs p))) + ((p p* ...) + (format (current-error-port) + (_ "warning: ambiguous package specification `~a'~%") + request) + (format (current-error-port) + (_ "warning: choosing ~a from ~a~%") + (package-full-name p) + (location->string (package-location p))) + (list name (package-version p) sub-drv (ensure-output p sub-drv) + (package-transitive-propagated-inputs p))) + (() + (leave (_ "~a: package not found~%") request))))) + + (define (upgradeable? name current-version current-path) + ;; Return #t if there's a version of package NAME newer than + ;; CURRENT-VERSION, or if the newest available version is equal to + ;; CURRENT-VERSION but would have an output path different than + ;; CURRENT-PATH. + (match (vhash-assoc name (newest-available-packages)) + ((_ candidate-version pkg . rest) + (case (version-compare candidate-version current-version) + ((>) #t) + ((<) #f) + ((=) (let ((candidate-path (derivation-path->output-path + (package-derivation (%store) pkg)))) + (not (string=? current-path candidate-path)))))) + (#f #f))) + + (define (ensure-default-profile) + ;; Ensure the default profile symlink and directory exist. + + ;; Create ~/.guix-profile if it doesn't exist yet. + (when (and %user-environment-directory + %current-profile + (not (false-if-exception + (lstat %user-environment-directory)))) + (symlink %current-profile %user-environment-directory)) + + ;; Attempt to create /…/profiles/per-user/$USER if needed. + (unless (directory-exists? %profile-directory) + (catch 'system-error + (lambda () + (mkdir-p %profile-directory)) + (lambda args + ;; Often, we cannot create %PROFILE-DIRECTORY because its + ;; parent directory is root-owned and we're running + ;; unprivileged. + (format (current-error-port) + (_ "error: while creating directory `~a': ~a~%") + %profile-directory + (strerror (system-error-errno args))) + (format (current-error-port) + (_ "Please create the `~a' directory, with you as the owner.~%") + %profile-directory) + (exit 1))))) + + (define (process-actions opts) + ;; Process any install/remove/upgrade action from OPTS. + + (define dry-run? (assoc-ref opts 'dry-run?)) + (define verbose? (assoc-ref opts 'verbose?)) + (define profile (assoc-ref opts 'profile)) + + (define (canonicalize-deps deps) + ;; Remove duplicate entries from DEPS, a list of propagated inputs, + ;; where each input is a name/path tuple. + (define (same? d1 d2) + (match d1 + ((_ path1) + (match d2 + ((_ path2) + (string=? path1 path2)))))) + + (delete-duplicates (map input->name+path deps) same?)) + + ;; First roll back if asked to. + (if (and (assoc-ref opts 'roll-back?) (not dry-run?)) + (begin + (roll-back profile) + (process-actions (alist-delete 'roll-back? opts))) + (let* ((installed (manifest-packages (profile-manifest profile))) + (upgrade-regexps (filter-map (match-lambda + (('upgrade . regexp) + (make-regexp regexp)) + (_ #f)) + opts)) + (upgrade (if (null? upgrade-regexps) + '() + (let ((newest (find-newest-available-packages))) + (filter-map (match-lambda + ((name version output path _) + (and (any (cut regexp-exec <> name) + upgrade-regexps) + (upgradeable? name version path) + (find-package name))) + (_ #f)) + installed)))) + (install (append + upgrade + (filter-map (match-lambda + (('install . (? store-path?)) + #f) + (('install . package) + (find-package package)) + (_ #f)) + opts))) + (drv (filter-map (match-lambda + ((name version sub-drv + (? package? package) + (deps ...)) + (package-derivation (%store) package)) + (_ #f)) + install)) + (install* (append + (filter-map (match-lambda + (('install . (? store-path? path)) + (let-values (((name version) + (package-name->name+version + (store-path-package-name + path)))) + `(,name ,version #f ,path ()))) + (_ #f)) + opts) + (map (lambda (tuple drv) + (match tuple + ((name version sub-drv _ (deps ...)) + (let ((output-path + (derivation-path->output-path + drv sub-drv))) + `(,name ,version ,sub-drv ,output-path + ,(canonicalize-deps deps)))))) + install drv))) + (remove (filter-map (match-lambda + (('remove . package) + package) + (_ #f)) + opts)) + (packages (append install* + (fold (lambda (package result) + (match package + ((name _ ...) + (alist-delete name result)))) + (fold alist-delete installed remove) + install*)))) + + (when (equal? profile %current-profile) + (ensure-default-profile)) + + (show-what-to-build drv dry-run?) + + (or dry-run? + (and (build-derivations (%store) drv) + (let* ((prof-drv (profile-derivation (%store) packages)) + (prof (derivation-path->output-path prof-drv)) + (old-drv (profile-derivation + (%store) (manifest-packages + (profile-manifest profile)))) + (old-prof (derivation-path->output-path old-drv)) + (number (profile-number profile)) + + ;; Always use NUMBER + 1 for the new profile, + ;; possibly overwriting a "previous future + ;; generation". + (name (format #f "~a-~a-link" + profile (+ 1 number)))) + (if (string=? old-prof prof) + (when (or (pair? install) (pair? remove)) + (format (current-error-port) + (_ "nothing to be done~%"))) + (and (parameterize ((current-build-output-port + ;; Output something when Guile + ;; needs to be built. + (if (or verbose? (guile-missing?)) + (current-error-port) + (%make-void-port "w")))) + (build-derivations (%store) (list prof-drv))) + (begin + (switch-symlinks name prof) + (switch-symlinks profile name)))))))))) + + (define (process-query opts) + ;; Process any query specified by OPTS. Return #t when a query was + ;; actually processed, #f otherwise. + (let ((profile (assoc-ref opts 'profile))) + (match (assoc-ref opts 'query) + (('list-installed regexp) + (let* ((regexp (and regexp (make-regexp regexp))) + (manifest (profile-manifest profile)) + (installed (manifest-packages manifest))) + (for-each (match-lambda + ((name version output path _) + (when (or (not regexp) + (regexp-exec regexp name)) + (format #t "~a\t~a\t~a\t~a~%" + name (or version "?") output path)))) + installed) + #t)) + + (('list-available regexp) + (let* ((regexp (and regexp (make-regexp regexp))) + (available (fold-packages + (lambda (p r) + (let ((n (package-name p))) + (if regexp + (if (regexp-exec regexp n) + (cons p r) + r) + (cons p r)))) + '()))) + (for-each (lambda (p) + (format #t "~a\t~a\t~a\t~a~%" + (package-name p) + (package-version p) + (string-join (package-outputs p) ",") + (location->string (package-location p)))) + (sort available + (lambda (p1 p2) + (stringrecutils <> (current-output-port)) + (find-packages-by-description regexp)) + #t)) + (_ #f)))) + + (install-locale) + (textdomain "guix") + (setvbuf (current-output-port) _IOLBF) + (setvbuf (current-error-port) _IOLBF) + + (let ((opts (parse-options))) + (or (process-query opts) + (parameterize ((%store (open-connection))) + (with-error-handling + (parameterize ((%guile-for-build + (package-derivation (%store) + (if (assoc-ref opts 'bootstrap?) + %bootstrap-guile + guile-final)))) + (process-actions opts))))))) diff --git a/guix/ui.scm b/guix/ui.scm index 4aa93de3b..644a3070f 100644 --- a/guix/ui.scm +++ b/guix/ui.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2012, 2013 Ludovic Courtès +;;; Copyright © 2013 Mark H Weaver ;;; ;;; This file is part of GNU Guix. ;;; @@ -30,6 +31,7 @@ #:export (_ N_ install-locale + initialize-guix leave show-version-and-exit show-bug-report-information @@ -38,7 +40,9 @@ location->string fill-paragraph string->recutils - package->recutils)) + package->recutils + run-guix-command + guix-main)) ;;; Commentary: ;;; @@ -62,6 +66,12 @@ (_ "warning: failed to install locale: ~a~%") (strerror (system-error-errno args)))))) +(define (initialize-guix) + (install-locale) + (textdomain "guix") + (setvbuf (current-output-port) _IOLBF) + (setvbuf (current-error-port) _IOLBF)) + (define-syntax-rule (leave fmt args ...) "Format FMT and ARGS to the error port and exit." (begin @@ -210,4 +220,30 @@ WIDTH columns." (and=> (package-description p) description->recutils)) (newline port)) +(define (show-guix-usage) + ;; TODO: Dynamically generate a summary of available commands. + (format (current-error-port) + (_ "Usage: guix COMMAND ARGS...~%"))) + +(define (run-guix-command command . args) + ;; TODO: Gracefully report errors + (let* ((module (resolve-interface `(guix scripts ,command))) + (command-main (module-ref module + (symbol-append 'guix- command)))) + (apply command-main args))) + +(define (guix-main arg0 . args) + (initialize-guix) + (let () + (define (option? str) (string-prefix? "-" str)) + (match args + (() (show-guix-usage) (exit 1)) + (("--help") (show-guix-usage)) + (("--version") (show-version-and-exit "guix")) + (((? option? arg1) args ...) (show-guix-usage) (exit 1)) + ((command args ...) + (apply run-guix-command + (string->symbol command) + args))))) + ;;; ui.scm ends here diff --git a/po/POTFILES.in b/po/POTFILES.in index 049a1c707..5c0f131c0 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -4,8 +4,8 @@ gnu/packages/base.scm gnu/packages/guile.scm gnu/packages/lout.scm gnu/packages/recutils.scm +guix/scripts/build.scm +guix/scripts/download.scm +guix/scripts/package.scm +guix/scripts/gc.scm guix/ui.scm -guix-build.in -guix-download.in -guix-package.in -guix-gc.in diff --git a/pre-inst-env.in b/pre-inst-env.in index 1dc63cd90..4e079c8d4 100644 --- a/pre-inst-env.in +++ b/pre-inst-env.in @@ -27,9 +27,9 @@ GUILE_LOAD_COMPILED_PATH="@abs_top_builddir@${GUILE_LOAD_COMPILED_PATH:+:}$GUILE GUILE_LOAD_PATH="@abs_top_builddir@:@abs_top_srcdir@${GUILE_LOAD_PATH:+:}:$GUILE_LOAD_PATH" export GUILE_LOAD_COMPILED_PATH GUILE_LOAD_PATH -# Define $PATH so that `guix-build' and friends are easily found. +# Define $PATH so that `guix' and friends are easily found. -PATH="@abs_top_builddir@:$PATH" +PATH="@abs_top_builddir@/scripts:@abs_top_builddir@:$PATH" export PATH # Daemon helpers. @@ -43,7 +43,12 @@ export NIX_ROOT_FINDER NIX_SETUID_HELPER # auto-compilation. NIX_HASH="@NIX_HASH@" - export NIX_HASH +# Define $GUIX_UNINSTALLED to prevent `guix' from +# prepending @guilemoduledir@ to the Guile load paths. + +GUIX_UNINSTALLED=1 +export GUIX_UNINSTALLED + exec "$@" diff --git a/scripts/guix.in b/scripts/guix.in new file mode 100644 index 000000000..2fdde7d13 --- /dev/null +++ b/scripts/guix.in @@ -0,0 +1,56 @@ +#!@GUILE@ -s +-*- scheme -*- +!# +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2013 Mark H Weaver +;;; +;;; 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 . + +;; IMPORTANT: We must avoid loading any modules from Guix here, +;; because we need to adjust the guile load paths first. +;; It's okay to import modules from core Guile though. +(use-modules (ice-9 regex)) + +(let () + (define-syntax-rule (push! elt v) (set! v (cons elt v))) + + (define config-lookup + (let ((config '(("prefix" . "@prefix@") + ("datarootdir" . "@datarootdir@") + ("guilemoduledir" . "@guilemoduledir@"))) + (var-ref-regexp (make-regexp "\\$\\{([a-z]+)\\}"))) + (define (expand-var-ref match) + (lookup (match:substring match 1))) + (define (expand str) + (regexp-substitute/global #f var-ref-regexp str + 'pre expand-var-ref 'post)) + (define (lookup name) + (expand (assoc-ref config name))) + lookup)) + + (define (maybe-augment-load-paths!) + (unless (getenv "GUIX_UNINSTALLED") + (let ((module-dir (config-lookup "guilemoduledir"))) + (push! module-dir %load-path) + (push! module-dir %load-compiled-path)))) + + (define (run-guix-main) + (let ((guix-main (module-ref (resolve-interface '(guix ui)) + 'guix-main))) + (apply guix-main (command-line)))) + + (maybe-augment-load-paths!) + (run-guix-main)) diff --git a/tests/guix-build.sh b/tests/guix-build.sh index 5718b07d0..721a7c676 100644 --- a/tests/guix-build.sh +++ b/tests/guix-build.sh @@ -17,44 +17,44 @@ # along with GNU Guix. If not, see . # -# Test the `guix-build' command-line utility. +# Test the `guix build' command-line utility. # -guix-build --version +guix build --version # Should fail. -if guix-build -e +; +if guix build -e +; then false; else true; fi # Should fail because this is a source-less package. -if guix-build -e '(@ (gnu packages bootstrap) %bootstrap-glibc)' -S +if guix build -e '(@ (gnu packages bootstrap) %bootstrap-glibc)' -S then false; else true; fi # Should pass. -guix-build -e '(@@ (gnu packages base) %bootstrap-guile)' | \ +guix build -e '(@@ (gnu packages base) %bootstrap-guile)' | \ grep -e '-guile-' -guix-build hello -d | \ +guix build hello -d | \ grep -e '-hello-[0-9\.]\+\.drv$' # Should fail because the name/version combination could not be found. -if guix-build hello-0.0.1 -n; then false; else true; fi +if guix build hello-0.0.1 -n; then false; else true; fi # Keep a symlink to the result, registered as a root. result="t-result-$$" -guix-build -r "$result" \ +guix build -r "$result" \ -e '(@@ (gnu packages base) %bootstrap-guile)' test -x "$result/bin/guile" # Should fail, because $result already exists. -if guix-build -r "$result" -e '(@@ (gnu packages base) %bootstrap-guile)' +if guix build -r "$result" -e '(@@ (gnu packages base) %bootstrap-guile)' then false; else true; fi rm -f "$result" # Parsing package names and versions. -guix-build -n time # PASS -guix-build -n time-1.7 # PASS, version found -if guix-build -n time-3.2; # FAIL, version not found +guix build -n time # PASS +guix build -n time-1.7 # PASS, version found +if guix build -n time-3.2; # FAIL, version not found then false; else true; fi -if guix-build -n something-that-will-never-exist; # FAIL +if guix build -n something-that-will-never-exist; # FAIL then false; else true; fi diff --git a/tests/guix-daemon.sh b/tests/guix-daemon.sh index 0d39ff4c2..698516490 100644 --- a/tests/guix-daemon.sh +++ b/tests/guix-daemon.sh @@ -23,7 +23,7 @@ set -e guix-daemon --version -guix-build --version +guix build --version -guix-build -e '(@ (gnu packages bootstrap) %bootstrap-guile)' -guix-build coreutils -n +guix build -e '(@ (gnu packages bootstrap) %bootstrap-guile)' +guix build coreutils -n diff --git a/tests/guix-download.sh b/tests/guix-download.sh index f0ea73143..7af6f181f 100644 --- a/tests/guix-download.sh +++ b/tests/guix-download.sh @@ -17,20 +17,20 @@ # along with GNU Guix. If not, see . # -# Test the `guix-download' command-line utility. +# Test the `guix download' command-line utility. # -guix-download --version +guix download --version # Make sure it fails here. -if guix-download http://does.not/exist +if guix download http://does.not/exist then false; else true; fi -if guix-download unknown://some/where; +if guix download unknown://some/where; then false; else true; fi -if guix-download not/a/uri; +if guix download not/a/uri; then false; else true; fi # This one should succeed. -guix-download "file://$abs_top_srcdir/README" +guix download "file://$abs_top_srcdir/README" diff --git a/tests/guix-gc.sh b/tests/guix-gc.sh index 805300eee..a90d085ab 100644 --- a/tests/guix-gc.sh +++ b/tests/guix-gc.sh @@ -17,38 +17,38 @@ # along with GNU Guix. If not, see . # -# Test the `guix-gc' command-line utility. +# Test the `guix gc' command-line utility. # -guix-gc --version +guix gc --version trap "rm -f guix-gc-root" EXIT rm -f guix-gc-root # Add then reclaim a .drv file. -drv="`guix-build idutils -d`" +drv="`guix build idutils -d`" test -f "$drv" -guix-gc --list-dead | grep "$drv" -guix-gc --delete "$drv" +guix gc --list-dead | grep "$drv" +guix gc --delete "$drv" ! test -f "$drv" # Add a .drv, register it as a root. -drv="`guix-build --root=guix-gc-root lsh -d`" +drv="`guix build --root=guix-gc-root lsh -d`" test -f "$drv" && test -L guix-gc-root -guix-gc --list-live | grep "$drv" -if guix-gc --delete "$drv"; +guix gc --list-live | grep "$drv" +if guix gc --delete "$drv"; then false; else true; fi rm guix-gc-root -guix-gc --list-dead | grep "$drv" -guix-gc --delete "$drv" +guix gc --list-dead | grep "$drv" +guix gc --delete "$drv" ! test -f "$drv" # Try a random collection. -guix-gc -C 1KiB +guix gc -C 1KiB # Check trivial error cases. -if guix-gc --delete /dev/null; +if guix gc --delete /dev/null; then false; else true; fi diff --git a/tests/guix-package.sh b/tests/guix-package.sh index 617318b79..cf8bc5c7e 100644 --- a/tests/guix-package.sh +++ b/tests/guix-package.sh @@ -18,10 +18,10 @@ # along with GNU Guix. If not, see . # -# Test the `guix-package' command-line utility. +# Test the `guix package' command-line utility. # -guix-package --version +guix package --version readlink_base () { @@ -33,12 +33,12 @@ rm -f "$profile" trap 'rm "$profile" "$profile-"[0-9]* ; rm -rf t-home-'"$$" EXIT -guix-package --bootstrap -p "$profile" -i guile-bootstrap +guix package --bootstrap -p "$profile" -i guile-bootstrap test -L "$profile" && test -L "$profile-1-link" test -f "$profile/bin/guile" # Installing the same package a second time does nothing. -guix-package --bootstrap -p "$profile" -i guile-bootstrap +guix package --bootstrap -p "$profile" -i guile-bootstrap test -L "$profile" && test -L "$profile-1-link" ! test -f "$profile-2-link" test -f "$profile/bin/guile" @@ -46,8 +46,8 @@ test -f "$profile/bin/guile" # Check whether we have network access. if guile -c '(getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)' 2> /dev/null then - boot_make="`guix-build -e '(@@ (gnu packages base) gnu-make-boot0)'`" - guix-package --bootstrap -p "$profile" -i "$boot_make" + boot_make="`guix build -e '(@@ (gnu packages base) gnu-make-boot0)'`" + guix package --bootstrap -p "$profile" -i "$boot_make" test -L "$profile-2-link" test -f "$profile/bin/make" && test -f "$profile/bin/guile" @@ -55,7 +55,7 @@ then # Check whether `--list-installed' works. # XXX: Change the tests when `--install' properly extracts the package # name and version string. - installed="`guix-package -p "$profile" --list-installed | cut -f1 | xargs echo | sort`" + installed="`guix package -p "$profile" --list-installed | cut -f1 | xargs echo | sort`" case "x$installed" in "guile-bootstrap make-boot0") true;; @@ -65,68 +65,68 @@ then false;; esac - test "`guix-package -p "$profile" -I 'g.*e' | cut -f1`" = "guile-bootstrap" + test "`guix package -p "$profile" -I 'g.*e' | cut -f1`" = "guile-bootstrap" # Search. - test "`guix-package -s "GNU Hello" | grep ^name:`" = "name: hello" - test "`guix-package -s "n0t4r341p4ck4g3"`" = "" + test "`guix package -s "GNU Hello" | grep ^name:`" = "name: hello" + test "`guix package -s "n0t4r341p4ck4g3"`" = "" # Remove a package. - guix-package --bootstrap -p "$profile" -r "guile-bootstrap" + guix package --bootstrap -p "$profile" -r "guile-bootstrap" test -L "$profile-3-link" test -f "$profile/bin/make" && ! test -f "$profile/bin/guile" # Roll back. - guix-package --roll-back -p "$profile" + guix package --roll-back -p "$profile" test "`readlink_base "$profile"`" = "$profile-2-link" test -x "$profile/bin/guile" && test -x "$profile/bin/make" - guix-package --roll-back -p "$profile" + guix package --roll-back -p "$profile" test "`readlink_base "$profile"`" = "$profile-1-link" test -x "$profile/bin/guile" && ! test -x "$profile/bin/make" # Move to the empty profile. for i in `seq 1 3` do - guix-package --bootstrap --roll-back -p "$profile" + guix package --bootstrap --roll-back -p "$profile" ! test -f "$profile/bin" ! test -f "$profile/lib" test "`readlink_base "$profile"`" = "$profile-0-link" done # Reinstall after roll-back to the empty profile. - guix-package --bootstrap -p "$profile" -i "$boot_make" + guix package --bootstrap -p "$profile" -i "$boot_make" test "`readlink_base "$profile"`" = "$profile-1-link" test -x "$profile/bin/guile" && ! test -x "$profile/bin/make" # Roll-back to generation 0, and install---all at once. - guix-package --bootstrap -p "$profile" --roll-back -i guile-bootstrap + guix package --bootstrap -p "$profile" --roll-back -i guile-bootstrap test "`readlink_base "$profile"`" = "$profile-1-link" test -x "$profile/bin/guile" && ! test -x "$profile/bin/make" # Install Make. - guix-package --bootstrap -p "$profile" -i "$boot_make" + guix package --bootstrap -p "$profile" -i "$boot_make" test "`readlink_base "$profile"`" = "$profile-2-link" test -x "$profile/bin/guile" && test -x "$profile/bin/make" # Make a "hole" in the list of generations, and make sure we can # roll back "over" it. rm "$profile-1-link" - guix-package --bootstrap -p "$profile" --roll-back + guix package --bootstrap -p "$profile" --roll-back test "`readlink_base "$profile"`" = "$profile-0-link" fi # Make sure the `:' syntax works. -guix-package --bootstrap -i "binutils:lib" -p "$profile" -n +guix package --bootstrap -i "binutils:lib" -p "$profile" -n # Make sure nonexistent outputs are reported. -guix-package --bootstrap -i "guile-bootstrap:out" -p "$profile" -n -if guix-package --bootstrap -i "guile-bootstrap:does-not-exist" -p "$profile" -n; +guix package --bootstrap -i "guile-bootstrap:out" -p "$profile" -n +if guix package --bootstrap -i "guile-bootstrap:does-not-exist" -p "$profile" -n; then false; else true; fi -if guix-package --bootstrap -i "guile-bootstrap:does-not-exist" -p "$profile"; +if guix package --bootstrap -i "guile-bootstrap:does-not-exist" -p "$profile"; then false; else true; fi # Check whether `--list-available' returns something sensible. -guix-package -A 'gui.*e' | grep guile +guix package -A 'gui.*e' | grep guile # # Try with the default profile. @@ -139,17 +139,17 @@ export HOME mkdir -p "$HOME" -guix-package --bootstrap -i guile-bootstrap +guix package --bootstrap -i guile-bootstrap test -L "$HOME/.guix-profile" test -f "$HOME/.guix-profile/bin/guile" if guile -c '(getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)' 2> /dev/null then - guix-package --bootstrap -i "$boot_make" + guix package --bootstrap -i "$boot_make" test -f "$HOME/.guix-profile/bin/make" first_environment="`cd $HOME/.guix-profile ; pwd`" - guix-package --bootstrap --roll-back + guix package --bootstrap --roll-back test -f "$HOME/.guix-profile/bin/guile" ! test -f "$HOME/.guix-profile/bin/make" test "`cd $HOME/.guix-profile ; pwd`" = "$first_environment" @@ -159,12 +159,12 @@ fi default_profile="`readlink "$HOME/.guix-profile"`" for i in `seq 1 3` do - guix-package --bootstrap --roll-back + guix package --bootstrap --roll-back ! test -f "$HOME/.guix-profile/bin" ! test -f "$HOME/.guix-profile/lib" test "`readlink "$default_profile"`" = "$default_profile-0-link" done # Extraneous argument. -if guix-package install foo-bar; +if guix package install foo-bar; then false; else true; fi -- cgit v1.3 From 855a8ad71def2ebc594ed32c57bda0ca4e13d91c Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sun, 17 Feb 2013 22:18:16 +0100 Subject: build: Build guix/scripts/download.go after guix/build/download.go. * Makefile.am (guix/scripts/download.go): Add dependency on `guix/build/download.go'. Reported by Nikita Karetnikov . --- Makefile.am | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 5932e1350..cabbe21cd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -164,6 +164,9 @@ MODULES = \ gnu/packages/zip.scm \ gnu/system/vm.scm +# Because of the autoload hack in (guix build download), we must build it +# first to avoid errors on systems where (gnutls) is unavailable. +guix/scripts/download.go: guix/build/download.go GOBJECTS = $(MODULES:%.scm=%.go) guix/config.go -- cgit v1.3 From f651b477b701d086402c18665eca68b26c3bec6b Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Wed, 20 Feb 2013 23:46:38 +0100 Subject: Add "guix pull". * guix/scripts/pull.scm: New file. * Makefile.am (MODULES): Add it. * doc/guix.texi (Invoking guix pull): New node. (Invoking guix package): Add cross-ref to it. * guix/ui.scm (config-directory): New procedure. * scripts/guix.in: When `GUIX_UNINSTALLED' is undefined, add $XDG_CONFIG_HOME/guix/latest to the search path. * po/POTFILES.in: Add guix/scripts/pull.scm. --- Makefile.am | 1 + doc/guix.texi | 33 ++++++++ guix/scripts/pull.scm | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++ guix/ui.scm | 21 +++++ po/POTFILES.in | 1 + scripts/guix.in | 12 ++- 6 files changed, 288 insertions(+), 2 deletions(-) create mode 100644 guix/scripts/pull.scm (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index cabbe21cd..bed4d06ec 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,6 +30,7 @@ MODULES = \ guix/scripts/import.scm \ guix/scripts/package.scm \ guix/scripts/gc.scm \ + guix/scripts/pull.scm \ guix/base32.scm \ guix/utils.scm \ guix/derivations.scm \ diff --git a/doc/guix.texi b/doc/guix.texi index 9245bd00f..6a9ebab1f 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -393,6 +393,7 @@ management tools it provides. * Features:: How Guix will make your life brighter. * Invoking guix package:: Package installation, removal, etc. * Invoking guix gc:: Running the garbage collector. +* Invoking guix pull:: Fetching the latest Guix and distribution. @end menu @node Features @@ -521,6 +522,11 @@ Remove @var{package}. @itemx -u @var{regexp} Upgrade all the installed packages matching @var{regexp}. +Note that this upgrades package to the latest version of packages found +in the distribution currently installed. To update your distribution, +you should regularly run @command{guix pull} (@pxref{Invoking guix +pull}). + @item --roll-back Roll back to the previous @dfn{generation} of the profile---i.e., undo the last transaction. @@ -654,6 +660,33 @@ Show the list of live store files and directories. @end table +@node Invoking guix pull +@section Invoking @command{guix pull} + +Packages are installed or upgraded to the latest version available in +the distribution currently available on your local machine. To update +that distribution, along with the Guix tools, you must run @command{guix +pull}: the command downloads the latest Guix source code and package +descriptions, and deploys it. + +On completion, @command{guix package} will use packages and package +versions from this just-retrieved copy of Guix. Not only that, but all +the Guix commands and Scheme modules will also be taken from that latest +version. New @command{guix} sub-commands added by the update also +become available. + +The @command{guix pull} command is usually invoked with no arguments, +but it supports the following options: + +@table @code +@item --verbose +Produce verbose output, writing build logs to the standard error output. + +@item --bootstrap +Use the bootstrap Guile to build the latest Guix. This option is only +useful to Guix developers. +@end table + @c ********************************************************************* @node Programming Interface @chapter Programming Interface diff --git a/guix/scripts/pull.scm b/guix/scripts/pull.scm new file mode 100644 index 000000000..f12133fff --- /dev/null +++ b/guix/scripts/pull.scm @@ -0,0 +1,222 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2013 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix scripts pull) + #:use-module (guix ui) + #:use-module (guix store) + #:use-module (guix config) + #:use-module (guix packages) + #:use-module (guix derivations) + #:use-module (guix build download) + #:use-module (gnu packages base) + #:use-module ((gnu packages bootstrap) + #:select (%bootstrap-guile)) + #:use-module (gnu packages compression) + #:use-module (gnu packages gnupg) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-37) + #:export (guix-pull)) + +(define %snapshot-url + "http://hydra.gnu.org/job/guix/master/tarball/latest/download" + ;;"http://git.savannah.gnu.org/cgit/guix.git/snapshot/guix-master.tar.gz" + ) + +(define (download-and-store store) + "Download the latest Guix tarball, add it to STORE, and return its store +path." + ;; FIXME: Authenticate the downloaded file! + ;; FIXME: Optimize data transfers using rsync, Git, bsdiff, or GNUnet's DHT. + (call-with-temporary-output-file + (lambda (temp port) + (let ((result + (parameterize ((current-output-port (current-error-port))) + (url-fetch %snapshot-url temp)))) + (close port) + (and result + (add-to-store store "guix-latest.tar.gz" #f "sha256" temp)))))) + +(define (unpack store tarball) + "Return a derivation that unpacks TARBALL into STORE and compiles Scheme +files." + (define builder + `(begin + (use-modules (guix build utils) + (system base compile) + (ice-9 ftw) + (ice-9 match)) + + (let ((out (assoc-ref %outputs "out")) + (tar (assoc-ref %build-inputs "tar")) + (gzip (assoc-ref %build-inputs "gzip")) + (gcrypt (assoc-ref %build-inputs "gcrypt")) + (tarball (assoc-ref %build-inputs "tarball"))) + (setenv "PATH" (string-append tar "/bin:" gzip "/bin")) + + (system* "tar" "xvf" tarball) + (match (scandir "." (lambda (name) + (and (not (member name '("." ".."))) + (file-is-directory? name)))) + ((dir) + (chdir dir)) + (x + (error "tarball did not produce a single source directory" x))) + + (format #t "copying and compiling Guix to `~a'...~%" out) + + ;; Copy everything under guix/ and gnu/ plus guix.scm. + (file-system-fold (lambda (dir stat result) ; enter? + (or (string-prefix? "./guix" dir) + (string-prefix? "./gnu" dir) + (string=? "." dir))) + (lambda (file stat result) ; leaf + (when (or (not (string=? (dirname file) ".")) + (string=? (basename file) "guix.scm")) + (let ((target (string-drop file 1))) + (copy-file file + (string-append out target))))) + (lambda (dir stat result) ; down + (mkdir (string-append out + (string-drop dir 1)))) + (const #t) ; up + (const #t) ; skip + (lambda (file stat errno result) + (error "cannot access file" + file (strerror errno))) + #f + "." + lstat) + + ;; Add a fake (guix config) module to allow the other modules to be + ;; compiled. The user's (guix config) is the one that will be used. + (copy-file "guix/config.scm.in" + (string-append out "/guix/config.scm")) + (substitute* (string-append out "/guix/config.scm") + (("@LIBGCRYPT@") + (string-append gcrypt "/lib/libgcrypt"))) + + ;; Augment the search path so Scheme code can be compiled. + (set! %load-path (cons out %load-path)) + (set! %load-compiled-path (cons out %load-compiled-path)) + + ;; Compile the .scm files. + (for-each (lambda (file) + (when (string-suffix? ".scm" file) + (let ((go (string-append (string-drop-right file 4) + ".go"))) + (compile-file file + #:output-file go + #:opts %auto-compilation-options)))) + (find-files out "\\.scm")) + + ;; Remove the "fake" (guix config). + (delete-file (string-append out "/guix/config.scm")) + (delete-file (string-append out "/guix/config.go"))))) + + (build-expression->derivation store "guix-latest" (%current-system) + builder + `(("tar" ,(package-derivation store tar)) + ("gzip" ,(package-derivation store gzip)) + ("gcrypt" ,(package-derivation store + libgcrypt)) + ("tarball" ,tarball)) + #:modules '((guix build utils)))) + + +;;; +;;; Command-line options. +;;; + +(define %default-options + ;; Alist of default option values. + '()) + +(define (show-help) + (display (_ "Usage: guix pull [OPTION]... +Download and deploy the latest version of Guix.\n")) + (display (_ " + --verbose produce verbose output")) + (display (_ " + --bootstrap use the bootstrap Guile to build the new Guix")) + (newline) + (display (_ " + -h, --help display this help and exit")) + (display (_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + +(define %options + ;; Specifications of the command-line options. + (list (option '("verbose") #f #f + (lambda (opt name arg result) + (alist-cons 'verbose? #t result))) + (option '("bootstrap") #f #f + (lambda (opt name arg result) + (alist-cons 'bootstrap? #t result))) + + (option '(#\h "help") #f #f + (lambda args + (show-help) + (exit 0))) + (option '(#\V "version") #f #f + (lambda args + (show-version-and-exit "guix pull"))))) + +(define (guix-pull . args) + (define (parse-options) + ;; Return the alist of option values. + (args-fold args %options + (lambda (opt name arg result) + (leave (_ "~A: unrecognized option~%") name)) + (lambda (arg result) + (leave (_ "~A: unexpected argument~%") arg)) + %default-options)) + + (let ((opts (parse-options)) + (store (open-connection))) + (with-error-handling + (let ((tarball (download-and-store store))) + (unless tarball + (leave (_ "failed to download up-to-date source, exiting\n"))) + (parameterize ((%guile-for-build + (package-derivation store + (if (assoc-ref opts 'bootstrap?) + %bootstrap-guile + guile-final))) + (current-build-output-port + (if (assoc-ref opts 'verbose?) + (current-error-port) + (%make-void-port "w")))) + (let*-values (((config-dir) + (config-directory)) + ((source drv) + (unpack store tarball)) + ((source-dir) + (derivation-output-path + (assoc-ref (derivation-outputs drv) "out")))) + (show-what-to-build store (list source)) + (if (build-derivations store (list source)) + (let ((latest (string-append config-dir "/latest"))) + (add-indirect-root store latest) + (switch-symlinks latest source-dir) + (format #t + (_ "updated ~a successfully deployed under `~a'~%") + %guix-package-name latest) + #t)))))))) diff --git a/guix/ui.scm b/guix/ui.scm index 2b7550457..7d1ea2bcb 100644 --- a/guix/ui.scm +++ b/guix/ui.scm @@ -41,6 +41,7 @@ location->string call-with-temporary-output-file switch-symlinks + config-directory fill-paragraph string->recutils package->recutils @@ -178,6 +179,26 @@ both when LINK already exists and when it does not." (symlink target pivot) (rename-file pivot link))) +(define (config-directory) + "Return the name of the configuration directory, after making sure that it +exists. Honor the XDG specs, +." + (let ((dir (and=> (or (getenv "XDG_CONFIG_HOME") + (and=> (getenv "HOME") + (cut string-append <> "/.config"))) + (cut string-append <> "/guix")))) + (catch 'system-error + (lambda () + (mkdir dir) + dir) + (lambda args + (match (system-error-errno args) + ((or EEXIST 0) + dir) + (err + (leave (_ "failed to create configuration directory `~a': ~a~%") + dir (strerror err)))))))) + (define* (fill-paragraph str width #:optional (column 0)) "Fill STR such that each line contains at most WIDTH characters, assuming that the first character is at COLUMN. diff --git a/po/POTFILES.in b/po/POTFILES.in index 5c0f131c0..bdb894db2 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -8,4 +8,5 @@ guix/scripts/build.scm guix/scripts/download.scm guix/scripts/package.scm guix/scripts/gc.scm +guix/scripts/pull.scm guix/ui.scm diff --git a/scripts/guix.in b/scripts/guix.in index 2fdde7d13..1315789a9 100644 --- a/scripts/guix.in +++ b/scripts/guix.in @@ -22,7 +22,8 @@ ;; IMPORTANT: We must avoid loading any modules from Guix here, ;; because we need to adjust the guile load paths first. ;; It's okay to import modules from core Guile though. -(use-modules (ice-9 regex)) +(use-modules (ice-9 regex) + (srfi srfi-26)) (let () (define-syntax-rule (push! elt v) (set! v (cons elt v))) @@ -45,7 +46,14 @@ (unless (getenv "GUIX_UNINSTALLED") (let ((module-dir (config-lookup "guilemoduledir"))) (push! module-dir %load-path) - (push! module-dir %load-compiled-path)))) + (push! module-dir %load-compiled-path)) + (let ((updates-dir (and=> (or (getenv "XDG_CONFIG_HOME") + (and=> (getenv "HOME") + (cut string-append <> "/.config"))) + (cut string-append <> "/guix/latest")))) + (when (file-exists? updates-dir) + (push! updates-dir %load-path) + (push! updates-dir %load-compiled-path))))) (define (run-guix-main) (let ((guix-main (module-ref (resolve-interface '(guix ui)) -- cgit v1.3 From 4cdbdd4439d493659af60608c37704545b376600 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sat, 2 Mar 2013 17:00:33 +0100 Subject: gnu: Add libdaemon. * gnu/packages/libdaemon.scm: New file. * Makefile.am (MODULES): Add it. --- Makefile.am | 1 + gnu/packages/libdaemon.scm | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 gnu/packages/libdaemon.scm (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index bed4d06ec..9018479a4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -98,6 +98,7 @@ MODULES = \ gnu/packages/ld-wrapper.scm \ gnu/packages/less.scm \ gnu/packages/libapr.scm \ + gnu/packages/libdaemon.scm \ gnu/packages/libevent.scm \ gnu/packages/libffi.scm \ gnu/packages/libidn.scm \ diff --git a/gnu/packages/libdaemon.scm b/gnu/packages/libdaemon.scm new file mode 100644 index 000000000..0c77e280a --- /dev/null +++ b/gnu/packages/libdaemon.scm @@ -0,0 +1,61 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2013 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu packages libdaemon) + #:use-module (guix licenses) + #:use-module (guix packages) + #:use-module (guix download) + #:use-module (guix build-system gnu)) + +(define-public libdaemon + (package + (name "libdaemon") + (version "0.14") + (source (origin + (method url-fetch) + (uri (string-append + "http://0pointer.de/lennart/projects/libdaemon/libdaemon-" + version + ".tar.gz")) + (sha256 + (base32 + "0d5qlq5ab95wh1xc87rqrh1vx6i8lddka1w3f1zcqvcqdxgyn8zx")))) + (build-system gnu-build-system) + (home-page "http://0pointer.de/lennart/projects/libdaemon/") + (synopsis "Lightweight C library that eases the writing of UNIX daemons") + (description + "libdaemon is a lightweight C library that eases the writing of UNIX +daemons. It consists of the following parts: + + • A wrapper around fork() which does the correct daemonization procedure of + a process + + • A wrapper around syslog() for simpler and compatible log output to Syslog + or STDERR + + • An API for writing PID files + + • An API for serializing UNIX signals into a pipe for usage with select() or + poll() + + • An API for running subprocesses with STDOUT and STDERR redirected to + syslog. + +APIs like these are used in most daemon software available. It is not that +simple to get it done right and code duplication is not a goal.") + (license lgpl2.1+))) -- cgit v1.3 From 49f24f41e33d8ee1c6d8e5a92d388c3aebc3b81a Mon Sep 17 00:00:00 2001 From: Andreas Enge Date: Sun, 3 Mar 2013 14:10:57 +0100 Subject: gnu: Add vpnc. * gnu/packages/vpn.scm: New file. * Makefile.am (MODULES): Add it. * gnu/packages/patches/vpnc-script.patch: New file. * Makefile.am (dist_patch_DATA): Add it. --- Makefile.am | 4 ++- gnu/packages/patches/vpnc-script.patch | 15 ++++++++ gnu/packages/vpn.scm | 66 ++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 gnu/packages/patches/vpnc-script.patch create mode 100644 gnu/packages/vpn.scm (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index 9018479a4..b70349adc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -158,6 +158,7 @@ MODULES = \ gnu/packages/tmux.scm \ gnu/packages/tor.scm \ gnu/packages/vim.scm \ + gnu/packages/vpn.scm \ gnu/packages/wdiff.scm \ gnu/packages/wget.scm \ gnu/packages/which.scm \ @@ -215,7 +216,8 @@ dist_patch_DATA = \ gnu/packages/patches/shishi-gets-undeclared.patch \ gnu/packages/patches/tar-gets-undeclared.patch \ gnu/packages/patches/tcsh-fix-autotest.patch \ - gnu/packages/patches/teckit-cstdio.patch + gnu/packages/patches/teckit-cstdio.patch \ + gnu/packages/patches/vpnc-script.patch bootstrapdir = $(guilemoduledir)/gnu/packages/bootstrap bootstrap_x86_64_linuxdir = $(bootstrapdir)/x86_64-linux diff --git a/gnu/packages/patches/vpnc-script.patch b/gnu/packages/patches/vpnc-script.patch new file mode 100644 index 000000000..a0d948195 --- /dev/null +++ b/gnu/packages/patches/vpnc-script.patch @@ -0,0 +1,15 @@ +This patch adapts the vpnc script to newer kernel versions, see + https://lkml.org/lkml/2011/3/24/645 + +diff -u a/vpnc-script.in b/vpnc-script.in +--- a/vpnc-script.in 2013-03-03 13:55:16.000000000 +0100 ++++ b/vpnc-script.in 2013-03-03 13:56:11.000000000 +0100 +@@ -116,7 +116,7 @@ + + if [ -n "$IPROUTE" ]; then + fix_ip_get_output () { +- sed 's/cache//;s/metric \?[0-9]\+ [0-9]\+//g;s/hoplimit [0-9]\+//g' ++ sed 's/cache//;s/metric \?[0-9]\+ [0-9]\+//g;s/hoplimit [0-9]\+//g;s/ipid 0x....//g' + } + + set_vpngateway_route() { diff --git a/gnu/packages/vpn.scm b/gnu/packages/vpn.scm new file mode 100644 index 000000000..9393e1e7b --- /dev/null +++ b/gnu/packages/vpn.scm @@ -0,0 +1,66 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2013 Andreas Enge +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu packages vpn) + #:use-module ((guix licenses) + #:renamer (symbol-prefix-proc 'license:)) + #:use-module (guix packages) + #:use-module (guix download) + #:use-module (guix build-system gnu) + #:use-module (gnu packages) + #:use-module (gnu packages gnupg) + #:use-module (gnu packages perl)) + +(define-public vpnc + (package + (name "vpnc") + (version "0.5.3") + (source (origin + (method url-fetch) + (uri (string-append "http://www.unix-ag.uni-kl.de/~massar/vpnc/vpnc-" + version ".tar.gz")) + (sha256 (base32 + "1128860lis89g1s21hqxvap2nq426c9j4bvgghncc1zj0ays7kj6")))) + (build-system gnu-build-system) + (inputs `(("libgcrypt" ,libgcrypt) + ("perl" ,perl) + ("patch/script" + ,(search-patch "vpnc-script.patch")))) + (arguments + `(#:tests? #f ; there is no check target + #:patches (list (assoc-ref %build-inputs + "patch/script")) + #:phases + (alist-replace + 'configure + (lambda* (#:key outputs #:allow-other-keys) + (let ((out (assoc-ref outputs "out"))) + (substitute* "Makefile" + (("PREFIX=/usr/local") (string-append "PREFIX=" out))) + (substitute* "Makefile" + (("ETCDIR=/etc/vpnc") (string-append "ETCDIR=" out "/etc/vpnc"))))) + %standard-phases))) + (synopsis "vpnc, a client for cisco vpn concentrators") + (description + "vpnc is a VPN client compatible with Cisco's EasyVPN equipment. +It supports IPSec (ESP) with Mode Configuration and Xauth. It supports only +shared-secret IPSec authentication with Xauth, AES (256, 192, 128), 3DES, +1DES, MD5, SHA1, DH1/2/5 and IP tunneling. It runs entirely in userspace. +Only \"Universal TUN/TAP device driver support\" is needed in the kernel.") + (license license:gpl2+) ; some file are bsd-2, see COPYING + (home-page "http://www.unix-ag.uni-kl.de/~massar/vpnc/"))) -- cgit v1.3 From 08fd1ebefdf7a61ede3de490dc466bc41ef1ba97 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Mon, 4 Mar 2013 00:41:46 +0100 Subject: Add (guix build-system perl). * guix/build-system/perl.scm, guix/build/perl-build-system.scm: New files. * Makefile.am (MODULES): Add them. * guix/build-system/gnu.scm (standard-inputs): Make public. --- Makefile.am | 2 + guix/build-system/gnu.scm | 2 +- guix/build-system/perl.scm | 103 +++++++++++++++++++++++++++++++++++++++ guix/build/perl-build-system.scm | 61 +++++++++++++++++++++++ 4 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 guix/build-system/perl.scm create mode 100644 guix/build/perl-build-system.scm (limited to 'Makefile.am') diff --git a/Makefile.am b/Makefile.am index b70349adc..c56bc4122 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,12 +39,14 @@ MODULES = \ guix/licenses.scm \ guix/build-system.scm \ guix/build-system/gnu.scm \ + guix/build-system/perl.scm \ guix/build-system/trivial.scm \ guix/ftp-client.scm \ guix/store.scm \ guix/ui.scm \ guix/build/download.scm \ guix/build/gnu-build-system.scm \ + guix/build/perl-build-system.scm \ guix/build/utils.scm \ guix/build/union.scm \ guix/packages.scm \ diff --git a/guix/build-system/gnu.scm b/guix/build-system/gnu.scm index 5be4782c2..8049e7510 100644 --- a/guix/build-system/gnu.scm +++ b/guix/build-system/gnu.scm @@ -21,13 +21,13 @@ #:use-module (guix utils) #:use-module (guix derivations) #:use-module (guix build-system) - #:use-module (guix build-system gnu) #:use-module (guix packages) #:use-module (srfi srfi-1) #:use-module (srfi srfi-39) #:use-module (ice-9 match) #:export (gnu-build gnu-build-system + standard-inputs package-with-explicit-inputs package-with-extra-configure-variable static-libgcc-package diff --git a/guix/build-system/perl.scm b/guix/build-system/perl.scm new file mode 100644 index 000000000..537c29e79 --- /dev/null +++ b/guix/build-system/perl.scm @@ -0,0 +1,103 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2013 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix build-system perl) + #:use-module (guix store) + #:use-module (guix utils) + #:use-module (guix derivations) + #:use-module (guix build-system) + #:use-module (guix build-system gnu) + #:use-module (guix packages) + #:use-module (ice-9 match) + #:export (perl-build + perl-build-system)) + +;; Commentary: +;; +;; Standard build procedure for Perl packages using the "makefile +;; maker"---i.e., "perl Makefile.PL". This is implemented as an extension of +;; `gnu-build-system'. +;; +;; Code: + +(define* (perl-build store name source inputs + #:key + (perl (@ (gnu packages perl) perl)) + (tests? #t) + (make-maker-flags ''()) + (phases '(@ (guix build perl-build-system) + %standard-phases)) + (outputs '("out")) + (system (%current-system)) + (guile #f) + (imported-modules '((guix build perl-build-system) + (guix build gnu-build-system) + (guix build utils))) + (modules '((guix build perl-build-system) + (guix build gnu-build-system) + (guix build utils)))) + "Build SOURCE using PERL, and with INPUTS. This assumes that SOURCE +provides a `Makefile.PL' file as its build system." + (define builder + `(begin + (use-modules ,@modules) + (perl-build #:name ,name + #:source ,(if (and source (derivation-path? source)) + (derivation-path->output-path source) + source) + #:make-maker-flags ,make-maker-flags + #:system ,system + #:test-target "test" + #:tests? ,tests? + #:outputs %outputs + #:inputs %build-inputs))) + + (define guile-for-build + (match guile + ((? package?) + (package-derivation store guile system)) + ((and (? string?) (? derivation-path?)) + guile) + (#f ; the default + (let* ((distro (resolve-interface '(gnu packages base))) + (guile (module-ref distro 'guile-final))) + (package-derivation store guile system))))) + + (let ((perl (package-derivation store perl system))) + (build-expression->derivation store name system + builder + `(,@(if source + `(("source" ,source)) + '()) + ("perl" ,perl) + ,@inputs + + ;; Keep the standard inputs of + ;; `gnu-build-system'. + ,@(standard-inputs system)) + + #:modules imported-modules + #:outputs outputs + #:guile-for-build guile-for-build))) + +(define perl-build-system + (build-system (name 'perl) + (description "The standard Perl build system") + (build perl-build))) + +;;; perl.scm ends here diff --git a/guix/build/perl-build-system.scm b/guix/build/perl-build-system.scm new file mode 100644 index 000000000..d625ef3ed --- /dev/null +++ b/guix/build/perl-build-system.scm @@ -0,0 +1,61 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2013 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix build perl-build-system) + #:use-module ((guix build gnu-build-system) + #:renamer (symbol-prefix-proc 'gnu:)) + #:use-module (guix build utils) + #:use-module (ice-9 match) + #:export (%standard-phases + perl-build)) + +;; Commentary: +;; +;; Builder-side code of the standard Perl package build procedure. +;; +;; Code: + +(define* (configure #:key outputs (make-maker-flags '()) + #:allow-other-keys) + "Configure the given Perl package." + (let ((out (assoc-ref outputs "out"))) + (if (file-exists? "Makefile.PL") + (let ((args `("Makefile.PL" ,(string-append "PREFIX=" out) + "INSTALLDIRS=site" ,@make-maker-flags))) + (format #t "running `perl' with arguments ~s~%" args) + (zero? (apply system* "perl" args))) + (error "no Makefile.PL found")))) + +(define %standard-phases + ;; Everything is as with the GNU Build System except for the `configure' + ;; phase. + (alist-replace 'configure configure + gnu:%standard-phases)) + +(define* (perl-build #:key inputs (phases %standard-phases) + #:allow-other-keys #:rest args) + "Build the given Perl package, applying all of PHASES in order." + (set-path-environment-variable "PERL5LIB" '("lib/perl5/site_perl") + (match inputs + (((_ . path) ...) + path))) + (apply gnu:gnu-build + #:inputs inputs #:phases phases + args)) + +;;; perl-build-system.scm ends here -- cgit v1.3