]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-cache.cc
Updated help text
[apt.git] / cmdline / apt-cache.cc
index 8dc56a72b5763a6502c32cbf3747e25fa771e4eb..5928676de8aa62dcb2b0a04f713cea912c51e7b2 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: apt-cache.cc,v 1.40 1999/10/18 04:15:25 jgg Exp $
+// $Id: apt-cache.cc,v 1.43 2000/05/12 04:00:59 jgg Exp $
 /* ######################################################################
    
    apt-cache - Manages the cache files
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/srcrecords.h>
+#include <apt-pkg/version.h>
 #include <config.h>
 
 #include <iostream.h>
 #include <unistd.h>
 #include <errno.h>
 #include <regex.h>
+#include <stdio.h>
                                                                        /*}}}*/
 
 pkgCache *GCache = 0;
@@ -433,6 +435,214 @@ bool Depends(CommandLine &CmdL)
       }
    }   
    
+   return true;
+}
+                                                                       /*}}}*/
+// Dotty - Generate a graph for Dotty                                  /*{{{*/
+// ---------------------------------------------------------------------
+/* Dotty is the graphvis program for generating graphs. It is a fairly
+   simple queuing algorithm that just writes dependencies and nodes. 
+   http://www.research.att.com/sw/tools/graphviz/ */
+bool Dotty(CommandLine &CmdL)
+{
+   pkgCache &Cache = *GCache;
+   bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
+   
+   /* Normal packages are boxes
+      Pure Provides are triangles
+      Mixed are diamonds
+      Hexagons are missing packages*/
+   const char *Shapes[] = {"hexagon","triangle","box","diamond"};
+   
+   /* 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
+   printf("digraph packages {\n");
+   printf("concentrate=true;\n");
+   printf("size=\"30,40\";\n");
+   
+   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;
+        
+        // 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 (pkgCheckDep(D.TargetVer(),I.VerStr(),D->CompareOp) == true)
+                 Hit = true;
+           }
+           
+           // Follow all provides
+           for (pkgCache::PrvIterator I = DPkg.ProvidesList(); 
+                     I.end() == false && Hit == false; I++)
+           {
+              if (pkgCheckDep(D.TargetVer(),I.ProvideVersion(),D->CompareOp) == false)
+                 Hit = true;
+           }
+           
+           // Only graph critical deps     
+           if (D.IsCritical() == true)
+           {
+              printf("\"%s\" -> \"%s\"",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)
+                 {
+                    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("[color=springgreen];\n");
+                 break;
+                 
+                 case pkgCache::Dep::PreDepends:
+                 printf("[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;
+      
+      // Orange box for early recursion stoppage
+      if (Show[Pkg->ID] == DoneNR)
+        printf("\"%s\" [color=orange,shape=%s];\n",Pkg.Name(),
+               Shapes[ShapeMap[Pkg->ID]]);
+      else
+        printf("\"%s\" [shape=%s];\n",Pkg.Name(),
+               Shapes[ShapeMap[Pkg->ID]]);
+   }
+   
+   printf("}\n");
    return true;
 }
                                                                        /*}}}*/
@@ -589,12 +799,58 @@ bool ShowPackage(CommandLine &CmdL)
       }
       
       // Find the proper version to use. We should probably use the DepCache.
-      pkgCache::VerIterator V = Cache.GetCandidateVer(Pkg);
-      if (V.end() == true || V.FileList().end() == true)
+      if (_config->FindB("APT::Cache::AllVersions","true") == true)
+      {
+        pkgCache::VerIterator V;
+        for (V = Pkg.VersionList(); V.end() == false; V++)
+        {
+           if (DisplayRecord(V) == false)
+              return false;
+        }
+      }
+      else
+      {
+        pkgCache::VerIterator V = Cache.GetCandidateVer(Pkg);
+        if (V.end() == true || V.FileList().end() == true)
+           continue;
+        if (DisplayRecord(V) == false)
+           return false;
+      }      
+   }
+   return true;
+}
+                                                                       /*}}}*/
+// ShowPkgNames - Show package names                                   /*{{{*/
+// ---------------------------------------------------------------------
+/* This does a prefix match on the first argument */
+bool ShowPkgNames(CommandLine &CmdL)
+{
+   pkgCache &Cache = *GCache;
+   pkgCache::PkgIterator I = Cache.PkgBegin();
+   bool All = _config->FindB("APT::Cache::AllNames","false");
+   
+   if (CmdL.FileList[1] != 0)
+   {
+      for (;I.end() != true; I++)
+      {
+        if (All == false && I->VersionList == 0)
+           continue;
+        
+        if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
+           cout << I.Name() << endl;
+      }
+
+      return true;
+   }
+   
+   // Show all pkgs
+   for (;I.end() != true; I++)
+   {
+      if (All == false && I->VersionList == 0)
         continue;
-      if (DisplayRecord(V) == false)
-        return false;
+      cout << I.Name() << endl;
    }
+   
    return true;
 }
                                                                        /*}}}*/
@@ -664,6 +920,8 @@ bool ShowHelp(CommandLine &Cmd)
    cout << "   search - Search the package list for a regex pattern" << endl;
    cout << "   show - Show a readable record for the package" << endl;
    cout << "   depends - Show raw dependency information for a package" << endl;
+   cout << "   pkgnames - List the names of all packages" << endl;
+   cout << "   dotty - Generate package graphs for GraphVis" << endl;
    cout << endl;
    cout << "Options:" << endl;
    cout << "  -h   This help text." << endl;
@@ -698,7 +956,9 @@ int main(int argc,const char *argv[])
       {'i',"important","APT::Cache::Important",0},
       {'f',"full","APT::Cache::ShowFull",0},
       {'g',"no-generate","APT::Cache::NoGenerate",0},
+      {'a',"all-versions","APT::Cache::AllVersions",0},
       {0,"names-only","APT::Cache::NamesOnly",0},
+      {0,"all-names","APT::Cache::AllNames",0},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
       {0,0,0,0}};
@@ -715,7 +975,9 @@ int main(int argc,const char *argv[])
                                     {"check",&Check},
                                     {"search",&Search},
                                     {"depends",&Depends},
+                                    {"dotty",&Dotty},
                                     {"show",&ShowPackage},
+                                    {"pkgnames",&ShowPkgNames},
                                     {0,0}};
 
    CacheInitialize();