summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2020-08-14 17:00:13 +0000
committerJohn Ericson <John.Ericson@Obsidian.Systems>2020-08-14 17:00:13 +0000
commit3c8b5b62192b828c392e9122536d666e23278d8e (patch)
tree6302c4599c947dee9044e74f5f116aa927713c8f
parent5f80aea795d3f6f78d682c7b99453b6fb7c9b6ba (diff)
parent13e49be6602314fe5e5d7beb8a807d5d892e864e (diff)
Merge remote-tracking branch 'upstream/master' into single-ca-drv-build
-rw-r--r--doc/manual/command-ref/conf-file.xml27
-rw-r--r--perl/lib/Nix/Store.xs11
-rw-r--r--src/build-remote/build-remote.cc18
-rw-r--r--src/libexpr/get-drvs.cc3
-rw-r--r--src/libexpr/primops.cc2
-rw-r--r--src/libexpr/primops/fetchTree.cc2
-rw-r--r--src/libfetchers/fetchers.cc4
-rw-r--r--src/libfetchers/tarball.cc6
-rw-r--r--src/libmain/progress-bar.cc2
-rw-r--r--src/libstore/binary-cache-store.cc24
-rw-r--r--src/libstore/build.cc72
-rw-r--r--src/libstore/builtins/fetchurl.cc14
-rw-r--r--src/libstore/daemon.cc22
-rw-r--r--src/libstore/daemon.hh7
-rw-r--r--src/libstore/derivations.cc15
-rw-r--r--src/libstore/derivations.hh19
-rw-r--r--src/libstore/export-import.cc15
-rw-r--r--src/libstore/globals.hh3
-rw-r--r--src/libstore/legacy-ssh-store.cc21
-rw-r--r--src/libstore/local-store.cc51
-rw-r--r--src/libstore/machines.cc24
-rw-r--r--src/libstore/machines.hh4
-rw-r--r--src/libstore/nar-info-disk-cache.cc7
-rw-r--r--src/libstore/nar-info.cc14
-rw-r--r--src/libstore/nar-info.hh6
-rw-r--r--src/libstore/parsed-derivations.cc8
-rw-r--r--src/libstore/parsed-derivations.hh4
-rw-r--r--src/libstore/path-info.hh7
-rw-r--r--src/libstore/remote-store.cc6
-rw-r--r--src/libstore/store-api.cc49
-rw-r--r--src/libstore/store-api.hh7
-rw-r--r--src/libutil/archive.cc6
-rw-r--r--src/libutil/hash.cc2
-rw-r--r--src/libutil/hash.hh5
-rw-r--r--src/libutil/serialise.hh11
-rw-r--r--src/nix-daemon/nix-daemon.cc15
-rw-r--r--src/nix-store/nix-store.cc28
-rw-r--r--src/nix/add-to-store.cc6
-rw-r--r--src/nix/installables.cc4
-rw-r--r--src/nix/make-content-addressable.cc8
-rw-r--r--src/nix/profile.cc8
-rw-r--r--src/nix/show-derivation.cc8
-rw-r--r--src/nix/verify.cc8
-rw-r--r--tests/build-hook.nix3
-rw-r--r--tests/build-remote.sh33
-rw-r--r--tests/local.mk2
-rw-r--r--tests/remote-store.sh3
47 files changed, 372 insertions, 252 deletions
diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml
index 9c55526a3..d0f1b09ca 100644
--- a/doc/manual/command-ref/conf-file.xml
+++ b/doc/manual/command-ref/conf-file.xml
@@ -370,6 +370,33 @@ false</literal>.</para>
</varlistentry>
+ <varlistentry xml:id="conf-hashed-mirrors"><term><literal>hashed-mirrors</literal></term>
+
+ <listitem><para>A list of web servers used by
+ <function>builtins.fetchurl</function> to obtain files by hash.
+ Given a hash type <replaceable>ht</replaceable> and a base-16 hash
+ <replaceable>h</replaceable>, Nix will try to download the file
+ from
+ <literal>hashed-mirror/<replaceable>ht</replaceable>/<replaceable>h</replaceable></literal>.
+ This allows files to be downloaded even if they have disappeared
+ from their original URI. For example, given the hashed mirror
+ <literal>http://tarballs.example.com/</literal>, when building the
+ derivation
+
+<programlisting>
+builtins.fetchurl {
+ url = "https://example.org/foo-1.2.3.tar.xz";
+ sha256 = "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae";
+}
+</programlisting>
+
+ Nix will attempt to download this file from
+ <literal>http://tarballs.example.com/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae</literal>
+ first. If it is not available there, if will try the original URI.</para></listitem>
+
+ </varlistentry>
+
+
<varlistentry xml:id="conf-http-connections"><term><literal>http-connections</literal></term>
<listitem><para>The maximum number of parallel TCP connections
diff --git a/perl/lib/Nix/Store.xs b/perl/lib/Nix/Store.xs
index 6fe01fff0..8546f6307 100644
--- a/perl/lib/Nix/Store.xs
+++ b/perl/lib/Nix/Store.xs
@@ -80,7 +80,7 @@ SV * queryReferences(char * path)
SV * queryPathHash(char * path)
PPCODE:
try {
- auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash->to_string(Base32, true);
+ auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash.to_string(Base32, true);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
} catch (Error & e) {
croak("%s", e.what());
@@ -106,7 +106,7 @@ SV * queryPathInfo(char * path, int base32)
XPUSHs(&PL_sv_undef);
else
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0)));
- auto s = info->narHash->to_string(base32 ? Base32 : Base16, true);
+ auto s = info->narHash.to_string(base32 ? Base32 : Base16, true);
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
mXPUSHi(info->registrationTime);
mXPUSHi(info->narSize);
@@ -303,13 +303,12 @@ SV * derivationFromPath(char * drvPath)
hash = newHV();
HV * outputs = newHV();
- for (auto & i : drv.outputs) {
- auto pathOpt = i.second.pathOpt(*store(), drv.name);
+ for (auto & i : drv.outputsAndOptPaths(*store())) {
hv_store(
outputs, i.first.c_str(), i.first.size(),
- !pathOpt
+ !i.second.second
? newSV(0) /* null value */
- : newSVpv(store()->printStorePath(*pathOpt).c_str(), 0),
+ : newSVpv(store()->printStorePath(*i.second.second).c_str(), 0),
0);
}
hv_stores(hash, "outputs", newRV((SV *) outputs));
diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc
index 5247cefa6..ce5127113 100644
--- a/src/build-remote/build-remote.cc
+++ b/src/build-remote/build-remote.cc
@@ -38,9 +38,9 @@ static AutoCloseFD openSlotLock(const Machine & m, uint64_t slot)
return openLockFile(fmt("%s/%s-%d", currentLoad, escapeUri(m.storeUri), slot), true);
}
-static bool allSupportedLocally(const std::set<std::string>& requiredFeatures) {
+static bool allSupportedLocally(Store & store, const std::set<std::string>& requiredFeatures) {
for (auto & feature : requiredFeatures)
- if (!settings.systemFeatures.get().count(feature)) return false;
+ if (!store.systemFeatures.get().count(feature)) return false;
return true;
}
@@ -106,7 +106,7 @@ static int _main(int argc, char * * argv)
auto canBuildLocally = amWilling
&& ( neededSystem == settings.thisSystem
|| settings.extraPlatforms.get().count(neededSystem) > 0)
- && allSupportedLocally(requiredFeatures);
+ && allSupportedLocally(*store, requiredFeatures);
/* Error ignored here, will be caught later */
mkdir(currentLoad.c_str(), 0777);
@@ -201,7 +201,7 @@ static int _main(int argc, char * * argv)
% concatStringsSep<StringSet>(", ", m.mandatoryFeatures);
}
- logError({
+ logErrorInfo(lvlInfo, {
.name = "Remote build",
.description = "Failed to find a machine for remote build!",
.hint = hint
@@ -224,15 +224,7 @@ static int _main(int argc, char * * argv)
Activity act(*logger, lvlTalkative, actUnknown, fmt("connecting to '%s'", bestMachine->storeUri));
- Store::Params storeParams;
- if (hasPrefix(bestMachine->storeUri, "ssh://")) {
- storeParams["max-connections"] = "1";
- storeParams["log-fd"] = "4";
- if (bestMachine->sshKey != "")
- storeParams["ssh-key"] = bestMachine->sshKey;
- }
-
- sshStore = openStore(bestMachine->storeUri, storeParams);
+ sshStore = bestMachine->openStore();
sshStore->connect();
storeUri = bestMachine->storeUri;
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index d41cac132..e66832182 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -38,8 +38,9 @@ DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPat
auto i = drv.outputs.find(outputName);
if (i == drv.outputs.end())
throw Error("derivation '%s' does not have output '%s'", store->printStorePath(drvPath), outputName);
+ auto & [outputName, output] = *i;
- auto optStorePath = i->second.pathOpt(*store, drv.name);
+ auto optStorePath = output.pathOpt(*store, drv.name, outputName);
if (optStorePath)
outPath = store->printStorePath(*optStorePath);
}
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 05c571d65..e6391f509 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -79,7 +79,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);
+ auto optOutputPath = o.second.pathOpt(*state.store, drv.name, o.first);
mkString(
*state.allocAttr(v, state.symbols.create(o.first)),
state.store->printStorePath(optOutputPath
diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc
index cddcf0e59..0dbf4ae1d 100644
--- a/src/libexpr/primops/fetchTree.cc
+++ b/src/libexpr/primops/fetchTree.cc
@@ -212,7 +212,7 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
: hashFile(htSHA256, path);
if (hash != *expectedHash)
throw Error((unsigned int) 102, "hash mismatch in file downloaded from '%s':\n wanted: %s\n got: %s",
- *url, expectedHash->to_string(Base32, true), hash->to_string(Base32, true));
+ *url, expectedHash->to_string(Base32, true), hash.to_string(Base32, true));
}
if (state.allowedPaths)
diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc
index 9c69fc564..eaa635595 100644
--- a/src/libfetchers/fetchers.cc
+++ b/src/libfetchers/fetchers.cc
@@ -130,12 +130,12 @@ std::pair<Tree, Input> Input::fetch(ref<Store> store) const
tree.actualPath = store->toRealPath(tree.storePath);
auto narHash = store->queryPathInfo(tree.storePath)->narHash;
- input.attrs.insert_or_assign("narHash", narHash->to_string(SRI, true));
+ input.attrs.insert_or_assign("narHash", narHash.to_string(SRI, true));
if (auto prevNarHash = getNarHash()) {
if (narHash != *prevNarHash)
throw Error((unsigned int) 102, "NAR hash mismatch in input '%s' (%s), expected '%s', got '%s'",
- to_string(), tree.actualPath, prevNarHash->to_string(SRI, true), narHash->to_string(SRI, true));
+ to_string(), tree.actualPath, prevNarHash->to_string(SRI, true), narHash.to_string(SRI, true));
}
if (auto prevLastModified = getLastModified()) {
diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc
index 55158cece..a2d16365e 100644
--- a/src/libfetchers/tarball.cc
+++ b/src/libfetchers/tarball.cc
@@ -67,8 +67,10 @@ DownloadFileResult downloadFile(
StringSink sink;
dumpString(*res.data, sink);
auto hash = hashString(htSHA256, *res.data);
- ValidPathInfo info(store->makeFixedOutputPath(FileIngestionMethod::Flat, hash, name));
- info.narHash = hashString(htSHA256, *sink.s);
+ ValidPathInfo info {
+ store->makeFixedOutputPath(FileIngestionMethod::Flat, hash, name),
+ hashString(htSHA256, *sink.s),
+ };
info.narSize = sink.s->size();
info.ca = FixedOutputHash {
.method = FileIngestionMethod::Flat,
diff --git a/src/libmain/progress-bar.cc b/src/libmain/progress-bar.cc
index 3f7d99a1d..be3c06a38 100644
--- a/src/libmain/progress-bar.cc
+++ b/src/libmain/progress-bar.cc
@@ -362,7 +362,7 @@ public:
auto width = getWindowSize().second;
if (width <= 0) width = std::numeric_limits<decltype(width)>::max();
- writeToStderr("\r" + filterANSIEscapes(line, false, width) + "\e[K");
+ writeToStderr("\r" + filterANSIEscapes(line, false, width) + ANSI_NORMAL + "\e[K");
}
std::string getStatus(State & state)
diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc
index 86877dd1a..5433fe50d 100644
--- a/src/libstore/binary-cache-store.cc
+++ b/src/libstore/binary-cache-store.cc
@@ -143,7 +143,7 @@ struct FileSource : FdSource
void BinaryCacheStore::addToStore(const ValidPathInfo & info, Source & narSource,
RepairFlag repair, CheckSigsFlag checkSigs)
{
- assert(info.narHash && info.narSize);
+ assert(info.narSize);
if (!repair && isValidPath(info.path)) {
// FIXME: copyNAR -> null sink
@@ -312,14 +312,10 @@ void BinaryCacheStore::narFromPath(const StorePath & storePath, Sink & sink)
{
auto info = queryPathInfo(storePath).cast<const NarInfo>();
- uint64_t narSize = 0;
+ LengthSink narSize;
+ TeeSink tee { sink, narSize };
- LambdaSink wrapperSink([&](const unsigned char * data, size_t len) {
- sink(data, len);
- narSize += len;
- });
-
- auto decompressor = makeDecompressionSink(info->compression, wrapperSink);
+ auto decompressor = makeDecompressionSink(info->compression, tee);
try {
getFile(info->url, *decompressor);
@@ -331,7 +327,7 @@ void BinaryCacheStore::narFromPath(const StorePath & storePath, Sink & sink)
stats.narRead++;
//stats.narReadCompressedBytes += nar->size(); // FIXME
- stats.narReadBytes += narSize;
+ stats.narReadBytes += narSize.length;
}
void BinaryCacheStore::queryPathInfoUncached(const StorePath & storePath,
@@ -385,7 +381,10 @@ StorePath BinaryCacheStore::addToStore(const string & name, const Path & srcPath
h = hashString(hashAlgo, s);
}
- ValidPathInfo info(makeFixedOutputPath(method, *h, name));
+ ValidPathInfo info {
+ makeFixedOutputPath(method, *h, name),
+ Hash::dummy, // Will be fixed in addToStore, which recomputes nar hash
+ };
auto source = StringSource { *sink.s };
addToStore(info, source, repair, CheckSigs);
@@ -396,7 +395,10 @@ StorePath BinaryCacheStore::addToStore(const string & name, const Path & srcPath
StorePath BinaryCacheStore::addTextToStore(const string & name, const string & s,
const StorePathSet & references, RepairFlag repair)
{
- ValidPathInfo info(computeStorePathForText(name, s, references));
+ ValidPathInfo info {
+ computeStorePathForText(name, s, references),
+ Hash::dummy, // Will be fixed in addToStore, which recomputes nar hash
+ };
info.references = references;
if (repair || !isValidPath(info.path)) {
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 0ea8f9c97..db93d6092 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -1235,12 +1235,9 @@ void DerivationGoal::haveDerivation()
retrySubstitution = false;
- /* Temporarily root output paths that are known a priori building */
- for (auto & i : drv->outputs) {
- auto optOutputPath = i.second.pathOpt(worker.store, drv->name);
- if (optOutputPath)
- worker.store.addTempRoot(*optOutputPath);
- }
+ for (auto & i : drv->outputsAndOptPaths(worker.store))
+ if (i.second.second)
+ worker.store.addTempRoot(*i.second.second);
/* Check what outputs paths are not already valid. */
checkPathValidity();
@@ -1524,11 +1521,9 @@ void DerivationGoal::tryToBuild()
PathSet lockFiles;
/* FIXME: Should lock something like the drv itself so we don't build same
CA drv concurrently */
- for (auto & i : drv->outputs) {
- auto optPath = i.second.pathOpt(worker.store, drv->name);
- if (optPath)
- lockFiles.insert(worker.store.Store::toRealPath(*optPath));
- }
+ for (auto & i : drv->outputsAndOptPaths(worker.store))
+ if (i.second.second)
+ lockFiles.insert(worker.store.Store::toRealPath(*i.second.second));
if (!outputLocks.lockPaths(lockFiles, "", false)) {
if (!actLock)
@@ -1575,7 +1570,7 @@ void DerivationGoal::tryToBuild()
/* Don't do a remote build if the derivation has the attribute
`preferLocalBuild' set. Also, check and repair modes are only
supported for local builds. */
- bool buildLocally = buildMode != bmNormal || parsedDrv->willBuildLocally();
+ bool buildLocally = buildMode != bmNormal || parsedDrv->willBuildLocally(worker.store);
if (!buildLocally) {
switch (tryBuildHook()) {
@@ -2031,15 +2026,14 @@ StorePathSet DerivationGoal::exportReferences(const StorePathSet & storePaths)
for (auto & j : paths2) {
if (j.isDerivation()) {
Derivation drv = worker.store.derivationFromPath(j);
- for (auto & k : drv.outputs) {
- auto optPath = k.second.pathOpt(worker.store, drv.name);
- if (!optPath)
+ for (auto & k : drv.outputsAndOptPaths(worker.store)) {
+ if (!k.second.second)
/* FIXME: I am confused why we are calling
`computeFSClosure` on the output path, rather than
derivation itself. That doesn't seem right to me, so I
won't try to implemented this for CA derivations. */
throw UnimplementedError("export references including CA derivations (themselves) is not yet implemented");
- worker.store.computeFSClosure(*optPath, paths);
+ worker.store.computeFSClosure(*k.second.second, paths);
}
}
}
@@ -2084,13 +2078,13 @@ void linkOrCopy(const Path & from, const Path & to)
void DerivationGoal::startBuilder()
{
/* Right platform? */
- if (!parsedDrv->canBuildLocally())
+ if (!parsedDrv->canBuildLocally(worker.store))
throw Error("a '%s' with features {%s} is required to build '%s', but I am a '%s' with features {%s}",
drv->platform,
concatStringsSep(", ", parsedDrv->getRequiredSystemFeatures()),
worker.store.printStorePath(drvPath),
settings.thisSystem,
- concatStringsSep<StringSet>(", ", settings.systemFeatures));
+ concatStringsSep<StringSet>(", ", worker.store.systemFeatures));
if (drv->isBuiltin())
preloadNSS();
@@ -2376,15 +2370,14 @@ void DerivationGoal::startBuilder()
rebuilding a path that is in settings.dirsInChroot
(typically the dependencies of /bin/sh). Throw them
out. */
- for (auto & i : drv->outputs) {
+ for (auto & i : drv->outputsAndOptPaths(worker.store)) {
/* If the name isn't known a priori (i.e. floating
content-addressed derivation), the temporary location we use
should be fresh. Freshness means it is impossible that the path
is already in the sandbox, so we don't need to worry about
removing it. */
- auto optPath = i.second.pathOpt(worker.store, drv->name);
- if (optPath)
- dirsInChroot.erase(worker.store.printStorePath(*optPath));
+ if (i.second.second)
+ dirsInChroot.erase(worker.store.printStorePath(*i.second.second));
}
#elif __APPLE__
@@ -3088,7 +3081,8 @@ void DerivationGoal::startDaemon()
FdSink to(remote.get());
try {
daemon::processConnection(store, from, to,
- daemon::NotTrusted, daemon::Recursive, "nobody", 65535);
+ daemon::NotTrusted, daemon::Recursive,
+ [&](Store & store) { store.createUser("nobody", 65535); });
debug("terminated daemon connection");
} catch (SysError &) {
ignoreException();
@@ -3347,7 +3341,7 @@ void DerivationGoal::runChild()
createDirs(chrootRootDir + "/dev/shm");
createDirs(chrootRootDir + "/dev/pts");
ss.push_back("/dev/full");
- if (settings.systemFeatures.get().count("kvm") && pathExists("/dev/kvm"))
+ if (worker.store.systemFeatures.get().count("kvm") && pathExists("/dev/kvm"))
ss.push_back("/dev/kvm");
ss.push_back("/dev/null");
ss.push_back("/dev/random");
@@ -3767,9 +3761,8 @@ void DerivationGoal::registerOutputs()
*/
if (hook) {
bool allValid = true;
- for (auto & i : drv->outputs) {
- auto optStorePath = i.second.pathOpt(worker.store, drv->name);
- if (!optStorePath || !worker.store.isValidPath(*optStorePath))
+ for (auto & i : drv->outputsAndOptPaths(worker.store)) {
+ if (!i.second.second || !worker.store.isValidPath(*i.second.second))
allValid = false;
}
if (allValid) return;
@@ -3997,6 +3990,9 @@ void DerivationGoal::registerOutputs()
}
auto got = caSink.finish().first;
auto refs = rewriteRefs();
+ HashModuloSink narSink { htSHA256, oldHashPart };
+ dumpPath(actualPath, narSink);
+ auto narHashAndSize = narSink.finish();
ValidPathInfo newInfo0 {
worker.store.makeFixedOutputPath(
outputHash.method,
@@ -4004,7 +4000,9 @@ void DerivationGoal::registerOutputs()
outputPathName(drv->name, outputName),
refs.second,
refs.first),
+ narHashAndSize.first,
};
+ newInfo0.narSize = narHashAndSize.second;
newInfo0.ca = FixedOutputHash {
.method = outputHash.method,
.hash = got,
@@ -4012,13 +4010,6 @@ void DerivationGoal::registerOutputs()
newInfo0.references = refs.second;
if (refs.first)
newInfo0.references.insert(newInfo0.path);
- {
- HashModuloSink narSink { htSHA256, oldHashPart };
- dumpPath(actualPath, narSink);
- auto narHashAndSize = narSink.finish();
- newInfo0.narHash = narHashAndSize.first;
- newInfo0.narSize = narHashAndSize.second;
- }
assert(newInfo0.ca);
return newInfo0;
@@ -4036,8 +4027,7 @@ void DerivationGoal::registerOutputs()
std::string { requiredFinalPath.hashPart() });
rewriteOutput();
auto narHashAndSize = hashPath(htSHA256, actualPath);
- ValidPathInfo newInfo0 { requiredFinalPath };
- newInfo0.narHash = narHashAndSize.first;
+ ValidPathInfo newInfo0 { requiredFinalPath, narHashAndSize.first };
newInfo0.narSize = narHashAndSize.second;
auto refs = rewriteRefs();
newInfo0.references = refs.second;
@@ -4081,7 +4071,7 @@ void DerivationGoal::registerOutputs()
floating CA derivations and hash-mismatching fixed-output
derivations. */
PathLocks dynamicOutputLock;
- auto optFixedPath = output.pathOpt(worker.store, drv->name);
+ auto optFixedPath = output.pathOpt(worker.store, drv->name, outputName);
if (!optFixedPath ||
worker.store.printStorePath(*optFixedPath) != finalDestPath)
{
@@ -4563,7 +4553,7 @@ std::map<std::string, std::optional<StorePath>> DerivationGoal::queryDerivationO
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));
+ res.insert_or_assign(name, output.pathOpt(worker.store, drv->name, name));
return res;
} else {
return worker.store.queryDerivationOutputMap(drvPath);
@@ -4574,8 +4564,8 @@ OutputPathMap DerivationGoal::queryDerivationOutputMapAssumeTotal()
{
if (drv->type() != DerivationType::CAFloating) {
OutputPathMap res;
- for (auto & [name, output] : drv->outputs)
- res.insert_or_assign(name, *output.pathOpt(worker.store, drv->name));
+ for (auto & [name, output] : drv->outputsAndOptPaths(worker.store))
+ res.insert_or_assign(name, *output.second);
return res;
} else {
return worker.store.queryDerivationOutputMapAssumeTotal(drvPath);
@@ -5427,7 +5417,7 @@ bool Worker::pathContentsGood(const StorePath & path)
if (!pathExists(store.printStorePath(path)))
res = false;
else {
- HashResult current = hashPath(info->narHash->type, store.printStorePath(path));
+ HashResult current = hashPath(info->narHash.type, store.printStorePath(path));
Hash nullHash(htSHA256);
res = info->narHash == nullHash || info->narHash == current.first;
}
diff --git a/src/libstore/builtins/fetchurl.cc b/src/libstore/builtins/fetchurl.cc
index 6585a480d..4fb5d8a06 100644
--- a/src/libstore/builtins/fetchurl.cc
+++ b/src/libstore/builtins/fetchurl.cc
@@ -58,6 +58,20 @@ void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData)
}
};
+ /* Try the hashed mirrors first. */
+ if (getAttr("outputHashMode") == "flat")
+ for (auto hashedMirror : settings.hashedMirrors.get())
+ try {
+ if (!hasSuffix(hashedMirror, "/")) hashedMirror += '/';
+ std::optional<HashType> ht = parseHashTypeOpt(getAttr("outputHashAlgo"));
+ Hash h = newHashAllowEmpty(getAttr("outputHash"), ht);
+ fetch(hashedMirror + printHashType(h.type) + "/" + h.to_string(Base16, false));
+ return;
+ } catch (Error & e) {
+ debug(e.what());
+ }
+
+ /* Otherwise try the specified URL. */
fetch(mainUrl);
}
diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc
index 9503915eb..046dfbe6e 100644
--- a/src/libstore/daemon.cc
+++ b/src/libstore/daemon.cc
@@ -289,7 +289,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
logger->startWork();
auto hash = store->queryPathInfo(path)->narHash;
logger->stopWork();
- to << hash->to_string(Base16, false);
+ to << hash.to_string(Base16, false);
break;
}
@@ -638,7 +638,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
if (GET_PROTOCOL_MINOR(clientVersion) >= 17)
to << 1;
to << (info->deriver ? store->printStorePath(*info->deriver) : "")
- << info->narHash->to_string(Base16, false);
+ << info->narHash.to_string(Base16, false);
writeStorePaths(*store, to, info->references);
to << info->registrationTime << info->narSize;
if (GET_PROTOCOL_MINOR(clientVersion) >= 16) {
@@ -694,11 +694,12 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
case wopAddToStoreNar: {
bool repair, dontCheckSigs;
- ValidPathInfo info(store->parseStorePath(readString(from)));
+ auto path = store->parseStorePath(readString(from));
auto deriver = readString(from);
+ auto narHash = Hash::parseAny(readString(from), htSHA256);
+ ValidPathInfo info { path, narHash };
if (deriver != "")
info.deriver = store-