From fd43b1694f1382a3a47f5dc546ebe3d39fcd6e7d Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 20 Jan 2020 14:14:49 +0100 Subject: 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. --- doc/apt-patterns.7.xml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'doc') diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index b94a9b226..f18fe6a19 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -46,7 +46,7 @@ ?and(PATTERN, PATTERN, ...) Selects objects where all specified patterns match. - ?false + ?false~F Selects nothing. ?not(PATTERN) @@ -55,7 +55,7 @@ ?or(PATTERN, PATTERN, ...) Selects objects where at least one of the specified patterns match. - ?true + ?true~T Selects all objects. @@ -83,40 +83,40 @@ These patterns select specific packages. - ?architecture(WILDCARD) + ?architecture(WILDCARD)~rWILDCARD Selects packages matching the specified architecture, which may contain wildcards using any. - ?automatic + ?automatic~M Selects packages that were installed automatically. - ?broken + ?broken~b Selects packages that have broken dependencies. - ?config-files + ?config-files~c Selects packages that are not fully installed, but have solely residual configuration files left. - ?essential + ?essential~E Selects packages that have Essential: yes set in their control file. ?exact-name(NAME) Selects packages with the exact specified name. - ?garbage + ?garbage~g Selects packages that can be removed automatically. - ?installed + ?installed~i Selects packages that are currently installed. - ?name(REGEX) + ?name(REGEX)~nREGEX Selects packages where the name matches the given regular expression. - ?obsolete + ?obsolete~o Selects packages that no longer exist in repositories. - ?upgradable + ?upgradable~U Selects packages that can be upgraded (have a newer candidate). - ?virtual + ?virtual~v 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. @@ -129,22 +129,22 @@ These patterns select specific versions of a package. - ?archive(REGEX) + ?archive(REGEX)~AREGEX Selects versions that come from the archive that matches the specified regular expression. Archive, here, means the values after a= in apt-cache policy. - ?origin(REGEX) + ?origin(REGEX)~OREGEX Selects versions that come from the origin that matches the specified regular expression. Origin, here, means the values after o= in apt-cache policy. - ?section(REGEX) + ?section(REGEX)~sREGEX Selects versions where the section matches the specified regular expression. - ?source-package(REGEX) + ?source-package(REGEX)~eREGEX Selects versions where the source package name matches the specified regular expression. ?source-version(REGEX) Selects versions where the source package version matches the specified regular expression. - ?version(REGEX) + ?version(REGEX)~VREGEX Selects versions where the version string matching the specified regular expression. -- cgit v1.2.3-70-g09d2 From 8d4967d3a187dd66cf14b070a9db63f8ea21b21f Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 28 Jan 2020 21:46:10 +0100 Subject: patterns: Implement unary ! --- apt-pkg/cachefilter-patterns.cc | 28 +++++++++++++++++++++++++++- apt-pkg/cachefilter-patterns.h | 2 ++ doc/apt-patterns.7.xml | 2 +- test/libapt/pattern_test.cc | 1 + 4 files changed, 31 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index 11ad5d723..9fab0281d 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -66,6 +66,32 @@ std::unique_ptr PatternTreeParser::parseTop() // Parse any pattern std::unique_ptr PatternTreeParser::parse() +{ + return parseUnary(); +} + +std::unique_ptr PatternTreeParser::parseUnary() +{ + + if (sentence[state.offset] != '!') + return parsePrimary(); + + auto start = ++state.offset; + auto primary = parsePrimary(); + + if (primary == nullptr) + throw Error{Node{start, sentence.size()}, "Expected pattern"}; + + auto node = std::make_unique(); + node->start = start; + node->end = primary->end; + node->term = "?not"; + node->arguments.push_back(std::move(primary)); + node->haveArgumentList = true; + return node; +} + +std::unique_ptr PatternTreeParser::parsePrimary() { std::unique_ptr node; if ((node = parseShortPattern()) != nullptr) @@ -198,7 +224,7 @@ std::unique_ptr PatternTreeParser::parseQuotedWord() // Parse a bare word atom std::unique_ptr PatternTreeParser::parseWord() { - static const constexpr auto DISALLOWED_START = "?~,()\0"_sv; + static const constexpr auto DISALLOWED_START = "!?~,()\0"_sv; static const constexpr auto DISALLOWED = ",()\0"_sv; if (DISALLOWED_START.find(sentence[state.offset]) != APT::StringView::npos) return nullptr; diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 0d6e9d99e..76318eafa 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -95,6 +95,8 @@ struct PatternTreeParser private: std::unique_ptr parse(); + std::unique_ptr parseUnary(); + std::unique_ptr parsePrimary(); std::unique_ptr parsePattern(); std::unique_ptr parseShortPattern(); std::unique_ptr parseWord(); diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index f18fe6a19..72f1ccbce 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -49,7 +49,7 @@ ?false~F Selects nothing. - ?not(PATTERN) + ?not(PATTERN)!PATTERN Selects objects where PATTERN does not match. ?or(PATTERN, PATTERN, ...) diff --git a/test/libapt/pattern_test.cc b/test/libapt/pattern_test.cc index 492a29eac..39959cd31 100644 --- a/test/libapt/pattern_test.cc +++ b/test/libapt/pattern_test.cc @@ -158,4 +158,5 @@ TEST(TreeParserTest, ParseShortPattern) EXPECT_PATTERN_EQ_ATOMIC("~U", "?upgradable"); EXPECT_PATTERN_EQ("~Vverstr", "?version(verstr)"); EXPECT_PATTERN_EQ_ATOMIC("~v", "?virtual"); + EXPECT_PATTERN_EQ("!foo", "?not(foo)"); } -- cgit v1.2.3-70-g09d2 From 250119362e44599aad7e75462fa4298ad1ab1ad9 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 28 Jan 2020 22:38:46 +0100 Subject: patterns: Parse sequence of patterns as ?and --- apt-pkg/cachefilter-patterns.cc | 32 +++++++++++++++++++++++++++++++- apt-pkg/cachefilter-patterns.h | 1 + doc/apt-patterns.7.xml | 2 +- test/libapt/pattern_test.cc | 8 ++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/apt-pkg/cachefilter-patterns.cc b/apt-pkg/cachefilter-patterns.cc index cf3e59ac6..dbf58e2a9 100644 --- a/apt-pkg/cachefilter-patterns.cc +++ b/apt-pkg/cachefilter-patterns.cc @@ -70,7 +70,37 @@ std::unique_ptr PatternTreeParser::parseTop() // Parse any pattern std::unique_ptr PatternTreeParser::parse() { - return parseUnary(); + return parseAnd(); +} + +std::unique_ptr PatternTreeParser::parseAnd() +{ + auto start = state.offset; + std::vector> nodes; + + for (skipSpace(); state.offset < sentence.size(); skipSpace()) + { + auto node = parseUnary(); + + if (node == nullptr) + break; + + nodes.push_back(std::move(node)); + } + + if (nodes.size() == 0) + return nullptr; + if (nodes.size() == 1) + return std::move(nodes[0]); + + auto node = std::make_unique(); + node->start = start; + node->end = nodes[nodes.size() - 1]->end; + node->term = "?and"; + node->arguments = std::move(nodes); + node->haveArgumentList = true; + + return node; } std::unique_ptr PatternTreeParser::parseUnary() diff --git a/apt-pkg/cachefilter-patterns.h b/apt-pkg/cachefilter-patterns.h index 1770c7307..7f30a3ea0 100644 --- a/apt-pkg/cachefilter-patterns.h +++ b/apt-pkg/cachefilter-patterns.h @@ -95,6 +95,7 @@ struct PatternTreeParser private: std::unique_ptr parse(); + std::unique_ptr parseAnd(); std::unique_ptr parseUnary(); std::unique_ptr parsePrimary(); std::unique_ptr parsePattern(); diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index 72f1ccbce..3de9b00fc 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -43,7 +43,7 @@ patterns. - ?and(PATTERN, PATTERN, ...) + ?and(PATTERN, PATTERN, ...)PATTERN PATTERN ... Selects objects where all specified patterns match. ?false~F diff --git a/test/libapt/pattern_test.cc b/test/libapt/pattern_test.cc index 7fc6a1f8f..00d356d47 100644 --- a/test/libapt/pattern_test.cc +++ b/test/libapt/pattern_test.cc @@ -176,4 +176,12 @@ TEST(TreeParserTest, ParseShortPattern) caught = true; }; EXPECT_TRUE(caught) << "!X should have thrown an exception"; + + EXPECT_PATTERN_EQ("?a?b", "?and(?a, ?b)"); + EXPECT_PATTERN_EQ("~T~F", "?and(?true, ?false)"); + EXPECT_PATTERN_EQ("~T ~F", "?and(?true, ?false)"); + EXPECT_PATTERN_EQ("~T !~F", "?and(?true, ?not(?false))"); + EXPECT_PATTERN_EQ("!~F ~T", "?and(?not(?false), ?true)"); + EXPECT_PATTERN_EQ("!~F~T", "?and(?not(?false), ?true)"); + } -- cgit v1.2.3-70-g09d2 From 775be4274e5c5427079e26d3ebe3c7f2f5f6b76a Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 28 Jan 2020 23:41:54 +0100 Subject: apt-patterns(7): Some updates and rationale --- doc/apt-patterns.7.xml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/apt-patterns.7.xml b/doc/apt-patterns.7.xml index 3de9b00fc..6fa945058 100644 --- a/doc/apt-patterns.7.xml +++ b/doc/apt-patterns.7.xml @@ -167,9 +167,6 @@ 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. @@ -193,6 +190,16 @@ ?narrow accepts infinite arguments + + foo cannot be used as a shortform for ?name(foo), as this can cause typos to go unnoticed: + Consider ?and(...,~poptional): + this requires the package to have required priority, but + if you do not type the ~, it would require the package name to contain poptional. + + + Grouping patterns with (...) or writing ?or(A,B) as A|B are not supported. We + do not believe that the use of | is that common, and the grouping is not necessary without it. + -- cgit v1.2.3-70-g09d2