]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-cache.cc
support optional PulseInterval in ListUpdate
[apt.git] / cmdline / apt-cache.cc
index 6792b576794d153a5c48d1bec955319e723a3846..c0655da40b5171c8a5a9a3e93c3b2dd9a6614d87 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: apt-cache.cc,v 1.49 2001/05/27 04:46:43 jgg Exp $
+// $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz Exp $
 /* ######################################################################
    
    apt-cache - Manages the cache files
 #include <config.h>
 #include <apti18n.h>
 
-#include <iostream.h>
+#include <locale.h>
+#include <iostream>
 #include <unistd.h>
 #include <errno.h>
 #include <regex.h>
 #include <stdio.h>
+
+#include <iomanip>
                                                                        /*}}}*/
 
+using namespace std;
+
 pkgCache *GCache = 0;
 pkgSourceList *SrcList = 0;
 
@@ -66,6 +71,12 @@ void LocalitySort(pkgCache::VerFile **begin,
 {   
    qsort(begin,Count,Size,LocalityCompare);
 }
+
+void LocalitySort(pkgCache::DescFile **begin,
+                 unsigned long Count,size_t Size)
+{   
+   qsort(begin,Count,Size,LocalityCompare);
+}
                                                                        /*}}}*/
 // UnMet - Show unmet dependencies                                     /*{{{*/
 // ---------------------------------------------------------------------
@@ -91,13 +102,15 @@ bool UnMet(CommandLine &CmdL)
            if (End->Type != pkgCache::Dep::PreDepends &&
                End->Type != pkgCache::Dep::Depends && 
                End->Type != pkgCache::Dep::Suggests &&
-               End->Type != pkgCache::Dep::Recommends)
+               End->Type != pkgCache::Dep::Recommends &&
+               End->Type != pkgCache::Dep::DpkgBreaks)
               continue;
 
            // Important deps only
            if (Important == true)
               if (End->Type != pkgCache::Dep::PreDepends &&
-                  End->Type != pkgCache::Dep::Depends)
+                  End->Type != pkgCache::Dep::Depends &&
+                  End->Type != pkgCache::Dep::DpkgBreaks)
                  continue;
            
            // Verify the or group
@@ -177,7 +190,14 @@ bool DumpPackage(CommandLine &CmdL)
       {
         cout << Cur.VerStr();
         for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
-           cout << "(" << Vf.File().FileName() << ")";
+           cout << " (" << Vf.File().FileName() << ")";
+        cout << endl;
+        for (pkgCache::DescIterator D = Cur.DescriptionList(); D.end() == false; D++)
+        {
+           cout << " Description Language: " << D.LanguageCode() << endl
+                << "                 File: " << D.FileList().File().FileName() << endl
+                << "                  MD5: " << D.md5() << endl;
+        }
         cout << endl;
       }
       
@@ -188,7 +208,7 @@ bool DumpPackage(CommandLine &CmdL)
       {
         cout << "  " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name();
         if (D->Version != 0)
-           cout << ' ' << D.TargetVer() << endl;
+           cout << ' ' << DeNull(D.TargetVer()) << endl;
         else
            cout << endl;
       }
@@ -198,7 +218,7 @@ bool DumpPackage(CommandLine &CmdL)
       {
         cout << Cur.VerStr() << " - ";
         for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
-           cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << Dep.TargetVer() << ") ";
+           cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
         cout << endl;
       }      
 
@@ -224,7 +244,7 @@ bool DumpPackage(CommandLine &CmdL)
 bool Stats(CommandLine &Cmd)
 {
    pkgCache &Cache = *GCache;
-   cout << _("Total Package Names : ") << Cache.Head().PackageCount << " (" <<
+   cout << _("Total package names : ") << Cache.Head().PackageCount << " (" <<
       SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
 
    int Normal = 0;
@@ -264,20 +284,24 @@ bool Stats(CommandLine &Cmd)
         continue;
       }
    }
