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