summary refs log tree commit diff
path: root/nix
diff options
context:
space:
mode:
Diffstat (limited to 'nix')
-rw-r--r--nix/libstore/build.cc80
-rw-r--r--nix/libstore/local-store.cc9
-rw-r--r--nix/libstore/pathlocks.cc6
-rw-r--r--nix/libutil/xml-writer.cc94
-rw-r--r--nix/libutil/xml-writer.hh69
-rw-r--r--nix/local.mk136
6 files changed, 145 insertions, 249 deletions
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index f9fd61adde..ae78e65199 100644
--- a/nix/libstore/build.cc
+++ b/nix/libstore/build.cc
@@ -1106,8 +1106,10 @@ void DerivationGoal::repairClosure()
 
     /* Get the output closure. */
     PathSet outputClosure;
-    foreach (DerivationOutputs::iterator, i, drv.outputs)
+    foreach (DerivationOutputs::iterator, i, drv.outputs) {
+        if (!wantOutput(i->first, wantedOutputs)) continue;
         computeFSClosure(worker.store, i->second.path, outputClosure);
+    }
 
     /* Filter out our own outputs (which we have already checked). */
     foreach (DerivationOutputs::iterator, i, drv.outputs)
@@ -1289,7 +1291,6 @@ void DerivationGoal::tryToBuild()
        now hold the locks on the output paths, no other process can
        build this derivation, so no further checks are necessary. */
     validPaths = checkPathValidity(true, buildMode == bmRepair);
-    assert(buildMode != bmCheck || validPaths.size() == drv.outputs.size());
     if (buildMode != bmCheck && validPaths.size() == drv.outputs.size()) {
         debug(format("skipping build of derivation `%1%', someone beat us to it") % drvPath);
         outputLocks.setDeletion(true);
@@ -1717,7 +1718,7 @@ void DerivationGoal::startBuilder()
 
     /* In a sandbox, for determinism, always use the same temporary
        directory. */
-    tmpDirInSandbox = useChroot ? "/tmp/guix-build-" + drvName + "-0" : tmpDir;
+    tmpDirInSandbox = useChroot ? canonPath("/tmp", true) + "/guix-build-" + drvName + "-0" : tmpDir;
 
     /* For convenience, set an environment pointing to the top build
        directory. */
@@ -2319,6 +2320,8 @@ void DerivationGoal::registerOutputs()
        outputs to allow hard links between outputs. */
     InodesSeen inodesSeen;
 
+    Path checkSuffix = "-check";
+
     /* Check whether the output paths were created, and grep each
        output path to determine what other paths it references.  Also make all
        output paths read-only. */
@@ -2344,7 +2347,7 @@ void DerivationGoal::registerOutputs()
                 && redirectedBadOutputs.find(path) != redirectedBadOutputs.end()
                 && pathExists(redirected))
                 replaceValidPath(path, redirected);
-            if (buildMode == bmCheck)
+            if (buildMode == bmCheck && redirected != "")
                 actualPath = redirected;
         }
 
@@ -2428,9 +2431,20 @@ void DerivationGoal::registerOutputs()
         PathSet references = scanForReferences(actualPath, allPaths, hash);
 
         if (buildMode == bmCheck) {
+            if (!store->isValidPath(path)) continue;
             ValidPathInfo info = worker.store.queryPathInfo(path);
-            if (hash.first != info.hash)
-                throw Error(format("derivation `%1%' may not be deterministic: hash mismatch in output `%2%'") % drvPath % path);
+            if (hash.first != info.hash) {
+                if (settings.keepFailed) {
+                    Path dst = path + checkSuffix;
+                    if (pathExists(dst)) deletePath(dst);
+                    if (rename(actualPath.c_str(), dst.c_str()))
+                        throw SysError(format("renaming `%1%' to `%2%'") % actualPath % dst);
+                    throw Error(format("derivation `%1%' may not be deterministic: output `%2%' differs from ‘%3%’")
+                        % drvPath % path % dst);
+                } else
+                    throw Error(format("derivation `%1%' may not be deterministic: output `%2%' differs")
+                        % drvPath % path);
+            }
             continue;
         }
 
@@ -2475,9 +2489,11 @@ void DerivationGoal::registerOutputs()
         checkRefs("disallowedReferences", false, false);
         checkRefs("disallowedRequisites", false, true);
 