-   cout << _("  Normal Packages: ") << Normal << endl;
-   cout << _("  Pure Virtual Packages: ") << Virtual << endl;
-   cout << _("  Single Virtual Packages: ") << DVirt << endl;
-   cout << _("  Mixed Virtual Packages: ") << NVirt << endl;
+   cout << _("  Normal packages: ") << Normal << endl;
+   cout << _("  Pure virtual packages: ") << Virtual << endl;
+   cout << _("  Single virtual packages: ") << DVirt << endl;
+   cout << _("  Mixed virtual packages: ") << NVirt << endl;
    cout << _("  Missing: ") << Missing << endl;
    
-   cout << _("Total Distinct Versions: ") << Cache.Head().VersionCount << " (" <<
+   cout << _("Total distinct versions: ") << Cache.Head().VersionCount << " (" <<
       SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
-   cout << _("Total Dependencies: ") << Cache.Head().DependsCount << " (" << 
+   cout << _("Total Distinct Descriptions: ") << Cache.Head().DescriptionCount << " (" <<
+      SizeToStr(Cache.Head().DescriptionCount*Cache.Head().DescriptionSz) << ')' << endl;
+   cout << _("Total dependencies: ") << Cache.Head().DependsCount << " (" << 
       SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
    
-   cout << _("Total Ver/File relations: ") << Cache.Head().VerFileCount << " (" <<
+   cout << _("Total ver/file relations: ") << Cache.Head().VerFileCount << " (" <<
       SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
-   cout << _("Total Provides Mappings: ") << Cache.Head().ProvidesCount << " (" <<
+   cout << _("Total Desc/File relations: ") << Cache.Head().DescFileCount << " (" <<
+      SizeToStr(Cache.Head().DescFileCount*Cache.Head().DescFileSz) << ')' << endl;
+   cout << _("Total Provides mappings: ") << Cache.Head().ProvidesCount << " (" <<
       SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
    
    // String list stats
@@ -289,7 +313,7 @@ bool Stats(CommandLine &Cmd)
       Count++;
       Size += strlen(Cache.StrP + I->String) + 1;
    }
-   cout << _("Total Globbed Strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
+   cout << _("Total globbed strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
 
    unsigned long DepVerSize = 0;
    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
@@ -303,12 +327,12 @@ bool Stats(CommandLine &Cmd)
         }
       }
    }
-   cout << _("Total Dependency Version space: ") << SizeToStr(DepVerSize) << endl;
+   cout << _("Total dependency version space: ") << SizeToStr(DepVerSize) << endl;
    
    unsigned long Slack = 0;
    for (int I = 0; I != 7; I++)
       Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count;
-   cout << _("Total Slack space: ") << SizeToStr(Slack) << endl;
+   cout << _("Total slack space: ") << SizeToStr(Slack) << endl;
    
    unsigned long Total = 0;
    Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz + 
@@ -316,7 +340,7 @@ bool Stats(CommandLine &Cmd)
            Cache.Head().PackageCount*Cache.Head().PackageSz + 
            Cache.Head().VerFileCount*Cache.Head().VerFileSz +
            Cache.Head().ProvidesCount*Cache.Head().ProvidesSz;
-   cout << _("Total Space Accounted for: ") << SizeToStr(Total) << endl;
+   cout << _("Total space accounted for: ") << SizeToStr(Total) << endl;
    
    return true;
 }
@@ -339,6 +363,12 @@ bool Dump(CommandLine &Cmd)
         for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
            cout << "  Depends: " << D.TargetPkg().Name() << ' ' << 
                             DeNull(D.TargetVer()) << endl;
+        for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; D++)
+        {
+           cout << " Description Language: " << D.LanguageCode() << endl
+                << "                 File: " << D.FileList().File().FileName() << endl
+                << "                  MD5: " << D.md5() << endl;
+        } 
       }      
    }
 
@@ -374,8 +404,9 @@ bool DumpAvail(CommandLine &Cmd)
    if (ReadPinFile(Plcy) == false)
       return false;
    
-   pkgCache::VerFile **VFList = new pkgCache::VerFile *[Cache.HeaderP->PackageCount];
-   memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount);
+   unsigned long Count = Cache.HeaderP->PackageCount+1;
+   pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
+   memset(VFList,0,sizeof(*VFList)*Count);
    
    // Map versions that we want to write out onto the VerList array.
    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
