|
|
|
// -*- mode: cpp; mode: fold -*-
|
|
|
|
// Description /*{{{*/
|
|
|
|
// $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz Exp $
|
|
|
|
/* ######################################################################
|
|
|
|
|
|
|
|
apt-cache - Manages the cache files
|
|
|
|
|
|
|
|
apt-cache provides some functions fo manipulating the cache files.
|
|
|
|
It uses the command line interface common to all the APT tools.
|
|
|
|
|
|
|
|
Returns 100 on failure, 0 on success.
|
|
|
|
|
|
|
|
##################################################################### */
|
|
|
|
/*}}}*/
|
|
|
|
// Include Files /*{{{*/
|
|
|
|
#include <apt-pkg/error.h>
|
|
|
|
#include <cassert>
|
|
|
|
#include <apt-pkg/pkgcachegen.h>
|
|
|
|
#include <apt-pkg/cachefile.h>
|
|
|
|
#include <apt-pkg/init.h>
|
|
|
|
#include <apt-pkg/progress.h>
|
|
|
|
#include <apt-pkg/sourcelist.h>
|
|
|
|
#include <apt-pkg/cmndline.h>
|
|
|
|
#include <apt-pkg/strutl.h>
|
|
|
|
#include <apt-pkg/pkgrecords.h>
|
|
|
|
#include <apt-pkg/srcrecords.h>
|
|
|
|
#include <apt-pkg/version.h>
|
|
|
|
#include <apt-pkg/policy.h>
|
|
|
|
#include <apt-pkg/tagfile.h>
|
|
|
|
#include <apt-pkg/algorithms.h>
|
|
|
|
#include <apt-pkg/sptr.h>
|
|
|
|
|
|
|
|
#include "cacheset.h"
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <apti18n.h>
|
|
|
|
|
|
|
|
#include <locale.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <regex.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <iomanip>
|
|
|
|
/*}}}*/
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
// LocalitySort - Sort a version list by package file locality /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* */
|
|
|
|
int LocalityCompare(const void *a, const void *b)
|
|
|
|
{
|
|
|
|
pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
|
|
|
|
pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
|
|
|
|
|
|
|
|
if (A == 0 && B == 0)
|
|
|
|
return 0;
|
|
|
|
if (A == 0)
|
|
|
|
return 1;
|
|
|
|
if (B == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (A->File == B->File)
|
|
|
|
return A->Offset - B->Offset;
|
|
|
|
return A->File - B->File;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LocalitySort(pkgCache::VerFile **begin,
|
|
|
|
unsigned long Count,size_t Size)
|
|
|
|
{
|
|
|
|
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 /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* */
|
|
|
|
bool ShowUnMet(pkgCache::VerIterator const &V, bool const &Important)
|
|
|
|
{
|
|
|
|
bool Header = false;
|
|
|
|
for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
|
|
|
|
{
|
|
|
|
// Collect or groups
|
|
|
|
pkgCache::DepIterator Start;
|
|
|
|
pkgCache::DepIterator End;
|
|
|
|
D.GlobOr(Start,End);
|
|
|
|
|
|
|
|
// Important deps only
|
|
|
|
if (Important == true)
|
|
|
|
if (End->Type != pkgCache::Dep::PreDepends &&
|
|
|
|
End->Type != pkgCache::Dep::Depends)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Skip conflicts and replaces
|
|
|
|
if (End->Type == pkgCache::Dep::DpkgBreaks ||
|
|
|
|
End->Type == pkgCache::Dep::Replaces ||
|
|
|
|
End->Type == pkgCache::Dep::Conflicts)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Verify the or group
|
|
|
|
bool OK = false;
|
|
|
|
pkgCache::DepIterator RealStart = Start;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
// See if this dep is Ok
|
|
|
|
pkgCache::Version **VList = Start.AllTargets();
|
|
|
|
if (*VList != 0)
|
|
|
|
{
|
|
|
|
OK = true;
|
|
|
|
delete [] VList;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
delete [] VList;
|
|
|
|
|
|
|
|
if (Start == End)
|
|
|
|
break;
|
|
|
|
Start++;
|
|
|
|
}
|
|
|
|
while (1);
|
|
|
|
|
|
|
|
// The group is OK
|
|
|
|
if (OK == true)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Oops, it failed..
|
|
|
|
if (Header == false)
|
|
|
|
ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
|
|
|
|
V.ParentPkg().FullName(true).c_str(),V.VerStr());
|
|
|
|
Header = true;
|
|
|
|
|
|
|
|
// Print out the dep type
|
|
|
|
cout << " " << End.DepType() << ": ";
|
|
|
|
|
|
|
|
// Show the group
|
|
|
|
Start = RealStart;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
cout << Start.TargetPkg().FullName(true);
|
|
|
|
if (Start.TargetVer() != 0)
|
|
|
|
cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
|
|
|
|
")";
|
|
|
|
if (Start == End)
|
|
|
|
break;
|
|
|
|
cout << " | ";
|
|
|
|
Start++;
|
|
|
|
}
|
|
|
|
while (1);
|
|
|
|
|
|
|
|
cout << endl;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool UnMet(CommandLine &CmdL)
|
|
|
|
{
|
|
|
|
bool const Important = _config->FindB("APT::Cache::Important",false);
|
|
|
|
|
|
|
|
pkgCacheFile CacheFile;
|
|
|
|
if (unlikely(CacheFile.GetPkgCache() == NULL))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (CmdL.FileSize() <= 1)
|
|
|
|
{
|
|
|
|
for (pkgCache::PkgIterator P = CacheFile.GetPkgCache()->PkgBegin(); P.end() == false; P++)
|
|
|
|
for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
|
|
|
|
if (ShowUnMet(V, Important) == false)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
APT::VersionSet verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
|
|
|
|
for (APT::VersionSet::iterator V = verset.begin(); V != verset.end(); ++V)
|
|
|
|
if (ShowUnMet(V, Important) == false)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
// DumpPackage - Show a dump of a package record /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* */
|
|
|
|
bool DumpPackage(CommandLine &CmdL)
|
|
|
|
{
|
|
|
|
pkgCacheFile CacheFile;
|
|
|
|
APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
|
|
|
|
|
|
|
|
for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
|
|
|
|
{
|
|
|
|
cout << "Package: " << Pkg.FullName(true) << endl;
|
|
|
|
cout << "Versions: " << endl;
|
|
|
|
for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
|
|
|
|
{
|
|
|
|
cout << Cur.VerStr();
|
|
|
|
for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
|
|
|
|
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 << endl;
|
|
|
|
|
|
|
|
cout << "Reverse Depends: " << endl;
|
|
|
|
for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
|
|
|
|
{
|
|
|
|
cout << " " << D.ParentPkg().FullName(true) << ',' << D.TargetPkg().FullName(true);
|
|
|
|
if (D->Version != 0)
|
|
|
|
cout << ' ' << DeNull(D.TargetVer()) << endl;
|
|
|
|
else
|
|
|
|
cout << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
cout << "Dependencies: " << endl;
|
|
|
|
for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
|
|
|
|
{
|
|
|
|
cout << Cur.VerStr() << " - ";
|
|
|
|
for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
|
|
|
|
cout << Dep.TargetPkg().FullName(true) << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
|
|
|
|
cout << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
cout << "Provides: " << endl;
|
|
|
|
for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
|
|
|
|
{
|
|
|
|
cout << Cur.VerStr() << " - ";
|
|
|
|
for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
|
|
|
|
cout << Prv.ParentPkg().FullName(true) << " ";
|
|
|
|
cout << endl;
|
|
|
|
}
|
|
|
|
cout << "Reverse Provides: " << endl;
|
|
|
|
for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
|
|
|
|
cout << Prv.OwnerPkg().FullName(true) << " " << Prv.OwnerVer().VerStr() << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
// Stats - Dump some nice statistics /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* */
|
|
|
|
bool Stats(CommandLine &Cmd)
|
|
|
|
{
|
|
|
|
pkgCacheFile CacheFile;
|
|
|
|
pkgCache *Cache = CacheFile.GetPkgCache();
|
|
|
|
if (unlikely(Cache == NULL))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
cout << _("Total package names: ") << Cache->Head().GroupCount << " (" <<
|
|
|
|
SizeToStr(Cache->Head().GroupCount*Cache->Head().GroupSz) << ')' << endl
|
|
|
|
<< _("Total package structures: ") << Cache->Head().PackageCount << " (" <<
|
|
|
|
SizeToStr(Cache->Head().PackageCount*Cache->Head().PackageSz) << ')' << endl;
|
|
|
|
|
|
|
|
int Normal = 0;
|
|
|
|
int Virtual = 0;
|
|
|
|
int NVirt = 0;
|
|
|
|
int DVirt = 0;
|
|
|
|
int Missing = 0;
|
|
|
|
pkgCache::PkgIterator I = Cache->PkgBegin();
|
|
|
|
for (;I.end() != true; I++)
|
|
|
|
{
|
|
|
|
if (I->VersionList != 0 && I->ProvidesList == 0)
|
|
|
|
{
|
|
|
|
Normal++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (I->VersionList != 0 && I->ProvidesList != 0)
|
|
|
|
{
|
|
|
|
NVirt++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (I->VersionList == 0 && I->ProvidesList != 0)
|
|
|
|
{
|
|
|
|
// Only 1 provides
|
|
|
|
if (I.ProvidesList()->NextProvides == 0)
|
|
|
|
{
|
|
|
|
DVirt++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Virtual++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (I->VersionList == 0 && I->ProvidesList == 0)
|
|
|
|
{
|
|
|
|
Missing++;
|
|
|
|
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 << _(" Missing: ") << Missing << endl;
|
|
|
|
|
|
|
|
cout << _("Total distinct versions: ") << Cache->Head().VersionCount << " (" <<
|
|
|
|
SizeToStr(Cache->Head().VersionCount*Cache->Head().VersionSz) << ')' << endl;
|
|
|
|
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 << " (" <<
|
|
|
|
SizeToStr(Cache->Head().VerFileCount*Cache->Head().VerFileSz) << ')' << endl;
|
|
|
|
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
|
|
|
|
unsigned long Size = 0;
|
|
|
|
unsigned long Count = 0;
|
|
|
|
for (pkgCache::StringItem *I = Cache->StringItemP + Cache->Head().StringList;
|
|
|
|
I!= Cache->StringItemP; I = Cache->StringItemP + I->NextItem)
|
|
|
|
{
|
|
|
|
Count++;
|
|
|
|
Size += strlen(Cache->StrP + I->String) + 1;
|
|
|
|
}
|
|
|
|
cout << _("Total globbed strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
|
|
|
|
|
|
|
|
unsigned long DepVerSize = 0;
|
|
|
|
for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
|
|
|
|
{
|
|
|
|
for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
|
|
|
|
{
|
|
|
|
for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
|
|
|
|
{
|
|
|
|
if (D->Version != 0)
|
|
|
|
DepVerSize += strlen(D.TargetVer()) + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
|
|
|
|
unsigned long Total = 0;
|
|
|
|
Total = Slack + Size + Cache->Head().DependsCount*Cache->Head().DependencySz +
|
|
|
|
Cache->Head().VersionCount*Cache->Head().VersionSz +
|
|
|
|
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;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
// Dump - show everything /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* This is worthless except fer debugging things */
|
|
|
|
bool Dump(CommandLine &Cmd)
|
|
|
|
{
|
|
|
|
pkgCacheFile CacheFile;
|
|
|
|
pkgCache *Cache = CacheFile.GetPkgCache();
|
|
|
|
if (unlikely(Cache == NULL))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
cout << "Using Versioning System: " << Cache->VS->Label << endl;
|
|
|
|
|
|
|
|
for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
|
|
|
|
{
|
|
|
|
cout << "Package: " << P.FullName(true) << endl;
|
|
|
|
for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
|
|
|
|
{
|
|
|
|
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().FullName(true) << ' ' <<
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; F++)
|
|
|
|
{
|
|
|
|
cout << "File: " << F.FileName() << endl;
|
|
|
|
cout << " Type: " << F.IndexType() << endl;
|
|
|
|
cout << " Size: " << F->Size << endl;
|
|
|
|
cout << " ID: " << F->ID << endl;
|
|
|
|
cout << " Flags: " << F->Flags << endl;
|
|
|
|
cout << " Time: " << TimeRFC1123(F->mtime) << 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;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
// DumpAvail - Print out the available list /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* This is needed to make dpkg --merge happy.. I spent a bit of time to
|
|
|
|
make this run really fast, perhaps I went a little overboard.. */
|
|
|
|
bool DumpAvail(CommandLine &Cmd)
|
|
|
|
{
|
|
|
|
pkgCacheFile CacheFile;
|
|
|
|
pkgCache *Cache = CacheFile.GetPkgCache();
|
|
|
|
if (unlikely(Cache == NULL || CacheFile.BuildPolicy() == false))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
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++)
|
|
|
|
{
|
|
|
|
if (P->VersionList == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Find the proper version to use. If the policy says there are no
|
|
|
|
possible selections we return the installed version, if available..
|
|
|
|
This prevents dselect from making it obsolete. */
|
|
|
|
pkgCache::VerIterator V = CacheFile.GetPolicy()->GetCandidateVer(P);
|
|
|
|
if (V.end() == true)
|
|
|
|
{
|
|
|
|
if (P->CurrentVer == 0)
|
|
|
|
continue;
|
|
|
|
V = P.CurrentVer();
|
|
|
|
}
|
|
|
|
|
|
|
|
pkgCache::VerFileIterator VF = V.FileList();
|
|
|
|
for (; VF.end() == false ; VF++)
|
|
|
|
if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Okay, here we have a bit of a problem.. The policy has selected the
|
|
|
|
currently installed package - however it only exists in the
|
|
|
|
status file.. We need to write out something or dselect will mark
|
|
|
|
the package as obsolete! Thus we emit the status file entry, but
|
|
|
|
below we remove the status line to make it valid for the
|
|
|
|
available file. However! We only do this if their do exist *any*
|
|
|
|
non-source versions of the package - that way the dselect obsolete
|
|
|
|
handling works OK. */
|
|
|
|
if (VF.end() == true)
|
|
|
|
{
|
|
|
|
for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; Cur++)
|
|
|
|
{
|
|
|
|
for (VF = Cur.FileList(); VF.end() == false; VF++)
|
|
|
|
{
|
|
|
|
if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
|
|
|
|
{
|
|
|
|
VF = V.FileList();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VF.end() == false)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VFList[P->ID] = VF;
|
|
|
|
}
|
|
|
|
|
|
|
|
LocalitySort(VFList,Count,sizeof(*VFList));
|
|
|
|
|
|
|
|
// Iterate over all the package files and write them out.
|
|
|
|
char *Buffer = new char[Cache->HeaderP->MaxVerFileSize+10];
|
|
|
|
for (pkgCache::VerFile **J = VFList; *J != 0;)
|
|
|
|
{
|
|
|
|
pkgCache::PkgFileIterator File(*Cache,(*J)->File + Cache->PkgFileP);
|
|
|
|
if (File.IsOk() == false)
|
|
|
|
{
|
|
|
|
_error->Error(_("Package file %s is out of sync."),File.FileName());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
FileFd PkgF(File.FileName(),FileFd::ReadOnly);
|
|
|
|
if (_error->PendingError() == true)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Write all of the records from this package file, since we
|
|
|
|
already did locality sorting we can now just seek through the
|
|
|
|
file in read order. We apply 1 more optimization here, since often
|
|
|
|
there will be < 1 byte gaps between records (for the \n) we read that
|
|
|
|
into the next buffer and offset a bit.. */
|
|
|
|
unsigned long Pos = 0;
|
|
|
|
for (; *J != 0; J++)
|
|
|
|
{
|
|
|
|
if ((*J)->File + Cache->PkgFileP != File)
|
|
|
|
break;
|
|
|
|
|
|
|
|
const pkgCache::VerFile &VF = **J;
|
|
|
|
|
|
|
|
// Read the record and then write it out again.
|
|
|
|
unsigned long Jitter = VF.Offset - Pos;
|
|
|
|
if (Jitter > 8)
|
|
|
|
{
|
|
|
|
if (PkgF.Seek(VF.Offset) == false)
|
|
|
|
break;
|
|
|
|
Jitter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
|
|
|
|
break;
|
|
|
|
Buffer[VF.Size + Jitter] = '\n';
|
|
|
|
|
|
|
|
// See above..
|
|
|
|
if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
|
|
|
|
{
|
|
|
|
pkgTagSection Tags;
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
_error->Error("Internal Error, Unable to parse a package record");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fputc('\n',stdout);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (fwrite(Buffer+Jitter,VF.Size+1,1,stdout) != 1)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Pos = VF.Offset + VF.Size;
|
|
|
|
}
|
|
|
|
|
|
|
|
fflush(stdout);
|
|
|
|
if (_error->PendingError() == true)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete [] Buffer;
|
|
|
|
delete [] VFList;
|
|
|
|
return !_error->PendingError();
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
// Depends - Print out a dependency tree /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* */
|
|
|
|
bool Depends(CommandLine &CmdL)
|
|
|
|
{
|
|
|
|
pkgCacheFile CacheFile;
|
|
|
|
pkgCache *Cache = CacheFile.GetPkgCache();
|
|
|
|
if (unlikely(Cache == NULL))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
SPtrArray<unsigned> Colours = new unsigned[Cache->Head().PackageCount];
|
|
|
|
memset(Colours,0,sizeof(*Colours)*Cache->Head().PackageCount);
|
|
|
|
|
|
|
|
APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
|
|
|
|
for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
|
|
|
|
Colours[Pkg->ID] = 1;
|
|
|
|
|
|
|
|
bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
|
|
|
|
bool Installed = _config->FindB("APT::Cache::Installed",false);
|
|
|
|
bool Important = _config->FindB("APT::Cache::Important",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.FullName(true) << '>' << endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
cout << Pkg.FullName(true) << endl;
|
|
|
|
|
|
|
|
for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
|
|
|
|
{
|
|
|
|
// Important deps only
|
|
|
|
if (Important == true)
|
|
|
|
if (D->Type != pkgCache::Dep::PreDepends &&
|
|
|
|
D->Type != pkgCache::Dep::Depends)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pkgCache::PkgIterator Trg = D.TargetPkg();
|
|
|
|
|
|
|
|
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.FullName(true) << ">" << endl;
|
|
|
|
else
|
|
|
|
cout << D.DepType() << ": " << Trg.FullName(true) << endl;
|
|
|
|
|
|
|
|
if (Recurse == true)
|
|
|
|
Colours[D.TargetPkg()->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().FullName(true) << endl;
|
|
|
|
|
|
|
|
if (Recurse == true)
|
|
|
|
Colours[D.ParentPkg()->ID]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (DidSomething == true);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
/*}}}*/
|
|
|
|
// RDepends - Print out a reverse dependency tree - mbc /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* */
|
|
|
|
bool RDepends(CommandLine &CmdL)
|
|
|
|
{
|
|
|
|
pkgCacheFile CacheFile;
|
|
|
|
pkgCache *Cache = CacheFile.GetPkgCache();
|
|
|
|
if (unlikely(Cache == NULL))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
SPtrArray<unsigned> Colours = new unsigned[Cache->Head().PackageCount];
|
|
|
|
memset(Colours,0,sizeof(*Colours)*Cache->Head().PackageCount);
|
|
|
|
|
|
|
|
APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
|
|
|
|
for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
|
|
|
|
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.FullName(true) << '>' << endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
cout << Pkg.FullName(true) << endl;
|
|
|
|
|
|
|
|
cout << "Reverse Depends:" << endl;
|
|
|
|
for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() == false; D++)
|
|
|
|
{
|
|
|
|
// Show the package
|
|
|
|
pkgCache |