]> git.saurik.com Git - apt.git/blame - apt-pkg/pkgcachegen.cc
More progress updates
[apt.git] / apt-pkg / pkgcachegen.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
8ce4327b 3// $Id: pkgcachegen.cc,v 1.14 1998/08/26 04:52:23 jgg Exp $
578bfd0a
AL
4/* ######################################################################
5
6 Package Cache Generator - Generator for the cache structure.
7
8 This builds the cache structure from the abstract package list parser.
9
10 ##################################################################### */
11 /*}}}*/
12// Include Files /*{{{*/
6c139d6e 13#ifdef __GNUG__
094a497d 14#pragma implementation "apt-pkg/pkgcachegen.h"
6c139d6e
AL
15#endif
16
094a497d
AL
17#include <apt-pkg/pkgcachegen.h>
18#include <apt-pkg/error.h>
19#include <apt-pkg/version.h>
b35d2f5f
AL
20#include <apt-pkg/progress.h>
21#include <apt-pkg/sourcelist.h>
22#include <apt-pkg/configuration.h>
23#include <apt-pkg/deblistparser.h>
24
9c14e3d6 25#include <strutl.h>
578bfd0a
AL
26
27#include <sys/stat.h>
28#include <unistd.h>
29 /*}}}*/
30
31// CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
32// ---------------------------------------------------------------------
33/* We set the diry flag and make sure that is written to the disk */
404ec98e
AL
34pkgCacheGenerator::pkgCacheGenerator(DynamicMMap &Map,OpProgress &Prog) :
35 Map(Map), Cache(Map), Progress(Prog)
578bfd0a
AL
36{
37 if (_error->PendingError() == true)
38 return;
39
40 if (Map.Size() == 0)
41 {
42 Map.RawAllocate(sizeof(pkgCache::Header));
43 *Cache.HeaderP = pkgCache::Header();
44 }
45 Cache.HeaderP->Dirty = true;
46 Map.Sync(0,sizeof(pkgCache::Header));
47 Map.UsePools(*Cache.HeaderP->Pools,sizeof(Cache.HeaderP->Pools)/sizeof(Cache.HeaderP->Pools[0]));
48}
49 /*}}}*/
50// CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/
51// ---------------------------------------------------------------------
52/* We sync the data then unset the dirty flag in two steps so as to
53 advoid a problem during a crash */
54pkgCacheGenerator::~pkgCacheGenerator()
55{
56 if (_error->PendingError() == true)
57 return;
58 if (Map.Sync() == false)
59 return;
60
61 Cache.HeaderP->Dirty = false;
62 Map.Sync(0,sizeof(pkgCache::Header));
63}
64 /*}}}*/
65// CacheGenerator::MergeList - Merge the package list /*{{{*/
66// ---------------------------------------------------------------------
67/* This provides the generation of the entries in the cache. Each loop
68 goes through a single package record from the underlying parse engine. */
69bool pkgCacheGenerator::MergeList(ListParser &List)
70{
71 List.Owner = this;
0149949b
AL
72
73 while (List.Step() == true)
578bfd0a
AL
74 {
75 // Get a pointer to the package structure
9ddf7030
AL
76 string PackageName = List.Package();
77 pkgCache::PkgIterator Pkg;
8efa2a3b 78 if (NewPackage(Pkg,PackageName) == false)
b35d2f5f 79 return _error->Error("Error occured while processing %s (NewPackage)",PackageName.c_str());
404ec98e 80 Progress.Progress(List.Offset());
8ce4327b 81
578bfd0a
AL
82 /* Get a pointer to the version structure. We know the list is sorted
83 so we use that fact in the search. Insertion of new versions is
84 done with correct sorting */
85 string Version = List.Version();
f55a958f
AL
86 if (Version.empty() == true)
87 {
88 if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false)
b35d2f5f 89 return _error->Error("Error occured while processing %s (UsePackage1)",PackageName.c_str());
f55a958f
AL
90 continue;
91 }
92
578bfd0a
AL
93 pkgCache::VerIterator Ver = Pkg.VersionList();
94 unsigned long *Last = &Pkg->VersionList;
2246928b 95 int Res = 1;
f55a958f 96 for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
578bfd0a
AL
97 {
98 Res = pkgVersionCompare(Version.begin(),Version.end(),Ver.VerStr(),
99 Ver.VerStr() + strlen(Ver.VerStr()));
100 if (Res >= 0)
101 break;
102 }
103
104 /* We already have a version for this item, record that we
105 saw it */
106 if (Res == 0)
107 {
f55a958f 108 if (List.UsePackage(Pkg,Ver) == false)
b35d2f5f 109 return _error->Error("Error occured while processing %s (UsePackage2)",PackageName.c_str());
f55a958f 110
578bfd0a 111 if (NewFileVer(Ver,List) == false)
b35d2f5f 112 return _error->Error("Error occured while processing %s (NewFileVer1)",PackageName.c_str());
578bfd0a
AL
113
114 continue;
115 }
116
117 // Add a new version
f55a958f
AL
118 *Last = NewVersion(Ver,Version,*Last);
119 Ver->ParentPkg = Pkg.Index();
578bfd0a 120 if (List.NewVersion(Ver) == false)
b35d2f5f 121 return _error->Error("Error occured while processing %s (NewVersion1)",PackageName.c_str());
0149949b 122
f55a958f 123 if (List.UsePackage(Pkg,Ver) == false)
b35d2f5f 124 return _error->Error("Error occured while processing %s (UsePackage3)",PackageName.c_str());
f55a958f 125
578bfd0a 126 if (NewFileVer(Ver,List) == false)
b35d2f5f 127 return _error->Error("Error occured while processing %s (NewVersion2)",PackageName.c_str());
578bfd0a 128 }
0149949b 129
578bfd0a
AL
130 return true;
131}
132 /*}}}*/
133// CacheGenerator::NewPackage - Add a new package /*{{{*/
134// ---------------------------------------------------------------------
135/* This creates a new package structure and adds it to the hash table */
f55a958f 136bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,string Name)
578bfd0a 137{
8efa2a3b
AL
138 Pkg = Cache.FindPkg(Name);
139 if (Pkg.end() == false)
140 return true;
141
578bfd0a
AL
142 // Get a structure
143 unsigned long Package = Map.Allocate(sizeof(pkgCache::Package));
144 if (Package == 0)
145 return false;
146
f55a958f 147 Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
578bfd0a
AL
148
149 // Insert it into the hash table
f55a958f 150 unsigned long Hash = Cache.Hash(Name);
578bfd0a
AL
151 Pkg->NextPackage = Cache.HeaderP->HashTable[Hash];
152 Cache.HeaderP->HashTable[Hash] = Package;
153
154 // Set the name and the ID
155 Pkg->Name = Map.WriteString(Name);
156 if (Pkg->Name == 0)
157 return false;
158 Pkg->ID = Cache.HeaderP->PackageCount++;
159
160 return true;
161}
162 /*}}}*/
163// CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
164// ---------------------------------------------------------------------
165/* */
f55a958f 166bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver,
578bfd0a
AL
167 ListParser &List)
168{
dcb79bae
AL
169 // Get a structure
170 unsigned long VerFile = Map.Allocate(sizeof(pkgCache::VerFile));
171 if (VerFile == 0)
172 return 0;
173
174 pkgCache::VerFileIterator VF(Cache,Cache.VerFileP + VerFile);
175 VF->File = CurrentFile - Cache.PkgFileP;
176 VF->NextFile = Ver->FileList;
177 Ver->FileList = VF.Index();
178 VF->Offset = List.Offset();
179 VF->Size = List.Size();
ad00ae81
AL
180 if (Cache.HeaderP->MaxVerFileSize < VF->Size)
181 Cache.HeaderP->MaxVerFileSize = VF->Size;
f55a958f 182 return true;
578bfd0a
AL
183}
184 /*}}}*/
185// CacheGenerator::NewVersion - Create a new Version /*{{{*/
186// ---------------------------------------------------------------------
f55a958f 187/* This puts a version structure in the linked list */
578bfd0a 188unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
f55a958f 189 string VerStr,
578bfd0a
AL
190 unsigned long Next)
191{
f55a958f
AL
192 // Get a structure
193 unsigned long Version = Map.Allocate(sizeof(pkgCache::Version));
194 if (Version == 0)
0149949b 195 return 0;
f55a958f
AL
196
197 // Fill it in
198 Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version);
f55a958f
AL
199 Ver->NextVer = Next;
200 Ver->ID = Cache.HeaderP->VersionCount++;
201 Ver->VerStr = Map.WriteString(VerStr);
202 if (Ver->VerStr == 0)
0149949b 203 return 0;
f55a958f 204
0149949b 205 return Version;
578bfd0a
AL
206}
207 /*}}}*/
dcb79bae
AL
208// ListParser::NewDepends - Create a dependency element /*{{{*/
209// ---------------------------------------------------------------------
210/* This creates a dependency element in the tree. It is linked to the
211 version and to the package that it is pointing to. */
212bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
9ddf7030
AL
213 string PackageName,
214 string Version,
dcb79bae
AL
215 unsigned int Op,
216 unsigned int Type)
217{
218 pkgCache &Cache = Owner->Cache;
219
220 // Get a structure
221 unsigned long Dependency = Owner->Map.Allocate(sizeof(pkgCache::Dependency));
222 if (Dependency == 0)
223 return false;
224
225 // Fill it in
226 pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency);
227 Dep->ParentVer = Ver.Index();
228 Dep->Type = Type;
229 Dep->CompareOp = Op;
230 Dep->ID = Cache.HeaderP->DependsCount++;
231
232 // Locate the target package
8efa2a3b
AL
233 pkgCache::PkgIterator Pkg;
234 if (Owner->NewPackage(Pkg,PackageName) == false)
235 return false;
dcb79bae
AL
236
237 // Probe the reverse dependency list for a version string that matches
238 if (Version.empty() == false)
239 {
240 for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
241 if (I->Version != 0 && I.TargetVer() == Version)
242 Dep->Version = I->Version;
243 if (Dep->Version == 0)
244 if ((Dep->Version = WriteString(Version)) == 0)
245 return false;
246 }
247
248 // Link it to the package
249 Dep->Package = Pkg.Index();
250 Dep->NextRevDepends = Pkg->RevDepends;
251 Pkg->RevDepends = Dep.Index();
252
253 // Link it to the version (at the end of the list)
254 unsigned long *Last = &Ver->DependsList;
255 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
256 Last = &D->NextDepends;
257 Dep->NextDepends = *Last;
258 *Last = Dep.Index();
259
260 return true;
261}
262 /*}}}*/
263// ListParser::NewProvides - Create a Provides element /*{{{*/
264// ---------------------------------------------------------------------
265/* */
266bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver,
8efa2a3b 267 string PackageName,
9ddf7030 268 string Version)
dcb79bae
AL
269{
270 pkgCache &Cache = Owner->Cache;
8efa2a3b
AL
271
272 // We do not add self referencing provides
273 if (Ver.ParentPkg().Name() == PackageName)
274 return true;
dcb79bae
AL
275
276 // Get a structure
277 unsigned long Provides = Owner->Map.Allocate(sizeof(pkgCache::Provides));
278 if (Provides == 0)
279 return false;
280
281 // Fill it in
282 pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP);
283 Prv->Version = Ver.Index();
284 Prv->NextPkgProv = Ver->ProvidesList;
285 Ver->ProvidesList = Prv.Index();
286 if (Version.empty() == false && (Prv->Version = WriteString(Version)) == 0)
287 return false;
288
289 // Locate the target package
8efa2a3b
AL
290 pkgCache::PkgIterator Pkg;
291 if (Owner->NewPackage(Pkg,PackageName) == false)
292 return false;
dcb79bae
AL
293
294 // Link it to the package
295 Prv->ParentPkg = Pkg.Index();
296 Prv->NextProvides = Pkg->ProvidesList;
297 Pkg->ProvidesList = Prv.Index();
298
299 return true;
300}
301 /*}}}*/
578bfd0a
AL
302// CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
303// ---------------------------------------------------------------------
304/* This is used to select which file is to be associated with all newly
305 added versions. */
306bool pkgCacheGenerator::SelectFile(string File,unsigned long Flags)
307{
308 struct stat Buf;
309 if (stat(File.c_str(),&Buf) == -1)
310 return _error->Errno("stat","Couldn't stat ",File.c_str());
311
312 // Get some space for the structure
313 CurrentFile = Cache.PkgFileP + Map.Allocate(sizeof(*CurrentFile));
314 if (CurrentFile == Cache.PkgFileP)
315 return false;
316
317 // Fill it in
318 CurrentFile->FileName = Map.WriteString(File);
319 CurrentFile->Size = Buf.st_size;
320 CurrentFile->mtime = Buf.st_mtime;
321 CurrentFile->NextFile = Cache.HeaderP->FileList;
322 CurrentFile->Flags = Flags;
323 PkgFileName = File;
ad00ae81 324 Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP;
b35d2f5f
AL
325 Cache.HeaderP->PackageFileCount++;
326
578bfd0a
AL
327 if (CurrentFile->FileName == 0)
328 return false;
404ec98e 329
8ce4327b 330 Progress.SubProgress(Buf.st_size);
8efa2a3b 331 return true;
578bfd0a
AL
332}
333 /*}}}*/
f55a958f
AL
334// CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
335// ---------------------------------------------------------------------
336/* This is used to create handles to strings. Given the same text it
337 always returns the same number */
338unsigned long pkgCacheGenerator::WriteUniqString(const char *S,
339 unsigned int Size)
340{
341 // Search for an insertion point
342 pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList;
343 int Res = 1;
344 unsigned long *Last = &Cache.HeaderP->StringList;
345 for (; I != Cache.StringItemP; Last = &I->NextItem,
346 I = Cache.StringItemP + I->NextItem)
347 {
9c14e3d6 348 Res = stringcmp(S,S+Size,Cache.StrP + I->String);
f55a958f
AL
349 if (Res >= 0)
350 break;
351 }
352
353 // Match
354 if (Res == 0)
0149949b 355 return I->String;
f55a958f
AL
356
357 // Get a structure
358 unsigned long Item = Map.Allocate(sizeof(pkgCache::StringItem));
359 if (Item == 0)
0149949b
AL
360 return 0;
361
f55a958f
AL
362 // Fill in the structure
363 pkgCache::StringItem *ItemP = Cache.StringItemP + Item;
364 ItemP->NextItem = I - Cache.StringItemP;
365 *Last = Item;
366 ItemP->String = Map.WriteString(S,Size);
367 if (ItemP->String == 0)
0149949b 368 return 0;
f55a958f 369
0149949b 370 return ItemP->String;
f55a958f
AL
371}
372 /*}}}*/
b35d2f5f
AL
373
374// SrcCacheCheck - Check if the source package cache is uptodate /*{{{*/
375// ---------------------------------------------------------------------
376/* The source cache is checked against the source list and the files
377 on disk, any difference results in a false. */
378bool pkgSrcCacheCheck(pkgSourceList &List)
379{
380 if (_error->PendingError() == true)
381 return false;
382
383 // Open the source package cache
384 string CacheFile = _config->FindDir("Dir::Cache::srcpkgcache");
385 string ListDir = _config->FindDir("Dir::State::lists");
386 if (FileExists(CacheFile) == false)
387 return false;
388
389 FileFd CacheF(CacheFile,FileFd::ReadOnly);
390 if (_error->PendingError() == true)
391 {
392 _error->Discard();
393 return false;
394 }
395
396 MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
397 if (_error->PendingError() == true)
398 {
399 _error->Discard();
400 return false;
401 }
402
403 pkgCache Cache(Map);
404 if (_error->PendingError() == true)
405 {
406 _error->Discard();
407 return false;
408 }
409
410 // They are certianly out of sync
411 if (Cache.Head().PackageFileCount != List.size())
412 return false;
413
414 for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
415 {
416 // Search for a match in the source list
417 bool Bad = true;
418 for (pkgSourceList::const_iterator I = List.begin();
419 I != List.end(); I++)
420 {
421 string File = ListDir + URItoFileName(I->PackagesURI());
422 if (F.FileName() == File)
423 {
424 Bad = false;
425 break;
426 }
427 }
428
429 // Check if the file matches what was cached
430 Bad |= !F.IsOk();
431 if (Bad == true)
432 return false;
433 }
434
435 return true;
436}
437 /*}}}*/
438// PkgCacheCheck - Check if the package cache is uptodate /*{{{*/
439// ---------------------------------------------------------------------
440/* This does a simple check of all files used to compose the cache */
441bool pkgPkgCacheCheck(string CacheFile)
442{
443 if (_error->PendingError() == true)
444 return false;
445
446 // Open the source package cache
447 if (FileExists(CacheFile) == false)
448 return false;
449
450 FileFd CacheF(CacheFile,FileFd::ReadOnly);
451 if (_error->PendingError() == true)
452 {
453 _error->Discard();
454 return false;
455 }
456
457 MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
458 if (_error->PendingError() == true)
459 {
460 _error->Discard();
461 return false;
462 }
463
464 pkgCache Cache(Map);
465 if (_error->PendingError() == true)
466 {
467 _error->Discard();
468 return false;
469 }
470
471 // Cheack each file
472 for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
473 if (F.IsOk() == false)
474 return false;
475 return true;
476}
477 /*}}}*/
478// AddSourcesSize - Add the size of the status files /*{{{*/
479// ---------------------------------------------------------------------
480/* This adds the size of all the status files to the size counter */
481static bool pkgAddSourcesSize(unsigned long &TotalSize)
482{
483 // Grab the file names
484 string xstatus = _config->FindDir("Dir::State::xstatus");
485 string userstatus = _config->FindDir("Dir::State::userstatus");
486 string status = _config->FindDir("Dir::State::status");
487
488 // Grab the sizes
489 struct stat Buf;
490 if (stat(xstatus.c_str(),&Buf) == 0)
491 TotalSize += Buf.st_size;
492 if (stat(userstatus.c_str(),&Buf) == 0)
493 TotalSize += Buf.st_size;
494 if (stat(status.c_str(),&Buf) != 0)
495 return _error->Errno("stat","Couldn't stat the status file %s",status.c_str());
496 TotalSize += Buf.st_size;
497
498 return true;
499}
500 /*}}}*/
501// MergeStatus - Add the status files to the cache /*{{{*/
502// ---------------------------------------------------------------------
503/* This adds the status files to the map */
504static bool pkgMergeStatus(OpProgress &Progress,pkgCacheGenerator &Gen,
505 unsigned long &CurrentSize,unsigned long TotalSize)
506{
507 // Grab the file names
508 string Status[3];
509 Status[0] = _config->FindDir("Dir::State::xstatus");
510 Status[1]= _config->FindDir("Dir::State::userstatus");
511 Status[2] = _config->FindDir("Dir::State::status");
512
513 for (int I = 0; I != 3; I++)
514 {
515 // Check if the file exists and it is not the primary status file.
516 string File = Status[I];
517 if (I != 2 && FileExists(File) == false)
518 continue;
519
520 FileFd Pkg(File,FileFd::ReadOnly);
521 debListParser Parser(Pkg);
8ce4327b 522 Progress.OverallProgress(CurrentSize,TotalSize,Pkg.Size(),"Reading Package Lists");
b35d2f5f
AL
523 if (_error->PendingError() == true)
524 return _error->Error("Problem opening %s",File.c_str());
525 CurrentSize += Pkg.Size();
8ce4327b
AL
526
527 Progress.SubProgress(0,"Local Package State - " + flNotDir(File));
b35d2f5f
AL
528 if (Gen.SelectFile(File,pkgCache::Flag::NotSource) == false)
529 return _error->Error("Problem with SelectFile %s",File.c_str());
530
531 if (Gen.MergeList(Parser) == false)
532 return _error->Error("Problem with MergeList %s",File.c_str());
8ce4327b 533 Progress.Progress(Pkg.Size());
b35d2f5f
AL
534 }
535
536 return true;
537}
538 /*}}}*/
539// MakeStatusCache - Generates a cache that includes the status files /*{{{*/
540// ---------------------------------------------------------------------
541/* This copies the package source cache and then merges the status and
542 xstatus files into it. */
543bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress)
544{
8ce4327b
AL
545 Progress.OverallProgress(0,1,1,"Reading Package Lists");
546
b35d2f5f
AL
547 string CacheFile = _config->FindDir("Dir::Cache::pkgcache");
548 bool SrcOk = pkgSrcCacheCheck(List);
549 bool PkgOk = pkgPkgCacheCheck(CacheFile);
550
551 // Rebuild the source and package caches
552 if (SrcOk == false)
553 {
554 string SCacheFile = _config->FindDir("Dir::Cache::srcpkgcache");
555 string ListDir = _config->FindDir("Dir::State::lists");
556
557 FileFd SCacheF(SCacheFile,FileFd::WriteEmpty);
558 FileFd CacheF(CacheFile,FileFd::WriteEmpty);
559 DynamicMMap Map(CacheF,MMap::Public);
560 if (_error->PendingError() == true)
561 return false;
562
563 pkgCacheGenerator Gen(Map,Progress);
564
565 // Prepare the progress indicator
566 unsigned long TotalSize = 0;
567 struct stat Buf;
568 for (pkgSourceList::const_iterator I = List.begin(); I != List.end(); I++)
569 {
570 string File = ListDir + URItoFileName(I->PackagesURI());
571 if (stat(File.c_str(),&Buf) != 0)
572 return _error->Errno("stat","Couldn't stat source package list %s",File.c_str());
573 TotalSize += Buf.st_size;
574 }
575
576 if (pkgAddSourcesSize(TotalSize) == false)
577 return false;
578
579 // Generate the pkg source cache
580 unsigned long CurrentSize = 0;
581 for (pkgSourceList::const_iterator I = List.begin(); I != List.end(); I++)
582 {
583 string File = ListDir + URItoFileName(I->PackagesURI());
584 FileFd Pkg(File,FileFd::ReadOnly);
585 debListParser Parser(Pkg);
8ce4327b 586 Progress.OverallProgress(CurrentSize,TotalSize,Pkg.Size(),"Reading Package Lists");
b35d2f5f
AL
587 if (_error->PendingError() == true)
588 return _error->Error("Problem opening %s",File.c_str());
589 CurrentSize += Pkg.Size();
590
8ce4327b 591 Progress.SubProgress(0,I->PackagesInfo());
b35d2f5f
AL
592 if (Gen.SelectFile(File) == false)
593 return _error->Error("Problem with SelectFile %s",File.c_str());
594
595 if (Gen.MergeList(Parser) == false)
596 return _error->Error("Problem with MergeList %s",File.c_str());
597 }
598
599 // Write the src cache
600 Gen.GetCache().HeaderP->Dirty = false;
601 if (SCacheF.Write(Map.Data(),Map.Size()) == false)
602 return _error->Error("IO Error saving source cache");
603 Gen.GetCache().HeaderP->Dirty = true;
604
605 // Merge in the source caches
606 return pkgMergeStatus(Progress,Gen,CurrentSize,TotalSize);
607 }
608
609 if (PkgOk == true)
8ce4327b
AL
610 {
611 Progress.OverallProgress(1,1,1,"Reading Package Lists");
b35d2f5f 612 return true;
8ce4327b 613 }
b35d2f5f
AL
614
615 // We use the source cache to generate the package cache
616 string SCacheFile = _config->FindDir("Dir::Cache::srcpkgcache");
617
618 FileFd SCacheF(SCacheFile,FileFd::ReadOnly);
619 FileFd CacheF(CacheFile,FileFd::WriteEmpty);
620 DynamicMMap Map(CacheF,MMap::Public);
621 if (_error->PendingError() == true)
622 return false;
623
624 // Preload the map with the source cache
625 if (SCacheF.Read((unsigned char *)Map.Data() + Map.RawAllocate(SCacheF.Size()),
626 SCacheF.Size()) == false)
627 return false;
628
629 pkgCacheGenerator Gen(Map,Progress);
630
631 // Compute the progress
632 unsigned long TotalSize = 0;
633 if (pkgAddSourcesSize(TotalSize) == false)
634 return false;
635
636 unsigned long CurrentSize = 0;
637 return pkgMergeStatus(Progress,Gen,CurrentSize,TotalSize);
638}
639 /*}}}*/