@@ -428,7 +459,7 @@ bool DumpAvail(CommandLine &Cmd)
       VFList[P->ID] = VF;
    }
    
-   LocalitySort(VFList,Cache.HeaderP->PackageCount,sizeof(*VFList));
+   LocalitySort(VFList,Count,sizeof(*VFList));
 
    // Iterate over all the package files and write them out.
    char *Buffer = new char[Cache.HeaderP->MaxVerFileSize+10];
@@ -475,7 +506,7 @@ bool DumpAvail(CommandLine &Cmd)
         if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
         {
            pkgTagSection Tags;
-           TFRewriteData RW[] = {{"Status",0},{}};
+           TFRewriteData RW[] = {{"Status",0},{"Config-Version",0},{}};
            const char *Zero = 0;
            if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
                TFRewrite(stdout,Tags,&Zero,RW) == false)
@@ -525,6 +556,7 @@ bool Depends(CommandLine &CmdL)
    }
    
    bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
+   bool Installed = _config->FindB("APT::Cache::Installed",false);
    bool DidSomething;
    do
    {
@@ -547,20 +579,115 @@ bool Depends(CommandLine &CmdL)
         
         for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
         {
-           if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
-              cout << " |";
-           else
-              cout << "  ";
-           
-           // Show the package
+
            pkgCache::PkgIterator Trg = D.TargetPkg();
-           if (Trg->VersionList == 0)
-              cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
-           else
-              cout << D.DepType() << ": " << Trg.Name() << endl;
+
+           if((Installed && Trg->CurrentVer != 0) || !Installed)
+             {
+
+               if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
+                 cout << " |";
+               else
+                 cout << "  ";
            
-           if (Recurse == true)
-              Colours[D.TargetPkg()->ID]++;
+               // Show the package
+               if (Trg->VersionList == 0)
+                 cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
+               else
+                 cout << D.DepType() << ": " << Trg.Name() << 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;
+              cout << "    " << V.ParentPkg().Name() << endl;
+              
+              if (Recurse == true)
+                 Colours[D.ParentPkg()->ID]++;
+           }
+        }
+      }      
+   }   
+   while (DidSomething == true);
+   
+   return true;
+}
+
+// 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();
@@ -583,7 +710,231 @@ bool Depends(CommandLine &CmdL)
    
    return true;
 }
+
                                                                        /*}}}*/
