diff options
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/experimental-features.cc | 10 | ||||
-rw-r--r-- | src/libutil/experimental-features.hh | 4 | ||||
-rw-r--r-- | src/libutil/git.cc | 25 | ||||
-rw-r--r-- | src/libutil/git.hh | 40 | ||||
-rw-r--r-- | src/libutil/json-utils.hh | 21 | ||||
-rw-r--r-- | src/libutil/tests/git.cc | 33 | ||||
-rw-r--r-- | src/libutil/tests/tests.cc | 20 | ||||
-rw-r--r-- | src/libutil/util.cc | 1 | ||||
-rw-r--r-- | src/libutil/util.hh | 24 |
9 files changed, 167 insertions, 11 deletions
diff --git a/src/libutil/experimental-features.cc b/src/libutil/experimental-features.cc index df37edf57..315de64a4 100644 --- a/src/libutil/experimental-features.cc +++ b/src/libutil/experimental-features.cc @@ -35,7 +35,9 @@ const std::optional<ExperimentalFeature> parseExperimentalFeature(const std::str std::string_view showExperimentalFeature(const ExperimentalFeature feature) { - return stringifiedXpFeatures.at(feature); + const auto ret = get(stringifiedXpFeatures, feature); + assert(ret); + return *ret; } std::set<ExperimentalFeature> parseFeatures(const std::set<std::string> & rawFeatures) @@ -58,11 +60,13 @@ std::ostream & operator <<(std::ostream & str, const ExperimentalFeature & featu return str << showExperimentalFeature(feature); } -void to_json(nlohmann::json& j, const ExperimentalFeature& feature) { +void to_json(nlohmann::json & j, const ExperimentalFeature & feature) +{ j = showExperimentalFeature(feature); } -void from_json(const nlohmann::json& j, ExperimentalFeature& feature) { +void from_json(const nlohmann::json & j, ExperimentalFeature & feature) +{ const std::string input = j; const auto parsed = parseExperimentalFeature(input); diff --git a/src/libutil/experimental-features.hh b/src/libutil/experimental-features.hh index a6d080094..57512830c 100644 --- a/src/libutil/experimental-features.hh +++ b/src/libutil/experimental-features.hh @@ -55,7 +55,7 @@ public: * Semi-magic conversion to and from json. * See the nlohmann/json readme for more details. */ -void to_json(nlohmann::json&, const ExperimentalFeature&); -void from_json(const nlohmann::json&, ExperimentalFeature&); +void to_json(nlohmann::json &, const ExperimentalFeature &); +void from_json(const nlohmann::json &, ExperimentalFeature &); } diff --git a/src/libutil/git.cc b/src/libutil/git.cc new file mode 100644 index 000000000..f35c2fdb7 --- /dev/null +++ b/src/libutil/git.cc @@ -0,0 +1,25 @@ +#include "git.hh" + +#include <regex> + +namespace nix { +namespace git { + +std::optional<LsRemoteRefLine> parseLsRemoteLine(std::string_view line) +{ + const static std::regex line_regex("^(ref: *)?([^\\s]+)(?:\\t+(.*))?$"); + std::match_results<std::string_view::const_iterator> match; + if (!std::regex_match(line.cbegin(), line.cend(), match, line_regex)) + return std::nullopt; + + return LsRemoteRefLine { + .kind = match[1].length() == 0 + ? LsRemoteRefLine::Kind::Object + : LsRemoteRefLine::Kind::Symbolic, + .target = match[2], + .reference = match[3].length() == 0 ? std::nullopt : std::optional<std::string>{ match[3] } + }; +} + +} +} diff --git a/src/libutil/git.hh b/src/libutil/git.hh new file mode 100644 index 000000000..cb13ef0e5 --- /dev/null +++ b/src/libutil/git.hh @@ -0,0 +1,40 @@ +#pragma once + +#include <string> +#include <string_view> +#include <optional> + +namespace nix { + +namespace git { + +// A line from the output of `git ls-remote --symref`. +// +// These can be of two kinds: +// +// - Symbolic references of the form +// +// ref: {target} {reference} +// +// where {target} is itself a reference and {reference} is optional +// +// - Object references of the form +// +// {target} {reference} +// +// where {target} is a commit id and {reference} is mandatory +struct LsRemoteRefLine { + enum struct Kind { + Symbolic, + Object + }; + Kind kind; + std::string target; + std::optional<std::string> reference; +}; + +std::optional<LsRemoteRefLine> parseLsRemoteLine(std::string_view line); + +} + +} diff --git a/src/libutil/json-utils.hh b/src/libutil/json-utils.hh new file mode 100644 index 000000000..b8a031227 --- /dev/null +++ b/src/libutil/json-utils.hh @@ -0,0 +1,21 @@ +#pragma once + +#include <nlohmann/json.hpp> + +namespace nix { + +const nlohmann::json * get(const nlohmann::json & map, const std::string & key) +{ + auto i = map.find(key); + if (i == map.end()) return nullptr; + return &*i; +} + +nlohmann::json * get(nlohmann::json & map, const std::string & key) +{ + auto i = map.find(key); + if (i == map.end()) return nullptr; + return &*i; +} + +} diff --git a/src/libutil/tests/git.cc b/src/libutil/tests/git.cc new file mode 100644 index 000000000..5b5715fc2 --- /dev/null +++ b/src/libutil/tests/git.cc @@ -0,0 +1,33 @@ +#include "git.hh" +#include <gtest/gtest.h> + +namespace nix { + + TEST(GitLsRemote, parseSymrefLineWithReference) { + auto line = "ref: refs/head/main HEAD"; + auto res = git::parseLsRemoteLine(line); + ASSERT_TRUE(res.has_value()); + ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Symbolic); + ASSERT_EQ(res->target, "refs/head/main"); + ASSERT_EQ(res->reference, "HEAD"); + } + + TEST(GitLsRemote, parseSymrefLineWithNoReference) { + auto line = "ref: refs/head/main"; + auto res = git::parseLsRemoteLine(line); + ASSERT_TRUE(res.has_value()); + ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Symbolic); + ASSERT_EQ(res->target, "refs/head/main"); + ASSERT_EQ(res->reference, std::nullopt); + } + + TEST(GitLsRemote, parseObjectRefLine) { + auto line = "abc123 refs/head/main"; + auto res = git::parseLsRemoteLine(line); + ASSERT_TRUE(res.has_value()); + ASSERT_EQ(res->kind, git::LsRemoteRefLine::Kind::Object); + ASSERT_EQ(res->target, "abc123"); + ASSERT_EQ(res->reference, "refs/head/main"); + } +} + diff --git a/src/libutil/tests/tests.cc b/src/libutil/tests/tests.cc index 92972ed14..6e325db98 100644 --- a/src/libutil/tests/tests.cc +++ b/src/libutil/tests/tests.cc @@ -548,7 +548,7 @@ namespace nix { TEST(get, emptyContainer) { StringMap s = { }; - auto expected = std::nullopt; + auto expected = nullptr; ASSERT_EQ(get(s, "one"), expected); } @@ -559,7 +559,23 @@ namespace nix { s["two"] = "er"; auto expected = "yi"; - ASSERT_EQ(get(s, "one"), expected); + ASSERT_EQ(*get(s, "one"), expected); + } + + TEST(getOr, emptyContainer) { + StringMap s = { }; + auto expected = "yi"; + + ASSERT_EQ(getOr(s, "one", "yi"), expected); + } + + TEST(getOr, getFromContainer) { + StringMap s; + s["one"] = "yi"; + s["two"] = "er"; + auto expected = "yi"; + + ASSERT_EQ(getOr(s, "one", "nope"), expected); } /* ---------------------------------------------------------------------------- diff --git a/src/libutil/util.cc b/src/libutil/util.cc index b49c1e466..d4d78329d 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1588,7 +1588,6 @@ std::string stripIndentation(std::string_view s) ////////////////////////////////////////////////////////////////////// - static Sync<std::pair<unsigned short, unsigned short>> windowSize{{0, 0}}; diff --git a/src/libutil/util.hh b/src/libutil/util.hh index a1d0e0e6b..09ccfa591 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -543,13 +543,31 @@ std::string stripIndentation(std::string_view s); /* Get a value for the specified key from an associate container. */ template <class T> -std::optional<typename T::mapped_type> get(const T & map, const typename T::key_type & key) +const typename T::mapped_type * get(const T & map, const typename T::key_type & key) { auto i = map.find(key); - if (i == map.end()) return {}; - return std::optional<typename T::mapped_type>(i->second); + if (i == map.end()) return nullptr; + return &i->second; } +template <class T> +typename T::mapped_type * get(T & map, const typename T::key_type & key) +{ + auto i = map.find(key); + if (i == map.end()) return nullptr; + return &i->second; +} + +/* Get a value for the specified key from an associate container, or a default value if the key isn't present. */ +template <class T> +const typename T::mapped_type & getOr(T & map, + const typename T::key_type & key, + const typename T::mapped_type & defaultValue) +{ + auto i = map.find(key); + if (i == map.end()) return defaultValue; + return i->second; +} /* Remove and return the first item from a container. */ template <class T> |