private-cacheset.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #ifndef APT_PRIVATE_CACHESET_H
  2. #define APT_PRIVATE_CACHESET_H
  3. #include <apt-pkg/cachefile.h>
  4. #include <apt-pkg/cacheset.h>
  5. #include <apt-pkg/sptr.h>
  6. #include <algorithm>
  7. #include <vector>
  8. #include "private-output.h"
  9. #include <apti18n.h>
  10. struct VersionSortDescriptionLocality
  11. {
  12. bool operator () (const pkgCache::VerIterator &v_lhs,
  13. const pkgCache::VerIterator &v_rhs)
  14. {
  15. pkgCache::DescFile *A = v_lhs.TranslatedDescription().FileList();
  16. pkgCache::DescFile *B = v_rhs.TranslatedDescription().FileList();
  17. if (A == 0 && B == 0)
  18. return false;
  19. if (A == 0)
  20. return true;
  21. if (B == 0)
  22. return false;
  23. if (A->File == B->File)
  24. return A->Offset < B->Offset;
  25. return A->File < B->File;
  26. }
  27. };
  28. // sorted by locality which makes iterating much faster
  29. typedef APT::VersionContainer<
  30. std::set<pkgCache::VerIterator,
  31. VersionSortDescriptionLocality> > LocalitySortedVersionSet;
  32. class Matcher {
  33. public:
  34. virtual bool operator () (const pkgCache::PkgIterator &P) {
  35. return true;};
  36. };
  37. // FIXME: add default argument for OpProgress (or overloaded function)
  38. bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
  39. LocalitySortedVersionSet &output_set,
  40. Matcher &matcher,
  41. OpProgress &progress);
  42. bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
  43. LocalitySortedVersionSet &output_set,
  44. OpProgress &progress);
  45. // CacheSetHelper saving virtual packages /*{{{*/
  46. class CacheSetHelperVirtuals: public APT::CacheSetHelper {
  47. public:
  48. APT::PackageSet virtualPkgs;
  49. virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
  50. virtualPkgs.insert(Pkg);
  51. return CacheSetHelper::canNotFindCandidateVer(Cache, Pkg);
  52. }
  53. virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
  54. virtualPkgs.insert(Pkg);
  55. return CacheSetHelper::canNotFindNewestVer(Cache, Pkg);
  56. }
  57. virtual void canNotFindAllVer(APT::VersionContainerInterface * vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
  58. virtualPkgs.insert(Pkg);
  59. CacheSetHelper::canNotFindAllVer(vci, Cache, Pkg);
  60. }
  61. CacheSetHelperVirtuals(bool const ShowErrors = true, GlobalError::MsgType const &ErrorType = GlobalError::NOTICE) : CacheSetHelper(ShowErrors, ErrorType) {}
  62. };
  63. /*}}}*/
  64. // CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/
  65. class CacheSetHelperAPTGet : public APT::CacheSetHelper {
  66. /** \brief stream message should be printed to */
  67. std::ostream &out;
  68. /** \brief were things like Task or RegEx used to select packages? */
  69. bool explicitlyNamed;
  70. APT::PackageSet virtualPkgs;
  71. public:
  72. std::list<std::pair<pkgCache::VerIterator, std::string> > selectedByRelease;
  73. CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) {
  74. explicitlyNamed = true;
  75. }
  76. virtual void showTaskSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) {
  77. ioprintf(out, _("Note, selecting '%s' for task '%s'\n"),
  78. Pkg.FullName(true).c_str(), pattern.c_str());
  79. explicitlyNamed = false;
  80. }
  81. virtual void showRegExSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) {
  82. ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"),
  83. Pkg.FullName(true).c_str(), pattern.c_str());
  84. explicitlyNamed = false;
  85. }
  86. virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
  87. std::string const &ver, bool const verIsRel) {
  88. if (ver == Ver.VerStr())
  89. return;
  90. selectedByRelease.push_back(make_pair(Ver, ver));
  91. }
  92. bool showVirtualPackageErrors(pkgCacheFile &Cache) {
  93. if (virtualPkgs.empty() == true)
  94. return true;
  95. for (APT::PackageSet::const_iterator Pkg = virtualPkgs.begin();
  96. Pkg != virtualPkgs.end(); ++Pkg) {
  97. if (Pkg->ProvidesList != 0) {
  98. ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
  99. Pkg.FullName(true).c_str());
  100. pkgCache::PrvIterator I = Pkg.ProvidesList();
  101. unsigned short provider = 0;
  102. for (; I.end() == false; ++I) {
  103. pkgCache::PkgIterator Pkg = I.OwnerPkg();
  104. if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer()) {
  105. c1out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr();
  106. if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
  107. c1out << _(" [Installed]");
  108. c1out << std::endl;
  109. ++provider;
  110. }
  111. }
  112. // if we found no candidate which provide this package, show non-candidates
  113. if (provider == 0)
  114. for (I = Pkg.ProvidesList(); I.end() == false; ++I)
  115. c1out << " " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr()
  116. << _(" [Not candidate version]") << std::endl;
  117. else
  118. out << _("You should explicitly select one to install.") << std::endl;
  119. } else {
  120. ioprintf(c1out,
  121. _("Package %s is not available, but is referred to by another package.\n"
  122. "This may mean that the package is missing, has been obsoleted, or\n"
  123. "is only available from another source\n"),Pkg.FullName(true).c_str());
  124. std::string List;
  125. std::string VersionsList;
  126. SPtrArray<bool> Seen = new bool[Cache.GetPkgCache()->Head().PackageCount];
  127. memset(Seen,0,Cache.GetPkgCache()->Head().PackageCount*sizeof(*Seen));
  128. for (pkgCache::DepIterator Dep = Pkg.RevDependsList();
  129. Dep.end() == false; ++Dep) {
  130. if (Dep->Type != pkgCache::Dep::Replaces)
  131. continue;
  132. if (Seen[Dep.ParentPkg()->ID] == true)
  133. continue;
  134. Seen[Dep.ParentPkg()->ID] = true;
  135. List += Dep.ParentPkg().FullName(true) + " ";
  136. //VersionsList += std::string(Dep.ParentPkg().CurVersion) + "\n"; ???
  137. }
  138. ShowList(c1out,_("However the following packages replace it:"),List,VersionsList);
  139. }
  140. c1out << std::endl;
  141. }
  142. return false;
  143. }
  144. virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
  145. APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDIDATE);
  146. if (verset.empty() == false)
  147. return *(verset.begin());
  148. else if (ShowError == true) {
  149. _error->Error(_("Package '%s' has no installation candidate"),Pkg.FullName(true).c_str());
  150. virtualPkgs.insert(Pkg);
  151. }
  152. return pkgCache::VerIterator(Cache, 0);
  153. }
  154. virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
  155. if (Pkg->ProvidesList != 0)
  156. {
  157. APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST);
  158. if (verset.empty() == false)
  159. return *(verset.begin());
  160. if (ShowError == true)
  161. ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str());
  162. }
  163. else
  164. {
  165. pkgCache::GrpIterator Grp = Pkg.Group();
  166. pkgCache::PkgIterator P = Grp.PackageList();
  167. for (; P.end() != true; P = Grp.NextPkg(P))
  168. {
  169. if (P == Pkg)
  170. continue;
  171. if (P->CurrentVer != 0) {
  172. // TRANSLATORS: Note, this is not an interactive question
  173. ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
  174. Pkg.FullName(true).c_str(), P.FullName(true).c_str());
  175. break;
  176. }
  177. }
  178. if (P.end() == true)
  179. ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
  180. }
  181. return pkgCache::VerIterator(Cache, 0);
  182. }
  183. APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg,
  184. APT::VersionSet::Version const &select) {
  185. /* This is a pure virtual package and there is a single available
  186. candidate providing it. */
  187. if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0)
  188. return APT::VersionSet();
  189. pkgCache::PkgIterator Prov;
  190. bool found_one = false;
  191. for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; ++P) {
  192. pkgCache::VerIterator const PVer = P.OwnerVer();
  193. pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
  194. /* Ignore versions that are not a candidate. */
  195. if (Cache[PPkg].CandidateVer != PVer)
  196. continue;
  197. if (found_one == false) {
  198. Prov = PPkg;
  199. found_one = true;
  200. } else if (PPkg != Prov) {
  201. // same group, so it's a foreign package
  202. if (PPkg->Group == Prov->Group) {
  203. // do we already have the requested arch?
  204. if (strcmp(Pkg.Arch(), Prov.Arch()) == 0 ||
  205. strcmp(Prov.Arch(), "all") == 0 ||
  206. unlikely(strcmp(PPkg.Arch(), Prov.Arch()) == 0)) // packages have only on candidate, but just to be sure
  207. continue;
  208. // see which architecture we prefer more and switch to it
  209. std::vector<std::string> archs = APT::Configuration::getArchitectures();
  210. if (std::find(archs.begin(), archs.end(), PPkg.Arch()) < std::find(archs.begin(), archs.end(), Prov.Arch()))
  211. Prov = PPkg;
  212. continue;
  213. }
  214. found_one = false; // we found at least two
  215. break;
  216. }
  217. }
  218. if (found_one == true) {
  219. ioprintf(out, _("Note, selecting '%s' instead of '%s'\n"),
  220. Prov.FullName(true).c_str(), Pkg.FullName(true).c_str());
  221. return APT::VersionSet::FromPackage(Cache, Prov, select, *this);
  222. }
  223. return APT::VersionSet();
  224. }
  225. inline bool allPkgNamedExplicitly() const { return explicitlyNamed; }
  226. };
  227. /*}}}*/
  228. #endif