- move common code in apt-cache/shell to cmdline
[apt.git] / cmdline / apt-cache.cc
index abd2350..e7952cc 100644 (file)
@@ -43,6 +43,7 @@
 // CNC:2003-11-23
 #include <apt-pkg/luaiface.h>
     
+#include "cmdline.h"
                                                                        /*}}}*/
 
 using namespace std;
@@ -50,32 +51,6 @@ using namespace std;
 pkgCache *GCache = 0;
 pkgSourceList *SrcList = 0;
 
-// LocalitySort - Sort a version list by package file locality         /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-int LocalityCompare(const void *a, const void *b)
-{
-   pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
-   pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
-   
-   if (A == 0 && B == 0)
-      return 0;
-   if (A == 0)
-      return 1;
-   if (B == 0)
-      return -1;
-   
-   if (A->File == B->File)
-      return A->Offset - B->Offset;
-   return A->File - B->File;
-}
-
-void LocalitySort(pkgCache::VerFile **begin,
-                 unsigned long Count,size_t Size)
-{   
-   qsort(begin,Count,Size,LocalityCompare);
-}
-                                                                       /*}}}*/
 // CNC:2003-11-23
 // Script - Scripting stuff.                                           /*{{{*/
 // ---------------------------------------------------------------------
@@ -99,88 +74,7 @@ bool Script(CommandLine &CmdL)
 /* */
 bool UnMet(CommandLine &CmdL)
 {
-   pkgCache &Cache = *GCache;
-   bool Important = _config->FindB("APT::Cache::Important",false);
-   
-   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
-   {
-      for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
-      {
-        bool Header = false;
-        for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
-        {
-           // Collect or groups
-           pkgCache::DepIterator Start;
-           pkgCache::DepIterator End;
-           D.GlobOr(Start,End);
-           
-           // Skip conflicts and replaces
-           if (End->Type != pkgCache::Dep::PreDepends &&
-               End->Type != pkgCache::Dep::Depends && 
-               End->Type != pkgCache::Dep::Suggests &&
-               End->Type != pkgCache::Dep::Recommends)
-              continue;
-
-           // Important deps only
-           if (Important == true)
-              if (End->Type != pkgCache::Dep::PreDepends &&
-                  End->Type != pkgCache::Dep::Depends)
-                 continue;
-           
-           // Verify the or group
-           bool OK = false;
-           pkgCache::DepIterator RealStart = Start;
-           do
-           {
-              // See if this dep is Ok
-              pkgCache::Version **VList = Start.AllTargets();
-              if (*VList != 0)
-              {
-                 OK = true;
-                 delete [] VList;
-                 break;
-              }
-              delete [] VList;
-              
-              if (Start == End)
-                 break;
-              Start++;
-           }
-           while (1);
-
-           // The group is OK
-           if (OK == true)
-              continue;
-           
-           // Oops, it failed..
-           if (Header == false)
-              ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
-                       P.Name(),V.VerStr());
-           Header = true;
-           
-           // Print out the dep type
-           cout << " " << End.DepType() << ": ";
-
-           // Show the group
-           Start = RealStart;
-           do
-           {
-              cout << Start.TargetPkg().Name();
-              if (Start.TargetVer() != 0)
-                 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
-                 ")";
-              if (Start == End)
-                 break;
-              cout << " | ";
-              Start++;
-           }
-           while (1);
-           
-           cout << endl;
-        }       
-      }
-   }   
-   return true;
+   return cmdUnMet(CmdL, *GCache);
 }
                                                                        /*}}}*/
 // DumpPackage - Show a dump of a package record                       /*{{{*/
