]>
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 Cache
.HeaderP
->CacheFileSize
= Map
.Size();
102 Map
.Sync(0,sizeof(pkgCache::Header
));
105 void pkgCacheGenerator::ReMap(void const * const oldMap
, void const * const newMap
) {/*{{{*/
106 if (oldMap
== newMap
)
111 CurrentFile
+= (pkgCache::PackageFile
*) newMap
- (pkgCache::PackageFile
*) oldMap
;
113 for (size_t i
= 0; i
< _count(UniqHash
); ++i
)
114 if (UniqHash
[i
] != 0)
115 UniqHash
[i
] += (pkgCache::StringItem
*) newMap
- (pkgCache::StringItem
*) oldMap
;
117 for (std::vector
<pkgCache::GrpIterator
*>::const_iterator i
= Dynamic
<pkgCache::GrpIterator
>::toReMap
.begin();
118 i
!= Dynamic
<pkgCache::GrpIterator
>::toReMap
.end(); ++i
)
119 (*i
)->ReMap(oldMap
, newMap
);
120 for (std::vector
<pkgCache::PkgIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgIterator
>::toReMap
.begin();
121 i
!= Dynamic
<pkgCache::PkgIterator
>::toReMap
.end(); ++i
)
122 (*i
)->ReMap(oldMap
, newMap
);
123 for (std::vector
<pkgCache::VerIterator
*>::const_iterator i
= Dynamic
<pkgCache::VerIterator
>::toReMap
.begin();
124 i
!= Dynamic
<pkgCache::VerIterator
>::toReMap
.end(); ++i
)
125 (*i
)->ReMap(oldMap
, newMap
);
126 for (std::vector
<pkgCache::DepIterator
*>::const_iterator i
= Dynamic
<pkgCache::DepIterator
>::toReMap
.begin();
127 i
!= Dynamic
<pkgCache::DepIterator
>::toReMap
.end(); ++i
)
128 (*i
)->ReMap(oldMap
, newMap
);
129 for (std::vector
<pkgCache::DescIterator
*>::const_iterator i
= Dynamic
<pkgCache::DescIterator
>::toReMap
.begin();
130 i
!= Dynamic
<pkgCache::DescIterator
>::toReMap
.end(); ++i
)
131 (*i
)->ReMap(oldMap
, newMap
);
132 for (std::vector
<pkgCache::PrvIterator
*>::const_iterator i
= Dynamic
<pkgCache::PrvIterator
>::toReMap
.begin();
133 i
!= Dynamic
<pkgCache::PrvIterator
>::toReMap
.end(); ++i
)
134 (*i
)->ReMap(oldMap
, newMap
);
135 for (std::vector
<pkgCache::PkgFileIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.begin();
136 i
!= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.end(); ++i
)
137 (*i
)->ReMap(oldMap
, newMap
);
139 // CacheGenerator::WriteStringInMap /*{{{*/
140 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
,
141 const unsigned long &Len
) {
142 void const * const oldMap
= Map
.Data();
143 map_ptrloc
const index
= Map
.WriteString(String
, Len
);
145 ReMap(oldMap
, Map
.Data());
149 // CacheGenerator::WriteStringInMap /*{{{*/
150 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
) {
151 void const * const oldMap
= Map
.Data();
152 map_ptrloc
const index
= Map
.WriteString(String
);
154 ReMap(oldMap
, Map
.Data());
158 map_ptrloc
pkgCacheGenerator::AllocateInMap(const unsigned long &size
) {/*{{{*/
159 void const * const oldMap
= Map
.Data();
160 map_ptrloc
const index
= Map
.Allocate(size
);
162 ReMap(oldMap
, Map
.Data());
166 // CacheGenerator::MergeList - Merge the package list /*{{{*/
167 // ---------------------------------------------------------------------
168 /* This provides the generation of the entries in the cache. Each loop
169 goes through a single package record from the underlying parse engine. */
170 bool pkgCacheGenerator::MergeList(ListParser
&List
,
171 pkgCache::VerIterator
*OutVer
)
175 unsigned int Counter
= 0;
176 while (List
.Step() == true)
178 string
const PackageName
= List
.Package();
179 if (PackageName
.empty() == true)
182 string
const Arch
= List
.Architecture();
184 // Get a pointer to the package structure
185 pkgCache::PkgIterator Pkg
;
186 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
187 if (NewPackage(Pkg
, PackageName
, Arch
) == false)
188 return _error
->Error(_("Error occurred while processing %s (NewPackage)"),PackageName
.c_str());
190 if (Counter
% 100 == 0 && Progress
!= 0)
191 Progress
->Progress(List
.Offset());
193 /* Get a pointer to the version structure. We know the list is sorted
194 so we use that fact in the search. Insertion of new versions is
195 done with correct sorting */
196 string Version
= List
.Version();
197 if (Version
.empty() == true)
199 // we first process the package, then the descriptions
200 // (this has the bonus that we get MMap error when we run out
202 pkgCache::VerIterator
Ver(Cache
);
203 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
204 if (List
.UsePackage(Pkg
, Ver
) == false)
205 return _error
->Error(_("Error occurred while processing %s (UsePackage1)"),
206 PackageName
.c_str());
208 // Find the right version to write the description
209 MD5SumValue CurMd5
= List
.Description_md5();
210 Ver
= Pkg
.VersionList();
212 for (; Ver
.end() == false; ++Ver
)
214 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
215 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
216 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
217 bool duplicate
=false;
219 // don't add a new description if we have one for the given
221 for ( ; Desc
.end() == false; Desc
++)
222 if (MD5SumValue(Desc
.md5()) == CurMd5
&&
223 Desc
.LanguageCode() == List
.DescriptionLanguage())
228 for (Desc
= Ver
.DescriptionList();
230 LastDesc
= &Desc
->NextDesc
, Desc
++)
232 if (MD5SumValue(Desc
.md5()) == CurMd5
)
234 // Add new description
235 void const * const oldMap
= Map
.Data();
236 map_ptrloc
const descindex
= NewDescription(Desc
, List
.DescriptionLanguage(), CurMd5
, *LastDesc
);
237 if (oldMap
!= Map
.Data())
238 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
239 *LastDesc
= descindex
;
240 Desc
->ParentPkg
= Pkg
.Index();
242 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
243 return _error
->Error(_("Error occurred while processing %s (NewFileDesc1)"),PackageName
.c_str());
252 pkgCache::VerIterator Ver
= Pkg
.VersionList();
253 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
254 map_ptrloc
*LastVer
= &Pkg
->VersionList
;
255 void const * oldMap
= Map
.Data();
257 unsigned long const Hash
= List
.VersionHash();
258 for (; Ver
.end() == false; LastVer
= &Ver
->NextVer
, Ver
++)
260 Res
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr());
261 // Version is higher as current version - insert here
264 // Versionstrings are equal - is hash also equal?
265 if (Res
== 0 && Ver
->Hash
== Hash
)
267 // proceed with the next till we have either the right
268 // or we found another version (which will be lower)
271 /* We already have a version for this item, record that we saw it */
272 if (Res
== 0 && Ver
.end() == false && Ver
->Hash
== Hash
)
274 if (List
.UsePackage(Pkg
,Ver
) == false)
275 return _error
->Error(_("Error occurred while processing %s (UsePackage2)"),
276 PackageName
.c_str());
278 if (NewFileVer(Ver
,List
) == false)
279 return _error
->Error(_("Error occurred while processing %s (NewFileVer1)"),
280 PackageName
.c_str());
282 // Read only a single record and return
286 FoundFileDeps
|= List
.HasFileDeps();
294 map_ptrloc
const verindex
= NewVersion(Ver
,Version
,*LastVer
);
295 if (verindex
== 0 && _error
->PendingError())
296 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
297 PackageName
.c_str(), 1);
299 if (oldMap
!= Map
.Data())
300 LastVer
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
302 Ver
->ParentPkg
= Pkg
.Index();
305 if (List
.NewVersion(Ver
) == false)
306 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
307 PackageName
.c_str(), 2);
309 if (List
.UsePackage(Pkg
,Ver
) == false)
310 return _error
->Error(_("Error occurred while processing %s (UsePackage3)"),
311 PackageName
.c_str());
313 if (NewFileVer(Ver
,List
) == false)
314 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
315 PackageName
.c_str(), 3);
317 // Read only a single record and return
321 FoundFileDeps
|= List
.HasFileDeps();
325 /* Record the Description data. Description data always exist in
326 Packages and Translation-* files. */
327 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
328 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
329 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
331 // Skip to the end of description set
332 for (; Desc
.end() == false; LastDesc
= &Desc
->NextDesc
, Desc
++);
334 // Add new description
336 map_ptrloc
const descindex
= NewDescription(Desc
, List
.DescriptionLanguage(), List
.Description_md5(), *LastDesc
);
337 if (oldMap
!= Map
.Data())
338 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
339 *LastDesc
= descindex
;
340 Desc
->ParentPkg
= Pkg
.Index();
342 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
343 return _error
->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName
.c_str());
346 FoundFileDeps
|= List
.HasFileDeps();
348 if (Cache
.HeaderP
->PackageCount
>= (1ULL<<sizeof(Cache
.PkgP
->ID
)*8)-1)
349 return _error
->Error(_("Wow, you exceeded the number of package "
350 "names this APT is capable of."));
351 if (Cache
.HeaderP
->VersionCount
>= (1ULL<<(sizeof(Cache
.VerP
->ID
)*8))-1)
352 return _error
->Error(_("Wow, you exceeded the number of versions "
353 "this APT is capable of."));
354 if (Cache
.HeaderP
->DescriptionCount
>= (1ULL<<(sizeof(Cache
.DescP
->ID
)*8))-1)
355 return _error
->Error(_("Wow, you exceeded the number of descriptions "
356 "this APT is capable of."));
357 if (Cache
.HeaderP
->DependsCount
>= (1ULL<<(sizeof(Cache
.DepP
->ID
)*8))-1ULL)
358 return _error
->Error(_("Wow, you exceeded the number of dependencies "
359 "this APT is capable of."));
363 // CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/
364 // ---------------------------------------------------------------------
365 /* If we found any file depends while parsing the main list we need to
366 resolve them. Since it is undesired to load the entire list of files
367 into the cache as virtual packages we do a two stage effort. MergeList
368 identifies the file depends and this creates Provdies for them by
369 re-parsing all the indexs. */
370 bool pkgCacheGenerator::MergeFileProvides(ListParser
&List
)
374 unsigned int Counter
= 0;
375 while (List
.Step() == true)
377 string PackageName
= List
.Package();
378 if (PackageName
.empty() == true)
380 string Version
= List
.Version();
381 if (Version
.empty() == true)
384 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(PackageName
);
385 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
386 if (Pkg
.end() == true)
387 return _error
->Error(_("Error occurred while processing %s (FindPkg)"),
388 PackageName
.c_str());
390 if (Counter
% 100 == 0 && Progress
!= 0)
391 Progress
->Progress(List
.Offset());
393 unsigned long Hash
= List
.VersionHash();
394 pkgCache::VerIterator Ver
= Pkg
.VersionList();
395 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
396 for (; Ver
.end() == false; Ver
++)
398 if (Ver
->Hash
== Hash
&& Version
.c_str() == Ver
.VerStr())
400 if (List
.CollectFileProvides(Cache
,Ver
) == false)
401 return _error
->Error(_("Error occurred while processing %s (CollectFileProvides)"),PackageName
.c_str());
406 if (Ver
.end() == true)
407 _error
->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName
.c_str(),Version
.c_str());
413 // CacheGenerator::NewGroup - Add a new group /*{{{*/
414 // ---------------------------------------------------------------------
415 /* This creates a new group structure and adds it to the hash table */
416 bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator
&Grp
, const string
&Name
)
418 Grp
= Cache
.FindGrp(Name
);
419 if (Grp
.end() == false)
423 map_ptrloc
const Group
= AllocateInMap(sizeof(pkgCache::Group
));
424 if (unlikely(Group
== 0))
427 Grp
= pkgCache::GrpIterator(Cache
, Cache
.GrpP
+ Group
);
428 map_ptrloc
const idxName
= WriteStringInMap(Name
);
429 if (unlikely(idxName
== 0))
433 // Insert it into the hash table
434 unsigned long const Hash
= Cache
.Hash(Name
);
435 Grp
->Next
= Cache
.HeaderP
->GrpHashTable
[Hash
];
436 Cache
.HeaderP
->GrpHashTable
[Hash
] = Group
;
438 Grp
->ID
= Cache
.HeaderP
->GroupCount
++;
442 // CacheGenerator::NewPackage - Add a new package /*{{{*/
443 // ---------------------------------------------------------------------
444 /* This creates a new package structure and adds it to the hash table */
445 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator
&Pkg
,const string
&Name
,
446 const string
&Arch
) {
447 pkgCache::GrpIterator Grp
;
448 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
449 if (unlikely(NewGroup(Grp
, Name
) == false))
452 Pkg
= Grp
.FindPkg(Arch
);
453 if (Pkg
.end() == false)
457 map_ptrloc
const Package
= AllocateInMap(sizeof(pkgCache::Package
));
458 if (unlikely(Package
== 0))
460 Pkg
= pkgCache::PkgIterator(Cache
,Cache
.PkgP
+ Package
);
462 // Insert the package into our package list
463 if (Grp
->FirstPackage
== 0) // the group is new
465 // Insert it into the hash table
466 unsigned long const Hash
= Cache
.Hash(Name
);
467 Pkg
->NextPackage
= Cache
.HeaderP
->PkgHashTable
[Hash
];
468 Cache
.HeaderP
->PkgHashTable
[Hash
] = Package
;
469 Grp
->FirstPackage
= Package
;
471 else // Group the Packages together
473 // this package is the new last package
474 pkgCache::PkgIterator
LastPkg(Cache
, Cache
.PkgP
+ Grp
->LastPackage
);
475 Pkg
->NextPackage
= LastPkg
->NextPackage
;
476 LastPkg
->NextPackage
= Package
;
478 Grp
->LastPackage
= Package
;
480 // Set the name, arch and the ID
481 Pkg
->Name
= Grp
->Name
;
482 Pkg
->Group
= Grp
.Index();
483 // all is mapped to the native architecture
484 map_ptrloc
const idxArch
= (Arch
== "all") ? Cache
.HeaderP
->Architecture
: WriteUniqString(Arch
.c_str());
485 if (unlikely(idxArch
== 0))
488 Pkg
->ID
= Cache
.HeaderP
->PackageCount
++;
493 // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
494 // ---------------------------------------------------------------------
496 bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator
&Ver
,
499 if (CurrentFile
== 0)
503 map_ptrloc
const VerFile
= AllocateInMap(sizeof(pkgCache::VerFile
));
507 pkgCache::VerFileIterator
VF(Cache
,Cache
.VerFileP
+ VerFile
);
508 VF
->File
= CurrentFile
- Cache
.PkgFileP
;
510 // Link it to the end of the list
511 map_ptrloc
*Last
= &Ver
->FileList
;
512 for (pkgCache::VerFileIterator V
= Ver
.FileList(); V
.end() == false; V
++)
514 VF
->NextFile
= *Last
;
517 VF
->Offset
= List
.Offset();
518 VF
->Size
= List
.Size();
519 if (Cache
.HeaderP
->MaxVerFileSize
< VF
->Size
)
520 Cache
.HeaderP
->MaxVerFileSize
= VF
->Size
;
521 Cache
.HeaderP
->VerFileCount
++;
526 // CacheGenerator::NewVersion - Create a new Version /*{{{*/
527 // ---------------------------------------------------------------------
528 /* This puts a version structure in the linked list */
529 unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator
&Ver
,
530 const string
&VerStr
,
534 map_ptrloc
const Version
= AllocateInMap(sizeof(pkgCache::Version
));
539 Ver
= pkgCache::VerIterator(Cache
,Cache
.VerP
+ Version
);
541 Ver
->ID
= Cache
.HeaderP
->VersionCount
++;
542 map_ptrloc
const idxVerStr
= WriteStringInMap(VerStr
);
543 if (unlikely(idxVerStr
== 0))
545 Ver
->VerStr
= idxVerStr
;
550 // CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/
551 // ---------------------------------------------------------------------
553 bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator
&Desc
,
556 if (CurrentFile
== 0)
560 map_ptrloc
const DescFile
= AllocateInMap(sizeof(pkgCache::DescFile
));
564 pkgCache::DescFileIterator
DF(Cache
,Cache
.DescFileP
+ DescFile
);
565 DF
->File
= CurrentFile
- Cache
.PkgFileP
;
567 // Link it to the end of the list
568 map_ptrloc
*Last
= &Desc
->FileList
;
569 for (pkgCache::DescFileIterator D
= Desc
.FileList(); D
.end() == false; D
++)
572 DF
->NextFile
= *Last
;
575 DF
->Offset
= List
.Offset();
576 DF
->Size
= List
.Size();
577 if (Cache
.HeaderP
->MaxDescFileSize
< DF
->Size
)
578 Cache
.HeaderP
->MaxDescFileSize
= DF
->Size
;
579 Cache
.HeaderP
->DescFileCount
++;
584 // CacheGenerator::NewDescription - Create a new Description /*{{{*/
585 // ---------------------------------------------------------------------
586 /* This puts a description structure in the linked list */
587 map_ptrloc
pkgCacheGenerator::NewDescription(pkgCache::DescIterator
&Desc
,
589 const MD5SumValue
&md5sum
,
593 map_ptrloc
const Description
= AllocateInMap(sizeof(pkgCache::Description
));
594 if (Description
== 0)
598 Desc
= pkgCache::DescIterator(Cache
,Cache
.DescP
+ Description
);
599 Desc
->NextDesc
= Next
;
600 Desc
->ID
= Cache
.HeaderP
->DescriptionCount
++;
601 map_ptrloc
const idxlanguage_code
= WriteStringInMap(Lang
);
602 map_ptrloc
const idxmd5sum
= WriteStringInMap(md5sum
.Value());
603 if (unlikely(idxlanguage_code
== 0 || idxmd5sum
== 0))
605 Desc
->language_code
= idxlanguage_code
;
606 Desc
->md5sum
= idxmd5sum
;
611 // CacheGenerator::FinishCache - do various finish operations /*{{{*/
612 // ---------------------------------------------------------------------
613 /* This prepares the Cache for delivery */
614 bool pkgCacheGenerator::FinishCache(OpProgress
*Progress
)
616 // FIXME: add progress reporting for this operation
617 // Do we have different architectures in your groups ?
618 vector
<string
> archs
= APT::Configuration::getArchitectures();
619 if (archs
.size() > 1)
621 // Create Conflicts in between the group
622 pkgCache::GrpIterator G
= GetCache().GrpBegin();
623 Dynamic
<pkgCache::GrpIterator
> DynG(G
);
624 for (; G
.end() != true; G
++)
626 string
const PkgName
= G
.Name();
627 pkgCache::PkgIterator P
= G
.PackageList();
628 Dynamic
<pkgCache::PkgIterator
> DynP(P
);
629 for (; P
.end() != true; P
= G
.NextPkg(P
))
631 pkgCache::PkgIterator allPkg
;
632 Dynamic
<pkgCache::PkgIterator
> DynallPkg(allPkg
);
633 pkgCache::VerIterator V
= P
.VersionList();
634 Dynamic
<pkgCache::VerIterator
> DynV(V
);
635 for (; V
.end() != true; V
++)
637 char const * const Arch
= P
.Arch();
638 map_ptrloc
*OldDepLast
= NULL
;
639 /* MultiArch handling introduces a lot of implicit Dependencies:
640 - MultiArch: same → Co-Installable if they have the same version
641 - Architecture: all → Need to be Co-Installable for internal reasons
642 - All others conflict with all other group members */
643 bool const coInstall
= ((V
->MultiArch
& pkgCache::Version::Same
) == pkgCache::Version::Same
);
644 for (vector
<string
>::const_iterator A
= archs
.begin(); A
!= archs
.end(); ++A
)
646 if (Arch
== 0 || *A
== Arch
)
648 /* We allow only one installed arch at the time
649 per group, therefore each group member conflicts
650 with all other group members */
651 pkgCache::PkgIterator D
= G
.FindPkg(*A
);
652 Dynamic
<pkgCache::PkgIterator
> DynD(D
);
655 if (coInstall
== true)
657 // Replaces: ${self}:other ( << ${binary:Version})
658 NewDepends(D
, V
, V
.VerStr(),
659 pkgCache::Dep::Less
, pkgCache::Dep::Replaces
,
661 // Breaks: ${self}:other (!= ${binary:Version})
662 NewDepends(D
, V
, V
.VerStr(),
663 pkgCache::Dep::NotEquals
, pkgCache::Dep::DpkgBreaks
,
666 // Conflicts: ${self}:other
668 pkgCache::Dep::NoOp
, pkgCache::Dep::Conflicts
,
679 // CacheGenerator::NewDepends - Create a dependency element /*{{{*/
680 // ---------------------------------------------------------------------
681 /* This creates a dependency element in the tree. It is linked to the
682 version and to the package that it is pointing to. */
683 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator
&Pkg
,
684 pkgCache::VerIterator
&Ver
,
685 string
const &Version
,
686 unsigned int const &Op
,
687 unsigned int const &Type
,
688 map_ptrloc
*OldDepLast
)
690 void const * const oldMap
= Map
.Data();
692 map_ptrloc
const Dependency
= AllocateInMap(sizeof(pkgCache::Dependency
));
693 if (unlikely(Dependency
== 0))
697 pkgCache::DepIterator
Dep(Cache
,Cache
.DepP
+ Dependency
);
698 Dynamic
<pkgCache::DepIterator
> DynDep(Dep
);
699 Dep
->ParentVer
= Ver
.Index();
702 Dep
->ID
= Cache
.HeaderP
->DependsCount
++;
704 // Probe the reverse dependency list for a version string that matches
705 if (Version
.empty() == false)
707 /* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
708 if (I->Version != 0 && I.TargetVer() == Version)
709 Dep->Version = I->Version;*/
710 if (Dep
->Version
== 0) {
711 map_ptrloc
const index
= WriteStringInMap(Version
);
712 if (unlikely(index
== 0))
714 Dep
->Version
= index
;
718 // Link it to the package
719 Dep
->Package
= Pkg
.Index();
720 Dep
->NextRevDepends
= Pkg
->RevDepends
;
721 Pkg
->RevDepends
= Dep
.Index();
723 // Do we know where to link the Dependency to?
724 if (OldDepLast
== NULL
)
726 OldDepLast
= &Ver
->DependsList
;
727 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
728 OldDepLast
= &D
->NextDepends
;
729 } else if (oldMap
!= Map
.Data())
730 OldDepLast
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
732 Dep
->NextDepends
= *OldDepLast
;
733 *OldDepLast
= Dep
.Index();
734 OldDepLast
= &Dep
->NextDepends
;
739 // ListParser::NewDepends - Create the environment for a new dependency /*{{{*/
740 // ---------------------------------------------------------------------
741 /* This creates a Group and the Package to link this dependency to if
742 needed and handles also the caching of the old endpoint */
743 bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator
&Ver
,
744 const string
&PackageName
,
746 const string
&Version
,
750 pkgCache::GrpIterator Grp
;
751 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
752 if (unlikely(Owner
->NewGroup(Grp
, PackageName
) == false))
755 // Locate the target package
756 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(Arch
);
757 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
758 if (Pkg
.end() == true) {
759 if (unlikely(Owner
->NewPackage(Pkg
, PackageName
, Arch
) == false))
763 // Is it a file dependency?
764 if (unlikely(PackageName
[0] == '/'))
765 FoundFileDeps
= true;
767 /* Caching the old end point speeds up generation substantially */
768 if (OldDepVer
!= Ver
) {
773 return Owner
->NewDepends(Pkg
, Ver
, Version
, Op
, Type
, OldDepLast
);
776 // ListParser::NewProvides - Create a Provides element /*{{{*/
777 // ---------------------------------------------------------------------
779 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator
&Ver
,
780 const string
&PkgName
,
781 const string
&PkgArch
,
782 const string
&Version
)
784 pkgCache
&Cache
= Owner
->Cache
;
786 // We do not add self referencing provides
787 if (Ver
.ParentPkg().Name() == PkgName
&& (PkgArch
== Ver
.ParentPkg().Arch() ||
788 (PkgArch
== "all" && strcmp((Cache
.StrP
+ Cache
.HeaderP
->Architecture
), Ver
.ParentPkg().Arch()) == 0)))
792 map_ptrloc
const Provides
= Owner
->AllocateInMap(sizeof(pkgCache::Provides
));
793 if (unlikely(Provides
== 0))
795 Cache
.HeaderP
->ProvidesCount
++;
798 pkgCache::PrvIterator
Prv(Cache
,Cache
.ProvideP
+ Provides
,Cache
.PkgP
);
799 Dynamic
<pkgCache::PrvIterator
> DynPrv(Prv
);
800 Prv
->Version
= Ver
.Index();
801 Prv
->NextPkgProv
= Ver
->ProvidesList
;
802 Ver
->ProvidesList
= Prv
.Index();
803 if (Version
.empty() == false && unlikely((Prv
->ProvideVersion
= WriteString(Version
)) == 0))
806 // Locate the target package
807 pkgCache::PkgIterator Pkg
;
808 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
809 if (unlikely(Owner
->NewPackage(Pkg
,PkgName
, PkgArch
) == false))
812 // Link it to the package
813 Prv
->ParentPkg
= Pkg
.Index();
814 Prv
->NextProvides
= Pkg
->ProvidesList
;
815 Pkg
->ProvidesList
= Prv
.Index();
820 // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
821 // ---------------------------------------------------------------------
822 /* This is used to select which file is to be associated with all newly
823 added versions. The caller is responsible for setting the IMS fields. */
824 bool pkgCacheGenerator::SelectFile(const string
&File
,const string
&Site
,
825 const pkgIndexFile
&Index
,
828 // Get some space for the structure
829 map_ptrloc
const idxFile
= AllocateInMap(sizeof(*CurrentFile
));
830 if (unlikely(idxFile
== 0))
832 CurrentFile
= Cache
.PkgFileP
+ idxFile
;
835 map_ptrloc
const idxFileName
= WriteStringInMap(File
);
836 map_ptrloc
const idxSite
= WriteUniqString(Site
);
837 if (unlikely(idxFileName
== 0 || idxSite
== 0))
839 CurrentFile
->FileName
= idxFileName
;
840 CurrentFile
->Site
= idxSite
;
841 CurrentFile
->NextFile
= Cache
.HeaderP
->FileList
;
842 CurrentFile
->Flags
= Flags
;
843 CurrentFile
->ID
= Cache
.HeaderP
->PackageFileCount
;
844 map_ptrloc
const idxIndexType
= WriteUniqString(Index
.GetType()->Label
);
845 if (unlikely(idxIndexType
== 0))
847 CurrentFile
->IndexType
= idxIndexType
;
849 Cache
.HeaderP
->FileList
= CurrentFile
- Cache
.PkgFileP
;
850 Cache
.HeaderP
->PackageFileCount
++;
853 Progress
->SubProgress(Index
.Size());
857 // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
858 // ---------------------------------------------------------------------
859 /* This is used to create handles to strings. Given the same text it
860 always returns the same number */
861 unsigned long pkgCacheGenerator::WriteUniqString(const char *S
,
864 /* We use a very small transient hash table here, this speeds up generation
865 by a fair amount on slower machines */
866 pkgCache::StringItem
*&Bucket
= UniqHash
[(S
[0]*5 + S
[1]) % _count(UniqHash
)];
868 stringcmp(S
,S
+Size
,Cache
.StrP
+ Bucket
->String
) == 0)
869 return Bucket
->String
;
871 // Search for an insertion point
872 pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.HeaderP
->StringList
;
874 map_ptrloc
*Last
= &Cache
.HeaderP
->StringList
;
875 for (; I
!= Cache
.StringItemP
; Last
= &I
->NextItem
,
876 I
= Cache
.StringItemP
+ I
->NextItem
)
878 Res
= stringcmp(S
,S
+Size
,Cache
.StrP
+ I
->String
);
891 void const * const oldMap
= Map
.Data();
892 map_ptrloc
const Item
= AllocateInMap(sizeof(pkgCache::StringItem
));
896 map_ptrloc
const idxString
= WriteStringInMap(S
,Size
);
897 if (unlikely(idxString
== 0))
899 if (oldMap
!= Map
.Data()) {
900 Last
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
901 I
+= (pkgCache::StringItem
*) Map
.Data() - (pkgCache::StringItem
*) oldMap
;
905 // Fill in the structure
906 pkgCache::StringItem
*ItemP
= Cache
.StringItemP
+ Item
;
907 ItemP
->NextItem
= I
- Cache
.StringItemP
;
908 ItemP
->String
= idxString
;
911 return ItemP
->String
;
914 // CheckValidity - Check that a cache is up-to-date /*{{{*/
915 // ---------------------------------------------------------------------
916 /* This just verifies that each file in the list of index files exists,
917 has matching attributes with the cache and the cache does not have
919 static bool CheckValidity(const string
&CacheFile
,
925 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
926 // No file, certainly invalid
927 if (CacheFile
.empty() == true || FileExists(CacheFile
) == false)
930 std::clog
<< "CacheFile doesn't exist" << std::endl
;
934 if (List
.GetLastModifiedTime() < GetModificationTime(CacheFile
))
937 std::clog
<< "sources.list is newer than the cache" << std::endl
;
942 FileFd
CacheF(CacheFile
,FileFd::ReadOnly
);
943 SPtr
<MMap
> Map
= new MMap(CacheF
,0);
945 if (_error
->PendingError() == true || Map
->Size() == 0)
948 std::clog
<< "Errors are pending or Map is empty()" << std::endl
;
953 /* Now we check every index file, see if it is in the cache,
954 verify the IMS data and check that it is on the disk too.. */
955 SPtrArray
<bool> Visited
= new bool[Cache
.HeaderP
->PackageFileCount
];
956 memset(Visited
,0,sizeof(*Visited
)*Cache
.HeaderP
->PackageFileCount
);
957 for (; Start
!= End
; Start
++)
960 std::clog
<< "Checking PkgFile " << (*Start
)->Describe() << ": ";
961 if ((*Start
)->HasPackages() == false)
964 std::clog
<< "Has NO packages" << std::endl
;
968 if ((*Start
)->Exists() == false)
970 #if 0 // mvo: we no longer give a message here (Default Sources spec)
971 _error
->WarningE("stat",_("Couldn't stat source package list %s"),
972 (*Start
)->Describe().c_str());
975 std::clog
<< "file doesn't exist" << std::endl
;
979 // FindInCache is also expected to do an IMS check.
980 pkgCache::PkgFileIterator File
= (*Start
)->FindInCache(Cache
);
981 if (File
.end() == true)
984 std::clog
<< "FindInCache returned end-Pointer" << std::endl
;
988 Visited
[File
->ID
] = true;
990 std::clog
<< "with ID " << File
->ID
<< " is valid" << std::endl
;
993 for (unsigned I
= 0; I
!= Cache
.HeaderP
->PackageFileCount
; I
++)
994 if (Visited
[I
] == false)
997 std::clog
<< "File with ID" << I
<< " wasn't visited" << std::endl
;
1001 if (_error
->PendingError() == true)
1005 std::clog
<< "Validity failed because of pending errors:" << std::endl
;
1006 _error
->DumpErrors();
1013 *OutMap
= Map
.UnGuard();
1017 // ComputeSize - Compute the total size of a bunch of files /*{{{*/
1018 // ---------------------------------------------------------------------
1019 /* Size is kind of an abstract notion that is only used for the progress
1021 static unsigned long ComputeSize(FileIterator Start
,FileIterator End
)
1023 unsigned long TotalSize
= 0;
1024 for (; Start
!= End
; Start
++)
1026 if ((*Start
)->HasPackages() == false)
1028 TotalSize
+= (*Start
)->Size();
1033 // BuildCache - Merge the list of index files into the cache /*{{{*/
1034 // ---------------------------------------------------------------------
1036 static bool BuildCache(pkgCacheGenerator
&Gen
,
1037 OpProgress
*Progress
,
1038 unsigned long &CurrentSize
,unsigned long TotalSize
,
1039 FileIterator Start
, FileIterator End
)
1042 for (I
= Start
; I
!= End
; I
++)
1044 if ((*I
)->HasPackages() == false)
1047 if ((*I
)->Exists() == false)
1050 if ((*I
)->FindInCache(Gen
.GetCache()).end() == false)
1052 _error
->Warning("Duplicate sources.list entry %s",
1053 (*I
)->Describe().c_str());
1057 unsigned long Size
= (*I
)->Size();
1058 if (Progress
!= NULL
)
1059 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Reading package lists"));
1060 CurrentSize
+= Size
;
1062 if ((*I
)->Merge(Gen
,Progress
) == false)
1066 if (Gen
.HasFileDeps() == true)
1068 if (Progress
!= NULL
)
1070 TotalSize
= ComputeSize(Start
, End
);
1072 for (I
= Start
; I
!= End
; I
++)
1074 unsigned long Size
= (*I
)->Size();
1075 if (Progress
!= NULL
)
1076 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Collecting File Provides"));
1077 CurrentSize
+= Size
;
1078 if ((*I
)->MergeFileProvides(Gen
,Progress
) == false)
1086 // CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/
1087 DynamicMMap
* pkgCacheGenerator::CreateDynamicMMap(FileFd
*CacheF
, unsigned long Flags
) {
1088 unsigned long const MapStart
= _config
->FindI("APT::Cache-Start", 24*1024*1024);
1089 unsigned long const MapGrow
= _config
->FindI("APT::Cache-Grow", 1*1024*1024);
1090 unsigned long const MapLimit
= _config
->FindI("APT::Cache-Limit", 0);
1091 Flags
|= MMap::Moveable
;
1092 if (_config
->FindB("APT::Cache-Fallback", false) == true)
1093 Flags
|= MMap::Fallback
;
1095 return new DynamicMMap(*CacheF
, Flags
, MapStart
, MapGrow
, MapLimit
);
1097 return new DynamicMMap(Flags
, MapStart
, MapGrow
, MapLimit
);
1100 // CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
1101 // ---------------------------------------------------------------------
1102 /* This makes sure that the status cache (the cache that has all
1103 index files from the sources list and all local ones) is ready
1104 to be mmaped. If OutMap is not zero then a MMap object representing
1105 the cache will be stored there. This is pretty much mandetory if you
1106 are using AllowMem. AllowMem lets the function be run as non-root
1107 where it builds the cache 'fast' into a memory buffer. */
1108 __deprecated
bool pkgMakeStatusCache(pkgSourceList
&List
,OpProgress
&Progress
,
1109 MMap
**OutMap
, bool AllowMem
)
1110 { return pkgCacheGenerator::MakeStatusCache(List
, &Progress
, OutMap
, AllowMem
); }
1111 bool pkgCacheGenerator::MakeStatusCache(pkgSourceList
&List
,OpProgress
*Progress
,
1112 MMap
**OutMap
,bool AllowMem
)
1114 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
1116 vector
<pkgIndexFile
*> Files
;
1117 for (vector
<metaIndex
*>::const_iterator i
= List
.begin();
1121 vector
<pkgIndexFile
*> *Indexes
= (*i
)->GetIndexFiles();
1122 for (vector
<pkgIndexFile
*>::const_iterator j
= Indexes
->begin();
1123 j
!= Indexes
->end();
1125 Files
.push_back (*j
);
1128 unsigned long const EndOfSource
= Files
.size();
1129 if (_system
->AddStatusFiles(Files
) == false)
1132 // Decide if we can write to the files..
1133 string
const CacheFile
= _config
->FindFile("Dir::Cache::pkgcache");
1134 string
const SrcCacheFile
= _config
->FindFile("Dir::Cache::srcpkgcache");
1136 // ensure the cache directory exists
1137 if (CacheFile
.empty() == false || SrcCacheFile
.empty() == false)
1139 string dir
= _config
->FindDir("Dir::Cache");
1140 size_t const len
= dir
.size();
1141 if (len
> 5 && dir
.find("/apt/", len
- 6, 5) == len
- 5)
1142 dir
= dir
.substr(0, len
- 5);
1143 if (CacheFile
.empty() == false)
1144 CreateDirectory(dir
, flNotFile(CacheFile
));
1145 if (SrcCacheFile
.empty() == false)
1146 CreateDirectory(dir
, flNotFile(SrcCacheFile
));
1149 // Decide if we can write to the cache
1150 bool Writeable
= false;
1151 if (CacheFile
.empty() == false)
1152 Writeable
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0;
1154 if (SrcCacheFile
.empty() == false)
1155 Writeable
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0;
1157 std::clog
<< "Do we have write-access to the cache files? " << (Writeable
? "YES" : "NO") << std::endl
;
1159 if (Writeable
== false && AllowMem
== false && CacheFile
.empty() == false)
1160 return _error
->Error(_("Unable to write to %s"),flNotFile(CacheFile
).c_str());
1162 if (Progress
!= NULL
)
1163 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1165 // Cache is OK, Fin.
1166 if (CheckValidity(CacheFile
, List
, Files
.begin(),Files
.end(),OutMap
) == true)
1168 if (Progress
!= NULL
)
1169 Progress
->OverallProgress(1,1,1,_("Reading package lists"));
1171 std::clog
<< "pkgcache.bin is valid - no need to build anything" << std::endl
;
1174 else if (Debug
== true)
1175 std::clog
<< "pkgcache.bin is NOT valid" << std::endl
;
1177 /* At this point we know we need to reconstruct the package cache,
1179 SPtr
<FileFd
> CacheF
;
1180 SPtr
<DynamicMMap
> Map
;
1181 if (Writeable
== true && CacheFile
.empty() == false)
1183 _error
->PushToStack();
1184 unlink(CacheFile
.c_str());
1185 CacheF
= new FileFd(CacheFile
,FileFd::WriteAtomic
);
1186 fchmod(CacheF
->Fd(),0644);
1187 Map
= CreateDynamicMMap(CacheF
, MMap::Public
);
1188 if (_error
->PendingError() == true)
1190 delete CacheF
.UnGuard();
1191 delete Map
.UnGuard();
1193 std::clog
<< "Open filebased MMap FAILED" << std::endl
;
1195 if (AllowMem
== false)
1197 _error
->MergeWithStack();
1200 _error
->RevertToStack();
1202 else if (Debug
== true)
1204 _error
->MergeWithStack();
1205 std::clog
<< "Open filebased MMap" << std::endl
;
1208 if (Writeable
== false || CacheFile
.empty() == true)
1210 // Just build it in memory..
1211 Map
= CreateDynamicMMap(NULL
);
1213 std::clog
<< "Open memory Map (not filebased)" << std::endl
;
1216 // Lets try the source cache.
1217 unsigned long CurrentSize
= 0;
1218 unsigned long TotalSize
= 0;
1219 if (CheckValidity(SrcCacheFile
, List
, Files
.begin(),
1220 Files
.begin()+EndOfSource
) == true)
1223 std::clog
<< "srcpkgcache.bin is valid - populate MMap with it." << std::endl
;
1224 // Preload the map with the source cache
1225 FileFd
SCacheF(SrcCacheFile
,FileFd::ReadOnly
);
1226 unsigned long const alloc
= Map
->RawAllocate(SCacheF
.Size());
1227 if ((alloc
== 0 && _error
->PendingError())
1228 || SCacheF
.Read((unsigned char *)Map
->Data() + alloc
,
1229 SCacheF
.Size()) == false)
1232 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1234 // Build the status cache
1235 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1236 if (_error
->PendingError() == true)
1238 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1239 Files
.begin()+EndOfSource
,Files
.end()) == false)
1242 // FIXME: move me to a better place
1243 Gen
.FinishCache(Progress
);
1248 std::clog
<< "srcpkgcache.bin is NOT valid - rebuild" << std::endl
;
1249 TotalSize
= ComputeSize(Files
.begin(),Files
.end());
1251 // Build the source cache
1252 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1253 if (_error
->PendingError() == true)
1255 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1256 Files
.begin(),Files
.begin()+EndOfSource
) == false)
1260 if (Writeable
== true && SrcCacheFile
.empty() == false)
1262 FileFd
SCacheF(SrcCacheFile
,FileFd::WriteAtomic
);
1263 if (_error
->PendingError() == true)
1266 fchmod(SCacheF
.Fd(),0644);
1268 // Write out the main data
1269 if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false)
1270 return _error
->Error(_("IO Error saving source cache"));
1273 // Write out the proper header
1274 Gen
.GetCache().HeaderP
->Dirty
= false;
1275 if (SCacheF
.Seek(0) == false ||
1276 SCacheF
.Write(Map
->Data(),sizeof(*Gen
.GetCache().HeaderP
)) == false)
1277 return _error
->Error(_("IO Error saving source cache"));
1278 Gen
.GetCache().HeaderP
->Dirty
= true;
1282 // Build the status cache
1283 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1284 Files
.begin()+EndOfSource
,Files
.end()) == false)
1287 // FIXME: move me to a better place
1288 Gen
.FinishCache(Progress
);
1291 std::clog
<< "Caches are ready for shipping" << std::endl
;
1293 if (_error
->PendingError() == true)
1299 delete Map
.UnGuard();
1300 *OutMap
= new MMap(*CacheF
,0);
1304 *OutMap
= Map
.UnGuard();
1311 // CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
1312 // ---------------------------------------------------------------------
1314 __deprecated
bool pkgMakeOnlyStatusCache(OpProgress
&Progress
,DynamicMMap
**OutMap
)
1315 { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress
, OutMap
); }
1316 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress
*Progress
,DynamicMMap
**OutMap
)
1318 vector
<pkgIndexFile
*> Files
;
1319 unsigned long EndOfSource
= Files
.size();
1320 if (_system
->AddStatusFiles(Files
) == false)
1323 SPtr
<DynamicMMap
> Map
= CreateDynamicMMap(NULL
);
1324 unsigned long CurrentSize
= 0;
1325 unsigned long TotalSize
= 0;
1327 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1329 // Build the status cache
1330 if (Progress
!= NULL
)
1331 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1332 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1333 if (_error
->PendingError() == true)
1335 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1336 Files
.begin()+EndOfSource
,Files
.end()) == false)
1339 // FIXME: move me to a better place
1340 Gen
.FinishCache(Progress
);
1342 if (_error
->PendingError() == true)
1344 *OutMap
= Map
.UnGuard();