diff options
Diffstat (limited to 'src/libstore/store-api.cc')
-rw-r--r-- | src/libstore/store-api.cc | 121 |
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; }); |