@@ -188,61 +82,7 @@ bool UnMet(CommandLine &CmdL)
 /* */
 bool DumpPackage(CommandLine &CmdL)
 {   
-   pkgCache &Cache = *GCache;
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-   {
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
-      if (Pkg.end() == true)
-      {
-        _error->Warning(_("Unable to locate package %s"),*I);
-        continue;
-      }
-
-      cout << "Package: " << Pkg.Name() << endl;
-      cout << "Versions: " << endl;
-      for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
-      {
-        cout << Cur.VerStr() << "." << Cur.Arch();
-        for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
-           cout << "(" << Vf.File().FileName() << ")";
-        cout << endl;
-      }
-      
-      cout << endl;
-      
-      cout << "Reverse Depends: " << endl;
-      for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
-      {
-        cout << "  " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name();
-        if (D->Version != 0)
-           cout << ' ' << DeNull(D.TargetVer()) << endl;
-        else
-           cout << endl;
-      }
-      
-      cout << "Dependencies: " << endl;
-      for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
-      {
-        cout << Cur.VerStr() << " - ";
-        for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
-           cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
-        cout << endl;
-      }      
-
-      cout << "Provides: " << endl;
-      for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
-      {
-        cout << Cur.VerStr() << " - ";
-        for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
-           cout << Prv.ParentPkg().Name() << " ";
-        cout << endl;
-      }
-      cout << "Reverse Provides: " << endl;
-      for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
-        cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr() << endl;            
-   }
-
-   return true;
+   return cmdDumpPackage(CmdL, *GCache);
 }
                                                                        /*}}}*/
 // Stats - Dump some nice statistics                                   /*{{{*/
@@ -547,399 +387,25 @@ bool DumpAvail(CommandLine &Cmd)
    return !_error->PendingError();
 }
                                                                        /*}}}*/
-// Depends - Print out a dependency tree                               /*{{{*/
-// ---------------------------------------------------------------------
-/* */
 bool Depends(CommandLine &CmdL)
 {
-   pkgCache &Cache = *GCache;
-   SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
-   memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
-   
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-   {
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
-      if (Pkg.end() == true)
-      {
-        _error->Warning(_("Unable to locate package %s"),*I);
-        continue;
-      }
-      Colours[Pkg->ID] = 1;
-   }
-   
-   bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
-   bool Installed = _config->FindB("APT::Cache::Installed",false);
-   bool DidSomething;
-   do
-   {
-      DidSomething = false;
-      for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
-      {
-        if (Colours[Pkg->ID] != 1)
-           continue;
-        Colours[Pkg->ID] = 2;
-        DidSomething = true;
-        
-        pkgCache::VerIterator Ver = Pkg.VersionList();
-        if (Ver.end() == true)
-        {
-           cout << '<' << Pkg.Name() << '>' << endl;
-           continue;
-        }
-        
-        // CNC:2003-03-03
-        cout << Pkg.Name() << "-" << Ver.VerStr() << endl;
-        
-        for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
-        {
-
-           pkgCache::PkgIterator Trg = D.TargetPkg();
-
-           if((Installed && Trg->CurrentVer != 0) || !Installed)
-             {
-
-               if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
-                 cout << " |";
-               else
-                 cout << "  ";
-           
-               // Show the package
-               if (Trg->VersionList == 0)
-                  cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
-               // CNC:2003-03-03
-               else if (D.TargetVer() == 0)
-                  cout << D.DepType() << ": " << Trg.Name() << endl;
-               else
-                  cout << D.DepType() << ": " << Trg.Name()
-                       << " " << D.CompType() << " " << D.TargetVer() << endl;
-           
-               if (Recurse == true)
-                 Colours[D.TargetPkg()->ID]++;
-
-             }
-           
-           // Display all solutions
-           SPtrArray<pkgCache::Version *> List = D.AllTargets();
-           pkgPrioSortList(Cache,List);
-           for (pkgCache::Version **I = List; *I != 0; I++)
-           {
-              pkgCache::VerIterator V(Cache,*I);
-              if (V != Cache.VerP + V.ParentPkg()->VersionList ||
-                  V->ParentPkg == D->Package)
-                 continue;
-              // CNC:2003-03-03
-              cout << "    " << V.ParentPkg().Name()
-                   << "-" << V.VerStr() << endl;
-              
-              if (Recurse == true)
-                 Colours[D.ParentPkg()->ID]++;
-           }
-        }
-      }      
-   }   
-   while (DidSomething == true);
-   
-   return true;
+   return cmdDepends(CmdL, *GCache);
 }
 
