]>
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 /*{{{*/
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>
26 #include <apt-pkg/tagfile.h>
27 #include <apt-pkg/metaindex.h>
28 #include <apt-pkg/fileutl.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
)
109 if (_config
->FindB("Debug::pkgCacheGen", false))
110 std::clog
<< "Remaping from " << oldMap
<< " to " << newMap
<< std::endl
;
114 CurrentFile
+= (pkgCache::PackageFile
*) newMap
- (pkgCache::PackageFile
*) oldMap
;
116 for (size_t i
= 0; i
< _count(UniqHash
); ++i
)
117 if (UniqHash
[i
] != 0)
118 UniqHash
[i
] += (pkgCache::StringItem
*) newMap
- (pkgCache::StringItem
*) oldMap
;
120 for (std::vector
<pkgCache::GrpIterator
*>::const_iterator i
= Dynamic
<pkgCache::GrpIterator
>::toReMap
.begin();
121 i
!= Dynamic
<pkgCache::GrpIterator
>::toReMap
.end(); ++i
)
122 (*i
)->ReMap(oldMap
, newMap
);
123 for (std::vector
<pkgCache::PkgIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgIterator
>::toReMap
.begin();
124 i
!= Dynamic
<pkgCache::PkgIterator
>::toReMap
.end(); ++i
)
125 (*i
)->ReMap(oldMap
, newMap
);
126 for (std::vector
<pkgCache::VerIterator
*>::const_iterator i
= Dynamic
<pkgCache::VerIterator
>::toReMap
.begin();
127 i
!= Dynamic
<pkgCache::VerIterator
>::toReMap
.end(); ++i
)
128 (*i
)->ReMap(oldMap
, newMap
);
129 for (std::vector
<pkgCache::DepIterator
*>::const_iterator i
= Dynamic
<pkgCache::DepIterator
>::toReMap
.begin();
130 i
!= Dynamic
<pkgCache::DepIterator
>::toReMap
.end(); ++i
)
131 (*i
)->ReMap(oldMap
, newMap
);
132 for (std::vector
<pkgCache::DescIterator
*>::const_iterator i
= Dynamic
<pkgCache::DescIterator
>::toReMap
.begin();
133 i
!= Dynamic
<pkgCache::DescIterator
>::toReMap
.end(); ++i
)
134 (*i
)->ReMap(oldMap
, newMap
);
135 for (std::vector
<pkgCache::PrvIterator
*>::const_iterator i
= Dynamic
<pkgCache::PrvIterator
>::toReMap
.begin();
136 i
!= Dynamic
<pkgCache::PrvIterator
>::toReMap
.end(); ++i
)
137 (*i
)->ReMap(oldMap
, newMap
);
138 for (std::vector
<pkgCache::PkgFileIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.begin();
139 i
!= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.end(); ++i
)
140 (*i
)->ReMap(oldMap
, newMap
);
142 // CacheGenerator::WriteStringInMap /*{{{*/
143 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
,
144 const unsigned long &Len
) {
145 void const * const oldMap
= Map
.Data();
146 map_ptrloc
const index
= Map
.WriteString(String
, Len
);
148 ReMap(oldMap
, Map
.Data());
152 // CacheGenerator::WriteStringInMap /*{{{*/
153 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
) {
154 void const * const oldMap
= Map
.Data();
155 map_ptrloc
const index
= Map
.WriteString(String
);
157 ReMap(oldMap
, Map
.Data());
161 map_ptrloc
pkgCacheGenerator::AllocateInMap(const unsigned long &size
) {/*{{{*/
162 void const * const oldMap
= Map
.Data();
163 map_ptrloc
const index
= Map
.Allocate(size
);
165 ReMap(oldMap
, Map
.Data());
169 // CacheGenerator::MergeList - Merge the package list /*{{{*/
170 // ---------------------------------------------------------------------
171 /* This provides the generation of the entries in the cache. Each loop
172 goes through a single package record from the underlying parse engine. */
173 bool pkgCacheGenerator::MergeList(ListParser
&List
,
174 pkgCache::VerIterator
*OutVer
)
178 unsigned int Counter
= 0;
179 while (List
.Step() == true)
181 string
const PackageName
= List
.Package();
182 if (PackageName
.empty() == true)
185 string
const Arch
= List
.Architecture();
187 // Get a pointer to the package structure
188 pkgCache::PkgIterator Pkg
;
189 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
190 if (NewPackage(Pkg
, PackageName
, Arch
) == false)
191 return _error
->Error(_("Error occurred while processing %s (NewPackage)"),PackageName
.c_str());
193 if (Counter
% 100 == 0 && Progress
!= 0)
194 Progress
->Progress(List
.Offset());
196 /* Get a pointer to the version structure. We know the list is sorted
197 so we use that fact in the search. Insertion of new versions is
198 done with correct sorting */
199 string Version
= List
.Version();
200 if (Version
.empty() == true)
202 // we first process the package, then the descriptions
203 // (this has the bonus that we get MMap error when we run out
205 pkgCache::VerIterator
Ver(Cache
);
206 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
207 if (List
.UsePackage(Pkg
, Ver
) == false)
208 return _error
->Error(_("Error occurred while processing %s (UsePackage1)"),
209 PackageName
.c_str());
211 // Find the right version to write the description
212 MD5SumValue CurMd5
= List
.Description_md5();
213 Ver
= Pkg
.VersionList();
215 for (; Ver
.end() == false; ++Ver
)
217 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
218 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
219 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
220 bool duplicate
=false;
222 // don't add a new description if we have one for the given
224 for ( ; Desc
.end() == false; ++Desc
)
225 if (MD5SumValue(Desc
.md5()) == CurMd5
&&
226 Desc
.LanguageCode() == List
.DescriptionLanguage())
231 for (Desc
= Ver
.DescriptionList();
233 LastDesc
= &Desc
->NextDesc
, ++Desc
)
235 if (MD5SumValue(Desc
.md5()) == CurMd5
)
237 // Add new description
238 void const * const oldMap
= Map
.Data();
239 map_ptrloc
const descindex
= NewDescription(Desc
, List
.DescriptionLanguage(), CurMd5
, *LastDesc
);
240 if (oldMap
!= Map
.Data())
241 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
242 *LastDesc
= descindex
;
243 Desc
->ParentPkg
= Pkg
.Index();
245 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
246 return _error
->Error(_("Error occurred while processing %s (NewFileDesc1)"),PackageName
.c_str());
255 pkgCache::VerIterator Ver
= Pkg
.VersionList();
256 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
257 map_ptrloc
*LastVer
= &Pkg
->VersionList
;
258 void const * oldMap
= Map
.Data();
260 unsigned long const Hash
= List
.VersionHash();
261 for (; Ver
.end() == false; LastVer
= &Ver
->NextVer
, Ver
++)
263 Res
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr());
264 // Version is higher as current version - insert here
267 // Versionstrings are equal - is hash also equal?
268 if (Res
== 0 && Ver
->Hash
== Hash
)
270 // proceed with the next till we have either the right
271 // or we found another version (which will be lower)
274 /* We already have a version for this item, record that we saw it */
275 if (Res
== 0 && Ver
.end() == false && Ver
->Hash
== Hash
)
277 if (List
.UsePackage(Pkg
,Ver
) == false)
278 return _error
->Error(_("Error occurred while processing %s (UsePackage2)"),
279 PackageName
.c_str());
281 if (NewFileVer(Ver
,List
) == false)
282 return _error
->Error(_("Error occurred while processing %s (NewFileVer1)"),
283 PackageName
.c_str());
285 // Read only a single record and return
289 FoundFileDeps
|= List
.HasFileDeps();
297 map_ptrloc
const verindex
= NewVersion(Ver
,Version
,*LastVer
);
298 if (verindex
== 0 && _error
->PendingError())
299 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
300 PackageName
.c_str(), 1);
302 if (oldMap
!= Map
.Data())
303 LastVer
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
305 Ver
->ParentPkg
= Pkg
.Index();
308 if (List
.NewVersion(Ver
) == false)
309 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
310 PackageName
.c_str(), 2);
312 if (List
.UsePackage(Pkg
,Ver
) == false)
313 return _error
->Error(_("Error occurred while processing %s (UsePackage3)"),
314 PackageName
.c_str());
316 if (NewFileVer(Ver
,List
) == false)
317 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
318 PackageName
.c_str(), 3);
320 // Read only a single record and return
324 FoundFileDeps
|= List
.HasFileDeps();
328 /* Record the Description data. Description data always exist in
329 Packages and Translation-* files. */
330 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
331 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
332 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
334 // Skip to the end of description set
335 for (; Desc
.end() == false; LastDesc
= &Desc
->NextDesc
, Desc
++);
337 // Add new description
339 map_ptrloc
const descindex
= NewDescription(Desc
, List
.DescriptionLanguage(), List
.Description_md5(), *LastDesc
);
340 if (oldMap
!= Map
.Data())
341 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
342 *LastDesc
= descindex
;
343 Desc
->ParentPkg
= Pkg
.Index();
345 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
346 return _error
->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName
.c_str());
349 FoundFileDeps
|= List
.HasFileDeps();
351 if (Cache
.HeaderP
->PackageCount
>= (1ULL<<sizeof(Cache
.PkgP
->ID
)*8)-1)
352 return _error
->Error(_("Wow, you exceeded the number of package "
353 "names this APT is capable of."));
354 if (Cache
.HeaderP
->VersionCount
>= (1ULL<<(sizeof(Cache
.VerP
->ID
)*8))-1)
355 return _error
->Error(_("Wow, you exceeded the number of versions "
356 "this APT is capable of."));
357 if (Cache
.HeaderP
->DescriptionCount
>= (1ULL<<(sizeof(Cache
.DescP
->ID
)*8))-1)
358 return _error
->Error(_("Wow, you exceeded the number of descriptions "
359 "this APT is capable of."));
360 if (Cache
.HeaderP
->DependsCount
>= (1ULL<<(sizeof(Cache
.DepP
->ID
)*8))-1ULL)
361 return _error
->Error(_("Wow, you exceeded the number of dependencies "
362 "this APT is capable of."));
366 // CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/
367 // ---------------------------------------------------------------------
368 /* If we found any file depends while parsing the main list we need to
369 resolve them. Since it is undesired to load the entire list of files
370 into the cache as virtual packages we do a two stage effort. MergeList
371 identifies the file depends and this creates Provdies for them by
372 re-parsing all the indexs. */
373 bool pkgCacheGenerator::MergeFileProvides(ListParser
&List
)
377 unsigned int Counter
= 0;
378 while (List
.Step() == true)
380 string PackageName
= List
.Package();
381 if (PackageName
.empty() == true)
383 string Version
= List
.Version();
384 if (Version
.empty() == true)
387 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(PackageName
);
388 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
389 if (Pkg
.end() == true)
390 return _error
->Error(_("Error occurred while processing %s (FindPkg)"),
391 PackageName
.c_str());
393 if (Counter
% 100 == 0 && Progress
!= 0)
394 Progress
->Progress(List
.Offset());
396 unsigned long Hash
= List
.VersionHash();
397 pkgCache::VerIterator Ver
= Pkg
.VersionList();
398 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
399 for (; Ver
.end() == false; ++Ver
)
401 if (Ver
->Hash
== Hash
&& Version
.c_str() == Ver
.VerStr())
403 if (List
.CollectFileProvides(Cache
,Ver
) == false)
404 return _error
->Error(_("Error occurred while processing %s (CollectFileProvides)"),PackageName
.c_str());
409 if (Ver
.end() == true)
410 _error
->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName
.c_str(),Version
.c_str());
416 // CacheGenerator::NewGroup - Add a new group /*{{{*/
417 // ---------------------------------------------------------------------
418 /* This creates a new group structure and adds it to the hash table */
419 bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator
&Grp
, const string
&Name
)
421 Grp
= Cache
.FindGrp(Name
);
422 if (Grp
.end() == false)
426 map_ptrloc
const Group
= AllocateInMap(sizeof(pkgCache::Group
));
427 if (unlikely(Group
== 0))
430 Grp
= pkgCache::GrpIterator(Cache
, Cache
.GrpP
+ Group
);
431 map_ptrloc
const idxName
= WriteStringInMap(Name
);
432 if (unlikely(idxName
== 0))
436 // Insert it into the hash table
437 unsigned long const Hash
= Cache
.Hash(Name
);
438 Grp
->Next
= Cache
.HeaderP
->GrpHashTable
[Hash
];
439 Cache
.HeaderP
->GrpHashTable
[Hash
] = Group
;
441 Grp
->ID
= Cache
.HeaderP
->GroupCount
++;
445 // CacheGenerator::NewPackage - Add a new package /*{{{*/
446 // ---------------------------------------------------------------------
447 /* This creates a new package structure and adds it to the hash table */
448 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator
&Pkg
,const string
&Name
,
449 const string
&Arch
) {
450 pkgCache::GrpIterator Grp
;
451 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
452 if (unlikely(NewGroup(Grp
, Name
) == false))
455 Pkg
= Grp
.FindPkg(Arch
);
456 if (Pkg
.end() == false)
460 map_ptrloc
const Package
= AllocateInMap(sizeof(pkgCache::Package
));
461 if (unlikely(Package
== 0))
463 Pkg
= pkgCache::PkgIterator(Cache
,Cache
.PkgP
+ Package
);
465 // Insert the package into our package list
466 if (Grp
->FirstPackage
== 0) // the group is new
468 // Insert it into the hash table
469 unsigned long const Hash
= Cache
.Hash(Name
);
470 Pkg
->NextPackage
= Cache
.HeaderP
->PkgHashTable
[Hash
];
471 Cache
.HeaderP
->PkgHashTable
[Hash
] = Package
;
472 Grp
->FirstPackage
= Package
;
474 else // Group the Packages together
476 // this package is the new last package
477 pkgCache::PkgIterator
LastPkg(Cache
, Cache
.PkgP
+ Grp
->LastPackage
);
478 Pkg
->NextPackage
= LastPkg
->NextPackage
;
479 LastPkg
->NextPackage
= Package
;
481 Grp
->LastPackage
= Package
;
483 // Set the name, arch and the ID
484 Pkg
->Name
= Grp
->Name
;
485 Pkg
->Group
= Grp
.Index();
486 // all is mapped to the native architecture
487 map_ptrloc
const idxArch
= (Arch
== "all") ? Cache
.HeaderP
->Architecture
: 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 // copy P.Arch() into a string here as a cache remap
641 // in NewDepends() later may alter the pointer location
642 string Arch
= P
.Arch() == NULL
? "" : P
.Arch();
643 map_ptrloc
*OldDepLast
= NULL
;
644 /* MultiArch handling introduces a lot of implicit Dependencies:
645 - MultiArch: same → Co-Installable if they have the same version
646 - Architecture: all → Need to be Co-Installable for internal reasons
647 - All others conflict with all other group members */
648 bool const coInstall
= ((V
->MultiArch
& pkgCache::Version::Same
) == pkgCache::Version::Same
);
649 for (vector
<string
>::const_iterator A
= archs
.begin(); A
!= archs
.end(); ++A
)
653 /* We allow only one installed arch at the time
654 per group, therefore each group member conflicts
655 with all other group members */
656 pkgCache::PkgIterator D
= G
.FindPkg(*A
);
657 Dynamic
<pkgCache::PkgIterator
> DynD(D
);
660 if (coInstall
== true)
662 // Replaces: ${self}:other ( << ${binary:Version})
663 NewDepends(D
, V
, V
.VerStr(),
664 pkgCache::Dep::Less
, pkgCache::Dep::Replaces
,
666 // Breaks: ${self}:other (!= ${binary:Version})
667 NewDepends(D
, V
, V
.VerStr(),
668 pkgCache::Dep::NotEquals
, pkgCache::Dep::DpkgBreaks
,
671 // Conflicts: ${self}:other
673 pkgCache::Dep::NoOp
, pkgCache::Dep::Conflicts
,
684 // CacheGenerator::NewDepends - Create a dependency element /*{{{*/
685 // ---------------------------------------------------------------------
686 /* This creates a dependency element in the tree. It is linked to the
687 version and to the package that it is pointing to. */
688 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator
&Pkg
,
689 pkgCache::VerIterator
&Ver
,
690 string
const &Version
,
691 unsigned int const &Op
,
692 unsigned int const &Type
,
693 map_ptrloc
* &OldDepLast
)
695 void const * const oldMap
= Map
.Data();
697 map_ptrloc
const Dependency
= AllocateInMap(sizeof(pkgCache::Dependency
));
698 if (unlikely(Dependency
== 0))
702 pkgCache::DepIterator
Dep(Cache
,Cache
.DepP
+ Dependency
);
703 Dynamic
<pkgCache::DepIterator
> DynDep(Dep
);
704 Dep
->ParentVer
= Ver
.Index();
707 Dep
->ID
= Cache
.HeaderP
->DependsCount
++;
709 // Probe the reverse dependency list for a version string that matches
710 if (Version
.empty() == false)
712 /* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
713 if (I->Version != 0 && I.TargetVer() == Version)
714 Dep->Version = I->Version;*/
715 if (Dep
->Version
== 0) {
716 map_ptrloc
const index
= WriteStringInMap(Version
);
717 if (unlikely(index
== 0))
719 Dep
->Version
= index
;
723 // Link it to the package
724 Dep
->Package
= Pkg
.Index();
725 Dep
->NextRevDepends
= Pkg
->RevDepends
;
726 Pkg
->RevDepends
= Dep
.Index();
728 // Do we know where to link the Dependency to?
729 if (OldDepLast
== NULL
)
731 OldDepLast
= &Ver
->DependsList
;
732 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
733 OldDepLast
= &D
->NextDepends
;
734 } else if (oldMap
!= Map
.Data())
735 OldDepLast
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
737 Dep
->NextDepends
= *OldDepLast
;
738 *OldDepLast
= Dep
.Index();
739 OldDepLast
= &Dep
->NextDepends
;
744 // ListParser::NewDepends - Create the environment for a new dependency /*{{{*/
745 // ---------------------------------------------------------------------
746 /* This creates a Group and the Package to link this dependency to if
747 needed and handles also the caching of the old endpoint */
748 bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator
&Ver
,
749 const string
&PackageName
,
751 const string
&Version
,
755 pkgCache::GrpIterator Grp
;
756 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
757 if (unlikely(Owner
->NewGroup(Grp
, PackageName
) == false))
760 // Locate the target package
761 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(Arch
);
762 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
763 if (Pkg
.end() == true) {
764 if (unlikely(Owner
->NewPackage(Pkg
, PackageName
, Arch
) == false))
768 // Is it a file dependency?
769 if (unlikely(PackageName
[0] == '/'))
770 FoundFileDeps
= true;
772 /* Caching the old end point speeds up generation substantially */
773 if (OldDepVer
!= Ver
) {
778 return Owner
->NewDepends(Pkg
, Ver
, Version
, Op
, Type
, OldDepLast
);
781 // ListParser::NewProvides - Create a Provides element /*{{{*/
782 // ---------------------------------------------------------------------
784 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator
&Ver
,
785 const string
&PkgName
,
786 const string
&PkgArch
,
787 const string
&Version
)
789 pkgCache
&Cache
= Owner
->Cache
;
791 // We do not add self referencing provides
792 if (Ver
.ParentPkg().Name() == PkgName
&& (PkgArch
== Ver
.ParentPkg().Arch() ||
793 (PkgArch
== "all" && strcmp((Cache
.StrP
+ Cache
.HeaderP
->Architecture
), Ver
.ParentPkg().Arch()) == 0)))
797 map_ptrloc
const Provides
= Owner
->AllocateInMap(sizeof(pkgCache::Provides
));
798 if (unlikely(Provides
== 0))
800 Cache
.HeaderP
->ProvidesCount
++;
803 pkgCache::PrvIterator
Prv(Cache
,Cache
.ProvideP
+ Provides
,Cache
.PkgP
);
804 Dynamic
<pkgCache::PrvIterator
> DynPrv(Prv
);
805 Prv
->Version
= Ver
.Index();
806 Prv
->NextPkgProv
= Ver
->ProvidesList
;
807 Ver
->ProvidesList
= Prv
.Index();
808 if (Version
.empty() == false && unlikely((Prv
->ProvideVersion
= WriteString(Version
)) == 0))
811 // Locate the target package
812 pkgCache::PkgIterator Pkg
;
813 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
814 if (unlikely(Owner
->NewPackage(Pkg
,PkgName
, PkgArch
) == false))
817 // Link it to the package
818 Prv
->ParentPkg
= Pkg
.Index();
819 Prv
->NextProvides
= Pkg
->ProvidesList
;
820 Pkg
->ProvidesList
= Prv
.Index();
825 // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
826 // ---------------------------------------------------------------------
827 /* This is used to select which file is to be associated with all newly
828 added versions. The caller is responsible for setting the IMS fields. */
829 bool pkgCacheGenerator::SelectFile(const string
&File
,const string
&Site
,
830 const pkgIndexFile
&Index
,
833 // Get some space for the structure
834 map_ptrloc
const idxFile
= AllocateInMap(sizeof(*CurrentFile
));
835 if (unlikely(idxFile
== 0))
837 CurrentFile
= Cache
.PkgFileP
+ idxFile
;
840 map_ptrloc
const idxFileName
= WriteStringInMap(File
);
841 map_ptrloc
const idxSite
= WriteUniqString(Site
);
842 if (unlikely(idxFileName
== 0 || idxSite
== 0))
844 CurrentFile
->FileName
= idxFileName
;
845 CurrentFile
->Site
= idxSite
;
846 CurrentFile
->NextFile
= Cache
.HeaderP
->FileList
;
847 CurrentFile
->Flags
= Flags
;
848 CurrentFile
->ID
= Cache
.HeaderP
->PackageFileCount
;
849 map_ptrloc
const idxIndexType
= WriteUniqString(Index
.GetType()->Label
);
850 if (unlikely(idxIndexType
== 0))
852 CurrentFile
->IndexType
= idxIndexType
;
854 Cache
.HeaderP
->FileList
= CurrentFile
- Cache
.PkgFileP
;
855 Cache
.HeaderP
->PackageFileCount
++;
858 Progress
->SubProgress(Index
.Size());
862 // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
863 // ---------------------------------------------------------------------
864 /* This is used to create handles to strings. Given the same text it
865 always returns the same number */
866 unsigned long pkgCacheGenerator::WriteUniqString(const char *S
,
869 /* We use a very small transient hash table here, this speeds up generation
870 by a fair amount on slower machines */
871 pkgCache::StringItem
*&Bucket
= UniqHash
[(S
[0]*5 + S
[1]) % _count(UniqHash
)];
873 stringcmp(S
,S
+Size
,Cache
.StrP
+ Bucket
->String
) == 0)
874 return Bucket
->String
;
876 // Search for an insertion point
877 pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.HeaderP
->StringList
;
879 map_ptrloc
*Last
= &Cache
.HeaderP
->StringList
;
880 for (; I
!= Cache
.StringItemP
; Last
= &I
->NextItem
,
881 I
= Cache
.StringItemP
+ I
->NextItem
)
883 Res
= stringcmp(S
,S
+Size
,Cache
.StrP
+ I
->String
);
896 void const * const oldMap
= Map
.Data();
897 map_ptrloc
const Item
= AllocateInMap(sizeof(pkgCache::StringItem
));
901 map_ptrloc
const idxString
= WriteStringInMap(S
,Size
);
902 if (unlikely(idxString
== 0))
904 if (oldMap
!= Map
.Data()) {
905 Last
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
906 I
+= (pkgCache::StringItem
*) Map
.Data() - (pkgCache::StringItem
*) oldMap
;
910 // Fill in the structure
911 pkgCache::StringItem
*ItemP
= Cache
.StringItemP
+ Item
;
912 ItemP
->NextItem
= I
- Cache
.StringItemP
;
913 ItemP
->String
= idxString
;
916 return ItemP
->String
;
919 // CheckValidity - Check that a cache is up-to-date /*{{{*/
920 // ---------------------------------------------------------------------
921 /* This just verifies that each file in the list of index files exists,
922 has matching attributes with the cache and the cache does not have
924 static bool CheckValidity(const string
&CacheFile
,
930 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
931 // No file, certainly invalid
932 if (CacheFile
.empty() == true || FileExists(CacheFile
) == false)
935 std::clog
<< "CacheFile doesn't exist" << std::endl
;
939 if (List
.GetLastModifiedTime() > GetModificationTime(CacheFile
))
942 std::clog
<< "sources.list is newer than the cache" << std::endl
;
947 FileFd
CacheF(CacheFile
,FileFd::ReadOnly
);
948 SPtr
<MMap
> Map
= new MMap(CacheF
,0);
950 if (_error
->PendingError() == true || Map
->Size() == 0)
953 std::clog
<< "Errors are pending or Map is empty()" << std::endl
;
958 /* Now we check every index file, see if it is in the cache,
959 verify the IMS data and check that it is on the disk too.. */
960 SPtrArray
<bool> Visited
= new bool[Cache
.HeaderP
->PackageFileCount
];
961 memset(Visited
,0,sizeof(*Visited
)*Cache
.HeaderP
->PackageFileCount
);
962 for (; Start
!= End
; ++Start
)
965 std::clog
<< "Checking PkgFile " << (*Start
)->Describe() << ": ";
966 if ((*Start
)->HasPackages() == false)
969 std::clog
<< "Has NO packages" << std::endl
;
973 if ((*Start
)->Exists() == false)
975 #if 0 // mvo: we no longer give a message here (Default Sources spec)
976 _error
->WarningE("stat",_("Couldn't stat source package list %s"),
977 (*Start
)->Describe().c_str());
980 std::clog
<< "file doesn't exist" << std::endl
;
984 // FindInCache is also expected to do an IMS check.
985 pkgCache::PkgFileIterator File
= (*Start
)->FindInCache(Cache
);
986 if (File
.end() == true)
989 std::clog
<< "FindInCache returned end-Pointer" << std::endl
;
993 Visited
[File
->ID
] = true;
995 std::clog
<< "with ID " << File
->ID
<< " is valid" << std::endl
;
998 for (unsigned I
= 0; I
!= Cache
.HeaderP
->PackageFileCount
; I
++)
999 if (Visited
[I
] == false)
1002 std::clog
<< "File with ID" << I
<< " wasn't visited" << std::endl
;
1006 if (_error
->PendingError() == true)
1010 std::clog
<< "Validity failed because of pending errors:" << std::endl
;
1011 _error
->DumpErrors();
1018 *OutMap
= Map
.UnGuard();
1022 // ComputeSize - Compute the total size of a bunch of files /*{{{*/
1023 // ---------------------------------------------------------------------
1024 /* Size is kind of an abstract notion that is only used for the progress
1026 static unsigned long ComputeSize(FileIterator Start
,FileIterator End
)
1028 unsigned long TotalSize
= 0;
1029 for (; Start
!= End
; ++Start
)
1031 if ((*Start
)->HasPackages() == false)
1033 TotalSize
+= (*Start
)->Size();
1038 // BuildCache - Merge the list of index files into the cache /*{{{*/
1039 // ---------------------------------------------------------------------
1041 static bool BuildCache(pkgCacheGenerator
&Gen
,
1042 OpProgress
*Progress
,
1043 unsigned long &CurrentSize
,unsigned long TotalSize
,
1044 FileIterator Start
, FileIterator End
)
1047 for (I
= Start
; I
!= End
; ++I
)
1049 if ((*I
)->HasPackages() == false)
1052 if ((*I
)->Exists() == false)
1055 if ((*I
)->FindInCache(Gen
.GetCache()).end() == false)
1057 _error
->Warning("Duplicate sources.list entry %s",
1058 (*I
)->Describe().c_str());
1062 unsigned long Size
= (*I
)->Size();
1063 if (Progress
!= NULL
)
1064 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Reading package lists"));
1065 CurrentSize
+= Size
;
1067 if ((*I
)->Merge(Gen
,Progress
) == false)
1071 if (Gen
.HasFileDeps() == true)
1073 if (Progress
!= NULL
)
1075 TotalSize
= ComputeSize(Start
, End
);
1077 for (I
= Start
; I
!= End
; ++I
)
1079 unsigned long Size
= (*I
)->Size();
1080 if (Progress
!= NULL
)
1081 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Collecting File Provides"));
1082 CurrentSize
+= Size
;
1083 if ((*I
)->MergeFileProvides(Gen
,Progress
) == false)
1091 // CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/
1092 DynamicMMap
* pkgCacheGenerator::CreateDynamicMMap(FileFd
*CacheF
, unsigned long Flags
) {
1093 unsigned long const MapStart
= _config
->FindI("APT::Cache-Start", 24*1024*1024);
1094 unsigned long const MapGrow
= _config
->FindI("APT::Cache-Grow", 1*1024*1024);
1095 unsigned long const MapLimit
= _config
->FindI("APT::Cache-Limit", 0);
1096 Flags
|= MMap::Moveable
;
1097 if (_config
->FindB("APT::Cache-Fallback", false) == true)
1098 Flags
|= MMap::Fallback
;
1100 return new DynamicMMap(*CacheF
, Flags
, MapStart
, MapGrow
, MapLimit
);
1102 return new DynamicMMap(Flags
, MapStart
, MapGrow
, MapLimit
);
1105 // CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
1106 // ---------------------------------------------------------------------
1107 /* This makes sure that the status cache (the cache that has all
1108 index files from the sources list and all local ones) is ready
1109 to be mmaped. If OutMap is not zero then a MMap object representing
1110 the cache will be stored there. This is pretty much mandetory if you
1111 are using AllowMem. AllowMem lets the function be run as non-root
1112 where it builds the cache 'fast' into a memory buffer. */
1113 __deprecated
bool pkgMakeStatusCache(pkgSourceList
&List
,OpProgress
&Progress
,
1114 MMap
**OutMap
, bool AllowMem
)
1115 { return pkgCacheGenerator::MakeStatusCache(List
, &Progress
, OutMap
, AllowMem
); }
1116 bool pkgCacheGenerator::MakeStatusCache(pkgSourceList
&List
,OpProgress
*Progress
,
1117 MMap
**OutMap
,bool AllowMem
)
1119 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
1121 vector
<pkgIndexFile
*> Files
;
1122 for (vector
<metaIndex
*>::const_iterator i
= List
.begin();
1126 vector
<pkgIndexFile
*> *Indexes
= (*i
)->GetIndexFiles();
1127 for (vector
<pkgIndexFile
*>::const_iterator j
= Indexes
->begin();
1128 j
!= Indexes
->end();
1130 Files
.push_back (*j
);
1133 unsigned long const EndOfSource
= Files
.size();
1134 if (_system
->AddStatusFiles(Files
) == false)
1137 // Decide if we can write to the files..
1138 string
const CacheFile
= _config
->FindFile("Dir::Cache::pkgcache");
1139 string
const SrcCacheFile
= _config
->FindFile("Dir::Cache::srcpkgcache");
1141 // ensure the cache directory exists
1142 if (CacheFile
.empty() == false || SrcCacheFile
.empty() == false)
1144 string dir
= _config
->FindDir("Dir::Cache");
1145 size_t const len
= dir
.size();
1146 if (len
> 5 && dir
.find("/apt/", len
- 6, 5) == len
- 5)
1147 dir
= dir
.substr(0, len
- 5);
1148 if (CacheFile
.empty() == false)
1149 CreateDirectory(dir
, flNotFile(CacheFile
));
1150 if (SrcCacheFile
.empty() == false)
1151 CreateDirectory(dir
, flNotFile(SrcCacheFile
));
1154 // Decide if we can write to the cache
1155 bool Writeable
= false;
1156 if (CacheFile
.empty() == false)
1157 Writeable
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0;
1159 if (SrcCacheFile
.empty() == false)
1160 Writeable
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0;
1162 std::clog
<< "Do we have write-access to the cache files? " << (Writeable
? "YES" : "NO") << std::endl
;
1164 if (Writeable
== false && AllowMem
== false && CacheFile
.empty() == false)
1165 return _error
->Error(_("Unable to write to %s"),flNotFile(CacheFile
).c_str());
1167 if (Progress
!= NULL
)
1168 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1170 // Cache is OK, Fin.
1171 if (CheckValidity(CacheFile
, List
, Files
.begin(),Files
.end(),OutMap
) == true)
1173 if (Progress
!= NULL
)
1174 Progress
->OverallProgress(1,1,1,_("Reading package lists"));
1176 std::clog
<< "pkgcache.bin is valid - no need to build anything" << std::endl
;
1179 else if (Debug
== true)
1180 std::clog
<< "pkgcache.bin is NOT valid" << std::endl
;
1182 /* At this point we know we need to reconstruct the package cache,
1184 SPtr
<FileFd
> CacheF
;
1185 SPtr
<DynamicMMap
> Map
;
1186 if (Writeable
== true && CacheFile
.empty() == false)
1188 _error
->PushToStack();
1189 unlink(CacheFile
.c_str());
1190 CacheF
= new FileFd(CacheFile
,FileFd::WriteAtomic
);
1191 fchmod(CacheF
->Fd(),0644);
1192 Map
= CreateDynamicMMap(CacheF
, MMap::Public
);
1193 if (_error
->PendingError() == true)
1195 delete CacheF
.UnGuard();
1196 delete Map
.UnGuard();
1198 std::clog
<< "Open filebased MMap FAILED" << std::endl
;
1200 if (AllowMem
== false)
1202 _error
->MergeWithStack();
1205 _error
->RevertToStack();
1207 else if (Debug
== true)
1209 _error
->MergeWithStack();
1210 std::clog
<< "Open filebased MMap" << std::endl
;
1213 if (Writeable
== false || CacheFile
.empty() == true)
1215 // Just build it in memory..
1216 Map
= CreateDynamicMMap(NULL
);
1218 std::clog
<< "Open memory Map (not filebased)" << std::endl
;
1221 // Lets try the source cache.
1222 unsigned long CurrentSize
= 0;
1223 unsigned long TotalSize
= 0;
1224 if (CheckValidity(SrcCacheFile
, List
, Files
.begin(),
1225 Files
.begin()+EndOfSource
) == true)
1228 std::clog
<< "srcpkgcache.bin is valid - populate MMap with it." << std::endl
;
1229 // Preload the map with the source cache
1230 FileFd
SCacheF(SrcCacheFile
,FileFd::ReadOnly
);
1231 unsigned long const alloc
= Map
->RawAllocate(SCacheF
.Size());
1232 if ((alloc
== 0 && _error
->PendingError())
1233 || SCacheF
.Read((unsigned char *)Map
->Data() + alloc
,
1234 SCacheF
.Size()) == false)
1237 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1239 // Build the status cache
1240 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1241 if (_error
->PendingError() == true)
1243 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1244 Files
.begin()+EndOfSource
,Files
.end()) == false)
1247 // FIXME: move me to a better place
1248 Gen
.FinishCache(Progress
);
1253 std::clog
<< "srcpkgcache.bin is NOT valid - rebuild" << std::endl
;
1254 TotalSize
= ComputeSize(Files
.begin(),Files
.end());
1256 // Build the source cache
1257 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1258 if (_error
->PendingError() == true)
1260 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1261 Files
.begin(),Files
.begin()+EndOfSource
) == false)
1265 if (Writeable
== true && SrcCacheFile
.empty() == false)
1267 FileFd
SCacheF(SrcCacheFile
,FileFd::WriteAtomic
);
1268 if (_error
->PendingError() == true)
1271 fchmod(SCacheF
.Fd(),0644);
1273 // Write out the main data
1274 if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false)
1275 return _error
->Error(_("IO Error saving source cache"));
1278 // Write out the proper header
1279 Gen
.GetCache().HeaderP
->Dirty
= false;
1280 if (SCacheF
.Seek(0) == false ||
1281 SCacheF
.Write(Map
->Data(),sizeof(*Gen
.GetCache().HeaderP
)) == false)
1282 return _error
->Error(_("IO Error saving source cache"));
1283 Gen
.GetCache().HeaderP
->Dirty
= true;
1287 // Build the status cache
1288 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1289 Files
.begin()+EndOfSource
,Files
.end()) == false)
1292 // FIXME: move me to a better place
1293 Gen
.FinishCache(Progress
);
1296 std::clog
<< "Caches are ready for shipping" << std::endl
;
1298 if (_error
->PendingError() == true)
1304 delete Map
.UnGuard();
1305 *OutMap
= new MMap(*CacheF
,0);
1309 *OutMap
= Map
.UnGuard();
1316 // CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
1317 // ---------------------------------------------------------------------
1319 __deprecated
bool pkgMakeOnlyStatusCache(OpProgress
&Progress
,DynamicMMap
**OutMap
)
1320 { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress
, OutMap
); }
1321 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress
*Progress
,DynamicMMap
**OutMap
)
1323 vector
<pkgIndexFile
*> Files
;
1324 unsigned long EndOfSource
= Files
.size();
1325 if (_system
->AddStatusFiles(Files
) == false)
1328 SPtr
<DynamicMMap
> Map
= CreateDynamicMMap(NULL
);
1329 unsigned long CurrentSize
= 0;
1330 unsigned long TotalSize
= 0;
1332 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1334 // Build the status cache
1335 if (Progress
!= NULL
)
1336 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1337 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1338 if (_error
->PendingError() == true)
1340 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1341 Files
.begin()+EndOfSource
,Files
.end()) == false)
1344 // FIXME: move me to a better place
1345 Gen
.FinishCache(Progress
);
1347 if (_error
->PendingError() == true)
1349 *OutMap
= Map
.UnGuard();