- [ABI BREAK] add an ErrorType option to CacheSetHelper
[ntk/apt.git] / cmdline / apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz 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 <cassert>
18 #include <apt-pkg/pkgcachegen.h>
19 #include <apt-pkg/cachefile.h>
20 #include <apt-pkg/cacheset.h>
21 #include <apt-pkg/init.h>
22 #include <apt-pkg/progress.h>
23 #include <apt-pkg/sourcelist.h>
24 #include <apt-pkg/cmndline.h>
25 #include <apt-pkg/strutl.h>
26 #include <apt-pkg/pkgrecords.h>
27 #include <apt-pkg/srcrecords.h>
28 #include <apt-pkg/version.h>
29 #include <apt-pkg/policy.h>
30 #include <apt-pkg/tagfile.h>
31 #include <apt-pkg/algorithms.h>
32 #include <apt-pkg/sptr.h>
33
34 #include <config.h>
35 #include <apti18n.h>
36
37 #include <locale.h>
38 #include <iostream>
39 #include <unistd.h>
40 #include <errno.h>
41 #include <regex.h>
42 #include <stdio.h>
43
44 #include <iomanip>
45 /*}}}*/
46
47 using namespace std;
48
49 // LocalitySort - Sort a version list by package file locality /*{{{*/
50 // ---------------------------------------------------------------------
51 /* */
52 int LocalityCompare(const void *a, const void *b)
53 {
54 pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
55 pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
56
57 if (A == 0 && B == 0)
58 return 0;
59 if (A == 0)
60 return 1;
61 if (B == 0)
62 return -1;
63
64 if (A->File == B->File)
65 return A->Offset - B->Offset;
66 return A->File - B->File;
67 }
68
69 void LocalitySort(pkgCache::VerFile **begin,
70 unsigned long Count,size_t Size)
71 {
72 qsort(begin,Count,Size,LocalityCompare);
73 }
74
75 void LocalitySort(pkgCache::DescFile **begin,
76 unsigned long Count,size_t Size)
77 {
78 qsort(begin,Count,Size,LocalityCompare);
79 }
80 /*}}}*/
81 // UnMet - Show unmet dependencies /*{{{*/
82 // ---------------------------------------------------------------------
83 /* */
84 bool ShowUnMet(pkgCache::VerIterator const &V, bool const &Important)
85 {
86 bool Header = false;
87 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
88 {
89 // Collect or groups
90 pkgCache::DepIterator Start;
91 pkgCache::DepIterator End;
92 D.GlobOr(Start,End);
93
94 // Important deps only
95 if (Important == true)
96 if (End->Type != pkgCache::Dep::PreDepends &&
97 End->Type != pkgCache::Dep::Depends)
98 continue;
99
100 // Skip conflicts and replaces
101 if (End->Type == pkgCache::Dep::DpkgBreaks ||
102 End->Type == pkgCache::Dep::Replaces ||
103 End->Type == pkgCache::Dep::Conflicts)
104 continue;
105
106 // Verify the or group
107 bool OK = false;
108 pkgCache::DepIterator RealStart = Start;
109 do
110 {
111 // See if this dep is Ok
112 pkgCache::Version **VList = Start.AllTargets();
113 if (*VList != 0)
114 {
115 OK = true;
116 delete [] VList;
117 break;
118 }
119 delete [] VList;
120
121 if (Start == End)
122 break;
123 Start++;
124 }
125 while (1);
126
127 // The group is OK
128 if (OK == true)
129 continue;
130
131 // Oops, it failed..
132 if (Header == false)
133 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
134 V.ParentPkg().FullName(true).c_str(),V.VerStr());
135 Header = true;
136
137 // Print out the dep type
138 cout << " " << End.DepType() << ": ";
139
140 // Show the group
141 Start = RealStart;
142 do
143 {
144 cout << Start.TargetPkg().FullName(true);
145 if (Start.TargetVer() != 0)
146 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
147 ")";
148 if (Start == End)
149 break;
150 cout << " | ";
151 Start++;
152 }
153 while (1);
154
155 cout << endl;
156 }
157 return true;
158 }
159 bool UnMet(CommandLine &CmdL)
160 {
161 bool const Important = _config->FindB("APT::Cache::Important",false);
162
163 pkgCacheFile CacheFile;
164 if (unlikely(CacheFile.GetPkgCache() == NULL))
165 return false;
166
167 if (CmdL.FileSize() <= 1)
168 {
169 for (pkgCache::PkgIterator P = CacheFile.GetPkgCache()->PkgBegin(); P.end() == false; P++)
170 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
171 if (ShowUnMet(V, Important) == false)
172 return false;
173 }
174 else
175 {
176 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
177 APT::VersionSet verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1,
178 APT::VersionSet::CANDIDATE, helper);
179 for (APT::VersionSet::iterator V = verset.begin(); V != verset.end(); ++V)
180 if (ShowUnMet(V, Important) == false)
181 return false;
182 }
183 return true;
184 }
185 /*}}}*/
186 // DumpPackage - Show a dump of a package record /*{{{*/
187 // ---------------------------------------------------------------------
188 /* */
189 bool DumpPackage(CommandLine &CmdL)
190 {
191 pkgCacheFile CacheFile;
192 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
193 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
194
195 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
196 {
197 cout << "Package: " << Pkg.FullName(true) << endl;
198 cout << "Versions: " << endl;
199 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
200 {
201 cout << Cur.VerStr();
202 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
203 cout << " (" << Vf.File().FileName() << ")";
204 cout << endl;
205 for (pkgCache::DescIterator D = Cur.DescriptionList(); D.end() == false; D++)
206 {
207 cout << " Description Language: " << D.LanguageCode() << endl
208 << " File: " << D.FileList().File().FileName() << endl
209 << " MD5: " << D.md5() << endl;
210 }
211 cout << endl;
212 }
213
214 cout << endl;
215
216 cout << "Reverse Depends: " << endl;
217 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
218 {
219 cout << " " << D.ParentPkg().FullName(true) << ',' << D.TargetPkg().FullName(true);
220 if (D->Version != 0)
221 cout << ' ' << DeNull(D.TargetVer()) << endl;
222 else
223 cout << endl;
224 }
225
226 cout << "Dependencies: " << endl;
227 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
228 {
229 cout << Cur.VerStr() << " - ";
230 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
231 cout << Dep.TargetPkg().FullName(true) << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
232 cout << endl;
233 }
234
235 cout << "Provides: " << endl;
236 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
237 {
238 cout << Cur.VerStr() << " - ";
239 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
240 cout << Prv.ParentPkg().FullName(true) << " ";
241 cout << endl;
242 }
243 cout << "Reverse Provides: " << endl;
244 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
245 cout << Prv.OwnerPkg().FullName(true) << " " << Prv.OwnerVer().VerStr() << endl;
246 }
247
248 return true;
249 }
250 /*}}}*/
251 // Stats - Dump some nice statistics /*{{{*/
252 // ---------------------------------------------------------------------
253 /* */
254 bool Stats(CommandLine &Cmd)
255 {
256 pkgCacheFile CacheFile;
257 pkgCache *Cache = CacheFile.GetPkgCache();
258 if (unlikely(Cache == NULL))
259 return false;
260
261 cout << _("Total package names: ") << Cache->Head().GroupCount << " (" <<
262 SizeToStr(Cache->Head().GroupCount*Cache->Head().GroupSz) << ')' << endl
263 << _("Total package structures: ") << Cache->Head().PackageCount << " (" <<
264 SizeToStr(Cache->Head().PackageCount*Cache->Head().PackageSz) << ')' << endl;
265
266 int Normal = 0;
267 int Virtual = 0;
268 int NVirt = 0;
269 int DVirt = 0;
270 int Missing = 0;
271 pkgCache::PkgIterator I = Cache->PkgBegin();
272 for (;I.end() != true; I++)
273 {
274 if (I->VersionList != 0 && I->ProvidesList == 0)
275 {
276 Normal++;
277 continue;
278 }
279
280 if (I->VersionList != 0 && I->ProvidesList != 0)
281 {
282 NVirt++;
283 continue;
284 }
285
286 if (I->VersionList == 0 && I->ProvidesList != 0)
287 {
288 // Only 1 provides
289 if (I.ProvidesList()->NextProvides == 0)
290 {
291 DVirt++;
292 }
293 else
294 Virtual++;
295 continue;
296 }
297 if (I->VersionList == 0 && I->ProvidesList == 0)
298 {
299 Missing++;
300 continue;
301 }
302 }
303 cout << _(" Normal packages: ") << Normal << endl;
304 cout << _(" Pure virtual packages: ") << Virtual << endl;
305 cout << _(" Single virtual packages: ") << DVirt << endl;
306 cout << _(" Mixed virtual packages: ") << NVirt << endl;
307 cout << _(" Missing: ") << Missing << endl;
308
309 cout << _("Total distinct versions: ") << Cache->Head().VersionCount << " (" <<
310 SizeToStr(Cache->Head().VersionCount*Cache->Head().VersionSz) << ')' << endl;
311 cout << _("Total distinct descriptions: ") << Cache->Head().DescriptionCount << " (" <<
312 SizeToStr(Cache->Head().DescriptionCount*Cache->Head().DescriptionSz) << ')' << endl;
313 cout << _("Total dependencies: ") << Cache->Head().DependsCount << " (" <<
314 SizeToStr(Cache->Head().DependsCount*Cache->Head().DependencySz) << ')' << endl;
315
316 cout << _("Total ver/file relations: ") << Cache->Head().VerFileCount << " (" <<
317 SizeToStr(Cache->Head().VerFileCount*Cache->Head().VerFileSz) << ')' << endl;
318 cout << _("Total Desc/File relations: ") << Cache->Head().DescFileCount << " (" <<
319 SizeToStr(Cache->Head().DescFileCount*Cache->Head().DescFileSz) << ')' << endl;
320 cout << _("Total Provides mappings: ") << Cache->Head().ProvidesCount << " (" <<
321 SizeToStr(Cache->Head().ProvidesCount*Cache->Head().ProvidesSz) << ')' << endl;
322
323 // String list stats
324 unsigned long Size = 0;
325 unsigned long Count = 0;
326 for (pkgCache::StringItem *I = Cache->StringItemP + Cache->Head().StringList;
327 I!= Cache->StringItemP; I = Cache->StringItemP + I->NextItem)
328 {
329 Count++;
330 Size += strlen(Cache->StrP + I->String) + 1;
331 }
332 cout << _("Total globbed strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
333
334 unsigned long DepVerSize = 0;
335 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
336 {
337 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
338 {
339 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
340 {
341 if (D->Version != 0)
342 DepVerSize += strlen(D.TargetVer()) + 1;
343 }
344 }
345 }
346 cout << _("Total dependency version space: ") << SizeToStr(DepVerSize) << endl;
347
348 unsigned long Slack = 0;
349 for (int I = 0; I != 7; I++)
350 Slack += Cache->Head().Pools[I].ItemSize*Cache->Head().Pools[I].Count;
351 cout << _("Total slack space: ") << SizeToStr(Slack) << endl;
352
353 unsigned long Total = 0;
354 Total = Slack + Size + Cache->Head().DependsCount*Cache->Head().DependencySz +
355 Cache->Head().VersionCount*Cache->Head().VersionSz +
356 Cache->Head().PackageCount*Cache->Head().PackageSz +
357 Cache->Head().VerFileCount*Cache->Head().VerFileSz +
358 Cache->Head().ProvidesCount*Cache->Head().ProvidesSz;
359 cout << _("Total space accounted for: ") << SizeToStr(Total) << endl;
360
361 return true;
362 }
363 /*}}}*/
364 // Dump - show everything /*{{{*/
365 // ---------------------------------------------------------------------
366 /* This is worthless except fer debugging things */
367 bool Dump(CommandLine &Cmd)
368 {
369 pkgCacheFile CacheFile;
370 pkgCache *Cache = CacheFile.GetPkgCache();
371 if (unlikely(Cache == NULL))
372 return false;
373
374 cout << "Using Versioning System: " << Cache->VS->Label << endl;
375
376 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
377 {
378 cout << "Package: " << P.FullName(true) << endl;
379 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
380 {
381 cout << " Version: " << V.VerStr() << endl;
382 cout << " File: " << V.FileList().File().FileName() << endl;
383 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
384 cout << " Depends: " << D.TargetPkg().FullName(true) << ' ' <<
385 DeNull(D.TargetVer()) << endl;
386 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; D++)
387 {
388 cout << " Description Language: " << D.LanguageCode() << endl
389 << " File: " << D.FileList().File().FileName() << endl
390 << " MD5: " << D.md5() << endl;
391 }
392 }
393 }
394
395 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; F++)
396 {
397 cout << "File: " << F.FileName() << endl;
398 cout << " Type: " << F.IndexType() << endl;
399 cout << " Size: " << F->Size << endl;
400 cout << " ID: " << F->ID << endl;
401 cout << " Flags: " << F->Flags << endl;
402 cout << " Time: " << TimeRFC1123(F->mtime) << endl;
403 cout << " Archive: " << DeNull(F.Archive()) << endl;
404 cout << " Component: " << DeNull(F.Component()) << endl;
405 cout << " Version: " << DeNull(F.Version()) << endl;
406 cout << " Origin: " << DeNull(F.Origin()) << endl;
407 cout << " Site: " << DeNull(F.Site()) << endl;
408 cout << " Label: " << DeNull(F.Label()) << endl;
409 cout << " Architecture: " << DeNull(F.Architecture()) << endl;
410 }
411
412 return true;
413 }
414 /*}}}*/
415 // DumpAvail - Print out the available list /*{{{*/
416 // ---------------------------------------------------------------------
417 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
418 make this run really fast, perhaps I went a little overboard.. */
419 bool DumpAvail(CommandLine &Cmd)
420 {
421 pkgCacheFile CacheFile;
422 pkgCache *Cache = CacheFile.GetPkgCache();
423 if (unlikely(Cache == NULL || CacheFile.BuildPolicy() == false))
424 return false;
425
426 unsigned long Count = Cache->HeaderP->PackageCount+1;
427 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
428 memset(VFList,0,sizeof(*VFList)*Count);
429
430 // Map versions that we want to write out onto the VerList array.
431 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
432 {
433 if (P->VersionList == 0)
434 continue;
435
436 /* Find the proper version to use. If the policy says there are no
437 possible selections we return the installed version, if available..
438 This prevents dselect from making it obsolete. */
439 pkgCache::VerIterator V = CacheFile.GetPolicy()->GetCandidateVer(P);
440 if (V.end() == true)
441 {
442 if (P->CurrentVer == 0)
443 continue;
444 V = P.CurrentVer();
445 }
446
447 pkgCache::VerFileIterator VF = V.FileList();
448 for (; VF.end() == false ; VF++)
449 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
450 break;
451
452 /* Okay, here we have a bit of a problem.. The policy has selected the
453 currently installed package - however it only exists in the
454 status file.. We need to write out something or dselect will mark
455 the package as obsolete! Thus we emit the status file entry, but
456 below we remove the status line to make it valid for the
457 available file. However! We only do this if their do exist *any*
458 non-source versions of the package - that way the dselect obsolete
459 handling works OK. */
460 if (VF.end() == true)
461 {
462 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; Cur++)
463 {
464 for (VF = Cur.FileList(); VF.end() == false; VF++)
465 {
466 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
467 {
468 VF = V.FileList();
469 break;
470 }
471 }
472
473 if (VF.end() == false)
474 break;
475 }
476 }
477
478 VFList[P->ID] = VF;
479 }
480
481 LocalitySort(VFList,Count,sizeof(*VFList));
482
483 // Iterate over all the package files and write them out.
484 char *Buffer = new char[Cache->HeaderP->MaxVerFileSize+10];
485 for (pkgCache::VerFile **J = VFList; *J != 0;)
486 {
487 pkgCache::PkgFileIterator File(*Cache,(*J)->File + Cache->PkgFileP);
488 if (File.IsOk() == false)
489 {
490 _error->Error(_("Package file %s is out of sync."),File.FileName());
491 break;
492 }
493
494 FileFd PkgF(File.FileName(),FileFd::ReadOnly);
495 if (_error->PendingError() == true)
496 break;
497
498 /* Write all of the records from this package file, since we
499 already did locality sorting we can now just seek through the
500 file in read order. We apply 1 more optimization here, since often
501 there will be < 1 byte gaps between records (for the \n) we read that
502 into the next buffer and offset a bit.. */
503 unsigned long Pos = 0;
504 for (; *J != 0; J++)
505 {
506 if ((*J)->File + Cache->PkgFileP != File)
507 break;
508
509 const pkgCache::VerFile &VF = **J;
510
511 // Read the record and then write it out again.
512 unsigned long Jitter = VF.Offset - Pos;
513 if (Jitter > 8)
514 {
515 if (PkgF.Seek(VF.Offset) == false)
516 break;
517 Jitter = 0;
518 }
519
520 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
521 break;
522 Buffer[VF.Size + Jitter] = '\n';
523
524 // See above..
525 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
526 {
527 pkgTagSection Tags;
528 TFRewriteData RW[] = {{"Status",0},{"Config-Version",0},{}};
529 const char *Zero = 0;
530 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
531 TFRewrite(stdout,Tags,&Zero,RW) == false)
532 {
533 _error->Error("Internal Error, Unable to parse a package record");
534 break;
535 }
536 fputc('\n',stdout);
537 }
538 else
539 {
540 if (fwrite(Buffer+Jitter,VF.Size+1,1,stdout) != 1)
541 break;
542 }
543
544 Pos = VF.Offset + VF.Size;
545 }
546
547 fflush(stdout);
548 if (_error->PendingError() == true)
549 break;
550 }
551
552 delete [] Buffer;
553 delete [] VFList;
554 return !_error->PendingError();
555 }
556 /*}}}*/
557 // ShowDepends - Helper for printing out a dependency tree /*{{{*/
558 class CacheSetHelperDepends: public APT::CacheSetHelper {
559 public:
560 APT::PackageSet virtualPkgs;
561
562 virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
563 virtualPkgs.insert(Pkg);
564 return pkgCache::VerIterator(Cache, 0);
565 }
566
567 virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
568 virtualPkgs.insert(Pkg);
569 return pkgCache::VerIterator(Cache, 0);
570 }
571
572 CacheSetHelperDepends() : CacheSetHelper(false, GlobalError::NOTICE) {}
573 };
574 bool ShowDepends(CommandLine &CmdL, bool const RevDepends)
575 {
576 pkgCacheFile CacheFile;
577 pkgCache *Cache = CacheFile.GetPkgCache();
578 if (unlikely(Cache == NULL))
579 return false;
580
581 CacheSetHelperDepends helper;
582 APT::VersionSet verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper);
583 if (verset.empty() == true && helper.virtualPkgs.empty() == true)
584 return false;
585 std::vector<bool> Shown(Cache->Head().PackageCount);
586
587 bool const Recurse = _config->FindB("APT::Cache::RecurseDepends", false);
588 bool const Installed = _config->FindB("APT::Cache::Installed", false);
589 bool const Important = _config->FindB("APT::Cache::Important", false);
590 bool const ShowDepType = _config->FindB("APT::Cache::ShowDependencyType", RevDepends == false);
591 bool const ShowPreDepends = _config->FindB("APT::Cache::ShowPre-Depends", true);
592 bool const ShowDepends = _config->FindB("APT::Cache::ShowDepends", true);
593 bool const ShowRecommends = _config->FindB("APT::Cache::ShowRecommends", Important == false);
594 bool const ShowSuggests = _config->FindB("APT::Cache::ShowSuggests", Important == false);
595 bool const ShowReplaces = _config->FindB("APT::Cache::ShowReplaces", Important == false);
596 bool const ShowConflicts = _config->FindB("APT::Cache::ShowConflicts", Important == false);
597 bool const ShowBreaks = _config->FindB("APT::Cache::ShowBreaks", Important == false);
598 bool const ShowEnhances = _config->FindB("APT::Cache::ShowEnhances", Important == false);
599 bool const ShowOnlyFirstOr = _config->FindB("APT::Cache::ShowOnlyFirstOr", false);
600
601 while (verset.empty() != true)
602 {
603 pkgCache::VerIterator Ver = *verset.begin();
604 verset.erase(verset.begin());
605 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
606 Shown[Pkg->ID] = true;
607
608 cout << Pkg.FullName(true) << endl;
609
610 if (RevDepends == true)
611 cout << "Reverse Depends:" << endl;
612 for (pkgCache::DepIterator D = RevDepends ? Pkg.RevDependsList() : Ver.DependsList();
613 D.end() == false; D++)
614 {
615 switch (D->Type) {
616 case pkgCache::Dep::PreDepends: if (!ShowPreDepends) continue; break;
617 case pkgCache::Dep::Depends: if (!ShowDepends) continue; break;
618 case pkgCache::Dep::Recommends: if (!ShowRecommends) continue; break;
619 case pkgCache::Dep::Suggests: if (!ShowSuggests) continue; break;
620 case pkgCache::Dep::Replaces: if (!ShowReplaces) continue; break;
621 case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break;
622 case pkgCache::Dep::DpkgBreaks: if (!ShowBreaks) continue; break;
623 case pkgCache::Dep::Enhances: if (!ShowEnhances) continue; break;
624 }
625
626 pkgCache::PkgIterator Trg = RevDepends ? D.ParentPkg() : D.TargetPkg();
627
628 if((Installed && Trg->CurrentVer != 0) || !Installed)
629 {
630
631 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or && ShowOnlyFirstOr == false)
632 cout << " |";
633 else
634 cout << " ";
635
636 // Show the package
637 if (ShowDepType == true)
638 cout << D.DepType() << ": ";
639 if (Trg->VersionList == 0)
640 cout << "<" << Trg.FullName(true) << ">" << endl;
641 else
642 cout << Trg.FullName(true) << endl;
643
644 if (Recurse == true && Shown[Trg->ID] == false)
645 {
646 Shown[Trg->ID] = true;
647 verset.insert(APT::VersionSet::FromPackage(CacheFile, Trg, APT::VersionSet::CANDIDATE, helper));
648 }
649
650 }
651
652 // Display all solutions
653 SPtrArray<pkgCache::Version *> List = D.AllTargets();
654 pkgPrioSortList(*Cache,List);
655 for (pkgCache::Version **I = List; *I != 0; I++)
656 {
657 pkgCache::VerIterator V(*Cache,*I);
658 if (V != Cache->VerP + V.ParentPkg()->VersionList ||
659 V->ParentPkg == D->Package)
660 continue;
661 cout << " " << V.ParentPkg().FullName(true) << endl;
662
663 if (Recurse == true && Shown[V.ParentPkg()->ID] == false)
664 {
665 Shown[V.ParentPkg()->ID] = true;
666 verset.insert(APT::VersionSet::FromPackage(CacheFile, V.ParentPkg(), APT::VersionSet::CANDIDATE, helper));
667 }
668 }
669
670 if (ShowOnlyFirstOr == true)
671 while ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) ++D;
672 }
673 }
674
675 for (APT::PackageSet::const_iterator Pkg = helper.virtualPkgs.begin();
676 Pkg != helper.virtualPkgs.end(); ++Pkg)
677 cout << '<' << Pkg.FullName(true) << '>' << endl;
678
679 return true;
680 }
681 /*}}}*/
682 // Depends - Print out a dependency tree /*{{{*/
683 // ---------------------------------------------------------------------
684 /* */
685 bool Depends(CommandLine &CmdL)
686 {
687 return ShowDepends(CmdL, false);
688 }
689 /*}}}*/
690 // RDepends - Print out a reverse dependency tree /*{{{*/
691 // ---------------------------------------------------------------------
692 /* */
693 bool RDepends(CommandLine &CmdL)
694 {
695 return ShowDepends(CmdL, true);
696 }
697 /*}}}*/
698 // xvcg - Generate a graph for xvcg /*{{{*/
699 // ---------------------------------------------------------------------
700 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
701
702 bool XVcg(CommandLine &CmdL)
703 {
704 pkgCacheFile CacheFile;
705 pkgCache *Cache = CacheFile.GetPkgCache();
706 if (unlikely(Cache == NULL))
707 return false;
708
709 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
710
711 /* Normal packages are boxes
712 Pure Provides are triangles
713 Mixed are diamonds
714 rhomb are missing packages*/
715 const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
716
717 /* Initialize the list of packages to show.
718 1 = To Show
719 2 = To Show no recurse
720 3 = Emitted no recurse
721 4 = Emitted
722 0 = None */
723 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
724 enum TheFlags {ForceNR=(1<<0)};
725 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
726 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
727 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
728
729 // Show everything if no arguments given
730 if (CmdL.FileList[1] == 0)
731 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
732 Show[I] = ToShow;
733 else
734 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
735 Show[I] = None;
736 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
737
738 // Map the shapes
739 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
740 {
741 if (Pkg->VersionList == 0)
742 {
743 // Missing
744 if (Pkg->ProvidesList == 0)
745 ShapeMap[Pkg->ID] = 0;
746 else
747 ShapeMap[Pkg->ID] = 1;
748 }
749 else
750 {
751 // Normal
752 if (Pkg->ProvidesList == 0)
753 ShapeMap[Pkg->ID] = 2;
754 else
755 ShapeMap[Pkg->ID] = 3;
756 }
757 }
758
759 // Load the list of packages from the command line into the show list
760 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
761 std::list<APT::PackageSet::Modifier> mods;
762 mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
763 mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
764 std::map<unsigned short, APT::PackageSet> pkgsets =
765 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
766
767 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
768 Pkg != pkgsets[0].end(); ++Pkg)
769 Show[Pkg->ID] = ToShow;
770 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
771 Pkg != pkgsets[1].end(); ++Pkg)
772 {
773 Show[Pkg->ID] = ToShow;
774 Flags[Pkg->ID] |= ForceNR;
775 }
776
777 // Little header
778 cout << "graph: { title: \"packages\"" << endl <<
779 "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
780 "layout_downfactor: 8" << endl;
781
782 bool Act = true;
783 while (Act == true)
784 {
785 Act = false;
786 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
787 {
788 // See we need to show this package
789 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
790 continue;
791
792 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
793
794 // Colour as done
795 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
796 {
797 // Pure Provides and missing packages have no deps!
798 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
799 Show[Pkg->ID] = Done;
800 else
801 Show[Pkg->ID] = DoneNR;
802 }
803 else
804 Show[Pkg->ID] = Done;
805 Act = true;
806
807 // No deps to map out
808 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
809 continue;
810
811 pkgCache::VerIterator Ver = Pkg.VersionList();
812 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
813 {
814 // See if anything can meet this dep
815 // Walk along the actual package providing versions
816 bool Hit = false;
817 pkgCache::PkgIterator DPkg = D.TargetPkg();
818 for (pkgCache::VerIterator I = DPkg.VersionList();
819 I.end() == false && Hit == false; I++)
820 {
821 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
822 Hit = true;
823 }
824
825 // Follow all provides
826 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
827 I.end() == false && Hit == false; I++)
828 {
829 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
830 Hit = true;
831 }
832
833
834 // Only graph critical deps
835 if (D.IsCritical() == true)
836 {
837 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.FullName(true).c_str(), D.TargetPkg().FullName(true).c_str() );
838
839 // Colour the node for recursion
840 if (Show[D.TargetPkg()->ID] <= DoneNR)
841 {
842 /* If a conflicts does not meet anything in the database
843 then show the relation but do not recurse */
844 if (Hit == false &&
845 (D->Type == pkgCache::Dep::Conflicts ||
846 D->Type == pkgCache::Dep::DpkgBreaks ||
847 D->Type == pkgCache::Dep::Obsoletes))
848 {
849 if (Show[D.TargetPkg()->ID] == None &&
850 Show[D.TargetPkg()->ID] != ToShow)
851 Show[D.TargetPkg()->ID] = ToShowNR;
852 }
853 else
854 {
855 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
856 Show[D.TargetPkg()->ID] = ToShowNR;
857 else
858 Show[D.TargetPkg()->ID] = ToShow;
859 }
860 }
861
862 // Edge colour
863 switch(D->Type)
864 {
865 case pkgCache::Dep::Conflicts:
866 printf("label: \"conflicts\" color: lightgreen }\n");
867 break;
868 case pkgCache::Dep::DpkgBreaks:
869 printf("label: \"breaks\" color: lightgreen }\n");
870 break;
871 case pkgCache::Dep::Obsoletes:
872 printf("label: \"obsoletes\" color: lightgreen }\n");
873 break;
874
875 case pkgCache::Dep::PreDepends:
876 printf("label: \"predepends\" color: blue }\n");
877 break;
878
879 default:
880 printf("}\n");
881 break;
882 }
883 }
884 }
885 }
886 }
887
888 /* Draw the box colours after the fact since we can not tell what colour
889 they should be until everything is finished drawing */
890 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
891 {
892 if (Show[Pkg->ID] < DoneNR)
893 continue;
894
895 if (Show[Pkg->ID] == DoneNR)
896 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
897 Shapes[ShapeMap[Pkg->ID]]);
898 else
899 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
900 Shapes[ShapeMap[Pkg->ID]]);
901
902 }
903
904 delete[] Show;
905 delete[] Flags;
906 delete[] ShapeMap;
907
908 printf("}\n");
909 return true;
910 }
911 /*}}}*/
912 // Dotty - Generate a graph for Dotty /*{{{*/
913 // ---------------------------------------------------------------------
914 /* Dotty is the graphvis program for generating graphs. It is a fairly
915 simple queuing algorithm that just writes dependencies and nodes.
916 http://www.research.att.com/sw/tools/graphviz/ */
917 bool Dotty(CommandLine &CmdL)
918 {
919 pkgCacheFile CacheFile;
920 pkgCache *Cache = CacheFile.GetPkgCache();
921 if (unlikely(Cache == NULL))
922 return false;
923
924 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
925
926 /* Normal packages are boxes
927 Pure Provides are triangles
928 Mixed are diamonds
929 Hexagons are missing packages*/
930 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
931
932 /* Initialize the list of packages to show.
933 1 = To Show
934 2 = To Show no recurse
935 3 = Emitted no recurse
936 4 = Emitted
937 0 = None */
938 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
939 enum TheFlags {ForceNR=(1<<0)};
940 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
941 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
942 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
943
944 // Show everything if no arguments given
945 if (CmdL.FileList[1] == 0)
946 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
947 Show[I] = ToShow;
948 else
949 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
950 Show[I] = None;
951 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
952
953 // Map the shapes
954 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
955 {
956 if (Pkg->VersionList == 0)
957 {
958 // Missing
959 if (Pkg->ProvidesList == 0)
960 ShapeMap[Pkg->ID] = 0;
961 else
962 ShapeMap[Pkg->ID] = 1;
963 }
964 else
965 {
966 // Normal
967 if (Pkg->ProvidesList == 0)
968 ShapeMap[Pkg->ID] = 2;
969 else
970 ShapeMap[Pkg->ID] = 3;
971 }
972 }
973
974 // Load the list of packages from the command line into the show list
975 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
976 std::list<APT::PackageSet::Modifier> mods;
977 mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
978 mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
979 std::map<unsigned short, APT::PackageSet> pkgsets =
980 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
981
982 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
983 Pkg != pkgsets[0].end(); ++Pkg)
984 Show[Pkg->ID] = ToShow;
985 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
986 Pkg != pkgsets[1].end(); ++Pkg)
987 {
988 Show[Pkg->ID] = ToShow;
989 Flags[Pkg->ID] |= ForceNR;
990 }
991
992 // Little header
993 printf("digraph packages {\n");
994 printf("concentrate=true;\n");
995 printf("size=\"30,40\";\n");
996
997 bool Act = true;
998 while (Act == true)
999 {
1000 Act = false;
1001 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
1002 {
1003 // See we need to show this package
1004 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
1005 continue;
1006
1007 // Colour as done
1008 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
1009 {
1010 // Pure Provides and missing packages have no deps!
1011 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
1012 Show[Pkg->ID] = Done;
1013 else
1014 Show[Pkg->ID] = DoneNR;
1015 }
1016 else
1017 Show[Pkg->ID] = Done;
1018 Act = true;
1019
1020 // No deps to map out
1021 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
1022 continue;
1023
1024 pkgCache::VerIterator Ver = Pkg.VersionList();
1025 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
1026 {
1027 // See if anything can meet this dep
1028 // Walk along the actual package providing versions
1029 bool Hit = false;
1030 pkgCache::PkgIterator DPkg = D.TargetPkg();
1031 for (pkgCache::VerIterator I = DPkg.VersionList();
1032 I.end() == false && Hit == false; I++)
1033 {
1034 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
1035 Hit = true;
1036 }
1037
1038 // Follow all provides
1039 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
1040 I.end() == false && Hit == false; I++)
1041 {
1042 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
1043 Hit = true;
1044 }
1045
1046 // Only graph critical deps
1047 if (D.IsCritical() == true)
1048 {
1049 printf("\"%s\" -> \"%s\"",Pkg.FullName(true).c_str(),D.TargetPkg().FullName(true).c_str());
1050
1051 // Colour the node for recursion
1052 if (Show[D.TargetPkg()->ID] <= DoneNR)
1053 {
1054 /* If a conflicts does not meet anything in the database
1055 then show the relation but do not recurse */
1056 if (Hit == false &&
1057 (D->Type == pkgCache::Dep::Conflicts ||
1058 D->Type == pkgCache::Dep::Obsoletes))
1059 {
1060 if (Show[D.TargetPkg()->ID] == None &&
1061 Show[D.TargetPkg()->ID] != ToShow)
1062 Show[D.TargetPkg()->ID] = ToShowNR;
1063 }
1064 else
1065 {
1066 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
1067 Show[D.TargetPkg()->ID] = ToShowNR;
1068 else
1069 Show[D.TargetPkg()->ID] = ToShow;
1070 }
1071 }
1072
1073 // Edge colour
1074 switch(D->Type)
1075 {
1076 case pkgCache::Dep::Conflicts:
1077 case pkgCache::Dep::Obsoletes:
1078 printf("[color=springgreen];\n");
1079 break;
1080
1081 case pkgCache::Dep::PreDepends:
1082 printf("[color=blue];\n");
1083 break;
1084
1085 default:
1086 printf(";\n");
1087 break;
1088 }
1089 }
1090 }
1091 }
1092 }
1093
1094 /* Draw the box colours after the fact since we can not tell what colour
1095 they should be until everything is finished drawing */
1096 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
1097 {
1098 if (Show[Pkg->ID] < DoneNR)
1099 continue;
1100
1101 // Orange box for early recursion stoppage
1102 if (Show[Pkg->ID] == DoneNR)
1103 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.FullName(true).c_str(),
1104 Shapes[ShapeMap[Pkg->ID]]);
1105 else
1106 printf("\"%s\" [shape=%s];\n",Pkg.FullName(true).c_str(),
1107 Shapes[ShapeMap[Pkg->ID]]);
1108 }
1109
1110 printf("}\n");
1111 return true;
1112 }
1113 /*}}}*/
1114 // DoAdd - Perform an adding operation /*{{{*/
1115 // ---------------------------------------------------------------------
1116 /* */
1117 bool DoAdd(CommandLine &CmdL)
1118 {
1119 return _error->Error("Unimplemented");
1120 #if 0
1121 // Make sure there is at least one argument
1122 if (CmdL.FileSize() <= 1)
1123 return _error->Error("You must give at least one file name");
1124
1125 // Open the cache
1126 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
1127 if (_error->PendingError() == true)
1128 return false;
1129
1130 DynamicMMap Map(CacheF,MMap::Public);
1131 if (_error->PendingError() == true)
1132 return false;
1133
1134 OpTextProgress Progress(*_config);
1135 pkgCacheGenerator Gen(Map,Progress);
1136 if (_error->PendingError() == true)
1137 return false;
1138
1139 unsigned long Length = CmdL.FileSize() - 1;
1140 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1141 {
1142 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
1143 Progress.SubProgress(Length);
1144
1145 // Do the merge
1146 FileFd TagF(*I,FileFd::ReadOnly);
1147 debListParser Parser(TagF);
1148 if (_error->PendingError() == true)
1149 return _error->Error("Problem opening %s",*I);
1150
1151 if (Gen.SelectFile(*I,"") == false)
1152 return _error->Error("Problem with SelectFile");
1153
1154 if (Gen.MergeList(Parser) == false)
1155 return _error->Error("Problem with MergeList");
1156 }
1157
1158 Progress.Done();
1159 GCache = &Gen.GetCache();
1160 Stats(CmdL);
1161
1162 return true;
1163 #endif
1164 }
1165 /*}}}*/
1166 // DisplayRecord - Displays the complete record for the package /*{{{*/
1167 // ---------------------------------------------------------------------
1168 /* This displays the package record from the proper package index file.
1169 It is not used by DumpAvail for performance reasons. */
1170 bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
1171 {
1172 pkgCache *Cache = CacheFile.GetPkgCache();
1173 if (unlikely(Cache == NULL))
1174 return false;
1175
1176 // Find an appropriate file
1177 pkgCache::VerFileIterator Vf = V.FileList();
1178 for (; Vf.end() == false; Vf++)
1179 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
1180 break;
1181 if (Vf.end() == true)
1182 Vf = V.FileList();
1183
1184 // Check and load the package list file
1185 pkgCache::PkgFileIterator I = Vf.File();
1186 if (I.IsOk() == false)
1187 return _error->Error(_("Package file %s is out of sync."),I.FileName());
1188
1189 FileFd PkgF;
1190 if (PkgF.Open(I.FileName(), FileFd::ReadOnlyGzip) == false)
1191 return false;
1192
1193 // Read the record
1194 unsigned char *Buffer = new unsigned char[Cache->HeaderP->MaxVerFileSize+1];
1195 Buffer[V.FileList()->Size] = '\n';
1196 if (PkgF.Seek(V.FileList()->Offset) == false ||
1197 PkgF.Read(Buffer,V.FileList()->Size) == false)
1198 {
1199 delete [] Buffer;
1200 return false;
1201 }
1202
1203 // Get a pointer to start of Description field
1204 const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "Description:");
1205
1206 // Write all but Description
1207 if (fwrite(Buffer,1,DescP - Buffer,stdout) < (size_t)(DescP - Buffer))
1208 {
1209 delete [] Buffer;
1210 return false;
1211 }
1212
1213 // Show the right description
1214 pkgRecords Recs(*Cache);
1215 pkgCache::DescIterator Desc = V.TranslatedDescription();
1216 pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
1217 cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
1218
1219 // Find the first field after the description (if there is any)
1220 for(DescP++;DescP != &Buffer[V.FileList()->Size];DescP++)
1221 {
1222 if(*DescP == '\n' && *(DescP+1) != ' ')
1223 {
1224 // write the rest of the buffer
1225 const unsigned char *end=&Buffer[V.FileList()->Size];
1226 if (fwrite(DescP,1,end-DescP,stdout) < (size_t)(end-DescP))
1227 {
1228 delete [] Buffer;
1229 return false;
1230 }
1231
1232 break;
1233 }
1234 }
1235 // write a final newline (after the description)
1236 cout<<endl;
1237 delete [] Buffer;
1238
1239 return true;
1240 }
1241 /*}}}*/
1242
1243 struct ExDescFile
1244 {
1245 pkgCache::DescFile *Df;
1246 bool NameMatch;
1247 };
1248
1249 // Search - Perform a search /*{{{*/
1250 // ---------------------------------------------------------------------
1251 /* This searches the package names and package descriptions for a pattern */
1252 bool Search(CommandLine &CmdL)
1253 {
1254 bool const ShowFull = _config->FindB("APT::Cache::ShowFull",false);
1255 bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
1256 unsigned int const NumPatterns = CmdL.FileSize() -1;
1257
1258 pkgCacheFile CacheFile;
1259 pkgCache *Cache = CacheFile.GetPkgCache();
1260 pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
1261 if (unlikely(Cache == NULL || Plcy == NULL))
1262 return false;
1263
1264 // Make sure there is at least one argument
1265 if (NumPatterns < 1)
1266 return _error->Error(_("You must give at least one search pattern"));
1267
1268 // Compile the regex pattern
1269 regex_t *Patterns = new regex_t[NumPatterns];
1270 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
1271 for (unsigned I = 0; I != NumPatterns; I++)
1272 {
1273 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
1274 REG_NOSUB) != 0)
1275 {
1276 for (; I != 0; I--)
1277 regfree(&Patterns[I]);
1278 return _error->Error("Regex compilation error");
1279 }
1280 }
1281
1282 if (_error->PendingError() == true)
1283 {
1284 for (unsigned I = 0; I != NumPatterns; I++)
1285 regfree(&Patterns[I]);
1286 return false;
1287 }
1288
1289 ExDescFile *DFList = new ExDescFile[Cache->HeaderP->GroupCount+1];
1290 memset(DFList,0,sizeof(*DFList)*Cache->HeaderP->GroupCount+1);
1291
1292 // Map versions that we want to write out onto the VerList array.
1293 for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
1294 {
1295 if (DFList[G->ID].NameMatch == true)
1296 continue;
1297
1298 DFList[G->ID].NameMatch = true;
1299 for (unsigned I = 0; I != NumPatterns; I++)
1300 {
1301 if (regexec(&Patterns[I],G.Name(),0,0,0) == 0)
1302 continue;
1303 DFList[G->ID].NameMatch = false;
1304 break;
1305 }
1306
1307 // Doing names only, drop any that dont match..
1308 if (NamesOnly == true && DFList[G->ID].NameMatch == false)
1309 continue;
1310
1311 // Find the proper version to use
1312 pkgCache::PkgIterator P = G.FindPreferredPkg();
1313 if (P.end() == true)
1314 continue;
1315 pkgCache::VerIterator V = Plcy->GetCandidateVer(P);
1316 if (V.end() == false)
1317 DFList[G->ID].Df = V.DescriptionList().FileList();
1318
1319 if (DFList[G->ID].NameMatch == false)
1320 continue;
1321
1322 // Include all the packages that provide matching names too
1323 for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
1324 {
1325 pkgCache::VerIterator V = Plcy->GetCandidateVer(Prv.OwnerPkg());
1326 if (V.end() == true)
1327 continue;
1328
1329 unsigned long id = Prv.OwnerPkg().Group()->ID;
1330 DFList[id].Df = V.DescriptionList().FileList();
1331 DFList[id].NameMatch = true;
1332 }
1333 }
1334
1335 LocalitySort(&DFList->Df,Cache->HeaderP->GroupCount,sizeof(*DFList));
1336
1337 // Create the text record parser
1338 pkgRecords Recs(*Cache);
1339 // Iterate over all the version records and check them
1340 for (ExDescFile *J = DFList; J->Df != 0; J++)
1341 {
1342 pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(*Cache,J->Df));
1343
1344 if (J->NameMatch == false && NamesOnly == false)
1345 {
1346 string const LongDesc = P.LongDesc();
1347 J->NameMatch = true;
1348 for (unsigned I = 0; I != NumPatterns; I++)
1349 {
1350 if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
1351 continue;
1352 J->NameMatch = false;
1353 break;
1354 }
1355 }
1356
1357 if (J->NameMatch == true)
1358 {
1359 if (ShowFull == true)
1360 {
1361 const char *Start;
1362 const char *End;
1363 P.GetRec(Start,End);
1364 fwrite(Start,End-Start,1,stdout);
1365 putc('\n',stdout);
1366 }
1367 else
1368 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
1369 }
1370 }
1371
1372 delete [] DFList;
1373 for (unsigned I = 0; I != NumPatterns; I++)
1374 regfree(&Patterns[I]);
1375 if (ferror(stdout))
1376 return _error->Error("Write to stdout failed");
1377 return true;
1378 }
1379
1380
1381 /* show automatically installed packages (sorted) */
1382 bool ShowAuto(CommandLine &CmdL)
1383 {
1384 pkgCacheFile CacheFile;
1385 pkgCache *Cache = CacheFile.GetPkgCache();
1386 pkgDepCache *DepCache = CacheFile.GetDepCache();
1387 if (unlikely(Cache == NULL || DepCache == NULL))
1388 return false;
1389
1390 std::vector<string> packages;
1391 packages.reserve(Cache->HeaderP->PackageCount / 3);
1392
1393 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
1394 if ((*DepCache)[P].Flags & pkgCache::Flag::Auto)
1395 packages.push_back(P.Name());
1396
1397 std::sort(packages.begin(), packages.end());
1398
1399 for (vector<string>::iterator I = packages.begin(); I != packages.end(); I++)
1400 cout << *I << "\n";
1401
1402 return true;
1403 }
1404 /*}}}*/
1405 // ShowPackage - Dump the package record to the screen /*{{{*/
1406 // ---------------------------------------------------------------------
1407 /* */
1408 bool ShowPackage(CommandLine &CmdL)
1409 {
1410 pkgCacheFile CacheFile;
1411 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
1412 APT::VersionSet::Version const select = _config->FindB("APT::Cache::AllVersions", true) ?
1413 APT::VersionSet::ALL : APT::VersionSet::CANDIDATE;
1414 APT::VersionSet const verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1, select, helper);
1415 for (APT::VersionSet::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver)
1416 if (DisplayRecord(CacheFile, Ver) == false)
1417 return false;
1418
1419 if (verset.empty() == false)
1420 return true;
1421 return _error->Error(_("No packages found"));
1422 }
1423 /*}}}*/
1424 // ShowPkgNames - Show package names /*{{{*/
1425 // ---------------------------------------------------------------------
1426 /* This does a prefix match on the first argument */
1427 bool ShowPkgNames(CommandLine &CmdL)
1428 {
1429 pkgCacheFile CacheFile;
1430 if (unlikely(CacheFile.BuildCaches(NULL, false) == false))
1431 return false;
1432 pkgCache::GrpIterator I = CacheFile.GetPkgCache()->GrpBegin();
1433 bool const All = _config->FindB("APT::Cache::AllNames","false");
1434
1435 if (CmdL.FileList[1] != 0)
1436 {
1437 for (;I.end() != true; I++)
1438 {
1439 if (All == false && I->FirstPackage == 0)
1440 continue;
1441 if (I.FindPkg("any")->VersionList == 0)
1442 continue;
1443 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1444 cout << I.Name() << endl;
1445 }
1446
1447 return true;
1448 }
1449
1450 // Show all pkgs
1451 for (;I.end() != true; I++)
1452 {
1453 if (All == false && I->FirstPackage == 0)
1454 continue;
1455 if (I.FindPkg("any")->VersionList == 0)
1456 continue;
1457 cout << I.Name() << endl;
1458 }
1459
1460 return true;
1461 }
1462 /*}}}*/
1463 // ShowSrcPackage - Show source package records /*{{{*/
1464 // ---------------------------------------------------------------------
1465 /* */
1466 bool ShowSrcPackage(CommandLine &CmdL)
1467 {
1468 pkgCacheFile CacheFile;
1469 pkgSourceList *List = CacheFile.GetSourceList();
1470 if (unlikely(List == NULL))
1471 return false;
1472
1473 // Create the text record parsers
1474 pkgSrcRecords SrcRecs(*List);
1475 if (_error->PendingError() == true)
1476 return false;
1477
1478 unsigned found = 0;
1479 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1480 {
1481 SrcRecs.Restart();
1482
1483 pkgSrcRecords::Parser *Parse;
1484 unsigned found_this = 0;
1485 while ((Parse = SrcRecs.Find(*I,false)) != 0) {
1486 cout << Parse->AsStr() << endl;;
1487 found++;
1488 found_this++;
1489 }
1490 if (found_this == 0) {
1491 _error->Warning(_("Unable to locate package %s"),*I);
1492 continue;
1493 }
1494 }
1495 if (found > 0)
1496 return true;
1497 return _error->Error(_("No packages found"));
1498 }
1499 /*}}}*/
1500 // Policy - Show the results of the preferences file /*{{{*/
1501 // ---------------------------------------------------------------------
1502 /* */
1503 bool Policy(CommandLine &CmdL)
1504 {
1505 pkgCacheFile CacheFile;
1506 pkgCache *Cache = CacheFile.GetPkgCache();
1507 pkgPolicy *Plcy = CacheFile.GetPolicy();
1508 pkgSourceList *SrcList = CacheFile.GetSourceList();
1509 if (unlikely(Cache == NULL || Plcy == NULL || SrcList == NULL))
1510 return false;
1511
1512 /* Should the MultiArchKiller be run to see which pseudo packages for an
1513 arch all package are currently installed? Activating it gives a speed
1514 penality for no real gain beside enhanced debugging, so in general no. */
1515 if (_config->FindB("APT::Cache::Policy::DepCache", false) == true)
1516 CacheFile.GetDepCache();
1517
1518 // Print out all of the package files
1519 if (CmdL.FileList[1] == 0)
1520 {
1521 cout << _("Package files:") << endl;
1522 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; F++)
1523 {
1524 // Locate the associated index files so we can derive a description
1525 pkgIndexFile *Indx;
1526 if (SrcList->FindIndex(F,Indx) == false &&
1527 _system->FindIndex(F,Indx) == false)
1528 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1529
1530 printf("%4i %s\n",
1531 Plcy->GetPriority(F),Indx->Describe(true).c_str());
1532
1533 // Print the reference information for the package
1534 string Str = F.RelStr();
1535 if (Str.empty() == false)
1536 printf(" release %s\n",F.RelStr().c_str());
1537 if (F.Site() != 0 && F.Site()[0] != 0)
1538 printf(" origin %s\n",F.Site());
1539 }
1540
1541 // Show any packages have explicit pins
1542 cout << _("Pinned packages:") << endl;
1543 pkgCache::PkgIterator I = Cache->PkgBegin();
1544 for (;I.end() != true; I++)
1545 {
1546 if (Plcy->GetPriority(I) == 0)
1547 continue;
1548
1549 // Print the package name and the version we are forcing to
1550 cout << " " << I.FullName(true) << " -> ";
1551
1552 pkgCache::VerIterator V = Plcy->GetMatch(I);
1553 if (V.end() == true)
1554 cout << _("(not found)") << endl;
1555 else
1556 cout << V.VerStr() << endl;
1557 }
1558
1559 return true;
1560 }
1561
1562 string const myArch = _config->Find("APT::Architecture");
1563 char const * const msgInstalled = _(" Installed: ");
1564 char const * const msgCandidate = _(" Candidate: ");
1565 short const InstalledLessCandidate =
1566 mbstowcs(NULL, msgInstalled, 0) - mbstowcs(NULL, msgCandidate, 0);
1567 short const deepInstalled =
1568 (InstalledLessCandidate < 0 ? (InstalledLessCandidate*-1) : 0) - 1;
1569 short const deepCandidate =
1570 (InstalledLessCandidate > 0 ? (InstalledLessCandidate) : 0) - 1;
1571
1572 // Print out detailed information for each package
1573 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
1574 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
1575 for (APT::PackageSet::const_iterator I = pkgset.begin(); I != pkgset.end(); ++I)
1576 {
1577 pkgCache::PkgIterator Pkg = I.Group().FindPkg("any");
1578
1579 for (; Pkg.end() != true; Pkg = I.Group().NextPkg(Pkg)) {
1580 if (strcmp(Pkg.Arch(),"all") == 0)
1581 continue;
1582
1583 cout << Pkg.FullName(true) << ":" << endl;
1584
1585 // Installed version
1586 cout << msgInstalled << OutputInDepth(deepInstalled, " ");
1587 if (Pkg->CurrentVer == 0)
1588 cout << _("(none)") << endl;
1589 else
1590 cout << Pkg.CurrentVer().VerStr() << endl;
1591
1592 // Candidate Version
1593 cout << msgCandidate << OutputInDepth(deepCandidate, " ");
1594 pkgCache::VerIterator V = Plcy->GetCandidateVer(Pkg);
1595 if (V.end() == true)
1596 cout << _("(none)") << endl;
1597 else
1598 cout << V.VerStr() << endl;
1599
1600 // Pinned version
1601 if (Plcy->GetPriority(Pkg) != 0)
1602 {
1603 cout << _(" Package pin: ");
1604 V = Plcy->GetMatch(Pkg);
1605 if (V.end() == true)
1606 cout << _("(not found)") << endl;
1607 else
1608 cout << V.VerStr() << endl;
1609 }
1610
1611 // Show the priority tables
1612 cout << _(" Version table:") << endl;
1613 for (V = Pkg.VersionList(); V.end() == false; V++)
1614 {
1615 if (Pkg.CurrentVer() == V)
1616 cout << " *** " << V.VerStr();
1617 else
1618 cout << " " << V.VerStr();
1619 cout << " " << Plcy->GetPriority(Pkg) << endl;
1620 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1621 {
1622 // Locate the associated index files so we can derive a description
1623 pkgIndexFile *Indx;
1624 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1625 _system->FindIndex(VF.File(),Indx) == false)
1626 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1627 printf(" %4i %s\n",Plcy->GetPriority(VF.File()),
1628 Indx->Describe(true).c_str());
1629 }
1630 }
1631 }
1632 }
1633
1634 return true;
1635 }
1636 /*}}}*/
1637 // Madison - Look a bit like katie's madison /*{{{*/
1638 // ---------------------------------------------------------------------
1639 /* */
1640 bool Madison(CommandLine &CmdL)
1641 {
1642 pkgCacheFile CacheFile;
1643 pkgSourceList *SrcList = CacheFile.GetSourceList();
1644
1645 if (SrcList == 0)
1646 return false;
1647
1648 // Create the src text record parsers and ignore errors about missing
1649 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1650 pkgSrcRecords SrcRecs(*SrcList);
1651 if (_error->PendingError() == true)
1652 _error->Discard();
1653
1654 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
1655 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
1656 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
1657 {
1658 if (Pkg.end() == false)
1659 {
1660 for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; V++)
1661 {
1662 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1663 {
1664 // This might be nice, but wouldn't uniquely identify the source -mdz
1665 // if (VF.File().Archive() != 0)
1666 // {
1667 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1668 // << VF.File().Archive() << endl;
1669 // }
1670
1671 // Locate the associated index files so we can derive a description
1672 for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); S++)
1673 {
1674 vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
1675 for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
1676 IF != Indexes->end(); IF++)
1677 {
1678 if ((*IF)->FindInCache(*(VF.File().Cache())) == VF.File())
1679 {
1680 cout << setw(10) << Pkg.FullName(true) << " | " << setw(10) << V.VerStr() << " | "
1681 << (*IF)->Describe(true) << endl;
1682 }
1683 }
1684 }
1685 }
1686 }
1687 }
1688
1689
1690 SrcRecs.Restart();
1691 pkgSrcRecords::Parser *SrcParser;
1692 while ((SrcParser = SrcRecs.Find(Pkg.Name(),false)) != 0)
1693 {
1694 // Maybe support Release info here too eventually
1695 cout << setw(10) << SrcParser->Package() << " | "
1696 << setw(10) << SrcParser->Version() << " | "
1697 << SrcParser->Index().Describe(true) << endl;
1698 }
1699 }
1700
1701 return true;
1702 }
1703 /*}}}*/
1704 // GenCaches - Call the main cache generator /*{{{*/
1705 // ---------------------------------------------------------------------
1706 /* */
1707 bool GenCaches(CommandLine &Cmd)
1708 {
1709 OpTextProgress Progress(*_config);
1710
1711 pkgCacheFile CacheFile;
1712 return CacheFile.BuildCaches(&Progress, true);
1713 }
1714 /*}}}*/
1715 // ShowHelp - Show a help screen /*{{{*/
1716 // ---------------------------------------------------------------------
1717 /* */
1718 bool ShowHelp(CommandLine &Cmd)
1719 {
1720 ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION,
1721 COMMON_ARCH,__DATE__,__TIME__);
1722
1723 if (_config->FindB("version") == true)
1724 return true;
1725
1726 cout <<
1727 _("Usage: apt-cache [options] command\n"
1728 " apt-cache [options] add file1 [file2 ...]\n"
1729 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1730 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1731 "\n"
1732 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1733 "cache files, and query information from them\n"
1734 "\n"
1735 "Commands:\n"
1736 " add - Add a package file to the source cache\n"
1737 " gencaches - Build both the package and source cache\n"
1738 " showpkg - Show some general information for a single package\n"
1739 " showsrc - Show source records\n"
1740 " stats - Show some basic statistics\n"
1741 " dump - Show the entire file in a terse form\n"
1742 " dumpavail - Print an available file to stdout\n"
1743 " unmet - Show unmet dependencies\n"
1744 " search - Search the package list for a regex pattern\n"
1745 " show - Show a readable record for the package\n"
1746 " showauto - Display a list of automatically installed packages\n"
1747 " depends - Show raw dependency information for a package\n"
1748 " rdepends - Show reverse dependency information for a package\n"
1749 " pkgnames - List the names of all packages in the system\n"
1750 " dotty - Generate package graphs for GraphViz\n"
1751 " xvcg - Generate package graphs for xvcg\n"
1752 " policy - Show policy settings\n"
1753 "\n"
1754 "Options:\n"
1755 " -h This help text.\n"
1756 " -p=? The package cache.\n"
1757 " -s=? The source cache.\n"
1758 " -q Disable progress indicator.\n"
1759 " -i Show only important deps for the unmet command.\n"
1760 " -c=? Read this configuration file\n"
1761 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1762 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1763 return true;
1764 }
1765 /*}}}*/
1766 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1767 // ---------------------------------------------------------------------
1768 /* */
1769 void CacheInitialize()
1770 {
1771 _config->Set("quiet",0);
1772 _config->Set("help",false);
1773 }
1774 /*}}}*/
1775 int main(int argc,const char *argv[]) /*{{{*/
1776 {
1777 CommandLine::Args Args[] = {
1778 {'h',"help","help",0},
1779 {'v',"version","version",0},
1780 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
1781 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
1782 {'q',"quiet","quiet",CommandLine::IntLevel},
1783 {'i',"important","APT::Cache::Important",0},
1784 {'f',"full","APT::Cache::ShowFull",0},
1785 {'g',"generate","APT::Cache::Generate",0},
1786 {'a',"all-versions","APT::Cache::AllVersions",0},
1787 {'n',"names-only","APT::Cache::NamesOnly",0},
1788 {0,"all-names","APT::Cache::AllNames",0},
1789 {0,"recurse","APT::Cache::RecurseDepends",0},
1790 {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
1791 {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
1792 {'c',"config-file",0,CommandLine::ConfigFile},
1793 {'o',"option",0,CommandLine::ArbItem},
1794 {0,"installed","APT::Cache::Installed",0},
1795 {0,"pre-depends","APT::Cache::ShowPreDepends",0},
1796 {0,"depends","APT::Cache::ShowDepends",0},
1797 {0,"recommends","APT::Cache::ShowRecommends",0},
1798 {0,"suggests","APT::Cache::ShowSuggests",0},
1799 {0,"replaces","APT::Cache::ShowReplaces",0},
1800 {0,"breaks","APT::Cache::ShowBreaks",0},
1801 {0,"conflicts","APT::Cache::ShowConflicts",0},
1802 {0,"enhances","APT::Cache::ShowEnhances",0},
1803 {0,0,0,0}};
1804 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
1805 {"add",&DoAdd},
1806 {"gencaches",&GenCaches},
1807 {"showsrc",&ShowSrcPackage},
1808 {0,0}};
1809 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
1810 {"stats",&Stats},
1811 {"dump",&Dump},
1812 {"dumpavail",&DumpAvail},
1813 {"unmet",&UnMet},
1814 {"search",&Search},
1815 {"depends",&Depends},
1816 {"rdepends",&RDepends},
1817 {"dotty",&Dotty},
1818 {"xvcg",&XVcg},
1819 {"show",&ShowPackage},
1820 {"pkgnames",&ShowPkgNames},
1821 {"showauto",&ShowAuto},
1822 {"policy",&Policy},
1823 {"madison",&Madison},
1824 {0,0}};
1825
1826 CacheInitialize();
1827
1828 // Set up gettext support
1829 setlocale(LC_ALL,"");
1830 textdomain(PACKAGE);
1831
1832 // Parse the command line and initialize the package library
1833 CommandLine CmdL(Args,_config);
1834 if (pkgInitConfig(*_config) == false ||
1835 CmdL.Parse(argc,argv) == false ||
1836 pkgInitSystem(*_config,_system) == false)
1837 {
1838 _error->DumpErrors();
1839 return 100;
1840 }
1841
1842 // See if the help should be shown
1843 if (_config->FindB("help") == true ||
1844 CmdL.FileSize() == 0)
1845 {
1846 ShowHelp(CmdL);
1847 return 0;
1848 }
1849
1850 // Deal with stdout not being a tty
1851 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
1852 _config->Set("quiet","1");
1853
1854 if (_config->Exists("APT::Cache::Generate") == true)
1855 _config->Set("pkgCacheFile::Generate", _config->FindB("APT::Cache::Generate", true));
1856
1857 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
1858 CmdL.DispatchArg(CmdsB);
1859
1860 // Print any errors or warnings found during parsing
1861 bool const Errors = _error->PendingError();
1862 if (_config->FindI("quiet",0) > 0)
1863 _error->DumpErrors();
1864 else
1865 _error->DumpErrors(GlobalError::DEBUG);
1866 return Errors == true ? 100 : 0;
1867 }
1868 /*}}}*/