-// RDepends - Print out a reverse dependency tree - mbc                        /*{{{*/
-// ---------------------------------------------------------------------
-/* */
 bool RDepends(CommandLine &CmdL)
 {
-   pkgCache &Cache = *GCache;
-   SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
-   memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
-   
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-   {
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
-      if (Pkg.end() == true)
-      {
-        _error->Warning(_("Unable to locate package %s"),*I);
-        continue;
-      }
-      Colours[Pkg->ID] = 1;
-   }
-   
-   bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
-   bool Installed = _config->FindB("APT::Cache::Installed",false);
-   bool DidSomething;
-   do
-   {
-      DidSomething = false;
-      for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
-      {
-        if (Colours[Pkg->ID] != 1)
-           continue;
-        Colours[Pkg->ID] = 2;
-        DidSomething = true;
-        
-        pkgCache::VerIterator Ver = Pkg.VersionList();
-        if (Ver.end() == true)
-        {
-           cout << '<' << Pkg.Name() << '>' << endl;
-           continue;
-        }
-        
-        cout << Pkg.Name() << endl;
-        
-        cout << "Reverse Depends:" << endl;
-        for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() == false; D++)
-        {          
-           // Show the package
-           pkgCache::PkgIterator Trg = D.ParentPkg();
-
-           if((Installed && Trg->CurrentVer != 0) || !Installed)
-             {
-
-               if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
-                 cout << " |";
-               else
-                 cout << "  ";
-
-               if (Trg->VersionList == 0)
-                 cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
-               else
-                 cout << Trg.Name() << endl;
-
-               if (Recurse == true)
-                 Colours[D.ParentPkg()->ID]++;
-
-             }
-           
-           // Display all solutions
-           SPtrArray<pkgCache::Version *> List = D.AllTargets();
-           pkgPrioSortList(Cache,List);
-           for (pkgCache::Version **I = List; *I != 0; I++)
-           {
-              pkgCache::VerIterator V(Cache,*I);
-              if (V != Cache.VerP + V.ParentPkg()->VersionList ||
-                  V->ParentPkg == D->Package)
-                 continue;
-              cout << "    " << V.ParentPkg().Name() << endl;
-              
-              if (Recurse == true)
-                 Colours[D.ParentPkg()->ID]++;
-           }
-        }
-      }      
-   }   
-   while (DidSomething == true);
-   
-   return true;
+   return cmdRDepends(CmdL, *GCache);
 }
 
