forked from lix-project/lix
7ad66cb3ef
We use the same nested map representation we used for goals, again in order to save space. We might someday want to combine with `inputDrvs`, by doing `V = bool` instead of `V = std::set<OutputName>`, but we are not doing that yet for sake of a smaller diff. The ATerm format for Derivations also needs to be extended, in addition to the in-memory format. To accomodate this, we added a new basic versioning scheme, so old versions of Nix will get nice errors. (And going forward, if the ATerm format changes again the errors will be even better.) `parsedStrings`, an internal function used as part of parsing derivations in A-Term format, used to consume the final `]` but expect the initial `[` to already be consumed. This made for what looked like unbalanced brackets at callsites, which was confusing. Now it consumes both which is hopefully less confusing. As part of testing, we also created a unit test for the A-Term format for regular non-experimental derivations too. Co-authored-by: Robert Hensing <roberth@users.noreply.github.com> Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io> Apply suggestions from code review Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
149 lines
4.6 KiB
C++
149 lines
4.6 KiB
C++
#include "built-path.hh"
|
||
#include "derivations.hh"
|
||
#include "store-api.hh"
|
||
|
||
#include <nlohmann/json.hpp>
|
||
|
||
#include <optional>
|
||
|
||
namespace nix {
|
||
|
||
#define CMP_ONE(CHILD_TYPE, MY_TYPE, FIELD, COMPARATOR) \
|
||
bool MY_TYPE ::operator COMPARATOR (const MY_TYPE & other) const \
|
||
{ \
|
||
const MY_TYPE* me = this; \
|
||
auto fields1 = std::make_tuple<const CHILD_TYPE &, const FIELD_TYPE &>(*me->drvPath, me->FIELD); \
|
||
me = &other; \
|
||
auto fields2 = std::make_tuple<const CHILD_TYPE &, const FIELD_TYPE &>(*me->drvPath, me->FIELD); \
|
||
return fields1 COMPARATOR fields2; \
|
||
}
|
||
#define CMP(CHILD_TYPE, MY_TYPE, FIELD) \
|
||
CMP_ONE(CHILD_TYPE, MY_TYPE, FIELD, ==) \
|
||
CMP_ONE(CHILD_TYPE, MY_TYPE, FIELD, !=) \
|
||
CMP_ONE(CHILD_TYPE, MY_TYPE, FIELD, <)
|
||
|
||
#define FIELD_TYPE std::pair<std::string, StorePath>
|
||
CMP(SingleBuiltPath, SingleBuiltPathBuilt, output)
|
||
#undef FIELD_TYPE
|
||
|
||
#define FIELD_TYPE std::map<std::string, StorePath>
|
||
CMP(SingleBuiltPath, BuiltPathBuilt, outputs)
|
||
#undef FIELD_TYPE
|
||
|
||
#undef CMP
|
||
#undef CMP_ONE
|
||
|
||
StorePath SingleBuiltPath::outPath() const
|
||
{
|
||
return std::visit(
|
||
overloaded{
|
||
[](const SingleBuiltPath::Opaque & p) { return p.path; },
|
||
[](const SingleBuiltPath::Built & b) { return b.output.second; },
|
||
}, raw()
|
||
);
|
||
}
|
||
|
||
StorePathSet BuiltPath::outPaths() const
|
||
{
|
||
return std::visit(
|
||
overloaded{
|
||
[](const BuiltPath::Opaque & p) { return StorePathSet{p.path}; },
|
||
[](const BuiltPath::Built & b) {
|
||
StorePathSet res;
|
||
for (auto & [_, path] : b.outputs)
|
||
res.insert(path);
|
||
return res;
|
||
},
|
||
}, raw()
|
||
);
|
||
}
|
||
|
||
SingleDerivedPath::Built SingleBuiltPath::Built::discardOutputPath() const
|
||
{
|
||
return SingleDerivedPath::Built {
|
||
.drvPath = make_ref<SingleDerivedPath>(drvPath->discardOutputPath()),
|
||
.output = output.first,
|
||
};
|
||
}
|
||
|
||
SingleDerivedPath SingleBuiltPath::discardOutputPath() const
|
||
{
|
||
return std::visit(
|
||
overloaded{
|
||
[](const SingleBuiltPath::Opaque & p) -> SingleDerivedPath {
|
||
return p;
|
||
},
|
||
[](const SingleBuiltPath::Built & b) -> SingleDerivedPath {
|
||
return b.discardOutputPath();
|
||
},
|
||
}, raw()
|
||
);
|
||
}
|
||
|
||
nlohmann::json BuiltPath::Built::toJSON(const Store & store) const
|
||
{
|
||
nlohmann::json res;
|
||
res["drvPath"] = drvPath->toJSON(store);
|
||
for (const auto & [outputName, outputPath] : outputs) {
|
||
res["outputs"][outputName] = store.printStorePath(outputPath);
|
||
}
|
||
return res;
|
||
}
|
||
|
||
nlohmann::json SingleBuiltPath::Built::toJSON(const Store & store) const
|
||
{
|
||
nlohmann::json res;
|
||
res["drvPath"] = drvPath->toJSON(store);
|
||
auto & [outputName, outputPath] = output;
|
||
res["output"] = outputName;
|
||
res["outputPath"] = store.printStorePath(outputPath);
|
||
return res;
|
||
}
|
||
|
||
nlohmann::json SingleBuiltPath::toJSON(const Store & store) const
|
||
{
|
||
return std::visit([&](const auto & buildable) {
|
||
return buildable.toJSON(store);
|
||
}, raw());
|
||
}
|
||
|
||
nlohmann::json BuiltPath::toJSON(const Store & store) const
|
||
{
|
||
return std::visit([&](const auto & buildable) {
|
||
return buildable.toJSON(store);
|
||
}, raw());
|
||
}
|
||
|
||
RealisedPath::Set BuiltPath::toRealisedPaths(Store & store) const
|
||
{
|
||
RealisedPath::Set res;
|
||
std::visit(
|
||
overloaded{
|
||
[&](const BuiltPath::Opaque & p) { res.insert(p.path); },
|
||
[&](const BuiltPath::Built & p) {
|
||
auto drvHashes =
|
||
staticOutputHashes(store, store.readDerivation(p.drvPath->outPath()));
|
||
for (auto& [outputName, outputPath] : p.outputs) {
|
||
if (experimentalFeatureSettings.isEnabled(
|
||
Xp::CaDerivations)) {
|
||
auto drvOutput = get(drvHashes, outputName);
|
||
if (!drvOutput)
|
||
throw Error(
|
||
"the derivation '%s' has unrealised output '%s' (derived-path.cc/toRealisedPaths)",
|
||
store.printStorePath(p.drvPath->outPath()), outputName);
|
||
auto thisRealisation = store.queryRealisation(
|
||
DrvOutput{*drvOutput, outputName});
|
||
assert(thisRealisation); // We’ve built it, so we must
|
||
// have the realisation
|
||
res.insert(*thisRealisation);
|
||
} else {
|
||
res.insert(outputPath);
|
||
}
|
||
}
|
||
},
|
||
},
|
||
raw());
|
||
return res;
|
||
}
|
||
|
||
}
|