+
+
+// xvcg - Generate a graph for xvcg                                    /*{{{*/
+// ---------------------------------------------------------------------
+// Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
+
+bool XVcg(CommandLine &CmdL)
+{
+   pkgCache &Cache = *GCache;
+   bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
+   
+   /* Normal packages are boxes
+      Pure Provides are triangles
+      Mixed are diamonds
+      rhomb are missing packages*/
+   const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
+   
+   /* Initialize the list of packages to show.
+      1 = To Show
+      2 = To Show no recurse
+      3 = Emitted no recurse
+      4 = Emitted
+      0 = None */
+   enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
+   enum TheFlags {ForceNR=(1<<0)};
+   unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
+   unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
+   unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
+   
+   // Show everything if no arguments given
+   if (CmdL.FileList[1] == 0)
+      for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
+        Show[I] = ToShow;
+   else
+      for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
+        Show[I] = None;
+   memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
+   
+   // Map the shapes
+   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+   {   
+      if (Pkg->VersionList == 0)
+      {
+        // Missing
+        if (Pkg->ProvidesList == 0)
+           ShapeMap[Pkg->ID] = 0;
+        else
+           ShapeMap[Pkg->ID] = 1;
+      }
+      else
+      {
+        // Normal
+        if (Pkg->ProvidesList == 0)
+           ShapeMap[Pkg->ID] = 2;
+        else
+           ShapeMap[Pkg->ID] = 3;
+      }
+   }
+   
+   // Load the list of packages from the command line into the show list
+   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   {
+      // Process per-package flags
+      string P = *I;
+      bool Force = false;
+      if (P.length() > 3)
+      {
+        if (P.end()[-1] == '^')
+        {
+           Force = true;
+           P.erase(P.end()-1);
+        }
+        
+        if (P.end()[-1] == ',')
+           P.erase(P.end()-1);
+      }
+      
+      // Locate the package
+      pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
+      if (Pkg.end() == true)
+      {
+        _error->Warning(_("Unable to locate package %s"),*I);
+        continue;
+      }
+      Show[Pkg->ID] = ToShow;
+      
+      if (Force == true)
+        Flags[Pkg->ID] |= ForceNR;
+   }
+   
+   // Little header
+   cout << "graph: { title: \"packages\"" << endl <<
+     "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
+     "layout_downfactor: 8" << endl;
+
+   bool Act = true;
+   while (Act == true)
+   {
+      Act = false;
+      for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+      {
+        // See we need to show this package
+        if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
+           continue;
+
+        //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
+        
+        // Colour as done
+        if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
+        {
+           // Pure Provides and missing packages have no deps!
+           if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
+              Show[Pkg->ID] = Done;
+           else
+              Show[Pkg->ID] = DoneNR;
+        }       
+        else
+           Show[Pkg->ID] = Done;
+        Act = true;
+
+        // No deps to map out
+        if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
+           continue;
+        
+        pkgCache::VerIterator Ver = Pkg.VersionList();
+        for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
+        {
+           // See if anything can meet this dep
+           // Walk along the actual package providing versions
+           bool Hit = false;
+           pkgCache::PkgIterator DPkg = D.TargetPkg();
+           for (pkgCache::VerIterator I = DPkg.VersionList();
+                     I.end() == false && Hit == false; I++)
+           {
+              if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
+                 Hit = true;
+           }
+           
+           // Follow all provides
+           for (pkgCache::PrvIterator I = DPkg.ProvidesList(); 
+                     I.end() == false && Hit == false; I++)
+           {
+              if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
+                 Hit = true;
+           }
+           
+
+           // Only graph critical deps     
+           if (D.IsCritical() == true)
+           {
+              printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.Name(), D.TargetPkg().Name() );
+              
+              // Colour the node for recursion
+              if (Show[D.TargetPkg()->ID] <= DoneNR)
+              {
+                 /* If a conflicts does not meet anything in the database
+                    then show the relation but do not recurse */
+                 if (Hit == false && 
+                     (D->Type == pkgCache::Dep::Conflicts ||
+                      D->Type == pkgCache::Dep::DpkgBreaks ||
+                      D->Type == pkgCache::Dep::Obsoletes))
+                 {
+                    if (Show[D.TargetPkg()->ID] == None && 
+                        Show[D.TargetPkg()->ID] != ToShow)
+                       Show[D.TargetPkg()->ID] = ToShowNR;
+                 }               
+                 else
+                 {
+                    if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
+                       Show[D.TargetPkg()->ID] = ToShowNR;
+                    else
+                       Show[D.TargetPkg()->ID] = ToShow;
+                 }
+              }
+              
+              // Edge colour
+              switch(D->Type)
+              {
+                 case pkgCache::Dep::Conflicts:
+                   printf("label: \"conflicts\" color: lightgreen }\n");
+                   break;
+                 case pkgCache::Dep::DpkgBreaks:
+                   printf("label: \"breaks\" color: lightgreen }\n");
+                   break;
+                 case pkgCache::Dep::Obsoletes:
+                   printf("label: \"obsoletes\" color: lightgreen }\n");
+                   break;
+                 
+                 case pkgCache::Dep::PreDepends:
+                   printf("label: \"predepends\" color: blue }\n");
+                   break;
+                 
+                 default:
+                   printf("}\n");
+                 break;
+              }               
+           }       
+        }
+      }
+   }   
+   
+   /* Draw the box colours after the fact since we can not tell what colour
+      they should be until everything is finished drawing */
+   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+   {
+      if (Show[Pkg->ID] < DoneNR)
+        continue;
+
+      if (Show[Pkg->ID] == DoneNR)
+        printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.Name(), Pkg.Name(),
+               Shapes[ShapeMap[Pkg->ID]]);
+      else
+       printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.Name(), Pkg.Name(), 
+               Shapes[ShapeMap[Pkg->ID]]);
+      
+   }
+   
+   printf("}\n");
+   return true;
+}
+                                                                       /*}}}*/
+
+
 // Dotty - Generate a graph for Dotty                                  /*{{{*/
 // ---------------------------------------------------------------------
 /* Dotty is the graphvis program for generating graphs. It is a fairly
@@ -870,17 +1221,50 @@ bool DisplayRecord(pkgCache::VerIterator V)
    if (_error->PendingError() == true)
       return false;
    
-   // Read the record and then write it out again.
+   // Read the record
    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 ||
-       write(STDOUT_FILENO,Buffer,V.FileList()->Size+1) != V.FileList()->Size+1)
+       PkgF.Read(Buffer,V.FileList()->Size) == false)
    {
       delete [] Buffer;
       return false;
    }
-   
+
+   // Get a pointer to start of Description field
+   const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "Description:");
+
+   // Write all but Description
+   if (fwrite(Buffer,1,DescP - Buffer,stdout) < (size_t)(DescP - Buffer))
+   {
+      delete [] Buffer;
+      return false;
+   }
+
+   // Show the right description
+   pkgRecords Recs(*GCache);
+   pkgCache::DescIterator Desc = V.TranslatedDescription();
+   pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
+   cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
+
+   // Find the first field after the description (if there is any)
+   for(DescP++;DescP != &Buffer[V.FileList()->Size];DescP++) 
+   {
+      if(*DescP == '\n' && *(DescP+1) != ' ') 
+      {
+        // write the rest of the buffer
+        const unsigned char *end=&Buffer[V.FileList()->Size];
+        if (fwrite(DescP,1,end-DescP,stdout) < (size_t)(end-DescP)) 
+        {
+           delete [] Buffer;
+           return false;
+        }
+
+        break;
+      }
+   }
+   // write a final newline (after the description)
+   cout<<endl;
    delete [] Buffer;
 
    return true;
@@ -889,9 +1273,9 @@ bool DisplayRecord(pkgCache::VerIterator V)
 // Search - Perform a search                                           /*{{{*/
 // ---------------------------------------------------------------------
 /* This searches the package names and pacakge descriptions for a pattern */
