* apt-pkg/cacheset.cc:
[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::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 DidSomething;
584 do
585 {
586 DidSomething = false;
587 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
588 {
589 if (Colours[Pkg->ID] != 1)
590 continue;
591 Colours[Pkg->ID] = 2;
592 DidSomething = true;
593
594 pkgCache::VerIterator Ver = Pkg.VersionList();
595 if (Ver.end() == true)
596 {
597 cout << '<' << Pkg.FullName(true) << '>' << endl;
598 continue;
599 }
600
601 cout << Pkg.FullName(true) << endl;
602
603 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
604 {
605 switch (D->Type) {
606 case pkgCache::Dep::PreDepends: if (!ShowPreDepends) continue; break;
607 case pkgCache::Dep::Depends: if (!ShowDepends) continue; break;
608 case pkgCache::Dep::Recommends: if (!ShowRecommends) continue; break;
609 case pkgCache::Dep::Suggests: if (!ShowSuggests) continue; break;
610 case pkgCache::Dep::Replaces: if (!ShowReplaces) continue; break;
611 case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break;
612 case pkgCache::Dep::DpkgBreaks: if (!ShowBreaks) continue; break;
613 case pkgCache::Dep::Enhances: if (!ShowEnhances) continue; break;
614 }
615
616 pkgCache::PkgIterator Trg = D.TargetPkg();
617
618 if((Installed && Trg->CurrentVer != 0) || !Installed)
619 {
620
621 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
622 cout << " |";
623 else
624 cout << " ";
625
626 // Show the package
627 if (ShowDepType == true)
628 cout << D.DepType() << ": ";
629 if (Trg->VersionList == 0)
630 cout << "<" << Trg.FullName(true) << ">" << endl;
631 else
632 cout << Trg.FullName(true) << endl;
633
634 if (Recurse == true)
635 Colours[D.TargetPkg()->ID]++;
636
637 }
638
639 // Display all solutions
640 SPtrArray<pkgCache::Version *> List = D.AllTargets();
641 pkgPrioSortList(*Cache,List);
642 for (pkgCache::Version **I = List; *I != 0; I++)
643 {
644 pkgCache::VerIterator V(*Cache,*I);
645 if (V != Cache->VerP + V.ParentPkg()->VersionList ||
646 V->ParentPkg == D->Package)
647 continue;
648 cout << " " << V.ParentPkg().FullName(true) << endl;
649
650 if (Recurse == true)
651 Colours[D.ParentPkg()->ID]++;
652 }
653 }
654 }
655 }
656 while (DidSomething == true);
657
658 return true;
659 }
660 /*}}}*/
661 // RDepends - Print out a reverse dependency tree - mbc /*{{{*/
662 // ---------------------------------------------------------------------
663 /* */
664 bool RDepends(CommandLine &CmdL)
665 {
666 pkgCacheFile CacheFile;
667 pkgCache *Cache = CacheFile.GetPkgCache();
668 if (unlikely(Cache == NULL))
669 return false;
670
671 SPtrArray<unsigned> Colours = new unsigned[Cache->Head().PackageCount];
672 memset(Colours,0,sizeof(*Colours)*Cache->Head().PackageCount);
673
674 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
675 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
676 Colours[Pkg->ID] = 1;
677
678 bool const Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
679 bool const Installed = _config->FindB("APT::Cache::Installed",false);
680 bool const Important = _config->FindB("APT::Cache::Important", false);
681 bool const ShowDepType = _config->FindB("APT::Cache::ShowDependencyType",false);
682 bool const ShowPreDepends = _config->FindB("APT::Cache::ShowPre-Depends", true);
683 bool const ShowDepends = _config->FindB("APT::Cache::ShowDepends", true);
684 bool const ShowRecommends = _config->FindB("APT::Cache::ShowRecommends", Important == false);
685 bool const ShowSuggests = _config->FindB("APT::Cache::ShowSuggests", Important == false);
686 bool const ShowReplaces = _config->FindB("APT::Cache::ShowReplaces", Important == false);
687 bool const ShowConflicts = _config->FindB("APT::Cache::ShowConflicts", Important == false);
688 bool const ShowBreaks = _config->FindB("APT::Cache::ShowBreaks", Important == false);
689 bool const ShowEnhances = _config->FindB("APT::Cache::ShowEnhances", Important == false);
690 bool DidSomething;
691 do
692 {
693 DidSomething = false;
694 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
695 {
696 if (Colours[Pkg->ID] != 1)
697 continue;
698 Colours[Pkg->ID] = 2;
699 DidSomething = true;
700
701 pkgCache::VerIterator Ver = Pkg.VersionList();
702 if (Ver.end() == true)
703 {
704 cout << '<' << Pkg.FullName(true) << '>' << endl;
705 continue;
706 }
707
708 cout << Pkg.FullName(true) << endl;
709
710 cout << "Reverse Depends:" << endl;
711 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() == false; D++)
712 {
713 switch (D->Type) {
714 case pkgCache::Dep::PreDepends: if (!ShowPreDepends) continue; break;
715 case pkgCache::Dep::Depends: if (!ShowDepends) continue; break;
716 case pkgCache::Dep::Recommends: if (!ShowRecommends) continue; break;
717 case pkgCache::Dep::Suggests: if (!ShowSuggests) continue; break;
718 case pkgCache::Dep::Replaces: if (!ShowReplaces) continue; break;
719 case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break;
720 case pkgCache::Dep::DpkgBreaks: if (!ShowBreaks) continue; break;
721 case pkgCache::Dep::Enhances: if (!ShowEnhances) continue; break;
722 }
723
724 // Show the package
725 pkgCache::PkgIterator Trg = D.ParentPkg();
726
727 if((Installed && Trg->CurrentVer != 0) || !Installed)
728 {
729
730 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
731 cout << " |";
732 else
733 cout << " ";
734
735 if (ShowDepType == true)
736 cout << D.DepType() << ": ";
737 if (Trg->VersionList == 0)
738 cout << "<" << Trg.FullName(true) << ">" << endl;
739 else
740 cout << Trg.FullName(true) << endl;
741
742 if (Recurse == true)
743 Colours[D.ParentPkg()->ID]++;
744
745 }
746
747 // Display all solutions
748 SPtrArray<pkgCache::Version *> List = D.AllTargets();
749 pkgPrioSortList(*Cache,List);
750 for (pkgCache::Version **I = List; *I != 0; I++)
751 {
752 pkgCache::VerIterator V(*Cache,*I);
753 if (V != Cache->VerP + V.ParentPkg()->VersionList ||
754 V->ParentPkg == D->Package)
755 continue;
756 cout << " " << V.ParentPkg().FullName(true) << endl;
757
758 if (Recurse == true)
759 Colours[D.ParentPkg()->ID]++;
760 }
761 }
762 }
763 }
764 while (DidSomething == true);
765
766 return true;
767 }
768 /*}}}*/
769 // xvcg - Generate a graph for xvcg /*{{{*/
770 // ---------------------------------------------------------------------
771 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
772
773 bool XVcg(CommandLine &CmdL)
774 {
775 pkgCacheFile CacheFile;
776 pkgCache *Cache = CacheFile.GetPkgCache();
777 if (unlikely(Cache == NULL))
778 return false;
779
780 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
781
782 /* Normal packages are boxes
783 Pure Provides are triangles
784 Mixed are diamonds
785 rhomb are missing packages*/
786 const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
787
788 /* Initialize the list of packages to show.
789 1 = To Show
790 2 = To Show no recurse
791 3 = Emitted no recurse
792 4 = Emitted
793 0 = None */
794 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
795 enum TheFlags {ForceNR=(1<<0)};
796 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
797 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
798 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
799
800 // Show everything if no arguments given
801 if (CmdL.FileList[1] == 0)
802 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
803 Show[I] = ToShow;
804 else
805 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
806 Show[I] = None;
807 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
808
809 // Map the shapes
810 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
811 {
812 if (Pkg->VersionList == 0)
813 {
814 // Missing
815 if (Pkg->ProvidesList == 0)
816 ShapeMap[Pkg->ID] = 0;
817 else
818 ShapeMap[Pkg->ID] = 1;
819 }
820 else
821 {
822 // Normal
823 if (Pkg->ProvidesList == 0)
824 ShapeMap[Pkg->ID] = 2;
825 else
826 ShapeMap[Pkg->ID] = 3;
827 }
828 }
829
830 // Load the list of packages from the command line into the show list
831 std::list<APT::PackageSet::Modifier> mods;
832 mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
833 mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
834 std::map<unsigned short, APT::PackageSet> pkgsets =
835 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0);
836
837 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
838 Pkg != pkgsets[0].end(); ++Pkg)
839 Show[Pkg->ID] = ToShow;
840 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
841 Pkg != pkgsets[1].end(); ++Pkg)
842 {
843 Show[Pkg->ID] = ToShow;
844 Flags[Pkg->ID] |= ForceNR;
845 }
846
847 // Little header
848 cout << "graph: { title: \"packages\"" << endl <<
849 "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
850 "layout_downfactor: 8" << endl;
851
852 bool Act = true;
853 while (Act == true)
854 {
855 Act = false;
856 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
857 {
858 // See we need to show this package
859 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
860 continue;
861
862 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
863
864 // Colour as done
865 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
866 {
867 // Pure Provides and missing packages have no deps!
868 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
869 Show[Pkg->ID] = Done;
870 else
871 Show[Pkg->ID] = DoneNR;
872 }
873 else
874 Show[Pkg->ID] = Done;
875 Act = true;
876
877 // No deps to map out
878 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
879 continue;
880
881 pkgCache::VerIterator Ver = Pkg.VersionList();
882 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
883 {
884 // See if anything can meet this dep
885 // Walk along the actual package providing versions
886 bool Hit = false;
887 pkgCache::PkgIterator DPkg = D.TargetPkg();
888 for (pkgCache::VerIterator I = DPkg.VersionList();
889 I.end() == false && Hit == false; I++)
890 {
891 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
892 Hit = true;
893 }
894
895 // Follow all provides
896 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
897 I.end() == false && Hit == false; I++)
898 {
899 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
900 Hit = true;
901 }
902
903
904 // Only graph critical deps
905 if (D.IsCritical() == true)
906 {
907 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.FullName(true).c_str(), D.TargetPkg().FullName(true).c_str() );
908
909 // Colour the node for recursion
910 if (Show[D.TargetPkg()->ID] <= DoneNR)
911 {
912 /* If a conflicts does not meet anything in the database
913 then show the relation but do not recurse */
914 if (Hit == false &&
915 (D->Type == pkgCache::Dep::Conflicts ||
916 D->Type == pkgCache::Dep::DpkgBreaks ||
917 D->Type == pkgCache::Dep::Obsoletes))
918 {
919 if (Show[D.TargetPkg()->ID] == None &&
920 Show[D.TargetPkg()->ID] != ToShow)
921 Show[D.TargetPkg()->ID] = ToShowNR;
922 }
923 else
924 {
925 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
926 Show[D.TargetPkg()->ID] = ToShowNR;
927 else
928 Show[D.TargetPkg()->ID] = ToShow;
929 }
930 }
931
932 // Edge colour
933 switch(D->Type)
934 {
935 case pkgCache::Dep::Conflicts:
936 printf("label: \"conflicts\" color: lightgreen }\n");
937 break;
938 case pkgCache::Dep::DpkgBreaks:
939 printf("label: \"breaks\" color: lightgreen }\n");
940 break;
941 case pkgCache::Dep::Obsoletes:
942 printf("label: \"obsoletes\" color: lightgreen }\n");
943 break;
944
945 case pkgCache::Dep::PreDepends:
946 printf("label: \"predepends\" color: blue }\n");
947 break;
948
949 default:
950 printf("}\n");
951 break;
952 }
953 }
954 }
955 }
956 }
957
958 /* Draw the box colours after the fact since we can not tell what colour
959 they should be until everything is finished drawing */
960 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
961 {
962 if (Show[Pkg->ID] < DoneNR)
963 continue;
964
965 if (Show[Pkg->ID] == DoneNR)
966 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
967 Shapes[ShapeMap[Pkg->ID]]);
968 else
969 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
970 Shapes[ShapeMap[Pkg->ID]]);
971
972 }
973
974 delete[] Show;
975 delete[] Flags;
976 delete[] ShapeMap;
977
978 printf("}\n");
979 return true;
980 }
981 /*}}}*/
982 // Dotty - Generate a graph for Dotty /*{{{*/
983 // ---------------------------------------------------------------------
984 /* Dotty is the graphvis program for generating graphs. It is a fairly
985 simple queuing algorithm that just writes dependencies and nodes.
986 http://www.research.att.com/sw/tools/graphviz/ */
987 bool Dotty(CommandLine &CmdL)
988 {
989 pkgCacheFile CacheFile;
990 pkgCache *Cache = CacheFile.GetPkgCache();
991 if (unlikely(Cache == NULL))
992 return false;
993
994 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
995
996 /* Normal packages are boxes
997 Pure Provides are triangles
998 Mixed are diamonds
999 Hexagons are missing packages*/
1000 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
1001
1002 /* Initialize the list of packages to show.
1003 1 = To Show
1004 2 = To Show no recurse
1005 3 = Emitted no recurse
1006 4 = Emitted
1007 0 = None */
1008 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
1009 enum TheFlags {ForceNR=(1<<0)};
1010 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
1011 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
1012 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
1013
1014 // Show everything if no arguments given
1015 if (CmdL.FileList[1] == 0)
1016 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
1017 Show[I] = ToShow;
1018 else
1019 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
1020 Show[I] = None;
1021 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
1022
1023 // Map the shapes
1024 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
1025 {
1026 if (Pkg->VersionList == 0)
1027 {
1028 // Missing
1029 if (Pkg->ProvidesList == 0)
1030 ShapeMap[Pkg->ID] = 0;
1031 else
1032 ShapeMap[Pkg->ID] = 1;
1033 }
1034 else
1035 {
1036 // Normal
1037 if (Pkg->ProvidesList == 0)
1038 ShapeMap[Pkg->ID] = 2;
1039 else
1040 ShapeMap[Pkg->ID] = 3;
1041 }
1042 }
1043
1044 // Load the list of packages from the command line into the show list
1045 std::list<APT::PackageSet::Modifier> mods;
1046 mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
1047 mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
1048 std::map<unsigned short, APT::PackageSet> pkgsets =
1049 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0);
1050
1051 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
1052 Pkg != pkgsets[0].end(); ++Pkg)
1053 Show[Pkg->ID] = ToShow;
1054 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
1055 Pkg != pkgsets[1].end(); ++Pkg)
1056 {
1057 Show[Pkg->ID] = ToShow;
1058 Flags[Pkg->ID] |= ForceNR;
1059 }
1060
1061 // Little header
1062 printf("digraph packages {\n");
1063 printf("concentrate=true;\n");
1064 printf("size=\"30,40\";\n");
1065
1066 bool Act = true;
1067 while (Act == true)
1068 {
1069 Act = false;
1070 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
1071 {
1072 // See we need to show this package
1073 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
1074 continue;
1075
1076 // Colour as done
1077 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
1078 {
1079 // Pure Provides and missing packages have no deps!
1080 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
1081 Show[Pkg->ID] = Done;
1082 else
1083 Show[Pkg->ID] = DoneNR;
1084 }
1085 else
1086 Show[Pkg->ID] = Done;
1087 Act = true;
1088
1089 // No deps to map out
1090 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
1091 continue;
1092
1093 pkgCache::VerIterator Ver = Pkg.VersionList();
1094 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
1095 {
1096 // See if anything can meet this dep
1097 // Walk along the actual package providing versions
1098 bool Hit = false;
1099 pkgCache::PkgIterator DPkg = D.TargetPkg();
1100 for (pkgCache::VerIterator I = DPkg.VersionList();
1101 I.end() == false && Hit == false; I++)
1102 {
1103 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
1104 Hit = true;
1105 }
1106
1107 // Follow all provides
1108 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
1109 I.end() == false && Hit == false; I++)
1110 {
1111 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
1112 Hit = true;
1113 }
1114
1115 // Only graph critical deps
1116 if (D.IsCritical() == true)
1117 {
1118 printf("\"%s\" -> \"%s\"",Pkg.FullName(true).c_str(),D.TargetPkg().FullName(true).c_str());
1119
1120 // Colour the node for recursion
1121 if (Show[D.TargetPkg()->ID] <= DoneNR)
1122 {
1123 /* If a conflicts does not meet anything in the database
1124 then show the relation but do not recurse */
1125 if (Hit == false &&
1126 (D->Type == pkgCache::Dep::Conflicts ||
1127 D->Type == pkgCache::Dep::Obsoletes))
1128 {
1129 if (Show[D.TargetPkg()->ID] == None &&
1130 Show[D.TargetPkg()->ID] != ToShow)
1131 Show[D.TargetPkg()->ID] = ToShowNR;
1132 }
1133 else
1134 {
1135 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
1136 Show[D.TargetPkg()->ID] = ToShowNR;
1137 else
1138 Show[D.TargetPkg()->ID] = ToShow;
1139 }
1140 }
1141
1142 // Edge colour
1143 switch(D->Type)
1144 {
1145 case pkgCache::Dep::Conflicts:
1146 case pkgCache::Dep::Obsoletes:
1147 printf("[color=springgreen];\n");
1148 break;
1149
1150 case pkgCache::Dep::PreDepends:
1151 printf("[color=blue];\n");
1152 break;
1153
1154 default:
1155 printf(";\n");
1156 break;
1157 }
1158 }
1159 }
1160 }
1161 }
1162
1163 /* Draw the box colours after the fact since we can not tell what colour
1164 they should be until everything is finished drawing */
1165 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
1166 {
1167 if (Show[Pkg->ID] < DoneNR)
1168 continue;
1169
1170 // Orange box for early recursion stoppage
1171 if (Show[Pkg->ID] == DoneNR)
1172 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.FullName(true).c_str(),
1173 Shapes[ShapeMap[Pkg->ID]]);
1174 else
1175 printf("\"%s\" [shape=%s];\n",Pkg.FullName(true).c_str(),
1176 Shapes[ShapeMap[Pkg->ID]]);
1177 }
1178
1179 printf("}\n");
1180 return true;
1181 }
1182 /*}}}*/
1183 // DoAdd - Perform an adding operation /*{{{*/
1184 // ---------------------------------------------------------------------
1185 /* */
1186 bool DoAdd(CommandLine &CmdL)
1187 {
1188 return _error->Error("Unimplemented");
1189 #if 0
1190 // Make sure there is at least one argument
1191 if (CmdL.FileSize() <= 1)
1192 return _error->Error("You must give at least one file name");
1193
1194 // Open the cache
1195 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
1196 if (_error->PendingError() == true)
1197 return false;
1198
1199 DynamicMMap Map(CacheF,MMap::Public);
1200 if (_error->PendingError() == true)
1201 return false;
1202
1203 OpTextProgress Progress(*_config);
1204 pkgCacheGenerator Gen(Map,Progress);
1205 if (_error->PendingError() == true)
1206 return false;
1207
1208 unsigned long Length = CmdL.FileSize() - 1;
1209 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1210 {
1211 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
1212 Progress.SubProgress(Length);
1213
1214 // Do the merge
1215 FileFd TagF(*I,FileFd::ReadOnly);
1216 debListParser Parser(TagF);
1217 if (_error->PendingError() == true)
1218 return _error->Error("Problem opening %s",*I);
1219
1220 if (Gen.SelectFile(*I,"") == false)
1221 return _error->Error("Problem with SelectFile");
1222
1223 if (Gen.MergeList(Parser) == false)
1224 return _error->Error("Problem with MergeList");
1225 }
1226
1227 Progress.Done();
1228 GCache = &Gen.GetCache();
1229 Stats(CmdL);
1230
1231 return true;
1232 #endif
1233 }
1234 /*}}}*/
1235 // DisplayRecord - Displays the complete record for the package /*{{{*/
1236 // ---------------------------------------------------------------------
1237 /* This displays the package record from the proper package index file.
1238 It is not used by DumpAvail for performance reasons. */
1239 bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
1240 {
1241 pkgCache *Cache = CacheFile.GetPkgCache();
1242 if (unlikely(Cache == NULL))
1243 return false;
1244
1245 // Find an appropriate file
1246 pkgCache::VerFileIterator Vf = V.FileList();
1247 for (; Vf.end() == false; Vf++)
1248 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
1249 break;
1250 if (Vf.end() == true)
1251 Vf = V.FileList();
1252
1253 // Check and load the package list file
1254 pkgCache::PkgFileIterator I = Vf.File();
1255 if (I.IsOk() == false)
1256 return _error->Error(_("Package file %s is out of sync."),I.FileName());
1257
1258 FileFd PkgF;
1259 if (PkgF.Open(I.FileName(), FileFd::ReadOnlyGzip) == false)
1260 return false;
1261
1262 // Read the record
1263 unsigned char *Buffer = new unsigned char[Cache->HeaderP->MaxVerFileSize+1];
1264 Buffer[V.FileList()->Size] = '\n';
1265 if (PkgF.Seek(V.FileList()->Offset) == false ||
1266 PkgF.Read(Buffer,V.FileList()->Size) == false)
1267 {
1268 delete [] Buffer;
1269 return false;
1270 }
1271
1272 // Get a pointer to start of Description field
1273 const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "Description:");
1274
1275 // Write all but Description
1276 if (fwrite(Buffer,1,DescP - Buffer,stdout) < (size_t)(DescP - Buffer))
1277 {
1278 delete [] Buffer;
1279 return false;
1280 }
1281
1282 // Show the right description
1283 pkgRecords Recs(*Cache);
1284 pkgCache::DescIterator Desc = V.TranslatedDescription();
1285 pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
1286 cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
1287
1288 // Find the first field after the description (if there is any)
1289 for(DescP++;DescP != &Buffer[V.FileList()->Size];DescP++)
1290 {
1291 if(*DescP == '\n' && *(DescP+1) != ' ')
1292 {
1293 // write the rest of the buffer
1294 const unsigned char *end=&Buffer[V.FileList()->Size];
1295 if (fwrite(DescP,1,end-DescP,stdout) < (size_t)(end-DescP))
1296 {
1297 delete [] Buffer;
1298 return false;
1299 }
1300
1301 break;
1302 }
1303 }
1304 // write a final newline (after the description)
1305 cout<<endl;
1306 delete [] Buffer;
1307
1308 return true;
1309 }
1310 /*}}}*/
1311
1312 struct ExDescFile
1313 {
1314 pkgCache::DescFile *Df;
1315 bool NameMatch;
1316 };
1317
1318 // Search - Perform a search /*{{{*/
1319 // ---------------------------------------------------------------------
1320 /* This searches the package names and package descriptions for a pattern */
1321 bool Search(CommandLine &CmdL)
1322 {
1323 bool const ShowFull = _config->FindB("APT::Cache::ShowFull",false);
1324 bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
1325 unsigned int const NumPatterns = CmdL.FileSize() -1;
1326
1327 pkgCacheFile CacheFile;
1328 pkgCache *Cache = CacheFile.GetPkgCache();
1329 pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
1330 if (unlikely(Cache == NULL || Plcy == NULL))
1331 return false;
1332
1333 // Make sure there is at least one argument
1334 if (NumPatterns < 1)
1335 return _error->Error(_("You must give at least one search pattern"));
1336
1337 // Compile the regex pattern
1338 regex_t *Patterns = new regex_t[NumPatterns];
1339 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
1340 for (unsigned I = 0; I != NumPatterns; I++)
1341 {
1342 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
1343 REG_NOSUB) != 0)
1344 {
1345 for (; I != 0; I--)
1346 regfree(&Patterns[I]);
1347 return _error->Error("Regex compilation error");
1348 }
1349 }
1350
1351 if (_error->PendingError() == true)
1352 {
1353 for (unsigned I = 0; I != NumPatterns; I++)
1354 regfree(&Patterns[I]);
1355 return false;
1356 }
1357
1358 ExDescFile *DFList = new ExDescFile[Cache->HeaderP->GroupCount+1];
1359 memset(DFList,0,sizeof(*DFList)*Cache->HeaderP->GroupCount+1);
1360
1361 // Map versions that we want to write out onto the VerList array.
1362 for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
1363 {
1364 if (DFList[G->ID].NameMatch == true)
1365 continue;
1366
1367 DFList[G->ID].NameMatch = true;
1368 for (unsigned I = 0; I != NumPatterns; I++)
1369 {
1370 if (regexec(&Patterns[I],G.Name(),0,0,0) == 0)
1371 continue;
1372 DFList[G->ID].NameMatch = false;
1373 break;
1374 }
1375
1376 // Doing names only, drop any that dont match..
1377 if (NamesOnly == true && DFList[G->ID].NameMatch == false)
1378 continue;
1379
1380 // Find the proper version to use
1381 pkgCache::PkgIterator P = G.FindPreferredPkg();
1382 if (P.end() == true)
1383 continue;
1384 pkgCache::VerIterator V = Plcy->GetCandidateVer(P);
1385 if (V.end() == false)
1386 DFList[G->ID].Df = V.DescriptionList().FileList();
1387
1388 if (DFList[G->ID].NameMatch == false)
1389 continue;
1390
1391 // Include all the packages that provide matching names too
1392 for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
1393 {
1394 pkgCache::VerIterator V = Plcy->GetCandidateVer(Prv.OwnerPkg());
1395 if (V.end() == true)
1396 continue;
1397
1398 unsigned long id = Prv.OwnerPkg().Group()->ID;
1399 DFList[id].Df = V.DescriptionList().FileList();
1400 DFList[id].NameMatch = true;
1401 }
1402 }
1403
1404 LocalitySort(&DFList->Df,Cache->HeaderP->GroupCount,sizeof(*DFList));
1405
1406 // Create the text record parser
1407 pkgRecords Recs(*Cache);
1408 // Iterate over all the version records and check them
1409 for (ExDescFile *J = DFList; J->Df != 0; J++)
1410 {
1411 pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(*Cache,J->Df));
1412
1413 if (J->NameMatch == false && NamesOnly == false)
1414 {
1415 string const LongDesc = P.LongDesc();
1416 J->NameMatch = true;
1417 for (unsigned I = 0; I != NumPatterns; I++)
1418 {
1419 if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
1420 continue;
1421 J->NameMatch = false;
1422 break;
1423 }
1424 }
1425
1426 if (J->NameMatch == true)
1427 {
1428 if (ShowFull == true)
1429 {
1430 const char *Start;
1431 const char *End;
1432 P.GetRec(Start,End);
1433 fwrite(Start,End-Start,1,stdout);
1434 putc('\n',stdout);
1435 }
1436 else
1437 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
1438 }
1439 }
1440
1441 delete [] DFList;
1442 for (unsigned I = 0; I != NumPatterns; I++)
1443 regfree(&Patterns[I]);
1444 if (ferror(stdout))
1445 return _error->Error("Write to stdout failed");
1446 return true;
1447 }
1448
1449
1450 /* show automatically installed packages (sorted) */
1451 bool ShowAuto(CommandLine &CmdL)
1452 {
1453 pkgCacheFile CacheFile;
1454 pkgCache *Cache = CacheFile.GetPkgCache();
1455 pkgDepCache *DepCache = CacheFile.GetDepCache();
1456 if (unlikely(Cache == NULL || DepCache == NULL))
1457 return false;
1458
1459 std::vector<string> packages;
1460 packages.reserve(Cache->HeaderP->PackageCount / 3);
1461
1462 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
1463 if ((*DepCache)[P].Flags & pkgCache::Flag::Auto)
1464 packages.push_back(P.Name());
1465
1466 std::sort(packages.begin(), packages.end());
1467
1468 for (vector<string>::iterator I = packages.begin(); I != packages.end(); I++)
1469 cout << *I << "\n";
1470
1471 return true;
1472 }
1473 /*}}}*/
1474 // ShowPackage - Dump the package record to the screen /*{{{*/
1475 // ---------------------------------------------------------------------
1476 /* */
1477 bool ShowPackage(CommandLine &CmdL)
1478 {
1479 pkgCacheFile CacheFile;
1480 APT::VersionSet::Version const select = _config->FindB("APT::Cache::AllVersions", true) ?
1481 APT::VersionSet::ALL : APT::VersionSet::CANDIDATE;
1482 APT::VersionSet const verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1, select);
1483 for (APT::VersionSet::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver)
1484 if (DisplayRecord(CacheFile, Ver) == false)
1485 return false;
1486
1487 if (verset.empty() == false)
1488 return true;
1489 return _error->Error(_("No packages found"));
1490 }
1491 /*}}}*/
1492 // ShowPkgNames - Show package names /*{{{*/
1493 // ---------------------------------------------------------------------
1494 /* This does a prefix match on the first argument */
1495 bool ShowPkgNames(CommandLine &CmdL)
1496 {
1497 pkgCacheFile CacheFile;
1498 if (unlikely(CacheFile.BuildCaches(NULL, false) == false))
1499 return false;
1500 pkgCache::GrpIterator I = CacheFile.GetPkgCache()->GrpBegin();
1501 bool const All = _config->FindB("APT::Cache::AllNames","false");
1502
1503 if (CmdL.FileList[1] != 0)
1504 {
1505 for (;I.end() != true; I++)
1506 {
1507 if (All == false && I->FirstPackage == 0)
1508 continue;
1509 if (I.FindPkg("any")->VersionList == 0)
1510 continue;
1511 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1512 cout << I.Name() << endl;
1513 }
1514
1515 return true;
1516 }
1517
1518 // Show all pkgs
1519 for (;I.end() != true; I++)
1520 {
1521 if (All == false && I->FirstPackage == 0)
1522 continue;
1523 if (I.FindPkg("any")->VersionList == 0)
1524 continue;
1525 cout << I.Name() << endl;
1526 }
1527
1528 return true;
1529 }
1530 /*}}}*/
1531 // ShowSrcPackage - Show source package records /*{{{*/
1532 // ---------------------------------------------------------------------
1533 /* */
1534 bool ShowSrcPackage(CommandLine &CmdL)
1535 {
1536 pkgCacheFile CacheFile;
1537 pkgSourceList *List = CacheFile.GetSourceList();
1538 if (unlikely(List == NULL))
1539 return false;
1540
1541 // Create the text record parsers
1542 pkgSrcRecords SrcRecs(*List);
1543 if (_error->PendingError() == true)
1544 return false;
1545
1546 unsigned found = 0;
1547 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1548 {
1549 SrcRecs.Restart();
1550
1551 pkgSrcRecords::Parser *Parse;
1552 unsigned found_this = 0;
1553 while ((Parse = SrcRecs.Find(*I,false)) != 0) {
1554 cout << Parse->AsStr() << endl;;
1555 found++;
1556 found_this++;
1557 }
1558 if (found_this == 0) {
1559 _error->Warning(_("Unable to locate package %s"),*I);
1560 continue;
1561 }
1562 }
1563 if (found > 0)
1564 return true;
1565 return _error->Error(_("No packages found"));
1566 }
1567 /*}}}*/
1568 // Policy - Show the results of the preferences file /*{{{*/
1569 // ---------------------------------------------------------------------
1570 /* */
1571 bool Policy(CommandLine &CmdL)
1572 {
1573 pkgCacheFile CacheFile;
1574 pkgCache *Cache = CacheFile.GetPkgCache();
1575 pkgPolicy *Plcy = CacheFile.GetPolicy();
1576 pkgSourceList *SrcList = CacheFile.GetSourceList();
1577 if (unlikely(Cache == NULL || Plcy == NULL || SrcList == NULL))
1578 return false;
1579
1580 /* Should the MultiArchKiller be run to see which pseudo packages for an
1581 arch all package are currently installed? Activating it gives a speed
1582 penality for no real gain beside enhanced debugging, so in general no. */
1583 if (_config->FindB("APT::Cache::Policy::DepCache", false) == true)
1584 CacheFile.GetDepCache();
1585
1586 // Print out all of the package files
1587 if (CmdL.FileList[1] == 0)
1588 {
1589 cout << _("Package files:") << endl;
1590 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; F++)
1591 {
1592 // Locate the associated index files so we can derive a description
1593 pkgIndexFile *Indx;
1594 if (SrcList->FindIndex(F,Indx) == false &&
1595 _system->FindIndex(F,Indx) == false)
1596 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1597
1598 printf("%4i %s\n",
1599 Plcy->GetPriority(F),Indx->Describe(true).c_str());
1600
1601 // Print the reference information for the package
1602 string Str = F.RelStr();
1603 if (Str.empty() == false)
1604 printf(" release %s\n",F.RelStr().c_str());
1605 if (F.Site() != 0 && F.Site()[0] != 0)
1606 printf(" origin %s\n",F.Site());
1607 }
1608
1609 // Show any packages have explicit pins
1610 cout << _("Pinned packages:") << endl;
1611 pkgCache::PkgIterator I = Cache->PkgBegin();
1612 for (;I.end() != true; I++)
1613 {
1614 if (Plcy->GetPriority(I) == 0)
1615 continue;
1616
1617 // Print the package name and the version we are forcing to
1618 cout << " " << I.FullName(true) << " -> ";
1619
1620 pkgCache::VerIterator V = Plcy->GetMatch(I);
1621 if (V.end() == true)
1622 cout << _("(not found)") << endl;
1623 else
1624 cout << V.VerStr() << endl;
1625 }
1626
1627 return true;
1628 }
1629
1630 string const myArch = _config->Find("APT::Architecture");
1631 char const * const msgInstalled = _(" Installed: ");
1632 char const * const msgCandidate = _(" Candidate: ");
1633 short const InstalledLessCandidate =
1634 mbstowcs(NULL, msgInstalled, 0) - mbstowcs(NULL, msgCandidate, 0);
1635 short const deepInstalled =
1636 (InstalledLessCandidate < 0 ? (InstalledLessCandidate*-1) : 0) - 1;
1637 short const deepCandidate =
1638 (InstalledLessCandidate > 0 ? (InstalledLessCandidate) : 0) - 1;
1639
1640 // Print out detailed information for each package
1641 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
1642 for (APT::PackageSet::const_iterator I = pkgset.begin(); I != pkgset.end(); ++I)
1643 {
1644 pkgCache::PkgIterator Pkg = I.Group().FindPkg("any");
1645
1646 for (; Pkg.end() != true; Pkg = I.Group().NextPkg(Pkg)) {
1647 if (strcmp(Pkg.Arch(),"all") == 0)
1648 continue;
1649
1650 cout << Pkg.FullName(true) << ":" << endl;
1651
1652 // Installed version
1653 cout << msgInstalled << OutputInDepth(deepInstalled, " ");
1654 if (Pkg->CurrentVer == 0)
1655 cout << _("(none)") << endl;
1656 else
1657 cout << Pkg.CurrentVer().VerStr() << endl;
1658
1659 // Candidate Version
1660 cout << msgCandidate << OutputInDepth(deepCandidate, " ");
1661 pkgCache::VerIterator V = Plcy->GetCandidateVer(Pkg);
1662 if (V.end() == true)
1663 cout << _("(none)") << endl;
1664 else
1665 cout << V.VerStr() << endl;
1666
1667 // Pinned version
1668 if (Plcy->GetPriority(Pkg) != 0)
1669 {
1670 cout << _(" Package pin: ");
1671 V = Plcy->GetMatch(Pkg);
1672 if (V.end() == true)
1673 cout << _("(not found)") << endl;
1674 else
1675 cout << V.VerStr() << endl;
1676 }
1677
1678 // Show the priority tables
1679 cout << _(" Version table:") << endl;
1680 for (V = Pkg.VersionList(); V.end() == false; V++)
1681 {
1682 if (Pkg.CurrentVer() == V)
1683 cout << " *** " << V.VerStr();
1684 else
1685 cout << " " << V.VerStr();
1686 cout << " " << Plcy->GetPriority(Pkg) << endl;
1687 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1688 {
1689 // Locate the associated index files so we can derive a description
1690 pkgIndexFile *Indx;
1691 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1692 _system->FindIndex(VF.File(),Indx) == false)
1693 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1694 printf(" %4i %s\n",Plcy->GetPriority(VF.File()),
1695 Indx->Describe(true).c_str());
1696 }
1697 }
1698 }
1699 }
1700
1701 return true;
1702 }
1703 /*}}}*/
1704 // Madison - Look a bit like katie's madison /*{{{*/
1705 // ---------------------------------------------------------------------
1706 /* */
1707 bool Madison(CommandLine &CmdL)
1708 {
1709 pkgCacheFile CacheFile;
1710 pkgSourceList *SrcList = CacheFile.GetSourceList();
1711
1712 if (SrcList == 0)
1713 return false;
1714
1715 // Create the src text record parsers and ignore errors about missing
1716 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1717 pkgSrcRecords SrcRecs(*SrcList);
1718 if (_error->PendingError() == true)
1719 _error->Discard();
1720
1721 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
1722 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
1723 {
1724 if (Pkg.end() == false)
1725 {
1726 for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; V++)
1727 {
1728 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1729 {
1730 // This might be nice, but wouldn't uniquely identify the source -mdz
1731 // if (VF.File().Archive() != 0)
1732 // {
1733 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1734 // << VF.File().Archive() << endl;
1735 // }
1736
1737 // Locate the associated index files so we can derive a description
1738 for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); S++)
1739 {
1740 vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
1741 for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
1742 IF != Indexes->end(); IF++)
1743 {
1744 if ((*IF)->FindInCache(*(VF.File().Cache())) == VF.File())
1745 {
1746 cout << setw(10) << Pkg.FullName(true) << " | " << setw(10) << V.VerStr() << " | "
1747 << (*IF)->Describe(true) << endl;
1748 }
1749 }
1750 }
1751 }
1752 }
1753 }
1754
1755
1756 SrcRecs.Restart();
1757 pkgSrcRecords::Parser *SrcParser;
1758 while ((SrcParser = SrcRecs.Find(Pkg.Name(),false)) != 0)
1759 {
1760 // Maybe support Release info here too eventually
1761 cout << setw(10) << SrcParser->Package() << " | "
1762 << setw(10) << SrcParser->Version() << " | "
1763 << SrcParser->Index().Describe(true) << endl;
1764 }
1765 }
1766
1767 return true;
1768 }
1769 /*}}}*/
1770 // GenCaches - Call the main cache generator /*{{{*/
1771 // ---------------------------------------------------------------------
1772 /* */
1773 bool GenCaches(CommandLine &Cmd)
1774 {
1775 OpTextProgress Progress(*_config);
1776
1777 pkgCacheFile CacheFile;
1778 return CacheFile.BuildCaches(&Progress, true);
1779 }
1780 /*}}}*/
1781 // ShowHelp - Show a help screen /*{{{*/
1782 // ---------------------------------------------------------------------
1783 /* */
1784 bool ShowHelp(CommandLine &Cmd)
1785 {
1786 ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION,
1787 COMMON_ARCH,__DATE__,__TIME__);
1788
1789 if (_config->FindB("version") == true)
1790 return true;
1791
1792 cout <<
1793 _("Usage: apt-cache [options] command\n"
1794 " apt-cache [options] add file1 [file2 ...]\n"
1795 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1796 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1797 "\n"
1798 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1799 "cache files, and query information from them\n"
1800 "\n"
1801 "Commands:\n"
1802 " add - Add a package file to the source cache\n"
1803 " gencaches - Build both the package and source cache\n"
1804 " showpkg - Show some general information for a single package\n"
1805 " showsrc - Show source records\n"
1806 " stats - Show some basic statistics\n"
1807 " dump - Show the entire file in a terse form\n"
1808 " dumpavail - Print an available file to stdout\n"
1809 " unmet - Show unmet dependencies\n"
1810 " search - Search the package list for a regex pattern\n"
1811 " show - Show a readable record for the package\n"
1812 " showauto - Display a list of automatically installed packages\n"
1813 " depends - Show raw dependency information for a package\n"
1814 " rdepends - Show reverse dependency information for a package\n"
1815 " pkgnames - List the names of all packages in the system\n"
1816 " dotty - Generate package graphs for GraphViz\n"
1817 " xvcg - Generate package graphs for xvcg\n"
1818 " policy - Show policy settings\n"
1819 "\n"
1820 "Options:\n"
1821 " -h This help text.\n"
1822 " -p=? The package cache.\n"
1823 " -s=? The source cache.\n"
1824 " -q Disable progress indicator.\n"
1825 " -i Show only important deps for the unmet command.\n"
1826 " -c=? Read this configuration file\n"
1827 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1828 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1829 return true;
1830 }
1831 /*}}}*/
1832 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1833 // ---------------------------------------------------------------------
1834 /* */
1835 void CacheInitialize()
1836 {
1837 _config->Set("quiet",0);
1838 _config->Set("help",false);
1839 }
1840 /*}}}*/
1841 int main(int argc,const char *argv[]) /*{{{*/
1842 {
1843 CommandLine::Args Args[] = {
1844 {'h',"help","help",0},
1845 {'v',"version","version",0},
1846 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
1847 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
1848 {'q',"quiet","quiet",CommandLine::IntLevel},
1849 {'i',"important","APT::Cache::Important",0},
1850 {'f',"full","APT::Cache::ShowFull",0},
1851 {'g',"generate","APT::Cache::Generate",0},
1852 {'a',"all-versions","APT::Cache::AllVersions",0},
1853 {'n',"names-only","APT::Cache::NamesOnly",0},
1854 {0,"all-names","APT::Cache::AllNames",0},
1855 {0,"recurse","APT::Cache::RecurseDepends",0},
1856 {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
1857 {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
1858 {'c',"config-file",0,CommandLine::ConfigFile},
1859 {'o',"option",0,CommandLine::ArbItem},
1860 {0,"installed","APT::Cache::Installed",0},
1861 {0,"pre-depends","APT::Cache::ShowPreDepends",0},
1862 {0,"depends","APT::Cache::ShowDepends",0},
1863 {0,"recommends","APT::Cache::ShowRecommends",0},
1864 {0,"suggests","APT::Cache::ShowSuggests",0},
1865 {0,"replaces","APT::Cache::ShowReplaces",0},
1866 {0,"breaks","APT::Cache::ShowBreaks",0},
1867 {0,"conflicts","APT::Cache::ShowConflicts",0},
1868 {0,"enhances","APT::Cache::ShowEnhances",0},
1869 {0,0,0,0}};
1870 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
1871 {"add",&DoAdd},
1872 {"gencaches",&GenCaches},
1873 {"showsrc",&ShowSrcPackage},
1874 {0,0}};
1875 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
1876 {"stats",&Stats},
1877 {"dump",&Dump},
1878 {"dumpavail",&DumpAvail},
1879 {"unmet",&UnMet},
1880 {"search",&Search},
1881 {"depends",&Depends},
1882 {"rdepends",&RDepends},
1883 {"dotty",&Dotty},
1884 {"xvcg",&XVcg},
1885 {"show",&ShowPackage},
1886 {"pkgnames",&ShowPkgNames},
1887 {"showauto",&ShowAuto},
1888 {"policy",&Policy},
1889 {"madison",&Madison},
1890 {0,0}};
1891
1892 CacheInitialize();
1893
1894 // Set up gettext support
1895 setlocale(LC_ALL,"");
1896 textdomain(PACKAGE);
1897
1898 // Parse the command line and initialize the package library
1899 CommandLine CmdL(Args,_config);
1900 if (pkgInitConfig(*_config) == false ||
1901 CmdL.Parse(argc,argv) == false ||
1902 pkgInitSystem(*_config,_system) == false)
1903 {
1904 _error->DumpErrors();
1905 return 100;
1906 }
1907
1908 // See if the help should be shown
1909 if (_config->FindB("help") == true ||
1910 CmdL.FileSize() == 0)
1911 {
1912 ShowHelp(CmdL);
1913 return 0;
1914 }
1915
1916 // Deal with stdout not being a tty
1917 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
1918 _config->Set("quiet","1");
1919
1920 if (_config->Exists("APT::Cache::Generate") == true)
1921 _config->Set("pkgCacheFile::Generate", _config->FindB("APT::Cache::Generate", true));
1922
1923 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
1924 CmdL.DispatchArg(CmdsB);
1925
1926 // Print any errors or warnings found during parsing
1927 bool const Errors = _error->PendingError();
1928 if (_config->FindI("quiet",0) > 0)
1929 _error->DumpErrors();
1930 else
1931 _error->DumpErrors(GlobalError::DEBUG);
1932 return Errors == true ? 100 : 0;
1933 }
1934 /*}}}*/