diff options
-rw-r--r-- | cmdline/apt-cache.cc | 223 | ||||
-rw-r--r-- | debian/changelog | 1 |
2 files changed, 223 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}, diff --git a/debian/changelog b/debian/changelog index 963674d65..98725d645 100644 --- a/debian/changelog +++ b/debian/changelog @@ -107,6 +107,7 @@ apt (0.5.4.9) unstable; urgency=low * Update es.po. Closes: #183111. * Add pt_BR translation of apt_preferences(5). Also, build fr manpages. Closes: #183904. + * Add a vcg command to apt-cache, similiar to dotty. Closes: #150512. -- Adam Heath <doogie@debian.org> Sun, 02 Feb 2003 02:54:45 -0600 |