* merged the apt--curl-https branch
[ntk/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
11 This is the general utility functions for cache managment. They provide
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 /*{{{*/
6c139d6e 23#ifdef __GNUG__
094a497d
AL
24#pragma implementation "apt-pkg/pkgcache.h"
25#pragma implementation "apt-pkg/cacheiterators.h"
6c139d6e 26#endif
b2e465d6 27
094a497d 28#include <apt-pkg/pkgcache.h>
012b102a 29#include <apt-pkg/indexfile.h>
094a497d
AL
30#include <apt-pkg/version.h>
31#include <apt-pkg/error.h>
231fea14 32#include <apt-pkg/strutl.h>
b2e465d6 33#include <apt-pkg/configuration.h>
578bfd0a 34
b2e465d6
AL
35#include <apti18n.h>
36
578bfd0a
AL
37#include <string>
38#include <sys/stat.h>
39#include <unistd.h>
1ae93c94 40
851a45a8 41#include <ctype.h>
1ae93c94 42#include <system.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{
53 Signature = 0x98FE76DC;
54
55 /* Whenever the structures change the major version should be bumped,
56 whenever the generator changes the minor version should be bumped. */
d242b9e7 57 MajorVersion = 6;
6a3da7a6 58 MinorVersion = 0;
b2e465d6 59 Dirty = false;
578bfd0a
AL
60
61 HeaderSz = sizeof(pkgCache::Header);
62 PackageSz = sizeof(pkgCache::Package);
63 PackageFileSz = sizeof(pkgCache::PackageFile);
64 VersionSz = sizeof(pkgCache::Version);
a52f938b 65 DescriptionSz = sizeof(pkgCache::Description);
578bfd0a
AL
66 DependencySz = sizeof(pkgCache::Dependency);
67 ProvidesSz = sizeof(pkgCache::Provides);
dcb79bae 68 VerFileSz = sizeof(pkgCache::VerFile);
a52f938b 69 DescFileSz = sizeof(pkgCache::DescFile);
dcb79bae 70
578bfd0a
AL
71 PackageCount = 0;
72 VersionCount = 0;
a52f938b 73 DescriptionCount = 0;
578bfd0a
AL
74 DependsCount = 0;
75 PackageFileCount = 0;
a7e66b17 76 VerFileCount = 0;
a52f938b 77 DescFileCount = 0;
a7e66b17 78 ProvidesCount = 0;
ad00ae81 79 MaxVerFileSize = 0;
a52f938b 80 MaxDescFileSize = 0;
578bfd0a
AL
81
82 FileList = 0;
83 StringList = 0;
b2e465d6
AL
84 VerSysName = 0;
85 Architecture = 0;
578bfd0a
AL
86 memset(HashTable,0,sizeof(HashTable));
87 memset(Pools,0,sizeof(Pools));
88}
89 /*}}}*/
90// Cache::Header::CheckSizes - Check if the two headers have same *sz /*{{{*/
91// ---------------------------------------------------------------------
92/* */
93bool pkgCache::Header::CheckSizes(Header &Against) const
94{
95 if (HeaderSz == Against.HeaderSz &&
96 PackageSz == Against.PackageSz &&
97 PackageFileSz == Against.PackageFileSz &&
98 VersionSz == Against.VersionSz &&
a52f938b 99 DescriptionSz == Against.DescriptionSz &&
dcb79bae
AL
100 DependencySz == Against.DependencySz &&
101 VerFileSz == Against.VerFileSz &&
a52f938b 102 DescFileSz == Against.DescFileSz &&
578bfd0a
AL
103 ProvidesSz == Against.ProvidesSz)
104 return true;
105 return false;
106}
107 /*}}}*/
108
109// Cache::pkgCache - Constructor /*{{{*/
110// ---------------------------------------------------------------------
111/* */
b2e465d6 112pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map)
578bfd0a 113{
b2e465d6
AL
114 if (DoMap == true)
115 ReMap();
578bfd0a
AL
116}
117 /*}}}*/
118// Cache::ReMap - Reopen the cache file /*{{{*/
119// ---------------------------------------------------------------------
120/* If the file is already closed then this will open it open it. */
121bool pkgCache::ReMap()
122{
123 // Apply the typecasts.
124 HeaderP = (Header *)Map.Data();
125 PkgP = (Package *)Map.Data();
dcb79bae 126 VerFileP = (VerFile *)Map.Data();
a52f938b 127 DescFileP = (DescFile *)Map.Data();
578bfd0a
AL
128 PkgFileP = (PackageFile *)Map.Data();
129 VerP = (Version *)Map.Data();
a52f938b 130 DescP = (Description *)Map.Data();
578bfd0a
AL
131 ProvideP = (Provides *)Map.Data();
132 DepP = (Dependency *)Map.Data();
133 StringItemP = (StringItem *)Map.Data();
134 StrP = (char *)Map.Data();
135
b2e465d6
AL
136 if (Map.Size() == 0 || HeaderP == 0)
137 return _error->Error(_("Empty package cache"));
578bfd0a
AL
138
139 // Check the header
140 Header DefHeader;
141 if (HeaderP->Signature != DefHeader.Signature ||
142 HeaderP->Dirty == true)
b2e465d6 143 return _error->Error(_("The package cache file is corrupted"));
578bfd0a
AL
144
145 if (HeaderP->MajorVersion != DefHeader.MajorVersion ||
146 HeaderP->MinorVersion != DefHeader.MinorVersion ||
147 HeaderP->CheckSizes(DefHeader) == false)
b2e465d6
AL
148 return _error->Error(_("The package cache file is an incompatible version"));
149
150 // Locate our VS..
151 if (HeaderP->VerSysName == 0 ||
152 (VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
db0db9fe 153 return _error->Error(_("This APT does not support the versioning system '%s'"),StrP + HeaderP->VerSysName);
b2e465d6
AL
154
155 // Chcek the arhcitecture
156 if (HeaderP->Architecture == 0 ||
157 _config->Find("APT::Architecture") != StrP + HeaderP->Architecture)
bac2e715 158 return _error->Error(_("The package cache was built for a different architecture"));
578bfd0a
AL
159 return true;
160}
161 /*}}}*/
162// Cache::Hash - Hash a string /*{{{*/
163// ---------------------------------------------------------------------
164/* This is used to generate the hash entries for the HashTable. With my
165 package list from bo this function gets 94% table usage on a 512 item
166 table (480 used items) */
171c75f1 167unsigned long pkgCache::sHash(const string &Str) const
578bfd0a
AL
168{
169 unsigned long Hash = 0;
851a45a8 170 for (string::const_iterator I = Str.begin(); I != Str.end(); I++)
231fea14 171 Hash = 5*Hash + tolower(*I);
f9eec0e7 172 return Hash % _count(HeaderP->HashTable);
578bfd0a
AL
173}
174
f9eec0e7 175unsigned long pkgCache::sHash(const char *Str) const
578bfd0a
AL
176{
177 unsigned long Hash = 0;
f9eec0e7 178 for (const char *I = Str; *I != 0; I++)
231fea14 179 Hash = 5*Hash + tolower(*I);
f9eec0e7 180 return Hash % _count(HeaderP->HashTable);
578bfd0a
AL
181}
182
183 /*}}}*/
184// Cache::FindPkg - Locate a package by name /*{{{*/
185// ---------------------------------------------------------------------
186/* Returns 0 on error, pointer to the package otherwise */
171c75f1 187pkgCache::PkgIterator pkgCache::FindPkg(const string &Name)
578bfd0a
AL
188{
189 // Look at the hash bucket
190 Package *Pkg = PkgP + HeaderP->HashTable[Hash(Name)];
191 for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage)
192 {
c1a22377 193 if (Pkg->Name != 0 && StrP[Pkg->Name] == Name[0] &&
851a45a8 194 stringcasecmp(Name,StrP + Pkg->Name) == 0)
578bfd0a
AL
195 return PkgIterator(*this,Pkg);
196 }
197 return PkgIterator(*this,0);
198}
199 /*}}}*/
b2e465d6
AL
200// Cache::CompTypeDeb - Return a string describing the compare type /*{{{*/
201// ---------------------------------------------------------------------
202/* This returns a string representation of the dependency compare
203 type in the weird debian style.. */
204const char *pkgCache::CompTypeDeb(unsigned char Comp)
205{
206 const char *Ops[] = {"","<=",">=","<<",">>","=","!="};
207 if ((unsigned)(Comp & 0xF) < 7)
208 return Ops[Comp & 0xF];
209 return "";
210}
211 /*}}}*/
212// Cache::CompType - Return a string describing the compare type /*{{{*/
213// ---------------------------------------------------------------------
214/* This returns a string representation of the dependency compare
215 type */
216const char *pkgCache::CompType(unsigned char Comp)
217{
218 const char *Ops[] = {"","<=",">=","<",">","=","!="};
219 if ((unsigned)(Comp & 0xF) < 7)
220 return Ops[Comp & 0xF];
221 return "";
222}
223 /*}}}*/
224// Cache::DepType - Return a string describing the dep type /*{{{*/
225// ---------------------------------------------------------------------
226/* */
227const char *pkgCache::DepType(unsigned char Type)
228{
229 const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
230 _("Recommends"),_("Conflicts"),_("Replaces"),
308c7d30
IJ
231 _("Obsoletes"),_("Breaks")};
232 if (Type < sizeof(Types)/sizeof(*Types))
b2e465d6
AL
233 return Types[Type];
234 return "";
235}
236 /*}}}*/
0149949b
AL
237// Cache::Priority - Convert a priority value to a string /*{{{*/
238// ---------------------------------------------------------------------
239/* */
240const char *pkgCache::Priority(unsigned char Prio)
241{
b2e465d6
AL
242 const char *Mapping[] = {0,_("important"),_("required"),_("standard"),
243 _("optional"),_("extra")};
0149949b
AL
244 if (Prio < _count(Mapping))
245 return Mapping[Prio];
246 return 0;
247}
248 /*}}}*/
f55a958f
AL
249// Bases for iterator classes /*{{{*/
250void pkgCache::VerIterator::_dummy() {}
251void pkgCache::DepIterator::_dummy() {}
252void pkgCache::PrvIterator::_dummy() {}
770c32ec 253void pkgCache::DescIterator::_dummy() {}
f55a958f
AL
254 /*}}}*/
255// PkgIterator::operator ++ - Postfix incr /*{{{*/
578bfd0a
AL
256// ---------------------------------------------------------------------
257/* This will advance to the next logical package in the hash table. */
258void pkgCache::PkgIterator::operator ++(int)
259{
260 // Follow the current links
261 if (Pkg != Owner->PkgP)
262 Pkg = Owner->PkgP + Pkg->NextPackage;
b2e465d6 263
578bfd0a 264 // Follow the hash table
b2e465d6 265 while (Pkg == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->HashTable))
578bfd0a
AL
266 {
267 HashIndex++;
268 Pkg = Owner->PkgP + Owner->HeaderP->HashTable[HashIndex];
269 }
270};
271 /*}}}*/
578bfd0a
AL
272// PkgIterator::State - Check the State of the package /*{{{*/
273// ---------------------------------------------------------------------
274/* By this we mean if it is either cleanly installed or cleanly removed. */
275pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
d38b7b3d 276{
c7c1b0f6
AL
277 if (Pkg->InstState == pkgCache::State::ReInstReq ||
278 Pkg->InstState == pkgCache::State::HoldReInstReq)
279 return NeedsUnpack;
280
7d4f285b
AL
281 if (Pkg->CurrentState == pkgCache::State::UnPacked ||
282 Pkg->CurrentState == pkgCache::State::HalfConfigured)
578bfd0a
AL
283 return NeedsConfigure;
284
a005475e 285 if (Pkg->CurrentState == pkgCache::State::HalfInstalled ||
7d4f285b 286 Pkg->InstState != pkgCache::State::Ok)
578bfd0a
AL
287 return NeedsUnpack;
288
289 return NeedsNothing;
290}
291 /*}}}*/
292// DepIterator::IsCritical - Returns true if the dep is important /*{{{*/
293// ---------------------------------------------------------------------
294/* Currently critical deps are defined as depends, predepends and
308c7d30 295 conflicts (including dpkg's Breaks fields). */
578bfd0a
AL
296bool pkgCache::DepIterator::IsCritical()
297{
b2e465d6 298 if (Dep->Type == pkgCache::Dep::Conflicts ||
308c7d30 299 Dep->Type == pkgCache::Dep::DpkgBreaks ||
b2e465d6 300 Dep->Type == pkgCache::Dep::Obsoletes ||
f07b5628
AL
301 Dep->Type == pkgCache::Dep::Depends ||
302 Dep->Type == pkgCache::Dep::PreDepends)
578bfd0a
AL
303 return true;
304 return false;
305}
306 /*}}}*/
307// DepIterator::SmartTargetPkg - Resolve dep target pointers w/provides /*{{{*/
308// ---------------------------------------------------------------------
309/* This intellegently looks at dep target packages and tries to figure
310 out which package should be used. This is needed to nicely handle
311 provide mapping. If the target package has no other providing packages
312 then it returned. Otherwise the providing list is looked at to
313 see if there is one one unique providing package if so it is returned.
314 Otherwise true is returned and the target package is set. The return
b2e465d6
AL
315 result indicates whether the node should be expandable
316
317 In Conjunction with the DepCache the value of Result may not be
318 super-good since the policy may have made it uninstallable. Using
319 AllTargets is better in this case. */
578bfd0a
AL
320bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result)
321{
322 Result = TargetPkg();
323
324 // No provides at all
325 if (Result->ProvidesList == 0)
326 return false;
327
328 // There is the Base package and the providing ones which is at least 2
329 if (Result->VersionList != 0)
330 return true;
331
332 /* We have to skip over indirect provisions of the package that
333 owns the dependency. For instance, if libc5-dev depends on the
334 virtual package libc-dev which is provided by libc5-dev and libc6-dev
335 we must ignore libc5-dev when considering the provides list. */
336 PrvIterator PStart = Result.ProvidesList();
337 for (; PStart.end() != true && PStart.OwnerPkg() == ParentPkg(); PStart++);
338
339 // Nothing but indirect self provides
340 if (PStart.end() == true)
341 return false;
342
343 // Check for single packages in the provides list
344 PrvIterator P = PStart;
345 for (; P.end() != true; P++)
346 {
347 // Skip over self provides
348 if (P.OwnerPkg() == ParentPkg())
349 continue;
350 if (PStart.OwnerPkg() != P.OwnerPkg())
351 break;
352 }
b2e465d6
AL
353
354 Result = PStart.OwnerPkg();
578bfd0a
AL
355
356 // Check for non dups
357 if (P.end() != true)
358 return true;
b2e465d6 359
578bfd0a
AL
360 return false;
361}
362 /*}}}*/
363// DepIterator::AllTargets - Returns the set of all possible targets /*{{{*/
364// ---------------------------------------------------------------------
b2e465d6 365/* This is a more useful version of TargetPkg() that follows versioned
578bfd0a 366 provides. It includes every possible package-version that could satisfy
fbfb2a7c
AL
367 the dependency. The last item in the list has a 0. The resulting pointer
368 must be delete [] 'd */
578bfd0a
AL
369pkgCache::Version **pkgCache::DepIterator::AllTargets()
370{
371 Version **Res = 0;
372 unsigned long Size =0;
373 while (1)
374 {
375 Version **End = Res;
376 PkgIterator DPkg = TargetPkg();
377
378 // Walk along the actual package providing versions
379 for (VerIterator I = DPkg.VersionList(); I.end() == false; I++)
380 {
b2e465d6 381 if (Owner->VS->CheckDep(I.VerStr(),Dep->CompareOp,TargetVer()) == false)
578bfd0a
AL
382 continue;
383
b2e465d6 384 if ((Dep->Type == pkgCache::Dep::Conflicts ||
308c7d30 385 Dep->Type == pkgCache::Dep::DpkgBreaks ||
b2e465d6 386 Dep->Type == pkgCache::Dep::Obsoletes) &&
f07b5628 387 ParentPkg() == I.ParentPkg())
578bfd0a
AL
388 continue;
389
390 Size++;
391 if (Res != 0)
392 *End++ = I;
393 }
394
395 // Follow all provides
396 for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; I++)
397 {
b2e465d6 398 if (Owner->VS->CheckDep(I.ProvideVersion(),Dep->CompareOp,TargetVer()) == false)
578bfd0a
AL
399 continue;
400
b2e465d6 401 if ((Dep->Type == pkgCache::Dep::Conflicts ||
308c7d30 402 Dep->Type == pkgCache::Dep::DpkgBreaks ||
b2e465d6 403 Dep->Type == pkgCache::Dep::Obsoletes) &&
f07b5628 404 ParentPkg() == I.OwnerPkg())
578bfd0a
AL
405 continue;
406
407 Size++;
408 if (Res != 0)
409 *End++ = I.OwnerVer();
410 }
411
412 // Do it again and write it into the array
413 if (Res == 0)
414 {
415 Res = new Version *[Size+1];
416 Size = 0;
417 }
418 else
419 {
420 *End = 0;
421 break;
422 }
423 }
424
425 return Res;
426}
427 /*}}}*/
43d017d6
AL
428// DepIterator::GlobOr - Compute an OR group /*{{{*/
429// ---------------------------------------------------------------------
430/* This Takes an iterator, iterates past the current dependency grouping
431 and returns Start and End so that so End is the final element
432 in the group, if End == Start then D is End++ and End is the
433 dependency D was pointing to. Use in loops to iterate sensibly. */
434void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End)
435{
436 // Compute a single dependency element (glob or)
437 Start = *this;
438 End = *this;
018f1533 439 for (bool LastOR = true; end() == false && LastOR == true;)
43d017d6
AL
440 {
441 LastOR = (Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
018f1533 442 (*this)++;
43d017d6
AL
443 if (LastOR == true)
444 End = (*this);
445 }
446}
447 /*}}}*/
578bfd0a
AL
448// VerIterator::CompareVer - Fast version compare for same pkgs /*{{{*/
449// ---------------------------------------------------------------------
450/* This just looks over the version list to see if B is listed before A. In
451 most cases this will return in under 4 checks, ver lists are short. */
452int pkgCache::VerIterator::CompareVer(const VerIterator &B) const
453{
454 // Check if they are equal
455 if (*this == B)
456 return 0;
457 if (end() == true)
458 return -1;
459 if (B.end() == true)
460 return 1;
461
462 /* Start at A and look for B. If B is found then A > B otherwise
463 B was before A so A < B */
464 VerIterator I = *this;
465 for (;I.end() == false; I++)
466 if (I == B)
467 return 1;
468 return -1;
469}
470 /*}}}*/
b518cca6
AL
471// VerIterator::Downloadable - Checks if the version is downloadable /*{{{*/
472// ---------------------------------------------------------------------
473/* */
474bool pkgCache::VerIterator::Downloadable() const
475{
476 VerFileIterator Files = FileList();
477 for (; Files.end() == false; Files++)
f07b5628 478 if ((Files.File()->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource)
b518cca6
AL
479 return true;
480 return false;
481}
482 /*}}}*/
3c124dde
AL
483// VerIterator::Automatic - Check if this version is 'automatic' /*{{{*/
484// ---------------------------------------------------------------------
485/* This checks to see if any of the versions files are not NotAutomatic.
486 True if this version is selectable for automatic installation. */
487bool pkgCache::VerIterator::Automatic() const
488{
489 VerFileIterator Files = FileList();
490 for (; Files.end() == false; Files++)
491 if ((Files.File()->Flags & pkgCache::Flag::NotAutomatic) != pkgCache::Flag::NotAutomatic)
492 return true;
493 return false;
494}
495 /*}}}*/
496// VerIterator::NewestFile - Return the newest file version relation /*{{{*/
497// ---------------------------------------------------------------------
498/* This looks at the version numbers associated with all of the sources
499 this version is in and returns the highest.*/
500pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const
501{
502 VerFileIterator Files = FileList();
503 VerFileIterator Highest = Files;
504 for (; Files.end() == false; Files++)
505 {
b2e465d6 506 if (Owner->VS->CmpReleaseVer(Files.File().Version(),Highest.File().Version()) > 0)
3c124dde
AL
507 Highest = Files;
508 }
509
510 return Highest;
511}
512 /*}}}*/
b2e465d6
AL
513// VerIterator::RelStr - Release description string /*{{{*/
514// ---------------------------------------------------------------------
515/* This describes the version from a release-centric manner. The output is a
516 list of Label:Version/Archive */
517string pkgCache::VerIterator::RelStr()
518{
519 bool First = true;
520 string Res;
521 for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; I++)
522 {
523 // Do not print 'not source' entries'
524 pkgCache::PkgFileIterator File = I.File();
525 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
526 continue;
527
528 // See if we have already printed this out..
529 bool Seen = false;
530 for (pkgCache::VerFileIterator J = this->FileList(); I != J; J++)
531 {
532 pkgCache::PkgFileIterator File2 = J.File();
533 if (File2->Label == 0 || File->Label == 0)
534 continue;
535
536 if (strcmp(File.Label(),File2.Label()) != 0)
537 continue;
538
539 if (File2->Version == File->Version)
540 {
541 Seen = true;
542 break;
543 }
10639577 544 if (File2->Version == 0 || File->Version == 0)
b2e465d6
AL
545 break;
546 if (strcmp(File.Version(),File2.Version()) == 0)
547 Seen = true;
548 }
549
550 if (Seen == true)
551 continue;
552
553 if (First == false)
554 Res += ", ";
555 else
556 First = false;
557
558 if (File->Label != 0)
559 Res = Res + File.Label() + ':';
560
561 if (File->Archive != 0)
562 {
563 if (File->Version == 0)
564 Res += File.Archive();
565 else
566 Res = Res + File.Version() + '/' + File.Archive();
567 }
568 else
569 {
570 // No release file, print the host name that this came from
571 if (File->Site == 0 || File.Site()[0] == 0)
572 Res += "localhost";
573 else
574 Res += File.Site();
575 }
576 }
577 return Res;
578}
579 /*}}}*/
578bfd0a
AL
580// PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/
581// ---------------------------------------------------------------------
582/* This stats the file and compares its stats with the ones that were
583 stored during generation. Date checks should probably also be
584 included here. */
585bool pkgCache::PkgFileIterator::IsOk()
586{
587 struct stat Buf;
588 if (stat(FileName(),&Buf) != 0)
589 return false;
590
591 if (Buf.st_size != (signed)File->Size || Buf.st_mtime != File->mtime)
592 return false;
593
594 return true;
595}
596 /*}}}*/
af87ab54
AL
597// PkgFileIterator::RelStr - Return the release string /*{{{*/
598// ---------------------------------------------------------------------
599/* */
600string pkgCache::PkgFileIterator::RelStr()
601{
602 string Res;
603 if (Version() != 0)
604 Res = Res + (Res.empty() == true?"v=":",v=") + Version();
605 if (Origin() != 0)
606 Res = Res + (Res.empty() == true?"o=":",o=") + Origin();
607 if (Archive() != 0)
608 Res = Res + (Res.empty() == true?"a=":",a=") + Archive();
609 if (Label() != 0)
610 Res = Res + (Res.empty() == true?"l=":",l=") + Label();
611 if (Component() != 0)
612 Res = Res + (Res.empty() == true?"c=":",c=") + Component();
613 return Res;
614}
615 /*}}}*/
012b102a
MV
616// VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
617// ---------------------------------------------------------------------
618/* return a DescIter for the current locale or the default if none is
619 * found
620 */
621pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
622{
623 pkgCache::DescIterator DescDefault = DescriptionList();
624 pkgCache::DescIterator Desc = DescDefault;
625 for (; Desc.end() == false; Desc++)
626 if (pkgIndexFile::LanguageCode() == Desc.LanguageCode())
627 break;
628 if (Desc.end() == true) Desc = DescDefault;
629 return Desc;
630};
631
632 /*}}}*/