-                                                                       /*}}}*/
-// CNC:2003-02-19
-// WhatDepends - Print out a reverse dependency tree                   /*{{{*/
-// ---------------------------------------------------------------------
-/* */
 bool WhatDepends(CommandLine &CmdL)
 {
-   pkgCache &Cache = *GCache;
-   SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
-   memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
-   
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-   {
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
-      if (Pkg.end() == true)
-      {
-        _error->Warning(_("Unable to locate package %s"),*I);
-        continue;
-      }
-      Colours[Pkg->ID] = 1;
-   }
-   
-   bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
-   bool DidSomething;
-   do
-   {
-      DidSomething = false;
-      for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
-      {
-        if (Colours[Pkg->ID] != 1)
-           continue;
-        Colours[Pkg->ID] = 2;
-        DidSomething = true;
-        
-        pkgCache::VerIterator Ver = Pkg.VersionList();
-        if (Ver.end() == true)
-           cout << '<' << Pkg.Name() << '>' << endl;
-        else
-           cout << Pkg.Name() << "-" << Ver.VerStr() << endl;
-
-        SPtrArray<unsigned> LocalColours = 
-                    new unsigned[Cache.Head().PackageCount];
-        memset(LocalColours,0,sizeof(*LocalColours)*Cache.Head().PackageCount);
-           
-        // Display all dependencies directly on the package.
-        for (pkgCache::DepIterator RD = Pkg.RevDependsList();
-             RD.end() == false; RD++)
-        {
-           pkgCache::PkgIterator Parent = RD.ParentPkg();
-
-           if (LocalColours[Parent->ID] == 1)
-              continue;
-           LocalColours[Parent->ID] = 1;
-              
-           if (Ver.end() == false && RD.TargetVer() &&
-               Cache.VS->CheckDep(Ver.VerStr(),RD) == false)
-              continue;
-
-           if (Recurse == true && Colours[Parent->ID] == 0)
-              Colours[Parent->ID] = 1;
-
-           pkgCache::VerIterator ParentVer = Parent.VersionList();
-
-           // Show the package
-           cout << "  " << Parent.Name()
-                << "-" << ParentVer.VerStr() << endl;
-
-           // Display all dependencies from that package that relate
-           // to the queried package.
-           for (pkgCache::DepIterator D = ParentVer.DependsList();
-                D.end() == false; D++)
-           {
-              // If this is a virtual package, there's no provides.
-              if (Ver.end() == true) {
-                 // If it's not the same package, and there's no provides
-                 // skip that package.
-                 if (D.TargetPkg() != Pkg)
-                    continue;
-              } else if (D.TargetPkg() != Pkg ||
-                         Cache.VS->CheckDep(Ver.VerStr(),D) == false) {
-                 // Oops. Either it's not the same package, or the
-                 // version didn't match. Check virtual provides from
-                 // the queried package version and verify if this
-                 // dependency matches one of those.
-                 bool Hit = false;
-                 for (pkgCache::PrvIterator Prv = Ver.ProvidesList();
-                      Prv.end() == false; Prv++) {
-                    if (Prv.ParentPkg() == D.TargetPkg() &&
-                        (Prv.ParentPkg()->VersionList == 0 ||
-                         Cache.VS->CheckDep(Prv.ProvideVersion(),D)==false)) {
-                       Hit = true;
-                       break;
-                    }
-                 }
-                 if (Hit == false)
-                    continue;
-              }
-
-              // Bingo!
-              pkgCache::PkgIterator Trg = D.TargetPkg();
-              if (Trg->VersionList == 0)
-                 cout << "    " << D.DepType()
-                                << ": <" << Trg.Name() << ">" << endl;
-              else if (D.TargetVer() == 0)
-                 cout << "    " << D.DepType()
-                                << ": " << Trg.Name() << endl;
-              else
-                 cout << "    " << D.DepType()
-                                << ": " << Trg.Name()
-                                << " " << D.CompType() << " "
-                                << D.TargetVer() << endl;
-
-              // Display all solutions
-              SPtrArray<pkgCache::Version *> List = D.AllTargets();
-              pkgPrioSortList(Cache,List);
-              for (pkgCache::Version **I = List; *I != 0; I++)
-              {
-                 pkgCache::VerIterator V(Cache,*I);
-                 if (V != Cache.VerP + V.ParentPkg()->VersionList ||
-                     V->ParentPkg == D->Package)
-                    continue;
-                 cout << "      " << V.ParentPkg().Name()
-                      << "-" << V.VerStr() << endl;
-                 
-                 if (Recurse == true)
-                    Colours[D.ParentPkg()->ID]++;
-              }
-           }
-        }
-
-        // Is this a virtual package the user queried directly?
-        if (Ver.end())
-           continue;
-
-        // Display all dependencies on virtual provides, which were not
-        // yet shown in the step above.
-        for (pkgCache::PrvIterator RDPrv = Ver.ProvidesList();
-             RDPrv.end() == false; RDPrv++) {
-           for (pkgCache::DepIterator RD = RDPrv.ParentPkg().RevDependsList();
-                RD.end() == false; RD++)
-           {
-              pkgCache::PkgIterator Parent = RD.ParentPkg();
-
-              if (LocalColours[Parent->ID] == 1)
-                 continue;
-              LocalColours[Parent->ID] = 1;
-                 
-              if (Ver.end() == false &&
-                  Cache.VS->CheckDep(Ver.VerStr(),RD) == false)
-                 continue;
-
-              if (Recurse == true && Colours[Parent->ID] == 0)
-                 Colours[Parent->ID] = 1;
-
-              pkgCache::VerIterator ParentVer = Parent.VersionList();
-
-              // Show the package
-              cout << "  " << Parent.Name()
-                   << "-" << ParentVer.VerStr() << endl;
-
-              for (pkgCache::DepIterator D = ParentVer.DependsList();
-                   D.end() == false; D++)
-              {
-                 // Go on if it's the same package and version or
-                 // if it's the same package and has no versions
-                 // (a virtual package).
-                 if (D.TargetPkg() != RDPrv.ParentPkg() ||
-                     (RDPrv.ProvideVersion() != 0 &&
-                      Cache.VS->CheckDep(RDPrv.ProvideVersion(),D) == false))
-                    continue;
-
-                 // Bingo!
-                 pkgCache::PkgIterator Trg = D.TargetPkg();
-                 if (Trg->VersionList == 0)
-                    cout << "    " << D.DepType()
-                                   << ": <" << Trg.Name() << ">" << endl;
-                 else if (D.TargetVer() == 0)
-                    cout << "    " << D.DepType()
-                                   << ": " << Trg.Name() << endl;
-                 else
-                    cout << "    " << D.DepType()
-                                   << ": " << Trg.Name()
-                                   << " " << D.CompType() << " "
-                                   << D.TargetVer() << endl;
+   return cmdWhatDepends(CmdL, *GCache);
+}
 
-                 // Display all solutions
-                 SPtrArray<pkgCache::Version *> List = D.AllTargets();
-                 pkgPrioSortList(Cache,List);
-                 for (pkgCache::Version **I = List; *I != 0; I++)
-                 {
-                    pkgCache::VerIterator V(Cache,*I);
-                    if (V != Cache.VerP + V.ParentPkg()->VersionList ||
-                        V->ParentPkg == D->Package)
-                       continue;
-                    cout << "      " << V.ParentPkg().Name()
-                         << "-" << V.VerStr() << endl;
-                    
-                    if (Recurse == true)
-                       Colours[D.ParentPkg()->ID]++;
-                 }
-              }
-           }
-        }
-      } 
-   }
-   while (DidSomething == true);
-   
-   return true;
+bool WhatProvides(CommandLine &CmdL)
+{
+   return cmdWhatProvides(CmdL, *GCache);
 }
