You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

365 lines
13 KiB

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