-struct ExVerFile
+struct ExDescFile
 {
-   pkgCache::VerFile *Vf;
+   pkgCache::DescFile *Df;
    bool NameMatch;
 };
 
@@ -931,38 +1315,54 @@ bool Search(CommandLine &CmdL)
       return false;
    }
    
-   ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
-   memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
+   ExDescFile *DFList = new ExDescFile[Cache.HeaderP->PackageCount+1];
+   memset(DFList,0,sizeof(*DFList)*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;
+      DFList[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;
+           DFList[P->ID].NameMatch &= true;
         else
-           VFList[P->ID].NameMatch = false;
+           DFList[P->ID].NameMatch = false;
       }
-      
+        
       // Doing names only, drop any that dont match..
-      if (NamesOnly == true && VFList[P->ID].NameMatch == false)
+      if (NamesOnly == true && DFList[P->ID].NameMatch == false)
         continue;
         
       // Find the proper version to use. 
       pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
-      if (V.end() == true)
+      if (V.end() == false)
+        DFList[P->ID].Df = V.DescriptionList().FileList();
+   }
+      
+   // Include all the packages that provide matching names too
+   for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
+   {
+      if (DFList[P->ID].NameMatch == false)
         continue;
-      VFList[P->ID].Vf = V.FileList();
+
+      for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
+      {
+        pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
+        if (V.end() == false)
+        {
+           DFList[Prv.OwnerPkg()->ID].Df = V.DescriptionList().FileList();
+           DFList[Prv.OwnerPkg()->ID].NameMatch = true;
+        }
+      }
    }
    
-   LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
+   LocalitySort(&DFList->Df,Cache.HeaderP->PackageCount,sizeof(*DFList));
 
    // Iterate over all the version records and check them
-   for (ExVerFile *J = VFList; J->Vf != 0; J++)
+   for (ExDescFile *J = DFList; J->Df != 0; J++)
    {
-      pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
+      pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(Cache,J->Df));
 
       bool Match = true;
       if (J->NameMatch == false)
@@ -993,7 +1393,7 @@ bool Search(CommandLine &CmdL)
       }
    }
    