-                                                                       /*}}}*/
 
 // xvcg - Generate a graph for xvcg                                    /*{{{*/
 // ---------------------------------------------------------------------
@@ -1158,55 +624,6 @@ bool XVcg(CommandLine &CmdL)
                                                                        /*}}}*/
 
 
-// WhatProvides - Show all packages that provide the given (virtual) package
-// ---------------------------------------------------------------------
-/* */
-bool WhatProvides(CommandLine &CmdL)
-{
-  pkgCache &Cache = *GCache;
-  bool    found;
-
-  for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-  {
-       cout << "<" << *I << ">" << endl;
-       found = false;
-       for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
-       {
-           for (pkgCache::VerIterator Ver = Pkg.VersionList(); !Ver.end(); Ver++)
-           {
-                if (!strcmp(Pkg.Name(), *I))
-                {
-                     // match on real package, ignore any provides in the package
-                     // since they would be meaningless
-                     cout << "  " << Pkg.Name() << "-" << Ver.VerStr() << endl;
-                     found = true;
-                }
-                else
-                {
-                     // seach in package's provides list
-                     for (pkgCache::PrvIterator Prv = Ver.ProvidesList(); Prv.end() == false; Prv++)
-                     {
-                          if (!strcmp(Prv.Name(), *I))
-                          {
-                               cout << "  " << Pkg.Name() << "-" << Ver.VerStr() << endl;
-                               cout << "    Provides: <" << Prv.Name();
-                               if (Prv.ProvideVersion() != 0)
-                                       cout << " = " << Prv.ProvideVersion();
-                               cout << ">" << endl;
-                               found = true;
-                          }
-                     }
-                }
-           }
-       }
-       
-       if (!found)
-           cout << "  nothing provides <" << *I << ">" << endl;
-  }
-  
-  return true;
-}
-                                                                 /*}}}*/
 // Dotty - Generate a graph for Dotty                                  /*{{{*/
 // ---------------------------------------------------------------------
 /* Dotty is the graphvis program for generating graphs. It is a fairly
@@ -1476,279 +893,28 @@ bool DoAdd(CommandLine &CmdL)
    It is not used by DumpAvail for performance reasons. */
 bool DisplayRecord(pkgCache::VerIterator V)
 {
-   // Find an appropriate file
-   pkgCache::VerFileIterator Vf = V.FileList();
-   for (; Vf.end() == false; Vf++)
-      if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
-        break;
-   if (Vf.end() == true)
-      Vf = V.FileList();
-      
-// CNC:2002-07-24
-#if HAVE_RPM
-   pkgRecords Recs(*GCache);
-   pkgRecords::Parser &P = Recs.Lookup(Vf);
-   const char *Start;
-   const char *End;
-   P.GetRec(Start,End);
-   cout << string(Start,End-Start) << endl;
-#else
-   // Check and load the package list file
-   pkgCache::PkgFileIterator I = Vf.File();
-   if (I.IsOk() == false)
-      return _error->Error(_("Package file %s is out of sync."),I.FileName());
-   
-   FileFd PkgF(I.FileName(),FileFd::ReadOnly);
-   if (_error->PendingError() == true)
-      return false;
-   
-   // Read the record and then write it out again.
-   unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
-   Buffer[V.FileList()->Size] = '\n';
-   if (PkgF.Seek(V.FileList()->Offset) == false ||
-       PkgF.Read(Buffer,V.FileList()->Size) == false ||
-       fwrite(Buffer,1,V.FileList()->Size+1,stdout) < V.FileList()->Size+1)
-   {
-      delete [] Buffer;
-      return false;
-   }
-   
-   delete [] Buffer;
-#endif
-
-   return true;
+   return cmdDisplayRecord(V, *GCache);
 }
                                                                        /*}}}*/
 // Search - Perform a search                                           /*{{{*/
 // ---------------------------------------------------------------------
 /* This searches the package names and pacakge descriptions for a pattern */
