]>
git.saurik.com Git - apt.git/blob - apt-pkg/pkgcachegen.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: pkgcachegen.cc,v 1.53.2.1 2003/12/24 23:09:17 mdz Exp $
4 /* ######################################################################
6 Package Cache Generator - Generator for the cache structure.
8 This builds the cache structure from the abstract package list parser.
10 ##################################################################### */
12 // Include Files /*{{{*/
13 #define APT_COMPATIBILITY 986
15 #include <apt-pkg/pkgcachegen.h>
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/version.h>
18 #include <apt-pkg/progress.h>
19 #include <apt-pkg/sourcelist.h>
20 #include <apt-pkg/configuration.h>
21 #include <apt-pkg/aptconfiguration.h>
22 #include <apt-pkg/strutl.h>
23 #include <apt-pkg/sptr.h>
24 #include <apt-pkg/pkgsystem.h>
25 #include <apt-pkg/macros.h>
27 #include <apt-pkg/tagfile.h>
38 typedef vector
<pkgIndexFile
*>::iterator FileIterator
;
39 template <typename Iter
> std::vector
<Iter
*> pkgCacheGenerator::Dynamic
<Iter
>::toReMap
;
41 // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
42 // ---------------------------------------------------------------------
43 /* We set the dirty flag and make sure that is written to the disk */
44 pkgCacheGenerator::pkgCacheGenerator(DynamicMMap
*pMap
,OpProgress
*Prog
) :
45 Map(*pMap
), Cache(pMap
,false), Progress(Prog
),
49 memset(UniqHash
,0,sizeof(UniqHash
));
51 if (_error
->PendingError() == true)
56 // Setup the map interface..
57 Cache
.HeaderP
= (pkgCache::Header
*)Map
.Data();
58 if (Map
.RawAllocate(sizeof(pkgCache::Header
)) == 0 && _error
->PendingError() == true)
61 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
64 *Cache
.HeaderP
= pkgCache::Header();
65 map_ptrloc
const idxVerSysName
= WriteStringInMap(_system
->VS
->Label
);
66 Cache
.HeaderP
->VerSysName
= idxVerSysName
;
67 map_ptrloc
const idxArchitecture
= WriteStringInMap(_config
->Find("APT::Architecture"));
68 Cache
.HeaderP
->Architecture
= idxArchitecture
;
69 if (unlikely(idxVerSysName
== 0 || idxArchitecture
== 0))
75 // Map directly from the existing file
77 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
78 if (Cache
.VS
!= _system
->VS
)
80 _error
->Error(_("Cache has an incompatible versioning system"));
85 Cache
.HeaderP
->Dirty
= true;
86 Map
.Sync(0,sizeof(pkgCache::Header
));
89 // CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/
90 // ---------------------------------------------------------------------
91 /* We sync the data then unset the dirty flag in two steps so as to
92 advoid a problem during a crash */
93 pkgCacheGenerator::~pkgCacheGenerator()
95 if (_error
->PendingError() == true)
97 if (Map
.Sync() == false)
100 Cache
.HeaderP
->Dirty
= false;
101 Map
.Sync(0,sizeof(pkgCache::Header
));
104 void pkgCacheGenerator::ReMap(void const * const oldMap
, void const * const newMap
) {/*{{{*/
105 if (oldMap
== newMap
)
110 CurrentFile
+= (pkgCache::PackageFile
*) newMap
- (pkgCache::PackageFile
*) oldMap
;
112 for (size_t i
= 0; i
< _count(UniqHash
); ++i
)
113 if (UniqHash
[i
] != 0)
114 UniqHash
[i
] += (pkgCache::StringItem
*) newMap
- (pkgCache::StringItem
*) oldMap
;
116 for (std::vector
<pkgCache::GrpIterator
*>::const_iterator i
= Dynamic
<pkgCache::GrpIterator
>::toReMap
.begin();
117 i
!= Dynamic
<pkgCache::GrpIterator
>::toReMap
.end(); ++i
)
118 (*i
)->ReMap(oldMap
, newMap
);
119 for (std::vector
<pkgCache::PkgIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgIterator
>::toReMap
.begin();
120 i
!= Dynamic
<pkgCache::PkgIterator
>::toReMap
.end(); ++i
)
121 (*i
)->ReMap(oldMap
, newMap
);
122 for (std::vector
<pkgCache::VerIterator
*>::const_iterator i
= Dynamic
<pkgCache::VerIterator
>::toReMap
.begin();
123 i
!= Dynamic
<pkgCache::VerIterator
>::toReMap
.end(); ++i
)
124 (*i
)->ReMap(oldMap
, newMap
);
125 for (std::vector
<pkgCache::DepIterator
*>::const_iterator i
= Dynamic
<pkgCache::DepIterator
>::toReMap
.begin();
126 i
!= Dynamic
<pkgCache::DepIterator
>::toReMap
.end(); ++i
)
127 (*i
)->ReMap(oldMap
, newMap
);
128 for (std::vector
<pkgCache::DescIterator
*>::const_iterator i
= Dynamic
<pkgCache::DescIterator
>::toReMap
.begin();
129 i
!= Dynamic
<pkgCache::DescIterator
>::toReMap
.end(); ++i
)
130 (*i
)->ReMap(oldMap
, newMap
);
131 for (std::vector
<pkgCache::PrvIterator
*>::const_iterator i
= Dynamic
<pkgCache::PrvIterator
>::toReMap
.begin();
132 i
!= Dynamic
<pkgCache::PrvIterator
>::toReMap
.end(); ++i
)
133 (*i
)->ReMap(oldMap
, newMap
);
134 for (std::vector
<pkgCache::PkgFileIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.begin();
135 i
!= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.end(); ++i
)
136 (*i
)->ReMap(oldMap
, newMap
);
138 // CacheGenerator::WriteStringInMap /*{{{*/
139 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
,
140 const unsigned long &Len
) {
141 void const * const oldMap
= Map
.Data();
142 map_ptrloc
const index
= Map
.WriteString(String
, Len
);
144 ReMap(oldMap
, Map
.Data());
148 // CacheGenerator::WriteStringInMap /*{{{*/
149 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
) {
150 void const * const oldMap
= Map
.Data();
151 map_ptrloc
const index
= Map
.WriteString(String
);
153 ReMap(oldMap
, Map
.Data());
157 map_ptrloc
pkgCacheGenerator::AllocateInMap(const unsigned long &size
) {/*{{{*/
158 void const * const oldMap
= Map
.Data();
159 map_ptrloc
const index
= Map
.Allocate(size
);
161 ReMap(oldMap
, Map
.Data());
165 // CacheGenerator::MergeList - Merge the package list /*{{{*/
166 // ---------------------------------------------------------------------
167 /* This provides the generation of the entries in the cache. Each loop
168 goes through a single package record from the underlying parse engine. */
169 bool pkgCacheGenerator::MergeList(ListParser
&List
,
170 pkgCache::VerIterator
*OutVer
)
174 unsigned int Counter
= 0;
175 while (List
.Step() == true)
177 string
const PackageName
= List
.Package();
178 if (PackageName
.empty() == true)
181 /* Treat Arch all packages as the same as the native arch. */
183 if (List
.ArchitectureAll() == true)
184 Arch
= _config
->Find("APT::Architecture");
186 Arch
= List
.Architecture();
188 // Get a pointer to the package structure
189 pkgCache::PkgIterator Pkg
;
190 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
191 if (NewPackage(Pkg
, PackageName
, Arch
) == false)
192 return _error
->Error(_("Error occurred while processing %s (NewPackage)"),PackageName
.c_str());
194 if (Counter
% 100 == 0 && Progress
!= 0)
195 Progress
->Progress(List
.Offset());
197 /* Get a pointer to the version structure. We know the list is sorted
198 so we use that fact in the search. Insertion of new versions is
199 done with correct sorting */
200 string Version
= List
.Version();
201 if (Version
.empty() == true)
203 // we first process the package, then the descriptions
204 // (this has the bonus that we get MMap error when we run out
206 pkgCache::VerIterator
Ver(Cache
);
207 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
208 if (List
.UsePackage(Pkg
, Ver
) == false)
209 return _error
->Error(_("Error occurred while processing %s (UsePackage1)"),
210 PackageName
.c_str());
212 // Find the right version to write the description
213 MD5SumValue CurMd5
= List
.Description_md5();
214 Ver
= Pkg
.VersionList();
216 for (; Ver
.end() == false; ++Ver
)
218 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
219 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
220 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
221 bool duplicate
=false;
223 // don't add a new description if we have one for the given
225 for ( ; Desc
.end() == false; Desc
++)
226 if (MD5SumValue(Desc
.md5()) == CurMd5
&&
227 Desc
.LanguageCode() == List
.DescriptionLanguage())
232 for (Desc
= Ver
.DescriptionList();
234 LastDesc
= &Desc
->NextDesc
, Desc
++)
236 if (MD5SumValue(Desc
.md5()) == CurMd5
)
238 // Add new description
239 void const * const oldMap
= Map
.Data();
240 map_ptrloc
const descindex
= NewDescription(Desc
, List
.DescriptionLanguage(), CurMd5
, *LastDesc
);
241 if (oldMap
!= Map
.Data())
242 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
243 *LastDesc
= descindex
;
244 Desc
->ParentPkg
= Pkg
.Index();
246 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
247 return _error
->Error(_("Error occurred while processing %s (NewFileDesc1)"),PackageName
.c_str());
256 pkgCache::VerIterator Ver
= Pkg
.VersionList();
257 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
258 map_ptrloc
*LastVer
= &Pkg
->VersionList
;
259 void const * oldMap
= Map
.Data();
261 unsigned long const Hash
= List
.VersionHash();
262 for (; Ver
.end() == false; LastVer
= &Ver
->NextVer
, Ver
++)
264 Res
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr());
265 // Version is higher as current version - insert here
268 // Versionstrings are equal - is hash also equal?
269 if (Res
== 0 && Ver
->Hash
== Hash
)
271 // proceed with the next till we have either the right
272 // or we found another version (which will be lower)
275 /* We already have a version for this item, record that we saw it */
276 if (Res
== 0 && Ver
.end() == false && Ver
->Hash
== Hash
)
278 if (List
.UsePackage(Pkg
,Ver
) == false)
279 return _error
->Error(_("Error occurred while processing %s (UsePackage2)"),
280 PackageName
.c_str());
282 if (NewFileVer(Ver
,List
) == false)
283 return _error
->Error(_("Error occurred while processing %s (NewFileVer1)"),
284 PackageName
.c_str());
286 // Read only a single record and return
290 FoundFileDeps
|= List
.HasFileDeps();
298 map_ptrloc
const verindex
= NewVersion(Ver
,Version
,*LastVer
);
299 if (verindex
== 0 && _error
->PendingError())
300 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
301 PackageName
.c_str(), 1);
303 if (oldMap
!= Map
.Data())
304 LastVer
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
306 Ver
->ParentPkg
= Pkg
.Index();
309 if (List
.NewVersion(Ver
) == false)
310 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
311 PackageName
.c_str(), 2);
313 if (List
.UsePackage(Pkg
,Ver
) == false)
314 return _error
->Error(_("Error occurred while processing %s (UsePackage3)"),
315 PackageName
.c_str());
317 if (NewFileVer(Ver
,List
) == false)
318 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
319 PackageName
.c_str(), 3);
321 // Read only a single record and return
325 FoundFileDeps
|= List
.HasFileDeps();
329 /* Record the Description data. Description data always exist in
330 Packages and Translation-* files. */
331 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
332 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
333 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
335 // Skip to the end of description set
336 for (; Desc
.end() == false; LastDesc
= &Desc
->NextDesc
, Desc
++);
338 // Add new description
340 map_ptrloc
const descindex
= NewDescription(Desc
, List
.DescriptionLanguage(), List
.Description_md5(), *LastDesc
);
341 if (oldMap
!= Map
.Data())
342 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
343 *LastDesc
= descindex
;
344 Desc
->ParentPkg
= Pkg
.Index();
346 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
347 return _error
->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName
.c_str());
350 FoundFileDeps
|= List
.HasFileDeps();
352 if (Cache
.HeaderP
->PackageCount
>= (1ULL<<sizeof(Cache
.PkgP
->ID
)*8)-1)
353 return _error
->Error(_("Wow, you exceeded the number of package "
354 "names this APT is capable of."));
355 if (Cache
.HeaderP
->VersionCount
>= (1ULL<<(sizeof(Cache
.VerP
->ID
)*8))-1)
356 return _error
->Error(_("Wow, you exceeded the number of versions "
357 "this APT is capable of."));
358 if (Cache
.HeaderP
->DescriptionCount
>= (1ULL<<(sizeof(Cache
.DescP
->ID
)*8))-1)
359 return _error
->Error(_("Wow, you exceeded the number of descriptions "
360 "this APT is capable of."));
361 if (Cache
.HeaderP
->DependsCount
>= (1ULL<<(sizeof(Cache
.DepP
->ID
)*8))-1ULL)
362 return _error
->Error(_("Wow, you exceeded the number of dependencies "
363 "this APT is capable of."));
367 // CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/
368 // ---------------------------------------------------------------------
369 /* If we found any file depends while parsing the main list we need to
370 resolve them. Since it is undesired to load the entire list of files
371 into the cache as virtual packages we do a two stage effort. MergeList
372 identifies the file depends and this creates Provdies for them by
373 re-parsing all the indexs. */
374 bool pkgCacheGenerator::MergeFileProvides(ListParser
&List
)
378 unsigned int Counter
= 0;
379 while (List
.Step() == true)
381 string PackageName
= List
.Package();
382 if (PackageName
.empty() == true)
384 string Version
= List
.Version();
385 if (Version
.empty() == true)
388 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(PackageName
);
389 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
390 if (Pkg
.end() == true)
391 return _error
->Error(_("Error occurred while processing %s (FindPkg)"),
392 PackageName
.c_str());
394 if (Counter
% 100 == 0 && Progress
!= 0)
395 Progress
->Progress(List
.Offset());
397 unsigned long Hash
= List
.VersionHash();
398 pkgCache::VerIterator Ver
= Pkg
.VersionList();
399 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
400 for (; Ver
.end() == false; Ver
++)
402 if (Ver
->Hash
== Hash
&& Version
.c_str() == Ver
.VerStr())
404 if (List
.CollectFileProvides(Cache
,Ver
) == false)
405 return _error
->Error(_("Error occurred while processing %s (CollectFileProvides)"),PackageName
.c_str());
410 if (Ver
.end() == true)
411 _error
->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName
.c_str(),Version
.c_str());
417 // CacheGenerator::NewGroup - Add a new group /*{{{*/
418 // ---------------------------------------------------------------------
419 /* This creates a new group structure and adds it to the hash table */
420 bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator
&Grp
, const string
&Name
)
422 Grp
= Cache
.FindGrp(Name
);
423 if (Grp
.end() == false)
427 map_ptrloc
const Group
= AllocateInMap(sizeof(pkgCache::Group
));
428 if (unlikely(Group
== 0))
431 Grp
= pkgCache::GrpIterator(Cache
, Cache
.GrpP
+ Group
);
432 map_ptrloc
const idxName
= WriteStringInMap(Name
);
433 if (unlikely(idxName
== 0))
437 // Insert it into the hash table
438 unsigned long const Hash
= Cache
.Hash(Name
);
439 Grp
->Next
= Cache
.HeaderP
->GrpHashTable
[Hash
];
440 Cache
.HeaderP
->GrpHashTable
[Hash
] = Group
;
442 Grp
->ID
= Cache
.HeaderP
->GroupCount
++;
446 // CacheGenerator::NewPackage - Add a new package /*{{{*/
447 // ---------------------------------------------------------------------
448 /* This creates a new package structure and adds it to the hash table */
449 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator
&Pkg
,const string
&Name
,
450 const string
&Arch
) {
451 pkgCache::GrpIterator Grp
;
452 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
453 if (unlikely(NewGroup(Grp
, Name
) == false))
456 Pkg
= Grp
.FindPkg(Arch
);
457 if (Pkg
.end() == false)
461 map_ptrloc
const Package
= AllocateInMap(sizeof(pkgCache::Package
));
462 if (unlikely(Package
== 0))
464 Pkg
= pkgCache::PkgIterator(Cache
,Cache
.PkgP
+ Package
);
466 // Insert the package into our package list
467 if (Grp
->FirstPackage
== 0) // the group is new
469 // Insert it into the hash table
470 unsigned long const Hash
= Cache
.Hash(Name
);
471 Pkg
->NextPackage
= Cache
.HeaderP
->PkgHashTable
[Hash
];
472 Cache
.HeaderP
->PkgHashTable
[Hash
] = Package
;
473 Grp
->FirstPackage
= Package
;
475 else // Group the Packages together
477 // this package is the new last package
478 pkgCache::PkgIterator
LastPkg(Cache
, Cache
.PkgP
+ Grp
->LastPackage
);
479 Pkg
->NextPackage
= LastPkg
->NextPackage
;
480 LastPkg
->NextPackage
= Package
;
482 Grp
->LastPackage
= Package
;
484 // Set the name, arch and the ID
485 Pkg
->Name
= Grp
->Name
;
486 Pkg
->Group
= Grp
.Index();
487 map_ptrloc
const idxArch
= WriteUniqString(Arch
.c_str());
488 if (unlikely(idxArch
== 0))
491 Pkg
->ID
= Cache
.HeaderP
->PackageCount
++;
496 // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
497 // ---------------------------------------------------------------------
499 bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator
&Ver
,
502 if (CurrentFile
== 0)
506 map_ptrloc
const VerFile
= AllocateInMap(sizeof(pkgCache::VerFile
));
510 pkgCache::VerFileIterator
VF(Cache
,Cache
.VerFileP
+ VerFile
);
511 VF
->File
= CurrentFile
- Cache
.PkgFileP
;
513 // Link it to the end of the list
514 map_ptrloc
*Last
= &Ver
->FileList
;
515 for (pkgCache::VerFileIterator V
= Ver
.FileList(); V
.end() == false; V
++)
517 VF
->NextFile
= *Last
;
520 VF
->Offset
= List
.Offset();
521 VF
->Size
= List
.Size();
522 if (Cache
.HeaderP
->MaxVerFileSize
< VF
->Size
)
523 Cache
.HeaderP
->MaxVerFileSize
= VF
->Size
;
524 Cache
.HeaderP
->VerFileCount
++;
529 // CacheGenerator::NewVersion - Create a new Version /*{{{*/
530 // ---------------------------------------------------------------------
531 /* This puts a version structure in the linked list */
532 unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator
&Ver
,
533 const string
&VerStr
,
537 map_ptrloc
const Version
= AllocateInMap(sizeof(pkgCache::Version
));
542 Ver
= pkgCache::VerIterator(Cache
,Cache
.VerP
+ Version
);
544 Ver
->ID
= Cache
.HeaderP
->VersionCount
++;
545 map_ptrloc
const idxVerStr
= WriteStringInMap(VerStr
);
546 if (unlikely(idxVerStr
== 0))
548 Ver
->VerStr
= idxVerStr
;
553 // CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/
554 // ---------------------------------------------------------------------
556 bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator
&Desc
,
559 if (CurrentFile
== 0)
563 map_ptrloc
const DescFile
= AllocateInMap(sizeof(pkgCache::DescFile
));
567 pkgCache::DescFileIterator
DF(Cache
,Cache
.DescFileP
+ DescFile
);
568 DF
->File
= CurrentFile
- Cache
.PkgFileP
;
570 // Link it to the end of the list
571 map_ptrloc
*Last
= &Desc
->FileList
;
572 for (pkgCache::DescFileIterator D
= Desc
.FileList(); D
.end() == false; D
++)
575 DF
->NextFile
= *Last
;
578 DF
->Offset
= List
.Offset();
579 DF
->Size
= List
.Size();
580 if (Cache
.HeaderP
->MaxDescFileSize
< DF
->Size
)
581 Cache
.HeaderP
->MaxDescFileSize
= DF
->Size
;
582 Cache
.HeaderP
->DescFileCount
++;
587 // CacheGenerator::NewDescription - Create a new Description /*{{{*/
588 // ---------------------------------------------------------------------
589 /* This puts a description structure in the linked list */
590 map_ptrloc
pkgCacheGenerator::NewDescription(pkgCache::DescIterator
&Desc
,
592 const MD5SumValue
&md5sum
,
596 map_ptrloc
const Description
= AllocateInMap(sizeof(pkgCache::Description
));
597 if (Description
== 0)
601 Desc
= pkgCache::DescIterator(Cache
,Cache
.DescP
+ Description
);
602 Desc
->NextDesc
= Next
;
603 Desc
->ID
= Cache
.HeaderP
->DescriptionCount
++;
604 map_ptrloc
const idxlanguage_code
= WriteStringInMap(Lang
);
605 map_ptrloc
const idxmd5sum
= WriteStringInMap(md5sum
.Value());
606 if (unlikely(idxlanguage_code
== 0 || idxmd5sum
== 0))
608 Desc
->language_code
= idxlanguage_code
;
609 Desc
->md5sum
= idxmd5sum
;
614 // CacheGenerator::FinishCache - do various finish operations /*{{{*/
615 // ---------------------------------------------------------------------
616 /* This prepares the Cache for delivery */
617 bool pkgCacheGenerator::FinishCache(OpProgress
*Progress
)
619 // FIXME: add progress reporting for this operation
620 // Do we have different architectures in your groups ?
621 vector
<string
> archs
= APT::Configuration::getArchitectures();
622 if (archs
.size() > 1)
624 // Create Conflicts in between the group
625 pkgCache::GrpIterator G
= GetCache().GrpBegin();
626 Dynamic
<pkgCache::GrpIterator
> DynG(G
);
627 for (; G
.end() != true; G
++)
629 string
const PkgName
= G
.Name();
630 pkgCache::PkgIterator P
= G
.PackageList();
631 Dynamic
<pkgCache::PkgIterator
> DynP(P
);
632 for (; P
.end() != true; P
= G
.NextPkg(P
))
634 pkgCache::PkgIterator allPkg
;
635 Dynamic
<pkgCache::PkgIterator
> DynallPkg(allPkg
);
636 pkgCache::VerIterator V
= P
.VersionList();
637 Dynamic
<pkgCache::VerIterator
> DynV(V
);
638 for (; V
.end() != true; V
++)
640 char const * const Arch
= P
.Arch();
641 map_ptrloc
*OldDepLast
= NULL
;
642 /* MultiArch handling introduces a lot of implicit Dependencies:
643 - MultiArch: same → Co-Installable if they have the same version
644 - Architecture: all → Need to be Co-Installable for internal reasons
645 - All others conflict with all other group members */
646 bool const coInstall
= (V
->MultiArch
== pkgCache::Version::Same
);
647 for (vector
<string
>::const_iterator A
= archs
.begin(); A
!= archs
.end(); ++A
)
651 /* We allow only one installed arch at the time
652 per group, therefore each group member conflicts
653 with all other group members */
654 pkgCache::PkgIterator D
= G
.FindPkg(*A
);
655 Dynamic
<pkgCache::PkgIterator
> DynD(D
);
658 if (coInstall
== true)
660 // Replaces: ${self}:other ( << ${binary:Version})
661 NewDepends(D
, V
, V
.VerStr(),
662 pkgCache::Dep::Less
, pkgCache::Dep::Replaces
,
664 // Breaks: ${self}:other (!= ${binary:Version})
665 NewDepends(D
, V
, V
.VerStr(),
666 pkgCache::Dep::NotEquals
, pkgCache::Dep::DpkgBreaks
,
669 // Conflicts: ${self}:other
671 pkgCache::Dep::NoOp
, pkgCache::Dep::Conflicts
,
682 // CacheGenerator::NewDepends - Create a dependency element /*{{{*/
683 // ---------------------------------------------------------------------
684 /* This creates a dependency element in the tree. It is linked to the
685 version and to the package that it is pointing to. */
686 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator
&Pkg
,
687 pkgCache::VerIterator
&Ver
,
688 string
const &Version
,
689 unsigned int const &Op
,
690 unsigned int const &Type
,
691 map_ptrloc
*OldDepLast
)
693 void const * const oldMap
= Map
.Data();
695 map_ptrloc
const Dependency
= AllocateInMap(sizeof(pkgCache::Dependency
));
696 if (unlikely(Dependency
== 0))
700 pkgCache::DepIterator
Dep(Cache
,Cache
.DepP
+ Dependency
);
701 Dynamic
<pkgCache::DepIterator
> DynDep(Dep
);
702 Dep
->ParentVer
= Ver
.Index();
705 Dep
->ID
= Cache
.HeaderP
->DependsCount
++;
707 // Probe the reverse dependency list for a version string that matches
708 if (Version
.empty() == false)
710 /* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
711 if (I->Version != 0 && I.TargetVer() == Version)
712 Dep->Version = I->Version;*/
713 if (Dep
->Version
== 0) {
714 map_ptrloc
const index
= WriteStringInMap(Version
);
715 if (unlikely(index
== 0))
717 Dep
->Version
= index
;
721 // Link it to the package
722 Dep
->Package
= Pkg
.Index();
723 Dep
->NextRevDepends
= Pkg
->RevDepends
;
724 Pkg
->RevDepends
= Dep
.Index();
726 // Do we know where to link the Dependency to?
727 if (OldDepLast
== NULL
)
729 OldDepLast
= &Ver
->DependsList
;
730 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
731 OldDepLast
= &D
->NextDepends
;
732 } else if (oldMap
!= Map
.Data())
733 OldDepLast
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
735 Dep
->NextDepends
= *OldDepLast
;
736 *OldDepLast
= Dep
.Index();
737 OldDepLast
= &Dep
->NextDepends
;
742 // ListParser::NewDepends - Create the environment for a new dependency /*{{{*/
743 // ---------------------------------------------------------------------
744 /* This creates a Group and the Package to link this dependency to if
745 needed and handles also the caching of the old endpoint */
746 bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator
&Ver
,
747 const string
&PackageName
,
749 const string
&Version
,
753 pkgCache::GrpIterator Grp
;
754 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
755 if (unlikely(Owner
->NewGroup(Grp
, PackageName
) == false))
758 // Locate the target package
759 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(Arch
);
760 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
761 if (Pkg
.end() == true) {
762 if (unlikely(Owner
->NewPackage(Pkg
, PackageName
, Arch
) == false))
766 // Is it a file dependency?
767 if (unlikely(PackageName
[0] == '/'))
768 FoundFileDeps
= true;
770 /* Caching the old end point speeds up generation substantially */
771 if (OldDepVer
!= Ver
) {
776 return Owner
->NewDepends(Pkg
, Ver
, Version
, Op
, Type
, OldDepLast
);
779 // ListParser::NewProvides - Create a Provides element /*{{{*/
780 // ---------------------------------------------------------------------
782 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator
&Ver
,
783 const string
&PkgName
,
784 const string
&PkgArch
,
785 const string
&Version
)
787 pkgCache
&Cache
= Owner
->Cache
;
789 // We do not add self referencing provides
790 if (Ver
.ParentPkg().Name() == PkgName
&& PkgArch
== Ver
.Arch())
794 map_ptrloc
const Provides
= Owner
->AllocateInMap(sizeof(pkgCache::Provides
));
795 if (unlikely(Provides
== 0))
797 Cache
.HeaderP
->ProvidesCount
++;
800 pkgCache::PrvIterator
Prv(Cache
,Cache
.ProvideP
+ Provides
,Cache
.PkgP
);
801 Dynamic
<pkgCache::PrvIterator
> DynPrv(Prv
);
802 Prv
->Version
= Ver
.Index();
803 Prv
->NextPkgProv
= Ver
->ProvidesList
;
804 Ver
->ProvidesList
= Prv
.Index();
805 if (Version
.empty() == false && unlikely((Prv
->ProvideVersion
= WriteString(Version
)) == 0))
808 // Locate the target package
809 pkgCache::PkgIterator Pkg
;
810 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
811 if (unlikely(Owner
->NewPackage(Pkg
,PkgName
, PkgArch
) == false))
814 // Link it to the package
815 Prv
->ParentPkg
= Pkg
.Index();
816 Prv
->NextProvides
= Pkg
->ProvidesList
;
817 Pkg
->ProvidesList
= Prv
.Index();
822 // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
823 // ---------------------------------------------------------------------
824 /* This is used to select which file is to be associated with all newly
825 added versions. The caller is responsible for setting the IMS fields. */
826 bool pkgCacheGenerator::SelectFile(const string
&File
,const string
&Site
,
827 const pkgIndexFile
&Index
,
830 // Get some space for the structure
831 map_ptrloc
const idxFile
= AllocateInMap(sizeof(*CurrentFile
));
832 if (unlikely(idxFile
== 0))
834 CurrentFile
= Cache
.PkgFileP
+ idxFile
;
837 map_ptrloc
const idxFileName
= WriteStringInMap(File
);
838 map_ptrloc
const idxSite
= WriteUniqString(Site
);
839 if (unlikely(idxFileName
== 0 || idxSite
== 0))
841 CurrentFile
->FileName
= idxFileName
;
842 CurrentFile
->Site
= idxSite
;
843 CurrentFile
->NextFile
= Cache
.HeaderP
->FileList
;
844 CurrentFile
->Flags
= Flags
;
845 CurrentFile
->ID
= Cache
.HeaderP
->PackageFileCount
;
846 map_ptrloc
const idxIndexType
= WriteUniqString(Index
.GetType()->Label
);
847 if (unlikely(idxIndexType
== 0))
849 CurrentFile
->IndexType
= idxIndexType
;
851 Cache
.HeaderP
->FileList
= CurrentFile
- Cache
.PkgFileP
;
852 Cache
.HeaderP
->PackageFileCount
++;
855 Progress
->SubProgress(Index
.Size());
859 // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
860 // ---------------------------------------------------------------------
861 /* This is used to create handles to strings. Given the same text it
862 always returns the same number */
863 unsigned long pkgCacheGenerator::WriteUniqString(const char *S
,
866 /* We use a very small transient hash table here, this speeds up generation
867 by a fair amount on slower machines */
868 pkgCache::StringItem
*&Bucket
= UniqHash
[(S
[0]*5 + S
[1]) % _count(UniqHash
)];
870 stringcmp(S
,S
+Size
,Cache
.StrP
+ Bucket
->String
) == 0)
871 return Bucket
->String
;
873 // Search for an insertion point
874 pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.HeaderP
->StringList
;
876 map_ptrloc
*Last
= &Cache
.HeaderP
->StringList
;
877 for (; I
!= Cache
.StringItemP
; Last
= &I
->NextItem
,
878 I
= Cache
.StringItemP
+ I
->NextItem
)
880 Res
= stringcmp(S
,S
+Size
,Cache
.StrP
+ I
->String
);
893 void const * const oldMap
= Map
.Data();
894 map_ptrloc
const Item
= AllocateInMap(sizeof(pkgCache::StringItem
));
898 map_ptrloc
const idxString
= WriteStringInMap(S
,Size
);
899 if (unlikely(idxString
== 0))
901 if (oldMap
!= Map
.Data()) {
902 Last
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
903 I
+= (pkgCache::StringItem
*) Map
.Data() - (pkgCache::StringItem
*) oldMap
;
907 // Fill in the structure
908 pkgCache::StringItem
*ItemP
= Cache
.StringItemP
+ Item
;
909 ItemP
->NextItem
= I
- Cache
.StringItemP
;
910 ItemP
->String
= idxString
;
913 return ItemP
->String
;
916 // CheckValidity - Check that a cache is up-to-date /*{{{*/
917 // ---------------------------------------------------------------------
918 /* This just verifies that each file in the list of index files exists,
919 has matching attributes with the cache and the cache does not have
921 static bool CheckValidity(const string
&CacheFile
, FileIterator Start
,
922 FileIterator End
,MMap
**OutMap
= 0)
924 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
925 // No file, certainly invalid
926 if (CacheFile
.empty() == true || FileExists(CacheFile
) == false)
929 std::clog
<< "CacheFile doesn't exist" << std::endl
;
934 FileFd
CacheF(CacheFile
,FileFd::ReadOnly
);
935 SPtr
<MMap
> Map
= new MMap(CacheF
,0);
937 if (_error
->PendingError() == true || Map
->Size() == 0)
940 std::clog
<< "Errors are pending or Map is empty()" << std::endl
;
945 /* Now we check every index file, see if it is in the cache,
946 verify the IMS data and check that it is on the disk too.. */
947 SPtrArray
<bool> Visited
= new bool[Cache
.HeaderP
->PackageFileCount
];
948 memset(Visited
,0,sizeof(*Visited
)*Cache
.HeaderP
->PackageFileCount
);
949 for (; Start
!= End
; Start
++)
952 std::clog
<< "Checking PkgFile " << (*Start
)->Describe() << ": ";
953 if ((*Start
)->HasPackages() == false)
956 std::clog
<< "Has NO packages" << std::endl
;
960 if ((*Start
)->Exists() == false)
962 #if 0 // mvo: we no longer give a message here (Default Sources spec)
963 _error
->WarningE("stat",_("Couldn't stat source package list %s"),
964 (*Start
)->Describe().c_str());
967 std::clog
<< "file doesn't exist" << std::endl
;
971 // FindInCache is also expected to do an IMS check.
972 pkgCache::PkgFileIterator File
= (*Start
)->FindInCache(Cache
);
973 if (File
.end() == true)
976 std::clog
<< "FindInCache returned end-Pointer" << std::endl
;
980 Visited
[File
->ID
] = true;
982 std::clog
<< "with ID " << File
->ID
<< " is valid" << std::endl
;
985 for (unsigned I
= 0; I
!= Cache
.HeaderP
->PackageFileCount
; I
++)
986 if (Visited
[I
] == false)
989 std::clog
<< "File with ID" << I
<< " wasn't visited" << std::endl
;
993 if (_error
->PendingError() == true)
997 std::clog
<< "Validity failed because of pending errors:" << std::endl
;
998 _error
->DumpErrors();
1005 *OutMap
= Map
.UnGuard();
1009 // ComputeSize - Compute the total size of a bunch of files /*{{{*/
1010 // ---------------------------------------------------------------------
1011 /* Size is kind of an abstract notion that is only used for the progress
1013 static unsigned long ComputeSize(FileIterator Start
,FileIterator End
)
1015 unsigned long TotalSize
= 0;
1016 for (; Start
!= End
; Start
++)
1018 if ((*Start
)->HasPackages() == false)
1020 TotalSize
+= (*Start
)->Size();
1025 // BuildCache - Merge the list of index files into the cache /*{{{*/
1026 // ---------------------------------------------------------------------
1028 static bool BuildCache(pkgCacheGenerator
&Gen
,
1029 OpProgress
*Progress
,
1030 unsigned long &CurrentSize
,unsigned long TotalSize
,
1031 FileIterator Start
, FileIterator End
)
1034 for (I
= Start
; I
!= End
; I
++)
1036 if ((*I
)->HasPackages() == false)
1039 if ((*I
)->Exists() == false)
1042 if ((*I
)->FindInCache(Gen
.GetCache()).end() == false)
1044 _error
->Warning("Duplicate sources.list entry %s",
1045 (*I
)->Describe().c_str());
1049 unsigned long Size
= (*I
)->Size();
1050 if (Progress
!= NULL
)
1051 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Reading package lists"));
1052 CurrentSize
+= Size
;
1054 if ((*I
)->Merge(Gen
,Progress
) == false)
1058 if (Gen
.HasFileDeps() == true)
1060 if (Progress
!= NULL
)
1062 TotalSize
= ComputeSize(Start
, End
);
1064 for (I
= Start
; I
!= End
; I
++)
1066 unsigned long Size
= (*I
)->Size();
1067 if (Progress
!= NULL
)
1068 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Collecting File Provides"));
1069 CurrentSize
+= Size
;
1070 if ((*I
)->MergeFileProvides(Gen
,Progress
) == false)
1078 // CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/
1079 DynamicMMap
* pkgCacheGenerator::CreateDynamicMMap(FileFd
*CacheF
, unsigned long Flags
) {
1080 unsigned long const MapStart
= _config
->FindI("APT::Cache-Start", 24*1024*1024);
1081 unsigned long const MapGrow
= _config
->FindI("APT::Cache-Grow", 1*1024*1024);
1082 unsigned long const MapLimit
= _config
->FindI("APT::Cache-Limit", 0);
1083 Flags
|= MMap::Moveable
;
1084 if (_config
->FindB("APT::Cache-Fallback", false) == true)
1085 Flags
|= MMap::Fallback
;
1087 return new DynamicMMap(*CacheF
, Flags
, MapStart
, MapGrow
, MapLimit
);
1089 return new DynamicMMap(Flags
, MapStart
, MapGrow
, MapLimit
);
1092 // CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
1093 // ---------------------------------------------------------------------
1094 /* This makes sure that the status cache (the cache that has all
1095 index files from the sources list and all local ones) is ready
1096 to be mmaped. If OutMap is not zero then a MMap object representing
1097 the cache will be stored there. This is pretty much mandetory if you
1098 are using AllowMem. AllowMem lets the function be run as non-root
1099 where it builds the cache 'fast' into a memory buffer. */
1100 __deprecated
bool pkgMakeStatusCache(pkgSourceList
&List
,OpProgress
&Progress
,
1101 MMap
**OutMap
, bool AllowMem
)
1102 { return pkgCacheGenerator::MakeStatusCache(List
, &Progress
, OutMap
, AllowMem
); }
1103 bool pkgCacheGenerator::MakeStatusCache(pkgSourceList
&List
,OpProgress
*Progress
,
1104 MMap
**OutMap
,bool AllowMem
)
1106 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
1108 vector
<pkgIndexFile
*> Files
;
1109 for (vector
<metaIndex
*>::const_iterator i
= List
.begin();
1113 vector
<pkgIndexFile
*> *Indexes
= (*i
)->GetIndexFiles();
1114 for (vector
<pkgIndexFile
*>::const_iterator j
= Indexes
->begin();
1115 j
!= Indexes
->end();
1117 Files
.push_back (*j
);
1120 unsigned long const EndOfSource
= Files
.size();
1121 if (_system
->AddStatusFiles(Files
) == false)
1124 // Decide if we can write to the files..
1125 string
const CacheFile
= _config
->FindFile("Dir::Cache::pkgcache");
1126 string
const SrcCacheFile
= _config
->FindFile("Dir::Cache::srcpkgcache");
1128 // ensure the cache directory exists
1129 if (CacheFile
.empty() == false || SrcCacheFile
.empty() == false)
1131 string dir
= _config
->FindDir("Dir::Cache");
1132 size_t const len
= dir
.size();
1133 if (len
> 5 && dir
.find("/apt/", len
- 6, 5) == len
- 5)
1134 dir
= dir
.substr(0, len
- 5);
1135 if (CacheFile
.empty() == false)
1136 CreateDirectory(dir
, flNotFile(CacheFile
));
1137 if (SrcCacheFile
.empty() == false)
1138 CreateDirectory(dir
, flNotFile(SrcCacheFile
));
1141 // Decide if we can write to the cache
1142 bool Writeable
= false;
1143 if (CacheFile
.empty() == false)
1144 Writeable
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0;
1146 if (SrcCacheFile
.empty() == false)
1147 Writeable
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0;
1149 std::clog
<< "Do we have write-access to the cache files? " << (Writeable
? "YES" : "NO") << std::endl
;
1151 if (Writeable
== false && AllowMem
== false && CacheFile
.empty() == false)
1152 return _error
->Error(_("Unable to write to %s"),flNotFile(CacheFile
).c_str());
1154 if (Progress
!= NULL
)
1155 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1157 // Cache is OK, Fin.
1158 if (CheckValidity(CacheFile
,Files
.begin(),Files
.end(),OutMap
) == true)
1160 if (Progress
!= NULL
)
1161 Progress
->OverallProgress(1,1,1,_("Reading package lists"));
1163 std::clog
<< "pkgcache.bin is valid - no need to build anything" << std::endl
;
1166 else if (Debug
== true)
1167 std::clog
<< "pkgcache.bin is NOT valid" << std::endl
;
1169 /* At this point we know we need to reconstruct the package cache,
1171 SPtr
<FileFd
> CacheF
;
1172 SPtr
<DynamicMMap
> Map
;
1173 if (Writeable
== true && CacheFile
.empty() == false)
1175 unlink(CacheFile
.c_str());
1176 CacheF
= new FileFd(CacheFile
,FileFd::WriteAtomic
);
1177 fchmod(CacheF
->Fd(),0644);
1178 Map
= CreateDynamicMMap(CacheF
, MMap::Public
);
1179 if (_error
->PendingError() == true)
1182 std::clog
<< "Open filebased MMap" << std::endl
;
1186 // Just build it in memory..
1187 Map
= CreateDynamicMMap(NULL
);
1189 std::clog
<< "Open memory Map (not filebased)" << std::endl
;
1192 // Lets try the source cache.
1193 unsigned long CurrentSize
= 0;
1194 unsigned long TotalSize
= 0;
1195 if (CheckValidity(SrcCacheFile
,Files
.begin(),
1196 Files
.begin()+EndOfSource
) == true)
1199 std::clog
<< "srcpkgcache.bin is valid - populate MMap with it." << std::endl
;
1200 // Preload the map with the source cache
1201 FileFd
SCacheF(SrcCacheFile
,FileFd::ReadOnly
);
1202 unsigned long const alloc
= Map
->RawAllocate(SCacheF
.Size());
1203 if ((alloc
== 0 && _error
->PendingError())
1204 || SCacheF
.Read((unsigned char *)Map
->Data() + alloc
,
1205 SCacheF
.Size()) == false)
1208 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1210 // Build the status cache
1211 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1212 if (_error
->PendingError() == true)
1214 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1215 Files
.begin()+EndOfSource
,Files
.end()) == false)
1218 // FIXME: move me to a better place
1219 Gen
.FinishCache(Progress
);
1224 std::clog
<< "srcpkgcache.bin is NOT valid - rebuild" << std::endl
;
1225 TotalSize
= ComputeSize(Files
.begin(),Files
.end());
1227 // Build the source cache
1228 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1229 if (_error
->PendingError() == true)
1231 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1232 Files
.begin(),Files
.begin()+EndOfSource
) == false)
1236 if (Writeable
== true && SrcCacheFile
.empty() == false)
1238 FileFd
SCacheF(SrcCacheFile
,FileFd::WriteAtomic
);
1239 if (_error
->PendingError() == true)
1242 fchmod(SCacheF
.Fd(),0644);
1244 // Write out the main data
1245 if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false)
1246 return _error
->Error(_("IO Error saving source cache"));
1249 // Write out the proper header
1250 Gen
.GetCache().HeaderP
->Dirty
= false;
1251 if (SCacheF
.Seek(0) == false ||
1252 SCacheF
.Write(Map
->Data(),sizeof(*Gen
.GetCache().HeaderP
)) == false)
1253 return _error
->Error(_("IO Error saving source cache"));
1254 Gen
.GetCache().HeaderP
->Dirty
= true;
1258 // Build the status cache
1259 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1260 Files
.begin()+EndOfSource
,Files
.end()) == false)
1263 // FIXME: move me to a better place
1264 Gen
.FinishCache(Progress
);
1267 std::clog
<< "Caches are ready for shipping" << std::endl
;
1269 if (_error
->PendingError() == true)
1275 delete Map
.UnGuard();
1276 *OutMap
= new MMap(*CacheF
,0);
1280 *OutMap
= Map
.UnGuard();
1287 // CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
1288 // ---------------------------------------------------------------------
1290 __deprecated
bool pkgMakeOnlyStatusCache(OpProgress
&Progress
,DynamicMMap
**OutMap
)
1291 { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress
, OutMap
); }
1292 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress
*Progress
,DynamicMMap
**OutMap
)
1294 vector
<pkgIndexFile
*> Files
;
1295 unsigned long EndOfSource
= Files
.size();
1296 if (_system
->AddStatusFiles(Files
) == false)
1299 SPtr
<DynamicMMap
> Map
= CreateDynamicMMap(NULL
);
1300 unsigned long CurrentSize
= 0;
1301 unsigned long TotalSize
= 0;
1303 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1305 // Build the status cache
1306 if (Progress
!= NULL
)
1307 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1308 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1309 if (_error
->PendingError() == true)
1311 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1312 Files
.begin()+EndOfSource
,Files
.end()) == false)
1315 // FIXME: move me to a better place
1316 Gen
.FinishCache(Progress
);
1318 if (_error
->PendingError() == true)
1320 *OutMap
= Map
.UnGuard();