-        worker.store.optimisePath(path); // FIXME: combine with scanForReferences()
+        if (curRound == nrRounds) {
+            worker.store.optimisePath(path); // FIXME: combine with scanForReferences()
 
-        worker.store.markContentsGood(path);
+            worker.store.markContentsGood(path);
+        }
 
         ValidPathInfo info;
         info.path = path;
@@ -2490,10 +2506,37 @@ void DerivationGoal::registerOutputs()
 
     if (buildMode == bmCheck) return;
 
-    if (curRound > 1 && prevInfos != infos)
-        throw NotDeterministic(
-            format("result of ‘%1%’ differs from previous round; rejecting as non-deterministic")
-            % drvPath);
+    /* Compare the result with the previous round, and report which
+       path is different, if any.*/
+    if (curRound > 1 && prevInfos != infos) {
+        assert(prevInfos.size() == infos.size());
+        for (auto i = prevInfos.begin(), j = infos.begin(); i != prevInfos.end(); ++i, ++j)
+            if (!(*i == *j)) {
+                Path prev = i->path + checkSuffix;
+                if (pathExists(prev))
+                    throw NotDeterministic(
+                        format("output ‘%1%’ of ‘%2%’ differs from ‘%3%’ from previous round")
+                        % i->path % drvPath % prev);
+                else
+                    throw NotDeterministic(
+                        format("output ‘%1%’ of ‘%2%’ differs from previous round")
+                        % i->path % drvPath);
+            }
+        assert(false); // shouldn't happen
+    }
+
+    if (settings.keepFailed) {
+        for (auto & i : drv.outputs) {
+            Path prev = i.second.path + checkSuffix;
+            if (pathExists(prev)) deletePath(prev);
+            if (curRound < nrRounds) {
+                Path dst = i.second.path + checkSuffix;
+                if (rename(i.second.path.c_str(), dst.c_str()))
+                    throw SysError(format("renaming ‘%1%’ to ‘%2%’") % i.second.path % dst);
+            }
+        }
+
+    }
 
     if (curRound < nrRounds) {
         prevInfos = infos;
@@ -3480,8 +3523,17 @@ void LocalStore::repairPath(const Path & path)
 
     worker.run(goals);
 
-    if (goal->getExitCode() != Goal::ecSuccess)
-        throw Error(format("cannot repair path `%1%'") % path, worker.exitStatus());
+    if (goal->getExitCode() != Goal::ecSuccess) {
+        /* Since substituting the path didn't work, if we have a valid
+           deriver, then rebuild the deriver. */
+        Path deriver = queryDeriver(path);
+        if (deriver != "" && isValidPath(deriver)) {
+            goals.clear();
+            goals.insert(worker.makeDerivationGoal(deriver, StringSet(), bmRepair));
+            worker.run(goals);
+        } else
+            throw Error(format("cannot repair path `%1%'") % path, worker.exitStatus());
+    }
 }
 
 
diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc
index 11f61ae030..347e8a703f 100644
--- a/nix/libstore/local-store.cc
+++ b/nix/libstore/local-store.cc
@@ -606,10 +606,10 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
        users group); we check for this case below. */
     if (st.st_uid != geteuid()) {
 #if HAVE_LCHOWN
-        if (lchown(path.c_str(), geteuid(), (gid_t) -1) == -1)
+        if (lchown(path.c_str(), geteuid(), getegid()) == -1)
 #else
         if (!S_ISLNK(st.st_mode) &&
-            chown(path.c_str(), geteuid(), (gid_t) -1) == -1)
+            chown(path.c_str(), geteuid(), getegid()) == -1)
 #endif
             throw SysError(format("changing owner of `%1%' to %2%")
                 % path % geteuid());
