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