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