diff options
author | Julian Andres Klode <julian.klode@canonical.com> | 2019-08-15 11:47:00 +0200 |
---|---|---|
committer | Julian Andres Klode <julian.klode@canonical.com> | 2019-08-15 20:21:34 +0200 |
commit | 08b61197f418883ea20563e2251fb60779c0ba87 (patch) | |
tree | 6a3bd0c40526d0094e5eec38b15e7e4eaf516068 /apt-pkg | |
parent | 7e22425c2cf937fd45160c6bbbda9210ea5d52ba (diff) |
Add pattern tree parser infra and connect with cacheset and apt list
This adds a transformation from parse tree into a CacheFilter and
connects it with cachesets and the apt list command.
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/cachefilter-patterns.cc | 51 | ||||
-rw-r--r-- | apt-pkg/cachefilter-patterns.h | 15 | ||||
-rw-r--r-- | apt-pkg/cachefilter.h | 4 | ||||
-rw-r--r-- | apt-pkg/cacheset.cc | 31 | ||||
-rw-r--r-- | apt-pkg/cacheset.h | 6 |
5 files changed, 105 insertions, 2 deletions
diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index 3c958ebae..ea4cf3cd8 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -201,5 +201,56 @@ bool PatternTreeParser::PatternNode::matches(APT::StringView name, int min, int return true; } +std::unique_ptr<APT::CacheFilter::Matcher> PatternParser::aPattern(std::unique_ptr<PatternTreeParser::Node> &nodeP) +{ + assert(nodeP != nullptr); + auto node = dynamic_cast<PatternTreeParser::PatternNode *>(nodeP.get()); + if (node == nullptr) + nodeP->error("Expected a pattern"); + + node->error(rstrprintf("Unrecognized pattern '%s'", node->term.to_string().c_str())); + + return nullptr; +} + +std::string PatternParser::aWord(std::unique_ptr<PatternTreeParser::Node> &nodeP) +{ + assert(nodeP != nullptr); + auto node = dynamic_cast<PatternTreeParser::WordNode *>(nodeP.get()); + if (node == nullptr) + nodeP->error("Expected a word"); + return node->word.to_string(); +} + } // namespace Internal + +// The bridge into the public world +std::unique_ptr<APT::CacheFilter::Matcher> APT::CacheFilter::ParsePattern(APT::StringView pattern, pkgCacheFile *file) +{ + if (file != nullptr && !file->BuildDepCache()) + return nullptr; + + try + { + auto top = APT::Internal::PatternTreeParser(pattern).parseTop(); + APT::Internal::PatternParser parser{file}; + return parser.aPattern(top); + } + catch (APT::Internal::PatternTreeParser::Error &e) + { + std::stringstream ss; + ss << "input:" << e.location.start << "-" << e.location.end << ": error: " << e.message << "\n"; + ss << pattern.to_string() << "\n"; + for (size_t i = 0; i < e.location.start; i++) + ss << " "; + for (size_t i = e.location.start; i < e.location.end; i++) + ss << "^"; + + ss << "\n"; + + _error->Error("%s", ss.str().c_str()); + return nullptr; + } +} + } // namespace APT diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index dfbcd66a5..3097ba94b 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -98,6 +98,21 @@ struct PatternTreeParser std::unique_ptr<Node> parseQuotedWord(); }; +/** + * \brief PatternParser parses the given sentence into a parse tree. + * + * The parse tree consists of nodes: + * - Word nodes which contains words or quoted words + * - Patterns, which represent ?foo and ?foo(...) patterns + */ +struct PatternParser +{ + pkgCacheFile *file; + + std::unique_ptr<APT::CacheFilter::Matcher> aPattern(std::unique_ptr<PatternTreeParser::Node> &nodeP); + std::string aWord(std::unique_ptr<PatternTreeParser::Node> &nodeP); +}; + } // namespace Internal } // namespace APT #endif diff --git a/apt-pkg/cachefilter.h b/apt-pkg/cachefilter.h index 8a6c01341..3c6e1559d 100644 --- a/apt-pkg/cachefilter.h +++ b/apt-pkg/cachefilter.h @@ -7,7 +7,9 @@ #define APT_CACHEFILTER_H // Include Files /*{{{*/ #include <apt-pkg/pkgcache.h> +#include <apt-pkg/string_view.h> +#include <memory> #include <string> #include <vector> @@ -145,6 +147,8 @@ public: }; /*}}}*/ +/// \brief Parse a pattern, return nullptr or pattern +std::unique_ptr<APT::CacheFilter::Matcher> ParsePattern(APT::StringView pattern, pkgCacheFile *file); } } #endif diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 789727266..dd55edb4e 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -46,6 +46,7 @@ bool CacheSetHelper::PackageFrom(enum PkgSelector const select, PackageContainer case FNMATCH: return PackageFromFnmatch(pci, Cache, pattern); case PACKAGENAME: return PackageFromPackageName(pci, Cache, pattern); case STRING: return PackageFromString(pci, Cache, pattern); + case PATTERN: return PackageFromPattern(pci, Cache, pattern); } return false; } @@ -281,13 +282,33 @@ bool CacheSetHelper::PackageFromPackageName(PackageContainerInterface * const pc pci->insert(Pkg); return true; } + +bool CacheSetHelper::PackageFromPattern(PackageContainerInterface *const pci, pkgCacheFile &Cache, std::string const &pattern) +{ + if (pattern.size() < 1 || pattern[0] != '?') + return false; + + auto compiledPattern = APT::CacheFilter::ParsePattern(pattern, &Cache); + if (!compiledPattern) + return false; + + for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg) + { + if ((*compiledPattern)(Pkg) == false) + continue; + + pci->insert(Pkg); + } + return true; +} /*}}}*/ // PackageFromString - Return all packages matching a specific string /*{{{*/ bool CacheSetHelper::PackageFromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &str) { bool found = true; _error->PushToStack(); - if (PackageFrom(CacheSetHelper::PACKAGENAME, pci, Cache, str) == false && + if (PackageFrom(CacheSetHelper::PATTERN, pci, Cache, str) == false && + PackageFrom(CacheSetHelper::PACKAGENAME, pci, Cache, str) == false && PackageFrom(CacheSetHelper::TASK, pci, Cache, str) == false && // FIXME: hm, hm, regexp/fnmatch incompatible? PackageFrom(CacheSetHelper::FNMATCH, pci, Cache, str) == false && @@ -686,6 +707,7 @@ void CacheSetHelper::canNotFindPackage(enum PkgSelector const select, case FNMATCH: canNotFindFnmatch(pci, Cache, pattern); break; case PACKAGENAME: canNotFindPackage(pci, Cache, pattern); break; case STRING: canNotFindPackage(pci, Cache, pattern); break; + case PATTERN: canNotFindPackage(pci, Cache, pattern); break; case UNKNOWN: break; } } @@ -822,6 +844,7 @@ void CacheSetHelper::showPackageSelection(pkgCache::PkgIterator const &pkg, enum case REGEX: showRegExSelection(pkg, pattern); break; case TASK: showTaskSelection(pkg, pattern); break; case FNMATCH: showFnmatchSelection(pkg, pattern); break; + case PATTERN: showPatternSelection(pkg, pattern); break; case PACKAGENAME: /* no surprises here */ break; case STRING: /* handled by the special cases */ break; case UNKNOWN: break; @@ -842,6 +865,12 @@ void CacheSetHelper::showFnmatchSelection(pkgCache::PkgIterator const &/*pkg*/, std::string const &/*pattern*/) { } /*}}}*/ +// showPatternSelection /*{{{*/ +void CacheSetHelper::showPatternSelection(pkgCache::PkgIterator const & /*pkg*/, + std::string const & /*pattern*/) +{ +} + /*}}}*/ /*}}}*/ // showVersionSelection /*{{{*/ void CacheSetHelper::showVersionSelection(pkgCache::PkgIterator const &Pkg, diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 489fb6220..6023b861d 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -52,7 +52,7 @@ public: /*{{{*/ GlobalError::MsgType ErrorType = GlobalError::ERROR); virtual ~CacheSetHelper(); - enum PkgSelector { UNKNOWN, REGEX, TASK, FNMATCH, PACKAGENAME, STRING }; + enum PkgSelector { UNKNOWN, REGEX, TASK, FNMATCH, PACKAGENAME, STRING, PATTERN }; virtual bool PackageFrom(enum PkgSelector const select, PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern); @@ -172,10 +172,12 @@ protected: bool PackageFromFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern); bool PackageFromPackageName(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern); bool PackageFromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern); + bool PackageFromPattern(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern); private: void showTaskSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern); void showRegExSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern); void showFnmatchSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern); + void showPatternSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern); void canNotFindTask(PackageContainerInterface *const pci, pkgCacheFile &Cache, std::string pattern); void canNotFindRegEx(PackageContainerInterface *const pci, pkgCacheFile &Cache, std::string pattern); void canNotFindFnmatch(PackageContainerInterface *const pci, pkgCacheFile &Cache, std::string pattern); @@ -739,6 +741,8 @@ public: std::string pkg, CacheSetHelper::VerSelector const fallback, CacheSetHelper &helper, bool const onlyFromName = false); + static bool FromPattern(VersionContainerInterface *const vci, pkgCacheFile &Cache, + std::string pkg, CacheSetHelper::VerSelector const fallback, CacheSetHelper &helper); static bool FromPackage(VersionContainerInterface * const vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &P, CacheSetHelper::VerSelector const fallback, |