aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/store-api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/store-api.cc')
-rw-r--r--src/libstore/store-api.cc121
1 files changed, 87 insertions, 34 deletions
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index c2696f7a5..f470cfd99 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -11,6 +11,8 @@
#include "archive.hh"
#include "callback.hh"
+#include <regex>
+
namespace nix {
@@ -382,12 +384,22 @@ bool Store::PathInfoCacheValue::isKnownNow()
return std::chrono::steady_clock::now() < time_point + ttl;
}
+std::map<std::string, std::optional<StorePath>> Store::queryPartialDerivationOutputMap(const StorePath & path)
+{
+ std::map<std::string, std::optional<StorePath>> outputs;
+ auto drv = readInvalidDerivation(path);
+ for (auto& [outputName, output] : drv.outputsAndOptPaths(*this)) {
+ outputs.emplace(outputName, output.second);
+ }
+ return outputs;
+}
+
OutputPathMap Store::queryDerivationOutputMap(const StorePath & path) {
auto resp = queryPartialDerivationOutputMap(path);
OutputPathMap result;
for (auto & [outName, optOutPath] : resp) {
if (!optOutPath)
- throw Error("output '%s' has no store path mapped to it", outName);
+ throw Error("output '%s' of derivation '%s' has no store path mapped to it", outName, printStorePath(path));
result.insert_or_assign(outName, *optOutPath);
}
return result;
@@ -538,6 +550,28 @@ void Store::queryPathInfo(const StorePath & storePath,
}
+void Store::substitutePaths(const StorePathSet & paths)
+{
+ std::vector<StorePathWithOutputs> paths2;
+ for (auto & path : paths)
+ if (!path.isDerivation())
+ paths2.push_back({path});
+ uint64_t downloadSize, narSize;
+ StorePathSet willBuild, willSubstitute, unknown;
+ queryMissing(paths2,
+ willBuild, willSubstitute, unknown, downloadSize, narSize);
+
+ if (!willSubstitute.empty())
+ try {
+ std::vector<StorePathWithOutputs> subs;
+ for (auto & p : willSubstitute) subs.push_back({p});
+ buildPaths(subs);
+ } catch (Error & e) {
+ logWarning(e.info());
+ }
+}
+
+
StorePathSet Store::queryValidPaths(const StorePathSet & paths, SubstituteFlag maybeSubstitute)
{
struct State
@@ -716,21 +750,6 @@ const Store::Stats & Store::getStats()
}
-void Store::buildPaths(const std::vector<StorePathWithOutputs> & paths, BuildMode buildMode)
-{
- StorePathSet paths2;
-
- for (auto & path : paths) {
- if (path.path.isDerivation())
- unsupported("buildPaths");
- paths2.insert(path.path);
- }
-
- if (queryValidPaths(paths2).size() != paths2.size())
- unsupported("buildPaths");
-}
-
-
void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
const StorePath & storePath, RepairFlag repair, CheckSigsFlag checkSigs)
{
@@ -767,8 +786,8 @@ void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
}
auto source = sinkToSource([&](Sink & sink) {
- LambdaSink progressSink([&](const unsigned char * data, size_t len) {
- total += len;
+ LambdaSink progressSink([&](std::string_view data) {
+ total += data.size();
act.progress(total, info->narSize);
});
TeeSink tee { sink, progressSink };
@@ -896,19 +915,20 @@ std::optional<ValidPathInfo> decodeValidPathInfo(const Store & store, std::istre
getline(str, s);
auto narHash = Hash::parseAny(s, htSHA256);
getline(str, s);
- uint64_t narSize;
- if (!string2Int(s, narSize)) throw Error("number expected");
- hashGiven = { narHash, narSize };
+ auto narSize = string2Int<uint64_t>(s);
+ if (!narSize) throw Error("number expected");
+ hashGiven = { narHash, *narSize };
}
ValidPathInfo info(store.parseStorePath(path), hashGiven->first);
info.narSize = hashGiven->second;
std::string deriver;
getline(str, deriver);
if (deriver != "") info.deriver = store.parseStorePath(deriver);
- string s; int n;
+ string s;
getline(str, s);
- if (!string2Int(s, n)) throw Error("number expected");
- while (n--) {
+ auto n = string2Int<int>(s);
+ if (!n) throw Error("number expected");
+ while ((*n)--) {
getline(str, s);
info.insertReferencePossiblyToSelf(store.parseStorePath(s));
}
@@ -1060,19 +1080,24 @@ Derivation Store::derivationFromPath(const StorePath & drvPath)
return readDerivation(drvPath);
}
-
-Derivation Store::readDerivation(const StorePath & drvPath)
+Derivation readDerivationCommon(Store& store, const StorePath& drvPath, bool requireValidPath)
{
- auto accessor = getFSAccessor();
+ auto accessor = store.getFSAccessor();
try {
- return parseDerivation(*this,
- accessor->readFile(printStorePath(drvPath)),
+ return parseDerivation(store,
+ accessor->readFile(store.printStorePath(drvPath), requireValidPath),
Derivation::nameFromPath(drvPath));
} catch (FormatError & e) {
- throw Error("error parsing derivation '%s': %s", printStorePath(drvPath), e.msg());
+ throw Error("error parsing derivation '%s': %s", store.printStorePath(drvPath), e.msg());
}
}
+Derivation Store::readDerivation(const StorePath & drvPath)
+{ return readDerivationCommon(*this, drvPath, true); }
+
+Derivation Store::readInvalidDerivation(const StorePath & drvPath)
+{ return readDerivationCommon(*this, drvPath, false); }
+
}
@@ -1127,6 +1152,34 @@ std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Para
}
}
+// The `parseURL` function supports both IPv6 URIs as defined in
+// RFC2732, but also pure addresses. The latter one is needed here to
+// connect to a remote store via SSH (it's possible to do e.g. `ssh root@::1`).
+//
+// This function now ensures that a usable connection string is available:
+// * If the store to be opened is not an SSH store, nothing will be done.
+// * If the URL looks like `root@[::1]` (which is allowed by the URL parser and probably
+// needed to pass further flags), it
+// will be transformed into `root@::1` for SSH (same for `[::1]` -> `::1`).
+// * If the URL looks like `root@::1` it will be left as-is.
+// * In any other case, the string will be left as-is.
+static std::string extractConnStr(const std::string &proto, const std::string &connStr)
+{
+ if (proto.rfind("ssh") != std::string::npos) {
+ std::smatch result;
+ std::regex v6AddrRegex("^((.*)@)?\\[(.*)\\]$");
+
+ if (std::regex_match(connStr, result, v6AddrRegex)) {
+ if (result[1].matched) {
+ return result.str(1) + result.str(3);
+ }
+ return result.str(3);
+ }
+ }
+
+ return connStr;
+}
+
ref<Store> openStore(const std::string & uri_,
const Store::Params & extraParams)
{
@@ -1135,7 +1188,10 @@ ref<Store> openStore(const std::string & uri_,
auto parsedUri = parseURL(uri_);
params.insert(parsedUri.query.begin(), parsedUri.query.end());
- auto baseURI = parsedUri.authority.value_or("") + parsedUri.path;
+ auto baseURI = extractConnStr(
+ parsedUri.scheme,
+ parsedUri.authority.value_or("") + parsedUri.path
+ );
for (auto implem : *Implementations::registered) {
if (implem.uriSchemes.count(parsedUri.scheme)) {
@@ -1180,9 +1236,6 @@ std::list<ref<Store>> getDefaultSubstituters()
for (auto uri : settings.substituters.get())
addStore(uri);
- for (auto uri : settings.extraSubstituters.get())
- addStore(uri);
-
stores.sort([](ref<Store> & a, ref<Store> & b) {
return a->priority < b->priority;
});