// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: apt-cache.cc,v 1.46 2001/03/07 04:25:35 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;
// LocalitySort - Sort a version list by package file locality /*{{{*/
// ---------------------------------------------------------------------
{
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 /*{{{*/
// ---------------------------------------------------------------------
{
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;
}
{
cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name();
if (D->Version != 0)
- cout << ' ' << D.TargetVer() << endl;
+ cout << ' ' << DeNull(D.TargetVer()) << endl;
else
cout << endl;
}
{
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;
}
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;
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
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++)
}
}
}
- 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 +
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;
}
cout << " Version: " << V.VerStr() << endl;
cout << " File: " << V.FileList().File().FileName() << endl;
for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
- cout << " Depends: " << D.TargetPkg().Name() << ' ' << D.TargetVer() << endl;
+ 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;
+ }
}
}
cout << " ID: " << F->ID << endl;
cout << " Flags: " << F->Flags << endl;
cout << " Time: " << TimeRFC1123(F->mtime) << endl;
- cout << " Archive: " << F.Archive() << endl;
- cout << " Component: " << F.Component() << endl;
- cout << " Version: " << F.Version() << endl;
- cout << " Origin: " << F.Origin() << endl;
- cout << " Site: " << F.Site() << endl;
- cout << " Label: " << F.Label() << endl;
- cout << " Architecture: " << F.Architecture() << endl;
+ cout << " Archive: " << DeNull(F.Archive()) << endl;
+ cout << " Component: " << DeNull(F.Component()) << endl;
+ cout << " Version: " << DeNull(F.Version()) << endl;
+ cout << " Origin: " << DeNull(F.Origin()) << endl;
+ cout << " Site: " << DeNull(F.Site()) << endl;
+ cout << " Label: " << DeNull(F.Label()) << endl;
+ cout << " Architecture: " << DeNull(F.Architecture()) << endl;
}
return true;
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++)
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];
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)
}
bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
+ bool Installed = _config->FindB("APT::Cache::Installed",false);
bool DidSomething;
do
{
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 << " ";
+
+ // 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]++;
+ if (Recurse == true)
+ Colours[D.TargetPkg()->ID]++;
+
+ }
// Display all solutions
SPtrArray<pkgCache::Version *> List = D.AllTargets();
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();
+ 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;
+}
+
/*}}}*/
+
+
+// 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
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;
// 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;
};
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)
}
}
- delete [] VFList;
+ delete [] DFList;
for (unsigned I = 0; I != NumPatterns; I++)
regfree(&Patterns[I]);
if (ferror(stdout))
{
pkgCache &Cache = *GCache;
pkgDepCache::Policy Plcy;
+
+ unsigned found = 0;
for (const char **I = CmdL.FileList + 1; *I != 0; I++)
{
continue;
}
+ ++found;
+
// Find the proper version to use.
if (_config->FindB("APT::Cache::AllVersions","true") == true)
{
return false;
}
}
- return true;
+
+ if (found > 0)
+ return true;
+ return _error->Error(_("No packages found"));
}
/*}}}*/
// ShowPkgNames - Show package names /*{{{*/
}
return true;
}
+ /*}}}*/
+// Policy - Show the results of the preferences file /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool Policy(CommandLine &CmdL)
+{
+ if (SrcList == 0)
+ return _error->Error("Generate must be enabled for this function");
+
+ pkgCache &Cache = *GCache;
+ pkgPolicy Plcy(&Cache);
+ if (ReadPinFile(Plcy) == false)
+ return false;
+
+ // Print out all of the package files
+ if (CmdL.FileList[1] == 0)
+ {
+ 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
+ pkgIndexFile *Indx;
+ if (SrcList->FindIndex(F,Indx) == false &&
+ _system->FindIndex(F,Indx) == false)
+ return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
+ printf(_("%4i %s\n"),
+ Plcy.GetPriority(F),Indx->Describe(true).c_str());
+
+ // Print the reference information for the package
+ string Str = F.RelStr();
+ if (Str.empty() == false)
+ printf(" release %s\n",F.RelStr().c_str());
+ if (F.Site() != 0 && F.Site()[0] != 0)
+ printf(" origin %s\n",F.Site());
+ }
+
+ // Show any packages have explicit pins
+ cout << _("Pinned packages:") << endl;
+ pkgCache::PkgIterator I = Cache.PkgBegin();
+ for (;I.end() != true; I++)
+ {
+ if (Plcy.GetPriority(I) == 0)
+ continue;
+
+ // Print the package name and the version we are forcing to
+ cout << " " << I.Name() << " -> ";
+
+ pkgCache::VerIterator V = Plcy.GetMatch(I);
+ if (V.end() == true)
+ cout << _("(not found)") << endl;
+ else
+ cout << V.VerStr() << endl;
+ }
+
+ return true;
+ }
+
+ // Print out detailed information for each package
+ 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;
+ }
+
+ cout << Pkg.Name() << ":" << endl;
+
+ // Installed version
+ cout << _(" Installed: ");
+ if (Pkg->CurrentVer == 0)
+ cout << _("(none)") << endl;
+ else
+ cout << Pkg.CurrentVer().VerStr() << endl;
+
+ // Candidate Version
+ cout << _(" Candidate: ");
+ pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
+ if (V.end() == true)
+ cout << _("(none)") << endl;
+ else
+ cout << V.VerStr() << endl;
+
+ // Pinned version
+ if (Plcy.GetPriority(Pkg) != 0)
+ {
+ cout << _(" Package pin: ");
+ V = Plcy.GetMatch(Pkg);
+ if (V.end() == true)
+ cout << _("(not found)") << endl;
+ else
+ cout << V.VerStr() << endl;
+ }
+
+ // Show the priority tables
+ cout << _(" Version table:") << endl;
+ for (V = Pkg.VersionList(); V.end() == false; V++)
+ {
+ if (Pkg.CurrentVer() == V)
+ cout << " *** " << V.VerStr();
+ else
+ cout << " " << V.VerStr();
+ cout << " " << Plcy.GetPriority(Pkg) << endl;
+ for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
+ {
+ // Locate the associated index files so we can derive a description
+ pkgIndexFile *Indx;
+ if (SrcList->FindIndex(VF.File(),Indx) == false &&
+ _system->FindIndex(VF.File(),Indx) == false)
+ return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
+ printf(_(" %4i %s\n"),Plcy.GetPriority(VF.File()),
+ Indx->Describe(true).c_str());
+ }
+ }
+ }
+
+ 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 /*{{{*/
// ---------------------------------------------------------------------
ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
COMMON_OS,COMMON_CPU,__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"
" 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"
" -h This help text.\n"
" -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;
}
{'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},
{"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 ||
}
// 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"),
else
{
// Open the cache file
- pkgSourceList List;
- List.ReadMainList();
+ SrcList = new pkgSourceList;
+ SrcList->ReadMainList();
// Generate it and map it
OpProgress Prog;
- pkgMakeStatusCache(List,Prog,&Map,true);
+ pkgMakeStatusCache(*SrcList,Prog,&Map,true);
}
if (_error->PendingError() == false)