-   delete [] VFList;
+   delete [] DFList;
    for (unsigned I = 0; I != NumPatterns; I++)
       regfree(&Patterns[I]);
    if (ferror(stdout))
@@ -1008,6 +1408,8 @@ bool ShowPackage(CommandLine &CmdL)
 {   
    pkgCache &Cache = *GCache;
    pkgDepCache::Policy Plcy;
+
+   unsigned found = 0;
    
    for (const char **I = CmdL.FileList + 1; *I != 0; I++)
    {
@@ -1018,6 +1420,8 @@ bool ShowPackage(CommandLine &CmdL)
         continue;
       }
 
+      ++found;
+
       // Find the proper version to use.
       if (_config->FindB("APT::Cache::AllVersions","true") == true)
       {
@@ -1037,7 +1441,10 @@ bool ShowPackage(CommandLine &CmdL)
            return false;
       }      
    }
-   return true;
+
+   if (found > 0)
+        return true;
+   return _error->Error(_("No packages found"));
 }
                                                                        /*}}}*/
 // ShowPkgNames - Show package names                                   /*{{{*/
@@ -1114,7 +1521,7 @@ bool Policy(CommandLine &CmdL)
    // Print out all of the package files
    if (CmdL.FileList[1] == 0)
    {
-      cout << _("Package Files:") << endl;   
+      cout << _("Package files:") << endl;   
       for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
       {
         // Locate the associated index files so we can derive a description
@@ -1134,7 +1541,7 @@ bool Policy(CommandLine &CmdL)
       }
       
       // Show any packages have explicit pins
-      cout << _("Pinned Packages:") << endl;
+      cout << _("Pinned packages:") << endl;
       pkgCache::PkgIterator I = Cache.PkgBegin();
       for (;I.end() != true; I++)
       {
@@ -1184,7 +1591,7 @@ bool Policy(CommandLine &CmdL)
       // Pinned version
       if (Plcy.GetPriority(Pkg) != 0)
       {
-        cout << _("  Package Pin: ");
+        cout << _("  Package pin: ");
         V = Plcy.GetMatch(Pkg);
         if (V.end() == true)
            cout << _("(not found)") << endl;
@@ -1193,7 +1600,7 @@ bool Policy(CommandLine &CmdL)
       }
       
       // Show the priority tables
-      cout << _("  Version Table:") << endl;
+      cout << _("  Version table:") << endl;
       for (V = Pkg.VersionList(); V.end() == false; V++)
       {
         if (Pkg.CurrentVer() == V)
@@ -1216,6 +1623,75 @@ bool Policy(CommandLine &CmdL)
    
    return true;
 }
+                                                                       /*}}}*/
+// Madison - Look a bit like katie's madison                           /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool Madison(CommandLine &CmdL)
+{
+   if (SrcList == 0)
+      return _error->Error("Generate must be enabled for this function");
+
+   SrcList->ReadMainList();
+
+   pkgCache &Cache = *GCache;
+
+   // Create the src text record parsers and ignore errors about missing
+   // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
+   pkgSrcRecords SrcRecs(*SrcList);
+   if (_error->PendingError() == true)
+      _error->Discard();
+
+   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   {
+      pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
+
+      if (Pkg.end() == false)
+      {
+         for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; V++)
+         {
+            for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
+            {
+// This might be nice, but wouldn't uniquely identify the source -mdz
+//                if (VF.File().Archive() != 0)
+//                {
+//                   cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
+//                        << VF.File().Archive() << endl;
+//                }
+
+               // Locate the associated index files so we can derive a description
+               for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); S++)
+               {
+                    vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
+                    for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
+                         IF != Indexes->end(); IF++)
+                    {
+                         if ((*IF)->FindInCache(*(VF.File().Cache())) == VF.File())
+                         {
+                                   cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
+                                        << (*IF)->Describe(true) << endl;
+                         }
+                    }
+               }
+            }
+         }
+      }
+
+      
+      SrcRecs.Restart();
+      pkgSrcRecords::Parser *SrcParser;
+      while ((SrcParser = SrcRecs.Find(*I,false)) != 0)
+      {
+         // Maybe support Release info here too eventually
+         cout << setw(10) << SrcParser->Package() << " | "
+              << setw(10) << SrcParser->Version() << " | "
+              << SrcParser->Index().Describe(true) << endl;
+      }
+   }
+
+   return true;
+}
+
                                                                        /*}}}*/
 // GenCaches - Call the main cache generator                           /*{{{*/
 // ---------------------------------------------------------------------
