]> git.saurik.com Git - apt.git/blame - apt-pkg/pkgcachegen.cc
equal comparisions are used mostly in same-source relations,
[apt.git] / apt-pkg / pkgcachegen.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
7db98ffc 3// $Id: pkgcachegen.cc,v 1.53.2.1 2003/12/24 23:09:17 mdz Exp $
578bfd0a
AL
4/* ######################################################################
5
6 Package Cache Generator - Generator for the cache structure.
7
8 This builds the cache structure from the abstract package list parser.
9
10 ##################################################################### */
11 /*}}}*/
12// Include Files /*{{{*/
ea542140 13#include <config.h>
b2e465d6 14
094a497d
AL
15#include <apt-pkg/pkgcachegen.h>
16#include <apt-pkg/error.h>
17#include <apt-pkg/version.h>
b35d2f5f
AL
18#include <apt-pkg/progress.h>
19#include <apt-pkg/sourcelist.h>
20#include <apt-pkg/configuration.h>
25396fb0 21#include <apt-pkg/aptconfiguration.h>
cdcc6d34 22#include <apt-pkg/strutl.h>
b2e465d6
AL
23#include <apt-pkg/sptr.h>
24#include <apt-pkg/pkgsystem.h>
aea7f4c8 25#include <apt-pkg/macros.h>
afb1e2e3 26#include <apt-pkg/tagfile.h>
472ff00e
DK
27#include <apt-pkg/metaindex.h>
28#include <apt-pkg/fileutl.h>
afb1e2e3 29
e7b470ee 30#include <vector>
578bfd0a
AL
31#include <sys/stat.h>
32#include <unistd.h>
803fafcb 33#include <errno.h>
7ef72446 34#include <stdio.h>
ea542140
DK
35
36#include <apti18n.h>
578bfd0a 37 /*}}}*/
73688d27 38typedef std::vector<pkgIndexFile *>::iterator FileIterator;
d10cef82 39template <typename Iter> std::vector<Iter*> pkgCacheGenerator::Dynamic<Iter>::toReMap;
578bfd0a 40
60683765 41static bool IsDuplicateDescription(pkgCache::DescIterator Desc,
5f4db009
DK
42 MD5SumValue const &CurMd5, std::string const &CurLang);
43
73688d27
DK
44using std::string;
45
578bfd0a
AL
46// CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
47// ---------------------------------------------------------------------
25396fb0 48/* We set the dirty flag and make sure that is written to the disk */
b2e465d6 49pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
45415543
AL
50 Map(*pMap), Cache(pMap,false), Progress(Prog),
51 FoundFileDeps(0)
578bfd0a 52{
ddc1d8d0 53 CurrentFile = 0;
b2e465d6 54 memset(UniqHash,0,sizeof(UniqHash));
ddc1d8d0 55
578bfd0a
AL
56 if (_error->PendingError() == true)
57 return;
b2e465d6 58
578bfd0a
AL
59 if (Map.Size() == 0)
60 {
b2e465d6
AL
61 // Setup the map interface..
62 Cache.HeaderP = (pkgCache::Header *)Map.Data();
c5f44afc
DK
63 if (Map.RawAllocate(sizeof(pkgCache::Header)) == 0 && _error->PendingError() == true)
64 return;
65
b2e465d6 66 Map.UsePools(*Cache.HeaderP->Pools,sizeof(Cache.HeaderP->Pools)/sizeof(Cache.HeaderP->Pools[0]));
c5f44afc 67
b2e465d6 68 // Starting header
578bfd0a 69 *Cache.HeaderP = pkgCache::Header();
a9fe5928
DK
70 map_ptrloc const idxVerSysName = WriteStringInMap(_system->VS->Label);
71 Cache.HeaderP->VerSysName = idxVerSysName;
7ccb5efb
DK
72 // this pointer is set in ReMap, but we need it now for WriteUniqString
73 Cache.StringItemP = (pkgCache::StringItem *)Map.Data();
74 map_ptrloc const idxArchitecture = WriteUniqString(_config->Find("APT::Architecture"));
a9fe5928
DK
75 Cache.HeaderP->Architecture = idxArchitecture;
76 if (unlikely(idxVerSysName == 0 || idxArchitecture == 0))
77 return;
c5f44afc 78 Cache.ReMap();
578bfd0a 79 }
b2e465d6
AL
80 else
81 {
82 // Map directly from the existing file
83 Cache.ReMap();
84 Map.UsePools(*Cache.HeaderP->Pools,sizeof(Cache.HeaderP->Pools)/sizeof(Cache.HeaderP->Pools[0]));
85 if (Cache.VS != _system->VS)
86 {
87 _error->Error(_("Cache has an incompatible versioning system"));
88 return;
89 }
90 }
91
578bfd0a
AL
92 Cache.HeaderP->Dirty = true;
93 Map.Sync(0,sizeof(pkgCache::Header));
578bfd0a
AL
94}
95 /*}}}*/
96// CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/
97// ---------------------------------------------------------------------
98/* We sync the data then unset the dirty flag in two steps so as to
99 advoid a problem during a crash */
100pkgCacheGenerator::~pkgCacheGenerator()
101{
102 if (_error->PendingError() == true)
103 return;
104 if (Map.Sync() == false)
105 return;
106
107 Cache.HeaderP->Dirty = false;
1dfda2ce 108 Cache.HeaderP->CacheFileSize = Map.Size();
578bfd0a
AL
109 Map.Sync(0,sizeof(pkgCache::Header));
110}
111 /*}}}*/
a9fe5928
DK
112void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap) {/*{{{*/
113 if (oldMap == newMap)
114 return;
115
64dda04b
MV
116 if (_config->FindB("Debug::pkgCacheGen", false))
117 std::clog << "Remaping from " << oldMap << " to " << newMap << std::endl;
118
a9fe5928
DK
119 Cache.ReMap(false);
120
121 CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
122
123 for (size_t i = 0; i < _count(UniqHash); ++i)
124 if (UniqHash[i] != 0)
125 UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
126
7635093c 127 for (std::vector<pkgCache::GrpIterator*>::const_iterator i = Dynamic<pkgCache::GrpIterator>::toReMap.begin();
a9fe5928 128 i != Dynamic<pkgCache::GrpIterator>::toReMap.end(); ++i)
f7a35f2e 129 (*i)->ReMap(oldMap, newMap);
7635093c 130 for (std::vector<pkgCache::PkgIterator*>::const_iterator i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
a9fe5928 131 i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
f7a35f2e 132 (*i)->ReMap(oldMap, newMap);
7635093c 133 for (std::vector<pkgCache::VerIterator*>::const_iterator i = Dynamic<pkgCache::VerIterator>::toReMap.begin();
a9fe5928 134 i != Dynamic<pkgCache::VerIterator>::toReMap.end(); ++i)
f7a35f2e 135 (*i)->ReMap(oldMap, newMap);
7635093c 136 for (std::vector<pkgCache::DepIterator*>::const_iterator i = Dynamic<pkgCache::DepIterator>::toReMap.begin();
a9fe5928 137 i != Dynamic<pkgCache::DepIterator>::toReMap.end(); ++i)
f7a35f2e 138 (*i)->ReMap(oldMap, newMap);
7635093c 139 for (std::vector<pkgCache::DescIterator*>::const_iterator i = Dynamic<pkgCache::DescIterator>::toReMap.begin();
a9fe5928 140 i != Dynamic<pkgCache::DescIterator>::toReMap.end(); ++i)
f7a35f2e 141 (*i)->ReMap(oldMap, newMap);
7635093c 142 for (std::vector<pkgCache::PrvIterator*>::const_iterator i = Dynamic<pkgCache::PrvIterator>::toReMap.begin();
a9fe5928 143 i != Dynamic<pkgCache::PrvIterator>::toReMap.end(); ++i)
f7a35f2e 144 (*i)->ReMap(oldMap, newMap);
7635093c 145 for (std::vector<pkgCache::PkgFileIterator*>::const_iterator i = Dynamic<pkgCache::PkgFileIterator>::toReMap.begin();
a9fe5928 146 i != Dynamic<pkgCache::PkgFileIterator>::toReMap.end(); ++i)
f7a35f2e 147 (*i)->ReMap(oldMap, newMap);
a9fe5928 148} /*}}}*/
7e58ab0c 149// CacheGenerator::WriteStringInMap /*{{{*/
a9fe5928 150map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String,
7e58ab0c 151 const unsigned long &Len) {
a9fe5928
DK
152 void const * const oldMap = Map.Data();
153 map_ptrloc const index = Map.WriteString(String, Len);
154 if (index != 0)
155 ReMap(oldMap, Map.Data());
156 return index;
7e58ab0c
DK
157}
158 /*}}}*/
159// CacheGenerator::WriteStringInMap /*{{{*/
a9fe5928
DK
160map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String) {
161 void const * const oldMap = Map.Data();
162 map_ptrloc const index = Map.WriteString(String);
163 if (index != 0)
164 ReMap(oldMap, Map.Data());
165 return index;
7e58ab0c
DK
166}
167 /*}}}*/
a9fe5928
DK
168map_ptrloc pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/
169 void const * const oldMap = Map.Data();
170 map_ptrloc const index = Map.Allocate(size);
171 if (index != 0)
172 ReMap(oldMap, Map.Data());
173 return index;
7e58ab0c
DK
174}
175 /*}}}*/
578bfd0a
AL
176// CacheGenerator::MergeList - Merge the package list /*{{{*/
177// ---------------------------------------------------------------------
178/* This provides the generation of the entries in the cache. Each loop
179 goes through a single package record from the underlying parse engine. */
ddc1d8d0
AL
180bool pkgCacheGenerator::MergeList(ListParser &List,
181 pkgCache::VerIterator *OutVer)
578bfd0a
AL
182{
183 List.Owner = this;
0149949b 184
f9eec0e7 185 unsigned int Counter = 0;
0149949b 186 while (List.Step() == true)
578bfd0a 187 {
5bf15716 188 string const PackageName = List.Package();
65a1e968
AL
189 if (PackageName.empty() == true)
190 return false;
5bf15716 191
99a2ea5a
DK
192 Counter++;
193 if (Counter % 100 == 0 && Progress != 0)
194 Progress->Progress(List.Offset());
195
196 string Arch = List.Architecture();
197 string const Version = List.Version();
198 if (Version.empty() == true && Arch.empty() == true)
199 {
8ec00880 200 // package descriptions
99a2ea5a
DK
201 if (MergeListGroup(List, PackageName) == false)
202 return false;
8ec00880 203 continue;
99a2ea5a
DK
204 }
205
206 if (Arch.empty() == true)
c919ad6e
DK
207 {
208 // use the pseudo arch 'none' for arch-less packages
209 Arch = "none";
210 /* We might built a SingleArchCache here, which we don't want to blow up
211 just for these :none packages to a proper MultiArchCache, so just ensure
212 that we have always a native package structure first for SingleArch */
213 pkgCache::PkgIterator NP;
9abb2283 214 Dynamic<pkgCache::PkgIterator> DynPkg(NP);
c919ad6e
DK
215 if (NewPackage(NP, PackageName, _config->Find("APT::Architecture")) == false)
216 // TRANSLATOR: The first placeholder is a package name,
217 // the other two should be copied verbatim as they include debug info
218 return _error->Error(_("Error occurred while processing %s (%s%d)"),
219 PackageName.c_str(), "NewPackage", 0);
220 }
99a2ea5a 221
8b32e920 222 // Get a pointer to the package structure
9ddf7030 223 pkgCache::PkgIterator Pkg;
a9fe5928 224 Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
28166356 225 if (NewPackage(Pkg, PackageName, Arch) == false)
79e9003c
DK
226 // TRANSLATOR: The first placeholder is a package name,
227 // the other two should be copied verbatim as they include debug info
228 return _error->Error(_("Error occurred while processing %s (%s%d)"),
229 PackageName.c_str(), "NewPackage", 1);
8ce4327b 230
99a2ea5a 231
f55a958f
AL
232 if (Version.empty() == true)
233 {
99a2ea5a
DK
234 if (MergeListPackage(List, Pkg) == false)
235 return false;
236 }
237 else
238 {
239 if (MergeListVersion(List, Pkg, Version, OutVer) == false)
240 return false;
241 }
770c32ec 242
99a2ea5a
DK
243 if (OutVer != 0)
244 {
245 FoundFileDeps |= List.HasFileDeps();
246 return true;
f55a958f 247 }
99a2ea5a
DK
248 }
249
250 if (Cache.HeaderP->PackageCount >= (1ULL<<sizeof(Cache.PkgP->ID)*8)-1)
251 return _error->Error(_("Wow, you exceeded the number of package "
252 "names this APT is capable of."));
253 if (Cache.HeaderP->VersionCount >= (1ULL<<(sizeof(Cache.VerP->ID)*8))-1)
254 return _error->Error(_("Wow, you exceeded the number of versions "
255 "this APT is capable of."));
256 if (Cache.HeaderP->DescriptionCount >= (1ULL<<(sizeof(Cache.DescP->ID)*8))-1)
257 return _error->Error(_("Wow, you exceeded the number of descriptions "
258 "this APT is capable of."));
259 if (Cache.HeaderP->DependsCount >= (1ULL<<(sizeof(Cache.DepP->ID)*8))-1ULL)
260 return _error->Error(_("Wow, you exceeded the number of dependencies "
261 "this APT is capable of."));
262
263 FoundFileDeps |= List.HasFileDeps();
264 return true;
265}
266// CacheGenerator::MergeListGroup /*{{{*/
267bool pkgCacheGenerator::MergeListGroup(ListParser &List, std::string const &GrpName)
268{
269 pkgCache::GrpIterator Grp = Cache.FindGrp(GrpName);
5f4db009
DK
270 // a group has no data on it's own, only packages have it but these
271 // stanzas like this come from Translation- files to add descriptions,
272 // but without a version we don't need a description for it…
99a2ea5a 273 if (Grp.end() == true)
5f4db009 274 return true;
99a2ea5a
DK
275 Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
276
277 pkgCache::PkgIterator Pkg;
278 Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
279 for (Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
280 if (MergeListPackage(List, Pkg) == false)
281 return false;
282
283 return true;
284}
285 /*}}}*/
286// CacheGenerator::MergeListPackage /*{{{*/
287bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator &Pkg)
288{
289 // we first process the package, then the descriptions
290 // (for deb this package processing is in fact a no-op)
291 pkgCache::VerIterator Ver(Cache);
292 Dynamic<pkgCache::VerIterator> DynVer(Ver);
293 if (List.UsePackage(Pkg, Ver) == false)
79e9003c
DK
294 return _error->Error(_("Error occurred while processing %s (%s%d)"),
295 Pkg.Name(), "UsePackage", 1);
99a2ea5a
DK
296
297 // Find the right version to write the description
298 MD5SumValue CurMd5 = List.Description_md5();
5f4db009 299 std::string CurLang = List.DescriptionLanguage();
99a2ea5a
DK
300
301 for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
302 {
a65e22c6 303 pkgCache::DescIterator VerDesc = Ver.DescriptionList();
22f07fc5
DK
304
305 // a version can only have one md5 describing it
a65e22c6 306 if (VerDesc.end() == true || MD5SumValue(VerDesc.md5()) != CurMd5)
22f07fc5 307 continue;
99a2ea5a 308
99a2ea5a
DK
309 // don't add a new description if we have one for the given
310 // md5 && language
a65e22c6 311 if (IsDuplicateDescription(VerDesc, CurMd5, CurLang) == true)
99a2ea5a 312 continue;
f55a958f 313
a65e22c6 314 pkgCache::DescIterator Desc;
22f07fc5 315 Dynamic<pkgCache::DescIterator> DynDesc(Desc);
22f07fc5 316
a65e22c6 317 map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, VerDesc->md5sum);
5954d4d2
DK
318 if (unlikely(descindex == 0 && _error->PendingError()))
319 return _error->Error(_("Error occurred while processing %s (%s%d)"),
320 Pkg.Name(), "NewDescription", 1);
a65e22c6 321
22f07fc5
DK
322 Desc->ParentPkg = Pkg.Index();
323
a65e22c6
DK
324 // we add at the end, so that the start is constant as we need
325 // that to be able to efficiently share these lists
326 VerDesc = Ver.DescriptionList(); // old value might be invalid after ReMap
327 for (;VerDesc.end() == false && VerDesc->NextDesc != 0; ++VerDesc);
328 map_ptrloc * const LastNextDesc = (VerDesc.end() == true) ? &Ver->DescriptionList : &VerDesc->NextDesc;
329 *LastNextDesc = descindex;
330
331 if (NewFileDesc(Desc,List) == false)
79e9003c
DK
332 return _error->Error(_("Error occurred while processing %s (%s%d)"),
333 Pkg.Name(), "NewFileDesc", 1);
22f07fc5
DK
334
335 // we can stop here as all "same" versions will share the description
336 break;
99a2ea5a
DK
337 }
338
339 return true;
340}
341 /*}}}*/
342// CacheGenerator::MergeListVersion /*{{{*/
343bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator &Pkg,
344 std::string const &Version, pkgCache::VerIterator* &OutVer)
345{
346 pkgCache::VerIterator Ver = Pkg.VersionList();
347 Dynamic<pkgCache::VerIterator> DynVer(Ver);
348 map_ptrloc *LastVer = &Pkg->VersionList;
349 void const * oldMap = Map.Data();
350
351 unsigned long const Hash = List.VersionHash();
352 if (Ver.end() == false)
353 {
354 /* We know the list is sorted so we use that fact in the search.
355 Insertion of new versions is done with correct sorting */
2246928b 356 int Res = 1;
9ee47c29 357 for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
578bfd0a 358 {
c24972cb 359 Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
7e2b56a3
DK
360 // Version is higher as current version - insert here
361 if (Res > 0)
578bfd0a 362 break;
7e2b56a3
DK
363 // Versionstrings are equal - is hash also equal?
364 if (Res == 0 && Ver->Hash == Hash)
365 break;
366 // proceed with the next till we have either the right
367 // or we found another version (which will be lower)
578bfd0a 368 }
7e2b56a3
DK
369
370 /* We already have a version for this item, record that we saw it */
e426a5ff 371 if (Res == 0 && Ver.end() == false && Ver->Hash == Hash)
578bfd0a 372 {
f55a958f 373 if (List.UsePackage(Pkg,Ver) == false)
79e9003c
DK
374 return _error->Error(_("Error occurred while processing %s (%s%d)"),
375 Pkg.Name(), "UsePackage", 2);
f78439bf 376
578bfd0a 377 if (NewFileVer(Ver,List) == false)
79e9003c
DK
378 return _error->Error(_("Error occurred while processing %s (%s%d)"),
379 Pkg.Name(), "NewFileVer", 1);
99a2ea5a 380
ddc1d8d0
AL
381 // Read only a single record and return
382 if (OutVer != 0)
383 {
384 *OutVer = Ver;
385 return true;
386 }
99a2ea5a
DK
387
388 return true;
204fbdcc 389 }
99a2ea5a 390 }
204fbdcc 391
99a2ea5a
DK
392 // Add a new version
393 map_ptrloc const verindex = NewVersion(Ver,Version,*LastVer);
394 if (verindex == 0 && _error->PendingError())
79e9003c
DK
395 return _error->Error(_("Error occurred while processing %s (%s%d)"),
396 Pkg.Name(), "NewVersion", 1);
a9fe5928 397
99a2ea5a 398 if (oldMap != Map.Data())
a9fe5928 399 LastVer += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
99a2ea5a
DK
400 *LastVer = verindex;
401 Ver->ParentPkg = Pkg.Index();
402 Ver->Hash = Hash;
a52f938b 403
79e9003c
DK
404 if (unlikely(List.NewVersion(Ver) == false))
405 return _error->Error(_("Error occurred while processing %s (%s%d)"),
406 Pkg.Name(), "NewVersion", 2);
a9fe5928 407
79e9003c
DK
408 if (unlikely(List.UsePackage(Pkg,Ver) == false))
409 return _error->Error(_("Error occurred while processing %s (%s%d)"),
410 Pkg.Name(), "UsePackage", 3);
411
412 if (unlikely(NewFileVer(Ver,List) == false))
413 return _error->Error(_("Error occurred while processing %s (%s%d)"),
414 Pkg.Name(), "NewFileVer", 2);
a52f938b 415
5a8e963b
DK
416 pkgCache::GrpIterator Grp = Pkg.Group();
417 Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
418
419 /* If it is the first version of this package we need to add implicit
420 Multi-Arch dependencies to all other package versions in the group now -
421 otherwise we just add them for this new version */
422 if (Pkg.VersionList()->NextVer == 0)
423 {
424 pkgCache::PkgIterator P = Grp.PackageList();
425 Dynamic<pkgCache::PkgIterator> DynP(P);
426 for (; P.end() != true; P = Grp.NextPkg(P))
427 {
428 if (P->ID == Pkg->ID)
429 continue;
430 pkgCache::VerIterator V = P.VersionList();
431 Dynamic<pkgCache::VerIterator> DynV(V);
432 for (; V.end() != true; ++V)
433 if (unlikely(AddImplicitDepends(V, Pkg) == false))
434 return _error->Error(_("Error occurred while processing %s (%s%d)"),
435 Pkg.Name(), "AddImplicitDepends", 1);
436 }
c919ad6e
DK
437 /* :none packages are packages without an architecture. They are forbidden by
438 debian-policy, so usually they will only be in (old) dpkg status files -
439 and dpkg will complain about them - and are pretty rare. We therefore do
440 usually not create conflicts while the parent is created, but only if a :none
441 package (= the target) appears. This creates incorrect dependencies on :none
442 for architecture-specific dependencies on the package we copy from, but we
443 will ignore this bug as architecture-specific dependencies are only allowed
444 in jessie and until then the :none packages should be extinct (hopefully).
445 In other words: This should work long enough to allow graceful removal of
446 these packages, it is not supposed to allow users to keep using them … */
447 if (strcmp(Pkg.Arch(), "none") == 0)
448 {
449 pkgCache::PkgIterator M = Grp.FindPreferredPkg();
450 if (M.end() == false && Pkg != M)
451 {
452 pkgCache::DepIterator D = M.RevDependsList();
453 Dynamic<pkgCache::DepIterator> DynD(D);
454 for (; D.end() == false; ++D)
455 {
456 if ((D->Type != pkgCache::Dep::Conflicts &&
457 D->Type != pkgCache::Dep::DpkgBreaks &&
458 D->Type != pkgCache::Dep::Replaces) ||
459 D.ParentPkg().Group() == Grp)
460 continue;
461
462 map_ptrloc *OldDepLast = NULL;
463 pkgCache::VerIterator ConVersion = D.ParentVer();
9abb2283 464 Dynamic<pkgCache::VerIterator> DynV(ConVersion);
c919ad6e 465 // duplicate the Conflicts/Breaks/Replaces for :none arch
9c44383f
DK
466 NewDepends(Pkg, ConVersion, D->Version,
467 D->CompareOp, D->Type, OldDepLast);
c919ad6e
DK
468 }
469 }
470 }
5a8e963b
DK
471 }
472 if (unlikely(AddImplicitDepends(Grp, Pkg, Ver) == false))
473 return _error->Error(_("Error occurred while processing %s (%s%d)"),
474 Pkg.Name(), "AddImplicitDepends", 2);
a52f938b 475
99a2ea5a
DK
476 // Read only a single record and return
477 if (OutVer != 0)
478 {
479 *OutVer = Ver;
480 return true;
578bfd0a 481 }
0149949b 482
5f4db009
DK
483 /* Record the Description (it is not translated) */
484 MD5SumValue CurMd5 = List.Description_md5();
485 if (CurMd5.Value().empty() == true)
486 return true;
487 std::string CurLang = List.DescriptionLanguage();
488
489 /* Before we add a new description we first search in the group for
490 a version with a description of the same MD5 - if so we reuse this
491 description group instead of creating our own for this version */
5f4db009
DK
492 for (pkgCache::PkgIterator P = Grp.PackageList();
493 P.end() == false; P = Grp.NextPkg(P))
494 {
495 for (pkgCache::VerIterator V = P.VersionList();
496 V.end() == false; ++V)
497 {
498 if (IsDuplicateDescription(V.DescriptionList(), CurMd5, "") == false)
499 continue;
500 Ver->DescriptionList = V->DescriptionList;
501 return true;
502 }
503 }
504
505 // We haven't found reusable descriptions, so add the first description
99a2ea5a
DK
506 pkgCache::DescIterator Desc = Ver.DescriptionList();
507 Dynamic<pkgCache::DescIterator> DynDesc(Desc);
99a2ea5a 508
a65e22c6 509 map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, 0);
5954d4d2
DK
510 if (unlikely(descindex == 0 && _error->PendingError()))
511 return _error->Error(_("Error occurred while processing %s (%s%d)"),
512 Pkg.Name(), "NewDescription", 2);
a65e22c6 513
99a2ea5a 514 Desc->ParentPkg = Pkg.Index();
a65e22c6 515 Ver->DescriptionList = descindex;
99a2ea5a 516
a65e22c6 517 if (NewFileDesc(Desc,List) == false)
79e9003c
DK
518 return _error->Error(_("Error occurred while processing %s (%s%d)"),
519 Pkg.Name(), "NewFileDesc", 2);
45415543 520
578bfd0a
AL
521 return true;
522}
523 /*}}}*/
99a2ea5a 524 /*}}}*/
45415543
AL
525// CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/
526// ---------------------------------------------------------------------
527/* If we found any file depends while parsing the main list we need to
528 resolve them. Since it is undesired to load the entire list of files
529 into the cache as virtual packages we do a two stage effort. MergeList
530 identifies the file depends and this creates Provdies for them by
531 re-parsing all the indexs. */
532bool pkgCacheGenerator::MergeFileProvides(ListParser &List)
533{
534 List.Owner = this;
535
536 unsigned int Counter = 0;
537 while (List.Step() == true)
538 {
539 string PackageName = List.Package();
540 if (PackageName.empty() == true)
541 return false;
542 string Version = List.Version();
543 if (Version.empty() == true)
544 continue;
545
546 pkgCache::PkgIterator Pkg = Cache.FindPkg(PackageName);
a9fe5928 547 Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
45415543 548 if (Pkg.end() == true)
79e9003c
DK
549 return _error->Error(_("Error occurred while processing %s (%s%d)"),
550 PackageName.c_str(), "FindPkg", 1);
45415543
AL
551 Counter++;
552 if (Counter % 100 == 0 && Progress != 0)
553 Progress->Progress(List.Offset());
554
555 unsigned long Hash = List.VersionHash();
556 pkgCache::VerIterator Ver = Pkg.VersionList();
a9fe5928 557 Dynamic<pkgCache::VerIterator> DynVer(Ver);
f7f0d6c7 558 for (; Ver.end() == false; ++Ver)
45415543
AL
559 {
560 if (Ver->Hash == Hash && Version.c_str() == Ver.VerStr())
561 {
562 if (List.CollectFileProvides(Cache,Ver) == false)
79e9003c
DK
563 return _error->Error(_("Error occurred while processing %s (%s%d)"),
564 PackageName.c_str(), "CollectFileProvides", 1);
45415543
AL
565 break;
566 }
567 }
568
569 if (Ver.end() == true)
570 _error->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName.c_str(),Version.c_str());
571 }
572
573 return true;
574}
575 /*}}}*/
5bf15716
DK
576// CacheGenerator::NewGroup - Add a new group /*{{{*/
577// ---------------------------------------------------------------------
578/* This creates a new group structure and adds it to the hash table */
33dd02e3
DK
579bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name)
580{
581 Grp = Cache.FindGrp(Name);
582 if (Grp.end() == false)
583 return true;
5bf15716 584
33dd02e3 585 // Get a structure
a9fe5928 586 map_ptrloc const Group = AllocateInMap(sizeof(pkgCache::Group));
33dd02e3
DK
587 if (unlikely(Group == 0))
588 return false;
5bf15716 589
33dd02e3 590 Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group);
a9fe5928
DK
591 map_ptrloc const idxName = WriteStringInMap(Name);
592 if (unlikely(idxName == 0))
33dd02e3 593 return false;
a9fe5928 594 Grp->Name = idxName;
5bf15716 595
33dd02e3
DK
596 // Insert it into the hash table
597 unsigned long const Hash = Cache.Hash(Name);
598 Grp->Next = Cache.HeaderP->GrpHashTable[Hash];
599 Cache.HeaderP->GrpHashTable[Hash] = Group;
5bf15716 600
52c41485 601 Grp->ID = Cache.HeaderP->GroupCount++;
33dd02e3 602 return true;
5bf15716
DK
603}
604 /*}}}*/
578bfd0a
AL
605// CacheGenerator::NewPackage - Add a new package /*{{{*/
606// ---------------------------------------------------------------------
607/* This creates a new package structure and adds it to the hash table */
5bf15716
DK
608bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name,
609 const string &Arch) {
610 pkgCache::GrpIterator Grp;
a9fe5928 611 Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
5bf15716
DK
612 if (unlikely(NewGroup(Grp, Name) == false))
613 return false;
614
615 Pkg = Grp.FindPkg(Arch);
616 if (Pkg.end() == false)
617 return true;
a52f938b 618
578bfd0a 619 // Get a structure
a9fe5928 620 map_ptrloc const Package = AllocateInMap(sizeof(pkgCache::Package));
5bf15716 621 if (unlikely(Package == 0))
578bfd0a 622 return false;
f55a958f 623 Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
5bf15716 624
c408e01e
DK
625 // Insert the package into our package list
626 if (Grp->FirstPackage == 0) // the group is new
627 {
628 // Insert it into the hash table
629 unsigned long const Hash = Cache.Hash(Name);
630 Pkg->NextPackage = Cache.HeaderP->PkgHashTable[Hash];
631 Cache.HeaderP->PkgHashTable[Hash] = Package;
632 Grp->FirstPackage = Package;
633 }
634 else // Group the Packages together
635 {
636 // this package is the new last package
637 pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage);
638 Pkg->NextPackage = LastPkg->NextPackage;
639 LastPkg->NextPackage = Package;
640 }
641 Grp->LastPackage = Package;
5bf15716
DK
642
643 // Set the name, arch and the ID
644 Pkg->Name = Grp->Name;
645 Pkg->Group = Grp.Index();
959470da
DK
646 // all is mapped to the native architecture
647 map_ptrloc const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : WriteUniqString(Arch.c_str());
a9fe5928 648 if (unlikely(idxArch == 0))
578bfd0a 649 return false;
a9fe5928 650 Pkg->Arch = idxArch;
578bfd0a 651 Pkg->ID = Cache.HeaderP->PackageCount++;
5bf15716 652
578bfd0a
AL
653 return true;
654}
5a8e963b
DK
655 /*}}}*/
656// CacheGenerator::AddImplicitDepends /*{{{*/
657bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator &G,
658 pkgCache::PkgIterator &P,
659 pkgCache::VerIterator &V)
660{
661 // copy P.Arch() into a string here as a cache remap
662 // in NewDepends() later may alter the pointer location
663 string Arch = P.Arch() == NULL ? "" : P.Arch();
664 map_ptrloc *OldDepLast = NULL;
665 /* MultiArch handling introduces a lot of implicit Dependencies:
666 - MultiArch: same → Co-Installable if they have the same version
667 - All others conflict with all other group members */
668 bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
669 pkgCache::PkgIterator D = G.PackageList();
670 Dynamic<pkgCache::PkgIterator> DynD(D);
9c44383f 671 map_ptrloc const VerStrIdx = V->VerStr;
5a8e963b
DK
672 for (; D.end() != true; D = G.NextPkg(D))
673 {
674 if (Arch == D.Arch() || D->VersionList == 0)
675 continue;
676 /* We allow only one installed arch at the time
677 per group, therefore each group member conflicts
678 with all other group members */
679 if (coInstall == true)
680 {
681 // Replaces: ${self}:other ( << ${binary:Version})
9c44383f 682 NewDepends(D, V, VerStrIdx,
5a8e963b
DK
683 pkgCache::Dep::Less, pkgCache::Dep::Replaces,
684 OldDepLast);
685 // Breaks: ${self}:other (!= ${binary:Version})
9c44383f 686 NewDepends(D, V, VerStrIdx,
5a8e963b
DK
687 pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks,
688 OldDepLast);
689 } else {
690 // Conflicts: ${self}:other
9c44383f 691 NewDepends(D, V, 0,
5a8e963b
DK
692 pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts,
693 OldDepLast);
694 }
695 }
696 return true;
697}
698bool pkgCacheGenerator::AddImplicitDepends(pkgCache::VerIterator &V,
699 pkgCache::PkgIterator &D)
700{
701 /* MultiArch handling introduces a lot of implicit Dependencies:
702 - MultiArch: same → Co-Installable if they have the same version
703 - All others conflict with all other group members */
704 map_ptrloc *OldDepLast = NULL;
705 bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
706 if (coInstall == true)
707 {
9c44383f 708 map_ptrloc const VerStrIdx = V->VerStr;
5a8e963b 709 // Replaces: ${self}:other ( << ${binary:Version})
9c44383f 710 NewDepends(D, V, VerStrIdx,
5a8e963b
DK
711 pkgCache::Dep::Less, pkgCache::Dep::Replaces,
712 OldDepLast);
713 // Breaks: ${self}:other (!= ${binary:Version})
9c44383f 714 NewDepends(D, V, VerStrIdx,
5a8e963b
DK
715 pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks,
716 OldDepLast);
717 } else {
718 // Conflicts: ${self}:other
9c44383f 719 NewDepends(D, V, 0,
5a8e963b
DK
720 pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts,
721 OldDepLast);
722 }
723 return true;
724}
725
578bfd0a
AL
726 /*}}}*/
727// CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
728// ---------------------------------------------------------------------
729/* */
f55a958f 730bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver,
578bfd0a
AL
731 ListParser &List)
732{
ddc1d8d0
AL
733 if (CurrentFile == 0)
734 return true;
735
dcb79bae 736 // Get a structure
a9fe5928 737 map_ptrloc const VerFile = AllocateInMap(sizeof(pkgCache::VerFile));
dcb79bae
AL
738 if (VerFile == 0)
739 return 0;
740
741 pkgCache::VerFileIterator VF(Cache,Cache.VerFileP + VerFile);
742 VF->File = CurrentFile - Cache.PkgFileP;
03e39e59
AL
743
744 // Link it to the end of the list
349cd3b8 745 map_ptrloc *Last = &Ver->FileList;
f7f0d6c7 746 for (pkgCache::VerFileIterator V = Ver.FileList(); V.end() == false; ++V)
03e39e59
AL
747 Last = &V->NextFile;
748 VF->NextFile = *Last;
749 *Last = VF.Index();
750
dcb79bae
AL
751 VF->Offset = List.Offset();
752 VF->Size = List.Size();
ad00ae81
AL
753 if (Cache.HeaderP->MaxVerFileSize < VF->Size)
754 Cache.HeaderP->MaxVerFileSize = VF->Size;
a7e66b17
AL
755 Cache.HeaderP->VerFileCount++;
756
f55a958f 757 return true;
578bfd0a
AL
758}
759 /*}}}*/
760// CacheGenerator::NewVersion - Create a new Version /*{{{*/
761// ---------------------------------------------------------------------
f55a958f 762/* This puts a version structure in the linked list */
578bfd0a 763unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
171c75f1 764 const string &VerStr,
578bfd0a
AL
765 unsigned long Next)
766{
f55a958f 767 // Get a structure
a9fe5928 768 map_ptrloc const Version = AllocateInMap(sizeof(pkgCache::Version));
f55a958f 769 if (Version == 0)
0149949b 770 return 0;
f55a958f
AL
771
772 // Fill it in
773 Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version);
dfe45e1f 774 //Dynamic<pkgCache::VerIterator> DynV(Ver); // caller MergeListVersion already takes care of it
f55a958f
AL
775 Ver->NextVer = Next;
776 Ver->ID = Cache.HeaderP->VersionCount++;
a9fe5928
DK
777 map_ptrloc const idxVerStr = WriteStringInMap(VerStr);
778 if (unlikely(idxVerStr == 0))
0149949b 779 return 0;
a9fe5928 780 Ver->VerStr = idxVerStr;
f55a958f 781
0149949b 782 return Version;
578bfd0a
AL
783}
784 /*}}}*/
a52f938b
OS
785// CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/
786// ---------------------------------------------------------------------
787/* */
788bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc,
789 ListParser &List)
790{
791 if (CurrentFile == 0)
792 return true;
793
794 // Get a structure
a9fe5928 795 map_ptrloc const DescFile = AllocateInMap(sizeof(pkgCache::DescFile));
a52f938b 796 if (DescFile == 0)
c5f44afc 797 return false;
770c32ec 798
a52f938b
OS
799 pkgCache::DescFileIterator DF(Cache,Cache.DescFileP + DescFile);
800 DF->File = CurrentFile - Cache.PkgFileP;
770c32ec 801
a52f938b
OS
802 // Link it to the end of the list
803 map_ptrloc *Last = &Desc->FileList;
f7f0d6c7 804 for (pkgCache::DescFileIterator D = Desc.FileList(); D.end() == false; ++D)
a52f938b 805 Last = &D->NextFile;
770c32ec 806
a52f938b
OS
807 DF->NextFile = *Last;
808 *Last = DF.Index();
809
810 DF->Offset = List.Offset();
811 DF->Size = List.Size();
812 if (Cache.HeaderP->MaxDescFileSize < DF->Size)
813 Cache.HeaderP->MaxDescFileSize = DF->Size;
814 Cache.HeaderP->DescFileCount++;
815
816 return true;
817}
818 /*}}}*/
819// CacheGenerator::NewDescription - Create a new Description /*{{{*/
820// ---------------------------------------------------------------------
821/* This puts a description structure in the linked list */
822map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
a65e22c6
DK
823 const string &Lang,
824 const MD5SumValue &md5sum,
825 map_ptrloc idxmd5str)
a52f938b
OS
826{
827 // Get a structure
a9fe5928 828 map_ptrloc const Description = AllocateInMap(sizeof(pkgCache::Description));
a52f938b
OS
829 if (Description == 0)
830 return 0;
831
832 // Fill it in
833 Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description);
a52f938b 834 Desc->ID = Cache.HeaderP->DescriptionCount++;
734b7c81 835 map_ptrloc const idxlanguage_code = WriteUniqString(Lang);
a65e22c6 836 if (unlikely(idxlanguage_code == 0))
c5f44afc 837 return 0;
a9fe5928 838 Desc->language_code = idxlanguage_code;
a65e22c6
DK
839
840 if (idxmd5str != 0)
841 Desc->md5sum = idxmd5str;
842 else
843 {
844 map_ptrloc const idxmd5sum = WriteStringInMap(md5sum.Value());
845 if (unlikely(idxmd5sum == 0))
846 return 0;
847 Desc->md5sum = idxmd5sum;
848 }
a52f938b
OS
849
850 return Description;
851}
852 /*}}}*/
25396fb0 853// CacheGenerator::NewDepends - Create a dependency element /*{{{*/
dcb79bae
AL
854// ---------------------------------------------------------------------
855/* This creates a dependency element in the tree. It is linked to the
856 version and to the package that it is pointing to. */
25396fb0
DK
857bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
858 pkgCache::VerIterator &Ver,
859 string const &Version,
860 unsigned int const &Op,
861 unsigned int const &Type,
64dda04b 862 map_ptrloc* &OldDepLast)
9c44383f
DK
863{
864 map_ptrloc index = 0;
865 if (Version.empty() == false)
866 {
b8a884c0
DK
867 int const CmpOp = Op & 0x0F;
868 // =-deps are used (79:1) for lockstep on same-source packages (e.g. data-packages)
869 if (CmpOp == pkgCache::Dep::Equals && strcmp(Version.c_str(), Ver.VerStr()) == 0)
870 index = Ver->VerStr;
871
872 if (index == 0)
873 {
874 void const * const oldMap = Map.Data();
875 index = WriteStringInMap(Version);
876 if (unlikely(index == 0))
877 return false;
878 if (oldMap != Map.Data())
879 OldDepLast += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
880 }
9c44383f
DK
881 }
882 return NewDepends(Pkg, Ver, index, Op, Type, OldDepLast);
883}
884bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
885 pkgCache::VerIterator &Ver,
886 map_ptrloc const Version,
887 unsigned int const &Op,
888 unsigned int const &Type,
889 map_ptrloc* &OldDepLast)
dcb79bae 890{
a9fe5928 891 void const * const oldMap = Map.Data();
dcb79bae 892 // Get a structure
a9fe5928 893 map_ptrloc const Dependency = AllocateInMap(sizeof(pkgCache::Dependency));
5bf15716 894 if (unlikely(Dependency == 0))
dcb79bae 895 return false;
9c44383f 896
dcb79bae
AL
897 // Fill it in
898 pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency);
a9fe5928 899 Dynamic<pkgCache::DepIterator> DynDep(Dep);
dcb79bae
AL
900 Dep->ParentVer = Ver.Index();
901 Dep->Type = Type;
902 Dep->CompareOp = Op;
9c44383f 903 Dep->Version = Version;
dcb79bae 904 Dep->ID = Cache.HeaderP->DependsCount++;
5bf15716 905
dcb79bae
AL
906 // Link it to the package
907 Dep->Package = Pkg.Index();
908 Dep->NextRevDepends = Pkg->RevDepends;
909 Pkg->RevDepends = Dep.Index();
25396fb0
DK
910
911 // Do we know where to link the Dependency to?
912 if (OldDepLast == NULL)
c1a22377 913 {
f9eec0e7 914 OldDepLast = &Ver->DependsList;
f7f0d6c7 915 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
f9eec0e7 916 OldDepLast = &D->NextDepends;
a9fe5928
DK
917 } else if (oldMap != Map.Data())
918 OldDepLast += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
45415543 919
f9eec0e7
AL
920 Dep->NextDepends = *OldDepLast;
921 *OldDepLast = Dep.Index();
922 OldDepLast = &Dep->NextDepends;
c1a22377 923
dcb79bae
AL
924 return true;
925}
926 /*}}}*/
25396fb0
DK
927// ListParser::NewDepends - Create the environment for a new dependency /*{{{*/
928// ---------------------------------------------------------------------
929/* This creates a Group and the Package to link this dependency to if
930 needed and handles also the caching of the old endpoint */
32b9a14c 931bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
25396fb0
DK
932 const string &PackageName,
933 const string &Arch,
934 const string &Version,
935 unsigned int Op,
936 unsigned int Type)
937{
938 pkgCache::GrpIterator Grp;
a9fe5928 939 Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
25396fb0
DK
940 if (unlikely(Owner->NewGroup(Grp, PackageName) == false))
941 return false;
942
943 // Locate the target package
944 pkgCache::PkgIterator Pkg = Grp.FindPkg(Arch);
c919ad6e 945 // we don't create 'none' packages and their dependencies if we can avoid it …
7605509f 946 if (Pkg.end() == true && Arch == "none" && strcmp(Ver.ParentPkg().Arch(), "none") != 0)
c919ad6e 947 return true;
a9fe5928 948 Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
25396fb0
DK
949 if (Pkg.end() == true) {
950 if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false))
951 return false;
952 }
953
954 // Is it a file dependency?
955 if (unlikely(PackageName[0] == '/'))
956 FoundFileDeps = true;
957
958 /* Caching the old end point speeds up generation substantially */
959 if (OldDepVer != Ver) {
960 OldDepLast = NULL;
961 OldDepVer = Ver;
962 }
963
964 return Owner->NewDepends(Pkg, Ver, Version, Op, Type, OldDepLast);
965}
966 /*}}}*/
dcb79bae
AL
967// ListParser::NewProvides - Create a Provides element /*{{{*/
968// ---------------------------------------------------------------------
969/* */
32b9a14c 970bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver,
67e0766f
DK
971 const string &PkgName,
972 const string &PkgArch,
171c75f1 973 const string &Version)
dcb79bae
AL
974{
975 pkgCache &Cache = Owner->Cache;
8efa2a3b
AL
976
977 // We do not add self referencing provides
566046f4 978 if (Ver.ParentPkg().Name() == PkgName && (PkgArch == Ver.ParentPkg().Arch() ||
959470da 979 (PkgArch == "all" && strcmp((Cache.StrP + Cache.HeaderP->Architecture), Ver.ParentPkg().Arch()) == 0)))
8efa2a3b 980 return true;
dcb79bae
AL
981
982 // Get a structure
a9fe5928 983 map_ptrloc const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides));
5bf15716 984 if (unlikely(Provides == 0))
dcb79bae 985 return false;
a7e66b17 986 Cache.HeaderP->ProvidesCount++;
dcb79bae
AL
987
988 // Fill it in
989 pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP);
a9fe5928 990 Dynamic<pkgCache::PrvIterator> DynPrv(Prv);
dcb79bae
AL
991 Prv->Version = Ver.Index();
992 Prv->NextPkgProv = Ver->ProvidesList;
993 Ver->ProvidesList = Prv.Index();
27cae771
MV
994 if (Version.empty() == false) {
995 map_ptrloc const idxProvideVersion = WriteString(Version);
996 Prv->ProvideVersion = idxProvideVersion;
997 if (unlikely(idxProvideVersion == 0))
998 return false;
999 }
dcb79bae
AL
1000
1001 // Locate the target package
8efa2a3b 1002 pkgCache::PkgIterator Pkg;
a9fe5928 1003 Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
67e0766f 1004 if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false))
8efa2a3b 1005 return false;
dcb79bae
AL
1006
1007 // Link it to the package
1008 Prv->ParentPkg = Pkg.Index();
1009 Prv->NextProvides = Pkg->ProvidesList;
1010 Pkg->ProvidesList = Prv.Index();
1011
1012 return true;
1013}
1014 /*}}}*/
578bfd0a
AL
1015// CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
1016// ---------------------------------------------------------------------
1017/* This is used to select which file is to be associated with all newly
b2e465d6 1018 added versions. The caller is responsible for setting the IMS fields. */
171c75f1 1019bool pkgCacheGenerator::SelectFile(const string &File,const string &Site,
b2e465d6
AL
1020 const pkgIndexFile &Index,
1021 unsigned long Flags)
578bfd0a 1022{
578bfd0a 1023 // Get some space for the structure
a9fe5928
DK
1024 map_ptrloc const idxFile = AllocateInMap(sizeof(*CurrentFile));
1025 if (unlikely(idxFile == 0))
578bfd0a 1026 return false;
a9fe5928
DK
1027 CurrentFile = Cache.PkgFileP + idxFile;
1028
578bfd0a 1029 // Fill it in
a9fe5928
DK
1030 map_ptrloc const idxFileName = WriteStringInMap(File);
1031 map_ptrloc const idxSite = WriteUniqString(Site);
1032 if (unlikely(idxFileName == 0 || idxSite == 0))
1033 return false;
1034 CurrentFile->FileName = idxFileName;
1035 CurrentFile->Site = idxSite;
578bfd0a
AL
1036 CurrentFile->NextFile = Cache.HeaderP->FileList;
1037 CurrentFile->Flags = Flags;
e1b74f61 1038 CurrentFile->ID = Cache.HeaderP->PackageFileCount;
a9fe5928
DK
1039 map_ptrloc const idxIndexType = WriteUniqString(Index.GetType()->Label);
1040 if (unlikely(idxIndexType == 0))
1041 return false;
1042 CurrentFile->IndexType = idxIndexType;
578bfd0a 1043 PkgFileName = File;
ad00ae81 1044 Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP;
b35d2f5f 1045 Cache.HeaderP->PackageFileCount++;
b2e465d6 1046
ddc1d8d0 1047 if (Progress != 0)
b2e465d6 1048 Progress->SubProgress(Index.Size());
8efa2a3b 1049 return true;
578bfd0a
AL
1050}
1051 /*}}}*/
f55a958f
AL
1052// CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
1053// ---------------------------------------------------------------------
1054/* This is used to create handles to strings. Given the same text it
1055 always returns the same number */
1056unsigned long pkgCacheGenerator::WriteUniqString(const char *S,
1057 unsigned int Size)
1058{
f9eec0e7
AL
1059 /* We use a very small transient hash table here, this speeds up generation
1060 by a fair amount on slower machines */
1061 pkgCache::StringItem *&Bucket = UniqHash[(S[0]*5 + S[1]) % _count(UniqHash)];
1062 if (Bucket != 0 &&
1063 stringcmp(S,S+Size,Cache.StrP + Bucket->String) == 0)
1064 return Bucket->String;
1065
f55a958f
AL
1066 // Search for an insertion point
1067 pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList;
1068 int Res = 1;
349cd3b8 1069 map_ptrloc *Last = &Cache.HeaderP->StringList;
f55a958f
AL
1070 for (; I != Cache.StringItemP; Last = &I->NextItem,
1071 I = Cache.StringItemP + I->NextItem)
1072 {
9c14e3d6 1073 Res = stringcmp(S,S+Size,Cache.StrP + I->String);
f55a958f
AL
1074 if (Res >= 0)
1075 break;
1076 }
1077
1078 // Match
1079 if (Res == 0)
f9eec0e7
AL
1080 {
1081 Bucket = I;
0149949b 1082 return I->String;
f9eec0e7 1083 }
f55a958f
AL
1084
1085 // Get a structure
a9fe5928
DK
1086 void const * const oldMap = Map.Data();
1087 map_ptrloc const Item = AllocateInMap(sizeof(pkgCache::StringItem));
f55a958f 1088 if (Item == 0)
0149949b
AL
1089 return 0;
1090
a9fe5928
DK
1091 map_ptrloc const idxString = WriteStringInMap(S,Size);
1092 if (unlikely(idxString == 0))
1093 return 0;
1094 if (oldMap != Map.Data()) {
1095 Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
1096 I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
1097 }
1098 *Last = Item;
1099
f55a958f
AL
1100 // Fill in the structure
1101 pkgCache::StringItem *ItemP = Cache.StringItemP + Item;
1102 ItemP->NextItem = I - Cache.StringItemP;
a9fe5928
DK
1103 ItemP->String = idxString;
1104
f9eec0e7 1105 Bucket = ItemP;
0149949b 1106 return ItemP->String;
f55a958f
AL
1107}
1108 /*}}}*/
b2e465d6 1109// CheckValidity - Check that a cache is up-to-date /*{{{*/
b35d2f5f 1110// ---------------------------------------------------------------------
b2e465d6
AL
1111/* This just verifies that each file in the list of index files exists,
1112 has matching attributes with the cache and the cache does not have
1113 any extra files. */
2ec858bc
MV
1114static bool CheckValidity(const string &CacheFile,
1115 pkgSourceList &List,
1116 FileIterator Start,
1117 FileIterator End,
1118 MMap **OutMap = 0)
b35d2f5f 1119{
c8e572e3 1120 bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
b2e465d6
AL
1121 // No file, certainly invalid
1122 if (CacheFile.empty() == true || FileExists(CacheFile) == false)
c8e572e3
MV
1123 {
1124 if (Debug == true)
1125 std::clog << "CacheFile doesn't exist" << std::endl;
b35d2f5f 1126 return false;
c8e572e3
MV
1127 }
1128
96d14a91 1129 if (List.GetLastModifiedTime() > GetModificationTime(CacheFile))
2ec858bc
MV
1130 {
1131 if (Debug == true)
1132 std::clog << "sources.list is newer than the cache" << std::endl;
1133 return false;
1134 }
1135
b2e465d6 1136 // Map it
b35d2f5f 1137 FileFd CacheF(CacheFile,FileFd::ReadOnly);
eb162ff7 1138 SPtr<MMap> Map = new MMap(CacheF,0);
b35d2f5f 1139 pkgCache Cache(Map);
b2e465d6 1140 if (_error->PendingError() == true || Map->Size() == 0)
b35d2f5f 1141 {
c8e572e3
MV
1142 if (Debug == true)
1143 std::clog << "Errors are pending or Map is empty()" << std::endl;
b35d2f5f
AL
1144 _error->Discard();
1145 return false;
1146 }
b35d2f5f 1147
b2e465d6
AL
1148 /* Now we check every index file, see if it is in the cache,
1149 verify the IMS data and check that it is on the disk too.. */
1150 SPtrArray<bool> Visited = new bool[Cache.HeaderP->PackageFileCount];
1151 memset(Visited,0,sizeof(*Visited)*Cache.HeaderP->PackageFileCount);
f7f0d6c7 1152 for (; Start != End; ++Start)
c8e572e3
MV
1153 {
1154 if (Debug == true)
1155 std::clog << "Checking PkgFile " << (*Start)->Describe() << ": ";
b2e465d6 1156 if ((*Start)->HasPackages() == false)
c8e572e3
MV
1157 {
1158 if (Debug == true)
1159 std::clog << "Has NO packages" << std::endl;
b2e465d6 1160 continue;
c8e572e3 1161 }
a77ad7c3 1162
b2e465d6 1163 if ((*Start)->Exists() == false)
b35d2f5f 1164 {
a791a450 1165#if 0 // mvo: we no longer give a message here (Default Sources spec)
b2e465d6
AL
1166 _error->WarningE("stat",_("Couldn't stat source package list %s"),
1167 (*Start)->Describe().c_str());
a791a450 1168#endif
c8e572e3
MV
1169 if (Debug == true)
1170 std::clog << "file doesn't exist" << std::endl;
b2e465d6 1171 continue;
b35d2f5f 1172 }
b2e465d6
AL
1173
1174 // FindInCache is also expected to do an IMS check.
1175 pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache);
1176 if (File.end() == true)
c8e572e3
MV
1177 {
1178 if (Debug == true)
1179 std::clog << "FindInCache returned end-Pointer" << std::endl;
b35d2f5f 1180 return false;
c8e572e3 1181 }
a52f938b 1182
b2e465d6 1183 Visited[File->ID] = true;
c8e572e3
MV
1184 if (Debug == true)
1185 std::clog << "with ID " << File->ID << " is valid" << std::endl;
b35d2f5f
AL
1186 }
1187
b2e465d6
AL
1188 for (unsigned I = 0; I != Cache.HeaderP->PackageFileCount; I++)
1189 if (Visited[I] == false)
c8e572e3
MV
1190 {
1191 if (Debug == true)
1192 std::clog << "File with ID" << I << " wasn't visited" << std::endl;
b2e465d6 1193 return false;
c8e572e3 1194 }
b35d2f5f 1195
b35d2f5f
AL
1196 if (_error->PendingError() == true)
1197 {
c8e572e3
MV
1198 if (Debug == true)
1199 {
1200 std::clog << "Validity failed because of pending errors:" << std::endl;
1201 _error->DumpErrors();
1202 }
b35d2f5f
AL
1203 _error->Discard();
1204 return false;
1205 }
b35d2f5f 1206
b2e465d6
AL
1207 if (OutMap != 0)
1208 *OutMap = Map.UnGuard();
b35d2f5f
AL
1209 return true;
1210}
1211 /*}}}*/
b2e465d6 1212// ComputeSize - Compute the total size of a bunch of files /*{{{*/
b35d2f5f 1213// ---------------------------------------------------------------------
b2e465d6
AL
1214/* Size is kind of an abstract notion that is only used for the progress
1215 meter */
e7b470ee 1216static unsigned long ComputeSize(FileIterator Start,FileIterator End)
b35d2f5f 1217{
b2e465d6 1218 unsigned long TotalSize = 0;
f7f0d6c7 1219 for (; Start != End; ++Start)
b35d2f5f 1220 {
b2e465d6
AL
1221 if ((*Start)->HasPackages() == false)
1222 continue;
1223 TotalSize += (*Start)->Size();
b35d2f5f 1224 }
b2e465d6 1225 return TotalSize;
2d11135a
AL
1226}
1227 /*}}}*/
b2e465d6 1228// BuildCache - Merge the list of index files into the cache /*{{{*/
2d11135a 1229// ---------------------------------------------------------------------
b2e465d6
AL
1230/* */
1231static bool BuildCache(pkgCacheGenerator &Gen,
2e5f4e45 1232 OpProgress *Progress,
b2e465d6 1233 unsigned long &CurrentSize,unsigned long TotalSize,
e7b470ee 1234 FileIterator Start, FileIterator End)
2d11135a 1235{
45415543 1236 FileIterator I;
f7f0d6c7 1237 for (I = Start; I != End; ++I)
2d11135a 1238 {
45415543 1239 if ((*I)->HasPackages() == false)
2d11135a
AL
1240 continue;
1241
45415543 1242 if ((*I)->Exists() == false)
2d11135a 1243 continue;
b2e465d6 1244
45415543 1245 if ((*I)->FindInCache(Gen.GetCache()).end() == false)
a77ad7c3
AL
1246 {
1247 _error->Warning("Duplicate sources.list entry %s",
45415543 1248 (*I)->Describe().c_str());
a77ad7c3
AL
1249 continue;
1250 }
1251
45415543 1252 unsigned long Size = (*I)->Size();
2e5f4e45
DK
1253 if (Progress != NULL)
1254 Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
b2e465d6 1255 CurrentSize += Size;
2d11135a 1256
45415543 1257 if ((*I)->Merge(Gen,Progress) == false)
b2e465d6
AL
1258 return false;
1259 }
45415543
AL
1260
1261 if (Gen.HasFileDeps() == true)
1262 {
2e5f4e45
DK
1263 if (Progress != NULL)
1264 Progress->Done();
45415543
AL
1265 TotalSize = ComputeSize(Start, End);
1266 CurrentSize = 0;
f7f0d6c7 1267 for (I = Start; I != End; ++I)
45415543
AL
1268 {
1269 unsigned long Size = (*I)->Size();
2e5f4e45
DK
1270 if (Progress != NULL)
1271 Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides"));
45415543
AL
1272 CurrentSize += Size;
1273 if ((*I)->MergeFileProvides(Gen,Progress) == false)
1274 return false;
1275 }
1276 }
2d11135a 1277
b35d2f5f
AL
1278 return true;
1279}
1280 /*}}}*/
dd13742e 1281// CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/
dcdf1ef1
DK
1282DynamicMMap* pkgCacheGenerator::CreateDynamicMMap(FileFd *CacheF, unsigned long Flags) {
1283 unsigned long const MapStart = _config->FindI("APT::Cache-Start", 24*1024*1024);
1284 unsigned long const MapGrow = _config->FindI("APT::Cache-Grow", 1*1024*1024);
1285 unsigned long const MapLimit = _config->FindI("APT::Cache-Limit", 0);
1286 Flags |= MMap::Moveable;
1287 if (_config->FindB("APT::Cache-Fallback", false) == true)
1288 Flags |= MMap::Fallback;
1289 if (CacheF != NULL)
1290 return new DynamicMMap(*CacheF, Flags, MapStart, MapGrow, MapLimit);
1291 else
1292 return new DynamicMMap(Flags, MapStart, MapGrow, MapLimit);
1293}
dd13742e 1294 /*}}}*/
2e5f4e45 1295// CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
b35d2f5f 1296// ---------------------------------------------------------------------
b2e465d6
AL
1297/* This makes sure that the status cache (the cache that has all
1298 index files from the sources list and all local ones) is ready
1299 to be mmaped. If OutMap is not zero then a MMap object representing
1300 the cache will be stored there. This is pretty much mandetory if you
1301 are using AllowMem. AllowMem lets the function be run as non-root
1302 where it builds the cache 'fast' into a memory buffer. */
2e5f4e45
DK
1303__deprecated bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
1304 MMap **OutMap, bool AllowMem)
1305 { return pkgCacheGenerator::MakeStatusCache(List, &Progress, OutMap, AllowMem); }
1306bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress,
b2e465d6 1307 MMap **OutMap,bool AllowMem)
b35d2f5f 1308{
c8e572e3 1309 bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
73688d27
DK
1310
1311 std::vector<pkgIndexFile *> Files;
1312 for (std::vector<metaIndex *>::const_iterator i = List.begin();
7db98ffc 1313 i != List.end();
f7f0d6c7 1314 ++i)
7db98ffc 1315 {
73688d27
DK
1316 std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles();
1317 for (std::vector<pkgIndexFile *>::const_iterator j = Indexes->begin();
7db98ffc 1318 j != Indexes->end();
f7f0d6c7 1319 ++j)
7db98ffc
MZ
1320 Files.push_back (*j);
1321 }
1322
c8e572e3 1323 unsigned long const EndOfSource = Files.size();
b2e465d6
AL
1324 if (_system->AddStatusFiles(Files) == false)
1325 return false;
c5f44afc 1326
b2e465d6 1327 // Decide if we can write to the files..
c8e572e3
MV
1328 string const CacheFile = _config->FindFile("Dir::Cache::pkgcache");
1329 string const SrcCacheFile = _config->FindFile("Dir::Cache::srcpkgcache");
1cd1c398
DK
1330
1331 // ensure the cache directory exists
1332 if (CacheFile.empty() == false || SrcCacheFile.empty() == false)
1333 {
1334 string dir = _config->FindDir("Dir::Cache");
1335 size_t const len = dir.size();
1336 if (len > 5 && dir.find("/apt/", len - 6, 5) == len - 5)
1337 dir = dir.substr(0, len - 5);
1338 if (CacheFile.empty() == false)
1339 CreateDirectory(dir, flNotFile(CacheFile));
1340 if (SrcCacheFile.empty() == false)
1341 CreateDirectory(dir, flNotFile(SrcCacheFile));
1342 }
1343
b2e465d6
AL
1344 // Decide if we can write to the cache
1345 bool Writeable = false;
1346 if (CacheFile.empty() == false)
1347 Writeable = access(flNotFile(CacheFile).c_str(),W_OK) == 0;
1348 else
1349 if (SrcCacheFile.empty() == false)
1350 Writeable = access(flNotFile(SrcCacheFile).c_str(),W_OK) == 0;
c8e572e3
MV
1351 if (Debug == true)
1352 std::clog << "Do we have write-access to the cache files? " << (Writeable ? "YES" : "NO") << std::endl;
1353
b2e465d6
AL
1354 if (Writeable == false && AllowMem == false && CacheFile.empty() == false)
1355 return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str());
2e5f4e45
DK
1356
1357 if (Progress != NULL)
1358 Progress->OverallProgress(0,1,1,_("Reading package lists"));
1359
b2e465d6 1360 // Cache is OK, Fin.
2ec858bc 1361 if (CheckValidity(CacheFile, List, Files.begin(),Files.end(),OutMap) == true)
b2e465d6 1362 {
2e5f4e45
DK
1363 if (Progress != NULL)
1364 Progress->OverallProgress(1,1,1,_("Reading package lists"));
c8e572e3
MV
1365 if (Debug == true)
1366 std::clog << "pkgcache.bin is valid - no need to build anything" << std::endl;
b2e465d6
AL
1367 return true;
1368 }
c8e572e3
MV
1369 else if (Debug == true)
1370 std::clog << "pkgcache.bin is NOT valid" << std::endl;
b2e465d6
AL
1371
1372 /* At this point we know we need to reconstruct the package cache,
1373 begin. */
1374 SPtr<FileFd> CacheF;
1375 SPtr<DynamicMMap> Map;
1376 if (Writeable == true && CacheFile.empty() == false)
1377 {
41b4dee4 1378 _error->PushToStack();
b2e465d6 1379 unlink(CacheFile.c_str());
22041bd2 1380 CacheF = new FileFd(CacheFile,FileFd::WriteAtomic);
7a3c2ab0 1381 fchmod(CacheF->Fd(),0644);
dcdf1ef1 1382 Map = CreateDynamicMMap(CacheF, MMap::Public);
b35d2f5f 1383 if (_error->PendingError() == true)
41b4dee4
DK
1384 {
1385 delete CacheF.UnGuard();
1386 delete Map.UnGuard();
1387 if (Debug == true)
1388 std::clog << "Open filebased MMap FAILED" << std::endl;
1389 Writeable = false;
1390 if (AllowMem == false)
1391 {
1392 _error->MergeWithStack();
1393 return false;
1394 }
1395 _error->RevertToStack();
1396 }
0952aee6 1397 else
41b4dee4
DK
1398 {
1399 _error->MergeWithStack();
0952aee6
DH
1400 if (Debug == true)
1401 std::clog << "Open filebased MMap" << std::endl;
41b4dee4 1402 }
b35d2f5f 1403 }
41b4dee4 1404 if (Writeable == false || CacheFile.empty() == true)
8ce4327b 1405 {
b2e465d6 1406 // Just build it in memory..
dcdf1ef1 1407 Map = CreateDynamicMMap(NULL);
c8e572e3
MV
1408 if (Debug == true)
1409 std::clog << "Open memory Map (not filebased)" << std::endl;
8ce4327b 1410 }
b35d2f5f 1411
b2e465d6 1412 // Lets try the source cache.
b35d2f5f 1413 unsigned long CurrentSize = 0;
b2e465d6 1414 unsigned long TotalSize = 0;
2ec858bc 1415 if (CheckValidity(SrcCacheFile, List, Files.begin(),
b2e465d6 1416 Files.begin()+EndOfSource) == true)
2d11135a 1417 {
c8e572e3
MV
1418 if (Debug == true)
1419 std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl;
b2e465d6
AL
1420 // Preload the map with the source cache
1421 FileFd SCacheF(SrcCacheFile,FileFd::ReadOnly);
c8e572e3 1422 unsigned long const alloc = Map->RawAllocate(SCacheF.Size());
eb162ff7
DK
1423 if ((alloc == 0 && _error->PendingError())
1424 || SCacheF.Read((unsigned char *)Map->Data() + alloc,
1425 SCacheF.Size()) == false)
b2e465d6
AL
1426 return false;
1427
1428 TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
c8e572e3 1429
b2e465d6 1430 // Build the status cache
2e5f4e45 1431 pkgCacheGenerator Gen(Map.Get(),Progress);
2d11135a 1432 if (_error->PendingError() == true)
b2e465d6
AL
1433 return false;
1434 if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
1435 Files.begin()+EndOfSource,Files.end()) == false)
1436 return false;
1437 }
1438 else
2d11135a 1439 {
c8e572e3
MV
1440 if (Debug == true)
1441 std::clog << "srcpkgcache.bin is NOT valid - rebuild" << std::endl;
b2e465d6 1442 TotalSize = ComputeSize(Files.begin(),Files.end());
2d11135a 1443
b2e465d6 1444 // Build the source cache
2e5f4e45 1445 pkgCacheGenerator Gen(Map.Get(),Progress);
b2e465d6
AL
1446 if (_error->PendingError() == true)
1447 return false;
1448 if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
1449 Files.begin(),Files.begin()+EndOfSource) == false)
1450 return false;
2d11135a 1451
b2e465d6
AL
1452 // Write it back
1453 if (Writeable == true && SrcCacheFile.empty() == false)
2d11135a 1454 {
22041bd2 1455 FileFd SCacheF(SrcCacheFile,FileFd::WriteAtomic);
b2e465d6
AL
1456 if (_error->PendingError() == true)
1457 return false;
7a3c2ab0
AL
1458
1459 fchmod(SCacheF.Fd(),0644);
1460
b2e465d6
AL
1461 // Write out the main data
1462 if (SCacheF.Write(Map->Data(),Map->Size()) == false)
1463 return _error->Error(_("IO Error saving source cache"));
1464 SCacheF.Sync();
1465
1466 // Write out the proper header
1467 Gen.GetCache().HeaderP->Dirty = false;
1468 if (SCacheF.Seek(0) == false ||
1469 SCacheF.Write(Map->Data(),sizeof(*Gen.GetCache().HeaderP)) == false)
1470 return _error->Error(_("IO Error saving source cache"));
b2e465d6 1471 Gen.GetCache().HeaderP->Dirty = true;
7a3c2ab0 1472 SCacheF.Sync();
2d11135a
AL
1473 }
1474
b2e465d6
AL
1475 // Build the status cache
1476 if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
1477 Files.begin()+EndOfSource,Files.end()) == false)
1478 return false;
2d11135a 1479 }
c8e572e3
MV
1480 if (Debug == true)
1481 std::clog << "Caches are ready for shipping" << std::endl;
2d11135a 1482
b2e465d6
AL
1483 if (_error->PendingError() == true)
1484 return false;
1485 if (OutMap != 0)
2d11135a 1486 {
b2e465d6 1487 if (CacheF != 0)
2d11135a 1488 {
b2e465d6 1489 delete Map.UnGuard();
eb162ff7 1490 *OutMap = new MMap(*CacheF,0);
2d11135a 1491 }
b2e465d6
AL
1492 else
1493 {
1494 *OutMap = Map.UnGuard();
1495 }
2d11135a
AL
1496 }
1497
b2e465d6
AL
1498 return true;
1499}
1500 /*}}}*/
2e5f4e45 1501// CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
b2e465d6
AL
1502// ---------------------------------------------------------------------
1503/* */
2e5f4e45
DK
1504__deprecated bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
1505 { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress, OutMap); }
1506bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap)
b2e465d6 1507{
73688d27 1508 std::vector<pkgIndexFile *> Files;
b2e465d6
AL
1509 unsigned long EndOfSource = Files.size();
1510 if (_system->AddStatusFiles(Files) == false)
1511 return false;
dcdf1ef1
DK
1512
1513 SPtr<DynamicMMap> Map = CreateDynamicMMap(NULL);
b2e465d6
AL
1514 unsigned long CurrentSize = 0;
1515 unsigned long TotalSize = 0;
1516
1517 TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
1518
1519 // Build the status cache
2e5f4e45
DK
1520 if (Progress != NULL)
1521 Progress->OverallProgress(0,1,1,_("Reading package lists"));
1522 pkgCacheGenerator Gen(Map.Get(),Progress);
2d11135a 1523 if (_error->PendingError() == true)
b2e465d6
AL
1524 return false;
1525 if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
1526 Files.begin()+EndOfSource,Files.end()) == false)
1527 return false;
25396fb0 1528
b2e465d6
AL
1529 if (_error->PendingError() == true)
1530 return false;
1531 *OutMap = Map.UnGuard();
2d11135a 1532
b2e465d6 1533 return true;
2d11135a
AL
1534}
1535 /*}}}*/
5f4db009 1536// IsDuplicateDescription /*{{{*/
60683765 1537static bool IsDuplicateDescription(pkgCache::DescIterator Desc,
5f4db009
DK
1538 MD5SumValue const &CurMd5, std::string const &CurLang)
1539{
22f07fc5 1540 // Descriptions in the same link-list have all the same md5
7f5aab82 1541 if (Desc.end() == true || MD5SumValue(Desc.md5()) != CurMd5)
22f07fc5
DK
1542 return false;
1543 for (; Desc.end() == false; ++Desc)
1544 if (Desc.LanguageCode() == CurLang)
5f4db009
DK
1545 return true;
1546 return false;
1547}
1548 /*}}}*/
5a8e963b
DK
1549// CacheGenerator::FinishCache /*{{{*/
1550bool pkgCacheGenerator::FinishCache(OpProgress *Progress)
1551{
1552 return true;
1553}
1554 /*}}}*/