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