libstore: remove DerivedPathMap
single-level maps suffice now that dynamic derivations are gone. Change-Id: If29998b104b31255292ab0c789622d7d27040f69
This commit is contained in:
@@ -324,7 +324,7 @@ connected:
|
||||
//
|
||||
// 2. Changing the `inputSrcs` set changes the associated
|
||||
// output ids, which break CA derivations
|
||||
if (!drv.inputDrvs.map.empty())
|
||||
if (!drv.inputDrvs.empty())
|
||||
drv.inputSrcs = store->parseStorePathSet(inputs);
|
||||
optResult = aio.blockOn(sshStore->buildDerivation(*drvPath, (const BasicDerivation &) drv));
|
||||
auto & result = *optResult;
|
||||
|
||||
+7
-13
@@ -368,18 +368,16 @@ static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings a
|
||||
}
|
||||
}
|
||||
|
||||
auto accumDerivedPath = [&](ref<SingleDerivedPath::Opaque> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode) {
|
||||
if (!inputNode.value.empty())
|
||||
auto accumDerivedPath = [&](ref<SingleDerivedPath::Opaque> inputDrv, const StringSet & inputNode) {
|
||||
if (!inputNode.empty())
|
||||
pathsToBuild.push_back(DerivedPath::Built {
|
||||
.drvPath = inputDrv,
|
||||
.outputs = OutputsSpec::Names { inputNode.value },
|
||||
.outputs = OutputsSpec::Names { inputNode },
|
||||
});
|
||||
// only dynamic derivations have a non-empty childMap
|
||||
assert(inputNode.childMap.empty());
|
||||
};
|
||||
|
||||
// Build or fetch all dependencies of the derivation.
|
||||
for (const auto & [inputDrv0, inputNode] : drv.inputDrvs.map) {
|
||||
for (const auto & [inputDrv0, inputNode] : drv.inputDrvs) {
|
||||
// To get around lambda capturing restrictions in the
|
||||
// standard.
|
||||
const auto & inputDrv = inputDrv0;
|
||||
@@ -451,20 +449,16 @@ static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings a
|
||||
if (env.count("__json")) {
|
||||
StorePathSet inputs;
|
||||
|
||||
std::function<void(const StorePath &, const DerivedPathMap<StringSet>::ChildNode &)> accumInputClosure;
|
||||
|
||||
accumInputClosure = [&](const StorePath & inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode) {
|
||||
auto accumInputClosure = [&](const StorePath & inputDrv, const StringSet & inputNode) {
|
||||
auto outputs =
|
||||
aio.blockOn(store->queryPartialDerivationOutputMap(inputDrv, &*evalStore));
|
||||
for (auto & i : inputNode.value) {
|
||||
for (auto & i : inputNode) {
|
||||
auto o = outputs.at(i);
|
||||
aio.blockOn(store->computeFSClosure(*o, inputs));
|
||||
}
|
||||
for (const auto & [outputName, childNode] : inputNode.childMap)
|
||||
accumInputClosure(*outputs.at(outputName), childNode);
|
||||
};
|
||||
|
||||
for (const auto & [inputDrv, inputNode] : drv.inputDrvs.map)
|
||||
for (const auto & [inputDrv, inputNode] : drv.inputDrvs)
|
||||
accumInputClosure(inputDrv, inputNode);
|
||||
|
||||
ParsedDerivation parsedDrv(drvInfo.requireDrvPath(*state), drv);
|
||||
|
||||
@@ -971,13 +971,13 @@ drvName, Bindings * attrs, Value & v)
|
||||
for (auto & j : refs) {
|
||||
drv.inputSrcs.insert(j);
|
||||
if (j.isDerivation()) {
|
||||
drv.inputDrvs.map[j].value =
|
||||
drv.inputDrvs[j] =
|
||||
state.aio.blockOn(state.ctx.store->readDerivation(j)).outputNames();
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](const NixStringContextElem::Built & b) {
|
||||
drv.inputDrvs.ensureSlot(*b.drvPath).value.insert(b.output);
|
||||
drv.inputDrvs[b.drvPath->path].insert(b.output);
|
||||
},
|
||||
[&](const NixStringContextElem::Opaque & o) {
|
||||
drv.inputSrcs.insert(o.path);
|
||||
|
||||
@@ -373,19 +373,17 @@ try {
|
||||
/* The inputs must be built before we can build this goal. */
|
||||
inputDrvOutputs.clear();
|
||||
if (useDerivation) {
|
||||
auto addWaiteeDerivedPath = [&](ref<DerivedPathOpaque> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode) {
|
||||
if (!inputNode.value.empty())
|
||||
auto addWaiteeDerivedPath = [&](ref<DerivedPathOpaque> inputDrv, const StringSet & inputNode) {
|
||||
if (!inputNode.empty())
|
||||
dependencies.add(worker.goalFactory().makeGoal(
|
||||
DerivedPath::Built {
|
||||
.drvPath = inputDrv,
|
||||
.outputs = inputNode.value,
|
||||
.outputs = inputNode,
|
||||
},
|
||||
buildMode == bmRepair ? bmRepair : bmNormal));
|
||||
// only dynamic derivations have a non-empty childMap
|
||||
assert(inputNode.childMap.empty());
|
||||
};
|
||||
|
||||
for (const auto & [inputDrvPath, inputNode] : dynamic_cast<Derivation *>(drv.get())->inputDrvs.map) {
|
||||
for (const auto & [inputDrvPath, inputNode] : dynamic_cast<Derivation *>(drv.get())->inputDrvs) {
|
||||
addWaiteeDerivedPath(makeConstantStorePathRef(inputDrvPath), inputNode);
|
||||
}
|
||||
}
|
||||
@@ -539,7 +537,7 @@ try {
|
||||
return ia.deferred;
|
||||
},
|
||||
[&](const DerivationType::ContentAddressed & ca) {
|
||||
return !fullDrv.inputDrvs.map.empty() && (
|
||||
return !fullDrv.inputDrvs.empty() && (
|
||||
ca.fixed
|
||||
/* Can optionally resolve if fixed, which is good
|
||||
for avoiding unnecessary rebuilds. */
|
||||
@@ -550,7 +548,7 @@ try {
|
||||
},
|
||||
}, drvType.raw);
|
||||
|
||||
if (resolveDrv && !fullDrv.inputDrvs.map.empty()) {
|
||||
if (resolveDrv && !fullDrv.inputDrvs.empty()) {
|
||||
experimentalFeatureSettings.require(Xp::CaDerivations);
|
||||
|
||||
/* We are be able to resolve this derivation based on the
|
||||
@@ -587,10 +585,8 @@ try {
|
||||
co_return co_await resolvedFinished();
|
||||
}
|
||||
|
||||
std::function<kj::Promise<Result<void>>(const StorePath &, const DerivedPathMap<StringSet>::ChildNode &)> accumInputPaths;
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
|
||||
accumInputPaths = [&](const StorePath & depDrvPath, const DerivedPathMap<StringSet>::ChildNode & inputNode) -> kj::Promise<Result<void>> {
|
||||
auto accumInputPaths = [&](const StorePath & depDrvPath, const StringSet & inputNode) -> kj::Promise<Result<void>> {
|
||||
try {
|
||||
/* Add the relevant output closures of the input derivation
|
||||
`i' as input paths. Only add the closures of output paths
|
||||
@@ -633,21 +629,19 @@ try {
|
||||
}
|
||||
};
|
||||
|
||||
for (auto & outputName : inputNode.value) {
|
||||
for (auto & outputName : inputNode) {
|
||||
TRY_AWAIT(
|
||||
worker.store.computeFSClosure(TRY_AWAIT(getOutput(outputName)), inputPaths)
|
||||
);
|
||||
}
|
||||
|
||||
for (auto & [outputName, childNode] : inputNode.childMap)
|
||||
TRY_AWAIT(accumInputPaths(TRY_AWAIT(getOutput(outputName)), childNode));
|
||||
co_return result::success();
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
};
|
||||
|
||||
for (auto & [depDrvPath, depNode] : fullDrv.inputDrvs.map)
|
||||
for (auto & [depDrvPath, depNode] : fullDrv.inputDrvs)
|
||||
TRY_AWAIT(accumInputPaths(depDrvPath, depNode));
|
||||
}
|
||||
|
||||
@@ -1762,9 +1756,9 @@ void DerivationGoal::waiteeDone(GoalPtr waitee)
|
||||
|
||||
auto & fullDrv = *dynamic_cast<Derivation *>(drv.get());
|
||||
|
||||
auto * nodeP = fullDrv.inputDrvs.findSlot(DerivedPath::Opaque { .path = dg->drvPath });
|
||||
auto * nodeP = get(fullDrv.inputDrvs, dg->drvPath);
|
||||
if (!nodeP) return;
|
||||
auto & outputs = nodeP->value;
|
||||
auto & outputs = *nodeP;
|
||||
|
||||
for (auto & outputName : outputs) {
|
||||
auto buildResult = dg->buildResult.restrictTo(DerivedPath::Built {
|
||||
|
||||
+25
-55
@@ -107,7 +107,7 @@ kj::Promise<Result<StorePath>> writeDerivation(Store & store,
|
||||
const Derivation & drv, RepairFlag repair, bool readOnly)
|
||||
try {
|
||||
auto references = drv.inputSrcs;
|
||||
for (auto & i : drv.inputDrvs.map)
|
||||
for (auto & i : drv.inputDrvs)
|
||||
references.insert(i.first);
|
||||
/* Note that the outputs of a derivation are *not* references
|
||||
(that can be missing (of course) and should not necessarily be
|
||||
@@ -287,13 +287,11 @@ static DerivationOutput parseDerivationOutput(
|
||||
return parseDerivationOutput(store, *pathS, *hashAlgo, *hash, xpSettings);
|
||||
}
|
||||
|
||||
static DerivedPathMap<StringSet>::ChildNode parseDerivedPathMapNode(
|
||||
static StringSet parseDerivedPathMapNode(
|
||||
const Store & store,
|
||||
StringViewStream & str)
|
||||
{
|
||||
DerivedPathMap<StringSet>::ChildNode node;
|
||||
node.value = parseStrings(str, false);
|
||||
return node;
|
||||
return parseStrings(str, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -333,7 +331,7 @@ Derivation parseDerivation(
|
||||
expect(str, "(");
|
||||
auto drvPath = parsePath(str);
|
||||
expect(str, ",");
|
||||
drv.inputDrvs.map.insert_or_assign(store.parseStorePath(*drvPath), parseDerivedPathMapNode(store, str));
|
||||
drv.inputDrvs.insert_or_assign(store.parseStorePath(*drvPath), parseDerivedPathMapNode(store, str));
|
||||
expect(str, ")");
|
||||
}
|
||||
|
||||
@@ -421,29 +419,15 @@ static void printUnquotedStrings(std::string & res, ForwardIterator i, ForwardIt
|
||||
}
|
||||
|
||||
|
||||
static void unparseDerivedPathMapNode(const Store & store, std::string & s, const DerivedPathMap<StringSet>::ChildNode & node)
|
||||
static void unparseDerivedPathMapNode(const Store & store, std::string & s, const StringSet & node)
|
||||
{
|
||||
s += ',';
|
||||
if (node.childMap.empty()) {
|
||||
printUnquotedStrings(s, node.value.begin(), node.value.end());
|
||||
} else {
|
||||
s += "(";
|
||||
printUnquotedStrings(s, node.value.begin(), node.value.end());
|
||||
s += ",[";
|
||||
bool first = true;
|
||||
for (auto & [outputName, childNode] : node.childMap) {
|
||||
if (first) first = false; else s += ',';
|
||||
s += '('; printUnquotedString(s, outputName);
|
||||
unparseDerivedPathMapNode(store, s, childNode);
|
||||
s += ')';
|
||||
}
|
||||
s += "])";
|
||||
}
|
||||
printUnquotedStrings(s, node.begin(), node.end());
|
||||
}
|
||||
|
||||
|
||||
std::string Derivation::unparse(const Store & store, bool maskOutputs,
|
||||
DerivedPathMap<StringSet>::ChildNode::Map * actualInputs) const
|
||||
std::map<std::string, StringSet> * actualInputs) const
|
||||
{
|
||||
std::string s;
|
||||
s.reserve(65536);
|
||||
@@ -490,7 +474,7 @@ std::string Derivation::unparse(const Store & store, bool maskOutputs,
|
||||
s += ')';
|
||||
}
|
||||
} else {
|
||||
for (auto & [drvPath, childMap] : inputDrvs.map) {
|
||||
for (auto & [drvPath, childMap] : inputDrvs) {
|
||||
if (first) first = false; else s += ',';
|
||||
s += '('; printUnquotedString(s, store.printStorePath(drvPath));
|
||||
unparseDerivedPathMapNode(store, s, childMap);
|
||||
@@ -701,16 +685,16 @@ try {
|
||||
},
|
||||
}, drv.type().raw);
|
||||
|
||||
DerivedPathMap<StringSet>::ChildNode::Map inputs2;
|
||||
for (auto & [drvPath, node] : drv.inputDrvs.map) {
|
||||
std::map<std::string, StringSet> inputs2;
|
||||
for (auto & [drvPath, node] : drv.inputDrvs) {
|
||||
const auto & res = TRY_AWAIT(pathDerivationModulo(store, drvPath));
|
||||
if (res.kind == DrvHash::Kind::Deferred)
|
||||
kind = DrvHash::Kind::Deferred;
|
||||
for (auto & outputName : node.value) {
|
||||
for (auto & outputName : node) {
|
||||
const auto h = get(res.hashes, outputName);
|
||||
if (!h)
|
||||
throw Error("no hash for output '%s' of derivation '%s'", outputName, drv.name);
|
||||
inputs2[h->to_string(Base::Base16, false)].value.insert(outputName);
|
||||
inputs2[h->to_string(Base::Base16, false)].insert(outputName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,19 +884,14 @@ Derivation::tryResolve(Store & store, Store * evalStore) const
|
||||
try {
|
||||
std::map<std::pair<StorePath, std::string>, StorePath> inputDrvOutputs;
|
||||
|
||||
std::function<
|
||||
kj::Promise<Result<void>>(const StorePath &, const DerivedPathMap<StringSet>::ChildNode &)>
|
||||
accum;
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
|
||||
accum = [&](auto & inputDrv, auto & node) -> kj::Promise<Result<void>> {
|
||||
auto accum = [&](auto & inputDrv, auto & node) -> kj::Promise<Result<void>> {
|
||||
try {
|
||||
for (auto & [outputName, outputPath] :
|
||||
TRY_AWAIT(store.queryPartialDerivationOutputMap(inputDrv, evalStore)))
|
||||
{
|
||||
if (outputPath) {
|
||||
inputDrvOutputs.insert_or_assign({inputDrv, outputName}, *outputPath);
|
||||
if (auto p = get(node.childMap, outputName))
|
||||
TRY_AWAIT(accum(*outputPath, *p));
|
||||
}
|
||||
}
|
||||
co_return result::success();
|
||||
@@ -921,7 +900,7 @@ try {
|
||||
}
|
||||
};
|
||||
|
||||
for (auto & [inputDrv, node] : inputDrvs.map)
|
||||
for (auto & [inputDrv, node] : inputDrvs)
|
||||
TRY_AWAIT(accum(inputDrv, node));
|
||||
|
||||
co_return TRY_AWAIT(tryResolve(store, inputDrvOutputs));
|
||||
@@ -931,7 +910,7 @@ try {
|
||||
|
||||
static bool tryResolveInput(
|
||||
Store & store, StorePathSet & inputSrcs, StringMap & inputRewrites,
|
||||
const StorePath & inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode,
|
||||
const StorePath & inputDrv, const StringSet & inputNode,
|
||||
const std::map<std::pair<StorePath, std::string>, StorePath> & inputDrvOutputs)
|
||||
{
|
||||
auto getOutput = [&](const std::string & outputName) {
|
||||
@@ -948,7 +927,7 @@ static bool tryResolveInput(
|
||||
return DownstreamPlaceholder::unknownCaOutput(inputDrv, outputName);
|
||||
};
|
||||
|
||||
for (auto & outputName : inputNode.value) {
|
||||
for (auto & outputName : inputNode) {
|
||||
auto actualPathOpt = getOutput(outputName);
|
||||
if (!actualPathOpt) return false;
|
||||
auto actualPath = *actualPathOpt;
|
||||
@@ -960,8 +939,6 @@ static bool tryResolveInput(
|
||||
inputSrcs.insert(std::move(actualPath));
|
||||
}
|
||||
|
||||
// only dynamic drvs can have non-empty childMaps
|
||||
assert(inputNode.childMap.empty());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -974,7 +951,7 @@ try {
|
||||
// Input paths that we'll want to rewrite in the derivation
|
||||
StringMap inputRewrites;
|
||||
|
||||
for (auto & [inputDrv, inputNode] : inputDrvs.map)
|
||||
for (auto & [inputDrv, inputNode] : inputDrvs)
|
||||
if (!tryResolveInput(store, resolved.inputSrcs, inputRewrites,
|
||||
inputDrv, inputNode, inputDrvOutputs))
|
||||
co_return std::nullopt;
|
||||
@@ -1171,22 +1148,16 @@ JSON Derivation::toJSON(const Store & store) const
|
||||
}
|
||||
|
||||
{
|
||||
std::function<JSON(const DerivedPathMap<StringSet>::ChildNode &)> doInput;
|
||||
doInput = [&](const auto & inputNode) {
|
||||
auto doInput = [&](const auto & inputNode) {
|
||||
auto value = JSON::object();
|
||||
value["outputs"] = inputNode.value;
|
||||
{
|
||||
auto next = JSON::object();
|
||||
for (auto & [outputId, childNode] : inputNode.childMap)
|
||||
next[outputId] = doInput(childNode);
|
||||
value["dynamicOutputs"] = std::move(next);
|
||||
}
|
||||
value["outputs"] = inputNode;
|
||||
value["dynamicOutputs"] = JSON::object(); // for compatibility with cppnix
|
||||
return value;
|
||||
};
|
||||
{
|
||||
auto& inputDrvsObj = res["inputDrvs"];
|
||||
inputDrvsObj = JSON::object();
|
||||
for (auto & [inputDrv, inputNode] : inputDrvs.map) {
|
||||
for (auto & [inputDrv, inputNode] : inputDrvs) {
|
||||
inputDrvsObj[store.printStorePath(inputDrv)] = doInput(inputNode);
|
||||
}
|
||||
}
|
||||
@@ -1236,10 +1207,9 @@ Derivation Derivation::fromJSON(
|
||||
}
|
||||
|
||||
try {
|
||||
std::function<DerivedPathMap<StringSet>::ChildNode(const JSON &)> doInput;
|
||||
doInput = [&](const auto & json) {
|
||||
DerivedPathMap<StringSet>::ChildNode node;
|
||||
node.value = static_cast<const StringSet &>(
|
||||
auto doInput = [&](const auto & json) {
|
||||
StringSet node;
|
||||
node = static_cast<const StringSet &>(
|
||||
ensureType(valueAt(json, "outputs"), value_t::array));
|
||||
if (!ensureType(valueAt(json, "dynamicOutputs"), value_t::object).empty()) {
|
||||
throw UnimplementedError("dynamic derivations are not supported");
|
||||
@@ -1248,7 +1218,7 @@ Derivation Derivation::fromJSON(
|
||||
};
|
||||
auto & inputDrvsObj = ensureType(valueAt(json, "inputDrvs"), value_t::object);
|
||||
for (auto & [inputDrvPath, inputOutputs] : inputDrvsObj.items())
|
||||
res.inputDrvs.map[store.parseStorePath(inputDrvPath)] =
|
||||
res.inputDrvs[store.parseStorePath(inputDrvPath)] =
|
||||
doInput(inputOutputs);
|
||||
} catch (Error & e) {
|
||||
e.addTrace({}, "while reading key 'inputDrvs'");
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
///@file
|
||||
|
||||
#include "lix/libstore/path.hh"
|
||||
#include "lix/libutil/config.hh"
|
||||
#include "lix/libutil/result.hh"
|
||||
#include "lix/libutil/types.hh"
|
||||
#include "lix/libutil/hash.hh"
|
||||
#include "lix/libstore/content-address.hh"
|
||||
#include "lix/libutil/repair-flag.hh"
|
||||
#include "lix/libstore/derived-path-map.hh"
|
||||
#include "lix/libutil/sync.hh"
|
||||
#include "lix/libutil/comparator.hh"
|
||||
#include "lix/libutil/variant-wrapper.hh"
|
||||
#include "outputs-spec.hh"
|
||||
|
||||
#include <kj/async.h>
|
||||
#include <map>
|
||||
@@ -286,13 +287,13 @@ struct Derivation : BasicDerivation
|
||||
/**
|
||||
* inputs that are sub-derivations
|
||||
*/
|
||||
DerivedPathMap<std::set<OutputName>> inputDrvs;
|
||||
std::map<StorePath, std::set<OutputName>> inputDrvs;
|
||||
|
||||
/**
|
||||
* Print a derivation.
|
||||
*/
|
||||
std::string unparse(const Store & store, bool maskOutputs,
|
||||
DerivedPathMap<StringSet>::ChildNode::Map * actualInputs = nullptr) const;
|
||||
std::map<std::string, StringSet> * actualInputs = nullptr) const;
|
||||
|
||||
/**
|
||||
* Return the underlying basic derivation but with these changes:
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
#include "lix/libstore/derived-path-map.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
template<typename V>
|
||||
typename DerivedPathMap<V>::ChildNode & DerivedPathMap<V>::ensureSlot(const SingleDerivedPath & k)
|
||||
{
|
||||
std::function<ChildNode &(const SingleDerivedPath & )> initIter;
|
||||
initIter = [&](const auto & k) -> auto & {
|
||||
return std::visit(overloaded {
|
||||
[&](const SingleDerivedPath::Opaque & bo) -> auto & {
|
||||
// will not overwrite if already there
|
||||
return map[bo.path];
|
||||
},
|
||||
[&](const SingleDerivedPath::Built & bfd) -> auto & {
|
||||
auto & n = initIter(*bfd.drvPath);
|
||||
return n.childMap[bfd.output];
|
||||
},
|
||||
}, k.raw());
|
||||
};
|
||||
return initIter(k);
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
typename DerivedPathMap<V>::ChildNode * DerivedPathMap<V>::findSlot(const SingleDerivedPath & k)
|
||||
{
|
||||
std::function<ChildNode *(const SingleDerivedPath & )> initIter;
|
||||
initIter = [&](const auto & k) {
|
||||
return std::visit(overloaded {
|
||||
[&](const SingleDerivedPath::Opaque & bo) {
|
||||
auto it = map.find(bo.path);
|
||||
return it != map.end()
|
||||
? &it->second
|
||||
: nullptr;
|
||||
},
|
||||
[&](const SingleDerivedPath::Built & bfd) {
|
||||
auto * n = initIter(*bfd.drvPath);
|
||||
if (!n) return (ChildNode *)nullptr;
|
||||
|
||||
auto it = n->childMap.find(bfd.output);
|
||||
return it != n->childMap.end()
|
||||
? &it->second
|
||||
: nullptr;
|
||||
},
|
||||
}, k.raw());
|
||||
};
|
||||
return initIter(k);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// instantiations
|
||||
|
||||
namespace nix {
|
||||
|
||||
GENERATE_CMP_EXT(
|
||||
template<>,
|
||||
DerivedPathMap<std::set<std::string>>::ChildNode,
|
||||
me->value,
|
||||
me->childMap);
|
||||
|
||||
GENERATE_CMP_EXT(
|
||||
template<>,
|
||||
DerivedPathMap<std::set<std::string>>,
|
||||
me->map);
|
||||
|
||||
template struct DerivedPathMap<std::set<std::string>>;
|
||||
|
||||
};
|
||||
@@ -1,96 +0,0 @@
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "lix/libutil/types.hh"
|
||||
#include "lix/libstore/derived-path.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
/**
|
||||
* A simple Trie, of sorts. Conceptually a map of `SingleDerivedPath` to
|
||||
* values.
|
||||
*
|
||||
* Concretely, an n-ary tree, as described below. A
|
||||
* `SingleDerivedPath::Opaque` maps to the value of an immediate child
|
||||
* of the root node. A `SingleDerivedPath::Built` maps to a deeper child
|
||||
* node: the `SingleDerivedPath::Built::drvPath` is first mapped to a a
|
||||
* child node (inductively), and then the
|
||||
* `SingleDerivedPath::Built::output` is used to look up that child's
|
||||
* child via its map. In this manner, every `SingleDerivedPath` is
|
||||
* mapped to a child node.
|
||||
*
|
||||
* @param V A type to instantiate for each output. It should probably
|
||||
* should be an "optional" type so not every interior node has to have a
|
||||
* value. `* const Something` or `std::optional<Something>` would be
|
||||
* good choices for "optional" types.
|
||||
*/
|
||||
template<typename V>
|
||||
struct DerivedPathMap {
|
||||
/**
|
||||
* A child node (non-root node).
|
||||
*/
|
||||
struct ChildNode {
|
||||
/**
|
||||
* Value of this child node.
|
||||
*
|
||||
* @see DerivedPathMap for what `V` should be.
|
||||
*/
|
||||
V value;
|
||||
|
||||
/**
|
||||
* The map type for the root node.
|
||||
*/
|
||||
using Map = std::map<OutputName, ChildNode>;
|
||||
|
||||
/**
|
||||
* The map of the root node.
|
||||
*/
|
||||
Map childMap;
|
||||
|
||||
DECLARE_CMP(ChildNode);
|
||||
};
|
||||
|
||||
/**
|
||||
* The map type for the root node.
|
||||
*/
|
||||
using Map = std::map<StorePath, ChildNode>;
|
||||
|
||||
/**
|
||||
* The map of root node.
|
||||
*/
|
||||
Map map;
|
||||
|
||||
DECLARE_CMP(DerivedPathMap);
|
||||
|
||||
/**
|
||||
* Find the node for `k`, creating it if needed.
|
||||
*
|
||||
* The node is referred to as a "slot" on the assumption that `V` is
|
||||
* some sort of optional type, so the given key can be set or unset
|
||||
* by changing this node.
|
||||
*/
|
||||
ChildNode & ensureSlot(const SingleDerivedPath & k);
|
||||
|
||||
/**
|
||||
* Like `ensureSlot` but does not create the slot if it doesn't exist.
|
||||
*
|
||||
* Read the entire description of `ensureSlot` to understand an
|
||||
* important caveat here that "have slot" does *not* imply "key is
|
||||
* set in map". To ensure a key is set one would need to get the
|
||||
* child node (with `findSlot` or `ensureSlot`) *and* check the
|
||||
* `ChildNode::value`.
|
||||
*/
|
||||
ChildNode * findSlot(const SingleDerivedPath & k);
|
||||
};
|
||||
|
||||
|
||||
DECLARE_CMP_EXT(
|
||||
template<>,
|
||||
DerivedPathMap<std::set<std::string>>::,
|
||||
DerivedPathMap<std::set<std::string>>);
|
||||
DECLARE_CMP_EXT(
|
||||
template<>,
|
||||
DerivedPathMap<std::set<std::string>>::ChildNode::,
|
||||
DerivedPathMap<std::set<std::string>>::ChildNode);
|
||||
|
||||
}
|
||||
@@ -156,7 +156,6 @@ libstore_sources = files(
|
||||
'crypto.cc',
|
||||
'daemon.cc',
|
||||
'derivations.cc',
|
||||
'derived-path-map.cc',
|
||||
'derived-path.cc',
|
||||
'downstream-placeholder.cc',
|
||||
'dummy-store.cc',
|
||||
@@ -225,7 +224,6 @@ libstore_headers = files(
|
||||
'crypto.hh',
|
||||
'daemon.hh',
|
||||
'derivations.hh',
|
||||
'derived-path-map.hh',
|
||||
'derived-path.hh',
|
||||
'downstream-placeholder.hh',
|
||||
'dummy-store.hh',
|
||||
|
||||
+9
-26
@@ -150,15 +150,13 @@ struct QueryMissingContext
|
||||
|
||||
kj::Promise<Result<void>> queryMissing(const std::vector<DerivedPath> & targets);
|
||||
|
||||
void enqueueDerivedPaths(ref<DerivedPathOpaque> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode)
|
||||
void enqueueDerivedPaths(ref<DerivedPathOpaque> inputDrv, const StringSet & inputNode)
|
||||
{
|
||||
if (!inputNode.value.empty()) {
|
||||
pool.enqueueWithAio([this, path{DerivedPath::Built{inputDrv, inputNode.value}}](
|
||||
if (!inputNode.empty()) {
|
||||
pool.enqueueWithAio([this, path{DerivedPath::Built{inputDrv, inputNode}}](
|
||||
AsyncIoRoot & aio
|
||||
) { doPath(aio, path); });
|
||||
}
|
||||
// only dynamic derivations have a non-empty childMap
|
||||
assert(inputNode.childMap.empty());
|
||||
}
|
||||
|
||||
void mustBuildDrv(const StorePath & drvPath, const Derivation & drv)
|
||||
@@ -168,7 +166,7 @@ struct QueryMissingContext
|
||||
state->willBuild.insert(drvPath);
|
||||
}
|
||||
|
||||
for (const auto & [inputDrv, inputNode] : drv.inputDrvs.map) {
|
||||
for (const auto & [inputDrv, inputNode] : drv.inputDrvs) {
|
||||
enqueueDerivedPaths(makeConstantStorePathRef(inputDrv), inputNode);
|
||||
}
|
||||
}
|
||||
@@ -415,20 +413,15 @@ try {
|
||||
|
||||
std::set<Realisation> inputRealisations;
|
||||
|
||||
std::function<
|
||||
kj::Promise<Result<void>>(const StorePath &, const DerivedPathMap<StringSet>::ChildNode &)>
|
||||
accumRealisations;
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
|
||||
accumRealisations = [&](const StorePath & inputDrv,
|
||||
const DerivedPathMap<StringSet>::ChildNode & inputNode
|
||||
) -> kj::Promise<Result<void>> {
|
||||
auto accumRealisations = [&](const StorePath & inputDrv,
|
||||
const StringSet & inputNode) -> kj::Promise<Result<void>> {
|
||||
try {
|
||||
if (!inputNode.value.empty()) {
|
||||
if (!inputNode.empty()) {
|
||||
auto outputHashes = TRY_AWAIT(
|
||||
staticOutputHashes(evalStore, TRY_AWAIT(evalStore.readDerivation(inputDrv)))
|
||||
);
|
||||
for (const auto & outputName : inputNode.value) {
|
||||
for (const auto & outputName : inputNode) {
|
||||
auto outputHash = get(outputHashes, outputName);
|
||||
if (!outputHash)
|
||||
throw Error(
|
||||
@@ -443,23 +436,13 @@ try {
|
||||
inputRealisations.insert(*thisRealisation);
|
||||
}
|
||||
}
|
||||
if (!inputNode.value.empty()) {
|
||||
auto d = makeConstantStorePathRef(inputDrv);
|
||||
for (const auto & [outputName, childNode] : inputNode.childMap) {
|
||||
SingleDerivedPath next = SingleDerivedPath::Built { d, outputName };
|
||||
TRY_AWAIT(accumRealisations(
|
||||
// TODO deep resolutions for dynamic derivations, issue #8947, would go here.
|
||||
TRY_AWAIT(resolveDerivedPath(store, next, evalStore_)),
|
||||
childNode));
|
||||
}
|
||||
}
|
||||
co_return result::success();
|
||||
} catch (...) {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
};
|
||||
|
||||
for (const auto & [inputDrv, inputNode] : drv.inputDrvs.map)
|
||||
for (const auto & [inputDrv, inputNode] : drv.inputDrvs)
|
||||
TRY_AWAIT(accumRealisations(inputDrv, inputNode));
|
||||
|
||||
auto info = TRY_AWAIT(store.queryPathInfo(outputPath));
|
||||
|
||||
@@ -339,7 +339,7 @@ SV * derivationFromPath(char * drvPath)
|
||||
hv_stores(hash, "outputs", newRV((SV *) outputs));
|
||||
|
||||
AV * inputDrvs = newAV();
|
||||
for (auto & i : drv.inputDrvs.map)
|
||||
for (auto & i : drv.inputDrvs)
|
||||
av_push(inputDrvs, newSVpv(store()->printStorePath(i.first).c_str(), 0)); // !!! ignores i->second
|
||||
hv_stores(hash, "inputDrvs", newRV((SV *) inputDrvs));
|
||||
|
||||
|
||||
@@ -134,8 +134,7 @@ void rewriteAggregates(std::map<std::string, nix::JSON> &jobs,
|
||||
auto childDrv = aio.blockOn(store->readDerivation(childDrvPath));
|
||||
job["constituents"].push_back(
|
||||
store->printStorePath(childDrvPath));
|
||||
drv.inputDrvs.map[childDrvPath].value = {
|
||||
childDrv.outputs.begin()->first};
|
||||
drv.inputDrvs[childDrvPath] = {childDrv.outputs.begin()->first};
|
||||
}
|
||||
|
||||
std::string drvName(drvPath.name());
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <lix/libexpr/value-to-json.hh>
|
||||
#include <lix/libstore/derivations.hh>
|
||||
#include <stdint.h>
|
||||
#include <lix/libstore/derived-path-map.hh>
|
||||
#include <lix/libexpr/eval.hh>
|
||||
#include <lix/libexpr/get-drvs.hh>
|
||||
#include <lix/libexpr/nixexpr.hh>
|
||||
@@ -103,9 +102,9 @@ Drv::Drv(std::string &attrPath, nix::EvalState &state, nix::DrvInfo &drvInfo,
|
||||
drvPath = localStore->printStorePath(drvInfo.requireDrvPath(state));
|
||||
|
||||
auto drv = state.aio.blockOn(localStore->readDerivation(drvInfo.requireDrvPath(state)));
|
||||
for (const auto &[inputDrvPath, inputNode] : drv.inputDrvs.map) {
|
||||
for (const auto &[inputDrvPath, inputNode] : drv.inputDrvs) {
|
||||
std::set<std::string> inputDrvOutputs;
|
||||
for (auto &outputName : inputNode.value) {
|
||||
for (auto &outputName : inputNode) {
|
||||
inputDrvOutputs.insert(outputName);
|
||||
}
|
||||
inputDrvs[localStore->printStorePath(inputDrvPath)] = inputDrvOutputs;
|
||||
|
||||
@@ -204,15 +204,11 @@ Derivation makeSimpleDrv(const Store & store) {
|
||||
store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"),
|
||||
};
|
||||
drv.inputDrvs = {
|
||||
.map = {
|
||||
{
|
||||
store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"),
|
||||
{
|
||||
store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"),
|
||||
{
|
||||
.value = {
|
||||
"cat",
|
||||
"dog",
|
||||
},
|
||||
},
|
||||
"cat",
|
||||
"dog",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user