summaryrefslogtreecommitdiff
path: root/cmdline
diff options
context:
space:
mode:
authorArch Librarian <arch@canonical.com>2004-09-20 17:01:14 +0000
committerArch Librarian <arch@canonical.com>2004-09-20 17:01:14 +0000
commitfff4b7f30be7fece23ecf8cead675fad9f830eb1 (patch)
tree98095ddc1190d5761f239d5bbc420a5c3ad2e534 /cmdline
parent9975c27866fd2f7b9a7f5ec44b5ca5ee70f947b2 (diff)
Add a vcg command to apt-cache, similiar to dotty.
Author: doogie Date: 2003-04-27 01:32:48 GMT Add a vcg command to apt-cache, similiar to dotty.
Diffstat (limited to 'cmdline')
-rw-r--r--cmdline/apt-cache.cc223
1 files changed, 222 insertions, 1 deletions
diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc
index 875b3cf8a..326bef1b8 100644
--- a/cmdline/apt-cache.cc
+++ b/cmdline/apt-cache.cc
@@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: apt-cache.cc,v 1.61 2003/02/10 01:40:58 doogie Exp $
+// $Id: apt-cache.cc,v 1.62 2003/04/27 01:32:48 doogie Exp $
/* ######################################################################
apt-cache - Manages the cache files
@@ -588,6 +588,225 @@ 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::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::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
@@ -1281,6 +1500,7 @@ bool ShowHelp(CommandLine &Cmd)
" depends - Show raw 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"
@@ -1336,6 +1556,7 @@ int main(int argc,const char *argv[])
{"search",&Search},
{"depends",&Depends},
{"dotty",&Dotty},
+ {"xvcg",&XVcg},
{"show",&ShowPackage},
{"pkgnames",&ShowPkgNames},
{"policy",&Policy},