summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2019-08-15 11:47:00 +0200
committerJulian Andres Klode <julian.klode@canonical.com>2019-08-15 20:21:34 +0200
commit08b61197f418883ea20563e2251fb60779c0ba87 (patch)
tree6a3bd0c40526d0094e5eec38b15e7e4eaf516068 /apt-pkg
parent7e22425c2cf937fd45160c6bbbda9210ea5d52ba (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.cc51
-rw-r--r--apt-pkg/cachefilter-patterns.h15
-rw-r--r--apt-pkg/cachefilter.h4
-rw-r--r--apt-pkg/cacheset.cc31
-rw-r--r--apt-pkg/cacheset.h6
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,