@@ -1235,21 +1711,26 @@ bool GenCaches(CommandLine &Cmd)
 /* */
 bool ShowHelp(CommandLine &Cmd)
 {
-   ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
-           COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
+   ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION,
+           COMMON_ARCH,__DATE__,__TIME__);
    
+   if (_config->FindB("version") == true)
+     return true;
+
    cout << 
     _("Usage: apt-cache [options] command\n"
-      "       apt-cache [options] add file1 [file1 ...]\n"
+      "       apt-cache [options] add file1 [file2 ...]\n"
       "       apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
+      "       apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
       "\n"
       "apt-cache is a low-level tool used to manipulate APT's binary\n"
       "cache files, and query information from them\n"
       "\n"
       "Commands:\n"
-      "   add - Add an package file to the source cache\n"
+      "   add - Add a package file to the source cache\n"
       "   gencaches - Build both the package and source cache\n"
       "   showpkg - Show some general information for a single package\n"
+      "   showsrc - Show source records\n"
       "   stats - Show some basic statistics\n"
       "   dump - Show the entire file in a terse form\n"
       "   dumpavail - Print an available file to stdout\n"
@@ -1257,8 +1738,10 @@ bool ShowHelp(CommandLine &Cmd)
       "   search - Search the package list for a regex pattern\n"
       "   show - Show a readable record for the package\n"
       "   depends - Show raw dependency information for a package\n"
+      "   rdepends - Show reverse dependency information for a package\n"
       "   pkgnames - List the names of all packages\n"
       "   dotty - Generate package graphs for GraphVis\n"
+      "   xvcg - Generate package graphs for xvcg\n"
       "   policy - Show policy settings\n"
       "\n"
       "Options:\n"
@@ -1268,7 +1751,7 @@ bool ShowHelp(CommandLine &Cmd)
       "  -q   Disable progress indicator.\n"
       "  -i   Show only important deps for the unmet command.\n"
       "  -c=? Read this configuration file\n"
-      "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+      "  -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
       "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
    return true;
 }
@@ -1295,11 +1778,12 @@ int main(int argc,const char *argv[])
       {'f',"full","APT::Cache::ShowFull",0},
       {'g',"generate","APT::Cache::Generate",0},
       {'a',"all-versions","APT::Cache::AllVersions",0},
-      {0,"names-only","APT::Cache::NamesOnly",0},
+      {'n',"names-only","APT::Cache::NamesOnly",0},
       {0,"all-names","APT::Cache::AllNames",0},
       {0,"recurse","APT::Cache::RecurseDepends",0},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
+      {0,"installed","APT::Cache::Installed",0},
       {0,0,0,0}};
    CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
                                     {"add",&DoAdd},
@@ -1313,14 +1797,21 @@ int main(int argc,const char *argv[])
                                     {"unmet",&UnMet},
                                     {"search",&Search},
                                     {"depends",&Depends},
+                                    {"rdepends",&RDepends},
                                     {"dotty",&Dotty},
+                                    {"xvcg",&XVcg},
                                     {"show",&ShowPackage},
                                     {"pkgnames",&ShowPkgNames},
                                     {"policy",&Policy},
+                                    {"madison",&Madison},
                                     {0,0}};
 
    CacheInitialize();
-   
+
+   // Set up gettext support
+   setlocale(LC_ALL,"");
+   textdomain(PACKAGE);
+
    // Parse the command line and initialize the package library
    CommandLine CmdL(Args,_config);
    if (pkgInitConfig(*_config) == false ||
@@ -1340,12 +1831,12 @@ int main(int argc,const char *argv[])
    }
    
    // Deal with stdout not being a tty
-   if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
+   if (isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
       _config->Set("quiet","1");
 
    if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
    { 
-      MMap *Map;
+      MMap *Map = 0;
       if (_config->FindB("APT::Cache::Generate",true) == false)
       {
         Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),