summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2012-12-13 22:14:25 +0100
committerLudovic Courtès <ludo@gnu.org>2012-12-13 22:14:25 +0100
commit1e9824513c570370638b1bfe33bf1dba1f12be4a (patch)
treecb7bd7f0bebd42dbeabf2c8f09ae1d5144ac969b
parent70915c1a2ef72e7350b2a29d1d93e30643bce6f3 (diff)
parentb35c0f866c83288e64dcf5839d908705d416c317 (diff)
downloadguix-1e9824513c570370638b1bfe33bf1dba1f12be4a.tar.gz
Merge branch 'nix-integration'
Conflicts:
	tests/guix-package.sh
-rw-r--r--.gitignore13
-rw-r--r--.gitmodules3
-rw-r--r--Makefile.am14
-rw-r--r--README13
-rw-r--r--TODO9
-rwxr-xr-xbootstrap16
-rw-r--r--config-daemon.ac100
-rw-r--r--configure.ac32
-rw-r--r--daemon.am169
-rw-r--r--guix/config.scm.in12
-rw-r--r--guix/store.scm9
-rw-r--r--guix/utils.scm3
-rw-r--r--m4/guix.m430
m---------nix-upstream6
-rw-r--r--nix/.gitignore4
-rw-r--r--nix/boost/.gitignore3
-rw-r--r--nix/libstore/.gitignore3
-rw-r--r--nix/libutil/.gitignore2
-rw-r--r--nix/libutil/gcrypt-hash.cc50
-rw-r--r--nix/libutil/gcrypt-hash.hh39
-rw-r--r--nix/libutil/md5.h35
-rw-r--r--nix/libutil/sha1.h35
-rw-r--r--nix/libutil/sha256.h35
-rw-r--r--nix/nix-daemon/guix-daemon.cc159
-rw-r--r--nix/nix-daemon/shared.hh37
-rw-r--r--nix/scripts/list-runtime-roots.in116
-rwxr-xr-xnix/sync-with-upstream68
-rw-r--r--release.nix35
-rw-r--r--test-env.in59
-rw-r--r--tests/base32.scm18
-rw-r--r--tests/builders.scm5
-rw-r--r--tests/derivations.scm8
-rw-r--r--tests/guix-daemon.sh29
-rw-r--r--tests/guix-package.sh46
-rw-r--r--tests/packages.scm2
-rw-r--r--tests/union.scm6
-rw-r--r--tests/utils.scm5
37 files changed, 1170 insertions, 58 deletions
diff --git a/.gitignore b/.gitignore
index 1fe15621e2..8f224467c9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,3 +50,16 @@ config.cache
 /guix-package
 /guix/config.scm
 /guix-import
+/nix/nix-daemon/nix-daemon.cc
+/nix/config.h
+/nix/config.h.in
+stamp-h[0-9]
+/nix/AUTHORS
+/nix/COPYING
+/libformat.a
+/libstore.a
+/libutil.a
+/guix-daemon
+/test-tmp
+/nix/scripts/list-runtime-roots
+/test-env
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000..0c3b046608
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "nix-upstream"]
+	path = nix-upstream
+	url = http://github.com/NixOS/nix.git
diff --git a/Makefile.am b/Makefile.am
index 7c33fe4b14..0b59f8901c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -186,10 +186,10 @@ TEST_EXTENSIONS = .scm .sh
 
 AM_TESTS_ENVIRONMENT = abs_top_srcdir="$(abs_top_srcdir)"
 
-SCM_LOG_COMPILER = $(top_builddir)/pre-inst-env $(GUILE)
+SCM_LOG_COMPILER = $(top_builddir)/test-env $(GUILE)
 AM_SCM_LOG_FLAGS = --no-auto-compile -L "$(top_srcdir)"
 
-SH_LOG_COMPILER = $(top_builddir)/pre-inst-env $(SHELL)
+SH_LOG_COMPILER = $(top_builddir)/test-env $(SHELL)
 AM_SH_LOG_FLAGS = -x -e
 
 EXTRA_DIST =					\
@@ -203,6 +203,7 @@ EXTRA_DIST =					\
   srfi/srfi-64.upstream.scm			\
   tests/test.drv				\
   build-aux/config.rpath			\
+  bootstrap					\
   release.nix					\
   $(TESTS)
 
@@ -231,7 +232,14 @@ SUBDIRS = po
 info_TEXINFOS = doc/guix.texi
 EXTRA_DIST += doc/fdl-1.3.texi
 
+if BUILD_DAEMON
+
+include daemon.am
+
+endif BUILD_DAEMON
+
 ACLOCAL_AMFLAGS = -I m4
 AM_DISTCHECK_CONFIGURE_FLAGS =			\
   --with-libgcrypt-prefix="$(LIBGCRYPT_PREFIX)"	\
