From a8f45b5e5a42daa9bdee640255464d4dbb431352 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 11 Jan 2023 01:51:14 -0500 Subject: [PATCH] Improve `OutputsSpec` slightly A few little changes preparing for the rest. --- src/libcmd/installables.cc | 3 ++- src/libexpr/flake/flakeref.cc | 2 +- src/libstore/outputs-spec.cc | 26 ++++++++++++++------------ src/libstore/outputs-spec.hh | 26 +++++++++++++++++++------- src/libstore/path-with-outputs.hh | 1 - src/libstore/tests/outputs-spec.cc | 14 +++++++------- src/nix/profile.cc | 6 +++--- 7 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index c0db2a715..ce40986d0 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -1,5 +1,6 @@ #include "globals.hh" #include "installables.hh" +#include "outputs-spec.hh" #include "util.hh" #include "command.hh" #include "attr-path.hh" @@ -796,7 +797,7 @@ std::vector> SourceExprCommand::parseInstallables( } for (auto & s : ss) { - auto [prefix, outputsSpec] = parseOutputsSpec(s); + auto [prefix, outputsSpec] = OutputsSpec::parse(s); result.push_back( std::make_shared( state, *this, vFile, diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc index eede493f8..cfa279fb4 100644 --- a/src/libexpr/flake/flakeref.cc +++ b/src/libexpr/flake/flakeref.cc @@ -244,7 +244,7 @@ std::tuple parseFlakeRefWithFragmentAndOutpu bool allowMissing, bool isFlake) { - auto [prefix, outputsSpec] = parseOutputsSpec(url); + auto [prefix, outputsSpec] = OutputsSpec::parse(url); auto [flakeRef, fragment] = parseFlakeRefWithFragment(prefix, baseDir, allowMissing, isFlake); return {std::move(flakeRef), fragment, outputsSpec}; } diff --git a/src/libstore/outputs-spec.cc b/src/libstore/outputs-spec.cc index 76779d193..b5ea7e325 100644 --- a/src/libstore/outputs-spec.cc +++ b/src/libstore/outputs-spec.cc @@ -1,3 +1,4 @@ +#include "util.hh" #include "outputs-spec.hh" #include "nlohmann/json.hpp" @@ -5,7 +6,7 @@ namespace nix { -std::pair parseOutputsSpec(const std::string & s) +std::pair OutputsSpec::parse(std::string s) { static std::regex regex(R"((.*)\^((\*)|([a-z]+(,[a-z]+)*)))"); @@ -19,18 +20,19 @@ std::pair parseOutputsSpec(const std::string & s) return {match[1], tokenizeString(match[4].str(), ",")}; } -std::string printOutputsSpec(const OutputsSpec & outputsSpec) +std::string OutputsSpec::to_string() const { - if (std::get_if(&outputsSpec)) - return ""; - - if (std::get_if(&outputsSpec)) - return "^*"; - - if (auto outputNames = std::get_if(&outputsSpec)) - return "^" + concatStringsSep(",", *outputNames); - - assert(false); + return std::visit(overloaded { + [&](const OutputsSpec::Default &) -> std::string { + return ""; + }, + [&](const OutputsSpec::All &) -> std::string { + return "*"; + }, + [&](const OutputsSpec::Names & outputNames) -> std::string { + return "^" + concatStringsSep(",", outputNames); + }, + }, raw()); } void to_json(nlohmann::json & json, const OutputsSpec & outputsSpec) diff --git a/src/libstore/outputs-spec.hh b/src/libstore/outputs-spec.hh index e2cf1d12b..6f886ccb6 100644 --- a/src/libstore/outputs-spec.hh +++ b/src/libstore/outputs-spec.hh @@ -1,9 +1,8 @@ #pragma once +#include #include -#include "util.hh" - #include "nlohmann/json_fwd.hpp" namespace nix { @@ -18,13 +17,26 @@ struct DefaultOutputs { bool operator < (const DefaultOutputs & _) const { return false; } }; -typedef std::variant OutputsSpec; +typedef std::variant _OutputsSpecRaw; -/* Parse a string of the form 'prefix^output1,...outputN' or - 'prefix^*', returning the prefix and the outputs spec. */ -std::pair parseOutputsSpec(const std::string & s); +struct OutputsSpec : _OutputsSpecRaw { + using Raw = _OutputsSpecRaw; + using Raw::Raw; -std::string printOutputsSpec(const OutputsSpec & outputsSpec); + using Names = OutputNames; + using All = AllOutputs; + using Default = DefaultOutputs; + + inline const Raw & raw() const { + return static_cast(*this); + } + + /* Parse a string of the form 'prefix^output1,...outputN' or + 'prefix^*', returning the prefix and the outputs spec. */ + static std::pair parse(std::string s); + + std::string to_string() const; +}; void to_json(nlohmann::json &, const OutputsSpec &); void from_json(const nlohmann::json &, OutputsSpec &); diff --git a/src/libstore/path-with-outputs.hh b/src/libstore/path-with-outputs.hh index ed55cc333..5d25656a5 100644 --- a/src/libstore/path-with-outputs.hh +++ b/src/libstore/path-with-outputs.hh @@ -2,7 +2,6 @@ #include "path.hh" #include "derived-path.hh" -#include "nlohmann/json_fwd.hpp" namespace nix { diff --git a/src/libstore/tests/outputs-spec.cc b/src/libstore/tests/outputs-spec.cc index d781a930e..552380837 100644 --- a/src/libstore/tests/outputs-spec.cc +++ b/src/libstore/tests/outputs-spec.cc @@ -4,40 +4,40 @@ namespace nix { -TEST(parseOutputsSpec, basic) +TEST(OutputsSpec_parse, basic) { { - auto [prefix, outputsSpec] = parseOutputsSpec("foo"); + auto [prefix, outputsSpec] = OutputsSpec::parse("foo"); ASSERT_EQ(prefix, "foo"); ASSERT_TRUE(std::get_if(&outputsSpec)); } { - auto [prefix, outputsSpec] = parseOutputsSpec("foo^*"); + auto [prefix, outputsSpec] = OutputsSpec::parse("foo^*"); ASSERT_EQ(prefix, "foo"); ASSERT_TRUE(std::get_if(&outputsSpec)); } { - auto [prefix, outputsSpec] = parseOutputsSpec("foo^out"); + auto [prefix, outputsSpec] = OutputsSpec::parse("foo^out"); ASSERT_EQ(prefix, "foo"); ASSERT_TRUE(std::get(outputsSpec) == OutputNames({"out"})); } { - auto [prefix, outputsSpec] = parseOutputsSpec("foo^out,bin"); + auto [prefix, outputsSpec] = OutputsSpec::parse("foo^out,bin"); ASSERT_EQ(prefix, "foo"); ASSERT_TRUE(std::get(outputsSpec) == OutputNames({"out", "bin"})); } { - auto [prefix, outputsSpec] = parseOutputsSpec("foo^bar^out,bin"); + auto [prefix, outputsSpec] = OutputsSpec::parse("foo^bar^out,bin"); ASSERT_EQ(prefix, "foo^bar"); ASSERT_TRUE(std::get(outputsSpec) == OutputNames({"out", "bin"})); } { - auto [prefix, outputsSpec] = parseOutputsSpec("foo^&*()"); + auto [prefix, outputsSpec] = OutputsSpec::parse("foo^&*()"); ASSERT_EQ(prefix, "foo^&*()"); ASSERT_TRUE(std::get_if(&outputsSpec)); } diff --git a/src/nix/profile.cc b/src/nix/profile.cc index 22ee51ab9..346c4e117 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -44,7 +44,7 @@ struct ProfileElement std::string describe() const { if (source) - return fmt("%s#%s%s", source->originalRef, source->attrPath, printOutputsSpec(source->outputs)); + return fmt("%s#%s%s", source->originalRef, source->attrPath, source->outputs.to_string()); StringSet names; for (auto & path : storePaths) names.insert(DrvName(path.name()).name); @@ -553,8 +553,8 @@ struct CmdProfileList : virtual EvalCommand, virtual StoreCommand, MixDefaultPro for (size_t i = 0; i < manifest.elements.size(); ++i) { auto & element(manifest.elements[i]); logger->cout("%d %s %s %s", i, - element.source ? element.source->originalRef.to_string() + "#" + element.source->attrPath + printOutputsSpec(element.source->outputs) : "-", - element.source ? element.source->resolvedRef.to_string() + "#" + element.source->attrPath + printOutputsSpec(element.source->outputs) : "-", + element.source ? element.source->originalRef.to_string() + "#" + element.source->attrPath + element.source->outputs.to_string() : "-", + element.source ? element.source->resolvedRef.to_string() + "#" + element.source->attrPath + element.source->outputs.to_string() : "-", concatStringsSep(" ", store->printStorePathSet(element.storePaths))); } }