diff options
author | Julian Andres Klode <julian.klode@canonical.com> | 2020-01-20 14:14:49 +0100 |
---|---|---|
committer | Julian Andres Klode <julian.klode@canonical.com> | 2020-02-03 12:55:54 +0100 |
commit | fd43b1694f1382a3a47f5dc546ebe3d39fcd6e7d (patch) | |
tree | f8a54edcd442f81a69c9603f4c6bdfb722af95f0 /apt-pkg | |
parent | d9c4c1d88ae6c42fee0f2da3a5b9669187fc2fc5 (diff) |
Implement short patterns (patterns starting with ~)
Also make pattern detector in cacheset and private's list accept
such patterns. We probably should just try to parse and see if it
is a (start of a) pattern.
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/cachefilter-patterns.cc | 57 | ||||
-rw-r--r-- | apt-pkg/cachefilter-patterns.h | 1 | ||||
-rw-r--r-- | apt-pkg/cacheset.cc | 2 |
3 files changed, 59 insertions, 1 deletions
diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index 7abc4536d..11ad5d723 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -17,6 +17,32 @@ namespace APT namespace Internal { +static const constexpr struct +{ + APT::StringView shortName; + APT::StringView longName; + bool takesArgument; +} shortPatterns[] = { + {"r"_sv, "?architecture"_sv, true}, + {"A"_sv, "?archive"_sv, true}, + {"M"_sv, "?automatic"_sv, false}, + {"b"_sv, "?broken"_sv, false}, + {"c"_sv, "?config-files"_sv, false}, + {"E"_sv, "?essential"_sv, false}, + {"F"_sv, "?false"_sv, false}, + {"g"_sv, "?garbage"_sv, false}, + {"i"_sv, "?installed"_sv, false}, + {"n"_sv, "?name"_sv, true}, + {"o"_sv, "?obsolete"_sv, false}, + {"O"_sv, "?origin"_sv, true}, + {"s"_sv, "?section"_sv, true}, + {"e"_sv, "?source-package"_sv, true}, + {"T"_sv, "?true"_sv, false}, + {"U"_sv, "?upgradable"_sv, false}, + {"V"_sv, "?version"_sv, true}, + {"v"_sv, "?virtual"_sv, false}, +}; + template <class... Args> std::string rstrprintf(Args... args) { @@ -42,6 +68,8 @@ std::unique_ptr<PatternTreeParser::Node> PatternTreeParser::parseTop() std::unique_ptr<PatternTreeParser::Node> PatternTreeParser::parse() { std::unique_ptr<Node> node; + if ((node = parseShortPattern()) != nullptr) + return node; if ((node = parsePattern()) != nullptr) return node; if ((node = parseQuotedWord()) != nullptr) @@ -53,6 +81,35 @@ std::unique_ptr<PatternTreeParser::Node> PatternTreeParser::parse() "Expected pattern, quoted word, or word"}; } +// Parse a short pattern +std::unique_ptr<PatternTreeParser::Node> PatternTreeParser::parseShortPattern() +{ + if (sentence[state.offset] != '~') + return nullptr; + + for (auto &sp : shortPatterns) + { + if (sentence.substr(state.offset + 1, sp.shortName.size()) != sp.shortName) + continue; + + auto node = std::make_unique<PatternNode>(); + node->end = node->start = state.offset; + node->term = sp.longName; + + state.offset += sp.shortName.size() + 1; + if (sp.takesArgument) + { + node->arguments.push_back(parse()); + node->haveArgumentList = true; + } + node->end = state.offset; + + return node; + } + + throw Error{Node{state.offset, sentence.size()}, "Unknown short pattern"}; +} + // Parse a list pattern (or function call pattern) std::unique_ptr<PatternTreeParser::Node> PatternTreeParser::parsePattern() { diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 8317665bc..0d6e9d99e 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -96,6 +96,7 @@ struct PatternTreeParser private: std::unique_ptr<Node> parse(); std::unique_ptr<Node> parsePattern(); + std::unique_ptr<Node> parseShortPattern(); std::unique_ptr<Node> parseWord(); std::unique_ptr<Node> parseQuotedWord(); }; diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index f5251eda8..ae1d5ee3e 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -295,7 +295,7 @@ bool CacheSetHelper::PackageFromPackageName(PackageContainerInterface * const pc bool CacheSetHelper::PackageFromPattern(PackageContainerInterface *const pci, pkgCacheFile &Cache, std::string const &pattern) { - if (pattern.size() < 1 || pattern[0] != '?') + if (pattern.size() < 1 || (pattern[0] != '?' && pattern[0] != '~')) return false; auto compiledPattern = APT::CacheFilter::ParsePattern(pattern, &Cache); |