private-cacheset.cc 13 KB

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