]> git.saurik.com Git - apt.git/blame - apt-pkg/pkgcache.cc
use a smaller type for flags storage in the cache
[apt.git] / apt-pkg / pkgcache.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
bac2e715 3// $Id: pkgcache.cc,v 1.37 2003/02/10 01:40:58 doogie Exp $
578bfd0a
AL
4/* ######################################################################
5
6 Package Cache - Accessor code for the cache
7
094a497d 8 Please see doc/apt-pkg/cache.sgml for a more detailed description of
578bfd0a
AL
9 this format. Also be sure to keep that file up-to-date!!
10
1e3f4083 11 This is the general utility functions for cache management. They provide
578bfd0a
AL
12 a complete set of accessor functions for the cache. The cacheiterators
13 header contains the STL-like iterators that can be used to easially
14 navigate the cache as well as seemlessly dereference the mmap'd
15 indexes. Use these always.
16
17 The main class provides for ways to get package indexes and some
18 general lookup functions to start the iterators.
19
20 ##################################################################### */
21 /*}}}*/
22// Include Files /*{{{*/
ea542140
DK
23#include<config.h>
24
094a497d 25#include <apt-pkg/pkgcache.h>
af29ffb4 26#include <apt-pkg/policy.h>
094a497d
AL
27#include <apt-pkg/version.h>
28#include <apt-pkg/error.h>
231fea14 29#include <apt-pkg/strutl.h>
b2e465d6 30#include <apt-pkg/configuration.h>
45df0ad2 31#include <apt-pkg/aptconfiguration.h>
453b82a3 32#include <apt-pkg/mmap.h>
5c0d3668 33#include <apt-pkg/macros.h>
578bfd0a 34
453b82a3
DK
35#include <stddef.h>
36#include <string.h>
37#include <ostream>
38#include <vector>
578bfd0a
AL
39#include <string>
40#include <sys/stat.h>
ea542140
DK
41
42#include <apti18n.h>
578bfd0a
AL
43 /*}}}*/
44
851a45a8
AL
45using std::string;
46
012b102a 47
578bfd0a
AL
48// Cache::Header::Header - Constructor /*{{{*/
49// ---------------------------------------------------------------------
50/* Simply initialize the header */
51pkgCache::Header::Header()
52{
dfe66c72
DK
53#define APT_HEADER_SET(X,Y) X = Y; static_assert(std::numeric_limits<decltype(X)>::max() > Y, "Size violation detected in pkgCache::Header")
54 APT_HEADER_SET(Signature, 0x98FE76DC);
55
578bfd0a
AL
56 /* Whenever the structures change the major version should be bumped,
57 whenever the generator changes the minor version should be bumped. */
dfe66c72
DK
58 APT_HEADER_SET(MajorVersion, 10);
59 APT_HEADER_SET(MinorVersion, 0);
60 APT_HEADER_SET(Dirty, false);
61
62 APT_HEADER_SET(HeaderSz, sizeof(pkgCache::Header));
63 APT_HEADER_SET(GroupSz, sizeof(pkgCache::Group));
64 APT_HEADER_SET(PackageSz, sizeof(pkgCache::Package));
65 APT_HEADER_SET(ReleaseFileSz, sizeof(pkgCache::ReleaseFile));
66 APT_HEADER_SET(PackageFileSz, sizeof(pkgCache::PackageFile));
67 APT_HEADER_SET(VersionSz, sizeof(pkgCache::Version));
68 APT_HEADER_SET(DescriptionSz, sizeof(pkgCache::Description));
69 APT_HEADER_SET(DependencySz, sizeof(pkgCache::Dependency));
70 APT_HEADER_SET(DependencyDataSz, sizeof(pkgCache::DependencyData));
71 APT_HEADER_SET(ProvidesSz, sizeof(pkgCache::Provides));
72 APT_HEADER_SET(VerFileSz, sizeof(pkgCache::VerFile));
73 APT_HEADER_SET(DescFileSz, sizeof(pkgCache::DescFile));
74#undef APT_HEADER_SET
75
52c41485 76 GroupCount = 0;
578bfd0a
AL
77 PackageCount = 0;
78 VersionCount = 0;
a52f938b 79 DescriptionCount = 0;
578bfd0a 80 DependsCount = 0;
71c9e95b 81 DependsDataCount = 0;
b07aeb1a 82 ReleaseFileCount = 0;
578bfd0a 83 PackageFileCount = 0;
a7e66b17 84 VerFileCount = 0;
a52f938b 85 DescFileCount = 0;
a7e66b17 86 ProvidesCount = 0;
ad00ae81 87 MaxVerFileSize = 0;
a52f938b 88 MaxDescFileSize = 0;
dfe66c72 89
578bfd0a 90 FileList = 0;
b07aeb1a 91 RlsFileList = 0;
b2e465d6
AL
92 VerSysName = 0;
93 Architecture = 0;
32ab4bd0
DK
94 SetArchitectures(0);
95 SetHashTableSize(_config->FindI("APT::Cache-HashTableSize", 10 * 1048));
578bfd0a 96 memset(Pools,0,sizeof(Pools));
0688ccd8
JAK
97
98 CacheFileSize = 0;
578bfd0a
AL
99}
100 /*}}}*/
101// Cache::Header::CheckSizes - Check if the two headers have same *sz /*{{{*/
102// ---------------------------------------------------------------------
103/* */
104bool pkgCache::Header::CheckSizes(Header &Against) const
105{
106 if (HeaderSz == Against.HeaderSz &&
52c41485 107 GroupSz == Against.GroupSz &&
578bfd0a 108 PackageSz == Against.PackageSz &&
b07aeb1a 109 ReleaseFileSz == Against.ReleaseFileSz &&
578bfd0a
AL
110 PackageFileSz == Against.PackageFileSz &&
111 VersionSz == Against.VersionSz &&
a52f938b 112 DescriptionSz == Against.DescriptionSz &&
dcb79bae 113 DependencySz == Against.DependencySz &&
71c9e95b 114 DependencyDataSz == Against.DependencyDataSz &&
dcb79bae 115 VerFileSz == Against.VerFileSz &&
a52f938b 116 DescFileSz == Against.DescFileSz &&
578bfd0a
AL
117 ProvidesSz == Against.ProvidesSz)
118 return true;
119 return false;
120}
121 /*}}}*/
122
123// Cache::pkgCache - Constructor /*{{{*/
124// ---------------------------------------------------------------------
125/* */
32ab4bd0 126APT_IGNORE_DEPRECATED_PUSH
6c55f07a 127pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map), d(NULL)
578bfd0a 128{
4cbf323f
MV
129 // call getArchitectures() with cached=false to ensure that the
130 // architectures cache is re-evaulated. this is needed in cases
131 // when the APT::Architecture field changes between two cache creations
132 MultiArchEnabled = APT::Configuration::getArchitectures(false).size() > 1;
b2e465d6
AL
133 if (DoMap == true)
134 ReMap();
578bfd0a 135}
32ab4bd0 136APT_IGNORE_DEPRECATED_POP
578bfd0a
AL
137 /*}}}*/
138// Cache::ReMap - Reopen the cache file /*{{{*/
139// ---------------------------------------------------------------------
140/* If the file is already closed then this will open it open it. */
a9fe5928 141bool pkgCache::ReMap(bool const &Errorchecks)
578bfd0a
AL
142{
143 // Apply the typecasts.
144 HeaderP = (Header *)Map.Data();
5bf15716 145 GrpP = (Group *)Map.Data();
578bfd0a 146 PkgP = (Package *)Map.Data();
dcb79bae 147 VerFileP = (VerFile *)Map.Data();
a52f938b 148 DescFileP = (DescFile *)Map.Data();
b07aeb1a 149 RlsFileP = (ReleaseFile *)Map.Data();
578bfd0a
AL
150 PkgFileP = (PackageFile *)Map.Data();
151 VerP = (Version *)Map.Data();
a52f938b 152 DescP = (Description *)Map.Data();
578bfd0a
AL
153 ProvideP = (Provides *)Map.Data();
154 DepP = (Dependency *)Map.Data();
71c9e95b 155 DepDataP = (DependencyData *)Map.Data();
578bfd0a
AL
156 StrP = (char *)Map.Data();
157
a9fe5928
DK
158 if (Errorchecks == false)
159 return true;
160
b2e465d6
AL
161 if (Map.Size() == 0 || HeaderP == 0)
162 return _error->Error(_("Empty package cache"));
578bfd0a
AL
163
164 // Check the header
165 Header DefHeader;
166 if (HeaderP->Signature != DefHeader.Signature ||
167 HeaderP->Dirty == true)
b2e465d6 168 return _error->Error(_("The package cache file is corrupted"));
578bfd0a
AL
169
170 if (HeaderP->MajorVersion != DefHeader.MajorVersion ||
171 HeaderP->MinorVersion != DefHeader.MinorVersion ||
172 HeaderP->CheckSizes(DefHeader) == false)
b2e465d6
AL
173 return _error->Error(_("The package cache file is an incompatible version"));
174
7d79339f
JAK
175 if (Map.Size() < HeaderP->CacheFileSize)
176 return _error->Error(_("The package cache file is corrupted, it is too small"));
177
32ab4bd0 178 if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->GetArchitectures() == 0)
7a223b93
DK
179 return _error->Error(_("The package cache file is corrupted"));
180
b2e465d6 181 // Locate our VS..
7a223b93 182 if ((VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
db0db9fe 183 return _error->Error(_("This APT does not support the versioning system '%s'"),StrP + HeaderP->VerSysName);
b2e465d6 184
7a223b93
DK
185 // Check the architecture
186 std::vector<std::string> archs = APT::Configuration::getArchitectures();
187 std::vector<std::string>::const_iterator a = archs.begin();
188 std::string list = *a;
189 for (++a; a != archs.end(); ++a)
190 list.append(",").append(*a);
191 if (_config->Find("APT::Architecture") != StrP + HeaderP->Architecture ||
32ab4bd0
DK
192 list != StrP + HeaderP->GetArchitectures())
193 return _error->Error(_("The package cache was built for different architectures: %s vs %s"), StrP + HeaderP->GetArchitectures(), list.c_str());
7a223b93 194
578bfd0a
AL
195 return true;
196}
197 /*}}}*/
198// Cache::Hash - Hash a string /*{{{*/
199// ---------------------------------------------------------------------
200/* This is used to generate the hash entries for the HashTable. With my
201 package list from bo this function gets 94% table usage on a 512 item
202 table (480 used items) */
4ad8619b 203map_id_t pkgCache::sHash(const string &Str) const
578bfd0a
AL
204{
205 unsigned long Hash = 0;
f7f0d6c7 206 for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
aa0fe657 207 Hash = 41 * Hash + tolower_ascii(*I);
32ab4bd0 208 return Hash % HeaderP->GetHashTableSize();
578bfd0a
AL
209}
210
4ad8619b 211map_id_t pkgCache::sHash(const char *Str) const
578bfd0a 212{
aa0fe657
DK
213 unsigned long Hash = tolower_ascii(*Str);
214 for (const char *I = Str + 1; *I != 0; ++I)
215 Hash = 41 * Hash + tolower_ascii(*I);
32ab4bd0 216 return Hash % HeaderP->GetHashTableSize();
578bfd0a 217}
8d4c859d
DK
218 /*}}}*/
219// Cache::SingleArchFindPkg - Locate a package by name /*{{{*/
220// ---------------------------------------------------------------------
221/* Returns 0 on error, pointer to the package otherwise
222 The multiArch enabled methods will fallback to this one as it is (a bit)
223 faster for single arch environments and realworld is mostly singlearch… */
224pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name)
225{
226 // Look at the hash bucket
32ab4bd0
DK
227 Package *Pkg = PkgP + HeaderP->PkgHashTableP()[Hash(Name)];
228 for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage)
8d4c859d 229 {
b59325e8 230 int const cmp = strcmp(Name.c_str(), StrP + (GrpP + Pkg->Group)->Name);
aa0fe657
DK
231 if (cmp == 0)
232 return PkgIterator(*this, Pkg);
233 else if (cmp < 0)
234 break;
8d4c859d
DK
235 }
236 return PkgIterator(*this,0);
237}
578bfd0a
AL
238 /*}}}*/
239// Cache::FindPkg - Locate a package by name /*{{{*/
240// ---------------------------------------------------------------------
241/* Returns 0 on error, pointer to the package otherwise */
25396fb0
DK
242pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) {
243 size_t const found = Name.find(':');
244 if (found == string::npos)
6c9937da 245 return FindPkg(Name, "native");
4d174dc8 246 string const Arch = Name.substr(found+1);
eddc9dd0
DK
247 /* Beware: This is specialcased to handle pkg:any in dependencies as
248 these are linked to virtual pkg:any named packages with all archs.
249 If you want any arch from a given pkg, use FindPkg(pkg,arch) */
4d174dc8
DK
250 if (Arch == "any")
251 return FindPkg(Name, "any");
252 return FindPkg(Name.substr(0, found), Arch);
25396fb0
DK
253}
254 /*}}}*/
255// Cache::FindPkg - Locate a package by name /*{{{*/
256// ---------------------------------------------------------------------
257/* Returns 0 on error, pointer to the package otherwise */
8d4c859d 258pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) {
5bf15716
DK
259 /* We make a detour via the GrpIterator here as
260 on a multi-arch environment a group is easier to
261 find than a package (less entries in the buckets) */
262 pkgCache::GrpIterator Grp = FindGrp(Name);
263 if (Grp.end() == true)
264 return PkgIterator(*this,0);
265
266 return Grp.FindPkg(Arch);
267}
268 /*}}}*/
269// Cache::FindGrp - Locate a group by name /*{{{*/
270// ---------------------------------------------------------------------
271/* Returns End-Pointer on error, pointer to the group otherwise */
272pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) {
273 if (unlikely(Name.empty() == true))
274 return GrpIterator(*this,0);
275
276 // Look at the hash bucket for the group
32ab4bd0 277 Group *Grp = GrpP + HeaderP->GrpHashTableP()[sHash(Name)];
5bf15716 278 for (; Grp != GrpP; Grp = GrpP + Grp->Next) {
b59325e8 279 int const cmp = strcmp(Name.c_str(), StrP + Grp->Name);
aa0fe657 280 if (cmp == 0)
5bf15716 281 return GrpIterator(*this, Grp);
aa0fe657
DK
282 else if (cmp < 0)
283 break;
5bf15716
DK
284 }
285
286 return GrpIterator(*this,0);
578bfd0a
AL
287}
288 /*}}}*/
b2e465d6
AL
289// Cache::CompTypeDeb - Return a string describing the compare type /*{{{*/
290// ---------------------------------------------------------------------
291/* This returns a string representation of the dependency compare
292 type in the weird debian style.. */
293const char *pkgCache::CompTypeDeb(unsigned char Comp)
294{
69c2ecbd
DK
295 const char * const Ops[] = {"","<=",">=","<<",">>","=","!="};
296 if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0])))
297 return "";
298 return Ops[Comp & 0xF];
b2e465d6
AL
299}
300 /*}}}*/
301// Cache::CompType - Return a string describing the compare type /*{{{*/
302// ---------------------------------------------------------------------
69c2ecbd 303/* This returns a string representation of the dependency compare
b2e465d6
AL
304 type */
305const char *pkgCache::CompType(unsigned char Comp)
306{
69c2ecbd
DK
307 const char * const Ops[] = {"","<=",">=","<",">","=","!="};
308 if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0])))
309 return "";
310 return Ops[Comp & 0xF];
b2e465d6
AL
311}
312 /*}}}*/
313// Cache::DepType - Return a string describing the dep type /*{{{*/
314// ---------------------------------------------------------------------
315/* */
316const char *pkgCache::DepType(unsigned char Type)
317{
318 const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
319 _("Recommends"),_("Conflicts"),_("Replaces"),
f8ae7e8b 320 _("Obsoletes"),_("Breaks"), _("Enhances")};
308c7d30 321 if (Type < sizeof(Types)/sizeof(*Types))
b2e465d6
AL
322 return Types[Type];
323 return "";
324}
325 /*}}}*/
0149949b
AL
326// Cache::Priority - Convert a priority value to a string /*{{{*/
327// ---------------------------------------------------------------------
328/* */
329const char *pkgCache::Priority(unsigned char Prio)
330{
b2e465d6
AL
331 const char *Mapping[] = {0,_("important"),_("required"),_("standard"),
332 _("optional"),_("extra")};
0149949b
AL
333 if (Prio < _count(Mapping))
334 return Mapping[Prio];
335 return 0;
336}
337 /*}}}*/
5bf15716
DK
338// GrpIterator::FindPkg - Locate a package by arch /*{{{*/
339// ---------------------------------------------------------------------
340/* Returns an End-Pointer on error, pointer to the package otherwise */
e841200b 341pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
5bf15716
DK
342 if (unlikely(IsGood() == false || S->FirstPackage == 0))
343 return PkgIterator(*Owner, 0);
344
60dcec6d
DK
345 /* If we accept any package we simply return the "first"
346 package in this group (the last one added). */
347 if (Arch == "any")
348 return PkgIterator(*Owner, Owner->PkgP + S->FirstPackage);
349
959470da 350 char const* const myArch = Owner->NativeArch();
5bf15716
DK
351 /* Most of the time the package for our native architecture is
352 the one we add at first to the cache, but this would be the
353 last one we check, so we do it now. */
566046f4 354 if (Arch == "native" || Arch == myArch || Arch == "all") {
5bf15716 355 pkgCache::Package *Pkg = Owner->PkgP + S->LastPackage;
b59325e8 356 if (strcmp(myArch, Owner->StrP + Pkg->Arch) == 0)
5bf15716 357 return PkgIterator(*Owner, Pkg);
959470da 358 Arch = myArch;
5bf15716
DK
359 }
360
5d1e330d 361 // Iterate over the list to find the matching arch
5bf15716 362 for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP;
32ab4bd0 363 Pkg = Owner->PkgP + Pkg->NextPackage) {
5d1e330d 364 if (stringcmp(Arch, Owner->StrP + Pkg->Arch) == 0)
5bf15716
DK
365 return PkgIterator(*Owner, Pkg);
366 if ((Owner->PkgP + S->LastPackage) == Pkg)
367 break;
368 }
369
bd2fb30a
DK
370 return PkgIterator(*Owner, 0);
371}
372 /*}}}*/
373// GrpIterator::FindPreferredPkg - Locate the "best" package /*{{{*/
374// ---------------------------------------------------------------------
375/* Returns an End-Pointer on error, pointer to the package otherwise */
3db58cf4 376pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &PreferNonVirtual) const {
bd2fb30a 377 pkgCache::PkgIterator Pkg = FindPkg("native");
3db58cf4 378 if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
bd2fb30a
DK
379 return Pkg;
380
381 std::vector<std::string> const archs = APT::Configuration::getArchitectures();
382 for (std::vector<std::string>::const_iterator a = archs.begin();
383 a != archs.end(); ++a) {
384 Pkg = FindPkg(*a);
3db58cf4 385 if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
bd2fb30a
DK
386 return Pkg;
387 }
c919ad6e
DK
388 // packages without an architecture
389 Pkg = FindPkg("none");
390 if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
391 return Pkg;
bd2fb30a 392
3db58cf4
DK
393 if (PreferNonVirtual == true)
394 return FindPreferredPkg(false);
5bf15716
DK
395 return PkgIterator(*Owner, 0);
396}
397 /*}}}*/
398// GrpIterator::NextPkg - Locate the next package in the group /*{{{*/
399// ---------------------------------------------------------------------
400/* Returns an End-Pointer on error, pointer to the package otherwise.
c408e01e
DK
401 We can't simply ++ to the next as the next package of the last will
402 be from a different group (with the same hash value) */
e841200b 403pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) const {
5bf15716
DK
404 if (unlikely(IsGood() == false || S->FirstPackage == 0 ||
405 LastPkg.end() == true))
406 return PkgIterator(*Owner, 0);
407
c408e01e
DK
408 if (S->LastPackage == LastPkg.Index())
409 return PkgIterator(*Owner, 0);
5bf15716 410
32ab4bd0 411 return PkgIterator(*Owner, Owner->PkgP + LastPkg->NextPackage);
5bf15716
DK
412}
413 /*}}}*/
71c9e95b 414// GrpIterator::operator++ - Prefix incr /*{{{*/
25396fb0
DK
415// ---------------------------------------------------------------------
416/* This will advance to the next logical group in the hash table. */
3707fd4f 417pkgCache::GrpIterator& pkgCache::GrpIterator::operator++()
25396fb0
DK
418{
419 // Follow the current links
420 if (S != Owner->GrpP)
421 S = Owner->GrpP + S->Next;
422
423 // Follow the hash table
32ab4bd0 424 while (S == Owner->GrpP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize())
25396fb0 425 {
71c9e95b 426 ++HashIndex;
32ab4bd0 427 S = Owner->GrpP + Owner->HeaderP->GrpHashTableP()[HashIndex];
25396fb0 428 }
3707fd4f 429 return *this;
d3e8fbb3 430}
f55a958f 431 /*}}}*/
71c9e95b 432// PkgIterator::operator++ - Prefix incr /*{{{*/
578bfd0a
AL
433// ---------------------------------------------------------------------
434/* This will advance to the next logical package in the hash table. */
71c9e95b 435pkgCache::PkgIterator& pkgCache::PkgIterator::operator++()
578bfd0a
AL
436{
437 // Follow the current links
773e2c1f 438 if (S != Owner->PkgP)
32ab4bd0 439 S = Owner->PkgP + S->NextPackage;
b2e465d6 440
578bfd0a 441 // Follow the hash table
32ab4bd0 442 while (S == Owner->PkgP && (HashIndex+1) < (signed)Owner->HeaderP->GetHashTableSize())
578bfd0a 443 {
71c9e95b 444 ++HashIndex;
32ab4bd0 445 S = Owner->PkgP + Owner->HeaderP->PkgHashTableP()[HashIndex];
578bfd0a 446 }
3707fd4f 447 return *this;
d3e8fbb3 448}
578bfd0a 449 /*}}}*/
71c9e95b
DK
450pkgCache::DepIterator& pkgCache::DepIterator::operator++() /*{{{*/
451{
452 if (S == Owner->DepP)
453 return *this;
454 S = Owner->DepP + (Type == DepVer ? S->NextDepends : S->NextRevDepends);
455 if (S == Owner->DepP)
456 S2 = Owner->DepDataP;
457 else
458 S2 = Owner->DepDataP + S->DependencyData;
459 return *this;
460}
461 /*}}}*/
578bfd0a
AL
462// PkgIterator::State - Check the State of the package /*{{{*/
463// ---------------------------------------------------------------------
464/* By this we mean if it is either cleanly installed or cleanly removed. */
465pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
d38b7b3d 466{
773e2c1f
DK
467 if (S->InstState == pkgCache::State::ReInstReq ||
468 S->InstState == pkgCache::State::HoldReInstReq)
c7c1b0f6
AL
469 return NeedsUnpack;
470
773e2c1f
DK
471 if (S->CurrentState == pkgCache::State::UnPacked ||
472 S->CurrentState == pkgCache::State::HalfConfigured)
c6aa14e4
MV
473 // we leave triggers alone complettely. dpkg deals with
474 // them in a hard-to-predict manner and if they get
475 // resolved by dpkg before apt run dpkg --configure on
476 // the TriggersPending package dpkg returns a error
09fab244 477 //Pkg->CurrentState == pkgCache::State::TriggersAwaited
c6aa14e4 478 //Pkg->CurrentState == pkgCache::State::TriggersPending)
578bfd0a
AL
479 return NeedsConfigure;
480
773e2c1f
DK
481 if (S->CurrentState == pkgCache::State::HalfInstalled ||
482 S->InstState != pkgCache::State::Ok)
578bfd0a
AL
483 return NeedsUnpack;
484
485 return NeedsNothing;
486}
487 /*}}}*/
af29ffb4
MV
488// PkgIterator::CandVersion - Returns the candidate version string /*{{{*/
489// ---------------------------------------------------------------------
490/* Return string representing of the candidate version. */
491const char *
d3e8fbb3 492pkgCache::PkgIterator::CandVersion() const
af29ffb4
MV
493{
494 //TargetVer is empty, so don't use it.
749eb4cf 495 VerIterator version = pkgPolicy(Owner).GetCandidateVer(*this);
af29ffb4
MV
496 if (version.IsGood())
497 return version.VerStr();
498 return 0;
d3e8fbb3 499}
af29ffb4
MV
500 /*}}}*/
501// PkgIterator::CurVersion - Returns the current version string /*{{{*/
502// ---------------------------------------------------------------------
503/* Return string representing of the current version. */
504const char *
d3e8fbb3 505pkgCache::PkgIterator::CurVersion() const
af29ffb4
MV
506{
507 VerIterator version = CurrentVer();
508 if (version.IsGood())
509 return CurrentVer().VerStr();
510 return 0;
d3e8fbb3 511}
af29ffb4
MV
512 /*}}}*/
513// ostream operator to handle string representation of a package /*{{{*/
514// ---------------------------------------------------------------------
515/* Output name < cur.rent.version -> candid.ate.version | new.est.version > (section)
1e3f4083 516 Note that the characters <|>() are all literal above. Versions will be omitted
af29ffb4
MV
517 if they provide no new information (e.g. there is no newer version than candidate)
518 If no version and/or section can be found "none" is used. */
519std::ostream&
8f3ba4e8 520operator<<(std::ostream& out, pkgCache::PkgIterator Pkg)
af29ffb4
MV
521{
522 if (Pkg.end() == true)
523 return out << "invalid package";
524
525 string current = string(Pkg.CurVersion() == 0 ? "none" : Pkg.CurVersion());
526 string candidate = string(Pkg.CandVersion() == 0 ? "none" : Pkg.CandVersion());
527 string newest = string(Pkg.VersionList().end() ? "none" : Pkg.VersionList().VerStr());
528
5dd4c8b8 529 out << Pkg.Name() << " [ " << Pkg.Arch() << " ] < " << current;
af29ffb4
MV
530 if (current != candidate)
531 out << " -> " << candidate;
532 if ( newest != "none" && candidate != newest)
533 out << " | " << newest;
7a669774
DK
534 if (Pkg->VersionList == 0)
535 out << " > ( none )";
536 else
537 out << " > ( " << string(Pkg.VersionList().Section()==0?"unknown":Pkg.VersionList().Section()) << " )";
af29ffb4
MV
538 return out;
539}
540 /*}}}*/
75ce2062
DK
541// PkgIterator::FullName - Returns Name and (maybe) Architecture /*{{{*/
542// ---------------------------------------------------------------------
543/* Returns a name:arch string */
544std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const
545{
546 string fullname = Name();
547 if (Pretty == false ||
959470da
DK
548 (strcmp(Arch(), "all") != 0 &&
549 strcmp(Owner->NativeArch(), Arch()) != 0))
75ce2062
DK
550 return fullname.append(":").append(Arch());
551 return fullname;
552}
553 /*}}}*/
578bfd0a
AL
554// DepIterator::IsCritical - Returns true if the dep is important /*{{{*/
555// ---------------------------------------------------------------------
556/* Currently critical deps are defined as depends, predepends and
308c7d30 557 conflicts (including dpkg's Breaks fields). */
e841200b 558bool pkgCache::DepIterator::IsCritical() const
578bfd0a 559{
359e46db 560 if (IsNegative() == true ||
71c9e95b
DK
561 S2->Type == pkgCache::Dep::Depends ||
562 S2->Type == pkgCache::Dep::PreDepends)
578bfd0a
AL
563 return true;
564 return false;
565}
566 /*}}}*/
df77d8a5
DK
567// DepIterator::IsNegative - Returns true if the dep is a negative one /*{{{*/
568// ---------------------------------------------------------------------
569/* Some dependencies are positive like Depends and Recommends, others
570 are negative like Conflicts which can and should be handled differently */
571bool pkgCache::DepIterator::IsNegative() const
572{
71c9e95b
DK
573 return S2->Type == Dep::DpkgBreaks ||
574 S2->Type == Dep::Conflicts ||
575 S2->Type == Dep::Obsoletes;
df77d8a5
DK
576}
577 /*}}}*/
578bfd0a
AL
578// DepIterator::SmartTargetPkg - Resolve dep target pointers w/provides /*{{{*/
579// ---------------------------------------------------------------------
580/* This intellegently looks at dep target packages and tries to figure
581 out which package should be used. This is needed to nicely handle
582 provide mapping. If the target package has no other providing packages
583 then it returned. Otherwise the providing list is looked at to
584 see if there is one one unique providing package if so it is returned.
585 Otherwise true is returned and the target package is set. The return
b2e465d6
AL
586 result indicates whether the node should be expandable
587
588 In Conjunction with the DepCache the value of Result may not be
589 super-good since the policy may have made it uninstallable. Using
590 AllTargets is better in this case. */
e841200b 591bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) const
578bfd0a
AL
592{
593 Result = TargetPkg();
594
595 // No provides at all
596 if (Result->ProvidesList == 0)
597 return false;
598
599 // There is the Base package and the providing ones which is at least 2
600 if (Result->VersionList != 0)
601 return true;
602
603 /* We have to skip over indirect provisions of the package that
604 owns the dependency. For instance, if libc5-dev depends on the
605 virtual package libc-dev which is provided by libc5-dev and libc6-dev
606 we must ignore libc5-dev when considering the provides list. */
607 PrvIterator PStart = Result.ProvidesList();
f7f0d6c7 608 for (; PStart.end() != true && PStart.OwnerPkg() == ParentPkg(); ++PStart);
578bfd0a
AL
609
610 // Nothing but indirect self provides
611 if (PStart.end() == true)
612 return false;
613
614 // Check for single packages in the provides list
615 PrvIterator P = PStart;
f7f0d6c7 616 for (; P.end() != true; ++P)
578bfd0a
AL
617 {
618 // Skip over self provides
619 if (P.OwnerPkg() == ParentPkg())
620 continue;
621 if (PStart.OwnerPkg() != P.OwnerPkg())
622 break;
623 }
b2e465d6
AL
624
625 Result = PStart.OwnerPkg();
578bfd0a
AL
626
627 // Check for non dups
628 if (P.end() != true)
629 return true;
b2e465d6 630
578bfd0a
AL
631 return false;
632}
633 /*}}}*/
634// DepIterator::AllTargets - Returns the set of all possible targets /*{{{*/
635// ---------------------------------------------------------------------
b2e465d6 636/* This is a more useful version of TargetPkg() that follows versioned
578bfd0a 637 provides. It includes every possible package-version that could satisfy
fbfb2a7c
AL
638 the dependency. The last item in the list has a 0. The resulting pointer
639 must be delete [] 'd */
e841200b 640pkgCache::Version **pkgCache::DepIterator::AllTargets() const
578bfd0a
AL
641{
642 Version **Res = 0;
643 unsigned long Size =0;
644 while (1)
645 {
646 Version **End = Res;
647 PkgIterator DPkg = TargetPkg();
648
649 // Walk along the actual package providing versions
f7f0d6c7 650 for (VerIterator I = DPkg.VersionList(); I.end() == false; ++I)
578bfd0a 651 {
85434114 652 if (IsIgnorable(I.ParentPkg()) == true)
578bfd0a 653 continue;
887c6940 654 if (IsSatisfied(I) == false)
578bfd0a 655 continue;
85434114 656
578bfd0a
AL
657 Size++;
658 if (Res != 0)
659 *End++ = I;
660 }
661
662 // Follow all provides
f7f0d6c7 663 for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; ++I)
578bfd0a 664 {
85434114 665 if (IsIgnorable(I) == true)
578bfd0a 666 continue;
887c6940 667 if (IsSatisfied(I) == false)
85434114 668 continue;
5f909b67 669
578bfd0a
AL
670 Size++;
671 if (Res != 0)
672 *End++ = I.OwnerVer();
673 }
674
675 // Do it again and write it into the array
676 if (Res == 0)
677 {
678 Res = new Version *[Size+1];
679 Size = 0;
680 }
681 else
682 {
683 *End = 0;
684 break;
685 }
686 }
687
688 return Res;
689}
690 /*}}}*/
43d017d6
AL
691// DepIterator::GlobOr - Compute an OR group /*{{{*/
692// ---------------------------------------------------------------------
693/* This Takes an iterator, iterates past the current dependency grouping
694 and returns Start and End so that so End is the final element
695 in the group, if End == Start then D is End++ and End is the
696 dependency D was pointing to. Use in loops to iterate sensibly. */
697void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End)
698{
699 // Compute a single dependency element (glob or)
700 Start = *this;
701 End = *this;
018f1533 702 for (bool LastOR = true; end() == false && LastOR == true;)
43d017d6 703 {
71c9e95b 704 LastOR = (S2->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
3707fd4f 705 ++(*this);
43d017d6
AL
706 if (LastOR == true)
707 End = (*this);
708 }
709}
710 /*}}}*/
85434114
DK
711// DepIterator::IsIgnorable - should this packag/providr be ignored? /*{{{*/
712// ---------------------------------------------------------------------
713/* Deps like self-conflicts should be ignored as well as implicit conflicts
714 on virtual packages. */
fd23676e 715bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &PT) const
85434114 716{
021626db
DK
717 if (IsNegative() == false)
718 return false;
719
fd23676e 720 pkgCache::PkgIterator const PP = ParentPkg();
021626db
DK
721 if (PP->Group != PT->Group)
722 return false;
723 // self-conflict
724 if (PP == PT)
725 return true;
fd23676e 726 pkgCache::VerIterator const PV = ParentVer();
021626db
DK
727 // ignore group-conflict on a M-A:same package - but not our implicit dependencies
728 // so that we can have M-A:same packages conflicting with their own real name
729 if ((PV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
730 {
731 // Replaces: ${self}:other ( << ${binary:Version})
71c9e95b 732 if (S2->Type == pkgCache::Dep::Replaces)
fd23676e 733 {
71c9e95b 734 if (S2->CompareOp == pkgCache::Dep::Less && strcmp(PV.VerStr(), TargetVer()) == 0)
fd23676e
DK
735 return false;
736 }
021626db 737 // Breaks: ${self}:other (!= ${binary:Version})
71c9e95b 738 else if (S2->Type == pkgCache::Dep::DpkgBreaks)
fd23676e 739 {
71c9e95b 740 if (S2->CompareOp == pkgCache::Dep::NotEquals && strcmp(PV.VerStr(), TargetVer()) == 0)
fd23676e
DK
741 return false;
742 }
021626db
DK
743 return true;
744 }
85434114
DK
745
746 return false;
747}
748bool pkgCache::DepIterator::IsIgnorable(PrvIterator const &Prv) const
749{
750 if (IsNegative() == false)
751 return false;
752
753 PkgIterator const Pkg = ParentPkg();
754 /* Provides may never be applied against the same package (or group)
755 if it is a conflicts. See the comment above. */
756 if (Prv.OwnerPkg()->Group == Pkg->Group)
757 return true;
758 // Implicit group-conflicts should not be applied on providers of other groups
759 if (Pkg->Group == TargetPkg()->Group && Prv.OwnerPkg()->Group != Pkg->Group)
760 return true;
761
762 return false;
763}
764 /*}}}*/
d5648746
DK
765// DepIterator::IsMultiArchImplicit - added by the cache generation /*{{{*/
766// ---------------------------------------------------------------------
767/* MultiArch can be translated to SingleArch for an resolver and we did so,
768 by adding dependencies to help the resolver understand the problem, but
769 sometimes it is needed to identify these to ignore them… */
770bool pkgCache::DepIterator::IsMultiArchImplicit() const
771{
0f485ee5 772 if (ParentPkg()->Arch != TargetPkg()->Arch &&
71c9e95b
DK
773 (S2->Type == pkgCache::Dep::Replaces ||
774 S2->Type == pkgCache::Dep::DpkgBreaks ||
775 S2->Type == pkgCache::Dep::Conflicts))
d5648746
DK
776 return true;
777 return false;
778}
779 /*}}}*/
887c6940
DK
780// DepIterator::IsSatisfied - check if a version satisfied the dependency /*{{{*/
781bool pkgCache::DepIterator::IsSatisfied(VerIterator const &Ver) const
782{
71c9e95b 783 return Owner->VS->CheckDep(Ver.VerStr(),S2->CompareOp,TargetVer());
887c6940
DK
784}
785bool pkgCache::DepIterator::IsSatisfied(PrvIterator const &Prv) const
786{
71c9e95b 787 return Owner->VS->CheckDep(Prv.ProvideVersion(),S2->CompareOp,TargetVer());
887c6940
DK
788}
789 /*}}}*/
47f6d1b7
DK
790// ostream operator to handle string representation of a dependecy /*{{{*/
791// ---------------------------------------------------------------------
792/* */
8f3ba4e8 793std::ostream& operator<<(std::ostream& out, pkgCache::DepIterator D)
47f6d1b7
DK
794{
795 if (D.end() == true)
796 return out << "invalid dependency";
797
798 pkgCache::PkgIterator P = D.ParentPkg();
799 pkgCache::PkgIterator T = D.TargetPkg();
800
801 out << (P.end() ? "invalid pkg" : P.FullName(false)) << " " << D.DepType()
802 << " on ";
803 if (T.end() == true)
804 out << "invalid pkg";
805 else
806 out << T;
807
808 if (D->Version != 0)
809 out << " (" << D.CompType() << " " << D.TargetVer() << ")";
810
811 return out;
812}
813 /*}}}*/
578bfd0a
AL
814// VerIterator::CompareVer - Fast version compare for same pkgs /*{{{*/
815// ---------------------------------------------------------------------
816/* This just looks over the version list to see if B is listed before A. In
817 most cases this will return in under 4 checks, ver lists are short. */
818int pkgCache::VerIterator::CompareVer(const VerIterator &B) const
819{
820 // Check if they are equal
821 if (*this == B)
822 return 0;
823 if (end() == true)
824 return -1;
825 if (B.end() == true)
826 return 1;
827
828 /* Start at A and look for B. If B is found then A > B otherwise
829 B was before A so A < B */
830 VerIterator I = *this;
f7f0d6c7 831 for (;I.end() == false; ++I)
578bfd0a
AL
832 if (I == B)
833 return 1;
834 return -1;
835}
836 /*}}}*/
b518cca6
AL
837// VerIterator::Downloadable - Checks if the version is downloadable /*{{{*/
838// ---------------------------------------------------------------------
839/* */
0e6fe58e 840APT_PURE bool pkgCache::VerIterator::Downloadable() const
b518cca6
AL
841{
842 VerFileIterator Files = FileList();
f7f0d6c7 843 for (; Files.end() == false; ++Files)
b07aeb1a 844 if (Files.File().Flagged(pkgCache::Flag::NotSource) == false)
b518cca6
AL
845 return true;
846 return false;
847}
848 /*}}}*/
3c124dde
AL
849// VerIterator::Automatic - Check if this version is 'automatic' /*{{{*/
850// ---------------------------------------------------------------------
851/* This checks to see if any of the versions files are not NotAutomatic.
852 True if this version is selectable for automatic installation. */
0e6fe58e 853APT_PURE bool pkgCache::VerIterator::Automatic() const
3c124dde
AL
854{
855 VerFileIterator Files = FileList();
f7f0d6c7 856 for (; Files.end() == false; ++Files)
5ed56f93 857 // Do not check ButAutomaticUpgrades here as it is kind of automatic…
b07aeb1a 858 if (Files.File().Flagged(pkgCache::Flag::NotAutomatic) == false)
3c124dde
AL
859 return true;
860 return false;
861}
862 /*}}}*/
863// VerIterator::NewestFile - Return the newest file version relation /*{{{*/
864// ---------------------------------------------------------------------
865/* This looks at the version numbers associated with all of the sources
866 this version is in and returns the highest.*/
867pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const
868{
869 VerFileIterator Files = FileList();
870 VerFileIterator Highest = Files;
f7f0d6c7 871 for (; Files.end() == false; ++Files)
3c124dde 872 {
b2e465d6 873 if (Owner->VS->CmpReleaseVer(Files.File().Version(),Highest.File().Version()) > 0)
3c124dde
AL
874 Highest = Files;
875 }
876
877 return Highest;
878}
879 /*}}}*/
b2e465d6
AL
880// VerIterator::RelStr - Release description string /*{{{*/
881// ---------------------------------------------------------------------
882/* This describes the version from a release-centric manner. The output is a
883 list of Label:Version/Archive */
d4489d49 884string pkgCache::VerIterator::RelStr() const
b2e465d6
AL
885{
886 bool First = true;
887 string Res;
f7f0d6c7 888 for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I)
b2e465d6
AL
889 {
890 // Do not print 'not source' entries'
b07aeb1a
DK
891 pkgCache::PkgFileIterator const File = I.File();
892 if (File.Flagged(pkgCache::Flag::NotSource))
b2e465d6
AL
893 continue;
894
895 // See if we have already printed this out..
896 bool Seen = false;
f7f0d6c7 897 for (pkgCache::VerFileIterator J = this->FileList(); I != J; ++J)
b2e465d6 898 {
b07aeb1a
DK
899 pkgCache::PkgFileIterator const File2 = J.File();
900 if (File2.Label() == 0 || File.Label() == 0)
b2e465d6
AL
901 continue;
902
903 if (strcmp(File.Label(),File2.Label()) != 0)
904 continue;
905
b07aeb1a 906 if (File2.Version() == File.Version())
b2e465d6
AL
907 {
908 Seen = true;
909 break;
910 }
b07aeb1a 911 if (File2.Version() == 0 || File.Version() == 0)
b2e465d6
AL
912 break;
913 if (strcmp(File.Version(),File2.Version()) == 0)
914 Seen = true;
915 }
916
917 if (Seen == true)
918 continue;
919
920 if (First == false)
921 Res += ", ";
922 else
923 First = false;
924
b07aeb1a 925 if (File.Label() != 0)
b2e465d6
AL
926 Res = Res + File.Label() + ':';
927
b07aeb1a 928 if (File.Archive() != 0)
b2e465d6 929 {
b07aeb1a 930 if (File.Version() == 0)
b2e465d6
AL
931 Res += File.Archive();
932 else
933 Res = Res + File.Version() + '/' + File.Archive();
934 }
935 else
936 {
937 // No release file, print the host name that this came from
b07aeb1a 938 if (File.Site() == 0 || File.Site()[0] == 0)
b2e465d6
AL
939 Res += "localhost";
940 else
941 Res += File.Site();
942 }
5dd4c8b8 943 }
857e9c13 944 if (S->ParentPkg != 0)
5dd4c8b8 945 Res.append(" [").append(Arch()).append("]");
b2e465d6
AL
946 return Res;
947}
948 /*}}}*/
7a948ec7
DK
949// VerIterator::MultiArchType - string representing MultiArch flag /*{{{*/
950const char * pkgCache::VerIterator::MultiArchType() const
951{
952 if ((S->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
953 return "same";
954 else if ((S->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign)
955 return "foreign";
956 else if ((S->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
957 return "allowed";
958 return "none";
959}
960 /*}}}*/
b07aeb1a 961// RlsFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/
578bfd0a
AL
962// ---------------------------------------------------------------------
963/* This stats the file and compares its stats with the ones that were
b07aeb1a 964 stored during generation. Date checks should probably also be
578bfd0a 965 included here. */
b07aeb1a 966bool pkgCache::RlsFileIterator::IsOk()
578bfd0a
AL
967{
968 struct stat Buf;
969 if (stat(FileName(),&Buf) != 0)
970 return false;
971
773e2c1f 972 if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime)
578bfd0a
AL
973 return false;
974
975 return true;
976}
977 /*}}}*/
b07aeb1a
DK
978// RlsFileIterator::RelStr - Return the release string /*{{{*/
979string pkgCache::RlsFileIterator::RelStr()
af87ab54
AL
980{
981 string Res;
982 if (Version() != 0)
983 Res = Res + (Res.empty() == true?"v=":",v=") + Version();
984 if (Origin() != 0)
985 Res = Res + (Res.empty() == true?"o=":",o=") + Origin();
986 if (Archive() != 0)
987 Res = Res + (Res.empty() == true?"a=":",a=") + Archive();
efc487fb
DK
988 if (Codename() != 0)
989 Res = Res + (Res.empty() == true?"n=":",n=") + Codename();
af87ab54
AL
990 if (Label() != 0)
991 Res = Res + (Res.empty() == true?"l=":",l=") + Label();
b07aeb1a
DK
992 return Res;
993}
994 /*}}}*/
995// PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/
996// ---------------------------------------------------------------------
997/* This stats the file and compares its stats with the ones that were
998 stored during generation. Date checks should probably also be
999 included here. */
1000bool pkgCache::PkgFileIterator::IsOk()
1001{
1002 struct stat Buf;
1003 if (stat(FileName(),&Buf) != 0)
1004 return false;
1005
1006 if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime)
1007 return false;
1008
1009 return true;
1010}
1011 /*}}}*/
1012string pkgCache::PkgFileIterator::RelStr() /*{{{*/
1013{
1014 std::string Res;
1015 if (ReleaseFile() == 0)
1016 {
1017 if (Component() != 0)
1018 Res = Res + (Res.empty() == true?"a=":",a=") + Component();
1019 }
1020 else
1021 {
1022 Res = ReleaseFile().RelStr();
1023 if (Component() != 0)
1024 Res = Res + (Res.empty() == true?"c=":",c=") + Component();
1025 }
5dd4c8b8
DK
1026 if (Architecture() != 0)
1027 Res = Res + (Res.empty() == true?"b=":",b=") + Architecture();
af87ab54
AL
1028 return Res;
1029}
1030 /*}}}*/
012b102a
MV
1031// VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
1032// ---------------------------------------------------------------------
d3e8fbb3 1033/* return a DescIter for the current locale or the default if none is
012b102a
MV
1034 * found
1035 */
1036pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
1037{
45df0ad2
DK
1038 std::vector<string> const lang = APT::Configuration::getLanguages();
1039 for (std::vector<string>::const_iterator l = lang.begin();
f7f0d6c7 1040 l != lang.end(); ++l)
45df0ad2 1041 {
4b625b95
DK
1042 pkgCache::DescIterator Desc = DescriptionList();
1043 for (; Desc.end() == false; ++Desc)
0e7c3313 1044 if (*l == Desc.LanguageCode())
45df0ad2 1045 break;
4b625b95 1046 if (Desc.end() == true)
0e7c3313
DK
1047 {
1048 if (*l == "en")
1049 {
1050 Desc = DescriptionList();
1051 for (; Desc.end() == false; ++Desc)
1052 if (strcmp(Desc.LanguageCode(), "") == 0)
1053 break;
1054 if (Desc.end() == true)
1055 continue;
1056 }
1057 else
1058 continue;
1059 }
45df0ad2
DK
1060 return Desc;
1061 }
4b625b95
DK
1062 for (pkgCache::DescIterator Desc = DescriptionList();
1063 Desc.end() == false; ++Desc)
1064 if (strcmp(Desc.LanguageCode(), "") == 0)
1065 return Desc;
45df0ad2 1066 return DescriptionList();
d3e8fbb3 1067}
012b102a
MV
1068
1069 /*}}}*/
d5648746
DK
1070// PrvIterator::IsMultiArchImplicit - added by the cache generation /*{{{*/
1071// ---------------------------------------------------------------------
1072/* MultiArch can be translated to SingleArch for an resolver and we did so,
1073 by adding provides to help the resolver understand the problem, but
1074 sometimes it is needed to identify these to ignore them… */
1075bool pkgCache::PrvIterator::IsMultiArchImplicit() const
1076{
1077 pkgCache::PkgIterator const Owner = OwnerPkg();
1078 pkgCache::PkgIterator const Parent = ParentPkg();
fe86debb 1079 if (strcmp(Owner.Arch(), Parent.Arch()) != 0 || Owner.Group()->Name == Parent.Group()->Name)
d5648746
DK
1080 return true;
1081 return false;
1082}
1083 /*}}}*/
c8a4ce6c
DK
1084
1085pkgCache::~pkgCache() {}