-struct ExVerFile
+bool Search(CommandLine &CmdL)
 {
-   pkgCache::VerFile *Vf;
-   bool NameMatch;
-};
-
+   return cmdSearch(CmdL, *GCache);
+}
+                                                                       /*}}}*/
 bool SearchFile(CommandLine &CmdL)
 {
-   pkgCache &Cache = *GCache;
-   pkgRecords Recs(Cache);
-   pkgDepCache::Policy Plcy;
-
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++) {
-      pkgCache::PkgIterator Pkg = Cache.PkgBegin();
-      for (; Pkg.end() == false; Pkg++) {
-        if (_config->FindB("APT::Cache::AllVersions", false) == true) {
-           pkgCache::VerIterator Ver = Pkg.VersionList();
-           for (; Ver.end() == false; Ver++) {
-              pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
-              if (Parse.HasFile(*I)) {
-                 cout << *I << " " << Pkg.Name() << "-" << Ver.VerStr() << endl;
-              }
-           }
-        } else {
-           pkgCache::VerIterator Ver = Plcy.GetCandidateVer(Pkg);
-           if (Ver.end() == false) {
-              pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
-              if (Parse.HasFile(*I)) {
-                 cout << *I << " " << Pkg.Name() << "-" << Ver.VerStr() << endl;
-              }
-           }
-        }
-      }
-   }
-
-   return true;
+   return cmdSearchFile(CmdL, *GCache);
 }
 
