mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-29 17:16:15 +02:00
profile: convert Matcher to abstract class
This commit is contained in:
parent
4741d3e308
commit
3d628d1704
1 changed files with 71 additions and 51 deletions
|
@ -453,65 +453,85 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MatcherType
|
|
||||||
{
|
|
||||||
Regex,
|
|
||||||
StorePath,
|
|
||||||
Name,
|
|
||||||
All,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Matcher
|
struct Matcher
|
||||||
{
|
{
|
||||||
MatcherType type;
|
virtual std::string getTitle() = 0;
|
||||||
std::string title;
|
virtual bool matches(const std::string & name, const ProfileElement & element) = 0;
|
||||||
std::function<bool(const std::string & name, const ProfileElement & element)> matches;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Matcher createRegexMatcher(const std::string & pattern)
|
struct RegexMatcher : public Matcher
|
||||||
{
|
{
|
||||||
std::regex reg(pattern, std::regex::extended | std::regex::icase);
|
std::regex regex;
|
||||||
return {
|
std::string pattern;
|
||||||
.type = MatcherType::Regex,
|
|
||||||
.title = fmt("Regex '%s'", pattern),
|
|
||||||
.matches = [reg](const std::string &name, const ProfileElement & element) {
|
|
||||||
return std::regex_match(element.identifier(), reg);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Matcher createStorePathMatcher(const nix::StorePath & storePath)
|
RegexMatcher(const std::string & pattern) : regex(pattern, std::regex::extended | std::regex::icase), pattern(pattern)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
std::string getTitle() override
|
||||||
|
{
|
||||||
|
return fmt("Regex '%s'", pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matches(const std::string & name, const ProfileElement & element) override
|
||||||
|
{
|
||||||
|
return std::regex_match(element.identifier(), regex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StorePathMatcher : public Matcher
|
||||||
{
|
{
|
||||||
return {
|
nix::StorePath storePath;
|
||||||
.type = MatcherType::StorePath,
|
|
||||||
.title = fmt("Store path '%s'", storePath.to_string()),
|
StorePathMatcher(const nix::StorePath & storePath) : storePath(storePath)
|
||||||
.matches = [storePath](const std::string &name, const ProfileElement & element) {
|
{ }
|
||||||
|
|
||||||
|
std::string getTitle() override
|
||||||
|
{
|
||||||
|
return fmt("Store path '%s'", storePath.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matches(const std::string & name, const ProfileElement & element) override
|
||||||
|
{
|
||||||
return element.storePaths.count(storePath);
|
return element.storePaths.count(storePath);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
Matcher createNameMatcher(const std::string & name) {
|
struct NameMatcher : public Matcher
|
||||||
return {
|
{
|
||||||
.type = MatcherType::Name,
|
std::string name;
|
||||||
.title = fmt("Package name '%s'", name),
|
|
||||||
.matches = [name](const std::string &elementName, const ProfileElement & element) {
|
NameMatcher(const std::string & name) : name(name)
|
||||||
return elementName == name;
|
{ }
|
||||||
|
|
||||||
|
std::string getTitle() override
|
||||||
|
{
|
||||||
|
return fmt("Package name '%s'", name);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Matcher all = {
|
bool matches(const std::string & name, const ProfileElement & element) override
|
||||||
.type = MatcherType::All,
|
{
|
||||||
.title = "--all",
|
return name == this->name;
|
||||||
.matches = [](const std::string &name, const ProfileElement & element) {
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AllMatcher : public Matcher
|
||||||
|
{
|
||||||
|
std::string getTitle() override
|
||||||
|
{
|
||||||
|
return "--all";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matches(const std::string & name, const ProfileElement & element) override
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AllMatcher all;
|
||||||
|
|
||||||
class MixProfileElementMatchers : virtual Args, virtual StoreCommand
|
class MixProfileElementMatchers : virtual Args, virtual StoreCommand
|
||||||
{
|
{
|
||||||
std::vector<Matcher> _matchers;
|
std::vector<ref<Matcher>> _matchers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -521,7 +541,7 @@ public:
|
||||||
.longName = "all",
|
.longName = "all",
|
||||||
.description = "Match all packages in the profile.",
|
.description = "Match all packages in the profile.",
|
||||||
.handler = {[this]() {
|
.handler = {[this]() {
|
||||||
_matchers.push_back(all);
|
_matchers.push_back(ref<AllMatcher>(std::shared_ptr<AllMatcher>(&all, [](AllMatcher*) {})));
|
||||||
}},
|
}},
|
||||||
});
|
});
|
||||||
addFlag({
|
addFlag({
|
||||||
|
@ -529,7 +549,7 @@ public:
|
||||||
.description = "A regular expression to match one or more packages in the profile.",
|
.description = "A regular expression to match one or more packages in the profile.",
|
||||||
.labels = {"pattern"},
|
.labels = {"pattern"},
|
||||||
.handler = {[this](std::string arg) {
|
.handler = {[this](std::string arg) {
|
||||||
_matchers.push_back(createRegexMatcher(arg));
|
_matchers.push_back(make_ref<RegexMatcher>(arg));
|
||||||
}},
|
}},
|
||||||
});
|
});
|
||||||
expectArgs({
|
expectArgs({
|
||||||
|
@ -540,9 +560,9 @@ public:
|
||||||
if (auto n = string2Int<size_t>(arg)) {
|
if (auto n = string2Int<size_t>(arg)) {
|
||||||
throw Error("'nix profile' no longer supports indices ('%d')", *n);
|
throw Error("'nix profile' no longer supports indices ('%d')", *n);
|
||||||
} else if (getStore()->isStorePath(arg)) {
|
} else if (getStore()->isStorePath(arg)) {
|
||||||
_matchers.push_back(createStorePathMatcher(getStore()->parseStorePath(arg)));
|
_matchers.push_back(make_ref<StorePathMatcher>(getStore()->parseStorePath(arg)));
|
||||||
} else {
|
} else {
|
||||||
_matchers.push_back(createNameMatcher(arg));
|
_matchers.push_back(make_ref<NameMatcher>(arg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@ -554,7 +574,7 @@ public:
|
||||||
throw UsageError("No packages specified.");
|
throw UsageError("No packages specified.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find_if(_matchers.begin(), _matchers.end(), [](const Matcher & m) { return m.type == MatcherType::All; }) != _matchers.end() && _matchers.size() > 1) {
|
if (std::find_if(_matchers.begin(), _matchers.end(), [](const ref<Matcher> & m) { return m.dynamic_pointer_cast<AllMatcher>(); }) != _matchers.end() && _matchers.size() > 1) {
|
||||||
throw UsageError("--all cannot be used with package names or regular expressions.");
|
throw UsageError("--all cannot be used with package names or regular expressions.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,13 +587,13 @@ public:
|
||||||
for (auto & matcher : _matchers) {
|
for (auto & matcher : _matchers) {
|
||||||
bool foundMatch = false;
|
bool foundMatch = false;
|
||||||
for (auto & [name, element] : manifest.elements) {
|
for (auto & [name, element] : manifest.elements) {
|
||||||
if (matcher.matches(name, element)) {
|
if (matcher->matches(name, element)) {
|
||||||
result.insert(name);
|
result.insert(name);
|
||||||
foundMatch = true;
|
foundMatch = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!foundMatch) {
|
if (!foundMatch) {
|
||||||
warn("%s does not match any packages in the profile.", matcher.title);
|
warn("%s does not match any packages in the profile.", matcher->getTitle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Reference in a new issue