private-search.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. std::vector<bool> PkgsDone(Cache->Head().PackageCount, false);
  67. for ( ;V != bag.end(); ++V)
  68. {
  69. if (Done%500 == 0)
  70. progress.Progress(Done);
  71. ++Done;
  72. // we want to list each package only once
  73. pkgCache::PkgIterator const P = V.ParentPkg();
  74. if (PkgsDone[P->ID] == true)
  75. continue;
  76. char const * const PkgName = P.Name();
  77. pkgCache::DescIterator Desc = V.TranslatedDescription();
  78. pkgRecords::Parser &parser = records.Lookup(Desc.FileList());
  79. std::string const LongDesc = parser.LongDesc();
  80. bool all_found = true;
  81. for (std::vector<regex_t>::const_iterator pattern = Patterns.begin();
  82. pattern != Patterns.end(); ++pattern)
  83. {
  84. if (regexec(&(*pattern), PkgName, 0, 0, 0) == 0)
  85. continue;
  86. else if (NamesOnly == false && regexec(&(*pattern), LongDesc.c_str(), 0, 0, 0) == 0)
  87. continue;
  88. // search patterns are AND, so one failing fails all
  89. all_found = false;
  90. break;
  91. }
  92. if (all_found == true)
  93. {
  94. PkgsDone[P->ID] = true;
  95. std::stringstream outs;
  96. ListSingleVersion(CacheFile, records, V, outs, format);
  97. output_map.insert(std::make_pair<std::string, std::string>(
  98. PkgName, outs.str()));
  99. }
  100. }
  101. APT_FREE_PATTERNS();
  102. progress.Done();
  103. // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
  104. // output the sorted map
  105. std::map<std::string, std::string>::const_iterator K;
  106. for (K = output_map.begin(); K != output_map.end(); ++K)
  107. std::cout << (*K).second << std::endl;
  108. return true;
  109. }
  110. /*}}}*/