Browse Source

Dotty

Author: jgg
Date: 2000-05-12 04:00:59 GMT
Dotty
debian/1.8.y
Arch Librarian 18 years ago
parent
commit
3e94da1bf2
  1. 214
      cmdline/apt-cache.cc
  2. 19
      doc/apt-cache.8.yo

214
cmdline/apt-cache.cc

@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: apt-cache.cc,v 1.42 1999/12/09 07:32:45 jgg Exp $
// $Id: apt-cache.cc,v 1.43 2000/05/12 04:00:59 jgg Exp $
/* ######################################################################
apt-cache - Manages the cache files
@ -25,12 +25,14 @@
#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;
}
/*}}}*/
@ -711,6 +921,7 @@ bool ShowHelp(CommandLine &Cmd)
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;
@ -764,6 +975,7 @@ int main(int argc,const char *argv[])
{"check",&Check},
{"search",&Search},
{"depends",&Depends},
{"dotty",&Dotty},
{"show",&ShowPackage},
{"pkgnames",&ShowPkgNames},
{0,0}};

19
doc/apt-cache.8.yo

@ -24,7 +24,8 @@ itemize(
it() show
it() showpkg
it() depends
it() pkgnames
it() pkgnames
it() dotty
)
Unless the -h, or --help option is given one of the above commands
@ -166,6 +167,22 @@ argument is a prefix match to filter the name list. The output is suitable
for use in a shell tab complete function and the output is generated extremly
quickly. This command is best used with the bf(--no-generate) option.
dit(bf(dotty))
bf(dotty) Takes a list of packages on the command line and gernerates output
suitable for use by dotty from the GraphVis
(http://www.research.att.com/sw/tools/graphviz/) package. The result will be
a set of nodes and edges representing the relationships between the
packages. By default the given packages will trace out all dependent packages
which can produce a very large graph. This can be turned off by setting the
APT::Cache::GivenOnly option.
The resulting nodes will have several shapse, normal packages are boxes,
pure provides are triangles, mixed provides are diamonds,
hexagons are missing packages. Orange boxes mean recursion was stopped
[leaf packages], blue lines are prre-depends, green lines are conflicts.
Caution, dotty cannot graph larger sets of packages.
enddit()
manpageoptions()

Loading…
Cancel
Save