]>
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 /* As we handle Arch all packages as architecture bounded
182 we add all information to every (simulated) arch package */
183 std::vector
<string
> genArch
;
184 if (List
.ArchitectureAll() == true) {
185 genArch
= APT::Configuration::getArchitectures();
186 if (genArch
.size() != 1)
187 genArch
.push_back("all");
189 genArch
.push_back(List
.Architecture());
191 for (std::vector
<string
>::const_iterator arch
= genArch
.begin();
192 arch
!= genArch
.end(); ++arch
)
194 // Get a pointer to the package structure
195 pkgCache::PkgIterator Pkg
;
196 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
197 if (NewPackage(Pkg
, PackageName
, *arch
) == false)
198 return _error
->Error(_("Error occurred while processing %s (NewPackage)"),PackageName
.c_str());
200 if (Counter
% 100 == 0 && Progress
!= 0)
201 Progress
->Progress(List
.Offset());
203 /* Get a pointer to the version structure. We know the list is sorted
204 so we use that fact in the search. Insertion of new versions is
205 done with correct sorting */
206 string Version
= List
.Version();
207 if (Version
.empty() == true)
209 // we first process the package, then the descriptions
210 // (this has the bonus that we get MMap error when we run out
212 pkgCache::VerIterator
Ver(Cache
);
213 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
214 if (List
.UsePackage(Pkg
, Ver
) == false)
215 return _error
->Error(_("Error occurred while processing %s (UsePackage1)"),
216 PackageName
.c_str());
218 // Find the right version to write the description
219 MD5SumValue CurMd5
= List
.Description_md5();
220 Ver
= Pkg
.VersionList();
222 for (; Ver
.end() == false; ++Ver
)
224 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
225 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
226 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
227 bool duplicate
=false;
229 // don't add a new description if we have one for the given
231 for ( ; Desc
.end() == false; Desc
++)
232 if (MD5SumValue(Desc
.md5()) == CurMd5
&&
233 Desc
.LanguageCode() == List
.DescriptionLanguage())
238 for (Desc
= Ver
.DescriptionList();
240 LastDesc
= &Desc
->NextDesc
, Desc
++)
242 if (MD5SumValue(Desc
.md5()) == CurMd5
)
244 // Add new description
245 void const * const oldMap
= Map
.Data();
246 map_ptrloc
const descindex
= NewDescription(Desc
, List
.DescriptionLanguage(), CurMd5
, *LastDesc
);
247 if (oldMap
!= Map
.Data())
248 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
249 *LastDesc
= descindex
;
250 Desc
->ParentPkg
= Pkg
.Index();
252 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
253 return _error
->Error(_("Error occurred while processing %s (NewFileDesc1)"),PackageName
.c_str());
262 pkgCache::VerIterator Ver
= Pkg
.VersionList();
263 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
264 map_ptrloc
*LastVer
= &Pkg
->VersionList
;
265 void const * oldMap
= Map
.Data();
267 unsigned long const Hash
= List
.VersionHash();
268 for (; Ver
.end() == false; LastVer
= &Ver
->NextVer
, Ver
++)
270 Res
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr());
271 // Version is higher as current version - insert here
274 // Versionstrings are equal - is hash also equal?
275 if (Res
== 0 && Ver
->Hash
== Hash
)
277 // proceed with the next till we have either the right
278 // or we found another version (which will be lower)
281 /* We already have a version for this item, record that we saw it */
282 if (Res
== 0 && Ver
.end() == false && Ver
->Hash
== Hash
)
284 if (List
.UsePackage(Pkg
,Ver
) == false)
285 return _error
->Error(_("Error occurred while processing %s (UsePackage2)"),
286 PackageName
.c_str());
288 if (NewFileVer(Ver
,List
) == false)
289 return _error
->Error(_("Error occurred while processing %s (NewFileVer1)"),
290 PackageName
.c_str());
292 // Read only a single record and return
296 FoundFileDeps
|= List
.HasFileDeps();
304 map_ptrloc
const verindex
= NewVersion(Ver
,Version
,*LastVer
);
305 if (verindex
== 0 && _error
->PendingError())
306 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
307 PackageName
.c_str(), 1);
309 if (oldMap
!= Map
.Data())
310 LastVer
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
312 Ver
->ParentPkg
= Pkg
.Index();
315 if (List
.NewVersion(Ver
) == false)
316 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
317 PackageName
.c_str(), 2);
319 if (List
.UsePackage(Pkg
,Ver
) == false)
320 return _error
->Error(_("Error occurred while processing %s (UsePackage3)"),
321 PackageName
.c_str());
323 if (NewFileVer(Ver
,List
) == false)
324 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
325 PackageName
.c_str(), 3);
327 // Read only a single record and return
331 FoundFileDeps
|= List
.HasFileDeps();
335 /* Record the Description data. Description data always exist in
336 Packages and Translation-* files. */
337 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
338 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
339 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
341 // Skip to the end of description set
342 for (; Desc
.end() == false; LastDesc
= &Desc
->NextDesc
, Desc
++);
344 // Add new description
346 map_ptrloc
const descindex
= NewDescription(Desc
, List
.DescriptionLanguage(), List
.Description_md5(), *LastDesc
);
347 if (oldMap
!= Map
.Data())
348 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
349 *LastDesc
= descindex
;
350 Desc
->ParentPkg
= Pkg
.Index();
352 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
353 return _error
->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName
.c_str());
357 FoundFileDeps
|= List
.HasFileDeps();
359 if (Cache
.HeaderP
->PackageCount
>= (1ULL<<sizeof(Cache
.PkgP
->ID
)*8)-1)
360 return _error
->Error(_("Wow, you exceeded the number of package "
361 "names this APT is capable of."));
362 if (Cache
.HeaderP
->VersionCount
>= (1ULL<<(sizeof(Cache
.VerP
->ID
)*8))-1)
363 return _error
->Error(_("Wow, you exceeded the number of versions "
364 "this APT is capable of."));
365 if (Cache
.HeaderP
->DescriptionCount
>= (1ULL<<(sizeof(Cache
.DescP
->ID
)*8))-1)
366 return _error
->Error(_("Wow, you exceeded the number of descriptions "
367 "this APT is capable of."));
368 if (Cache
.HeaderP
->DependsCount
>= (1ULL<<(sizeof(Cache
.DepP
->ID
)*8))-1ULL)
369 return _error
->Error(_("Wow, you exceeded the number of dependencies "
370 "this APT is capable of."));
374 // CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/
375 // ---------------------------------------------------------------------
376 /* If we found any file depends while parsing the main list we need to
377 resolve them. Since it is undesired to load the entire list of files
378 into the cache as virtual packages we do a two stage effort. MergeList
379 identifies the file depends and this creates Provdies for them by
380 re-parsing all the indexs. */
381 bool pkgCacheGenerator::MergeFileProvides(ListParser
&List
)
385 unsigned int Counter
= 0;
386 while (List
.Step() == true)
388 string PackageName
= List
.Package();
389 if (PackageName
.empty() == true)
391 string Version
= List
.Version();
392 if (Version
.empty() == true)
395 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(PackageName
);
396 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
397 if (Pkg
.end() == true)
398 return _error
->Error(_("Error occurred while processing %s (FindPkg)"),
399 PackageName
.c_str());
401 if (Counter
% 100 == 0 && Progress
!= 0)
402 Progress
->Progress(List
.Offset());
404 unsigned long Hash
= List
.VersionHash();
405 pkgCache::VerIterator Ver
= Pkg
.VersionList();
406 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
407 for (; Ver
.end() == false; Ver
++)
409 if (Ver
->Hash
== Hash
&& Version
.c_str() == Ver
.VerStr())
411 if (List
.CollectFileProvides(Cache
,Ver
) == false)
412 return _error
->Error(_("Error occurred while processing %s (CollectFileProvides)"),PackageName
.c_str());
417 if (Ver
.end() == true)
418 _error
->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName
.c_str(),Version
.c_str());
424 // CacheGenerator::NewGroup - Add a new group /*{{{*/
425 // ---------------------------------------------------------------------
426 /* This creates a new group structure and adds it to the hash table */
427 bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator
&Grp
, const string
&Name
)
429 Grp
= Cache
.FindGrp(Name
);
430 if (Grp
.end() == false)
434 map_ptrloc
const Group
= AllocateInMap(sizeof(pkgCache::Group
));
435 if (unlikely(Group
== 0))
438 Grp
= pkgCache::GrpIterator(Cache
, Cache
.GrpP
+ Group
);
439 map_ptrloc
const idxName
= WriteStringInMap(Name
);
440 if (unlikely(idxName
== 0))
444 // Insert it into the hash table
445 unsigned long const Hash
= Cache
.Hash(Name
);
446 Grp
->Next
= Cache
.HeaderP
->GrpHashTable
[Hash
];
447 Cache
.HeaderP
->GrpHashTable
[Hash
] = Group
;
449 Grp
->ID
= Cache
.HeaderP
->GroupCount
++;
453 // CacheGenerator::NewPackage - Add a new package /*{{{*/
454 // ---------------------------------------------------------------------
455 /* This creates a new package structure and adds it to the hash table */
456 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator
&Pkg
,const string
&Name
,
457 const string
&Arch
) {
458 pkgCache::GrpIterator Grp
;
459 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
460 if (unlikely(NewGroup(Grp
, Name
) == false))
463 Pkg
= Grp
.FindPkg(Arch
);
464 if (Pkg
.end() == false)
468 map_ptrloc
const Package
= AllocateInMap(sizeof(pkgCache::Package
));
469 if (unlikely(Package
== 0))
471 Pkg
= pkgCache::PkgIterator(Cache
,Cache
.PkgP
+ Package
);
473 // Insert the package into our package list
474 if (Grp
->FirstPackage
== 0) // the group is new
476 // Insert it into the hash table
477 unsigned long const Hash
= Cache
.Hash(Name
);
478 Pkg
->NextPackage
= Cache
.HeaderP
->PkgHashTable
[Hash
];
479 Cache
.HeaderP
->PkgHashTable
[Hash
] = Package
;
480 Grp
->FirstPackage
= Package
;
482 else // Group the Packages together
484 // this package is the new last package
485 pkgCache::PkgIterator
LastPkg(Cache
, Cache
.PkgP
+ Grp
->LastPackage
);
486 Pkg
->NextPackage
= LastPkg
->NextPackage
;
487 LastPkg
->NextPackage
= Package
;
489 Grp
->LastPackage
= Package
;
491 // Set the name, arch and the ID
492 Pkg
->Name
= Grp
->Name
;
493 Pkg
->Group
= Grp
.Index();
494 map_ptrloc
const idxArch
= WriteUniqString(Arch
.c_str());
495 if (unlikely(idxArch
== 0))
498 Pkg
->ID
= Cache
.HeaderP
->PackageCount
++;
503 // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
504 // ---------------------------------------------------------------------
506 bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator
&Ver
,
509 if (CurrentFile
== 0)
513 map_ptrloc
const VerFile
= AllocateInMap(sizeof(pkgCache::VerFile
));
517 pkgCache::VerFileIterator
VF(Cache
,Cache
.VerFileP
+ VerFile
);
518 VF
->File
= CurrentFile
- Cache
.PkgFileP
;
520 // Link it to the end of the list
521 map_ptrloc
*Last
= &Ver
->FileList
;
522 for (pkgCache::VerFileIterator V
= Ver
.FileList(); V
.end() == false; V
++)
524 VF
->NextFile
= *Last
;
527 VF
->Offset
= List
.Offset();
528 VF
->Size
= List
.Size();
529 if (Cache
.HeaderP
->MaxVerFileSize
< VF
->Size
)
530 Cache
.HeaderP
->MaxVerFileSize
= VF
->Size
;
531 Cache
.HeaderP
->VerFileCount
++;
536 // CacheGenerator::NewVersion - Create a new Version /*{{{*/
537 // ---------------------------------------------------------------------
538 /* This puts a version structure in the linked list */
539 unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator
&Ver
,
540 const string
&VerStr
,
544 map_ptrloc
const Version
= AllocateInMap(sizeof(pkgCache::Version
));
549 Ver
= pkgCache::VerIterator(Cache
,Cache
.VerP
+ Version
);
551 Ver
->ID
= Cache
.HeaderP
->VersionCount
++;
552 map_ptrloc
const idxVerStr
= WriteStringInMap(VerStr
);
553 if (unlikely(idxVerStr
== 0))
555 Ver
->VerStr
= idxVerStr
;
560 // CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/
561 // ---------------------------------------------------------------------
563 bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator
&Desc
,
566 if (CurrentFile
== 0)
570 map_ptrloc
const DescFile
= AllocateInMap(sizeof(pkgCache::DescFile
));
574 pkgCache::DescFileIterator
DF(Cache
,Cache
.DescFileP
+ DescFile
);
575 DF
->File
= CurrentFile
- Cache
.PkgFileP
;
577 // Link it to the end of the list
578 map_ptrloc
*Last
= &Desc
->FileList
;
579 for (pkgCache::DescFileIterator D
= Desc
.FileList(); D
.end() == false; D
++)
582 DF
->NextFile
= *Last
;
585 DF
->Offset
= List
.Offset();
586 DF
->Size
= List
.Size();
587 if (Cache
.HeaderP
->MaxDescFileSize
< DF
->Size
)
588 Cache
.HeaderP
->MaxDescFileSize
= DF
->Size
;
589 Cache
.HeaderP
->DescFileCount
++;
594 // CacheGenerator::NewDescription - Create a new Description /*{{{*/
595 // ---------------------------------------------------------------------
596 /* This puts a description structure in the linked list */
597 map_ptrloc
pkgCacheGenerator::NewDescription(pkgCache::DescIterator
&Desc
,
599 const MD5SumValue
&md5sum
,
603 map_ptrloc
const Description
= AllocateInMap(sizeof(pkgCache::Description
));
604 if (Description
== 0)
608 Desc
= pkgCache::DescIterator(Cache
,Cache
.DescP
+ Description
);
609 Desc
->NextDesc
= Next
;
610 Desc
->ID
= Cache
.HeaderP
->DescriptionCount
++;
611 map_ptrloc
const idxlanguage_code
= WriteStringInMap(Lang
);
612 map_ptrloc
const idxmd5sum
= WriteStringInMap(md5sum
.Value());
613 if (unlikely(idxlanguage_code
== 0 || idxmd5sum
== 0))
615 Desc
->language_code
= idxlanguage_code
;
616 Desc
->md5sum
= idxmd5sum
;
621 // CacheGenerator::FinishCache - do various finish operations /*{{{*/
622 // ---------------------------------------------------------------------
623 /* This prepares the Cache for delivery */
624 bool pkgCacheGenerator::FinishCache(OpProgress
*Progress
)
626 // FIXME: add progress reporting for this operation
627 // Do we have different architectures in your groups ?
628 vector
<string
> archs
= APT::Configuration::getArchitectures();
629 if (archs
.size() > 1)
631 // Create Conflicts in between the group
632 pkgCache::GrpIterator G
= GetCache().GrpBegin();
633 Dynamic
<pkgCache::GrpIterator
> DynG(G
);
634 for (; G
.end() != true; G
++)
636 string
const PkgName
= G
.Name();
637 pkgCache::PkgIterator P
= G
.PackageList();
638 Dynamic
<pkgCache::PkgIterator
> DynP(P
);
639 for (; P
.end() != true; P
= G
.NextPkg(P
))
641 pkgCache::PkgIterator allPkg
;
642 Dynamic
<pkgCache::PkgIterator
> DynallPkg(allPkg
);
643 pkgCache::VerIterator V
= P
.VersionList();
644 Dynamic
<pkgCache::VerIterator
> DynV(V
);
645 for (; V
.end() != true; V
++)
647 char const * const Arch
= P
.Arch();
648 map_ptrloc
*OldDepLast
= NULL
;
649 /* MultiArch handling introduces a lot of implicit Dependencies:
650 - MultiArch: same → Co-Installable if they have the same version
651 - Architecture: all → Need to be Co-Installable for internal reasons
652 - All others conflict with all other group members */
653 bool const coInstall
= ((V
->MultiArch
== pkgCache::Version::All
&& strcmp(Arch
, "all") != 0) ||
654 V
->MultiArch
== pkgCache::Version::Same
);
655 if (V
->MultiArch
== pkgCache::Version::All
&& allPkg
.end() == true)
656 allPkg
= G
.FindPkg("all");
657 for (vector
<string
>::const_iterator A
= archs
.begin(); A
!= archs
.end(); ++A
)
661 /* We allow only one installed arch at the time
662 per group, therefore each group member conflicts
663 with all other group members */
664 pkgCache::PkgIterator D
= G
.FindPkg(*A
);
665 Dynamic
<pkgCache::PkgIterator
> DynD(D
);
668 if (coInstall
== true)
670 // Replaces: ${self}:other ( << ${binary:Version})
671 NewDepends(D
, V
, V
.VerStr(),
672 pkgCache::Dep::Less
, pkgCache::Dep::Replaces
,
674 // Breaks: ${self}:other (!= ${binary:Version})
675 NewDepends(D
, V
, V
.VerStr(),
676 pkgCache::Dep::NotEquals
, pkgCache::Dep::DpkgBreaks
,
678 if (V
->MultiArch
== pkgCache::Version::All
)
680 // Depend on ${self}:all which does depend on nothing
681 NewDepends(allPkg
, V
, V
.VerStr(),
682 pkgCache::Dep::Equals
, pkgCache::Dep::Depends
,
686 // Conflicts: ${self}:other
687 if (strcmp(Arch
, "all") == 0) {
688 NewDepends(D
, V
, V
.VerStr(),
689 pkgCache::Dep::NotEquals
, pkgCache::Dep::Conflicts
,
693 pkgCache::Dep::NoOp
, pkgCache::Dep::Conflicts
,
705 // CacheGenerator::NewDepends - Create a dependency element /*{{{*/
706 // ---------------------------------------------------------------------
707 /* This creates a dependency element in the tree. It is linked to the
708 version and to the package that it is pointing to. */
709 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator
&Pkg
,
710 pkgCache::VerIterator
&Ver
,
711 string
const &Version
,
712 unsigned int const &Op
,
713 unsigned int const &Type
,
714 map_ptrloc
*OldDepLast
)
716 void const * const oldMap
= Map
.Data();
718 map_ptrloc
const Dependency
= AllocateInMap(sizeof(pkgCache::Dependency
));
719 if (unlikely(Dependency
== 0))
723 pkgCache::DepIterator
Dep(Cache
,Cache
.DepP
+ Dependency
);
724 Dynamic
<pkgCache::DepIterator
> DynDep(Dep
);
725 Dep
->ParentVer
= Ver
.Index();
728 Dep
->ID
= Cache
.HeaderP
->DependsCount
++;
730 // Probe the reverse dependency list for a version string that matches
731 if (Version
.empty() == false)
733 /* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
734 if (I->Version != 0 && I.TargetVer() == Version)
735 Dep->Version = I->Version;*/
736 if (Dep
->Version
== 0) {
737 map_ptrloc
const index
= WriteStringInMap(Version
);
738 if (unlikely(index
== 0))
740 Dep
->Version
= index
;
744 // Link it to the package
745 Dep
->Package
= Pkg
.Index();
746 Dep
->NextRevDepends
= Pkg
->RevDepends
;
747 Pkg
->RevDepends
= Dep
.Index();
749 // Do we know where to link the Dependency to?
750 if (OldDepLast
== NULL
)
752 OldDepLast
= &Ver
->DependsList
;
753 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
754 OldDepLast
= &D
->NextDepends
;
755 } else if (oldMap
!= Map
.Data())
756 OldDepLast
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
758 Dep
->NextDepends
= *OldDepLast
;
759 *OldDepLast
= Dep
.Index();
760 OldDepLast
= &Dep
->NextDepends
;
765 // ListParser::NewDepends - Create the environment for a new dependency /*{{{*/
766 // ---------------------------------------------------------------------
767 /* This creates a Group and the Package to link this dependency to if
768 needed and handles also the caching of the old endpoint */
769 bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator
&Ver
,
770 const string
&PackageName
,
772 const string
&Version
,
776 pkgCache::GrpIterator Grp
;
777 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
778 if (unlikely(Owner
->NewGroup(Grp
, PackageName
) == false))
781 // Locate the target package
782 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(Arch
);
783 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
784 if (Pkg
.end() == true) {
785 if (unlikely(Owner
->NewPackage(Pkg
, PackageName
, Arch
) == false))
789 // Is it a file dependency?
790 if (unlikely(PackageName
[0] == '/'))
791 FoundFileDeps
= true;
793 /* Caching the old end point speeds up generation substantially */
794 if (OldDepVer
!= Ver
) {
799 return Owner
->NewDepends(Pkg
, Ver
, Version
, Op
, Type
, OldDepLast
);
802 // ListParser::NewProvides - Create a Provides element /*{{{*/
803 // ---------------------------------------------------------------------
805 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator
&Ver
,
806 const string
&PkgName
,
807 const string
&PkgArch
,
808 const string
&Version
)
810 pkgCache
&Cache
= Owner
->Cache
;
812 // We do not add self referencing provides
813 if (Ver
.ParentPkg().Name() == PkgName
&& PkgArch
== Ver
.Arch(true))
817 map_ptrloc
const Provides
= Owner
->AllocateInMap(sizeof(pkgCache::Provides
));
818 if (unlikely(Provides
== 0))
820 Cache
.HeaderP
->ProvidesCount
++;
823 pkgCache::PrvIterator
Prv(Cache
,Cache
.ProvideP
+ Provides
,Cache
.PkgP
);
824 Dynamic
<pkgCache::PrvIterator
> DynPrv(Prv
);
825 Prv
->Version
= Ver
.Index();
826 Prv
->NextPkgProv
= Ver
->ProvidesList
;
827 Ver
->ProvidesList
= Prv
.Index();
828 if (Version
.empty() == false && unlikely((Prv
->ProvideVersion
= WriteString(Version
)) == 0))
831 // Locate the target package
832 pkgCache::PkgIterator Pkg
;
833 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
834 if (unlikely(Owner
->NewPackage(Pkg
,PkgName
, PkgArch
) == false))
837 // Link it to the package
838 Prv
->ParentPkg
= Pkg
.Index();
839 Prv
->NextProvides
= Pkg
->ProvidesList
;
840 Pkg
->ProvidesList
= Prv
.Index();
845 // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
846 // ---------------------------------------------------------------------
847 /* This is used to select which file is to be associated with all newly
848 added versions. The caller is responsible for setting the IMS fields. */
849 bool pkgCacheGenerator::SelectFile(const string
&File
,const string
&Site
,
850 const pkgIndexFile
&Index
,
853 // Get some space for the structure
854 map_ptrloc
const idxFile
= AllocateInMap(sizeof(*CurrentFile
));
855 if (unlikely(idxFile
== 0))
857 CurrentFile
= Cache
.PkgFileP
+ idxFile
;
860 map_ptrloc
const idxFileName
= WriteStringInMap(File
);
861 map_ptrloc
const idxSite
= WriteUniqString(Site
);
862 if (unlikely(idxFileName
== 0 || idxSite
== 0))
864 CurrentFile
->FileName
= idxFileName
;
865 CurrentFile
->Site
= idxSite
;
866 CurrentFile
->NextFile
= Cache
.HeaderP
->FileList
;
867 CurrentFile
->Flags
= Flags
;
868 CurrentFile
->ID
= Cache
.HeaderP
->PackageFileCount
;
869 map_ptrloc
const idxIndexType
= WriteUniqString(Index
.GetType()->Label
);
870 if (unlikely(idxIndexType
== 0))
872 CurrentFile
->IndexType
= idxIndexType
;
874 Cache
.HeaderP
->FileList
= CurrentFile
- Cache
.PkgFileP
;
875 Cache
.HeaderP
->PackageFileCount
++;
878 Progress
->SubProgress(Index
.Size());
882 // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
883 // ---------------------------------------------------------------------
884 /* This is used to create handles to strings. Given the same text it
885 always returns the same number */
886 unsigned long pkgCacheGenerator::WriteUniqString(const char *S
,
889 /* We use a very small transient hash table here, this speeds up generation
890 by a fair amount on slower machines */
891 pkgCache::StringItem
*&Bucket
= UniqHash
[(S
[0]*5 + S
[1]) % _count(UniqHash
)];
893 stringcmp(S
,S
+Size
,Cache
.StrP
+ Bucket
->String
) == 0)
894 return Bucket
->String
;
896 // Search for an insertion point
897 pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.HeaderP
->StringList
;
899 map_ptrloc
*Last
= &Cache
.HeaderP
->StringList
;
900 for (; I
!= Cache
.StringItemP
; Last
= &I
->NextItem
,
901 I
= Cache
.StringItemP
+ I
->NextItem
)
903 Res
= stringcmp(S
,S
+Size
,Cache
.StrP
+ I
->String
);
916 void const * const oldMap
= Map
.Data();
917 map_ptrloc
const Item
= AllocateInMap(sizeof(pkgCache::StringItem
));
921 map_ptrloc
const idxString
= WriteStringInMap(S
,Size
);
922 if (unlikely(idxString
== 0))
924 if (oldMap
!= Map
.Data()) {
925 Last
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
926 I
+= (pkgCache::StringItem
*) Map
.Data() - (pkgCache::StringItem
*) oldMap
;
930 // Fill in the structure
931 pkgCache::StringItem
*ItemP
= Cache
.StringItemP
+ Item
;
932 ItemP
->NextItem
= I
- Cache
.StringItemP
;
933 ItemP
->String
= idxString
;
936 return ItemP
->String
;
939 // CheckValidity - Check that a cache is up-to-date /*{{{*/
940 // ---------------------------------------------------------------------
941 /* This just verifies that each file in the list of index files exists,
942 has matching attributes with the cache and the cache does not have
944 static bool CheckValidity(const string
&CacheFile
, FileIterator Start
,
945 FileIterator End
,MMap
**OutMap
= 0)
947 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
948 // No file, certainly invalid
949 if (CacheFile
.empty() == true || FileExists(CacheFile
) == false)
952 std::clog
<< "CacheFile doesn't exist" << std::endl
;
957 FileFd
CacheF(CacheFile
,FileFd::ReadOnly
);
958 SPtr
<MMap
> Map
= new MMap(CacheF
,0);
960 if (_error
->PendingError() == true || Map
->Size() == 0)
963 std::clog
<< "Errors are pending or Map is empty()" << std::endl
;
968 /* Now we check every index file, see if it is in the cache,
969 verify the IMS data and check that it is on the disk too.. */
970 SPtrArray
<bool> Visited
= new bool[Cache
.HeaderP
->PackageFileCount
];
971 memset(Visited
,0,sizeof(*Visited
)*Cache
.HeaderP
->PackageFileCount
);
972 for (; Start
!= End
; Start
++)
975 std::clog
<< "Checking PkgFile " << (*Start
)->Describe() << ": ";
976 if ((*Start
)->HasPackages() == false)
979 std::clog
<< "Has NO packages" << std::endl
;
983 if ((*Start
)->Exists() == false)
985 #if 0 // mvo: we no longer give a message here (Default Sources spec)
986 _error
->WarningE("stat",_("Couldn't stat source package list %s"),
987 (*Start
)->Describe().c_str());
990 std::clog
<< "file doesn't exist" << std::endl
;
994 // FindInCache is also expected to do an IMS check.
995 pkgCache::PkgFileIterator File
= (*Start
)->FindInCache(Cache
);
996 if (File
.end() == true)
999 std::clog
<< "FindInCache returned end-Pointer" << std::endl
;
1003 Visited
[File
->ID
] = true;
1005 std::clog
<< "with ID " << File
->ID
<< " is valid" << std::endl
;
1008 for (unsigned I
= 0; I
!= Cache
.HeaderP
->PackageFileCount
; I
++)
1009 if (Visited
[I
] == false)
1012 std::clog
<< "File with ID" << I
<< " wasn't visited" << std::endl
;
1016 if (_error
->PendingError() == true)
1020 std::clog
<< "Validity failed because of pending errors:" << std::endl
;
1021 _error
->DumpErrors();
1028 *OutMap
= Map
.UnGuard();
1032 // ComputeSize - Compute the total size of a bunch of files /*{{{*/
1033 // ---------------------------------------------------------------------
1034 /* Size is kind of an abstract notion that is only used for the progress
1036 static unsigned long ComputeSize(FileIterator Start
,FileIterator End
)
1038 unsigned long TotalSize
= 0;
1039 for (; Start
!= End
; Start
++)
1041 if ((*Start
)->HasPackages() == false)
1043 TotalSize
+= (*Start
)->Size();
1048 // BuildCache - Merge the list of index files into the cache /*{{{*/
1049 // ---------------------------------------------------------------------
1051 static bool BuildCache(pkgCacheGenerator
&Gen
,
1052 OpProgress
*Progress
,
1053 unsigned long &CurrentSize
,unsigned long TotalSize
,
1054 FileIterator Start
, FileIterator End
)
1057 for (I
= Start
; I
!= End
; I
++)
1059 if ((*I
)->HasPackages() == false)
1062 if ((*I
)->Exists() == false)
1065 if ((*I
)->FindInCache(Gen
.GetCache()).end() == false)
1067 _error
->Warning("Duplicate sources.list entry %s",
1068 (*I
)->Describe().c_str());
1072 unsigned long Size
= (*I
)->Size();
1073 if (Progress
!= NULL
)
1074 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Reading package lists"));
1075 CurrentSize
+= Size
;
1077 if ((*I
)->Merge(Gen
,Progress
) == false)
1081 if (Gen
.HasFileDeps() == true)
1083 if (Progress
!= NULL
)
1085 TotalSize
= ComputeSize(Start
, End
);
1087 for (I
= Start
; I
!= End
; I
++)
1089 unsigned long Size
= (*I
)->Size();
1090 if (Progress
!= NULL
)
1091 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Collecting File Provides"));
1092 CurrentSize
+= Size
;
1093 if ((*I
)->MergeFileProvides(Gen
,Progress
) == false)
1101 // CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/
1102 DynamicMMap
* pkgCacheGenerator::CreateDynamicMMap(FileFd
*CacheF
, unsigned long Flags
) {
1103 unsigned long const MapStart
= _config
->FindI("APT::Cache-Start", 24*1024*1024);
1104 unsigned long const MapGrow
= _config
->FindI("APT::Cache-Grow", 1*1024*1024);
1105 unsigned long const MapLimit
= _config
->FindI("APT::Cache-Limit", 0);
1106 Flags
|= MMap::Moveable
;
1107 if (_config
->FindB("APT::Cache-Fallback", false) == true)
1108 Flags
|= MMap::Fallback
;
1110 return new DynamicMMap(*CacheF
, Flags
, MapStart
, MapGrow
, MapLimit
);
1112 return new DynamicMMap(Flags
, MapStart
, MapGrow
, MapLimit
);
1115 // CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
1116 // ---------------------------------------------------------------------
1117 /* This makes sure that the status cache (the cache that has all
1118 index files from the sources list and all local ones) is ready
1119 to be mmaped. If OutMap is not zero then a MMap object representing
1120 the cache will be stored there. This is pretty much mandetory if you
1121 are using AllowMem. AllowMem lets the function be run as non-root
1122 where it builds the cache 'fast' into a memory buffer. */
1123 __deprecated
bool pkgMakeStatusCache(pkgSourceList
&List
,OpProgress
&Progress
,
1124 MMap
**OutMap
, bool AllowMem
)
1125 { return pkgCacheGenerator::MakeStatusCache(List
, &Progress
, OutMap
, AllowMem
); }
1126 bool pkgCacheGenerator::MakeStatusCache(pkgSourceList
&List
,OpProgress
*Progress
,
1127 MMap
**OutMap
,bool AllowMem
)
1129 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
1131 vector
<pkgIndexFile
*> Files
;
1132 for (vector
<metaIndex
*>::const_iterator i
= List
.begin();
1136 vector
<pkgIndexFile
*> *Indexes
= (*i
)->GetIndexFiles();
1137 for (vector
<pkgIndexFile
*>::const_iterator j
= Indexes
->begin();
1138 j
!= Indexes
->end();
1140 Files
.push_back (*j
);
1143 unsigned long const EndOfSource
= Files
.size();
1144 if (_system
->AddStatusFiles(Files
) == false)
1147 // Decide if we can write to the files..
1148 string
const CacheFile
= _config
->FindFile("Dir::Cache::pkgcache");
1149 string
const SrcCacheFile
= _config
->FindFile("Dir::Cache::srcpkgcache");
1151 // ensure the cache directory exists
1152 if (CacheFile
.empty() == false || SrcCacheFile
.empty() == false)
1154 string dir
= _config
->FindDir("Dir::Cache");
1155 size_t const len
= dir
.size();
1156 if (len
> 5 && dir
.find("/apt/", len
- 6, 5) == len
- 5)
1157 dir
= dir
.substr(0, len
- 5);
1158 if (CacheFile
.empty() == false)
1159 CreateDirectory(dir
, flNotFile(CacheFile
));
1160 if (SrcCacheFile
.empty() == false)
1161 CreateDirectory(dir
, flNotFile(SrcCacheFile
));
1164 // Decide if we can write to the cache
1165 bool Writeable
= false;
1166 if (CacheFile
.empty() == false)
1167 Writeable
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0;
1169 if (SrcCacheFile
.empty() == false)
1170 Writeable
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0;
1172 std::clog
<< "Do we have write-access to the cache files? " << (Writeable
? "YES" : "NO") << std::endl
;
1174 if (Writeable
== false && AllowMem
== false && CacheFile
.empty() == false)
1175 return _error
->Error(_("Unable to write to %s"),flNotFile(CacheFile
).c_str());
1177 if (Progress
!= NULL
)
1178 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1180 // Cache is OK, Fin.
1181 if (CheckValidity(CacheFile
,Files
.begin(),Files
.end(),OutMap
) == true)
1183 if (Progress
!= NULL
)
1184 Progress
->OverallProgress(1,1,1,_("Reading package lists"));
1186 std::clog
<< "pkgcache.bin is valid - no need to build anything" << std::endl
;
1189 else if (Debug
== true)
1190 std::clog
<< "pkgcache.bin is NOT valid" << std::endl
;
1192 /* At this point we know we need to reconstruct the package cache,
1194 SPtr
<FileFd
> CacheF
;
1195 SPtr
<DynamicMMap
> Map
;
1196 if (Writeable
== true && CacheFile
.empty() == false)
1198 unlink(CacheFile
.c_str());
1199 CacheF
= new FileFd(CacheFile
,FileFd::WriteAtomic
);
1200 fchmod(CacheF
->Fd(),0644);
1201 Map
= CreateDynamicMMap(CacheF
, MMap::Public
);
1202 if (_error
->PendingError() == true)
1205 std::clog
<< "Open filebased MMap" << std::endl
;
1209 // Just build it in memory..
1210 Map
= CreateDynamicMMap(NULL
);
1212 std::clog
<< "Open memory Map (not filebased)" << std::endl
;
1215 // Lets try the source cache.
1216 unsigned long CurrentSize
= 0;
1217 unsigned long TotalSize
= 0;
1218 if (CheckValidity(SrcCacheFile
,Files
.begin(),
1219 Files
.begin()+EndOfSource
) == true)
1222 std::clog
<< "srcpkgcache.bin is valid - populate MMap with it." << std::endl
;
1223 // Preload the map with the source cache
1224 FileFd
SCacheF(SrcCacheFile
,FileFd::ReadOnly
);
1225 unsigned long const alloc
= Map
->RawAllocate(SCacheF
.Size());
1226 if ((alloc
== 0 && _error
->PendingError())
1227 || SCacheF
.Read((unsigned char *)Map
->Data() + alloc
,
1228 SCacheF
.Size()) == false)
1231 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1233 // Build the status cache
1234 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1235 if (_error
->PendingError() == true)
1237 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1238 Files
.begin()+EndOfSource
,Files
.end()) == false)
1241 // FIXME: move me to a better place
1242 Gen
.FinishCache(Progress
);
1247 std::clog
<< "srcpkgcache.bin is NOT valid - rebuild" << std::endl
;
1248 TotalSize
= ComputeSize(Files
.begin(),Files
.end());
1250 // Build the source cache
1251 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1252 if (_error
->PendingError() == true)
1254 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1255 Files
.begin(),Files
.begin()+EndOfSource
) == false)
1259 if (Writeable
== true && SrcCacheFile
.empty() == false)
1261 FileFd
SCacheF(SrcCacheFile
,FileFd::WriteAtomic
);
1262 if (_error
->PendingError() == true)
1265 fchmod(SCacheF
.Fd(),0644);
1267 // Write out the main data
1268 if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false)
1269 return _error
->Error(_("IO Error saving source cache"));
1272 // Write out the proper header
1273 Gen
.GetCache().HeaderP
->Dirty
= false;
1274 if (SCacheF
.Seek(0) == false ||
1275 SCacheF
.Write(Map
->Data(),sizeof(*Gen
.GetCache().HeaderP
)) == false)
1276 return _error
->Error(_("IO Error saving source cache"));
1277 Gen
.GetCache().HeaderP
->Dirty
= true;
1281 // Build the status cache
1282 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1283 Files
.begin()+EndOfSource
,Files
.end()) == false)
1286 // FIXME: move me to a better place
1287 Gen
.FinishCache(Progress
);
1290 std::clog
<< "Caches are ready for shipping" << std::endl
;
1292 if (_error
->PendingError() == true)
1298 delete Map
.UnGuard();
1299 *OutMap
= new MMap(*CacheF
,0);
1303 *OutMap
= Map
.UnGuard();
1310 // CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
1311 // ---------------------------------------------------------------------
1313 __deprecated
bool pkgMakeOnlyStatusCache(OpProgress
&Progress
,DynamicMMap
**OutMap
)
1314 { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress
, OutMap
); }
1315 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress
*Progress
,DynamicMMap
**OutMap
)
1317 vector
<pkgIndexFile
*> Files
;
1318 unsigned long EndOfSource
= Files
.size();
1319 if (_system
->AddStatusFiles(Files
) == false)
1322 SPtr
<DynamicMMap
> Map
= CreateDynamicMMap(NULL
);
1323 unsigned long CurrentSize
= 0;
1324 unsigned long TotalSize
= 0;
1326 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1328 // Build the status cache
1329 if (Progress
!= NULL
)
1330 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1331 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1332 if (_error
->PendingError() == true)
1334 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1335 Files
.begin()+EndOfSource
,Files
.end()) == false)
1338 // FIXME: move me to a better place
1339 Gen
.FinishCache(Progress
);
1341 if (_error
->PendingError() == true)
1343 *OutMap
= Map
.UnGuard();