support regular expressions in 'apt search'
[ntk/apt.git] / apt-private / private-search.cc
CommitLineData
ee0167c4 1// Includes /*{{{*/
453b82a3
DK
2#include <config.h>
3
b9179170 4#include <apt-pkg/cachefile.h>
b9179170 5#include <apt-pkg/cacheset.h>
b9179170 6#include <apt-pkg/cmndline.h>
b9179170 7#include <apt-pkg/pkgrecords.h>
b9179170 8#include <apt-pkg/policy.h>
453b82a3
DK
9#include <apt-pkg/progress.h>
10#include <apt-pkg/cacheiterators.h>
11#include <apt-pkg/configuration.h>
12#include <apt-pkg/depcache.h>
13#include <apt-pkg/macros.h>
14#include <apt-pkg/pkgcache.h>
b9179170 15
453b82a3
DK
16#include <apt-private/private-cacheset.h>
17#include <apt-private/private-output.h>
18#include <apt-private/private-search.h>
19
20#include <string.h>
b9179170 21#include <iostream>
453b82a3 22#include <sstream>
b9179170 23#include <map>
453b82a3
DK
24#include <string>
25#include <utility>
b9179170 26
453b82a3 27#include <apti18n.h>
ee0167c4 28 /*}}}*/
b9179170 29
ee0167c4 30bool FullTextSearch(CommandLine &CmdL) /*{{{*/
b9179170
MV
31{
32 pkgCacheFile CacheFile;
33 pkgCache *Cache = CacheFile.GetPkgCache();
34 pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
35 pkgRecords records(CacheFile);
36 if (unlikely(Cache == NULL || Plcy == NULL))
37 return false;
38
859093da
DK
39 // Make sure there is at least one argument
40 unsigned int const NumPatterns = CmdL.FileSize() -1;
41 if (NumPatterns < 1)
42 return _error->Error(_("You must give at least one search pattern"));
43
44#define APT_FREE_PATTERNS() for (std::vector<regex_t>::iterator P = Patterns.begin(); \
45 P != Patterns.end(); ++P) { regfree(&(*P)); }
46
47 // Compile the regex pattern
48 std::vector<regex_t> Patterns;
49 for (unsigned int I = 0; I != NumPatterns; ++I)
50 {
51 regex_t pattern;
52 if (regcomp(&pattern, CmdL.FileList[I + 1], REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
53 {
54 APT_FREE_PATTERNS();
55 return _error->Error("Regex compilation error");
56 }
57 Patterns.push_back(pattern);
58 }
59
60 bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly", false);
b9179170
MV
61
62 std::map<std::string, std::string> output_map;
63 std::map<std::string, std::string>::const_iterator K;
64
65 LocalitySortedVersionSet bag;
1bef0dd5 66 OpTextProgress progress(*_config);
b9179170
MV
67 progress.OverallProgress(0, 100, 50, _("Sorting"));
68 GetLocalitySortedVersionSet(CacheFile, bag, progress);
69 LocalitySortedVersionSet::iterator V = bag.begin();
70
71 progress.OverallProgress(50, 100, 50, _("Full Text Search"));
72 progress.SubProgress(bag.size());
73 int Done = 0;
9ce3cfc9 74 for ( ;V != bag.end(); ++V)
b9179170
MV
75 {
76 if (Done%500 == 0)
77 progress.Progress(Done);
9ce3cfc9 78 ++Done;
859093da 79
b9179170
MV
80 pkgCache::DescIterator Desc = V.TranslatedDescription();
81 pkgRecords::Parser &parser = records.Lookup(Desc.FileList());
859093da 82
b9179170 83 bool all_found = true;
859093da
DK
84 for (std::vector<regex_t>::const_iterator pattern = Patterns.begin();
85 pattern != Patterns.end(); ++pattern)
b9179170 86 {
859093da
DK
87 if (regexec(&(*pattern), V.ParentPkg().Name(), 0, 0, 0) == 0)
88 continue;
89 else if (NamesOnly == false && regexec(&(*pattern), parser.LongDesc().c_str(), 0, 0, 0) == 0)
90 continue;
91 // search patterns are AND, so one failing fails all
92 all_found = false;
93 break;
b9179170 94 }
859093da 95 if (all_found == true)
b9179170
MV
96 {
97 std::stringstream outs;
98 ListSingleVersion(CacheFile, records, V, outs);
99 output_map.insert(std::make_pair<std::string, std::string>(
100 V.ParentPkg().Name(), outs.str()));
101 }
102 }
859093da 103 APT_FREE_PATTERNS();
b9179170
MV
104 progress.Done();
105
106 // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
107 // output the sorted map
9ce3cfc9 108 for (K = output_map.begin(); K != output_map.end(); ++K)
b9179170
MV
109 std::cout << (*K).second << std::endl;
110
111 return true;
112}
ee0167c4 113 /*}}}*/