Merge "libutil/config: unify path setting types" into main

This commit is contained in:
rebecca “wiggles” turner 2024-08-23 22:09:11 +00:00 committed by Gerrit Code Review
commit c5949bfe31
8 changed files with 32 additions and 121 deletions

View file

@ -926,7 +926,7 @@ void NixRepl::loadFiles()
void NixRepl::loadReplOverlays() void NixRepl::loadReplOverlays()
{ {
if (!evalSettings.replOverlays) { if (evalSettings.replOverlays.get().empty()) {
return; return;
} }

View file

@ -151,7 +151,7 @@ struct EvalSettings : Config
This is useful for debugging warnings in third-party Nix code. This is useful for debugging warnings in third-party Nix code.
)"}; )"};
PathsSetting replOverlays{this, Paths(), "repl-overlays", PathsSetting<Paths> replOverlays{this, Paths(), "repl-overlays",
R"( R"(
A list of files containing Nix expressions that can be used to add A list of files containing Nix expressions that can be used to add
default bindings to [`nix default bindings to [`nix

View file

@ -634,7 +634,7 @@ public:
line. line.
)"}; )"};
OptionalPathSetting diffHook{ PathsSetting<std::optional<Path>> diffHook{
this, std::nullopt, "diff-hook", this, std::nullopt, "diff-hook",
R"( R"(
Absolute path to an executable capable of diffing build Absolute path to an executable capable of diffing build

View file

@ -11,21 +11,21 @@ struct LocalFSStoreConfig : virtual StoreConfig
{ {
using StoreConfig::StoreConfig; using StoreConfig::StoreConfig;
const OptionalPathSetting rootDir{this, std::nullopt, const PathsSetting<std::optional<Path>> rootDir{this, std::nullopt,
"root", "root",
"Directory prefixed to all other paths."}; "Directory prefixed to all other paths."};
const PathSetting stateDir{this, const PathsSetting<Path> stateDir{this,
rootDir.get() ? *rootDir.get() + "/nix/var/nix" : settings.nixStateDir, rootDir.get() ? *rootDir.get() + "/nix/var/nix" : settings.nixStateDir,
"state", "state",
"Directory where Lix will store state."}; "Directory where Lix will store state."};
const PathSetting logDir{this, const PathsSetting<Path> logDir{this,
rootDir.get() ? *rootDir.get() + "/nix/var/log/nix" : settings.nixLogDir, rootDir.get() ? *rootDir.get() + "/nix/var/log/nix" : settings.nixLogDir,
"log", "log",
"directory where Lix will store log files."}; "directory where Lix will store log files."};
const PathSetting realStoreDir{this, const PathsSetting<Path> realStoreDir{this,
rootDir.get() ? *rootDir.get() + "/nix/store" : storeDir, "real", rootDir.get() ? *rootDir.get() + "/nix/store" : storeDir, "real",
"Physical path of the Nix store."}; "Physical path of the Nix store."};
}; };

View file

@ -144,7 +144,7 @@ struct StoreConfig : public Config
return std::nullopt; return std::nullopt;
} }
const PathSetting storeDir_{this, settings.nixStore, const PathsSetting<Path> storeDir_{this, settings.nixStore,
"store", "store",
R"( R"(
Logical location of the Nix store, usually Logical location of the Nix store, usually

View file

@ -434,34 +434,12 @@ static Path parsePath(const AbstractSetting & s, const std::string & str)
return canonPath(str); return canonPath(str);
} }
PathSetting::PathSetting(Config * options, template<> Path PathsSetting<Path>::parse(const std::string & str) const
const Path & def,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases)
: BaseSetting<Path>(def, true, name, description, aliases)
{
options->addSetting(this);
}
Path PathSetting::parse(const std::string & str) const
{ {
return parsePath(*this, str); return parsePath(*this, str);
} }
template<> std::optional<Path> PathsSetting<std::optional<Path>>::parse(const std::string & str) const
OptionalPathSetting::OptionalPathSetting(Config * options,
const std::optional<Path> & def,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases)
: BaseSetting<std::optional<Path>>(def, true, name, description, aliases)
{
options->addSetting(this);
}
std::optional<Path> OptionalPathSetting::parse(const std::string & str) const
{ {
if (str == "") if (str == "")
return std::nullopt; return std::nullopt;
@ -469,23 +447,7 @@ std::optional<Path> OptionalPathSetting::parse(const std::string & str) const
return parsePath(*this, str); return parsePath(*this, str);
} }
void OptionalPathSetting::operator =(const std::optional<Path> & v) template<> Paths PathsSetting<Paths>::parse(const std::string & str) const
{
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); auto strings = tokenizeString<Strings>(str);
Paths parsed; Paths parsed;
@ -497,10 +459,10 @@ Paths PathsSetting::parse(const std::string & str) const
return parsed; return parsed;
} }
PathsSetting::operator bool() const noexcept template class PathsSetting<Path>;
{ template class PathsSetting<std::optional<Path>>;
return !get().empty(); template class PathsSetting<Paths>;
}
bool GlobalConfig::set(const std::string & name, const std::string & value) bool GlobalConfig::set(const std::string & name, const std::string & value)
{ {

View file

@ -353,69 +353,32 @@ public:
}; };
/** /**
* A special setting for Paths. These are automatically canonicalised * A special setting for Paths.
* (e.g. "/foo//bar/" becomes "/foo/bar"). * These are automatically canonicalised (e.g. "/foo//bar/" becomes "/foo/bar").
* * The empty string is not permitted when a path is required.
* It is mandatory to specify a path; i.e. the empty string is not
* permitted.
*/ */
class PathSetting : public BaseSetting<Path> template<typename T>
class PathsSetting : public BaseSetting<T>
{ {
public: public:
PathSetting(Config * options,
const Path & def,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {});
Path parse(const std::string & str) const override;
Path operator +(const char * p) const { return value + p; }
void operator =(const Path & v) { this->assign(v); }
};
/**
* Like `PathSetting`, but the absence of a path is also allowed.
*
* `std::optional` is used instead of the empty string for clarity.
*/
class OptionalPathSetting : public BaseSetting<std::optional<Path>>
{
public:
OptionalPathSetting(Config * options,
const std::optional<Path> & def,
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases = {});
std::optional<Path> parse(const std::string & str) const override;
void operator =(const std::optional<Path> & v);
};
/**
* Like `OptionalPathSetting`, but allows multiple paths.
*/
class PathsSetting : public BaseSetting<Paths>
{
public:
PathsSetting(Config * options, PathsSetting(Config * options,
const Paths & def, const T & def,
const std::string & name, const std::string & name,
const std::string & description, const std::string & description,
const std::set<std::string> & aliases = {}); const std::set<std::string> & aliases = {},
const bool documentDefault = true,
std::optional<ExperimentalFeature> experimentalFeature = std::nullopt)
: BaseSetting<T>(def, documentDefault, name, description, aliases, std::move(experimentalFeature))
{
options->addSetting(this);
}
Paths parse(const std::string & str) const override; T parse(const std::string & str) const override;
void operator =(const Paths & v); void operator =(const T & v) { this->assign(v); }
operator bool() const noexcept;
}; };
struct GlobalConfig : public AbstractConfig struct GlobalConfig : public AbstractConfig
{ {
typedef std::vector<Config*> ConfigRegistrations; typedef std::vector<Config*> ConfigRegistrations;

View file

@ -15,7 +15,7 @@ public:
: Config() : Config()
{ } { }
PathsSetting paths{this, Paths(), "paths", "documentation"}; PathsSetting<Paths> paths{this, Paths(), "paths", "documentation"};
}; };
struct PathsSettingTest : public ::testing::Test { struct PathsSettingTest : public ::testing::Test {
@ -55,20 +55,6 @@ TEST_F(PathsSettingTest, parse) {
); );
} }
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) { TEST_F(PathsSettingTest, append) {
auto config = mkConfig(); auto config = mkConfig();