aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2020-09-16 17:50:40 +0000
committerJohn Ericson <John.Ericson@Obsidian.Systems>2020-09-16 17:50:40 +0000
commitc5ccebae0025649abfa1fef361ada7992df67c6a (patch)
treea265c1b6a7f0a45dea268e2538f24a45c22d5761 /src
parent98dfd7531d6df6abc925a446f390c4a5bbb9a51d (diff)
parent609a6d6d9f1a8689c2336301a2e4db01ad20037c (diff)
Merge remote-tracking branch 'upstream/master' into ca-floating-upstream
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/eval.cc3
-rw-r--r--src/libexpr/get-drvs.cc2
-rw-r--r--src/libexpr/primops.cc2
-rw-r--r--src/libstore/build.cc73
-rw-r--r--src/libstore/daemon.cc2
-rw-r--r--src/libstore/derivations.cc4
-rw-r--r--src/libstore/derivations.hh2
-rw-r--r--src/libstore/remote-store.cc44
-rw-r--r--src/libstore/remote-store.hh10
-rw-r--r--src/libstore/ssh-store.cc17
-rwxr-xr-xsrc/nix-build/nix-build.cc6
11 files changed, 104 insertions, 61 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 8c97b3760..d678231c6 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -87,6 +87,7 @@ static void printValue(std::ostream & str, std::set<const Value *> & active, con
else if (*i == '\n') str << "\\n";
else if (*i == '\r') str << "\\r";
else if (*i == '\t') str << "\\t";
+ else if (*i == '$' && *(i+1) == '{') str << "\\" << *i;
else str << *i;
str << "\"";
break;
@@ -1348,7 +1349,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
}
Value * actualArgs = allocValue();
- mkAttrs(*actualArgs, fun.lambda.fun->formals->formals.size());
+ mkAttrs(*actualArgs, std::max(static_cast<uint32_t>(fun.lambda.fun->formals->formals.size()), args.size()));
if (fun.lambda.fun->formals->ellipsis) {
// If the formals have an ellipsis (eg the function accepts extra args) pass
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index e66832182..91916e8bf 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -40,7 +40,7 @@ DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPat
throw Error("derivation '%s' does not have output '%s'", store->printStorePath(drvPath), outputName);
auto & [outputName, output] = *i;
- auto optStorePath = output.pathOpt(*store, drv.name, outputName);
+ auto optStorePath = output.path(*store, drv.name, outputName);
if (optStorePath)
outPath = store->printStorePath(*optStorePath);
}
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 78dc314fa..4a0dd5544 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -91,7 +91,7 @@ static void mkOutputString(EvalState & state, Value & v,
const StorePath & drvPath, const BasicDerivation & drv,
std::pair<string, DerivationOutput> o)
{
- auto optOutputPath = o.second.pathOpt(*state.store, drv.name, o.first);
+ auto optOutputPath = o.second.path(*state.store, drv.name, o.first);
mkString(
*state.allocAttr(v, state.symbols.create(o.first)),
optOutputPath
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index e50b23ed6..ee12f8e67 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -718,16 +718,25 @@ typedef enum {rpAccept, rpDecline, rpPostpone} HookReply;
class SubstitutionGoal;
+/* Unless we are repairing, we don't both to test validity and just assume it,
+ so the choices are `Absent` or `Valid`. */
+enum struct PathStatus {
+ Corrupt,
+ Absent,
+ Valid,
+};
+
struct InitialOutputStatus {
StorePath path;
- /* The output optional indicates whether it's already valid; i.e. exists
- and is registered. If we're repairing, inner bool indicates whether the
- valid path is in fact not corrupt. Otherwise, the inner bool is always
- true (assumed no corruption). */
- std::optional<bool> valid;
+ PathStatus status;
/* Valid in the store, and additionally non-corrupt if we are repairing */
bool isValid() const {
- return valid && *valid;
+ return status == PathStatus::Valid;
+ }
+ /* Merely present, allowed to be corrupt */
+ bool isPresent() const {
+ return status == PathStatus::Corrupt
+ || status == PathStatus::Valid;
}
};
@@ -2186,10 +2195,10 @@ void DerivationGoal::startBuilder()
: !needsHashRewrite()
/* Can always use original path in sandbox */
? status.known->path
- : !status.known->valid
+ : !status.known->isPresent()
/* If path doesn't yet exist can just use it */
? status.known->path
- : buildMode != bmRepair && !*status.known->valid
+ : buildMode != bmRepair && !status.known->isValid()
/* If we aren't repairing we'll delete a corrupted path, so we
can use original path */
? status.known->path
@@ -2199,7 +2208,7 @@ void DerivationGoal::startBuilder()
scratchOutputs.insert_or_assign(outputName, scratchPath);
/* A non-removed corrupted path needs to be stored here, too */
- if (buildMode == bmRepair && !*status.known->valid)
+ if (buildMode == bmRepair && !status.known->isValid())
redirectedBadOutputs.insert(status.known->path);
/* Substitute output placeholders with the scratch output paths.
@@ -4110,7 +4119,7 @@ void DerivationGoal::registerOutputs()
floating CA derivations and hash-mismatching fixed-output
derivations. */
PathLocks dynamicOutputLock;
- auto optFixedPath = output.pathOpt(worker.store, drv->name, outputName);
+ auto optFixedPath = output.path(worker.store, drv->name, outputName);
if (!optFixedPath ||
worker.store.printStorePath(*optFixedPath) != finalDestPath)
{
@@ -4289,26 +4298,32 @@ void DerivationGoal::registerOutputs()
/* Register each output path as valid, and register the sets of
paths referenced by each of them. If there are cycles in the
outputs, this will fail. */
- {
- ValidPathInfos infos2;
- for (auto & [outputName, newInfo] : infos) {
- if (useDerivation)
- worker.store.linkDeriverToPath(drvPath, outputName, newInfo.path);
- else {
- /* Once a floating CA derivations reaches this point, it must
- already be resolved, drvPath the basic derivation path, and
- a file existsing at that path for sake of the DB's foreign key. */
- assert(drv->type() != DerivationType::CAFloating);
- }
- infos2.push_back(newInfo);
- }
- worker.store.registerValidPaths(infos2);
+ ValidPathInfos infos2;
+ for (auto & [outputName, newInfo] : infos) {
+ infos2.push_back(newInfo);
}
+ worker.store.registerValidPaths(infos2);
/* In case of a fixed-output derivation hash mismatch, throw an
exception now that we have registered the output as valid. */
if (delayedException)
std::rethrow_exception(delayedException);
+
+ /* If we made it this far, we are sure the output matches the derivation
+ (since the delayedException would be a fixed output CA mismatch). That
+ means it's safe to link the derivation to the output hash. We must do
+ that for floating CA derivations, which otherwise couldn't be cached,
+ but it's fine to do in all cases. */
+ for (auto & [outputName, newInfo] : infos) {
+ if (useDerivation)
+ worker.store.linkDeriverToPath(drvPath, outputName, newInfo.path);
+ else {
+ /* Once a floating CA derivations reaches this point, it must
+ already be resolved, drvPath the basic derivation path, and
+ a file existsing at that path for sake of the DB's foreign key. */
+ assert(drv->type() != DerivationType::CAFloating);
+ }
+ }
}
@@ -4601,7 +4616,7 @@ std::map<std::string, std::optional<StorePath>> DerivationGoal::queryPartialDeri
if (drv->type() != DerivationType::CAFloating) {
std::map<std::string, std::optional<StorePath>> res;
for (auto & [name, output] : drv->outputs)
- res.insert_or_assign(name, output.pathOpt(worker.store, drv->name, name));
+ res.insert_or_assign(name, output.path(worker.store, drv->name, name));
return res;
} else {
return worker.store.queryPartialDerivationOutputMap(drvPath);
@@ -4632,9 +4647,11 @@ void DerivationGoal::checkPathValidity()
auto outputPath = *i.second;
info.known = {
.path = outputPath,
- .valid = !worker.store.isValidPath(outputPath)
- ? std::optional<bool> {}
- : !checkHash || worker.pathContentsGood(outputPath),
+ .status = !worker.store.isValidPath(outputPath)
+ ? PathStatus::Absent
+ : !checkHash || worker.pathContentsGood(outputPath)
+ ? PathStatus::Valid
+ : PathStatus::Corrupt,
};
}
initialOutputs.insert_or_assign(i.first, info);
diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc
index f35ddb522..8adabf549 100644
--- a/src/libstore/daemon.cc
+++ b/src/libstore/daemon.cc
@@ -232,7 +232,7 @@ struct ClientSettings
else if (setSubstituters(settings.extraSubstituters))
;
else
- warn("ignoring the user-specified setting '%s', because it is a restricted setting and you are not a trusted user", name);
+ debug("ignoring the client-specified setting '%s', because it is a restricted setting and you are not a trusted user", name);
} catch (UsageError & e) {
warn(e.what());
}
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index afac00fc4..2612f1ff7 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -7,7 +7,7 @@
namespace nix {
-std::optional<StorePath> DerivationOutput::pathOpt(const Store & store, std::string_view drvName, std::string_view outputName) const
+std::optional<StorePath> DerivationOutput::path(const Store & store, std::string_view drvName, std::string_view outputName) const
{
return std::visit(overloaded {
[](DerivationOutputInputAddressed doi) -> std::optional<StorePath> {
@@ -557,7 +557,7 @@ DerivationOutputsAndOptPaths BasicDerivation::outputsAndOptPaths(const Store & s
for (auto output : outputs)
outsAndOptPaths.insert(std::make_pair(
output.first,
- std::make_pair(output.second, output.second.pathOpt(store, name, output.first))
+ std::make_pair(output.second, output.second.path(store, name, output.first))
)
);
return outsAndOptPaths;
diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh
index 716862127..adbf8c094 100644
--- a/src/libstore/derivations.hh
+++ b/src/libstore/derivations.hh
@@ -52,7 +52,7 @@ struct DerivationOutput
/* Note, when you use this function you should make sure that you're passing
the right derivation name. When in doubt, you should use the safer
interface provided by BasicDerivation::outputsAndOptPaths */
- std::optional<StorePath> pathOpt(const Store & store, std::string_view drvName, std::string_view outputName) const;
+ std::optional<StorePath> path(const Store & store, std::string_view drvName, std::string_view outputName) const;
};
typedef std::map<string, DerivationOutput> DerivationOutputs;
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index e4a4ef5af..dc61951d3 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -1,5 +1,6 @@
#include "serialise.hh"
#include "util.hh"
+#include "remote-fs-accessor.hh"
#include "remote-store.hh"
#include "worker-protocol.hh"
#include "archive.hh"
@@ -43,8 +44,11 @@ StorePathCAMap readStorePathCAMap(const Store & store, Source & from)
{
StorePathCAMap paths;
auto count = readNum<size_t>(from);
- while (count--)
- paths.insert_or_assign(store.parseStorePath(readString(from)), parseContentAddressOpt(readString(from)));
+ while (count--) {
+ auto path = store.parseStorePath(readString(from));
+ auto ca = parseContentAddressOpt(readString(from));
+ paths.insert_or_assign(path, ca);
+ }
return paths;
}
@@ -476,10 +480,26 @@ StorePathSet RemoteStore::queryDerivationOutputs(const StorePath & path)
std::map<std::string, std::optional<StorePath>> RemoteStore::queryPartialDerivationOutputMap(const StorePath & path)
{
- auto conn(getConnection());
- conn->to << wopQueryDerivationOutputMap << printStorePath(path);
- conn.processStderr();
- return worker_proto::read(*this, conn->from, Phantom<std::map<std::string, std::optional<StorePath>>> {});
+ if (GET_PROTOCOL_MINOR(getProtocol()) >= 0x16) {
+ auto conn(getConnection());
+ conn->to << wopQueryDerivationOutputMap << printStorePath(path);
+ conn.processStderr();
+ return worker_proto::read(*this, conn->from, Phantom<std::map<std::string, std::optional<StorePath>>> {});
+ } else {
+ // Fallback for old daemon versions.
+ // For floating-CA derivations (and their co-dependencies) this is an
+ // under-approximation as it only returns the paths that can be inferred
+ // from the derivation itself (and not the ones that are known because
+ // the have been built), but as old stores don't handle floating-CA
+ // derivations this shouldn't matter
+ auto derivation = readDerivation(path);
+ auto outputsWithOptPaths = derivation.outputsAndOptPaths(*this);
+ std::map<std::string, std::optional<StorePath>> ret;
+ for (auto & [outputName, outputAndPath] : outputsWithOptPaths) {
+ ret.emplace(outputName, outputAndPath.second);
+ }
+ return ret;
+ }
}
@@ -868,6 +888,18 @@ RemoteStore::Connection::~Connection()
}
}
+void RemoteStore::narFromPath(const StorePath & path, Sink & sink)
+{
+ auto conn(connections->get());
+ conn->to << wopNarFromPath << printStorePath(path);
+ conn->processStderr();
+ copyNAR(conn->from, sink);
+}
+
+ref<FSAccessor> RemoteStore::getFSAccessor()
+{
+ return make_ref<RemoteFSAccessor>(ref<Store>(shared_from_this()));
+}
static Logger::Fields readFields(Source & from)
{
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 7cf4c4d12..6f05f2197 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -131,6 +131,10 @@ protected:
friend struct ConnectionHandle;
+ virtual ref<FSAccessor> getFSAccessor() override;
+
+ virtual void narFromPath(const StorePath & path, Sink & sink) override;
+
private:
std::atomic_bool failed{false};
@@ -149,6 +153,12 @@ public:
bool sameMachine() override
{ return true; }
+ ref<FSAccessor> getFSAccessor() override
+ { return LocalFSStore::getFSAccessor(); }
+
+ void narFromPath(const StorePath & path, Sink & sink) override
+ { LocalFSStore::narFromPath(path, sink); }
+
private:
ref<RemoteStore::Connection> openConnection() override;
diff --git a/src/libstore/ssh-store.cc b/src/libstore/ssh-store.cc
index caae6b596..6cb97c1f1 100644
--- a/src/libstore/ssh-store.cc
+++ b/src/libstore/ssh-store.cc
@@ -40,10 +40,6 @@ public:
bool sameMachine() override
{ return false; }
- void narFromPath(const StorePath & path, Sink & sink) override;
-
- ref<FSAccessor> getFSAccessor() override;
-
private:
struct Connection : RemoteStore::Connection
@@ -68,19 +64,6 @@ private:
};
};
-void SSHStore::narFromPath(const StorePath & path, Sink & sink)
-{
- auto conn(connections->get());
- conn->to << wopNarFromPath << printStorePath(path);
- conn->processStderr();
- copyNAR(conn->from, sink);
-}
-
-ref<FSAccessor> SSHStore::getFSAccessor()
-{
- return make_ref<RemoteFSAccessor>(ref<Store>(shared_from_this()));
-}
-
ref<RemoteStore::Connection> SSHStore::openConnection()
{
auto conn = make_ref<Connection>();
diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc
index e6fd7a4e6..3a8d67f21 100755
--- a/src/nix-build/nix-build.cc
+++ b/src/nix-build/nix-build.cc
@@ -98,8 +98,8 @@ static void _main(int argc, char * * argv)
// List of environment variables kept for --pure
std::set<string> keepVars{
- "HOME", "USER", "LOGNAME", "DISPLAY", "PATH", "TERM",
- "IN_NIX_SHELL", "TZ", "PAGER", "NIX_BUILD_SHELL", "SHLVL",
+ "HOME", "USER", "LOGNAME", "DISPLAY", "PATH", "TERM", "IN_NIX_SHELL",
+ "NIX_SHELL_PRESERVE_PROMPT", "TZ", "PAGER", "NIX_BUILD_SHELL", "SHLVL",
"http_proxy", "https_proxy", "ftp_proxy", "all_proxy", "no_proxy"
};
@@ -446,7 +446,7 @@ static void _main(int argc, char * * argv)
"PATH=%4%:\"$PATH\"; "
"SHELL=%5%; "
"set +e; "
- R"s([ -n "$PS1" ] && PS1='\n\[\033[1;32m\][nix-shell:\w]\$\[\033[0m\] '; )s"
+ R"s([ -n "$PS1" -a -z "$NIX_SHELL_PRESERVE_PROMPT" ] && PS1='\n\[\033[1;32m\][nix-shell:\w]\$\[\033[0m\] '; )s"
"if [ \"$(type -t runHook)\" = function ]; then runHook shellHook; fi; "
"unset NIX_ENFORCE_PURITY; "
"shopt -u nullglob; "