@@ -1213,6 +1213,9 @@ template<class T> T LocalStore::getIntLineFromSubstituter(RunningSubstituter & r
 PathSet LocalStore::querySubstitutablePaths(const PathSet & paths)
 {
     PathSet res;
+
+    if (!settings.useSubstitutes) return res;
+
     foreach (Paths::iterator, i, settings.substituters) {
         if (res.size() == paths.size()) break;
         RunningSubstituter & run(runningSubstituters[*i]);
@@ -1239,6 +1242,8 @@ PathSet LocalStore::querySubstitutablePaths(const PathSet & paths)
 void LocalStore::querySubstitutablePathInfos(const Path & substituter,
     PathSet & paths, SubstitutablePathInfos & infos)
 {
+    if (!settings.useSubstitutes) return;
+
     RunningSubstituter & run(runningSubstituters[substituter]);
     startSubstituter(substituter, run);
     if (run.disabled) return;
diff --git a/nix/libstore/pathlocks.cc b/nix/libstore/pathlocks.cc
index 830858ff8d..9797ddd7ab 100644
--- a/nix/libstore/pathlocks.cc
+++ b/nix/libstore/pathlocks.cc
@@ -162,7 +162,11 @@ bool PathLocks::lockPaths(const PathSet & _paths,
 
 PathLocks::~PathLocks()
 {
-    unlock();
+    try {
+        unlock();
+    } catch (...) {
+        ignoreException();
+    }
 }
 
 
diff --git a/nix/libutil/xml-writer.cc b/nix/libutil/xml-writer.cc
deleted file mode 100644
index 01794001b2..0000000000
--- a/nix/libutil/xml-writer.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-#include <assert.h>
-
-#include "xml-writer.hh"
-
-
-namespace nix {
-    
-
-XMLWriter::XMLWriter(bool indent, std::ostream & output)
-    : output(output), indent(indent)
-{
-    output << "<?xml version='1.0' encoding='utf-8'?>" << std::endl;
-    closed = false;
-}
-
-
-XMLWriter::~XMLWriter()
-{
-    close();
-}
-
-
-void XMLWriter::close()
-{
-    if (closed) return;
-    while (!pendingElems.empty()) closeElement();
-    closed = true;
-}
-
-
-void XMLWriter::indent_(unsigned int depth)
-{
-    if (!indent) return;
-    output << string(depth * 2, ' ');
-}
-
-
-void XMLWriter::openElement(const string & name,
-    const XMLAttrs & attrs)
-{
-    assert(!closed);
-    indent_(pendingElems.size());
-    output << "<" << name;
-    writeAttrs(attrs);
-    output << ">";
-    if (indent) output << std::endl;
-    pendingElems.push_back(name);
-}
-
-
-void XMLWriter::closeElement()
-{
-    assert(!pendingElems.empty());
-    indent_(pendingElems.size() - 1);
-    output << "</" << pendingElems.back() << ">";
-    if (indent) output << std::endl;
-    pendingElems.pop_back();
-    if (pendingElems.empty()) closed = true;
-}
-
-
-void XMLWriter::writeEmptyElement(const string & name,
-    const XMLAttrs & attrs)
-{
-    assert(!closed);
-    indent_(pendingElems.size());
-    output << "<" << name;
-    writeAttrs(attrs);
-    output << " />";
-    if (indent) output << std::endl;
-}
-
-
-void XMLWriter::writeAttrs(const XMLAttrs & attrs)
-{
-    for (XMLAttrs::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
-        output << " " << i->first << "=\"";
-        for (unsigned int j = 0; j < i->second.size(); ++j) {
-            char c = i->second[j];
-            if (c == '"') output << "&quot;";
-            else if (c == '<') output << "&lt;";
-            else if (c == '>') output << "&gt;";
-            else if (c == '&') output << "&amp;";
-            /* Escape newlines to prevent attribute normalisation (see
-               XML spec, section 3.3.3. */
-            else if (c == '\n') output << "&#xA;";
-            else output << c;
-        }
-        output << "\"";
-    }
-}
-
-
-}
diff --git a/nix/libutil/xml-writer.hh b/nix/libutil/xml-writer.hh
deleted file mode 100644
index 3cefe3712c..0000000000
--- a/nix/libutil/xml-writer.hh
+++ /dev/null
@@ -1,69 +0,0 @@
-#pragma once
-
-#include <iostream>
-#include <string>
-#include <list>
-#include <map>
-
-
-namespace nix {
-
-using std::string;
-using std::map;
-using std::list;
-
-
-typedef map<string, string> XMLAttrs;
-
-
-class XMLWriter
-{
-private:
-
-    std::ostream & output;
-
-    bool indent;
-    bool closed;
-
-    list<string> pendingElems;
-
-public:
-
-    XMLWriter(bool indent, std::ostream & output);
-    ~XMLWriter();
-
-    void close();
-
-    void openElement(const string & name,
-        const XMLAttrs & attrs = XMLAttrs());
-    void closeElement();
-
-    void writeEmptyElement(const string & name,
-        const XMLAttrs & attrs = XMLAttrs());
-
-private:
-    void writeAttrs(const XMLAttrs & attrs);
-
-    void indent_(unsigned int depth);
-};
-
-
-class XMLOpenElement
-{
-private:
-    XMLWriter & writer;
-public:
-    XMLOpenElement(XMLWriter & writer, const string & name,
-        const XMLAttrs & attrs = XMLAttrs())
-        : writer(writer)
-    {
-        writer.openElement(name, attrs);
-    }
-    ~XMLOpenElement()
-    {
-        writer.closeElement();
-    }
-};
-
-
-}
diff --git a/nix/local.mk b/nix/local.mk
index 3c15531f54..07a92f74ea 100644
--- a/nix/local.mk
+++ b/nix/local.mk
@@ -21,7 +21,7 @@
 # Integration of the `guix-daemon' code taken from upstream Nix.
 #
 
-BUILT_SOURCES += nix/libstore/schema.sql.hh
+BUILT_SOURCES += %D%/libstore/schema.sql.hh
 CLEANFILES += $(BUILT_SOURCES) etc/guix-daemon.service etc/guix-daemon.conf
 
 noinst_LIBRARIES = libformat.a libutil.a libstore.a
@@ -30,80 +30,78 @@ noinst_LIBRARIES = libformat.a libutil.a libstore.a
 AM_CXXFLAGS = -Wall -std=c++11
 
 libformat_a_SOURCES =				\
-  nix/boost/format/free_funcs.cc		\
-  nix/boost/format/parsing.cc			\
-  nix/boost/format/format_implementation.cc
+  %D%/boost/format/free_funcs.cc		\
+  %D%/boost/format/parsing.cc			\
+  %D%/boost/format/format_implementation.cc
 
 libformat_headers =				\
-  nix/boost/throw_exception.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
+  %D%/boost/throw_exception.hpp			\
+  %D%/boost/format.hpp				\
+  %D%/boost/assert.hpp				\
+  %D%/boost/format/macros_default.hpp		\
+  %D%/boost/format/format_fwd.hpp		\
+  %D%/boost/format/format_class.hpp		\
+  %D%/boost/format/exceptions.hpp		\
+  %D%/boost/format/group.hpp			\
+  %D%/boost/format/feed_args.hpp		\
+  %D%/boost/format/internals_fwd.hpp		\
+  %D%/boost/format/internals.hpp
 
 libformat_a_CPPFLAGS =				\
   -I$(top_srcdir)/nix
 
 libutil_a_SOURCES =				\
-  nix/libutil/archive.cc			\
-  nix/libutil/affinity.cc			\
-  nix/libutil/serialise.cc			\
-  nix/libutil/util.cc				\
-  nix/libutil/xml-writer.cc			\
-  nix/libutil/hash.cc				\
-  nix/libutil/gcrypt-hash.cc
+  %D%/libutil/archive.cc			\
+  %D%/libutil/affinity.cc			\
+  %D%/libutil/serialise.cc			\
+  %D%/libutil/util.cc				\
+  %D%/libutil/hash.cc				\
+  %D%/libutil/gcrypt-hash.cc
 
 libutil_headers =				\
-  nix/libutil/affinity.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				\
-  nix/libutil/sha512.h
+  %D%/libutil/affinity.hh			\
+  %D%/libutil/hash.hh				\
+  %D%/libutil/serialise.hh			\
+  %D%/libutil/util.hh				\
+  %D%/libutil/archive.hh			\
+  %D%/libutil/types.hh				\
+  %D%/libutil/gcrypt-hash.hh			\
+  %D%/libutil/md5.h				\
+  %D%/libutil/sha1.h				\
+  %D%/libutil/sha256.h				\
+  %D%/libutil/sha512.h
 
 libutil_a_CPPFLAGS =				\
   -I$(top_builddir)/nix				\
-  -I$(top_srcdir)/nix/libutil			\
+  -I$(top_srcdir)/%D%/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/build.cc				\
-  nix/libstore/pathlocks.cc			\
-  nix/libstore/derivations.cc
+  %D%/libstore/gc.cc				\
+  %D%/libstore/globals.cc			\
+  %D%/libstore/misc.cc				\
+  %D%/libstore/references.cc			\
+  %D%/libstore/store-api.cc			\
+  %D%/libstore/optimise-store.cc		\
+  %D%/libstore/local-store.cc			\
+  %D%/libstore/build.cc				\
+  %D%/libstore/pathlocks.cc			\
+  %D%/libstore/derivations.cc
 
 libstore_headers =				\
-  nix/libstore/references.hh			\
-  nix/libstore/pathlocks.hh			\
-  nix/libstore/globals.hh			\
-  nix/libstore/worker-protocol.hh		\
-  nix/libstore/derivations.hh			\
-  nix/libstore/misc.hh				\
-  nix/libstore/local-store.hh			\
-  nix/libstore/store-api.hh
+  %D%/libstore/references.hh			\
+  %D%/libstore/pathlocks.hh			\
+  %D%/libstore/globals.hh			\
+  %D%/libstore/worker-protocol.hh		\
+  %D%/libstore/derivations.hh			\
+  %D%/libstore/misc.hh				\
+  %D%/libstore/local-store.hh			\
+  %D%/libstore/store-api.hh
 
 libstore_a_CPPFLAGS =				\
   $(libutil_a_CPPFLAGS)				\
-  -I$(top_srcdir)/nix/libstore			\
-  -I$(top_builddir)/nix/libstore		\
+  -I$(top_srcdir)/%D%/libstore			\
+  -I$(top_builddir)/%D%/libstore		\
   -DNIX_STORE_DIR=\"$(storedir)\"		\
   -DNIX_DATA_DIR=\"$(datadir)\"			\
   -DNIX_STATE_DIR=\"$(localstatedir)/guix\"	\
@@ -121,29 +119,29 @@ bin_PROGRAMS = guix-daemon
 sbin_PROGRAMS = guix-register
 
 guix_daemon_SOURCES =				\
-  nix/nix-daemon/nix-daemon.cc			\
-  nix/nix-daemon/guix-daemon.cc
+  %D%/nix-daemon/nix-daemon.cc			\
+  %D%/nix-daemon/guix-daemon.cc
 
 guix_daemon_CPPFLAGS =				\
   -DLOCALEDIR=\"$(localedir)\"			\
   $(libutil_a_CPPFLAGS)				\
-  -I$(top_srcdir)/nix/libstore
+  -I$(top_srcdir)/%D%/libstore
 
 guix_daemon_LDADD =				\
   libstore.a libutil.a libformat.a -lbz2	\
   $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS)
 
 guix_daemon_headers =				\
-  nix/nix-daemon/shared.hh
+  %D%/nix-daemon/shared.hh
 
 
 guix_register_SOURCES =				\
-  nix/guix-register/guix-register.cc
+  %D%/guix-register/guix-register.cc
 
 guix_register_CPPFLAGS =			\
   $(libutil_a_CPPFLAGS)				\
   $(libstore_a_CPPFLAGS)			\
-  -I$(top_srcdir)/nix/libstore
+  -I$(top_srcdir)/%D%/libstore
 
 # XXX: Should we start using shared libs?
 guix_register_LDADD =				\
@@ -155,7 +153,7 @@ noinst_HEADERS =						\
   $(libformat_headers) $(libutil_headers) $(libstore_headers)	\
   $(guix_daemon_headers)
 
-nix/libstore/schema.sql.hh: nix/libstore/schema.sql
+%D%/libstore/schema.sql.hh: %D%/libstore/schema.sql
 	$(AM_V_GEN)$(GUILE) --no-auto-compile -c		\
 	  "(use-modules (rnrs io ports))			\
 	   (call-with-output-file \"$@\"			\
@@ -165,20 +163,20 @@ nix/libstore/schema.sql.hh: nix/libstore/schema.sql
 	           (write (get-string-all in) out)))))"
 
 nodist_pkglibexec_SCRIPTS =			\
-  nix/scripts/list-runtime-roots		\
-  nix/scripts/substitute
+  %D%/scripts/list-runtime-roots		\
+  %D%/scripts/substitute
 
 if BUILD_DAEMON_OFFLOAD
 
 nodist_pkglibexec_SCRIPTS +=			\
-  nix/scripts/offload
+  %D%/scripts/offload
 
 endif BUILD_DAEMON_OFFLOAD
 
 
 # XXX: It'd be better to hide it in $(pkglibexecdir).
 nodist_libexec_SCRIPTS =			\
-  nix/scripts/guix-authenticate
+  %D%/scripts/guix-authenticate
 
 # The '.service' file for systemd.
 systemdservicedir = $(libdir)/systemd/system
@@ -203,9 +201,9 @@ etc/guix-daemon.conf: etc/guix-daemon.conf.in	\
 	mv "$@.tmp" "$@"
 
 EXTRA_DIST +=					\
-  nix/libstore/schema.sql			\
-  nix/AUTHORS					\
-  nix/COPYING					\
+  %D%/libstore/schema.sql			\
+  %D%/AUTHORS					\
+  %D%/COPYING					\
   etc/guix-daemon.service.in	\
   etc/guix-daemon.conf.in