Remove default constructor from OutputsSpec

This forces us to be explicit.

It also requires to rework how `from_json` works. A `JSON_IMPL` is added
to assist with this.
This commit is contained in:
John Ericson 2023-01-11 16:32:30 -05:00
parent 114a6e2b09
commit 5ba6e5d0d9
12 changed files with 103 additions and 49 deletions

View file

@ -827,7 +827,7 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
return storePath.isDerivation() return storePath.isDerivation()
? (DerivedPath) DerivedPath::Built { ? (DerivedPath) DerivedPath::Built {
.drvPath = std::move(storePath), .drvPath = std::move(storePath),
.outputs = {}, .outputs = OutputsSpec::All {},
} }
: (DerivedPath) DerivedPath::Opaque { : (DerivedPath) DerivedPath::Opaque {
.path = std::move(storePath), .path = std::move(storePath),

View file

@ -641,7 +641,12 @@ bool NixRepl::processLine(std::string line)
Path drvPathRaw = state->store->printStorePath(drvPath); Path drvPathRaw = state->store->printStorePath(drvPath);
if (command == ":b" || command == ":bl") { if (command == ":b" || command == ":bl") {
state->store->buildPaths({DerivedPath::Built{drvPath}}); state->store->buildPaths({
DerivedPath::Built {
.drvPath = drvPath,
.outputs = OutputsSpec::All { },
},
});
auto drv = state->store->readDerivation(drvPath); auto drv = state->store->readDerivation(drvPath);
logger->cout("\nThis derivation produced the following outputs:"); logger->cout("\nThis derivation produced the following outputs:");
for (auto & [outputName, outputPath] : state->store->queryDerivationOutputMap(drvPath)) { for (auto & [outputName, outputPath] : state->store->queryDerivationOutputMap(drvPath)) {

View file

@ -80,7 +80,7 @@ BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivat
BuildMode buildMode) BuildMode buildMode)
{ {
Worker worker(*this, *this); Worker worker(*this, *this);
auto goal = worker.makeBasicDerivationGoal(drvPath, drv, {}, buildMode); auto goal = worker.makeBasicDerivationGoal(drvPath, drv, OutputsSpec::All {}, buildMode);
try { try {
worker.run(Goals{goal}); worker.run(Goals{goal});
@ -89,7 +89,10 @@ BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivat
return BuildResult { return BuildResult {
.status = BuildResult::MiscFailure, .status = BuildResult::MiscFailure,
.errorMsg = e.msg(), .errorMsg = e.msg(),
.path = DerivedPath::Built { .drvPath = drvPath }, .path = DerivedPath::Built {
.drvPath = drvPath,
.outputs = OutputsSpec::All { },
},
}; };
}; };
} }

View file

@ -279,7 +279,12 @@ public:
conn->to.flush(); conn->to.flush();
BuildResult status { .path = DerivedPath::Built { .drvPath = drvPath } }; BuildResult status {
.path = DerivedPath::Built {
.drvPath = drvPath,
.outputs = OutputsSpec::All { },
},
};
status.status = (BuildResult::Status) readInt(conn->from); status.status = (BuildResult::Status) readInt(conn->from);
conn->from >> status.errorMsg; conn->from >> status.errorMsg;

View file

@ -110,9 +110,21 @@ bool OutputsSpec::merge(const OutputsSpec & that)
}, raw()); }, raw());
} }
}
void to_json(nlohmann::json & json, const OutputsSpec & outputsSpec) namespace nlohmann {
{
using namespace nix;
OutputsSpec adl_serializer<OutputsSpec>::from_json(const json & json) {
auto names = json.get<StringSet>();
if (names == StringSet({"*"}))
return OutputsSpec::All {};
else
return OutputsSpec::Names { std::move(names) };
}
void adl_serializer<OutputsSpec>::to_json(json & json, OutputsSpec t) {
std::visit(overloaded { std::visit(overloaded {
[&](const OutputsSpec::All &) { [&](const OutputsSpec::All &) {
json = std::vector<std::string>({"*"}); json = std::vector<std::string>({"*"});
@ -120,40 +132,27 @@ void to_json(nlohmann::json & json, const OutputsSpec & outputsSpec)
[&](const OutputsSpec::Names & names) { [&](const OutputsSpec::Names & names) {
json = names; json = names;
}, },
}, outputsSpec); }, t);
} }
void to_json(nlohmann::json & json, const ExtendedOutputsSpec & extendedOutputsSpec) ExtendedOutputsSpec adl_serializer<ExtendedOutputsSpec>::from_json(const json & json) {
{ if (json.is_null())
return ExtendedOutputsSpec::Default {};
else {
return ExtendedOutputsSpec::Explicit { json.get<OutputsSpec>() };
}
}
void adl_serializer<ExtendedOutputsSpec>::to_json(json & json, ExtendedOutputsSpec t) {
std::visit(overloaded { std::visit(overloaded {
[&](const ExtendedOutputsSpec::Default &) { [&](const ExtendedOutputsSpec::Default &) {
json = nullptr; json = nullptr;
}, },
[&](const ExtendedOutputsSpec::Explicit & e) { [&](const ExtendedOutputsSpec::Explicit & e) {
to_json(json, e); adl_serializer<OutputsSpec>::to_json(json, e);
}, },
}, extendedOutputsSpec); }, t);
}
void from_json(const nlohmann::json & json, OutputsSpec & outputsSpec)
{
auto names = json.get<StringSet>();
if (names == StringSet({"*"}))
outputsSpec = OutputsSpec::All {};
else
outputsSpec = OutputsSpec::Names { std::move(names) };
}
void from_json(const nlohmann::json & json, ExtendedOutputsSpec & extendedOutputsSpec)
{
if (json.is_null())
extendedOutputsSpec = ExtendedOutputsSpec::Default {};
else {
extendedOutputsSpec = ExtendedOutputsSpec::Explicit { json.get<OutputsSpec>() };
}
} }
} }

View file

@ -4,7 +4,7 @@
#include <set> #include <set>
#include <variant> #include <variant>
#include "nlohmann/json_fwd.hpp" #include "json-impls.hh"
namespace nix { namespace nix {
@ -35,6 +35,9 @@ struct OutputsSpec : _OutputsSpecRaw {
using Raw = _OutputsSpecRaw; using Raw = _OutputsSpecRaw;
using Raw::Raw; using Raw::Raw;
/* Force choosing a variant */
OutputsSpec() = delete;
using Names = OutputNames; using Names = OutputNames;
using All = AllOutputs; using All = AllOutputs;
@ -85,11 +88,7 @@ struct ExtendedOutputsSpec : _ExtendedOutputsSpecRaw {
std::string to_string() const; std::string to_string() const;
}; };
void to_json(nlohmann::json &, const OutputsSpec &);
void from_json(const nlohmann::json &, OutputsSpec &);
void to_json(nlohmann::json &, const ExtendedOutputsSpec &);
void from_json(const nlohmann::json &, ExtendedOutputsSpec &);
} }
JSON_IMPL(OutputsSpec)
JSON_IMPL(ExtendedOutputsSpec)

View file

@ -910,7 +910,12 @@ BuildResult RemoteStore::buildDerivation(const StorePath & drvPath, const BasicD
writeDerivation(conn->to, *this, drv); writeDerivation(conn->to, *this, drv);
conn->to << buildMode; conn->to << buildMode;
conn.processStderr(); conn.processStderr();
BuildResult res { .path = DerivedPath::Built { .drvPath = drvPath } }; BuildResult res {
.path = DerivedPath::Built {
.drvPath = drvPath,
.outputs = OutputsSpec::All { },
},
};
res.status = (BuildResult::Status) readInt(conn->from); res.status = (BuildResult::Status) readInt(conn->from);
conn->from >> res.errorMsg; conn->from >> res.errorMsg;
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 29) { if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 29) {

14
src/libutil/json-impls.hh Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include "nlohmann/json_fwd.hpp"
// Following https://github.com/nlohmann/json#how-can-i-use-get-for-non-default-constructiblenon-copyable-types
#define JSON_IMPL(TYPE) \
namespace nlohmann { \
using namespace nix; \
template <> \
struct adl_serializer<TYPE> { \
static TYPE from_json(const json & json); \
static void to_json(json & json, TYPE t); \
}; \
}

View file

@ -478,9 +478,14 @@ static void printMissing(EvalState & state, DrvInfos & elems)
std::vector<DerivedPath> targets; std::vector<DerivedPath> targets;
for (auto & i : elems) for (auto & i : elems)
if (auto drvPath = i.queryDrvPath()) if (auto drvPath = i.queryDrvPath())
targets.push_back(DerivedPath::Built{*drvPath}); targets.push_back(DerivedPath::Built{
.drvPath = *drvPath,
.outputs = OutputsSpec::All { },
});
else else
targets.push_back(DerivedPath::Opaque{i.queryOutPath()}); targets.push_back(DerivedPath::Opaque{
.path = i.queryOutPath(),
});
printMissing(state.store, targets); printMissing(state.store, targets);
} }
@ -751,8 +756,13 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
auto drvPath = drv.queryDrvPath(); auto drvPath = drv.queryDrvPath();
std::vector<DerivedPath> paths { std::vector<DerivedPath> paths {
drvPath drvPath
? (DerivedPath) (DerivedPath::Built { *drvPath }) ? (DerivedPath) (DerivedPath::Built {
: (DerivedPath) (DerivedPath::Opaque { drv.queryOutPath() }), .drvPath = *drvPath,
.outputs = OutputsSpec::All { },
})
: (DerivedPath) (DerivedPath::Opaque {
.path = drv.queryOutPath(),
}),
}; };
printMissing(globals.state->store, paths); printMissing(globals.state->store, paths);
if (globals.dryRun) return; if (globals.dryRun) return;

