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