From 7e22425c2cf937fd45160c6bbbda9210ea5d52ba Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 15 Aug 2019 11:19:20 +0200 Subject: doc: Add apt-patterns(7) manual page This does not describe much yet, as there's not much to talk about. --- doc/CMakeLists.txt | 1 + doc/apt-patterns.7.xml | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++ doc/po4a.conf | 1 + 3 files changed, 89 insertions(+) create mode 100644 doc/apt-patterns.7.xml (limited to 'doc') diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 7cca4cf81..3060949e5 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -82,6 +82,7 @@ add_docbook(apt-man MANPAGE ALL apt-key.8.xml apt-mark.8.xml apt_preferences.5.xml + apt-patterns.7.xml apt-secure.8.xml apt-sortpkgs.1.xml apt-transport-http.1.xml diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml new file mode 100644 index 000000000..079c493e4 --- /dev/null +++ b/doc/apt-patterns.7.xml @@ -0,0 +1,87 @@ + + %aptent; + %aptverbatiment; + %aptvendor; +]> + + + + &apt-author.jgunthorpe; + &apt-author.team; + &apt-email; + &apt-product; + + 2019-08-15T00:00:00Z + + + + apt-patterns + 7 + APT + + + + + apt-patterns + Syntax and semantics of apt search patterns + + + Description + + Starting with version 2.0, APT provides support for + patterns, which can be used to query the apt cache for packages. + + + + + Syntax + + + + + + Examples + + + Migrating from aptitude + + Patterns in apt are heavily inspired by patterns in aptitude, but with some tweaks: + + + + Only long forms — the ones starting with ? — are supported + + + + Syntax is uniform: If there is an opening parenthesis after a term, it is always assumed to be the beginning of an argument list. + + + In aptitude, a syntactic form "?foo(bar)" could mean "?and(?foo,bar)" if foo does not take an argument. In APT, this will cause an error. + + + + Not all patterns are supported. + + + Some additional patterns are available, for example, for finding gstreamer codecs. + + + Escaping terms with ~ is not supported. + + + A trailing comma is allowed in argument lists + + + + + See Also + + &apt-get;, &apt; + + + + &manbugs; + &manauthor; + diff --git a/doc/po4a.conf b/doc/po4a.conf index 587215abc..1cf170b80 100644 --- a/doc/po4a.conf +++ b/doc/po4a.conf @@ -30,6 +30,7 @@ [type: manpage] apt-transport-http.1.xml $lang:$lang/apt-transport-http.$lang.1.xml add_$lang:xml.add [type: manpage] apt-transport-https.1.xml $lang:$lang/apt-transport-https.$lang.1.xml add_$lang:xml.add [type: manpage] apt-transport-mirror.1.xml $lang:$lang/apt-transport-mirror.$lang.1.xml add_$lang:xml.add +[type: manpage] apt-patterns.7.xml $lang:$lang/apt-patterns.7.xml add_$lang:xml.add [type: docbook] guide.dbk $lang:$lang/guide.$lang.dbk # add_$lang::$lang/addendum/docbook_$lang.add -- cgit v1.2.3-70-g09d2 From c64a85dd7524546864603b955f601bf64c9a4bcf Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 15 Aug 2019 12:50:22 +0200 Subject: Add patterns for the existing CacheFilter::Matcher classes This implements the basic logic patterns: ?and ?false ?not ?or ?true and the basic package patterns: ?architecture ?name ?x-name-fnmatch --- apt-pkg/cachefilter-patterns.cc | 30 ++++++++++++++++++ doc/apt-patterns.7.xml | 38 +++++++++++++++++++++-- test/integration/test-apt-patterns | 62 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index ea4cf3cd8..dd5d741d3 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -208,6 +208,36 @@ std::unique_ptr PatternParser::aPattern(std::unique_p if (node == nullptr) nodeP->error("Expected a pattern"); + if (node->matches("?architecture", 1, 1)) + return std::make_unique(aWord(node->arguments[0])); + if (node->matches("?false", 0, 0)) + return std::make_unique(); + if (node->matches("?name", 1, 1)) + return std::make_unique(aWord(node->arguments[0])); + if (node->matches("?not", 1, 1)) + return std::make_unique(aPattern(node->arguments[0]).release()); + if (node->matches("?true", 0, 0)) + return std::make_unique(); + if (node->matches("?x-name-fnmatch", 1, 1)) + return std::make_unique(aWord(node->arguments[0])); + + // Variable argument patterns + if (node->matches("?and", 0, -1)) + { + auto pattern = std::make_unique(); + for (auto &arg : node->arguments) + pattern->AND(aPattern(arg).release()); + return pattern; + } + if (node->matches("?or", 0, -1)) + { + auto pattern = std::make_unique(); + + for (auto &arg : node->arguments) + pattern->OR(aPattern(arg).release()); + return pattern; + } + node->error(rstrprintf("Unrecognized pattern '%s'", node->term.to_string().c_str())); return nullptr; diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index 079c493e4..5aa352f03 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -36,12 +36,46 @@ - Syntax + Logic patterns + + These patterns provide the basic means to combine other patterns into + more complex expressions, as well as ?true and ?false + patterns. + + ?and(PATTERN, PATTERN, ...) + Selects objects where all specified patterns match. + + ?false + Selects nothing. + + ?not(PATTERN) + Selects objects where PATTERN does not match. + + ?or(PATTERN, PATTERN, ...) + Selects objects where at least one of the specified patterns match. + + ?true + Selects all objects. + + + + + Package patterns + + These patterns select specific packages. + + + ?architecture(WILDCARD) + Selects packages matching the specified architecture, which may contain wildcards using any. + + ?name(REGEX) + Selects packages where the name matches the given regular expression. + - + Examples diff --git a/test/integration/test-apt-patterns b/test/integration/test-apt-patterns index c33fa1bf8..0d7b1540d 100755 --- a/test/integration/test-apt-patterns +++ b/test/integration/test-apt-patterns @@ -59,3 +59,65 @@ E: Unable to locate package ?not-a-pattern E: Couldn't find any package by glob '?not-a-pattern' E: Regex compilation error - Invalid preceding regular expression E: Couldn't find any package by regex '?not-a-pattern'" apt install -s '?not-a-pattern' + + +msgmsg "Ensure that argument lists are present where needed, and absent elsewhere" + +testfailureequal "Listing... +E: input:0-7: error: ?true does not expect an argument list + ?true() + ^^^^^^^" apt list '?true()' +testfailureequal "Listing... +E: input:0-4: error: ?and expects an argument list + ?and + ^^^^" apt list '?and' +testfailureequal "Listing... +E: input:0-3: error: ?or expects an argument list + ?or + ^^^" apt list '?or' + + +msgmsg "Basic logic: true, false, not, ?or, ?and" +for pattern in '?true' '?not(?false)'; do +testsuccessequal "Listing... +automatic1/now 1.0 i386 [installed,local] +automatic2/now 1.0 i386 [installed,local] +available/unstable 1.0 all +broken/now 1.0 i386 [installed,local] +conf-only/now 1.0 i386 [residual-config] +dpkg/now 1.16.2+fake all [installed,local] +essential/now 1.0 i386 [installed,local] +foreign/unstable 2.0 amd64 +manual1/now 1.0 i386 [installed,local] +manual2/now 1.0 i386 [installed,local] +not-obsolete/unstable 2.0 i386 [upgradable from: 1.0]" apt list "$pattern" +done +testsuccessequal "Listing..." apt list '?false' +testsuccessequal "Listing..." apt list '?not(?true)' +testsuccessequal "Listing... +automatic1/now 1.0 i386 [installed,local] +automatic2/now 1.0 i386 [installed,local] +manual1/now 1.0 i386 [installed,local] +manual2/now 1.0 i386 [installed,local]" apt list '?or(?name(^automatic),?name(^manual))' +testsuccessequal "Listing... +automatic1/now 1.0 i386 [installed,local]" apt list '?and(?name(^automatic),?name(1$))' + + +msgmsg "Package patterns" + +testsuccessequal "Listing... +foreign/unstable 2.0 amd64" apt list '?architecture(amd64)' + +# XXX FIXME We should have support for foreign and native +testsuccessequal "Listing..." apt list '?architecture(foreign)' +testsuccessequal "Listing..." apt list '?architecture(native)' + + +testsuccessequal "Listing... +automatic1/now 1.0 i386 [installed,local] +automatic2/now 1.0 i386 [installed,local]" apt list '?name(^automatic)' + +testsuccessequal "Listing..." apt list '?x-name-fnmatch(1)' +testsuccessequal "Listing... +automatic1/now 1.0 i386 [installed,local] +manual1/now 1.0 i386 [installed,local]" apt list '?x-name-fnmatch(*1)' -- cgit v1.2.3-70-g09d2 From 083e72a5939d33dc1fd7596aa441a9982332f776 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 15 Aug 2019 13:12:43 +0200 Subject: Add ?automatic and ?garbage patterns These patterns allow you to identify automatically installed packages, as well as automatically installed packages that are no longer reachable from the manually installed ones. --- apt-pkg/cachefilter-patterns.cc | 4 ++++ apt-pkg/cachefilter-patterns.h | 26 ++++++++++++++++++++++++++ doc/apt-patterns.7.xml | 11 +++++++++++ test/integration/test-apt-patterns | 6 ++++++ 4 files changed, 47 insertions(+) (limited to 'doc') diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index dd5d741d3..6b506b740 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -210,8 +210,12 @@ std::unique_ptr PatternParser::aPattern(std::unique_p if (node->matches("?architecture", 1, 1)) return std::make_unique(aWord(node->arguments[0])); + if (node->matches("?automatic", 0, 0)) + return std::make_unique(file); if (node->matches("?false", 0, 0)) return std::make_unique(); + if (node->matches("?garbage", 0, 0)) + return std::make_unique(file); if (node->matches("?name", 1, 1)) return std::make_unique(aWord(node->arguments[0])); if (node->matches("?not", 1, 1)) diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 3097ba94b..4c2ef48df 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -113,6 +113,32 @@ struct PatternParser std::string aWord(std::unique_ptr &nodeP); }; +namespace Patterns +{ +using namespace APT::CacheFilter; + +struct PackageIsAutomatic : public PackageMatcher +{ + pkgCacheFile *Cache; + explicit PackageIsAutomatic(pkgCacheFile *Cache) : Cache(Cache) {} + bool operator()(pkgCache::PkgIterator const &Pkg) override + { + assert(Cache != nullptr); + return ((*Cache)[Pkg].Flags & pkgCache::Flag::Auto) != 0; + } +}; + +struct PackageIsGarbage : public PackageMatcher +{ + pkgCacheFile *Cache; + explicit PackageIsGarbage(pkgCacheFile *Cache) : Cache(Cache) {} + bool operator()(pkgCache::PkgIterator const &Pkg) override + { + assert(Cache != nullptr); + return (*Cache)[Pkg].Garbage; + } +}; +} // namespace Patterns } // namespace Internal } // namespace APT #endif diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index 5aa352f03..327ea17d5 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -69,6 +69,12 @@ ?architecture(WILDCARD) Selects packages matching the specified architecture, which may contain wildcards using any. + ?automatic + Selects packages that were installed automatically. + + ?garbage + Selects packages that can be removed automatically. + ?name(REGEX) Selects packages where the name matches the given regular expression. @@ -77,6 +83,11 @@ Examples + + apt remove ?garbage + Remove all packages that are automatically installed and no longer needed - same as apt autoremove + + Migrating from aptitude diff --git a/test/integration/test-apt-patterns b/test/integration/test-apt-patterns index 0d7b1540d..9a2c74f83 100755 --- a/test/integration/test-apt-patterns +++ b/test/integration/test-apt-patterns @@ -112,6 +112,12 @@ foreign/unstable 2.0 amd64" apt list '?architecture(amd64)' testsuccessequal "Listing..." apt list '?architecture(foreign)' testsuccessequal "Listing..." apt list '?architecture(native)' +testsuccessequal "Listing... +automatic1/now 1.0 i386 [installed,local] +automatic2/now 1.0 i386 [installed,local]" apt list '?automatic' + +testsuccessequal "Listing... +automatic2/now 1.0 i386 [installed,local]" apt list '?garbage' testsuccessequal "Listing... automatic1/now 1.0 i386 [installed,local] -- cgit v1.2.3-70-g09d2 From 89790c11799c4144e37a6a1f0dbe0f6fff89ea89 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 15 Aug 2019 13:23:55 +0200 Subject: Add ?obsolete and ?upgradable patterns These match packages that have no version in a repository, or where an upgrade is available. Notably, ?and(?obsolete,?upgradable) == ?false because an upgradable package is by definition not obsolete. --- apt-pkg/cachefilter-patterns.cc | 4 ++++ apt-pkg/cachefilter-patterns.h | 35 +++++++++++++++++++++++++++++++++++ doc/apt-patterns.7.xml | 6 ++++++ test/integration/test-apt-patterns | 10 ++++++++++ 4 files changed, 55 insertions(+) (limited to 'doc') diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index 6b506b740..b97d65a03 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -220,8 +220,12 @@ std::unique_ptr PatternParser::aPattern(std::unique_p return std::make_unique(aWord(node->arguments[0])); if (node->matches("?not", 1, 1)) return std::make_unique(aPattern(node->arguments[0]).release()); + if (node->matches("?obsolete", 0, 0)) + return std::make_unique(); if (node->matches("?true", 0, 0)) return std::make_unique(); + if (node->matches("?upgradable", 0, 0)) + return std::make_unique(file); if (node->matches("?x-name-fnmatch", 1, 1)) return std::make_unique(aWord(node->arguments[0])); diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 4c2ef48df..68ad32f9a 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -138,6 +138,41 @@ struct PackageIsGarbage : public PackageMatcher return (*Cache)[Pkg].Garbage; } }; + +struct PackageIsObsolete : public PackageMatcher +{ + bool operator()(pkgCache::PkgIterator const &pkg) override + { + // This code can be written without loops, as aptitude does, but it + // is far less readable. + if (pkg.CurrentVer().end()) + return false; + + // See if there is any version that exists in a repository, + // if so return false + for (auto ver = pkg.VersionList(); !ver.end(); ver++) + { + for (auto file = ver.FileList(); !file.end(); file++) + { + if ((file.File()->Flags & pkgCache::Flag::NotSource) == 0) + return false; + } + } + + return true; + } +}; + +struct PackageIsUpgradable : public PackageMatcher +{ + pkgCacheFile *Cache; + explicit PackageIsUpgradable(pkgCacheFile *Cache) : Cache(Cache) {} + bool operator()(pkgCache::PkgIterator const &Pkg) override + { + assert(Cache != nullptr); + return Pkg->CurrentVer != 0 && (*Cache)[Pkg].Upgradable(); + } +}; } // namespace Patterns } // namespace Internal } // namespace APT diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index 327ea17d5..6058d7a74 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -78,6 +78,12 @@ ?name(REGEX) Selects packages where the name matches the given regular expression. + ?obsolete + Selects packages that no longer exist in repositories. + + ?upgradable + Selects packages that can be upgraded (have a newer candidate). + diff --git a/test/integration/test-apt-patterns b/test/integration/test-apt-patterns index 9a2c74f83..549089d8a 100755 --- a/test/integration/test-apt-patterns +++ b/test/integration/test-apt-patterns @@ -123,6 +123,16 @@ testsuccessequal "Listing... automatic1/now 1.0 i386 [installed,local] automatic2/now 1.0 i386 [installed,local]" apt list '?name(^automatic)' +testsuccessequal "Listing... +available/unstable 1.0 all +conf-only/now 1.0 i386 [residual-config] +foreign/unstable 2.0 amd64 +not-obsolete/unstable 2.0 i386 [upgradable from: 1.0]" apt list '?not(?obsolete)' + +testsuccessequal "Listing... +not-obsolete/unstable 2.0 i386 [upgradable from: 1.0] +N: There is 1 additional version. Please use the '-a' switch to see it" apt list '?upgradable' + testsuccessequal "Listing..." apt list '?x-name-fnmatch(1)' testsuccessequal "Listing... automatic1/now 1.0 i386 [installed,local] -- cgit v1.2.3-70-g09d2 From a3e9ab661b2d670f7d0da53a5f56c52af0763c5b Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 15 Aug 2019 13:31:30 +0200 Subject: Add ?config-files and ?installed patterns These two are mutually exclusive states of installed-ness. And ?installed package is fully unpacked and configured; a ?config-files package only has config files left. --- apt-pkg/cachefilter-patterns.cc | 4 ++++ apt-pkg/cachefilter-patterns.h | 19 +++++++++++++++++++ doc/apt-patterns.7.xml | 9 +++++++++ test/integration/test-apt-patterns | 18 ++++++++++++++++++ 4 files changed, 50 insertions(+) (limited to 'doc') diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index b97d65a03..0f23890b4 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -212,10 +212,14 @@ std::unique_ptr PatternParser::aPattern(std::unique_p return std::make_unique(aWord(node->arguments[0])); if (node->matches("?automatic", 0, 0)) return std::make_unique(file); + if (node->matches("?config-files", 0, 0)) + return std::make_unique(); if (node->matches("?false", 0, 0)) return std::make_unique(); if (node->matches("?garbage", 0, 0)) return std::make_unique(file); + if (node->matches("?installed", 0, 0)) + return std::make_unique(file); if (node->matches("?name", 1, 1)) return std::make_unique(aWord(node->arguments[0])); if (node->matches("?not", 1, 1)) diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 68ad32f9a..7770385c9 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -128,6 +128,14 @@ struct PackageIsAutomatic : public PackageMatcher } }; +struct PackageIsConfigFiles : public PackageMatcher +{ + bool operator()(pkgCache::PkgIterator const &Pkg) override + { + return Pkg->CurrentState == pkgCache::State::ConfigFiles; + } +}; + struct PackageIsGarbage : public PackageMatcher { pkgCacheFile *Cache; @@ -139,6 +147,17 @@ struct PackageIsGarbage : public PackageMatcher } }; +struct PackageIsInstalled : public PackageMatcher +{ + pkgCacheFile *Cache; + explicit PackageIsInstalled(pkgCacheFile *Cache) : Cache(Cache) {} + bool operator()(pkgCache::PkgIterator const &Pkg) override + { + assert(Cache != nullptr); + return Pkg->CurrentVer != 0; + } +}; + struct PackageIsObsolete : public PackageMatcher { bool operator()(pkgCache::PkgIterator const &pkg) override diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index 6058d7a74..64dad4dd4 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -72,9 +72,15 @@ ?automatic Selects packages that were installed automatically. + ?config-files + Selects packages that are not fully installed, but have solely residual configuration files left. + ?garbage Selects packages that can be removed automatically. + ?installed + Selects packages that are currently installed. + ?name(REGEX) Selects packages where the name matches the given regular expression. @@ -93,6 +99,9 @@ apt remove ?garbage Remove all packages that are automatically installed and no longer needed - same as apt autoremove + apt purge ?config-files + Purge all packages that only have configuration files left + diff --git a/test/integration/test-apt-patterns b/test/integration/test-apt-patterns index 549089d8a..b84605256 100755 --- a/test/integration/test-apt-patterns +++ b/test/integration/test-apt-patterns @@ -116,9 +116,27 @@ testsuccessequal "Listing... automatic1/now 1.0 i386 [installed,local] automatic2/now 1.0 i386 [installed,local]" apt list '?automatic' +testsuccessequal "Listing... +conf-only/now 1.0 i386 [residual-config]" apt list '?config-files' + testsuccessequal "Listing... automatic2/now 1.0 i386 [installed,local]" apt list '?garbage' +testsuccessequal "Listing... +automatic1/now 1.0 i386 [installed,local] +automatic2/now 1.0 i386 [installed,local] +broken/now 1.0 i386 [installed,local] +dpkg/now 1.16.2+fake all [installed,local] +essential/now 1.0 i386 [installed,local] +manual1/now 1.0 i386 [installed,local] +manual2/now 1.0 i386 [installed,local] +not-obsolete/unstable 2.0 i386 [upgradable from: 1.0]" apt list '?installed' + +testsuccessequal "Listing... +available/unstable 1.0 all +conf-only/now 1.0 i386 [residual-config] +foreign/unstable 2.0 amd64" apt list '?not(?installed)' + testsuccessequal "Listing... automatic1/now 1.0 i386 [installed,local] automatic2/now 1.0 i386 [installed,local]" apt list '?name(^automatic)' -- cgit v1.2.3-70-g09d2 From 9282c9094ab3e77cebe90e97b2f9a5fc21463e2f Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 15 Aug 2019 13:32:54 +0200 Subject: Add ?broken pattern This matches all packages that have broken dependencies in the installed version or the version selected for install. --- apt-pkg/cachefilter-patterns.cc | 2 ++ apt-pkg/cachefilter-patterns.h | 12 ++++++++++++ doc/apt-patterns.7.xml | 3 +++ test/integration/test-apt-patterns | 3 +++ 4 files changed, 20 insertions(+) (limited to 'doc') diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index 0f23890b4..a180cf78e 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -212,6 +212,8 @@ std::unique_ptr PatternParser::aPattern(std::unique_p return std::make_unique(aWord(node->arguments[0])); if (node->matches("?automatic", 0, 0)) return std::make_unique(file); + if (node->matches("?broken", 0, 0)) + return std::make_unique(file); if (node->matches("?config-files", 0, 0)) return std::make_unique(); if (node->matches("?false", 0, 0)) diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 7770385c9..c219e5bcd 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -128,6 +128,18 @@ struct PackageIsAutomatic : public PackageMatcher } }; +struct PackageIsBroken : public PackageMatcher +{ + pkgCacheFile *Cache; + explicit PackageIsBroken(pkgCacheFile *Cache) : Cache(Cache) {} + bool operator()(pkgCache::PkgIterator const &Pkg) override + { + assert(Cache != nullptr); + auto state = (*Cache)[Pkg]; + return state.InstBroken() || state.NowBroken(); + } +}; + struct PackageIsConfigFiles : public PackageMatcher { bool operator()(pkgCache::PkgIterator const &Pkg) override diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index 64dad4dd4..e1c64de8e 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -72,6 +72,9 @@ ?automatic Selects packages that were installed automatically. + ?broken + Selects packages that have broken dependencies. + ?config-files Selects packages that are not fully installed, but have solely residual configuration files left. diff --git a/test/integration/test-apt-patterns b/test/integration/test-apt-patterns index b84605256..e566c6bd2 100755 --- a/test/integration/test-apt-patterns +++ b/test/integration/test-apt-patterns @@ -116,6 +116,9 @@ testsuccessequal "Listing... automatic1/now 1.0 i386 [installed,local] automatic2/now 1.0 i386 [installed,local]" apt list '?automatic' +testsuccessequal "Listing... +broken/now 1.0 i386 [installed,local]" apt list '?broken' + testsuccessequal "Listing... conf-only/now 1.0 i386 [residual-config]" apt list '?config-files' -- cgit v1.2.3-70-g09d2 From 08762e0e4e2923360339eeb4d8ed26a00d7f1de5 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 15 Aug 2019 13:35:01 +0200 Subject: Add ?essential pattern This matches all packages where at least one of the versions is marked essential; or well, whenver apt considers a package essential. --- apt-pkg/cachefilter-patterns.cc | 2 ++ apt-pkg/cachefilter-patterns.h | 7 +++++++ doc/apt-patterns.7.xml | 3 +++ test/integration/test-apt-patterns | 3 +++ 4 files changed, 15 insertions(+) (limited to 'doc') diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index a180cf78e..ea35b9c46 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -216,6 +216,8 @@ std::unique_ptr PatternParser::aPattern(std::unique_p return std::make_unique(file); if (node->matches("?config-files", 0, 0)) return std::make_unique(); + if (node->matches("?essential", 0, 0)) + return std::make_unique(); if (node->matches("?false", 0, 0)) return std::make_unique(); if (node->matches("?garbage", 0, 0)) diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index c219e5bcd..17f1fc752 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -158,6 +158,13 @@ struct PackageIsGarbage : public PackageMatcher return (*Cache)[Pkg].Garbage; } }; +struct PackageIsEssential : public PackageMatcher +{ + bool operator()(pkgCache::PkgIterator const &Pkg) override + { + return (Pkg->Flags & pkgCache::Flag::Essential) != 0; + } +}; struct PackageIsInstalled : public PackageMatcher { diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index e1c64de8e..11031be95 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -78,6 +78,9 @@ ?config-files Selects packages that are not fully installed, but have solely residual configuration files left. + ?essential + Selects packages that have Essential: yes set in their control file. + ?garbage Selects packages that can be removed automatically. diff --git a/test/integration/test-apt-patterns b/test/integration/test-apt-patterns index e566c6bd2..1efb10d2d 100755 --- a/test/integration/test-apt-patterns +++ b/test/integration/test-apt-patterns @@ -122,6 +122,9 @@ broken/now 1.0 i386 [installed,local]" apt list '?broken' testsuccessequal "Listing... conf-only/now 1.0 i386 [residual-config]" apt list '?config-files' +testsuccessequal "Listing... +essential/now 1.0 i386 [installed,local]" apt list '?essential' + testsuccessequal "Listing... automatic2/now 1.0 i386 [installed,local]" apt list '?garbage' -- cgit v1.2.3-70-g09d2 From af674d82d5cd36e22223ec49675d32adad07e0a9 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 15 Aug 2019 13:36:04 +0200 Subject: Add the ?exact-name pattern The ?exact-name pattern matches the name exactly, there is no substring matching going on, or any regular expression or fnmatch magic. --- apt-pkg/cachefilter-patterns.cc | 2 ++ apt-pkg/cachefilter-patterns.h | 10 ++++++++++ doc/apt-patterns.7.xml | 3 +++ test/integration/test-apt-patterns | 4 ++++ 4 files changed, 19 insertions(+) (limited to 'doc') diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index ea35b9c46..f078924ff 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -218,6 +218,8 @@ std::unique_ptr PatternParser::aPattern(std::unique_p return std::make_unique(); if (node->matches("?essential", 0, 0)) return std::make_unique(); + if (node->matches("?exact-name", 1, 1)) + return std::make_unique(aWord(node->arguments[0])); if (node->matches("?false", 0, 0)) return std::make_unique(); if (node->matches("?garbage", 0, 0)) diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 17f1fc752..993839425 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -166,6 +166,16 @@ struct PackageIsEssential : public PackageMatcher } }; +struct PackageHasExactName : public PackageMatcher +{ + std::string name; + explicit PackageHasExactName(std::string name) : name(name) {} + bool operator()(pkgCache::PkgIterator const &Pkg) override + { + return Pkg.Name() == name; + } +}; + struct PackageIsInstalled : public PackageMatcher { pkgCacheFile *Cache; diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index 11031be95..2eda77b55 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -81,6 +81,9 @@ ?essential Selects packages that have Essential: yes set in their control file. + ?exact-name(NAME) + Selects packages with the exact specified name. + ?garbage Selects packages that can be removed automatically. diff --git a/test/integration/test-apt-patterns b/test/integration/test-apt-patterns index 1efb10d2d..c75793e55 100755 --- a/test/integration/test-apt-patterns +++ b/test/integration/test-apt-patterns @@ -125,6 +125,10 @@ conf-only/now 1.0 i386 [residual-config]" apt list '?config-files' testsuccessequal "Listing... essential/now 1.0 i386 [installed,local]" apt list '?essential' +testsuccessequal "Listing..." apt list '?exact-name(automatic)' +testsuccessequal "Listing... +automatic1/now 1.0 i386 [installed,local]" apt list '?exact-name(automatic1)' + testsuccessequal "Listing... automatic2/now 1.0 i386 [installed,local]" apt list '?garbage' -- cgit v1.2.3-70-g09d2 From c94b507b92b3d833761f3e416d4d5bba709bf87f Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 15 Aug 2019 13:40:31 +0200 Subject: Add ?virtual pattern This matches any package that does not have versions. --- apt-pkg/cachefilter-patterns.cc | 2 ++ apt-pkg/cachefilter-patterns.h | 8 ++++++++ doc/apt-patterns.7.xml | 5 +++++ test/integration/test-apt-patterns | 6 ++++++ 4 files changed, 21 insertions(+) (limited to 'doc') diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index f078924ff..986faaf52 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -236,6 +236,8 @@ std::unique_ptr PatternParser::aPattern(std::unique_p return std::make_unique(); if (node->matches("?upgradable", 0, 0)) return std::make_unique(file); + if (node->matches("?virtual", 0, 0)) + return std::make_unique(); if (node->matches("?x-name-fnmatch", 1, 1)) return std::make_unique(aWord(node->arguments[0])); diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 993839425..d37da815f 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -221,6 +221,14 @@ struct PackageIsUpgradable : public PackageMatcher return Pkg->CurrentVer != 0 && (*Cache)[Pkg].Upgradable(); } }; + +struct PackageIsVirtual : public PackageMatcher +{ + bool operator()(pkgCache::PkgIterator const &Pkg) override + { + return Pkg->VersionList == 0; + } +}; } // namespace Patterns } // namespace Internal } // namespace APT diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index 2eda77b55..efd4293dc 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -99,6 +99,11 @@ ?upgradable Selects packages that can be upgraded (have a newer candidate). + ?virtual + Selects all virtual packages; that is packages without a version. + These exist when they are referenced somewhere in the archive, + for example because something depends on that name. + diff --git a/test/integration/test-apt-patterns b/test/integration/test-apt-patterns index c75793e55..92c76edd1 100755 --- a/test/integration/test-apt-patterns +++ b/test/integration/test-apt-patterns @@ -161,6 +161,12 @@ testsuccessequal "Listing... not-obsolete/unstable 2.0 i386 [upgradable from: 1.0] N: There is 1 additional version. Please use the '-a' switch to see it" apt list '?upgradable' +testsuccessequal "Package: does-not-exist +State: not a real package (virtual) +N: Can't select candidate version from package does-not-exist as it has no candidate +N: Can't select versions from package 'does-not-exist' as it is purely virtual +N: No packages found" apt show '?virtual' + testsuccessequal "Listing..." apt list '?x-name-fnmatch(1)' testsuccessequal "Listing... automatic1/now 1.0 i386 [installed,local] -- cgit v1.2.3-70-g09d2