private-cacheset.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. #include <config.h>
  2. #include <apt-pkg/cachefile.h>
  3. #include <apt-pkg/pkgcache.h>
  4. #include <apt-pkg/depcache.h>
  5. #include <apt-pkg/cacheiterators.h>
  6. #include <apt-pkg/aptconfiguration.h>
  7. #include <apt-pkg/configuration.h>
  8. #include <apt-pkg/progress.h>
  9. #include <apt-pkg/policy.h>
  10. #include <apt-pkg/strutl.h>
  11. #include <apt-private/private-cacheset.h>
  12. #include <stddef.h>
  13. #include <apti18n.h>
  14. bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, /*{{{*/
  15. APT::VersionContainerInterface * const vci,
  16. OpProgress * const progress)
  17. {
  18. Matcher null_matcher = Matcher();
  19. return GetLocalitySortedVersionSet(CacheFile, vci,
  20. null_matcher, progress);
  21. }
  22. bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
  23. APT::VersionContainerInterface * const vci,
  24. Matcher &matcher,
  25. OpProgress * const progress)
  26. {
  27. pkgCache *Cache = CacheFile.GetPkgCache();
  28. pkgDepCache *DepCache = CacheFile.GetDepCache();
  29. APT::CacheSetHelper helper(false);
  30. int Done=0;
  31. if (progress != NULL)
  32. progress->SubProgress(Cache->Head().PackageCount, _("Sorting"));
  33. bool const insertCurrentVer = _config->FindB("APT::Cmd::Installed", false);
  34. bool const insertUpgradable = _config->FindB("APT::Cmd::Upgradable", false);
  35. bool const insertManualInstalled = _config->FindB("APT::Cmd::Manual-Installed", false);
  36. for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
  37. {
  38. if (progress != NULL)
  39. {
  40. if (Done % 500 == 0)
  41. progress->Progress(Done);
  42. ++Done;
  43. }
  44. // exclude virtual pkgs
  45. if (P->VersionList == 0)
  46. continue;
  47. if ((matcher)(P) == false)
  48. continue;
  49. pkgDepCache::StateCache &state = (*DepCache)[P];
  50. if (insertCurrentVer == true)
  51. {
  52. if (P->CurrentVer != 0)
  53. vci->FromPackage(vci, CacheFile, P, APT::CacheSetHelper::INSTALLED, helper);
  54. }
  55. else if (insertUpgradable == true)
  56. {
  57. if(P.CurrentVer() && state.Upgradable())
  58. vci->FromPackage(vci, CacheFile, P, APT::CacheSetHelper::CANDIDATE, helper);
  59. }
  60. else if (insertManualInstalled == true)
  61. {
  62. if (P.CurrentVer() &&
  63. ((*DepCache)[P].Flags & pkgCache::Flag::Auto) == false)
  64. vci->FromPackage(vci, CacheFile, P, APT::CacheSetHelper::CANDIDATE, helper);
  65. }
  66. else
  67. {
  68. if (vci->FromPackage(vci, CacheFile, P, APT::CacheSetHelper::CANDIDATE, helper) == false)
  69. {
  70. // no candidate, this may happen for packages in
  71. // dpkg "deinstall ok config-file" state - we pick the first ver
  72. // (which should be the only one)
  73. vci->insert(P.VersionList());
  74. }
  75. }
  76. }
  77. if (progress != NULL)
  78. progress->Done();
  79. return true;
  80. }
  81. /*}}}*/
  82. // CacheSetHelper saving virtual packages /*{{{*/
  83. pkgCache::VerIterator CacheSetHelperVirtuals::canNotGetVersion(
  84. enum CacheSetHelper::VerSelector const select,
  85. pkgCacheFile &Cache,
  86. pkgCache::PkgIterator const &Pkg)
  87. {
  88. if (select == NEWEST || select == CANDIDATE || select == ALL)
  89. virtualPkgs.insert(Pkg);
  90. return CacheSetHelper::canNotGetVersion(select, Cache, Pkg);
  91. }
  92. void CacheSetHelperVirtuals::canNotFindVersion(
  93. enum CacheSetHelper::VerSelector const select,
  94. APT::VersionContainerInterface * vci,
  95. pkgCacheFile &Cache,
  96. pkgCache::PkgIterator const &Pkg)
  97. {
  98. if (select == NEWEST || select == CANDIDATE || select == ALL)
  99. virtualPkgs.insert(Pkg);
  100. return CacheSetHelper::canNotFindVersion(select, vci, Cache, Pkg);
  101. }
  102. CacheSetHelperVirtuals::CacheSetHelperVirtuals(bool const ShowErrors, GlobalError::MsgType const &ErrorType) :
  103. CacheSetHelper{ShowErrors, ErrorType}
  104. {}
  105. /*}}}*/
  106. // CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/
  107. CacheSetHelperAPTGet::CacheSetHelperAPTGet(std::ostream &out) :
  108. APT::CacheSetHelper{true}, out{out}
  109. {
  110. explicitlyNamed = true;
  111. }
  112. void CacheSetHelperAPTGet::showTaskSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern)
  113. {
  114. ioprintf(out, _("Note, selecting '%s' for task '%s'\n"),
  115. Pkg.FullName(true).c_str(), pattern.c_str());
  116. explicitlyNamed = false;
  117. }
  118. void CacheSetHelperAPTGet::showFnmatchSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern)
  119. {
  120. ioprintf(out, _("Note, selecting '%s' for glob '%s'\n"),
  121. Pkg.FullName(true).c_str(), pattern.c_str());
  122. explicitlyNamed = false;
  123. }
  124. void CacheSetHelperAPTGet::showRegExSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern)
  125. {
  126. ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"),
  127. Pkg.FullName(true).c_str(), pattern.c_str());
  128. explicitlyNamed = false;
  129. }
  130. void CacheSetHelperAPTGet::showSelectedVersion(pkgCache::PkgIterator const &/*Pkg*/, pkgCache::VerIterator const Ver,
  131. std::string const &ver, bool const /*verIsRel*/)
  132. {
  133. if (ver == Ver.VerStr())
  134. return;
  135. selectedByRelease.push_back(make_pair(Ver, ver));
  136. }
  137. bool CacheSetHelperAPTGet::showVirtualPackageErrors(pkgCacheFile &Cache)
  138. {
  139. if (virtualPkgs.empty() == true)
  140. return true;
  141. for (APT::PackageSet::const_iterator Pkg = virtualPkgs.begin();
  142. Pkg != virtualPkgs.end(); ++Pkg) {
  143. if (Pkg->ProvidesList != 0) {
  144. ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
  145. Pkg.FullName(true).c_str());
  146. pkgCache::PrvIterator I = Pkg.ProvidesList();
  147. unsigned short provider = 0;
  148. for (; I.end() == false; ++I) {
  149. pkgCache::PkgIterator Pkg = I.OwnerPkg();
  150. if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer()) {
  151. c1out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr();
  152. if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
  153. c1out << _(" [Installed]");
  154. c1out << std::endl;
  155. ++provider;
  156. }
  157. }
  158. // if we found no candidate which provide this package, show non-candidates
  159. if (provider == 0)
  160. for (I = Pkg.ProvidesList(); I.end() == false; ++I)
  161. c1out << " " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr()
  162. << _(" [Not candidate version]") << std::endl;
  163. else
  164. out << _("You should explicitly select one to install.") << std::endl;
  165. } else {
  166. ioprintf(c1out,
  167. _("Package %s is not available, but is referred to by another package.\n"
  168. "This may mean that the package is missing, has been obsoleted, or\n"
  169. "is only available from another source\n"),Pkg.FullName(true).c_str());
  170. std::string List;
  171. std::string VersionsList;
  172. std::vector<bool> Seen(Cache.GetPkgCache()->Head().PackageCount, false);
  173. APT::PackageList pkglist;
  174. for (pkgCache::DepIterator Dep = Pkg.RevDependsList();
  175. Dep.end() == false; ++Dep) {
  176. if (Dep->Type != pkgCache::Dep::Replaces)
  177. continue;
  178. pkgCache::PkgIterator const DP = Dep.ParentPkg();
  179. if (Seen[DP->ID] == true)
  180. continue;
  181. Seen[DP->ID] = true;
  182. pkglist.insert(DP);
  183. }
  184. ShowList(c1out, _("However the following packages replace it:"), pkglist,
  185. &AlwaysTrue, &PrettyFullName, &EmptyString);
  186. }
  187. c1out << std::endl;
  188. }
  189. return false;
  190. }
  191. pkgCache::VerIterator CacheSetHelperAPTGet::canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg)
  192. {
  193. APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, CacheSetHelper::CANDIDATE);
  194. if (verset.empty() == false)
  195. return *(verset.begin());
  196. else if (ShowError == true) {
  197. _error->Error(_("Package '%s' has no installation candidate"),Pkg.FullName(true).c_str());
  198. virtualPkgs.insert(Pkg);
  199. }
  200. return pkgCache::VerIterator(Cache, 0);
  201. }
  202. pkgCache::VerIterator CacheSetHelperAPTGet::canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg)
  203. {
  204. if (Pkg->ProvidesList != 0)
  205. {
  206. APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, CacheSetHelper::NEWEST);
  207. if (verset.empty() == false)
  208. return *(verset.begin());
  209. if (ShowError == true)
  210. ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str());
  211. }
  212. else
  213. {
  214. pkgCache::GrpIterator Grp = Pkg.Group();
  215. pkgCache::PkgIterator P = Grp.PackageList();
  216. for (; P.end() != true; P = Grp.NextPkg(P))
  217. {
  218. if (P == Pkg)
  219. continue;
  220. if (P->CurrentVer != 0) {
  221. // TRANSLATORS: Note, this is not an interactive question
  222. ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
  223. Pkg.FullName(true).c_str(), P.FullName(true).c_str());
  224. break;
  225. }
  226. }
  227. if (P.end() == true)
  228. ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
  229. }
  230. return pkgCache::VerIterator(Cache, 0);
  231. }
  232. APT::VersionSet CacheSetHelperAPTGet::tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg,
  233. CacheSetHelper::VerSelector const select)
  234. {
  235. /* This is a pure virtual package and there is a single available
  236. candidate providing it. */
  237. if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0)
  238. return APT::VersionSet();
  239. pkgCache::PkgIterator Prov;
  240. bool found_one = false;
  241. for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; ++P) {
  242. pkgCache::VerIterator const PVer = P.OwnerVer();
  243. pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
  244. /* Ignore versions that are not a candidate. */
  245. if (Cache[PPkg].CandidateVer != PVer)
  246. continue;
  247. if (found_one == false) {
  248. Prov = PPkg;
  249. found_one = true;
  250. } else if (PPkg != Prov) {
  251. // same group, so it's a foreign package
  252. if (PPkg->Group == Prov->Group) {
  253. // do we already have the requested arch?
  254. if (strcmp(Pkg.Arch(), Prov.Arch()) == 0 ||
  255. strcmp(Prov.Arch(), "all") == 0 ||
  256. unlikely(strcmp(PPkg.Arch(), Prov.Arch()) == 0)) // packages have only on candidate, but just to be sure
  257. continue;
  258. // see which architecture we prefer more and switch to it
  259. std::vector<std::string> archs = APT::Configuration::getArchitectures();
  260. if (std::find(archs.begin(), archs.end(), PPkg.Arch()) < std::find(archs.begin(), archs.end(), Prov.Arch()))
  261. Prov = PPkg;
  262. continue;
  263. }
  264. found_one = false; // we found at least two
  265. break;
  266. }
  267. }
  268. if (found_one == true) {
  269. ioprintf(out, _("Note, selecting '%s' instead of '%s'\n"),
  270. Prov.FullName(true).c_str(), Pkg.FullName(true).c_str());
  271. return APT::VersionSet::FromPackage(Cache, Prov, select, *this);
  272. }
  273. return APT::VersionSet();
  274. }
  275. /*}}}*/