View file

@ -105,7 +105,12 @@ struct CmdBundle : InstallableCommand
auto outPath = evalState->coerceToStorePath(attr2->pos, *attr2->value, context2, ""); auto outPath = evalState->coerceToStorePath(attr2->pos, *attr2->value, context2, "");
store->buildPaths({ DerivedPath::Built { drvPath } }); store->buildPaths({
DerivedPath::Built {
.drvPath = drvPath,
.outputs = OutputsSpec::All { },
},
});
auto outPathS = store->printStorePath(outPath); auto outPathS = store->printStorePath(outPath);

View file

@ -232,7 +232,12 @@ static StorePath getDerivationEnvironment(ref<Store> store, ref<Store> evalStore
auto shellDrvPath = writeDerivation(*evalStore, drv); auto shellDrvPath = writeDerivation(*evalStore, drv);
/* Build the derivation. */ /* Build the derivation. */
store->buildPaths({DerivedPath::Built{shellDrvPath}}, bmNormal, evalStore); store->buildPaths(
{ DerivedPath::Built {
.drvPath = shellDrvPath,
.outputs = OutputsSpec::All { },
}},
bmNormal, evalStore);
for (auto & [_0, optPath] : evalStore->queryPartialDerivationOutputMap(shellDrvPath)) { for (auto & [_0, optPath] : evalStore->queryPartialDerivationOutputMap(shellDrvPath)) {
assert(optPath); assert(optPath);

View file

@ -513,8 +513,12 @@ struct CmdFlakeCheck : FlakeCommand
auto drvPath = checkDerivation( auto drvPath = checkDerivation(
fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]), fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]),
*attr2.value, attr2.pos); *attr2.value, attr2.pos);
if (drvPath && attr_name == settings.thisSystem.get()) if (drvPath && attr_name == settings.thisSystem.get()) {
drvPaths.push_back(DerivedPath::Built{*drvPath}); drvPaths.push_back(DerivedPath::Built {
.drvPath = *drvPath,
.outputs = OutputsSpec::All { },
});
}
} }
} }
} }