]> git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
Various bug fixes
[apt.git] / cmdline / apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-cache.cc,v 1.51 2001/06/10 02:03:33 jgg Exp $
4 /* ######################################################################
5
6 apt-cache - Manages the cache files
7
8 apt-cache provides some functions fo manipulating the cache files.
9 It uses the command line interface common to all the APT tools.
10
11 Returns 100 on failure, 0 on success.
12
13 ##################################################################### */
14 /*}}}*/
15 // Include Files /*{{{*/
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/pkgcachegen.h>
18 #include <apt-pkg/init.h>
19 #include <apt-pkg/progress.h>
20 #include <apt-pkg/sourcelist.h>
21 #include <apt-pkg/cmndline.h>
22 #include <apt-pkg/strutl.h>
23 #include <apt-pkg/pkgrecords.h>
24 #include <apt-pkg/srcrecords.h>
25 #include <apt-pkg/version.h>
26 #include <apt-pkg/policy.h>
27 #include <apt-pkg/tagfile.h>
28 #include <apt-pkg/algorithms.h>
29 #include <apt-pkg/sptr.h>
30
31 #include <config.h>
32 #include <apti18n.h>
33
34 #include <iostream.h>
35 #include <unistd.h>
36 #include <errno.h>
37 #include <regex.h>
38 #include <stdio.h>
39 /*}}}*/
40
41 pkgCache *GCache = 0;
42 pkgSourceList *SrcList = 0;
43
44 // LocalitySort - Sort a version list by package file locality /*{{{*/
45 // ---------------------------------------------------------------------
46 /* */
47 int LocalityCompare(const void *a, const void *b)
48 {
49 pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
50 pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
51
52 if (A == 0 && B == 0)
53 return 0;
54 if (A == 0)
55 return 1;
56 if (B == 0)
57 return -1;
58
59 if (A->File == B->File)
60 return A->Offset - B->Offset;
61 return A->File - B->File;
62 }
63
64 void LocalitySort(pkgCache::VerFile **begin,
65 unsigned long Count,size_t Size)
66 {
67 qsort(begin,Count,Size,LocalityCompare);
68 }
69 /*}}}*/
70 // UnMet - Show unmet dependencies /*{{{*/
71 // ---------------------------------------------------------------------
72 /* */
73 bool UnMet(CommandLine &CmdL)
74 {
75 pkgCache &Cache = *GCache;
76 bool Important = _config->FindB("APT::Cache::Important",false);
77
78 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
79 {
80 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
81 {
82 bool Header = false;
83 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
84 {
85 // Collect or groups
86 pkgCache::DepIterator Start;
87 pkgCache::DepIterator End;
88 D.GlobOr(Start,End);
89
90 // Skip conflicts and replaces
91 if (End->Type != pkgCache::Dep::PreDepends &&
92 End->Type != pkgCache::Dep::Depends &&
93 End->Type != pkgCache::Dep::Suggests &&
94 End->Type != pkgCache::Dep::Recommends)
95 continue;
96
97 // Important deps only
98 if (Important == true)
99 if (End->Type != pkgCache::Dep::PreDepends &&
100 End->Type != pkgCache::Dep::Depends)
101 continue;
102
103 // Verify the or group
104 bool OK = false;
105 pkgCache::DepIterator RealStart = Start;
106 do
107 {
108 // See if this dep is Ok
109 pkgCache::Version **VList = Start.AllTargets();
110 if (*VList != 0)
111 {
112 OK = true;
113 delete [] VList;
114 break;
115 }
116 delete [] VList;
117
118 if (Start == End)
119 break;
120 Start++;
121 }
122 while (1);
123
124 // The group is OK
125 if (OK == true)
126 continue;
127
128 // Oops, it failed..
129 if (Header == false)
130 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
131 P.Name(),V.VerStr());
132 Header = true;
133
134 // Print out the dep type
135 cout << " " << End.DepType() << ": ";
136
137 // Show the group
138 Start = RealStart;
139 do
140 {
141 cout << Start.TargetPkg().Name();
142 if (Start.TargetVer() != 0)
143 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
144 ")";
145 if (Start == End)
146 break;
147 cout << " | ";
148 Start++;
149 }
150 while (1);
151
152 cout << endl;
153 }
154 }
155 }
156 return true;
157 }
158 /*}}}*/
159 // DumpPackage - Show a dump of a package record /*{{{*/
160 // ---------------------------------------------------------------------
161 /* */
162 bool DumpPackage(CommandLine &CmdL)
163 {
164 pkgCache &Cache = *GCache;
165 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
166 {
167 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
168 if (Pkg.end() == true)
169 {
170 _error->Warning(_("Unable to locate package %s"),*I);
171 continue;
172 }
173
174 cout << "Package: " << Pkg.Name() << endl;
175 cout << "Versions: " << endl;
176 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
177 {
178 cout << Cur.VerStr();
179 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
180 cout << "(" << Vf.File().FileName() << ")";
181 cout << endl;
182 }
183
184 cout << endl;
185
186 cout << "Reverse Depends: " << endl;
187 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
188 {
189 cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name();
190 if (D->Version != 0)
191 cout << ' ' << DeNull(D.TargetVer()) << endl;
192 else
193 cout << endl;
194 }
195
196 cout << "Dependencies: " << endl;
197 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
198 {
199 cout << Cur.VerStr() << " - ";
200 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
201 cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
202 cout << endl;
203 }
204
205 cout << "Provides: " << endl;
206 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
207 {
208 cout << Cur.VerStr() << " - ";
209 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
210 cout << Prv.ParentPkg().Name() << " ";
211 cout << endl;
212 }
213 cout << "Reverse Provides: " << endl;
214 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
215 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr() << endl;
216 }
217
218 return true;
219 }
220 /*}}}*/
221 // Stats - Dump some nice statistics /*{{{*/
222 // ---------------------------------------------------------------------
223 /* */
224 bool Stats(CommandLine &Cmd)
225 {
226 pkgCache &Cache = *GCache;
227 cout << _("Total Package Names : ") << Cache.Head().PackageCount << " (" <<
228 SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
229
230 int Normal = 0;
231 int Virtual = 0;
232 int NVirt = 0;
233 int DVirt = 0;
234 int Missing = 0;
235 pkgCache::PkgIterator I = Cache.PkgBegin();
236 for (;I.end() != true; I++)
237 {
238 if (I->VersionList != 0 && I->ProvidesList == 0)
239 {
240 Normal++;
241 continue;
242 }
243
244 if (I->VersionList != 0 && I->ProvidesList != 0)
245 {
246 NVirt++;
247 continue;
248 }
249
250 if (I->VersionList == 0 && I->ProvidesList != 0)
251 {
252 // Only 1 provides
253 if (I.ProvidesList()->NextProvides == 0)
254 {
255 DVirt++;
256 }
257 else
258 Virtual++;
259 continue;
260 }
261 if (I->VersionList == 0 && I->ProvidesList == 0)
262 {
263 Missing++;
264 continue;
265 }
266 }
267 cout << _(" Normal Packages: ") << Normal << endl;
268 cout << _(" Pure Virtual Packages: ") << Virtual << endl;
269 cout << _(" Single Virtual Packages: ") << DVirt << endl;
270 cout << _(" Mixed Virtual Packages: ") << NVirt << endl;
271 cout << _(" Missing: ") << Missing << endl;
272
273 cout << _("Total Distinct Versions: ") << Cache.Head().VersionCount << " (" <<
274 SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
275 cout << _("Total Dependencies: ") << Cache.Head().DependsCount << " (" <<
276 SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
277
278 cout << _("Total Ver/File relations: ") << Cache.Head().VerFileCount << " (" <<
279 SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
280 cout << _("Total Provides Mappings: ") << Cache.Head().ProvidesCount << " (" <<
281 SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
282
283 // String list stats
284 unsigned long Size = 0;
285 unsigned long Count = 0;
286 for (pkgCache::StringItem *I = Cache.StringItemP + Cache.Head().StringList;
287 I!= Cache.StringItemP; I = Cache.StringItemP + I->NextItem)
288 {
289 Count++;
290 Size += strlen(Cache.StrP + I->String) + 1;
291 }
292 cout << _("Total Globbed Strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
293
294 unsigned long DepVerSize = 0;
295 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
296 {
297 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
298 {
299 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
300 {
301 if (D->Version != 0)
302 DepVerSize += strlen(D.TargetVer()) + 1;
303 }
304 }
305 }
306 cout << _("Total Dependency Version space: ") << SizeToStr(DepVerSize) << endl;
307
308 unsigned long Slack = 0;
309 for (int I = 0; I != 7; I++)
310 Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count;
311 cout << _("Total Slack space: ") << SizeToStr(Slack) << endl;
312
313 unsigned long Total = 0;
314 Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz +
315 Cache.Head().VersionCount*Cache.Head().VersionSz +
316 Cache.Head().PackageCount*Cache.Head().PackageSz +
317 Cache.Head().VerFileCount*Cache.Head().VerFileSz +
318 Cache.Head().ProvidesCount*Cache.Head().ProvidesSz;
319 cout << _("Total Space Accounted for: ") << SizeToStr(Total) << endl;
320
321 return true;
322 }
323 /*}}}*/
324 // Dump - show everything /*{{{*/
325 // ---------------------------------------------------------------------
326 /* This is worthless except fer debugging things */
327 bool Dump(CommandLine &Cmd)
328 {
329 pkgCache &Cache = *GCache;
330 cout << "Using Versioning System: " << Cache.VS->Label << endl;
331
332 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
333 {
334 cout << "Package: " << P.Name() << endl;
335 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
336 {
337 cout << " Version: " << V.VerStr() << endl;
338 cout << " File: " << V.FileList().File().FileName() << endl;
339 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
340 cout << " Depends: " << D.TargetPkg().Name() << ' ' <<
341 DeNull(D.TargetVer()) << endl;
342 }
343 }
344
345 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
346 {
347 cout << "File: " << F.FileName() << endl;
348 cout << " Type: " << F.IndexType() << endl;
349 cout << " Size: " << F->Size << endl;
350 cout << " ID: " << F->ID << endl;
351 cout << " Flags: " << F->Flags << endl;
352 cout << " Time: " << TimeRFC1123(F->mtime) << endl;
353 cout << " Archive: " << DeNull(F.Archive()) << endl;
354 cout << " Component: " << DeNull(F.Component()) << endl;
355 cout << " Version: " << DeNull(F.Version()) << endl;
356 cout << " Origin: " << DeNull(F.Origin()) << endl;
357 cout << " Site: " << DeNull(F.Site()) << endl;
358 cout << " Label: " << DeNull(F.Label()) << endl;
359 cout << " Architecture: " << DeNull(F.Architecture()) << endl;
360 }
361
362 return true;
363 }
364 /*}}}*/
365 // DumpAvail - Print out the available list /*{{{*/
366 // ---------------------------------------------------------------------
367 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
368 make this run really fast, perhaps I went a little overboard.. */
369 bool DumpAvail(CommandLine &Cmd)
370 {
371 pkgCache &Cache = *GCache;
372
373 pkgPolicy Plcy(&Cache);
374 if (ReadPinFile(Plcy) == false)
375 return false;
376
377 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Cache.HeaderP->PackageCount];
378 memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount);
379
380 // Map versions that we want to write out onto the VerList array.
381 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
382 {
383 if (P->VersionList == 0)
384 continue;
385
386 /* Find the proper version to use. If the policy says there are no
387 possible selections we return the installed version, if available..
388 This prevents dselect from making it obsolete. */
389 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
390 if (V.end() == true)
391 {
392 if (P->CurrentVer == 0)
393 continue;
394 V = P.CurrentVer();
395 }
396
397 pkgCache::VerFileIterator VF = V.FileList();
398 for (; VF.end() == false ; VF++)
399 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
400 break;
401
402 /* Okay, here we have a bit of a problem.. The policy has selected the
403 currently installed package - however it only exists in the
404 status file.. We need to write out something or dselect will mark
405 the package as obsolete! Thus we emit the status file entry, but
406 below we remove the status line to make it valid for the
407 available file. However! We only do this if their do exist *any*
408 non-source versions of the package - that way the dselect obsolete
409 handling works OK. */
410 if (VF.end() == true)
411 {
412 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; Cur++)
413 {
414 for (VF = Cur.FileList(); VF.end() == false; VF++)
415 {
416 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
417 {
418 VF = V.FileList();
419 break;
420 }
421 }
422
423 if (VF.end() == false)
424 break;
425 }
426 }
427
428 VFList[P->ID] = VF;
429 }
430
431 LocalitySort(VFList,Cache.HeaderP->PackageCount,sizeof(*VFList));
432
433 // Iterate over all the package files and write them out.
434 char *Buffer = new char[Cache.HeaderP->MaxVerFileSize+10];
435 for (pkgCache::VerFile **J = VFList; *J != 0;)
436 {
437 pkgCache::PkgFileIterator File(Cache,(*J)->File + Cache.PkgFileP);
438 if (File.IsOk() == false)
439 {
440 _error->Error(_("Package file %s is out of sync."),File.FileName());
441 break;
442 }
443
444 FileFd PkgF(File.FileName(),FileFd::ReadOnly);
445 if (_error->PendingError() == true)
446 break;
447
448 /* Write all of the records from this package file, since we
449 already did locality sorting we can now just seek through the
450 file in read order. We apply 1 more optimization here, since often
451 there will be < 1 byte gaps between records (for the \n) we read that
452 into the next buffer and offset a bit.. */
453 unsigned long Pos = 0;
454 for (; *J != 0; J++)
455 {
456 if ((*J)->File + Cache.PkgFileP != File)
457 break;
458
459 const pkgCache::VerFile &VF = **J;
460
461 // Read the record and then write it out again.
462 unsigned long Jitter = VF.Offset - Pos;
463 if (Jitter > 8)
464 {
465 if (PkgF.Seek(VF.Offset) == false)
466 break;
467 Jitter = 0;
468 }
469
470 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
471 break;
472 Buffer[VF.Size + Jitter] = '\n';
473
474 // See above..
475 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
476 {
477 pkgTagSection Tags;
478 TFRewriteData RW[] = {{"Status",0},{"Config-Version",0},{}};
479 const char *Zero = 0;
480 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
481 TFRewrite(stdout,Tags,&Zero,RW) == false)
482 {
483 _error->Error("Internal Error, Unable to parse a package record");
484 break;
485 }
486 fputc('\n',stdout);
487 }
488 else
489 {
490 if (fwrite(Buffer+Jitter,VF.Size+1,1,stdout) != 1)
491 break;
492 }
493
494 Pos = VF.Offset + VF.Size;
495 }
496
497 fflush(stdout);
498 if (_error->PendingError() == true)
499 break;
500 }
501
502 delete [] Buffer;
503 delete [] VFList;
504 return !_error->PendingError();
505 }
506 /*}}}*/
507 // Depends - Print out a dependency tree /*{{{*/
508 // ---------------------------------------------------------------------
509 /* */
510 bool Depends(CommandLine &CmdL)
511 {
512 pkgCache &Cache = *GCache;
513 SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
514 memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
515
516 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
517 {
518 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
519 if (Pkg.end() == true)
520 {
521 _error->Warning(_("Unable to locate package %s"),*I);
522 continue;
523 }
524 Colours[Pkg->ID] = 1;
525 }
526
527 bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
528 bool DidSomething;
529 do
530 {
531 DidSomething = false;
532 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
533 {
534 if (Colours[Pkg->ID] != 1)
535 continue;
536 Colours[Pkg->ID] = 2;
537 DidSomething = true;
538
539 pkgCache::VerIterator Ver = Pkg.VersionList();
540 if (Ver.end() == true)
541 {
542 cout << '<' << Pkg.Name() << '>' << endl;
543 continue;
544 }
545
546 cout << Pkg.Name() << endl;
547
548 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
549 {
550 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
551 cout << " |";
552 else
553 cout << " ";
554
555 // Show the package
556 pkgCache::PkgIterator Trg = D.TargetPkg();
557 if (Trg->VersionList == 0)
558 cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
559 else
560 cout << D.DepType() << ": " << Trg.Name() << endl;
561
562 if (Recurse == true)
563 Colours[D.TargetPkg()->ID]++;
564
565 // Display all solutions
566 SPtrArray<pkgCache::Version *> List = D.AllTargets();
567 pkgPrioSortList(Cache,List);
568 for (pkgCache::Version **I = List; *I != 0; I++)
569 {
570 pkgCache::VerIterator V(Cache,*I);
571 if (V != Cache.VerP + V.ParentPkg()->VersionList ||
572 V->ParentPkg == D->Package)
573 continue;
574 cout << " " << V.ParentPkg().Name() << endl;
575
576 if (Recurse == true)
577 Colours[D.ParentPkg()->ID]++;
578 }
579 }
580 }
581 }
582 while (DidSomething == true);
583
584 return true;
585 }
586 /*}}}*/
587 // Dotty - Generate a graph for Dotty /*{{{*/
588 // ---------------------------------------------------------------------
589 /* Dotty is the graphvis program for generating graphs. It is a fairly
590 simple queuing algorithm that just writes dependencies and nodes.
591 http://www.research.att.com/sw/tools/graphviz/ */
592 bool Dotty(CommandLine &CmdL)
593 {
594 pkgCache &Cache = *GCache;
595 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
596
597 /* Normal packages are boxes
598 Pure Provides are triangles
599 Mixed are diamonds
600 Hexagons are missing packages*/
601 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
602
603 /* Initialize the list of packages to show.
604 1 = To Show
605 2 = To Show no recurse
606 3 = Emitted no recurse
607 4 = Emitted
608 0 = None */
609 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
610 enum TheFlags {ForceNR=(1<<0)};
611 unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
612 unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
613 unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
614
615 // Show everything if no arguments given
616 if (CmdL.FileList[1] == 0)
617 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
618 Show[I] = ToShow;
619 else
620 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
621 Show[I] = None;
622 memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
623
624 // Map the shapes
625 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
626 {
627 if (Pkg->VersionList == 0)
628 {
629 // Missing
630 if (Pkg->ProvidesList == 0)
631 ShapeMap[Pkg->ID] = 0;
632 else
633 ShapeMap[Pkg->ID] = 1;
634 }
635 else
636 {
637 // Normal
638 if (Pkg->ProvidesList == 0)
639 ShapeMap[Pkg->ID] = 2;
640 else
641 ShapeMap[Pkg->ID] = 3;
642 }
643 }
644
645 // Load the list of packages from the command line into the show list
646 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
647 {
648 // Process per-package flags
649 string P = *I;
650 bool Force = false;
651 if (P.length() > 3)
652 {
653 if (P.end()[-1] == '^')
654 {
655 Force = true;
656 P.erase(P.end()-1);
657 }
658
659 if (P.end()[-1] == ',')
660 P.erase(P.end()-1);
661 }
662
663 // Locate the package
664 pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
665 if (Pkg.end() == true)
666 {
667 _error->Warning(_("Unable to locate package %s"),*I);
668 continue;
669 }
670 Show[Pkg->ID] = ToShow;
671
672 if (Force == true)
673 Flags[Pkg->ID] |= ForceNR;
674 }
675
676 // Little header
677 printf("digraph packages {\n");
678 printf("concentrate=true;\n");
679 printf("size=\"30,40\";\n");
680
681 bool Act = true;
682 while (Act == true)
683 {
684 Act = false;
685 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
686 {
687 // See we need to show this package
688 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
689 continue;
690
691 // Colour as done
692 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
693 {
694 // Pure Provides and missing packages have no deps!
695 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
696 Show[Pkg->ID] = Done;
697 else
698 Show[Pkg->ID] = DoneNR;
699 }
700 else
701 Show[Pkg->ID] = Done;
702 Act = true;
703
704 // No deps to map out
705 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
706 continue;
707
708 pkgCache::VerIterator Ver = Pkg.VersionList();
709 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
710 {
711 // See if anything can meet this dep
712 // Walk along the actual package providing versions
713 bool Hit = false;
714 pkgCache::PkgIterator DPkg = D.TargetPkg();
715 for (pkgCache::VerIterator I = DPkg.VersionList();
716 I.end() == false && Hit == false; I++)
717 {
718 if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
719 Hit = true;
720 }
721
722 // Follow all provides
723 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
724 I.end() == false && Hit == false; I++)
725 {
726 if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
727 Hit = true;
728 }
729
730 // Only graph critical deps
731 if (D.IsCritical() == true)
732 {
733 printf("\"%s\" -> \"%s\"",Pkg.Name(),D.TargetPkg().Name());
734
735 // Colour the node for recursion
736 if (Show[D.TargetPkg()->ID] <= DoneNR)
737 {
738 /* If a conflicts does not meet anything in the database
739 then show the relation but do not recurse */
740 if (Hit == false &&
741 (D->Type == pkgCache::Dep::Conflicts ||
742 D->Type == pkgCache::Dep::Obsoletes))
743 {
744 if (Show[D.TargetPkg()->ID] == None &&
745 Show[D.TargetPkg()->ID] != ToShow)
746 Show[D.TargetPkg()->ID] = ToShowNR;
747 }
748 else
749 {
750 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
751 Show[D.TargetPkg()->ID] = ToShowNR;
752 else
753 Show[D.TargetPkg()->ID] = ToShow;
754 }
755 }
756
757 // Edge colour
758 switch(D->Type)
759 {
760 case pkgCache::Dep::Conflicts:
761 case pkgCache::Dep::Obsoletes:
762 printf("[color=springgreen];\n");
763 break;
764
765 case pkgCache::Dep::PreDepends:
766 printf("[color=blue];\n");
767 break;
768
769 default:
770 printf(";\n");
771 break;
772 }
773 }
774 }
775 }
776 }
777
778 /* Draw the box colours after the fact since we can not tell what colour
779 they should be until everything is finished drawing */
780 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
781 {
782 if (Show[Pkg->ID] < DoneNR)
783 continue;
784
785 // Orange box for early recursion stoppage
786 if (Show[Pkg->ID] == DoneNR)
787 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.Name(),
788 Shapes[ShapeMap[Pkg->ID]]);
789 else
790 printf("\"%s\" [shape=%s];\n",Pkg.Name(),
791 Shapes[ShapeMap[Pkg->ID]]);
792 }
793
794 printf("}\n");
795 return true;
796 }
797 /*}}}*/
798 // DoAdd - Perform an adding operation /*{{{*/
799 // ---------------------------------------------------------------------
800 /* */
801 bool DoAdd(CommandLine &CmdL)
802 {
803 return _error->Error("Unimplemented");
804 #if 0
805 // Make sure there is at least one argument
806 if (CmdL.FileSize() <= 1)
807 return _error->Error("You must give at least one file name");
808
809 // Open the cache
810 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
811 if (_error->PendingError() == true)
812 return false;
813
814 DynamicMMap Map(CacheF,MMap::Public);
815 if (_error->PendingError() == true)
816 return false;
817
818 OpTextProgress Progress(*_config);
819 pkgCacheGenerator Gen(Map,Progress);
820 if (_error->PendingError() == true)
821 return false;
822
823 unsigned long Length = CmdL.FileSize() - 1;
824 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
825 {
826 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
827 Progress.SubProgress(Length);
828
829 // Do the merge
830 FileFd TagF(*I,FileFd::ReadOnly);
831 debListParser Parser(TagF);
832 if (_error->PendingError() == true)
833 return _error->Error("Problem opening %s",*I);
834
835 if (Gen.SelectFile(*I,"") == false)
836 return _error->Error("Problem with SelectFile");
837
838 if (Gen.MergeList(Parser) == false)
839 return _error->Error("Problem with MergeList");
840 }
841
842 Progress.Done();
843 GCache = &Gen.GetCache();
844 Stats(CmdL);
845
846 return true;
847 #endif
848 }
849 /*}}}*/
850 // DisplayRecord - Displays the complete record for the package /*{{{*/
851 // ---------------------------------------------------------------------
852 /* This displays the package record from the proper package index file.
853 It is not used by DumpAvail for performance reasons. */
854 bool DisplayRecord(pkgCache::VerIterator V)
855 {
856 // Find an appropriate file
857 pkgCache::VerFileIterator Vf = V.FileList();
858 for (; Vf.end() == false; Vf++)
859 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
860 break;
861 if (Vf.end() == true)
862 Vf = V.FileList();
863
864 // Check and load the package list file
865 pkgCache::PkgFileIterator I = Vf.File();
866 if (I.IsOk() == false)
867 return _error->Error(_("Package file %s is out of sync."),I.FileName());
868
869 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
870 if (_error->PendingError() == true)
871 return false;
872
873 // Read the record and then write it out again.
874 unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
875 Buffer[V.FileList()->Size] = '\n';
876 if (PkgF.Seek(V.FileList()->Offset) == false ||
877 PkgF.Read(Buffer,V.FileList()->Size) == false ||
878 write(STDOUT_FILENO,Buffer,V.FileList()->Size+1) != V.FileList()->Size+1)
879 {
880 delete [] Buffer;
881 return false;
882 }
883
884 delete [] Buffer;
885
886 return true;
887 }
888 /*}}}*/
889 // Search - Perform a search /*{{{*/
890 // ---------------------------------------------------------------------
891 /* This searches the package names and pacakge descriptions for a pattern */
892 struct ExVerFile
893 {
894 pkgCache::VerFile *Vf;
895 bool NameMatch;
896 };
897
898 bool Search(CommandLine &CmdL)
899 {
900 pkgCache &Cache = *GCache;
901 bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
902 bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
903 unsigned NumPatterns = CmdL.FileSize() -1;
904
905 pkgDepCache::Policy Plcy;
906
907 // Make sure there is at least one argument
908 if (NumPatterns < 1)
909 return _error->Error(_("You must give exactly one pattern"));
910
911 // Compile the regex pattern
912 regex_t *Patterns = new regex_t[NumPatterns];
913 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
914 for (unsigned I = 0; I != NumPatterns; I++)
915 {
916 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
917 REG_NOSUB) != 0)
918 {
919 for (; I != 0; I--)
920 regfree(&Patterns[I]);
921 return _error->Error("Regex compilation error");
922 }
923 }
924
925 // Create the text record parser
926 pkgRecords Recs(Cache);
927 if (_error->PendingError() == true)
928 {
929 for (unsigned I = 0; I != NumPatterns; I++)
930 regfree(&Patterns[I]);
931 return false;
932 }
933
934 ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
935 memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
936
937 // Map versions that we want to write out onto the VerList array.
938 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
939 {
940 VFList[P->ID].NameMatch = NumPatterns != 0;
941 for (unsigned I = 0; I != NumPatterns; I++)
942 {
943 if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
944 VFList[P->ID].NameMatch &= true;
945 else
946 VFList[P->ID].NameMatch = false;
947 }
948
949 // Doing names only, drop any that dont match..
950 if (NamesOnly == true && VFList[P->ID].NameMatch == false)
951 continue;
952
953 // Find the proper version to use.
954 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
955 if (V.end() == true)
956 continue;
957 VFList[P->ID].Vf = V.FileList();
958 }
959
960 LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
961
962 // Iterate over all the version records and check them
963 for (ExVerFile *J = VFList; J->Vf != 0; J++)
964 {
965 pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
966
967 bool Match = true;
968 if (J->NameMatch == false)
969 {
970 string LongDesc = P.LongDesc();
971 Match = NumPatterns != 0;
972 for (unsigned I = 0; I != NumPatterns; I++)
973 {
974 if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
975 Match &= true;
976 else
977 Match = false;
978 }
979 }
980
981 if (Match == true)
982 {
983 if (ShowFull == true)
984 {
985 const char *Start;
986 const char *End;
987 P.GetRec(Start,End);
988 fwrite(Start,End-Start,1,stdout);
989 putc('\n',stdout);
990 }
991 else
992 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
993 }
994 }
995
996 delete [] VFList;
997 for (unsigned I = 0; I != NumPatterns; I++)
998 regfree(&Patterns[I]);
999 if (ferror(stdout))
1000 return _error->Error("Write to stdout failed");
1001 return true;
1002 }
1003 /*}}}*/
1004 // ShowPackage - Dump the package record to the screen /*{{{*/
1005 // ---------------------------------------------------------------------
1006 /* */
1007 bool ShowPackage(CommandLine &CmdL)
1008 {
1009 pkgCache &Cache = *GCache;
1010 pkgDepCache::Policy Plcy;
1011
1012 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1013 {
1014 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1015 if (Pkg.end() == true)
1016 {
1017 _error->Warning(_("Unable to locate package %s"),*I);
1018 continue;
1019 }
1020
1021 // Find the proper version to use.
1022 if (_config->FindB("APT::Cache::AllVersions","true") == true)
1023 {
1024 pkgCache::VerIterator V;
1025 for (V = Pkg.VersionList(); V.end() == false; V++)
1026 {
1027 if (DisplayRecord(V) == false)
1028 return false;
1029 }
1030 }
1031 else
1032 {
1033 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
1034 if (V.end() == true || V.FileList().end() == true)
1035 continue;
1036 if (DisplayRecord(V) == false)
1037 return false;
1038 }
1039 }
1040 return true;
1041 }
1042 /*}}}*/
1043 // ShowPkgNames - Show package names /*{{{*/
1044 // ---------------------------------------------------------------------
1045 /* This does a prefix match on the first argument */
1046 bool ShowPkgNames(CommandLine &CmdL)
1047 {
1048 pkgCache &Cache = *GCache;
1049 pkgCache::PkgIterator I = Cache.PkgBegin();
1050 bool All = _config->FindB("APT::Cache::AllNames","false");
1051
1052 if (CmdL.FileList[1] != 0)
1053 {
1054 for (;I.end() != true; I++)
1055 {
1056 if (All == false && I->VersionList == 0)
1057 continue;
1058
1059 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1060 cout << I.Name() << endl;
1061 }
1062
1063 return true;
1064 }
1065
1066 // Show all pkgs
1067 for (;I.end() != true; I++)
1068 {
1069 if (All == false && I->VersionList == 0)
1070 continue;
1071 cout << I.Name() << endl;
1072 }
1073
1074 return true;
1075 }
1076 /*}}}*/
1077 // ShowSrcPackage - Show source package records /*{{{*/
1078 // ---------------------------------------------------------------------
1079 /* */
1080 bool ShowSrcPackage(CommandLine &CmdL)
1081 {
1082 pkgSourceList List;
1083 List.ReadMainList();
1084
1085 // Create the text record parsers
1086 pkgSrcRecords SrcRecs(List);
1087 if (_error->PendingError() == true)
1088 return false;
1089
1090 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1091 {
1092 SrcRecs.Restart();
1093
1094 pkgSrcRecords::Parser *Parse;
1095 while ((Parse = SrcRecs.Find(*I,false)) != 0)
1096 cout << Parse->AsStr() << endl;;
1097 }
1098 return true;
1099 }
1100 /*}}}*/
1101 // Policy - Show the results of the preferences file /*{{{*/
1102 // ---------------------------------------------------------------------
1103 /* */
1104 bool Policy(CommandLine &CmdL)
1105 {
1106 if (SrcList == 0)
1107 return _error->Error("Generate must be enabled for this function");
1108
1109 pkgCache &Cache = *GCache;
1110 pkgPolicy Plcy(&Cache);
1111 if (ReadPinFile(Plcy) == false)
1112 return false;
1113
1114 // Print out all of the package files
1115 if (CmdL.FileList[1] == 0)
1116 {
1117 cout << _("Package Files:") << endl;
1118 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
1119 {
1120 // Locate the associated index files so we can derive a description
1121 pkgIndexFile *Indx;
1122 if (SrcList->FindIndex(F,Indx) == false &&
1123 _system->FindIndex(F,Indx) == false)
1124 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1125 printf(_("%4i %s\n"),
1126 Plcy.GetPriority(F),Indx->Describe(true).c_str());
1127
1128 // Print the reference information for the package
1129 string Str = F.RelStr();
1130 if (Str.empty() == false)
1131 printf(" release %s\n",F.RelStr().c_str());
1132 if (F.Site() != 0 && F.Site()[0] != 0)
1133 printf(" origin %s\n",F.Site());
1134 }
1135
1136 // Show any packages have explicit pins
1137 cout << _("Pinned Packages:") << endl;
1138 pkgCache::PkgIterator I = Cache.PkgBegin();
1139 for (;I.end() != true; I++)
1140 {
1141 if (Plcy.GetPriority(I) == 0)
1142 continue;
1143
1144 // Print the package name and the version we are forcing to
1145 cout << " " << I.Name() << " -> ";
1146
1147 pkgCache::VerIterator V = Plcy.GetMatch(I);
1148 if (V.end() == true)
1149 cout << _("(not found)") << endl;
1150 else
1151 cout << V.VerStr() << endl;
1152 }
1153
1154 return true;
1155 }
1156
1157 // Print out detailed information for each package
1158 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1159 {
1160 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1161 if (Pkg.end() == true)
1162 {
1163 _error->Warning(_("Unable to locate package %s"),*I);
1164 continue;
1165 }
1166
1167 cout << Pkg.Name() << ":" << endl;
1168
1169 // Installed version
1170 cout << _(" Installed: ");
1171 if (Pkg->CurrentVer == 0)
1172 cout << _("(none)") << endl;
1173 else
1174 cout << Pkg.CurrentVer().VerStr() << endl;
1175
1176 // Candidate Version
1177 cout << _(" Candidate: ");
1178 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
1179 if (V.end() == true)
1180 cout << _("(none)") << endl;
1181 else
1182 cout << V.VerStr() << endl;
1183
1184 // Pinned version
1185 if (Plcy.GetPriority(Pkg) != 0)
1186 {
1187 cout << _(" Package Pin: ");
1188 V = Plcy.GetMatch(Pkg);
1189 if (V.end() == true)
1190 cout << _("(not found)") << endl;
1191 else
1192 cout << V.VerStr() << endl;
1193 }
1194
1195 // Show the priority tables
1196 cout << _(" Version Table:") << endl;
1197 for (V = Pkg.VersionList(); V.end() == false; V++)
1198 {
1199 if (Pkg.CurrentVer() == V)
1200 cout << " *** " << V.VerStr();
1201 else
1202 cout << " " << V.VerStr();
1203 cout << " " << Plcy.GetPriority(Pkg) << endl;
1204 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1205 {
1206 // Locate the associated index files so we can derive a description
1207 pkgIndexFile *Indx;
1208 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1209 _system->FindIndex(VF.File(),Indx) == false)
1210 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1211 printf(_(" %4i %s\n"),Plcy.GetPriority(VF.File()),
1212 Indx->Describe(true).c_str());
1213 }
1214 }
1215 }
1216
1217 return true;
1218 }
1219 /*}}}*/
1220 // GenCaches - Call the main cache generator /*{{{*/
1221 // ---------------------------------------------------------------------
1222 /* */
1223 bool GenCaches(CommandLine &Cmd)
1224 {
1225 OpTextProgress Progress(*_config);
1226
1227 pkgSourceList List;
1228 if (List.ReadMainList() == false)
1229 return false;
1230 return pkgMakeStatusCache(List,Progress);
1231 }
1232 /*}}}*/
1233 // ShowHelp - Show a help screen /*{{{*/
1234 // ---------------------------------------------------------------------
1235 /* */
1236 bool ShowHelp(CommandLine &Cmd)
1237 {
1238 ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
1239 COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
1240
1241 cout <<
1242 _("Usage: apt-cache [options] command\n"
1243 " apt-cache [options] add file1 [file1 ...]\n"
1244 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1245 "\n"
1246 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1247 "cache files, and query information from them\n"
1248 "\n"
1249 "Commands:\n"
1250 " add - Add an package file to the source cache\n"
1251 " gencaches - Build both the package and source cache\n"
1252 " showpkg - Show some general information for a single package\n"
1253 " stats - Show some basic statistics\n"
1254 " dump - Show the entire file in a terse form\n"
1255 " dumpavail - Print an available file to stdout\n"
1256 " unmet - Show unmet dependencies\n"
1257 " search - Search the package list for a regex pattern\n"
1258 " show - Show a readable record for the package\n"
1259 " depends - Show raw dependency information for a package\n"
1260 " pkgnames - List the names of all packages\n"
1261 " dotty - Generate package graphs for GraphVis\n"
1262 " policy - Show policy settings\n"
1263 "\n"
1264 "Options:\n"
1265 " -h This help text.\n"
1266 " -p=? The package cache.\n"
1267 " -s=? The source cache.\n"
1268 " -q Disable progress indicator.\n"
1269 " -i Show only important deps for the unmet command.\n"
1270 " -c=? Read this configuration file\n"
1271 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
1272 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1273 return true;
1274 }
1275 /*}}}*/
1276 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1277 // ---------------------------------------------------------------------
1278 /* */
1279 void CacheInitialize()
1280 {
1281 _config->Set("quiet",0);
1282 _config->Set("help",false);
1283 }
1284 /*}}}*/
1285
1286 int main(int argc,const char *argv[])
1287 {
1288 CommandLine::Args Args[] = {
1289 {'h',"help","help",0},
1290 {'v',"version","version",0},
1291 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
1292 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
1293 {'q',"quiet","quiet",CommandLine::IntLevel},
1294 {'i',"important","APT::Cache::Important",0},
1295 {'f',"full","APT::Cache::ShowFull",0},
1296 {'g',"generate","APT::Cache::Generate",0},
1297 {'a',"all-versions","APT::Cache::AllVersions",0},
1298 {0,"names-only","APT::Cache::NamesOnly",0},
1299 {0,"all-names","APT::Cache::AllNames",0},
1300 {0,"recurse","APT::Cache::RecurseDepends",0},
1301 {'c',"config-file",0,CommandLine::ConfigFile},
1302 {'o',"option",0,CommandLine::ArbItem},
1303 {0,0,0,0}};
1304 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
1305 {"add",&DoAdd},
1306 {"gencaches",&GenCaches},
1307 {"showsrc",&ShowSrcPackage},
1308 {0,0}};
1309 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
1310 {"stats",&Stats},
1311 {"dump",&Dump},
1312 {"dumpavail",&DumpAvail},
1313 {"unmet",&UnMet},
1314 {"search",&Search},
1315 {"depends",&Depends},
1316 {"dotty",&Dotty},
1317 {"show",&ShowPackage},
1318 {"pkgnames",&ShowPkgNames},
1319 {"policy",&Policy},
1320 {0,0}};
1321
1322 CacheInitialize();
1323
1324 // Parse the command line and initialize the package library
1325 CommandLine CmdL(Args,_config);
1326 if (pkgInitConfig(*_config) == false ||
1327 CmdL.Parse(argc,argv) == false ||
1328 pkgInitSystem(*_config,_system) == false)
1329 {
1330 _error->DumpErrors();
1331 return 100;
1332 }
1333
1334 // See if the help should be shown
1335 if (_config->FindB("help") == true ||
1336 CmdL.FileSize() == 0)
1337 {
1338 ShowHelp(CmdL);
1339 return 0;
1340 }
1341
1342 // Deal with stdout not being a tty
1343 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
1344 _config->Set("quiet","1");
1345
1346 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
1347 {
1348 MMap *Map;
1349 if (_config->FindB("APT::Cache::Generate",true) == false)
1350 {
1351 Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
1352 FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
1353 }
1354 else
1355 {
1356 // Open the cache file
1357 SrcList = new pkgSourceList;
1358 SrcList->ReadMainList();
1359
1360 // Generate it and map it
1361 OpProgress Prog;
1362 pkgMakeStatusCache(*SrcList,Prog,&Map,true);
1363 }
1364
1365 if (_error->PendingError() == false)
1366 {
1367 pkgCache Cache(Map);
1368 GCache = &Cache;
1369 if (_error->PendingError() == false)
1370 CmdL.DispatchArg(CmdsB);
1371 }
1372 delete Map;
1373 }
1374
1375 // Print any errors or warnings found during parsing
1376 if (_error->empty() == false)
1377 {
1378 bool Errors = _error->PendingError();
1379 _error->DumpErrors();
1380 return Errors == true?100:0;
1381 }
1382
1383 return 0;
1384 }