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