From 859093dae7dcadaff2e15a3885a1824b0d5f5913 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 30 Aug 2014 11:29:45 +0200 Subject: support regular expressions in 'apt search' apt-cache search supported this since ever and in the code for apt was a fixme indicating this should be added here as well, so here we go. --- apt-private/private-search.cc | 52 +++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 17 deletions(-) (limited to 'apt-private/private-search.cc') diff --git a/apt-private/private-search.cc b/apt-private/private-search.cc index ecd5d7fad..2230c973a 100644 --- a/apt-private/private-search.cc +++ b/apt-private/private-search.cc @@ -36,8 +36,28 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ if (unlikely(Cache == NULL || Plcy == NULL)) return false; - const char **patterns; - patterns = CmdL.FileList + 1; + // Make sure there is at least one argument + unsigned int const NumPatterns = CmdL.FileSize() -1; + if (NumPatterns < 1) + return _error->Error(_("You must give at least one search pattern")); + +#define APT_FREE_PATTERNS() for (std::vector::iterator P = Patterns.begin(); \ + P != Patterns.end(); ++P) { regfree(&(*P)); } + + // Compile the regex pattern + std::vector Patterns; + for (unsigned int I = 0; I != NumPatterns; ++I) + { + regex_t pattern; + if (regcomp(&pattern, CmdL.FileList[I + 1], REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0) + { + APT_FREE_PATTERNS(); + return _error->Error("Regex compilation error"); + } + Patterns.push_back(pattern); + } + + bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly", false); std::map output_map; std::map::const_iterator K; @@ -56,26 +76,23 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ if (Done%500 == 0) progress.Progress(Done); ++Done; - - int i; + pkgCache::DescIterator Desc = V.TranslatedDescription(); pkgRecords::Parser &parser = records.Lookup(Desc.FileList()); - + bool all_found = true; - for(i=0; patterns[i] != NULL; ++i) + for (std::vector::const_iterator pattern = Patterns.begin(); + pattern != Patterns.end(); ++pattern) { - // FIXME: use regexp instead of simple find() - const char *pattern = patterns[i]; - all_found &= ( - strstr(V.ParentPkg().Name(), pattern) != NULL || - strcasestr(parser.ShortDesc().c_str(), pattern) != NULL || - strcasestr(parser.LongDesc().c_str(), pattern) != NULL); - // search patterns are AND by default so we can skip looking further - // on the first mismatch - if(all_found == false) - break; + if (regexec(&(*pattern), V.ParentPkg().Name(), 0, 0, 0) == 0) + continue; + else if (NamesOnly == false && regexec(&(*pattern), parser.LongDesc().c_str(), 0, 0, 0) == 0) + continue; + // search patterns are AND, so one failing fails all + all_found = false; + break; } - if (all_found) + if (all_found == true) { std::stringstream outs; ListSingleVersion(CacheFile, records, V, outs); @@ -83,6 +100,7 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ V.ParentPkg().Name(), outs.str())); } } + APT_FREE_PATTERNS(); progress.Done(); // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status) -- cgit v1.2.3 From 206b6bb3ec7d4cf45f3ae67e6d317f1da63f5b98 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 1 Sep 2014 19:09:40 +0200 Subject: skip version if we already have this package as search-result Git-Dch: Ignore --- apt-private/private-search.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'apt-private/private-search.cc') diff --git a/apt-private/private-search.cc b/apt-private/private-search.cc index 2230c973a..2d427fa25 100644 --- a/apt-private/private-search.cc +++ b/apt-private/private-search.cc @@ -32,7 +32,6 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ pkgCacheFile CacheFile; pkgCache *Cache = CacheFile.GetPkgCache(); pkgDepCache::Policy *Plcy = CacheFile.GetPolicy(); - pkgRecords records(CacheFile); if (unlikely(Cache == NULL || Plcy == NULL)) return false; @@ -60,7 +59,6 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly", false); std::map output_map; - std::map::const_iterator K; LocalitySortedVersionSet bag; OpTextProgress progress(*_config); @@ -70,6 +68,7 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ progress.OverallProgress(50, 100, 50, _("Full Text Search")); progress.SubProgress(bag.size()); + pkgRecords records(CacheFile); int Done = 0; for ( ;V != bag.end(); ++V) { @@ -77,16 +76,22 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ progress.Progress(Done); ++Done; + // we want to list each package only once + char const * const PkgName = V.ParentPkg().Name(); + if (output_map.find(PkgName) != output_map.end()) + continue; + pkgCache::DescIterator Desc = V.TranslatedDescription(); pkgRecords::Parser &parser = records.Lookup(Desc.FileList()); + std::string const LongDesc = parser.LongDesc(); bool all_found = true; for (std::vector::const_iterator pattern = Patterns.begin(); pattern != Patterns.end(); ++pattern) { - if (regexec(&(*pattern), V.ParentPkg().Name(), 0, 0, 0) == 0) + if (regexec(&(*pattern), PkgName, 0, 0, 0) == 0) continue; - else if (NamesOnly == false && regexec(&(*pattern), parser.LongDesc().c_str(), 0, 0, 0) == 0) + else if (NamesOnly == false && regexec(&(*pattern), LongDesc.c_str(), 0, 0, 0) == 0) continue; // search patterns are AND, so one failing fails all all_found = false; @@ -97,7 +102,7 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ std::stringstream outs; ListSingleVersion(CacheFile, records, V, outs); output_map.insert(std::make_pair( - V.ParentPkg().Name(), outs.str())); + PkgName, outs.str())); } } APT_FREE_PATTERNS(); @@ -105,6 +110,7 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status) // output the sorted map + std::map::const_iterator K; for (K = output_map.begin(); K != output_map.end(); ++K) std::cout << (*K).second << std::endl; -- cgit v1.2.3 From 1a68655de92fd036ebc7c920bc2e5e88c54eb34e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 2 Sep 2014 14:32:48 +0200 Subject: implement --full in apt search --- apt-private/private-search.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'apt-private/private-search.cc') diff --git a/apt-private/private-search.cc b/apt-private/private-search.cc index 2d427fa25..5e12902e8 100644 --- a/apt-private/private-search.cc +++ b/apt-private/private-search.cc @@ -69,6 +69,13 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ progress.OverallProgress(50, 100, 50, _("Full Text Search")); progress.SubProgress(bag.size()); pkgRecords records(CacheFile); + + std::string format = "${color:highlight}${Package}${color:neutral}/${Origin} ${Version} ${Architecture}${ }${apt:Status}\n"; + if (_config->FindB("APT::Cache::ShowFull",false) == false) + format += " ${Description}\n"; + else + format += " ${LongDescription}\n"; + int Done = 0; for ( ;V != bag.end(); ++V) { @@ -100,7 +107,7 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ if (all_found == true) { std::stringstream outs; - ListSingleVersion(CacheFile, records, V, outs); + ListSingleVersion(CacheFile, records, V, outs, format); output_map.insert(std::make_pair( PkgName, outs.str())); } -- cgit v1.2.3 From 25594bb5bddc031afc4d62f3164cd9116d778517 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 2 Sep 2014 18:20:49 +0200 Subject: make GetLocalitySortedVersionSet more generic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No reason in and of by itself at the moment, but prepares for the goal of having 'apt search' and 'apt-cache search' using the same code now that they at least support the same stuff. The 'apt' code is just a multitude slower at the moment… Git-Dch: Ignore --- apt-private/private-search.cc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'apt-private/private-search.cc') diff --git a/apt-private/private-search.cc b/apt-private/private-search.cc index 5e12902e8..6bce9ffa4 100644 --- a/apt-private/private-search.cc +++ b/apt-private/private-search.cc @@ -63,7 +63,7 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ LocalitySortedVersionSet bag; OpTextProgress progress(*_config); progress.OverallProgress(0, 100, 50, _("Sorting")); - GetLocalitySortedVersionSet(CacheFile, bag, progress); + GetLocalitySortedVersionSet(CacheFile, &bag, &progress); LocalitySortedVersionSet::iterator V = bag.begin(); progress.OverallProgress(50, 100, 50, _("Full Text Search")); @@ -77,6 +77,7 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ format += " ${LongDescription}\n"; int Done = 0; + std::vector PkgsDone(Cache->Head().PackageCount, false); for ( ;V != bag.end(); ++V) { if (Done%500 == 0) @@ -84,10 +85,11 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ ++Done; // we want to list each package only once - char const * const PkgName = V.ParentPkg().Name(); - if (output_map.find(PkgName) != output_map.end()) + pkgCache::PkgIterator const P = V.ParentPkg(); + if (PkgsDone[P->ID] == true) continue; + char const * const PkgName = P.Name(); pkgCache::DescIterator Desc = V.TranslatedDescription(); pkgRecords::Parser &parser = records.Lookup(Desc.FileList()); std::string const LongDesc = parser.LongDesc(); @@ -106,10 +108,11 @@ bool FullTextSearch(CommandLine &CmdL) /*{{{*/ } if (all_found == true) { - std::stringstream outs; - ListSingleVersion(CacheFile, records, V, outs, format); - output_map.insert(std::make_pair( - PkgName, outs.str())); + PkgsDone[P->ID] = true; + std::stringstream outs; + ListSingleVersion(CacheFile, records, V, outs, format); + output_map.insert(std::make_pair( + PkgName, outs.str())); } } APT_FREE_PATTERNS(); -- cgit v1.2.3