#include #include #include "nix/util/util.hh" #include "nix/util/regex-combinators.hh" #include "nix/store/outputs-spec.hh" #include "nix/store/path-regex.hh" #include "nix/util/strings-inline.hh" namespace nix { bool OutputsSpec::contains(const std::string & outputName) const { return std::visit( overloaded{ [&](const OutputsSpec::All &) { return true; }, [&](const OutputsSpec::Names & outputNames) { return outputNames.count(outputName) > 0; }, }, raw); } static std::string outputSpecRegexStr = regex::either(regex::group(R"(\*)"), regex::group(regex::list(nameRegexStr))); std::optional OutputsSpec::parseOpt(std::string_view s) { static std::regex regex(std::string{outputSpecRegexStr}); std::cmatch match; if (!std::regex_match(s.cbegin(), s.cend(), match, regex)) return std::nullopt; if (match[1].matched) return {OutputsSpec::All{}}; if (match[2].matched) return OutputsSpec::Names{tokenizeString({match[2].first, match[2].second}, ",")}; assert(false); } OutputsSpec OutputsSpec::parse(std::string_view s) { std::optional spec = parseOpt(s); if (!spec) throw Error("invalid outputs specifier '%s'", s); return std::move(*spec); } std::optional> ExtendedOutputsSpec::parseOpt(std::string_view s) { auto found = s.rfind('^'); if (found == std::string::npos) return std::pair{s, ExtendedOutputsSpec::Default{}}; auto specOpt = OutputsSpec::parseOpt(s.substr(found + 1)); if (!specOpt) return std::nullopt; return std::pair{s.substr(0, found), ExtendedOutputsSpec::Explicit{std::move(*specOpt)}}; } std::pair ExtendedOutputsSpec::parse(std::string_view s) { std::optional spec = parseOpt(s); if (!spec) throw Error("invalid extended outputs specifier '%s'", s); return *spec; } std::string OutputsSpec::to_string() const { return std::visit( overloaded{ [&](const OutputsSpec::All &) -> std::string { return "*"; }, [&](const OutputsSpec::Names & outputNames) -> std::string { return concatStringsSep(",", outputNames); }, }, raw); } std::string ExtendedOutputsSpec::to_string() const { return std::visit( overloaded{ [&](const ExtendedOutputsSpec::Default &) -> std::string { return ""; }, [&](const ExtendedOutputsSpec::Explicit & outputSpec) -> std::string { return "^" + outputSpec.to_string(); }, }, raw); } OutputsSpec OutputsSpec::union_(const OutputsSpec & that) const { return std::visit( overloaded{ [&](const OutputsSpec::All &) -> OutputsSpec { return OutputsSpec::All{}; }, [&](const OutputsSpec::Names & theseNames) -> OutputsSpec { return std::visit( overloaded{ [&](const OutputsSpec::All &) -> OutputsSpec { return OutputsSpec::All{}; }, [&](const OutputsSpec::Names & thoseNames) -> OutputsSpec { OutputsSpec::Names ret = theseNames; ret.insert(thoseNames.begin(), thoseNames.end()); return ret; }, }, that.raw); }, }, raw); } bool OutputsSpec::isSubsetOf(const OutputsSpec & that) const { return std::visit( overloaded{ [&](const OutputsSpec::All &) { return true; }, [&](const OutputsSpec::Names & thoseNames) { return std::visit( overloaded{ [&](const OutputsSpec::All &) { return false; }, [&](const OutputsSpec::Names & theseNames) { bool ret = true; for (auto & o : theseNames) if (thoseNames.count(o) == 0) ret = false; return ret; }, }, raw); }, }, that.raw); } } // namespace nix namespace nlohmann { using namespace nix; #ifndef DOXYGEN_SKIP OutputsSpec adl_serializer::from_json(const json & json) { auto names = json.get(); if (names == StringSet({"*"})) return OutputsSpec::All{}; else return OutputsSpec::Names{std::move(names)}; } void adl_serializer::to_json(json & json, OutputsSpec t) { std::visit( overloaded{ [&](const OutputsSpec::All &) { json = std::vector({"*"}); }, [&](const OutputsSpec::Names & names) { json = names; }, }, t.raw); } ExtendedOutputsSpec adl_serializer::from_json(const json & json) { if (json.is_null()) return ExtendedOutputsSpec::Default{}; else { return ExtendedOutputsSpec::Explicit{json.get()}; } } void adl_serializer::to_json(json & json, ExtendedOutputsSpec t) { std::visit( overloaded{ [&](const ExtendedOutputsSpec::Default &) { json = nullptr; }, [&](const ExtendedOutputsSpec::Explicit & e) { adl_serializer::to_json(json, e); }, }, t.raw); } #endif } // namespace nlohmann