-bool Search(CommandLine &CmdL)
-{
-   pkgCache &Cache = *GCache;
-   bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
-   bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
-   unsigned NumPatterns = CmdL.FileSize() -1;
-   
-   pkgDepCache::Policy Plcy;
-   
-   // Make sure there is at least one argument
-   if (NumPatterns < 1)
-      return _error->Error(_("You must give exactly one pattern"));
-   
-   // Compile the regex pattern
-   regex_t *Patterns = new regex_t[NumPatterns];
-   memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
-   for (unsigned I = 0; I != NumPatterns; I++)
-   {
-      if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE | 
-                 REG_NOSUB) != 0)
-      {
-        for (; I != 0; I--)
-           regfree(&Patterns[I]);
-        return _error->Error("Regex compilation error");
-      }      
-   }
-   
-   // Create the text record parser
-   pkgRecords Recs(Cache);
-   if (_error->PendingError() == true)
-   {
-      for (unsigned I = 0; I != NumPatterns; I++)
-        regfree(&Patterns[I]);
-      return false;
-   }
-   
-   ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
-   memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
-
-   // Map versions that we want to write out onto the VerList array.
-   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
-   {
-      VFList[P->ID].NameMatch = NumPatterns != 0;
-      for (unsigned I = 0; I != NumPatterns; I++)
-      {
-        if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
-           VFList[P->ID].NameMatch &= true;
-        else
-           VFList[P->ID].NameMatch = false;
-      }
-        
-      // Doing names only, drop any that dont match..
-      if (NamesOnly == true && VFList[P->ID].NameMatch == false)
-        continue;
-        
-      // Find the proper version to use. 
-      pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
-      if (V.end() == false)
-        VFList[P->ID].Vf = V.FileList();
-   }
-      
-   // Include all the packages that provide matching names too
-   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
-   {
-      if (VFList[P->ID].NameMatch == false)
-        continue;
-
-      for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
-      {
-        pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
-        if (V.end() == false)
-        {
-           VFList[Prv.OwnerPkg()->ID].Vf = V.FileList();
-           VFList[Prv.OwnerPkg()->ID].NameMatch = true;
-        }
-      }
-   }
-
-   LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
-
-   // Iterate over all the version records and check them
-   for (ExVerFile *J = VFList; J->Vf != 0; J++)
-   {
-      pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
-
-      bool Match = true;
-      if (J->NameMatch == false)
-      {
-        string LongDesc = P.LongDesc(); 
-        // CNC 2004-04-10
-        string ShortDesc = P.ShortDesc();
-        Match = NumPatterns != 0;
-        for (unsigned I = 0; I != NumPatterns; I++)
-        {
-           if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0 ||
-               regexec(&Patterns[I],ShortDesc.c_str(),0,0,0) == 0)
-              Match &= true;
-           else
-              Match = false;
-        }
-      }
-      
-      if (Match == true)
-      {
-        if (ShowFull == true)
-        {
-           const char *Start;
-           const char *End;
-           P.GetRec(Start,End);
-           cout << string(Start,End-Start) << endl;
-        }       
-        else
-           cout << P.Name() << " - " << P.ShortDesc() << endl;
-      }
-   }
-   
-   delete [] VFList;
-   for (unsigned I = 0; I != NumPatterns; I++)
-      regfree(&Patterns[I]);
-   if (ferror(stdout))
-       return _error->Error("Write to stdout failed");
-   return true;
-}
-                                                                       /*}}}*/
 // ShowPackage - Dump the package record to the screen                 /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 bool ShowPackage(CommandLine &CmdL)
 {   
-   pkgCache &Cache = *GCache;
-   pkgDepCache::Policy Plcy;
-
-   unsigned found = 0;
-   
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-   {
-      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
-      if (Pkg.end() == true)
-      {
-        _error->Warning(_("Unable to locate package %s"),*I);
-        continue;
-      }
-
-      ++found;
-
-      // CNC:2004-07-09
-      // If it's a virtual package, require user to select similarly to apt-get
-      if (Pkg.VersionList().end() == true and Pkg->ProvidesList != 0)
-      {
-         ioprintf(cout, _("Package %s is a virtual package provided by:\n"),
-                  Pkg.Name());
-         for (pkgCache::PrvIterator Prv = Pkg.ProvidesList();
-             Prv.end() == false; Prv++)
-         {
-           pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
-            if (V.end() == true)
-               continue;
-            if (V != Prv.OwnerVer())
-               continue;
-            cout << "  " << Prv.OwnerPkg().Name() << " " << V.VerStr() << endl;
-         }
-         cout << _("You should explicitly select one to show.") << endl;
-         _error->Error(_("Package %s is a virtual package with multiple providers."), Pkg.Name());
-         return false;
-      }
-
-      // Find the proper version to use.
-      if (_config->FindB("APT::Cache::AllVersions", false) == true)
-      {
-        pkgCache::VerIterator V;
-        for (V = Pkg.VersionList(); V.end() == false; V++)
-        {
-           if (DisplayRecord(V) == false)
-              return false;
-        }
-      }
-      else
-      {
-        pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
-        if (V.end() == true || V.FileList().end() == true)
-           continue;
-        if (DisplayRecord(V) == false)
-           return false;
-      }      
-   }
-
-   if (found > 0)
-        return true;
-   return _error->Error(_("No packages found"));
+   return cmdShowPackage(CmdL, *GCache);
 }
                                                                        /*}}}*/
 // ShowPkgNames - Show package names                                   /*{{{*/
@@ -1975,11 +1141,12 @@ bool ShowHelp(CommandLine &Cmd)
       "   dumpavail - Print an available file to stdout\n"
       "   unmet - Show unmet dependencies\n"
       "   search - Search the package list for a regex pattern\n"
+      "   searchfile - Search the packages for a file\n"
       "   show - Show a readable record for the package\n"
       "   depends - Show raw dependency information for a package\n"
-      "   whatdepends - Show packages depending on given items\n"
+      "   whatdepends - Show packages depending on given capabilities\n"
       // "   rdepends - Show reverse dependency information for a package\n"
-      "   whatprovides - Show packages that provide given items\n"
+      "   whatprovides - Show packages that provide given capabilities\n"
       "   pkgnames - List the names of all packages\n"
       "   dotty - Generate package graphs for GraphVis\n"
       "   xvcg - Generate package graphs for xvcg\n"