diff options
-rw-r--r-- | src/libstore/build.cc | 10 | ||||
-rw-r--r-- | src/libstore/daemon.cc | 4 | ||||
-rw-r--r-- | src/libstore/local-store.cc | 12 | ||||
-rw-r--r-- | src/libstore/local-store.hh | 2 | ||||
-rw-r--r-- | src/libstore/remote-store.cc | 21 | ||||
-rw-r--r-- | src/libstore/remote-store.hh | 2 | ||||
-rw-r--r-- | src/libstore/store-api.cc | 13 | ||||
-rw-r--r-- | src/libstore/store-api.hh | 10 | ||||
-rw-r--r-- | src/libstore/worker-protocol.hh | 52 | ||||
-rw-r--r-- | src/nix-env/nix-env.cc | 2 |
10 files changed, 105 insertions, 23 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 4156cd678..1f40dc42a 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -2756,8 +2756,12 @@ struct RestrictedStore : public LocalFSStore void queryReferrers(const StorePath & path, StorePathSet & referrers) override { } - OutputPathMap queryDerivationOutputMap(const StorePath & path) override - { throw Error("queryDerivationOutputMap"); } + std::map<std::string, std::optional<StorePath>> queryDerivationOutputMap(const StorePath & path) override + { + if (!goal.isAllowed(path)) + throw InvalidPath("cannot query output map for unknown path '%s' in recursive Nix", printStorePath(path)); + return next->queryDerivationOutputMap(path); + } std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) override { throw Error("queryPathFromHashPart"); } @@ -4947,7 +4951,7 @@ void Worker::waitForInput() std::vector<unsigned char> buffer(4096); for (auto & k : fds2) { if (pollStatus.at(fdToPollStatus.at(k)).revents) { - ssize_t rd = read(k, buffer.data(), buffer.size()); + ssize_t rd = ::read(k, buffer.data(), buffer.size()); // FIXME: is there a cleaner way to handle pt close // than EIO? Is this even standard? if (rd == 0 || (rd == -1 && errno == EIO)) { diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index b9a750425..9f7be6e1a 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -325,9 +325,9 @@ static void performOp(TunnelLogger * logger, ref<Store> store, case wopQueryDerivationOutputMap: { auto path = store->parseStorePath(readString(from)); logger->startWork(); - OutputPathMap outputs = store->queryDerivationOutputMap(path); + auto outputs = store->queryDerivationOutputMap(path); logger->stopWork(); - writeOutputPathMap(*store, to, outputs); + write(*store, to, outputs); break; } diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index f6ce8877e..e2cd3c0a5 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -767,17 +767,21 @@ StorePathSet LocalStore::queryValidDerivers(const StorePath & path) } -OutputPathMap LocalStore::queryDerivationOutputMap(const StorePath & path) +std::map<std::string, std::optional<StorePath>> LocalStore::queryDerivationOutputMap(const StorePath & path) { - return retrySQLite<OutputPathMap>([&]() { + std::map<std::string, std::optional<StorePath>> outputs; + BasicDerivation drv = readDerivation(path); + for (auto & [outName, _] : drv.outputs) { + outputs.insert_or_assign(outName, std::nullopt); + } + return retrySQLite<std::map<std::string, std::optional<StorePath>>>([&]() { auto state(_state.lock()); auto useQueryDerivationOutputs(state->stmtQueryDerivationOutputs.use() (queryValidPathId(*state, path))); - OutputPathMap outputs; while (useQueryDerivationOutputs.next()) - outputs.emplace( + outputs.insert_or_assign( useQueryDerivationOutputs.getStr(0), parseStorePath(useQueryDerivationOutputs.getStr(1)) ); diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 5a87ec2f8..285f46658 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -133,7 +133,7 @@ public: StorePathSet queryValidDerivers(const StorePath & path) override; - OutputPathMap queryDerivationOutputMap(const StorePath & path) override; + std::map<std::string, std::optional<StorePath>> queryDerivationOutputMap(const StorePath & path) override; std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) override; diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index 0c65bcd29..1200ab200 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -39,6 +39,12 @@ void writeStorePaths(const Store & store, Sink & out, const StorePathSet & paths out << store.printStorePath(i); } +StorePath read(const Store & store, Source & from, Proxy<StorePath> _) +{ + auto path = readString(from); + return store.parseStorePath(path); +} + StorePathCAMap readStorePathCAMap(const Store & store, Source & from) { StorePathCAMap paths; @@ -72,15 +78,14 @@ std::map<string, StorePath> readOutputPathMap(const Store & store, Source & from return pathMap; } -void writeOutputPathMap(const Store & store, Sink & out, const std::map<string, StorePath> & pathMap) + +void write(const Store & store, Sink & out, const StorePath & storePath) { - out << 2*pathMap.size(); - for (auto & i : pathMap) { - out << i.first; - out << store.printStorePath(i.second); - } + auto path = store.printStorePath(storePath); + out << path; } + /* TODO: Separate these store impls into different files, give them better names */ RemoteStore::RemoteStore(const Params & params) : Store(params) @@ -468,12 +473,12 @@ StorePathSet RemoteStore::queryDerivationOutputs(const StorePath & path) } -OutputPathMap RemoteStore::queryDerivationOutputMap(const StorePath & path) +std::map<std::string, std::optional<StorePath>> RemoteStore::queryDerivationOutputMap(const StorePath & path) { auto conn(getConnection()); conn->to << wopQueryDerivationOutputMap << printStorePath(path); conn.processStderr(); - return readOutputPathMap(*this, conn->from); + return read(*this, conn->from, Proxy<std::map<std::string, std::optional<StorePath>>> {}); } diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index 72d2a6689..4b093ad3b 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -51,7 +51,7 @@ public: StorePathSet queryDerivationOutputs(const StorePath & path) override; - OutputPathMap queryDerivationOutputMap(const StorePath & path) override; + std::map<std::string, std::optional<StorePath>> queryDerivationOutputMap(const StorePath & path) override; std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) override; StorePathSet querySubstitutablePaths(const StorePathSet & paths) override; diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 33f931442..f46e22874 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -347,9 +347,20 @@ bool Store::PathInfoCacheValue::isKnownNow() return std::chrono::steady_clock::now() < time_point + ttl; } +OutputPathMap Store::queryDerivationOutputMapAssumeTotal(const StorePath & path) { + auto resp = queryDerivationOutputMap(path); + OutputPathMap result; + for (auto & [outName, optOutPath] : resp) { + if (!optOutPath) + throw Error("output '%s' has no store path mapped to it", outName); + result.insert_or_assign(outName, *optOutPath); + } + return result; +} + StorePathSet Store::queryDerivationOutputs(const StorePath & path) { - auto outputMap = this->queryDerivationOutputMap(path); + auto outputMap = this->queryDerivationOutputMapAssumeTotal(path); StorePathSet outputPaths; for (auto & i: outputMap) { outputPaths.emplace(std::move(i.second)); diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 49da19496..3f8866a2c 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -428,10 +428,16 @@ public: /* Query the outputs of the derivation denoted by `path'. */ virtual StorePathSet queryDerivationOutputs(const StorePath & path); - /* Query the mapping outputName=>outputPath for the given derivation */ - virtual OutputPathMap queryDerivationOutputMap(const StorePath & path) + /* Query the mapping outputName => outputPath for the given derivation. All + outputs are mentioned so ones mising the mapping are mapped to + `std::nullopt`. */ + virtual std::map<std::string, std::optional<StorePath>> queryDerivationOutputMap(const StorePath & path) { unsupported("queryDerivationOutputMap"); } + /* Query the mapping outputName=>outputPath for the given derivation. + Assume every output has a mapping and throw an exception otherwise. */ + OutputPathMap queryDerivationOutputMapAssumeTotal(const StorePath & path); + /* Query the full store path given the hash part of a valid store path, or empty if the path doesn't exist. */ virtual std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) = 0; diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index f76b13fb4..ad5854c85 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -70,6 +70,58 @@ template<class T> T readStorePaths(const Store & store, Source & from); void writeStorePaths(const Store & store, Sink & out, const StorePathSet & paths); +/* To guide overloading */ +template<typename T> +struct Proxy {}; + +template<typename T> +std::map<std::string, T> read(const Store & store, Source & from, Proxy<std::map<std::string, T>> _) +{ + std::map<string, T> resMap; + auto size = (size_t)readInt(from); + while (size--) { + auto thisKey = readString(from); + resMap.insert_or_assign(std::move(thisKey), read(store, from, Proxy<T> {})); + } + return resMap; +} + +template<typename T> +void write(const Store & store, Sink & out, const std::map<string, T> & resMap) +{ + out << resMap.size(); + for (auto & i : resMap) { + out << i.first; + write(store, out, i.second); + } +} + +template<typename T> +std::optional<T> read(const Store & store, Source & from, Proxy<std::optional<T>> _) +{ + auto tag = readNum<uint8_t>(from); + switch (tag) { + case 0: + return std::nullopt; + case 1: + return read(store, from, Proxy<T> {}); + default: + throw Error("got an invalid tag bit for std::optional: %#04x", tag); + } +} + +template<typename T> +void write(const Store & store, Sink & out, const std::optional<T> & optVal) +{ + out << (optVal ? 1 : 0); + if (optVal) + write(store, out, *optVal); +} + +StorePath read(const Store & store, Source & from, Proxy<StorePath> _); + +void write(const Store & store, Sink & out, const StorePath & storePath); + StorePathCAMap readStorePathCAMap(const Store & store, Source & from); void writeStorePathCAMap(const Store & store, Sink & out, const StorePathCAMap & paths); diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index ddd036070..d36804658 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -381,7 +381,7 @@ static void queryInstSources(EvalState & state, if (path.isDerivation()) { elem.setDrvPath(state.store->printStorePath(path)); - auto outputs = state.store->queryDerivationOutputMap(path); + auto outputs = state.store->queryDerivationOutputMapAssumeTotal(path); elem.setOutPath(state.store->printStorePath(outputs.at("out"))); if (name.size() >= drvExtension.size() && string(name, name.size() - drvExtension.size()) == drvExtension) |