private-search.cc 3.8 KB

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