-  --with-nix-prefix="$(NIX_PREFIX)"
+  --with-nix-prefix="$(NIX_PREFIX)"		\
+  --enable-daemon
diff --git a/README b/README
index 9fdcc0effe..d2bbfacd5a 100644
--- a/README
+++ b/README
@@ -16,14 +16,23 @@ Guix.
 Guix is based on the [[http://nixos.org/nix/][Nix]] package manager.
 
 
-* Hacking
+* Requirements
 
 GNU Guix currently depends on the following packages:
 
   - [[http://gnu.org/software/guile/][GNU Guile 2.0.x]]
-  - [[http://nixos.org/nix/][Nix]]
   - [[http://gnupg.org/][GNU libgcrypt]]
 
+Unless `--disable-daemon' was passed, the following packages are needed:
+
+  - [[http://sqlite.org/][SQLite 3]]
+  - [[http://www.bzip.org][libbz2]]
+  - [[http://gcc.gnu.org][GCC's g++]]
+
+When `--disable-daemon' was passed, you instead need the following:
+
+  - [[http://nixos.org/nix/][Nix]]
+
 Optionally, packages from Nixpkgs may be transparently reused from Guix.
 For this to work, you need to have a checkout of the Nixpkgs repository;
 the `--with-nixpkgs' option allows you to let `configure' know where the
diff --git a/TODO b/TODO
index 1579504ea5..5510ee8c76 100644
--- a/TODO
+++ b/TODO
@@ -14,6 +14,15 @@ and GC-related tasks.  The daemon mainly uses ‘libstore’ from Nix.
 Integrating it in Guix itself will make Guix self-contained, thereby
 simplifying our users’ lives.
 
+** Remove dependency on OpenSSL
+
+The ‘openssl’ command-line tool is used in libstore to sign store paths
+to be exported, and to check such signatures.  The signing keys are
+usually in /etc/nix/signing-key.{pub,sec}.  They are a PKCS#8-encoded
+X.509 SubjectPublicKeyInfo.  These can be decoded with the [[http://lists.gnu.org/archive/html/help-gnutls/2012-12/msg00012.html][C API of
+GnuTLS]], but not yet with its Guile bindings.  There’s also
+‘gnutls_privkey_sign_data’ to sign, and related functions.
+
 * infrastructure
 
 ** have a Hydra instance build Guix packages
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000000..e445af2f2c
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Import missing source files and create the build system.
+
+set -e -x
+
+top_srcdir="$PWD"
+export top_srcdir
+
+if [ ! -d nix-upstream ]
+then
+    git submodule init
+fi
+git submodule update
+
+exec autoreconf -vfi
diff --git a/config-daemon.ac b/config-daemon.ac
new file mode 100644
index 0000000000..f48741dfda
--- /dev/null
+++ b/config-daemon.ac
@@ -0,0 +1,100 @@
+dnl -*- Autoconf -*- fragment for the C++ daemon.
+
+AC_MSG_CHECKING([whether to build daemon])
+AC_MSG_RESULT([$guix_build_daemon])
+
+dnl C++ environment.  This macro must be used unconditionnaly.
+AC_PROG_CXX
+
+if test "x$guix_build_daemon" = "xyes"; then
+
+  AC_PROG_RANLIB
+  AC_CONFIG_HEADER([nix/config.h])
+
+  dnl Use 64-bit file system calls so that we can support files > 2 GiB.
+  AC_SYS_LARGEFILE
+
+  dnl Look for libbz2, a required dependency.
+  AC_CHECK_LIB([bz2], [BZ2_bzWriteOpen], [true],
+    [AC_MSG_ERROR([Guix requires libbz2, which is part of bzip2.  See http://www.bzip.org/.])])
+  AC_CHECK_HEADERS([bzlib.h], [true],
+    [AC_MSG_ERROR([Guix requires libbz2, which is part of bzip2.  See http://www.bzip.org/.])])
+
+  dnl Look for SQLite, a required dependency.
+  PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.6.19])
+
+  AC_DEFINE([NIX_VERSION], ["0.0.0"], [Fake Nix version number.])
+  AC_DEFINE_UNQUOTED([SYSTEM], ["$guix_system"],
+    [Guix host system type--i.e., platform and OS kernel tuple.])
+
+  case "$LIBGCRYPT_PREFIX" in
+    no)
+      LIBGCRYPT_CFLAGS=""
+      LIBGCRYPT_LIBS=""
+      ;;
+    *)
+      LIBGCRYPT_CFLAGS="-I$LIBGCRYPT_PREFIX/include"
+      LIBGCRYPT_LIBS="-L$LIBGCRYPT_PREFIX/lib -lgcrypt"
+      ;;
+  esac
+  AC_SUBST([LIBGCRYPT_CFLAGS])
+  AC_SUBST([LIBGCRYPT_LIBS])
+
+  save_CFLAGS="$CFLAGS"
+  save_LDFLAGS="$LDFLAGS"
+  CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS"
+  LDFLAGS="$LDFLAGS $LIBGCRYPT_LDFLAGS"
+
+  have_gcrypt=yes
+  AC_CHECK_LIB([gcrypt], [gcry_md_open], [:], [have_gcrypt=no])
+  AC_CHECK_HEADER([gcrypt.h], [:], [have_gcrypt=no])
+  if test "x$have_gcrypt" != "xyes"; then
+    AC_MSG_ERROR([GNU libgcrypt not found; please install it.])
+  fi
+
+  CFLAGS="$save_CFLAGS"
+  LDFLAGS="$save_LDFLAGS"
+
+  dnl Chroot support.
+  AC_CHECK_FUNCS([chroot unshare])
+  AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h])
+
+  dnl Check for lutimes, optionally used for changing the mtime of
+  dnl symlinks.
+  AC_CHECK_FUNCS([lutimes])
+
+  dnl Check whether the store optimiser can optimise symlinks.
+  AC_MSG_CHECKING([whether it is possible to create a link to a symlink])
+  ln -s bla tmp_link
+  if ln tmp_link tmp_link2 2> /dev/null; then
+      AC_MSG_RESULT(yes)
+      AC_DEFINE(CAN_LINK_SYMLINK, 1, [Whether link() works on symlinks.])
+  else
+      AC_MSG_RESULT(no)
+  fi
+  rm -f tmp_link tmp_link2
+
+  dnl Check for <locale>.
+  AC_LANG_PUSH(C++)
+  AC_CHECK_HEADERS([locale])
+  AC_LANG_POP(C++)
+
+
+  dnl Check whether we have the `personality' syscall, which allows us
+  dnl to do i686-linux builds on x86_64-linux machines.
+  AC_CHECK_HEADERS([sys/personality.h])
+
+  dnl Check for <linux/fs.h> (for immutable file support).
+  AC_CHECK_HEADERS([linux/fs.h])
+
+  dnl Temporary directory used to store the daemon's data.
+  AC_MSG_CHECKING([for unit test root])
+  GUIX_TEST_ROOT="`pwd`/test-tmp"
+  AC_MSG_RESULT([$GUIX_TEST_ROOT])
+  AC_SUBST([GUIX_TEST_ROOT])
+
+  AC_CONFIG_FILES([nix/scripts/list-runtime-roots],
+    [chmod +x nix/scripts/list-runtime-roots])
+fi
+
+AM_CONDITIONAL([BUILD_DAEMON], [test "x$guix_build_daemon" = "xyes"])
diff --git a/configure.ac b/configure.ac
index 65fc01857f..bebb9885c4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12,13 +12,33 @@ AM_INIT_AUTOMAKE([1.11 gnu silent-rules subdir-objects \
 AC_CONFIG_SRCDIR([guix.scm])
 AC_CONFIG_MACRO_DIR([m4])
 
+dnl For the C++ code.  This must be used early.
+AC_USE_SYSTEM_EXTENSIONS
+
 AM_GNU_GETTEXT([external])
 AM_GNU_GETTEXT_VERSION([0.18.1])
 
 guilemoduledir="${datarootdir}/guile/site/2.0"
 AC_SUBST([guilemoduledir])
 
-AC_CANONICAL_HOST
+GUIX_SYSTEM_TYPE
+
+AC_ARG_WITH(store-dir,
+  AC_HELP_STRING([--with-store-dir=PATH],
+    [path of the store (defaults to /nix/store)]),
+  [storedir="$withval"],
+  [storedir="/nix/store"])
+AC_SUBST(storedir)
+
+AC_ARG_ENABLE([daemon],
+  [AS_HELP_STRING([--disable-daemon], [build the Nix daemon (C++)])],
+  [guix_build_daemon="$enableval"],
+  [guix_build_daemon="yes"])
+
+# Prepare a version of $localstatedir that does not contain references
+# to shell variables.
+guix_localstatedir="`eval echo $localstatedir | sed -e "s|NONE|/usr/local|g"`"
+AC_SUBST([guix_localstatedir])
 
 PKG_CHECK_MODULES([GUILE], [guile-2.0])
 AC_PATH_PROG([GUILE], [guile])
@@ -41,7 +61,7 @@ AC_ARG_WITH([nix-prefix],
 
 AC_PATH_PROG([NIX_INSTANTIATE], [nix-instantiate])
 AC_PATH_PROG([NIX_HASH], [nix-hash])
-if test "x$NIX_INSTANTIATE$NIX_HASH" = "x"; then
+if test "x$guix_build_daemon$NIX_INSTANTIATE$NIX_HASH" = "xno"; then
    AC_MSG_ERROR([Nix programs not found; please install Nix or use `--with-nix-prefix'.])
 fi
 
@@ -83,6 +103,9 @@ AC_SUBST([LIBGCRYPT_PREFIX])
 
 GUIX_ASSERT_LIBGCRYPT_USABLE
 
+AC_CACHE_SAVE
+
+m4_include([config-daemon.ac])
 
 AC_CONFIG_FILES([Makefile
                  po/Makefile.in
@@ -91,9 +114,10 @@ AC_CONFIG_FILES([Makefile
 		 guix-download
 		 guix-import
 		 guix-package
-		 pre-inst-env])
+		 pre-inst-env
+		 test-env])
 
 AC_CONFIG_COMMANDS([commands-exec],
-  [chmod +x guix-build guix-download guix-import guix-package pre-inst-env])
+  [chmod +x guix-build guix-download guix-import guix-package pre-inst-env test-env])
 
 AC_OUTPUT
diff --git a/daemon.am b/daemon.am
new file mode 100644
index 0000000000..aa75c6ed29
--- /dev/null
+++ b/daemon.am
@@ -0,0 +1,169 @@
+# Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+# Copyright (C) 2012 Ludovic Courtès <ludo@gnu.org>
+#
+# This file is part of Guix.
+#
+# 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.
+#
+# 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 Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+#
+# Integration of the `guix-daemon' code taken from upstream Nix.
+#
+
+BUILT_SOURCES = nix/libstore/schema.sql.hh
+CLEANFILES += $(BUILT_SOURCES)
+
+noinst_LIBRARIES = libformat.a libutil.a libstore.a
+
+libformat_a_SOURCES =				\
+  nix/boost/format/free_funcs.cc		\
+  nix/boost/format/parsing.cc			\
+  nix/boost/format/format_implementation.cc
+
+libformat_headers =				\
+  nix/boost/weak_ptr.hpp			\
+  nix/boost/throw_exception.hpp			\
+  nix/boost/checked_delete.hpp			\
+  nix/boost/shared_ptr.hpp			\
+  nix/boost/format.hpp				\
+  nix/boost/assert.hpp				\
+  nix/boost/format/macros_default.hpp		\
+  nix/boost/format/format_fwd.hpp		\
+  nix/boost/format/format_class.hpp		\
+  nix/boost/format/exceptions.hpp		\
+  nix/boost/format/group.hpp			\
+  nix/boost/format/feed_args.hpp		\
+  nix/boost/format/internals_fwd.hpp		\
+  nix/boost/format/internals.hpp		\
+  nix/boost/detail/workaround.hpp		\
+  nix/boost/detail/shared_count.hpp		\
+  nix/boost/enable_shared_from_this.hpp
+
+libformat_a_CPPFLAGS =				\
+  -I$(top_srcdir)/nix
+
+libutil_a_SOURCES =				\
+  nix/libutil/archive.cc			\
+  nix/libutil/serialise.cc			\
+  nix/libutil/immutable.cc			\
+  nix/libutil/util.cc				\
+  nix/libutil/xml-writer.cc			\
+  nix/libutil/hash.cc				\
+  nix/libutil/gcrypt-hash.cc
+
+libutil_headers =				\
+  nix/libutil/immutable.hh			\
+  nix/libutil/hash.hh				\
+  nix/libutil/serialise.hh			\
+  nix/libutil/xml-writer.hh			\
+  nix/libutil/util.hh				\
+  nix/libutil/archive.hh			\
+  nix/libutil/types.hh				\
+  nix/libutil/gcrypt-hash.hh			\
+  nix/libutil/md5.h				\
+  nix/libutil/sha1.h				\
+  nix/libutil/sha256.h
+
+libutil_a_CPPFLAGS =				\
+  -I$(top_builddir)/nix				\
+  -I$(top_srcdir)/nix/libutil			\
+  $(libformat_a_CPPFLAGS)
+
+libstore_a_SOURCES =				\
+  nix/libstore/gc.cc				\
+  nix/libstore/globals.cc			\
+  nix/libstore/misc.cc				\
+  nix/libstore/references.cc			\
+  nix/libstore/store-api.cc			\
+  nix/libstore/optimise-store.cc		\
+  nix/libstore/local-store.cc			\
+  nix/libstore/remote-store.cc			\
+  nix/libstore/build.cc				\
+  nix/libstore/pathlocks.cc			\
+  nix/libstore/derivations.cc
+
+libstore_headers =				\
+  nix/libstore/references.hh			\
+  nix/libstore/pathlocks.hh			\
+  nix/libstore/globals.hh			\
+  nix/libstore/schema.sql.hh			\
+  nix/libstore/worker-protocol.hh		\
+  nix/libstore/remote-store.hh			\
+  nix/libstore/derivations.hh			\
+  nix/libstore/misc.hh				\
+  nix/libstore/local-store.hh			\
+  nix/libstore/store-api.hh
+
+libstore_a_CPPFLAGS =				\
+  $(libutil_a_CPPFLAGS)				\
+  -I$(top_srcdir)/nix/libstore			\
+  -DNIX_STORE_DIR=\"$(storedir)\"		\
+  -DNIX_DATA_DIR=\"$(datadir)\"			\
+  -DNIX_STATE_DIR=\"$(localstatedir)/nix\"	\
+  -DNIX_LOG_DIR=\"$(localstatedir)/log/nix\"	\
+  -DNIX_CONF_DIR=\"$(sysconfdir)/nix\"		\
+  -DNIX_LIBEXEC_DIR=\"$(libexecdir)\"		\
+  -DNIX_BIN_DIR=\"$(bindir)\"			\
+  -DOPENSSL_PATH="\"openssl\""
+
+libstore_a_CFLAGS =				\
+  $(SQLITE3_CFLAGS) $(LIBGCRYPT_CFLAGS)
+
+bin_PROGRAMS = guix-daemon
+
+guix_daemon_SOURCES =				\
+  nix/nix-daemon/nix-daemon.cc			\
+  nix/nix-daemon/guix-daemon.cc
+
+guix_daemon_CPPFLAGS =				\
+  $(libutil_a_CPPFLAGS)				\
+  -I$(top_srcdir)/nix/libstore
+
+guix_daemon_LDADD =				\
+  libstore.a libutil.a libformat.a -lbz2	\
+  $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS)
+
+guix_daemon_headers =				\
+  nix/nix-daemon/shared.hh
+
+noinst_HEADERS =						\
+  $(libformat_headers) $(libutil_headers) $(libstore_headers)	\
+  $(guix_daemon_headers)
+
+nix/libstore/schema.sql.hh: nix/libstore/schema.sql
+	$(GUILE) --no-auto-compile -c				\
+	  "(use-modules (rnrs io ports))			\
+	   (call-with-output-file \"$@\"			\
+	     (lambda (out)					\
+	       (call-with-input-file \"$^\"			\
+	         (lambda (in)					\
+	           (write (get-string-all in) out)))))"
+
+nodist_pkglibexec_SCRIPTS =			\
+  nix/scripts/list-runtime-roots
+
+EXTRA_DIST +=					\
+  nix/sync-with-upstream			\
+  nix/libstore/schema.sql			\
+  nix/AUTHORS					\
+  nix/COPYING
+
+AM_TESTS_ENVIRONMENT +=				\
+  top_builddir="$(abs_top_builddir)"
+
+TESTS +=					\
+  tests/guix-daemon.sh
+
+clean-local:
+	-find "$(GUIX_TEST_ROOT)" | xargs chmod +w
+	-rm -rf "$(GUIX_TEST_ROOT)"
diff --git a/guix/config.scm.in b/guix/config.scm.in
index 462dcd0ed1..4717b1c967 100644
--- a/guix/config.scm.in
+++ b/guix/config.scm.in
@@ -20,6 +20,9 @@
   #:export (%guix-package-name
             %guix-version
             %guix-bug-report-address
+            %store-directory
+            %state-directory
+            %system
             %libgcrypt
             %nixpkgs
             %nix-instantiate))
@@ -39,6 +42,15 @@
 (define %guix-bug-report-address
   "@PACKAGE_BUGREPORT@")
 
+(define %store-directory
+  "@storedir@")
+
+(define %state-directory
+  "@guix_localstatedir@")
+
+(define %system
+  "@guix_system@")
+
 (define %libgcrypt
   "@LIBGCRYPT@")
 
diff --git a/guix/store.scm b/guix/store.scm
index 204364f319..a8dd566355 100644
--- a/guix/store.scm
+++ b/guix/store.scm
@@ -18,6 +18,7 @@
 
 (define-module (guix store)
   #:use-module (guix utils)
+  #:use-module (guix config)
   #:use-module (rnrs bytevectors)
   #:use-module (rnrs io ports)
   #:use-module (srfi srfi-1)
@@ -124,11 +125,9 @@
   (delete-dead 2)
   (delete-specific 3))
 
-(define %nix-state-dir
-  (or (getenv "NIX_STATE_DIR") "/nix/var/nix"))
-
 (define %default-socket-path
-  (string-append %nix-state-dir "/daemon-socket/socket"))
+  (string-append (or (getenv "NIX_STATE_DIR") %state-directory)
+                 "/daemon-socket/socket"))
 
 
 ;; serialize.cc
@@ -538,7 +537,7 @@ collected, and the number of bytes freed."
 (define %store-prefix
   ;; Absolute path to the Nix store.
   (make-parameter (or (and=> (getenv "NIX_STORE_DIR") canonicalize-path)
-                      "/nix/store")))
+                      %store-directory)))
 
 (define (store-path? path)
   "Return #t if PATH is a store path."
diff --git a/guix/utils.scm b/guix/utils.scm
index 453b3843dd..ad50c20cce 100644
--- a/guix/utils.scm
+++ b/guix/utils.scm
@@ -350,7 +350,8 @@ returned by `config.guess'."
 
 (define %current-system
   ;; System type as expected by Nix, usually ARCHITECTURE-KERNEL.
-  (make-parameter (gnu-triplet->nix-system %host-type)))
+  ;; By default, this is equal to (gnu-triplet->nix-system %host-type).
+  (make-parameter %system))
 
 (define (package-name->name+version name)
   "Given NAME, a package name like \"foo-0.9.1b\", return two values:
diff --git a/m4/guix.m4 b/m4/guix.m4
index 29f928f653..7d7d7381a0 100644
--- a/m4/guix.m4
+++ b/m4/guix.m4
@@ -33,3 +33,33 @@ AC_DEFUN([GUIX_ASSERT_LIBGCRYPT_USABLE],
    if test "x$guix_cv_libgcrypt_usable_p" != "xyes"; then
      AC_MSG_ERROR([GNU libgcrypt does not appear to be usable; see `--with-libgcrypt-prefix' and `README'.])
    fi])
+
+dnl GUIX_SYSTEM_TYPE
+dnl
+dnl Determine the Guix host system type, and store it in the
+dnl `guix_system' variable.
+AC_DEFUN([GUIX_SYSTEM_TYPE], [
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_ARG_WITH(system, AC_HELP_STRING([--with-system=SYSTEM],
+    [Platform identifier (e.g., `i686-linux').]),
+    [guix_system="$withval"],
+    [case "$host_cpu" in
+       i*86)
+	  machine_name="i686";;
+       amd64)
+	  machine_name="x86_64";;
+       *)
+	  machine_name="$host_cpu";;
+     esac
+
+     case "$host_os" in
+       linux-gnu*)
+	  # For backward compatibility, strip the `-gnu' part.
+	  guix_system="$machine_name-linux";;
+       *)
+	  # Strip the version number from names such as `gnu0.3',
+	  # `darwin10.2.0', etc.
+	  guix_system="$machine_name-`echo $host_os | "$SED" -e's/@<:@0-9.@:>@*$//g'`";;
+     esac])
+  AC_SUBST([guix_system])
+])
diff --git a/nix-upstream b/nix-upstream
new file mode 160000
+Subproject e087bfef5f36f309b1c8d01bfe297e4cf4decb3
diff --git a/nix/.gitignore b/nix/.gitignore
new file mode 100644
index 0000000000..92d0520cc7
--- /dev/null
+++ b/nix/.gitignore
@@ -0,0 +1,4 @@
+*.a
+*.o
+.deps
+.dirstamp
diff --git a/nix/boost/.gitignore b/nix/boost/.gitignore
new file mode 100644
index 0000000000..1f188e3b65
--- /dev/null
+++ b/nix/boost/.gitignore
@@ -0,0 +1,3 @@
+*.hpp
+*.cpp
+*.cc
diff --git a/nix/libstore/.gitignore b/nix/libstore/.gitignore
new file mode 100644
index 0000000000..512a0d022f
--- /dev/null
+++ b/nix/libstore/.gitignore
@@ -0,0 +1,3 @@
+*.cc
+*.hh
+/schema.sql
diff --git a/nix/libutil/.gitignore b/nix/libutil/.gitignore
new file mode 100644
index 0000000000..e539428b1b
--- /dev/null
+++ b/nix/libutil/.gitignore
@@ -0,0 +1,2 @@
+*.cc
+*.hh
diff --git a/nix/libutil/gcrypt-hash.cc b/nix/libutil/gcrypt-hash.cc
new file mode 100644
index 0000000000..de7e5afc1a
--- /dev/null
+++ b/nix/libutil/gcrypt-hash.cc
@@ -0,0 +1,50 @@
+/* Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+   Copyright (C) 2012  Ludovic Courtès <ludo@gnu.org>
+
+   This file is part of Guix.
+
+   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.
+
+   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 Guix.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <gcrypt-hash.hh>
+#include <assert.h>
+
+extern "C" {
+
+void
+guix_hash_init (struct guix_hash_context *ctx, gcry_md_algo_t algo)
+{
+  gcry_error_t err;
+
+  err = gcry_md_open (&ctx->md_handle, algo, 0);
+  assert (err == GPG_ERR_NO_ERROR);
+}
+
+void
+guix_hash_update (struct guix_hash_context *ctx, const void *buffer, size_t len)
+{
+  gcry_md_write (ctx->md_handle, buffer, len);
+}
+
+void
+guix_hash_final (void *resbuf, struct guix_hash_context *ctx,
+		 gcry_md_algo_t algo)
+{
+  memcpy (resbuf, gcry_md_read (ctx->md_handle, algo),
+	  gcry_md_get_algo_dlen (algo));
+  gcry_md_close (ctx->md_handle);
+}
+
+}
diff --git a/nix/libutil/gcrypt-hash.hh b/nix/libutil/gcrypt-hash.hh
new file mode 100644
index 0000000000..1e26398540
--- /dev/null
+++ b/nix/libutil/gcrypt-hash.hh
@@ -0,0 +1,39 @@
+/* Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+   Copyright (C) 2012  Ludovic Courtès <ludo@gnu.org>
+
+   This file is part of Guix.
+
+   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.
+
+   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 Guix.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* An OpenSSL-like interface to GNU libgcrypt cryptographic hash
+   functions.  */
+
+#pragma once
+#include <gcrypt.h>
+#include <unistd.h>
+
+extern "C" {
+
+struct guix_hash_context
+{
+  gcry_md_hd_t md_handle;
+};
+
+extern void guix_hash_init (struct guix_hash_context *ctx, gcry_md_algo_t algo);
+extern void guix_hash_update (struct guix_hash_context *ctx, const void *buffer,
+			      size_t len);
+extern void guix_hash_final (void *resbuf, struct guix_hash_context *ctx,
+			     gcry_md_algo_t algo);
+
+}
diff --git a/nix/libutil/md5.h b/nix/libutil/md5.h
new file mode 100644
index 0000000000..7fa29087d7
--- /dev/null
+++ b/nix/libutil/md5.h
@@ -0,0 +1,35 @@
+/* Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+   Copyright (C) 2012  Ludovic Courtès <ludo@gnu.org>
+
+   This file is part of Guix.
+
+   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.
+
+   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 Guix.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <gcrypt-hash.hh>
+
+#define MD5_CTX guix_hash_context
+
+static inline void
+MD5_Init (struct MD5_CTX *ctx)
+{
+  guix_hash_init (ctx, GCRY_MD_MD5);
+}
+
+#define MD5_Update guix_hash_update
+
+static inline void
+MD5_Final (void *resbuf, struct MD5_CTX *ctx)
+{
+  guix_hash_final (resbuf, ctx, GCRY_MD_MD5);
+}
diff --git a/nix/libutil/sha1.h b/nix/libutil/sha1.h
new file mode 100644
index 0000000000..0eca8e310d
--- /dev/null
+++ b/nix/libutil/sha1.h
@@ -0,0 +1,35 @@
+/* Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+   Copyright (C) 2012  Ludovic Courtès <ludo@gnu.org>
+
+   This file is part of Guix.
+
+   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.
+
+   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 Guix.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <gcrypt-hash.hh>
+
+#define SHA_CTX guix_hash_context
+
+static inline void
+SHA1_Init (struct SHA_CTX *ctx)
+{
+  guix_hash_init (ctx, GCRY_MD_SHA1);
+}
+
+#define SHA1_Update guix_hash_update
+
+static inline void
+SHA1_Final (void *resbuf, struct SHA_CTX *ctx)
+{
+  guix_hash_final (resbuf, ctx, GCRY_MD_SHA1);
+}
diff --git a/nix/libutil/sha256.h b/nix/libutil/sha256.h
new file mode 100644
index 0000000000..a91f18f689
--- /dev/null
+++ b/nix/libutil/sha256.h
@@ -0,0 +1,35 @@
+/* Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+   Copyright (C) 2012  Ludovic Courtès <ludo@gnu.org>
+
+   This file is part of Guix.
+
+   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.
+
+   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 Guix.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <gcrypt-hash.hh>
+
+#define SHA256_CTX guix_hash_context
+
+static inline void
+SHA256_Init (struct SHA256_CTX *ctx)
+{
+  guix_hash_init (ctx, GCRY_MD_SHA256);
+}
+
+#define SHA256_Update guix_hash_update
+
+static inline void
+SHA256_Final (void *resbuf, struct SHA256_CTX *ctx)
+{
+  guix_hash_final (resbuf, ctx, GCRY_MD_SHA256);
+}
diff --git a/nix/nix-daemon/guix-daemon.cc b/nix/nix-daemon/guix-daemon.cc
new file mode 100644
index 0000000000..6bbea52196
--- /dev/null
+++ b/nix/nix-daemon/guix-daemon.cc
@@ -0,0 +1,159 @@
+/* Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+   Copyright (C) 2012  Ludovic Courtès <ludo@gnu.org>
+
+   This file is part of Guix.
+
+   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.
+
+   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 Guix.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <types.hh>
+#include "shared.hh"
+#include <globals.hh>
+
+#include <stdlib.h>
+#include <argp.h>
+
+/* Variables used by `nix-daemon.cc'.  */
+volatile ::sig_atomic_t blockInt;
+char **argvSaved;
+
+using namespace nix;
+
+/* Entry point in `nix-daemon.cc'.  */
+extern void run (Strings args);
+
+
+/* Command-line options.  */
+
+const char *argp_program_version =
+  "guix-daemon (" PACKAGE_NAME ") " PACKAGE_VERSION;
+const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+
+static char doc[] =
+"guix-daemon -- perform derivation builds and store accesses\
+\v\
+This program is a daemon meant to run in the background.  It serves \
+requests sent over a Unix-domain socket.  It accesses the store, and \
+builds derivations on behalf of its clients.";
+
+#define GUIX_OPT_SYSTEM 1
+#define GUIX_OPT_DISABLE_CHROOT 2
+#define GUIX_OPT_BUILD_USERS_GROUP 3
+#define GUIX_OPT_CACHE_FAILURES 4
+#define GUIX_OPT_LOSE_LOGS 5
+#define GUIX_OPT_DISABLE_LOG_COMPRESSION 6
+#define GUIX_OPT_DISABLE_STORE_OPTIMIZATION 7
+#define GUIX_OPT_IMPERSONATE_LINUX_26 8
+
+static const struct argp_option options[] =
+  {
+    { "system", GUIX_OPT_SYSTEM, "SYSTEM", 0,
+      "Assume SYSTEM as the current system type" },
+    { "build-cores", 'C', "N", 0,
+      "Use N CPU cores to build each derivation; 0 means as many as available" },
+    { "max-jobs", 'M', "N", 0,
+      "Allow at most N build jobs" },
+    { "disable-chroot", GUIX_OPT_DISABLE_CHROOT, 0, 0,
+      "Disable chroot builds"
+#ifndef HAVE_CHROOT
+      " (chroots are not supported in this configuration, so "
+      "this option has no effect)"
+#endif
+    },
+    { "build-users-group", GUIX_OPT_BUILD_USERS_GROUP, "GROUP", 0,
+      "Perform builds as a user of GROUP" },
+    { "cache-failures", GUIX_OPT_CACHE_FAILURES, 0, 0,
+      "Cache build failures" },
+    { "lose-logs", GUIX_OPT_LOSE_LOGS, 0, 0,
+      "Do not keep build logs" },
+    { "disable-log-compression", GUIX_OPT_DISABLE_LOG_COMPRESSION, 0, 0,
+      "Disable compression of the build logs" },
+    { "disable-store-optimization", GUIX_OPT_DISABLE_STORE_OPTIMIZATION, 0, 0,
+      "Disable automatic file \"deduplication\" in the store" },
+    { "impersonate-linux-2.6", GUIX_OPT_IMPERSONATE_LINUX_26, 0, 0,
+      "Impersonate Linux 2.6"
+#ifndef HAVE_SYS_PERSONALITY_H
+      " (this option has no effect in this configuration)"
+#endif
+    },
+    { 0, 0, 0, 0, 0 }
+  };
+
+/* Parse a single option. */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case GUIX_OPT_DISABLE_CHROOT:
+      settings.useChroot = false;
+      break;
+    case GUIX_OPT_DISABLE_LOG_COMPRESSION:
+      settings.compressLog = false;
+      break;
+    case GUIX_OPT_BUILD_USERS_GROUP:
+      settings.buildUsersGroup = arg;
+      break;
+    case GUIX_OPT_DISABLE_STORE_OPTIMIZATION:
+      settings.autoOptimiseStore = false;
+      break;
+    case GUIX_OPT_CACHE_FAILURES:
+      settings.cacheFailure = true;
+      break;
+    case GUIX_OPT_IMPERSONATE_LINUX_26:
+      settings.impersonateLinux26 = true;
+      break;
+    case GUIX_OPT_LOSE_LOGS:
+      settings.keepLog = false;
+      break;
+    case 'C':
+      settings.buildCores = atoi (arg);
+      break;
+    case 'M':
+      settings.maxBuildJobs = atoi (arg);
+      break;
+    case GUIX_OPT_SYSTEM:
+      settings.thisSystem = arg;
+      break;
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+
+  return 0;
+}
+
+/* Argument parsing.  */
+static struct argp argp = { options, parse_opt, 0, doc };
+
+
+
+int
+main (int argc, char *argv[])
+{
+  Strings nothing;
+
+#ifdef HAVE_CHROOT
+  settings.useChroot = true;
+#else
+  settings.useChroot = false;
+#endif
+
+  settings.processEnvironment ();
+
+  argp_parse (&argp, argc, argv, 0, 0, 0);
+
+  argvSaved = argv;
+  run (nothing);
+}
diff --git a/nix/nix-daemon/shared.hh b/nix/nix-daemon/shared.hh
new file mode 100644
index 0000000000..a03c09c036
--- /dev/null
+++ b/nix/nix-daemon/shared.hh
@@ -0,0 +1,37 @@
+/* Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+   Copyright (C) 2012  Ludovic Courtès <ludo@gnu.org>
+
+   This file is part of Guix.
+
+   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.
+
+   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 Guix.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Replacement for Nix's libmain/shared.hh.  */
+
+#pragma once
+
+#include <string>
+
+#include <stdlib.h>
+#include <signal.h>
+
+static inline void
+showManPage (const char *name)
+{
+  /* This idea is evil.  Abort.  */
+  abort ();
+}
+
+extern volatile ::sig_atomic_t blockInt;
+
+extern char **argvSaved;
diff --git a/nix/scripts/list-runtime-roots.in b/nix/scripts/list-runtime-roots.in
new file mode 100644
index 0000000000..5c21ae543d
--- /dev/null
+++ b/nix/scripts/list-runtime-roots.in
@@ -0,0 +1,116 @@
+#!@GUILE@ -ds
+!#
+;;; Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+;;; Copyright (C) 2012 Ludovic Courtès <ludo@gnu.org>
+;;;
+;;; This file is part of Guix.
+;;;
+;;; 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.
+;;;
+;;; 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 Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+;;;
+;;; List files being used at run time; these files are garbage collector
+;;; roots.  This is equivalent to `find-runtime-roots.pl' in Nix.
+;;;
+
+(use-modules (ice-9 ftw)
+             (ice-9 regex)
+             (ice-9 rdelim)
+             (ice-9 popen)
+             (srfi srfi-1)
+             (srfi srfi-26))
+
+(define %proc-directory
+  ;; Mount point of Linuxish /proc file system.
+  "/proc")
+
+(define (proc-file-roots dir file)
+  "Return a one-element list containing the file pointed to by DIR/FILE,
+or the empty list."
+  (or (and=> (false-if-exception (readlink (string-append dir "/" file)))
+             list)
+      '()))
+
+(define proc-exe-roots (cut proc-file-roots <> "exe"))
+(define proc-cwd-roots (cut proc-file-roots <> "cwd"))
+
+(define (proc-fd-roots dir)
+  "Return the list of store files referenced by DIR, which is a
+/proc/XYZ directory."
+  (let ((dir (string-append dir "/fd")))
+    (filter-map (lambda (file)
+                  (let ((target (false-if-exception
+                                 (readlink (string-append dir "/" file)))))
+                    (and target
+                         (string-prefix? "/" target)
+                         target)))
+                (scandir dir string->number))))
+
+(define (proc-maps-roots dir)
+  "Return the list of store files referenced by DIR, which is a
+/proc/XYZ directory."
+  (define %file-mapping-line
+    (make-regexp "^.*[[:blank:]]+/([^ ]+)$"))
+
+  (call-with-input-file (string-append dir "/maps")
+    (lambda (maps)
+      (let loop ((line  (read-line maps))
+                 (roots '()))
+        (cond ((eof-object? line)
+               roots)
+              ((regexp-exec %file-mapping-line line)
+               =>
+               (lambda (match)
+                 (let ((file (string-append "/"
+                                            (match:substring match 1))))
+                   (loop (read-line maps)
+                         (cons file roots)))))
+              (else
+               (loop (read-line maps) roots)))))))
+
+(define (lsof-roots)
+  "Return the list of roots as found by calling `lsof'."
+  (catch 'system
+    (lambda ()
+      (let ((pipe (open-pipe* OPEN_READ "lsof" "-n" "-w" "-F" "n")))
+        (define %file-rx
+          (make-regexp "^n/(.*)$"))
+
+        (let loop ((line  (read-line pipe))
+                   (roots '()))
+          (cond ((eof-object? line)
+                 (begin
+                   (close-pipe pipe)
+                   roots))
+                ((regexp-exec %file-rx line)
+                 =>
+                 (lambda (match)
+                   (loop (read-line pipe)
+                         (cons (string-append "/"
+                                              (match:substring match 1))
+                               roots))))
+                (else
+                 (loop (read-line pipe) roots))))))
+    (lambda _
+      '())))
+
+(let ((proc (format #f "~a/~a" %proc-directory (getpid))))
+  (for-each (cut simple-format #t "~a~%" <>)
+            (delete-duplicates
+             (let ((proc-roots (if (file-exists? proc)
+                                   (append (proc-exe-roots proc)
+                                           (proc-cwd-roots proc)
+                                           (proc-fd-roots proc)
+                                           (proc-maps-roots proc))
+                                   '())))
+               (append proc-roots (lsof-roots))))))
diff --git a/nix/sync-with-upstream b/nix/sync-with-upstream
new file mode 100755
index 0000000000..69bd1fbee7
--- /dev/null
+++ b/nix/sync-with-upstream
@@ -0,0 +1,68 @@
+#!/bin/sh
+# Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+# Copyright (C) 2012 Ludovic Courtès <ludo@gnu.org>
+#
+# This file is part of Guix.
+#
+# 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.
+#
+# 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 Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+#
+# Update the local copy of Nix source code needed to build the daemon.
+# Assume GNU Coreutils and Git are available.
+#
+
+top_srcdir="${top_srcdir:-..}"
+
+log()
+{
+    echo "sync-with-upstream: $@" >&2
+}
+
+# checked_in_p FILE
+checked_in_p()
+{
+    ( cd "$top_srcdir" ;
+	git ls-tree HEAD -- "nix/$1" | grep "$1" > /dev/null )
+}
+
+if [ ! -d "$top_srcdir/build-aux" ]
+then
+    log "\`$top_srcdir' is not the valid top-level source directory"
+    exit 1
+fi
+
+set -e
+for upstream_file in `cd "$top_srcdir/nix-upstream/src" ;
+  find . -name \*.c -or -name \*.h -or -name \*.cc -or -name \*.hh \
+         -or -name \*.cpp -or -name \*.hpp -or -name \*.sql`
+do
+    if grep "$upstream_file" "$top_srcdir/daemon.am" > /dev/null
+    then
+    	if checked_in_p "$upstream_file"
+    	then
+    	    log "skipping \`$upstream_file', which has a checked-in copy"
+    	else
+    	    ( cd "$top_srcdir/nix-upstream/src" && \
+    		cp -v --parents "$upstream_file" ../../nix )
+    	fi
+    else
+    	log "skipping \`$upstream_file', which is not used"
+    fi
+done
+
+cp -v "$top_srcdir/nix-upstream/"{COPYING,AUTHORS} "$top_srcdir/nix"
+
+# Substitutions.
+sed -i "$top_srcdir/nix/libstore/gc.cc"					\
+    -e 's|/nix/find-runtime-roots\.pl|/guix/list-runtime-roots|g'
diff --git a/release.nix b/release.nix
index 1b913b497b..2d3a70f524 100644
--- a/release.nix
+++ b/release.nix
@@ -48,11 +48,12 @@ let
       pkgs.releaseTools.sourceTarball {
         name = "guix-tarball";
         src = <guix>;
-        buildInputs = with pkgs; [ guile ];
+        buildInputs = with pkgs; [ guile sqlite bzip2 git libgcrypt ];
         buildNativeInputs = with pkgs; [ texinfo gettext cvs pkgconfig ];
+        preAutoconf = ''git config submodule.gnulib.url "${<gnulib>}"'';
         configureFlags =
-          [ "--with-nix-prefix=${pkgs.nix}"
-            "--with-libgcrypt-prefix=${pkgs.libgcrypt}"
+          [ "--with-libgcrypt-prefix=${pkgs.libgcrypt}"
+            "--localstatedir=/nix/var/nix"
           ];
       };
 
@@ -62,12 +63,12 @@ let
       let pkgs = import nixpkgs { inherit system; }; in
       pkgs.releaseTools.nixBuild {
         name = "guix";
-        buildInputs = [ pkgs.guile ];
+        buildInputs = with pkgs; [ guile sqlite bzip2 libgcrypt ];
         buildNativeInputs = [ pkgs.pkgconfig ];
         src = jobs.tarball;
         configureFlags =
-          [ "--with-nix-prefix=${pkgs.nix}"
-            "--with-libgcrypt-prefix=${pkgs.libgcrypt}"
+          [ "--with-libgcrypt-prefix=${pkgs.libgcrypt}"
+            "--localstatedir=/nix/var/nix"
           ];
 
         preBuild =
@@ -80,16 +81,28 @@ let
                distro/packages/bootstrap/x86_64-linux/guile-bootstrap-2.0.6.tar.xz
           '';
 
-        # XXX: Since we need to talk to a running daemon, for the benefit of
-        # `nixpkgs-derivation*' & co., we need to escape the chroot.
-        preConfigure = "export NIX_REMOTE=daemon";
-        __noChroot = true;
-
         inherit succeedOnFailure keepBuildDirectory
           buildOutOfSourceTree;
       };
 
 
+    build_disable_daemon =
+      { system ? builtins.currentSystem }:
+
+      let
+        pkgs = import nixpkgs { inherit system; };
+        build = jobs.build { inherit system; };
+      in
+        pkgs.lib.overrideDerivation build ({ configureFlags, ... }: {
+          configureFlags = configureFlags ++ [ "--disable-daemon" ];
+          buildInputs = with pkgs; [ guile nixUnstable pkgconfig ];
+
+          # Since we need to talk to a running daemon, we need to escape
+          # the chroot.
+          preConfigure = "export NIX_REMOTE=daemon";
+          __noChroot = true;
+        });
+
     # Jobs to test the distro.
     distro = {
       hello =
diff --git a/test-env.in b/test-env.in
new file mode 100644
index 0000000000..4e388053f9
--- /dev/null
+++ b/test-env.in
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+# Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+# Copyright (C) 2012 Ludovic Courtès <ludo@gnu.org>
+#
+# This file is part of Guix.
+#
+# 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.
+#
+# 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 Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+# Usage: ./test-env COMMAND ARG...
+#
+# Run the daemon in the build directory, and run COMMAND within
+# `pre-inst-env'.  This is used to run unit tests with the just-built
+# daemon, unless `--disable-daemon' was passed at configure time.
+
+if [ -x "@abs_top_builddir@/guix-daemon" ]
+then
+    NIX_SUBSTITUTERS=""		# don't resort to substituters
+    NIX_IGNORE_SYMLINK_STORE=1	# in case the store is a symlink
+    NIX_STORE_DIR="@GUIX_TEST_ROOT@/store"
+    NIX_LOCALSTATE_DIR="@GUIX_TEST_ROOT@/var"
+    NIX_LOG_DIR="@GUIX_TEST_ROOT@/var/log/nix"
+    NIX_DB_DIR="@GUIX_TEST_ROOT@/db"
+    NIX_ROOT_FINDER="@abs_top_builddir@/nix/scripts/list-runtime-roots"
+
+    # Choose a PID-dependent name to allow for parallel builds.  Note
+    # that the directory name must be chosen so that the socket's file
+    # name is less than 108-char long (the size of `sun_path' in glibc).
+    # Currently, in Nix builds, we're at ~106 chars...
+    NIX_STATE_DIR="@GUIX_TEST_ROOT@/var/$$" # allow for parallel tests
+
+    export NIX_SUBSTITUTERS NIX_IGNORE_SYMLINK_STORE NIX_STORE_DIR	\
+	NIX_LOCALSTATE_DIR NIX_LOG_DIR NIX_STATE_DIR NIX_DB_DIR		\
+	NIX_ROOT_FINDER
+
+    # Do that because store.scm calls `canonicalize-path' on it.
+    mkdir -p "$NIX_STORE_DIR"
+
+    # Launch the daemon without chroot support because is may be
+    # unavailable, for instance if we're not running as root.
+    "@abs_top_builddir@/guix-daemon" --disable-chroot &
+
+    daemon_pid=$!
+    trap "kill $daemon_pid ; rm -rf $NIX_STATE_DIR" EXIT
+fi
+
+"@abs_top_builddir@/pre-inst-env" "$@"
+exit $?
diff --git a/tests/base32.scm b/tests/base32.scm
index b8b9ebb0dd..d1bbaa1764 100644
--- a/tests/base32.scm
+++ b/tests/base32.scm
@@ -23,15 +23,24 @@
   #:use-module (srfi srfi-64)
   #:use-module (ice-9 rdelim)
   #:use-module (ice-9 popen)
+  #:use-module (ice-9 match)
   #:use-module (rnrs bytevectors)
   #:use-module (rnrs io ports))
 
 ;; Test the (guix base32) module.
 
 (define %nix-hash
-  (or (getenv "NIX_HASH")
+  (or (and=> (getenv "NIX_HASH")
+             (match-lambda
+              ("" #f)
+              (val val)))
       "nix-hash"))
 
+(define %have-nix-hash?
+  ;; Note: Use `system', not `system*', because of <http://bugs.gnu.org/13166>.
+  (false-if-exception
+   (zero? (system (string-append %nix-hash " --version")))))
+
 (test-begin "base32")
 
 (test-assert "bytevector->base32-string"
@@ -67,10 +76,9 @@
          ;; Examples from RFC 4648.
          (map string->utf8 '("" "f" "fo" "foo" "foob" "fooba" "foobar"))))
 
-;; The following tests requires `nix-hash' in $PATH.
-(test-skip (if (false-if-exception (system* %nix-hash "--version"))
-               0
-               1))
+;; The following test requires `nix-hash' in $PATH.
+(unless %have-nix-hash?
+  (test-skip 1))
 
 (test-assert "sha256 & bytevector->nix-base32-string"
   (let ((file (search-path %load-path "tests/test.drv")))
diff --git a/tests/builders.scm b/tests/builders.scm
index 12841d5690..6035032d5d 100644
--- a/tests/builders.scm
+++ b/tests/builders.scm
@@ -50,9 +50,13 @@
               (list name (package-derivation %store package))))
             (@@ (distro packages base) %boot0-inputs))))
 
+(define network-reachable?
+  (false-if-exception (getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)))
+
 
 (test-begin "builders")
 
+(unless network-reachable? (test-skip 1))
 (test-assert "url-fetch"
   (let* ((url      '("http://ftp.gnu.org/gnu/hello/hello-2.8.tar.gz"
                      "ftp://ftp.gnu.org/gnu/hello/hello-2.8.tar.gz"))
@@ -69,6 +73,7 @@
   (and (build-system? gnu-build-system)
        (eq? gnu-build (build-system-builder gnu-build-system))))
 
+(unless network-reachable? (test-skip 1))
 (test-assert "gnu-build"
   (let* ((url      "http://ftp.gnu.org/gnu/hello/hello-2.8.tar.gz")
          (hash     (nix-base32-string->bytevector
diff --git a/tests/derivations.scm b/tests/derivations.scm
index 14e1863a12..46bab4e19d 100644
--- a/tests/derivations.scm
+++ b/tests/derivations.scm
@@ -76,7 +76,7 @@
     (and (equal? b1 b2)
          (equal? d1 d2))))
 
-(test-skip (if %store 0 4))
+(test-skip (if %store 0 11))
 
 (test-assert "add-to-store, flat"
   (let* ((file (search-path %load-path "language/tree-il/spec.scm"))
@@ -290,8 +290,9 @@
 
 (define %coreutils
   (false-if-exception
-   (or (package-derivation %store %bootstrap-coreutils&co)
-       (nixpkgs-derivation "coreutils"))))
+   (and (getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)
+        (or (package-derivation %store %bootstrap-coreutils&co)
+            (nixpkgs-derivation "coreutils")))))
 
 (test-skip (if %coreutils 0 1))
 
@@ -385,6 +386,7 @@
            (and (equal? '(hello) (call-with-input-file one read))
                 (equal? '(world) (call-with-input-file two read)))))))
 
+(test-skip (if %coreutils 0 1))
 (test-assert "build-expression->derivation with one input"
   (let* ((builder    '(call-with-output-file %output
                         (lambda (p)
diff --git a/tests/guix-daemon.sh b/tests/guix-daemon.sh
new file mode 100644
index 0000000000..b942cbd546
--- /dev/null
+++ b/tests/guix-daemon.sh
@@ -0,0 +1,29 @@
+# Guix --- Nix package management from Guile.         -*- coding: utf-8 -*-
+# Copyright (C) 2012 Ludovic Courtès <ludo@gnu.org>
+#
+# This file is part of Guix.
+#
+# 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.
+#
+# 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 Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+#
+# Test the daemon.
+#
+
+set -e
+
+guix-daemon --version
+guix-build --version
+
+guix-build -e '(@ (distro packages bootstrap) %bootstrap-guile)'
+guix-build coreutils -n
diff --git a/tests/guix-package.sh b/tests/guix-package.sh
index 2a424cc3de..60a0394f1c 100644
--- a/tests/guix-package.sh
+++ b/tests/guix-package.sh
@@ -39,31 +39,35 @@ test -L "$profile" && test -L "$profile-1-link"
 ! test -f "$profile-2-link"
 test -f "$profile/bin/guile"
 
-guix-package -b -p "$profile"						\
-    -i `guix-build -e '(@@ (distro packages base) gnu-make-boot0)'`
-test -L "$profile-2-link"
-test -f "$profile/bin/make" && 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
+    guix-package -b -p "$profile"						\
+	-i `guix-build -e '(@@ (distro packages base) gnu-make-boot0)'`
+    test -L "$profile-2-link"
+    test -f "$profile/bin/make" && test -f "$profile/bin/guile"
 
 
-# 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`"
-case "x$installed" in
-    "guile-bootstrap make-boot0")
-	true;;
-    "make-boot0 guile-bootstrap")
-	true;;
-    "*")
-        false;;
-esac
+    # 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`"
+    case "x$installed" in
+	"guile-bootstrap make-boot0")
+	    true;;
+	"make-boot0 guile-bootstrap")
+	    true;;
+	"*")
+            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"
 
-# Remove a package.
-guix-package -b -p "$profile" -r "guile-bootstrap"
-test -L "$profile-3-link"
-test -f "$profile/bin/make" && ! test -f "$profile/bin/guile"
+    # Remove a package.
+    guix-package -b -p "$profile" -r "guile-bootstrap"
+    test -L "$profile-3-link"
+    test -f "$profile/bin/make" && ! test -f "$profile/bin/guile"
+fi
 
 # Make sure the `:' syntax works.
 guix-package -b -i "libsigsegv:lib" -n
diff --git a/tests/packages.scm b/tests/packages.scm
index c89f6e7721..5b0cd79b0f 100644
--- a/tests/packages.scm
+++ b/tests/packages.scm
@@ -125,6 +125,8 @@
          (let ((p (pk 'drv d (derivation-path->output-path d))))
            (eq? 'hello (call-with-input-file p read))))))
 
+(unless (false-if-exception (getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV))
+  (test-skip 1))
 (test-assert "GNU Make, bootstrap"
   ;; GNU Make is the first program built during bootstrap; we choose it
   ;; here so that the test doesn't last for too long.
diff --git a/tests/union.scm b/tests/union.scm
index 73b95c49b8..c839855ef4 100644
--- a/tests/union.scm
+++ b/tests/union.scm
@@ -64,7 +64,11 @@
                 (bin make)
                 (share (doc (make README))))))
 
-(test-skip (if %store 0 1))
+(test-skip (if (and %store
+                    (false-if-exception
+                     (getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)))
+               0
+               1))
 
 (test-assert "union-build"
   (let* ((inputs  (map (match-lambda
diff --git a/tests/utils.scm b/tests/utils.scm
index 0a6e8a0833..ba04e281eb 100644
--- a/tests/utils.scm
+++ b/tests/utils.scm
@@ -18,7 +18,7 @@
 
 (define-module (test-utils)
   #:use-module (guix utils)
-  #:use-module ((guix store) #:select (store-path-package-name))
+  #:use-module ((guix store) #:select (%store-prefix store-path-package-name))
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-11)
   #:use-module (srfi srfi-64)
@@ -127,7 +127,8 @@
 (test-equal "store-path-package-name"
   "bash-4.2-p24"
   (store-path-package-name
-   "/nix/store/qvs2rj2ia5vci3wsdb7qvydrmacig4pg-bash-4.2-p24"))
+   (string-append (%store-prefix)
+                  "/qvs2rj2ia5vci3wsdb7qvydrmacig4pg-bash-4.2-p24")))
 
 (test-end)