aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRebecca Turner <rbt@sent.as>2024-03-09 14:00:43 -0800
committerRebecca Turner <rbt@sent.as>2024-04-07 18:22:15 -0700
commit6f863e8ccd44342e7650f612b46893b605755000 (patch)
tree349b2f44a3303cd4e9e65db3edd5f17bdfddcce4
parent06e11778b594931b24d256a0a68ccea6533c6b48 (diff)
Add `PathsSetting`
Change-Id: I1165f6ef033a5f757ca3716d3f8008ba36b01fd0
-rw-r--r--src/libutil/config.cc28
-rw-r--r--src/libutil/config.hh20
-rw-r--r--tests/unit/libutil/paths-setting.cc100
-rw-r--r--tests/unit/meson.build1
4 files changed, 149 insertions, 0 deletions
diff --git a/src/libutil/config.cc b/src/libutil/config.cc
index 8e76d6d66..81efcd507 100644
--- a/src/libutil/config.cc
+++ b/src/libutil/config.cc
@@ -437,6 +437,34 @@ void OptionalPathSetting::operator =(const std::optional<Path> & v)
this->assign(v);
}
+PathsSetting::PathsSetting(Config * options,
+ const Paths & def,
+ const std::string & name,
+ const std::string & description,
+ const std::set<std::string> & aliases)
+ : BaseSetting<Paths>(def, true, name, description, aliases)
+{
+ options->addSetting(this);
+}
+
+
+Paths PathsSetting::parse(const std::string & str) const
+{
+ auto strings = tokenizeString<Strings>(str);
+ Paths parsed;
+
+ for (auto str : strings) {
+ parsed.push_back(canonPath(str));
+ }
+
+ return parsed;
+}
+
+PathsSetting::operator bool() const noexcept
+{
+ return !get().empty();
+}
+
bool GlobalConfig::set(const std::string & name, const std::string & value)
{
for (auto & config : *configRegistrations)
diff --git a/src/libutil/config.hh b/src/libutil/config.hh
index 3e232d224..01e1239b3 100644
--- a/src/libutil/config.hh
+++ b/src/libutil/config.hh
@@ -375,6 +375,26 @@ public:
void operator =(const std::optional<Path> & v);
};
+/**
+ * Like `OptionalPathSetting`, but allows multiple paths.
+ */
+class PathsSetting : public BaseSetting<Paths>
+{
+public:
+
+ PathsSetting(Config * options,
+ const Paths & def,
+ const std::string & name,
+ const std::string & description,
+ const std::set<std::string> & aliases = {});
+
+ Paths parse(const std::string & str) const override;
+
+ void operator =(const Paths & v);
+
+ operator bool() const noexcept;
+};
+
struct GlobalConfig : public AbstractConfig
{
typedef std::vector<Config*> ConfigRegistrations;
diff --git a/tests/unit/libutil/paths-setting.cc b/tests/unit/libutil/paths-setting.cc
new file mode 100644
index 000000000..b450b0cf9
--- /dev/null
+++ b/tests/unit/libutil/paths-setting.cc
@@ -0,0 +1,100 @@
+#include "config.hh"
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <sstream>
+
+using testing::Eq;
+
+namespace nix {
+
+class PathsSettingTestConfig : public Config
+{
+public:
+ PathsSettingTestConfig()
+ : Config()
+ { }
+
+ PathsSetting paths{this, Paths(), "paths", "documentation"};
+};
+
+struct PathsSettingTest : public ::testing::Test {
+public:
+ PathsSettingTestConfig mkConfig()
+ {
+ return PathsSettingTestConfig();
+ }
+};
+
+TEST_F(PathsSettingTest, parse) {
+ auto config = mkConfig();
+ // Not an absolute path:
+ ASSERT_THROW(config.paths.parse("puppy.nix"), Error);
+
+ ASSERT_THAT(
+ config.paths.parse("/puppy.nix"),
+ Eq<Paths>({"/puppy.nix"})
+ );
+
+ // Splits on whitespace:
+ ASSERT_THAT(
+ config.paths.parse("/puppy.nix /doggy.nix"),
+ Eq<Paths>({"/puppy.nix", "/doggy.nix"})
+ );
+
+ // Splits on _any_ whitespace:
+ ASSERT_THAT(
+ config.paths.parse("/puppy.nix \t /doggy.nix\n\n\n/borzoi.nix\r/goldie.nix"),
+ Eq<Paths>({"/puppy.nix", "/doggy.nix", "/borzoi.nix", "/goldie.nix"})
+ );
+
+ // Canonicizes paths:
+ ASSERT_THAT(
+ config.paths.parse("/puppy/../doggy.nix"),
+ Eq<Paths>({"/doggy.nix"})
+ );
+}
+
+TEST_F(PathsSettingTest, bool) {
+ auto config = mkConfig();
+ // No paths:
+ ASSERT_FALSE(config.paths);
+ // Set a path:
+ config.set("paths", "/puppy.nix");
+ // Now there are paths:
+ ASSERT_TRUE(config.paths);
+
+ // Multiple paths count too:
+ config.set("paths", "/puppy.nix /doggy.nix");
+ ASSERT_TRUE(config.paths);
+}
+
+TEST_F(PathsSettingTest, append) {
+ auto config = mkConfig();
+
+ ASSERT_TRUE(config.paths.isAppendable());
+
+ // Starts with no paths:
+ ASSERT_THAT(
+ config.paths.get(),
+ Eq<Paths>({})
+ );
+
+ // Can append a path:
+ config.paths.set("/puppy.nix", true);
+
+ ASSERT_THAT(
+ config.paths.get(),
+ Eq<Paths>({"/puppy.nix"})
+ );
+
+ // Can append multiple paths:
+ config.paths.set("/silly.nix /doggy.nix", true);
+
+ ASSERT_THAT(
+ config.paths.get(),
+ Eq<Paths>({"/puppy.nix", "/silly.nix", "/doggy.nix"})
+ );
+}
+
+} // namespace nix
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index 60bb2de89..a05776eca 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -46,6 +46,7 @@ libutil_tests_sources = files(
'libutil/json-utils.cc',
'libutil/logging.cc',
'libutil/lru-cache.cc',
+ 'libutil/paths-setting.cc',
'libutil/pool.cc',
'libutil/references.cc',
'libutil/suggestions.cc',