]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
link DependencyData structs together
[apt.git] / cmdline / apt-cache.cc
CommitLineData
1164783d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
ea7f6363 3// $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz Exp $
1164783d
AL
4/* ######################################################################
5
e1b74f61 6 apt-cache - Manages the cache files
1164783d 7
e1b74f61 8 apt-cache provides some functions fo manipulating the cache files.
b2e465d6 9 It uses the command line interface common to all the APT tools.
1164783d
AL
10
11 Returns 100 on failure, 0 on success.
12
13 ##################################################################### */
14 /*}}}*/
15// Include Files /*{{{*/
ea542140
DK
16#include<config.h>
17
453b82a3 18#include <apt-pkg/algorithms.h>
6007c1d4 19#include <apt-pkg/cachefile.h>
8fde7239 20#include <apt-pkg/cacheset.h>
08e8f724 21#include <apt-pkg/cmndline.h>
453b82a3 22#include <apt-pkg/error.h>
472ff00e 23#include <apt-pkg/fileutl.h>
453b82a3
DK
24#include <apt-pkg/indexfile.h>
25#include <apt-pkg/init.h>
26#include <apt-pkg/metaindex.h>
9dbb421f 27#include <apt-pkg/pkgrecords.h>
453b82a3 28#include <apt-pkg/pkgsystem.h>
b2e465d6 29#include <apt-pkg/policy.h>
453b82a3
DK
30#include <apt-pkg/progress.h>
31#include <apt-pkg/sourcelist.h>
b2e465d6 32#include <apt-pkg/sptr.h>
453b82a3
DK
33#include <apt-pkg/srcrecords.h>
34#include <apt-pkg/strutl.h>
35#include <apt-pkg/tagfile.h>
36#include <apt-pkg/version.h>
37#include <apt-pkg/cacheiterators.h>
38#include <apt-pkg/configuration.h>
39#include <apt-pkg/depcache.h>
40#include <apt-pkg/macros.h>
41#include <apt-pkg/mmap.h>
42#include <apt-pkg/pkgcache.h>
31367812 43
b9179170 44#include <apt-private/private-cacheset.h>
453b82a3 45#include <apt-private/private-cmndline.h>
b9179170 46
9dbb421f 47#include <regex.h>
453b82a3 48#include <stddef.h>
3e94da1b 49#include <stdio.h>
453b82a3
DK
50#include <stdlib.h>
51#include <unistd.h>
472ff00e 52#include <algorithm>
453b82a3
DK
53#include <cstring>
54#include <iomanip>
55#include <iostream>
56#include <list>
57#include <map>
58#include <set>
59#include <string>
60#include <vector>
ea542140
DK
61
62#include <apti18n.h>
1164783d
AL
63 /*}}}*/
64
8f312f45
AL
65using namespace std;
66
b2e465d6
AL
67// LocalitySort - Sort a version list by package file locality /*{{{*/
68// ---------------------------------------------------------------------
69/* */
c3ccac92 70static int LocalityCompare(const void *a, const void *b)
b2e465d6
AL
71{
72 pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
73 pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
74
75 if (A == 0 && B == 0)
76 return 0;
77 if (A == 0)
78 return 1;
79 if (B == 0)
80 return -1;
81
82 if (A->File == B->File)
83 return A->Offset - B->Offset;
84 return A->File - B->File;
85}
86
c3ccac92 87static void LocalitySort(pkgCache::VerFile **begin,
b2e465d6
AL
88 unsigned long Count,size_t Size)
89{
90 qsort(begin,Count,Size,LocalityCompare);
91}
a52f938b 92
c3ccac92 93static void LocalitySort(pkgCache::DescFile **begin,
a52f938b
OS
94 unsigned long Count,size_t Size)
95{
96 qsort(begin,Count,Size,LocalityCompare);
97}
b2e465d6 98 /*}}}*/
cc718e9a
AL
99// UnMet - Show unmet dependencies /*{{{*/
100// ---------------------------------------------------------------------
101/* */
c3ccac92 102static bool ShowUnMet(pkgCache::VerIterator const &V, bool const Important)
cc718e9a 103{
cc718e9a 104 bool Header = false;
018f1533 105 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
cc718e9a
AL
106 {
107 // Collect or groups
108 pkgCache::DepIterator Start;
109 pkgCache::DepIterator End;
110 D.GlobOr(Start,End);
cc718e9a 111
018f1533
AL
112 // Important deps only
113 if (Important == true)
114 if (End->Type != pkgCache::Dep::PreDepends &&
7146a53c 115 End->Type != pkgCache::Dep::Depends)
018f1533 116 continue;
6ebaae9a
DK
117
118 // Skip conflicts and replaces
081c9d44 119 if (End.IsNegative() == true || End->Type == pkgCache::Dep::Replaces)
6ebaae9a
DK
120 continue;
121
cc718e9a
AL
122 // Verify the or group
123 bool OK = false;
124 pkgCache::DepIterator RealStart = Start;
125 do
126 {
127 // See if this dep is Ok
128 pkgCache::Version **VList = Start.AllTargets();
129 if (*VList != 0)
130 {
131 OK = true;
132 delete [] VList;
133 break;
134 }
135 delete [] VList;
081c9d44 136
cc718e9a
AL
137 if (Start == End)
138 break;
f7f0d6c7 139 ++Start;
cc718e9a
AL
140 }
141 while (1);
142
143 // The group is OK
144 if (OK == true)
145 continue;
146
147 // Oops, it failed..
148 if (Header == false)
b2e465d6 149 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
6ebaae9a 150 V.ParentPkg().FullName(true).c_str(),V.VerStr());
cc718e9a
AL
151 Header = true;
152
153 // Print out the dep type
154 cout << " " << End.DepType() << ": ";
155
156 // Show the group
157 Start = RealStart;
158 do
159 {
75ce2062 160 cout << Start.TargetPkg().FullName(true);
cc718e9a
AL
161 if (Start.TargetVer() != 0)
162 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
163 ")";
164 if (Start == End)
165 break;
166 cout << " | ";
f7f0d6c7 167 ++Start;
cc718e9a
AL
168 }
169 while (1);
170
171 cout << endl;
6ebaae9a
DK
172 }
173 return true;
174}
c3ccac92 175static bool UnMet(CommandLine &CmdL)
6ebaae9a
DK
176{
177 bool const Important = _config->FindB("APT::Cache::Important",false);
178
179 pkgCacheFile CacheFile;
180 if (unlikely(CacheFile.GetPkgCache() == NULL))
181 return false;
182
183 if (CmdL.FileSize() <= 1)
184 {
f7f0d6c7 185 for (pkgCache::PkgIterator P = CacheFile.GetPkgCache()->PkgBegin(); P.end() == false; ++P)
6ebaae9a
DK
186 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
187 if (ShowUnMet(V, Important) == false)
188 return false;
189 }
190 else
191 {
65f81081 192 CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
c4cca791 193 APT::VersionList verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1,
e6f0c9bc 194 APT::CacheSetHelper::CANDIDATE, helper);
c4cca791 195 for (APT::VersionList::iterator V = verset.begin(); V != verset.end(); ++V)
6ebaae9a
DK
196 if (ShowUnMet(V, Important) == false)
197 return false;
198 }
cc718e9a
AL
199 return true;
200}
201 /*}}}*/
1164783d
AL
202// DumpPackage - Show a dump of a package record /*{{{*/
203// ---------------------------------------------------------------------
204/* */
c3ccac92 205static bool DumpPackage(CommandLine &CmdL)
d9eb210e
DK
206{
207 pkgCacheFile CacheFile;
cd7bbc47 208 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
c4cca791 209 APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
1164783d 210
c4cca791 211 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
78c32596 212 {
75ce2062 213 cout << "Package: " << Pkg.FullName(true) << endl;
b2e465d6 214 cout << "Versions: " << endl;
f7f0d6c7 215 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
03e39e59
AL
216 {
217 cout << Cur.VerStr();
f7f0d6c7 218 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; ++Vf)
a52f938b
OS
219 cout << " (" << Vf.File().FileName() << ")";
220 cout << endl;
f7f0d6c7 221 for (pkgCache::DescIterator D = Cur.DescriptionList(); D.end() == false; ++D)
a52f938b
OS
222 {
223 cout << " Description Language: " << D.LanguageCode() << endl
224 << " File: " << D.FileList().File().FileName() << endl
225 << " MD5: " << D.md5() << endl;
226 }
b2e465d6 227 cout << endl;
03e39e59
AL
228 }
229
1164783d
AL
230 cout << endl;
231
232 cout << "Reverse Depends: " << endl;
f7f0d6c7 233 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; ++D)
b2e465d6 234 {
75ce2062 235 cout << " " << D.ParentPkg().FullName(true) << ',' << D.TargetPkg().FullName(true);
b2e465d6 236 if (D->Version != 0)
b1b663d1 237 cout << ' ' << DeNull(D.TargetVer()) << endl;
b2e465d6
AL
238 else
239 cout << endl;
240 }
241
1164783d 242 cout << "Dependencies: " << endl;
f7f0d6c7 243 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
1164783d
AL
244 {
245 cout << Cur.VerStr() << " - ";
f7f0d6c7 246 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; ++Dep)
75ce2062 247 cout << Dep.TargetPkg().FullName(true) << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
1164783d
AL
248 cout << endl;
249 }
250
251 cout << "Provides: " << endl;
f7f0d6c7 252 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
1164783d
AL
253 {
254 cout << Cur.VerStr() << " - ";
f7f0d6c7 255 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; ++Prv)
75ce2062 256 cout << Prv.ParentPkg().FullName(true) << " ";
1164783d 257 cout << endl;
8efa2a3b
AL
258 }
259 cout << "Reverse Provides: " << endl;
f7f0d6c7 260 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; ++Prv)
75ce2062 261 cout << Prv.OwnerPkg().FullName(true) << " " << Prv.OwnerVer().VerStr() << endl;
1164783d
AL
262 }
263
264 return true;
265}
266 /*}}}*/
637c3b23
MV
267// ShowHashTableStats - Show stats about a hashtable /*{{{*/
268// ---------------------------------------------------------------------
269/* */
32ab4bd0
DK
270static map_pointer_t PackageNext(pkgCache::Package const * const P) { return P->NextPackage; }
271static map_pointer_t GroupNext(pkgCache::Group const * const G) { return G->Next; }
637c3b23
MV
272template<class T>
273static void ShowHashTableStats(std::string Type,
274 T *StartP,
ac2c559b 275 map_pointer_t *Hashtable,
32ab4bd0
DK
276 unsigned long Size,
277 map_pointer_t(*Next)(T const * const))
637c3b23
MV
278{
279 // hashtable stats for the HashTable
ac2c559b
DK
280 unsigned long NumBuckets = Size;
281 unsigned long UsedBuckets = 0;
282 unsigned long UnusedBuckets = 0;
283 unsigned long LongestBucket = 0;
284 unsigned long ShortestBucket = NumBuckets;
285 unsigned long Entries = 0;
637c3b23
MV
286 for (unsigned int i=0; i < NumBuckets; ++i)
287 {
288 T *P = StartP + Hashtable[i];
289 if(P == 0 || P == StartP)
290 {
ac2c559b 291 ++UnusedBuckets;
637c3b23
MV
292 continue;
293 }
ac2c559b
DK
294 ++UsedBuckets;
295 unsigned long ThisBucketSize = 0;
32ab4bd0 296 for (; P != StartP; P = StartP + Next(P))
ac2c559b
DK
297 ++ThisBucketSize;
298 Entries += ThisBucketSize;
637c3b23
MV
299 LongestBucket = std::max(ThisBucketSize, LongestBucket);
300 ShortestBucket = std::min(ThisBucketSize, ShortestBucket);
637c3b23 301 }
ac2c559b
DK
302 cout << "Total buckets in " << Type << ": " << NumBuckets << std::endl;
303 cout << " Unused: " << UnusedBuckets << std::endl;
637c3b23 304 cout << " Used: " << UsedBuckets << std::endl;
ac2c559b 305 cout << " Average entries: " << Entries/(double)NumBuckets << std::endl;
637c3b23
MV
306 cout << " Longest: " << LongestBucket << std::endl;
307 cout << " Shortest: " << ShortestBucket << std::endl;
308}
309 /*}}}*/
1164783d
AL
310// Stats - Dump some nice statistics /*{{{*/
311// ---------------------------------------------------------------------
312/* */
65512241 313static bool Stats(CommandLine &)
1164783d 314{
d9eb210e
DK
315 pkgCacheFile CacheFile;
316 pkgCache *Cache = CacheFile.GetPkgCache();
317 if (unlikely(Cache == NULL))
318 return false;
319
320 cout << _("Total package names: ") << Cache->Head().GroupCount << " (" <<
321 SizeToStr(Cache->Head().GroupCount*Cache->Head().GroupSz) << ')' << endl
322 << _("Total package structures: ") << Cache->Head().PackageCount << " (" <<
323 SizeToStr(Cache->Head().PackageCount*Cache->Head().PackageSz) << ')' << endl;
b2e465d6 324
1164783d
AL
325 int Normal = 0;
326 int Virtual = 0;
327 int NVirt = 0;
328 int DVirt = 0;
329 int Missing = 0;
d9eb210e 330 pkgCache::PkgIterator I = Cache->PkgBegin();
f7f0d6c7 331 for (;I.end() != true; ++I)
1164783d
AL
332 {
333 if (I->VersionList != 0 && I->ProvidesList == 0)
334 {
335 Normal++;
336 continue;
337 }
338
339 if (I->VersionList != 0 && I->ProvidesList != 0)
340 {
341 NVirt++;
342 continue;
343 }
344
345 if (I->VersionList == 0 && I->ProvidesList != 0)
346 {
347 // Only 1 provides
348 if (I.ProvidesList()->NextProvides == 0)
349 {
350 DVirt++;
351 }
352 else
353 Virtual++;
354 continue;
355 }
356 if (I->VersionList == 0 && I->ProvidesList == 0)
357 {
358 Missing++;
359 continue;
360 }
361 }
db0db9fe
CP
362 cout << _(" Normal packages: ") << Normal << endl;
363 cout << _(" Pure virtual packages: ") << Virtual << endl;
364 cout << _(" Single virtual packages: ") << DVirt << endl;
365 cout << _(" Mixed virtual packages: ") << NVirt << endl;
b2e465d6 366 cout << _(" Missing: ") << Missing << endl;
71c9e95b 367
d9eb210e
DK
368 cout << _("Total distinct versions: ") << Cache->Head().VersionCount << " (" <<
369 SizeToStr(Cache->Head().VersionCount*Cache->Head().VersionSz) << ')' << endl;
370 cout << _("Total distinct descriptions: ") << Cache->Head().DescriptionCount << " (" <<
371 SizeToStr(Cache->Head().DescriptionCount*Cache->Head().DescriptionSz) << ')' << endl;
71c9e95b
DK
372 cout << _("Total dependencies: ") << Cache->Head().DependsCount << "/" << Cache->Head().DependsDataCount << " (" <<
373 SizeToStr((Cache->Head().DependsCount*Cache->Head().DependencySz) +
374 (Cache->Head().DependsDataCount*Cache->Head().DependencyDataSz)) << ')' << endl;
d9eb210e
DK
375 cout << _("Total ver/file relations: ") << Cache->Head().VerFileCount << " (" <<
376 SizeToStr(Cache->Head().VerFileCount*Cache->Head().VerFileSz) << ')' << endl;
377 cout << _("Total Desc/File relations: ") << Cache->Head().DescFileCount << " (" <<
378 SizeToStr(Cache->Head().DescFileCount*Cache->Head().DescFileSz) << ')' << endl;
379 cout << _("Total Provides mappings: ") << Cache->Head().ProvidesCount << " (" <<
380 SizeToStr(Cache->Head().ProvidesCount*Cache->Head().ProvidesSz) << ')' << endl;
b2e465d6 381
a3a91fd7
DK
382 // String list stats
383 std::set<map_stringitem_t> stritems;
384 for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
385 stritems.insert(G->Name);
f7f0d6c7 386 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
b2e465d6 387 {
a3a91fd7 388 stritems.insert(P->Arch);
f7f0d6c7 389 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
b2e465d6 390 {
a3a91fd7
DK
391 if (V->VerStr != 0)
392 stritems.insert(V->VerStr);
393 if (V->Section != 0)
394 stritems.insert(V->Section);
765190e4 395#if APT_PKG_ABI >= 413
a221efc3
DK
396 stritems.insert(V->SourcePkgName);
397 stritems.insert(V->SourceVerStr);
765190e4 398#endif
f7f0d6c7 399 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
b2e465d6
AL
400 {
401 if (D->Version != 0)
a3a91fd7
DK
402 stritems.insert(D->Version);
403 }
404 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
405 {
406 stritems.insert(D->md5sum);
407 stritems.insert(D->language_code);
b2e465d6
AL
408 }
409 }
a3a91fd7
DK
410 for (pkgCache::PrvIterator Prv = P.ProvidesList(); Prv.end() == false; ++Prv)
411 {
412 if (Prv->ProvideVersion != 0)
413 stritems.insert(Prv->ProvideVersion);
414 }
b2e465d6 415 }
b07aeb1a 416 for (pkgCache::RlsFileIterator F = Cache->RlsFileBegin(); F != Cache->RlsFileEnd(); ++F)
a3a91fd7
DK
417 {
418 stritems.insert(F->FileName);
419 stritems.insert(F->Archive);
420 stritems.insert(F->Codename);
a3a91fd7
DK
421 stritems.insert(F->Version);
422 stritems.insert(F->Origin);
423 stritems.insert(F->Label);
a3a91fd7 424 stritems.insert(F->Site);
b07aeb1a
DK
425 }
426 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F)
427 {
428 stritems.insert(F->FileName);
429 stritems.insert(F->Architecture);
430 stritems.insert(F->Component);
a3a91fd7
DK
431 stritems.insert(F->IndexType);
432 }
433 unsigned long Size = 0;
434 for (std::set<map_stringitem_t>::const_iterator i = stritems.begin(); i != stritems.end(); ++i)
435 Size += strlen(Cache->StrP + *i) + 1;
436
437 cout << _("Total globbed strings: ") << stritems.size() << " (" << SizeToStr(Size) << ')' << endl;
438 stritems.clear();
ac2c559b 439
f826cfaa
AL
440 unsigned long Slack = 0;
441 for (int I = 0; I != 7; I++)
d9eb210e 442 Slack += Cache->Head().Pools[I].ItemSize*Cache->Head().Pools[I].Count;
db0db9fe 443 cout << _("Total slack space: ") << SizeToStr(Slack) << endl;
ac2c559b 444
f826cfaa 445 unsigned long Total = 0;
ac2c559b
DK
446#define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
447 Total = Slack + Size +
448 APT_CACHESIZE(GroupCount, GroupSz) +
449 APT_CACHESIZE(PackageCount, PackageSz) +
450 APT_CACHESIZE(VersionCount, VersionSz) +
451 APT_CACHESIZE(DescriptionCount, DescriptionSz) +
452 APT_CACHESIZE(DependsCount, DependencySz) +
71c9e95b 453 APT_CACHESIZE(DependsDataCount, DependencyDataSz) +
b07aeb1a 454 APT_CACHESIZE(ReleaseFileCount, ReleaseFileSz) +
ac2c559b
DK
455 APT_CACHESIZE(PackageFileCount, PackageFileSz) +
456 APT_CACHESIZE(VerFileCount, VerFileSz) +
457 APT_CACHESIZE(DescFileCount, DescFileSz) +
458 APT_CACHESIZE(ProvidesCount, ProvidesSz) +
32ab4bd0 459 (2 * Cache->Head().GetHashTableSize() * sizeof(map_id_t));
db0db9fe 460 cout << _("Total space accounted for: ") << SizeToStr(Total) << endl;
ac2c559b 461#undef APT_CACHESIZE
a93a32b5 462
637c3b23 463 // hashtable stats
32ab4bd0
DK
464 ShowHashTableStats<pkgCache::Package>("PkgHashTable", Cache->PkgP, Cache->Head().PkgHashTableP(), Cache->Head().GetHashTableSize(), PackageNext);
465 ShowHashTableStats<pkgCache::Group>("GrpHashTable", Cache->GrpP, Cache->Head().GrpHashTableP(), Cache->Head().GetHashTableSize(), GroupNext);
a93a32b5 466
83d89a9f
AL
467 return true;
468}
469 /*}}}*/
1164783d
AL
470// Dump - show everything /*{{{*/
471// ---------------------------------------------------------------------
b2e465d6 472/* This is worthless except fer debugging things */
65512241 473static bool Dump(CommandLine &)
1164783d 474{
d9eb210e
DK
475 pkgCacheFile CacheFile;
476 pkgCache *Cache = CacheFile.GetPkgCache();
477 if (unlikely(Cache == NULL))
478 return false;
479
b9179170 480 std::cout << "Using Versioning System: " << Cache->VS->Label << std::endl;
b2e465d6 481
f7f0d6c7 482 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
1164783d 483 {
b9179170 484 std::cout << "Package: " << P.FullName(true) << std::endl;
f7f0d6c7 485 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
1164783d 486 {
b9179170
MV
487 std::cout << " Version: " << V.VerStr() << std::endl;
488 std::cout << " File: " << V.FileList().File().FileName() << std::endl;
f7f0d6c7 489 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
b9179170
MV
490 std::cout << " Depends: " << D.TargetPkg().FullName(true) << ' ' <<
491 DeNull(D.TargetVer()) << std::endl;
f7f0d6c7 492 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
a52f938b 493 {
b9179170
MV
494 std::cout << " Description Language: " << D.LanguageCode() << std::endl
495 << " File: " << D.FileList().File().FileName() << std::endl
496 << " MD5: " << D.md5() << std::endl;
a52f938b 497 }
1164783d
AL
498 }
499 }
500
f7f0d6c7 501 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; ++F)
1164783d 502 {
b9179170
MV
503 std::cout << "File: " << F.FileName() << std::endl;
504 std::cout << " Type: " << F.IndexType() << std::endl;
505 std::cout << " Size: " << F->Size << std::endl;
506 std::cout << " ID: " << F->ID << std::endl;
507 std::cout << " Flags: " << F->Flags << std::endl;
508 std::cout << " Time: " << TimeRFC1123(F->mtime) << std::endl;
509 std::cout << " Archive: " << DeNull(F.Archive()) << std::endl;
510 std::cout << " Component: " << DeNull(F.Component()) << std::endl;
511 std::cout << " Version: " << DeNull(F.Version()) << std::endl;
512 std::cout << " Origin: " << DeNull(F.Origin()) << std::endl;
513 std::cout << " Site: " << DeNull(F.Site()) << std::endl;
514 std::cout << " Label: " << DeNull(F.Label()) << std::endl;
515 std::cout << " Architecture: " << DeNull(F.Architecture()) << std::endl;
1164783d
AL
516 }
517
518 return true;
519}
520 /*}}}*/
521// DumpAvail - Print out the available list /*{{{*/
522// ---------------------------------------------------------------------
b2e465d6
AL
523/* This is needed to make dpkg --merge happy.. I spent a bit of time to
524 make this run really fast, perhaps I went a little overboard.. */
65512241 525static bool DumpAvail(CommandLine &)
1164783d 526{
d9eb210e
DK
527 pkgCacheFile CacheFile;
528 pkgCache *Cache = CacheFile.GetPkgCache();
529 if (unlikely(Cache == NULL || CacheFile.BuildPolicy() == false))
b2e465d6 530 return false;
d9eb210e
DK
531
532 unsigned long Count = Cache->HeaderP->PackageCount+1;
fe648919
AL
533 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
534 memset(VFList,0,sizeof(*VFList)*Count);
b2e465d6
AL
535
536 // Map versions that we want to write out onto the VerList array.
f7f0d6c7 537 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
b2e465d6
AL
538 {
539 if (P->VersionList == 0)
5b8c90bf
AL
540 continue;
541
b2e465d6
AL
542 /* Find the proper version to use. If the policy says there are no
543 possible selections we return the installed version, if available..
544 This prevents dselect from making it obsolete. */
d9eb210e 545 pkgCache::VerIterator V = CacheFile.GetPolicy()->GetCandidateVer(P);
b2e465d6 546 if (V.end() == true)
ad00ae81 547 {
b2e465d6
AL
548 if (P->CurrentVer == 0)
549 continue;
550 V = P.CurrentVer();
ad00ae81 551 }
1164783d 552
b2e465d6 553 pkgCache::VerFileIterator VF = V.FileList();
f7f0d6c7 554 for (; VF.end() == false ; ++VF)
b2e465d6
AL
555 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
556 break;
557
558 /* Okay, here we have a bit of a problem.. The policy has selected the
559 currently installed package - however it only exists in the
560 status file.. We need to write out something or dselect will mark
561 the package as obsolete! Thus we emit the status file entry, but
562 below we remove the status line to make it valid for the
563 available file. However! We only do this if their do exist *any*
564 non-source versions of the package - that way the dselect obsolete
565 handling works OK. */
566 if (VF.end() == true)
1164783d 567 {
f7f0d6c7 568 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; ++Cur)
b2e465d6 569 {
f7f0d6c7 570 for (VF = Cur.FileList(); VF.end() == false; ++VF)
b2e465d6
AL
571 {
572 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
573 {
574 VF = V.FileList();
575 break;
576 }
577 }
578
579 if (VF.end() == false)
580 break;
581 }
ad00ae81 582 }
b2e465d6
AL
583
584 VFList[P->ID] = VF;
585 }
586
fe648919 587 LocalitySort(VFList,Count,sizeof(*VFList));
ad00ae81 588
88593886
DK
589 std::vector<pkgTagSection::Tag> RW;
590 RW.push_back(pkgTagSection::Tag::Remove("Status"));
591 RW.push_back(pkgTagSection::Tag::Remove("Config-Version"));
592 FileFd stdoutfd;
593 stdoutfd.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly, false);
594
b2e465d6 595 // Iterate over all the package files and write them out.
d9eb210e 596 char *Buffer = new char[Cache->HeaderP->MaxVerFileSize+10];
b2e465d6
AL
597 for (pkgCache::VerFile **J = VFList; *J != 0;)
598 {
d9eb210e 599 pkgCache::PkgFileIterator File(*Cache,(*J)->File + Cache->PkgFileP);
b2e465d6 600 if (File.IsOk() == false)
ad00ae81 601 {
b2e465d6
AL
602 _error->Error(_("Package file %s is out of sync."),File.FileName());
603 break;
604 }
bd432be3 605
4dde2b42 606 FileFd PkgF(File.FileName(),FileFd::ReadOnly, FileFd::Extension);
b2e465d6
AL
607 if (_error->PendingError() == true)
608 break;
609
610 /* Write all of the records from this package file, since we
611 already did locality sorting we can now just seek through the
612 file in read order. We apply 1 more optimization here, since often
613 there will be < 1 byte gaps between records (for the \n) we read that
614 into the next buffer and offset a bit.. */
615 unsigned long Pos = 0;
616 for (; *J != 0; J++)
617 {
d9eb210e 618 if ((*J)->File + Cache->PkgFileP != File)
b2e465d6 619 break;
bd432be3 620
b2e465d6
AL
621 const pkgCache::VerFile &VF = **J;
622
bd432be3 623 // Read the record and then write it out again.
b2e465d6
AL
624 unsigned long Jitter = VF.Offset - Pos;
625 if (Jitter > 8)
1164783d 626 {
b2e465d6
AL
627 if (PkgF.Seek(VF.Offset) == false)
628 break;
629 Jitter = 0;
630 }
631
632 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
633 break;
634 Buffer[VF.Size + Jitter] = '\n';
88593886 635
b2e465d6
AL
636 // See above..
637 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
638 {
639 pkgTagSection Tags;
b2e465d6 640 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
88593886
DK
641 Tags.Write(stdoutfd, NULL, RW) == false ||
642 stdoutfd.Write("\n", 1) == false)
b2e465d6
AL
643 {
644 _error->Error("Internal Error, Unable to parse a package record");
645 break;
646 }
b2e465d6
AL
647 }
648 else
649 {
88593886 650 if (stdoutfd.Write(Buffer + Jitter, VF.Size + 1) == false)
b2e465d6
AL
651 break;
652 }
88593886 653
b2e465d6 654 Pos = VF.Offset + VF.Size;
1164783d 655 }
b2e465d6 656
b2e465d6
AL
657 if (_error->PendingError() == true)
658 break;
ad00ae81 659 }
88593886 660
b2e465d6
AL
661 delete [] Buffer;
662 delete [] VFList;
663 return !_error->PendingError();
349cd3b8
AL
664}
665 /*}}}*/
3de4647b 666// ShowDepends - Helper for printing out a dependency tree /*{{{*/
c3ccac92 667static bool ShowDepends(CommandLine &CmdL, bool const RevDepends)
349cd3b8 668{
d9eb210e
DK
669 pkgCacheFile CacheFile;
670 pkgCache *Cache = CacheFile.GetPkgCache();
671 if (unlikely(Cache == NULL))
672 return false;
78c32596 673
65f81081 674 CacheSetHelperVirtuals helper(false);
e6f0c9bc 675 APT::VersionList verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper);
3de4647b 676 if (verset.empty() == true && helper.virtualPkgs.empty() == true)
f23fc0e0 677 return _error->Error(_("No packages found"));
3de4647b 678 std::vector<bool> Shown(Cache->Head().PackageCount);
78c32596 679
fe1af091
DK
680 bool const Recurse = _config->FindB("APT::Cache::RecurseDepends", false);
681 bool const Installed = _config->FindB("APT::Cache::Installed", false);
682 bool const Important = _config->FindB("APT::Cache::Important", false);
3de4647b 683 bool const ShowDepType = _config->FindB("APT::Cache::ShowDependencyType", RevDepends == false);
173c98da 684 bool const ShowVersion = _config->FindB("APT::Cache::ShowVersion", false);
fe1af091
DK
685 bool const ShowPreDepends = _config->FindB("APT::Cache::ShowPre-Depends", true);
686 bool const ShowDepends = _config->FindB("APT::Cache::ShowDepends", true);
687 bool const ShowRecommends = _config->FindB("APT::Cache::ShowRecommends", Important == false);
688 bool const ShowSuggests = _config->FindB("APT::Cache::ShowSuggests", Important == false);
689 bool const ShowReplaces = _config->FindB("APT::Cache::ShowReplaces", Important == false);
690 bool const ShowConflicts = _config->FindB("APT::Cache::ShowConflicts", Important == false);
691 bool const ShowBreaks = _config->FindB("APT::Cache::ShowBreaks", Important == false);
692 bool const ShowEnhances = _config->FindB("APT::Cache::ShowEnhances", Important == false);
a5032f84 693 bool const ShowOnlyFirstOr = _config->FindB("APT::Cache::ShowOnlyFirstOr", false);
3de4647b
DK
694
695 while (verset.empty() != true)
b2e465d6 696 {
3de4647b
DK
697 pkgCache::VerIterator Ver = *verset.begin();
698 verset.erase(verset.begin());
699 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
700 Shown[Pkg->ID] = true;
701
75ce2062 702 cout << Pkg.FullName(true) << endl;
3de4647b
DK
703
704 if (RevDepends == true)
705 cout << "Reverse Depends:" << endl;
706 for (pkgCache::DepIterator D = RevDepends ? Pkg.RevDependsList() : Ver.DependsList();
f7f0d6c7 707 D.end() == false; ++D)
b2e465d6 708 {
fe1af091
DK
709 switch (D->Type) {
710 case pkgCache::Dep::PreDepends: if (!ShowPreDepends) continue; break;
711 case pkgCache::Dep::Depends: if (!ShowDepends) continue; break;
712 case pkgCache::Dep::Recommends: if (!ShowRecommends) continue; break;
713 case pkgCache::Dep::Suggests: if (!ShowSuggests) continue; break;
b9179170 714 case pkgCache::Dep::Replaces: if (!ShowReplaces) continue; break; case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break;
fe1af091
DK
715 case pkgCache::Dep::DpkgBreaks: if (!ShowBreaks) continue; break;
716 case pkgCache::Dep::Enhances: if (!ShowEnhances) continue; break;
717 }
718
3de4647b 719 pkgCache::PkgIterator Trg = RevDepends ? D.ParentPkg() : D.TargetPkg();
eba2b51d
AL
720
721 if((Installed && Trg->CurrentVer != 0) || !Installed)
722 {
723
a5032f84 724 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or && ShowOnlyFirstOr == false)
eba2b51d
AL
725 cout << " |";
726 else
727 cout << " ";
b2e465d6 728
eba2b51d 729 // Show the package
fe1af091
DK
730 if (ShowDepType == true)
731 cout << D.DepType() << ": ";
eba2b51d 732 if (Trg->VersionList == 0)
173c98da 733 cout << "<" << Trg.FullName(true) << ">";
eba2b51d 734 else
173c98da
DK
735 cout << Trg.FullName(true);
736 if (ShowVersion == true && D->Version != 0)
737 cout << " (" << pkgCache::CompTypeDeb(D->CompareOp) << ' ' << D.TargetVer() << ')';
738 cout << std::endl;
739
3de4647b
DK
740 if (Recurse == true && Shown[Trg->ID] == false)
741 {
742 Shown[Trg->ID] = true;
e6f0c9bc 743 verset.insert(APT::VersionSet::FromPackage(CacheFile, Trg, APT::CacheSetHelper::CANDIDATE, helper));
3de4647b 744 }
eba2b51d
AL
745
746 }
b2e465d6
AL
747
748 // Display all solutions
749 SPtrArray<pkgCache::Version *> List = D.AllTargets();
d9eb210e 750 pkgPrioSortList(*Cache,List);
b2e465d6
AL
751 for (pkgCache::Version **I = List; *I != 0; I++)
752 {
d9eb210e
DK
753 pkgCache::VerIterator V(*Cache,*I);
754 if (V != Cache->VerP + V.ParentPkg()->VersionList ||
b2e465d6
AL
755 V->ParentPkg == D->Package)
756 continue;
75ce2062 757 cout << " " << V.ParentPkg().FullName(true) << endl;
3de4647b
DK
758
759 if (Recurse == true && Shown[V.ParentPkg()->ID] == false)
760 {
761 Shown[V.ParentPkg()->ID] = true;
e6f0c9bc 762 verset.insert(APT::VersionSet::FromPackage(CacheFile, V.ParentPkg(), APT::CacheSetHelper::CANDIDATE, helper));
3de4647b 763 }
b2e465d6 764 }
a5032f84
DK
765
766 if (ShowOnlyFirstOr == true)
767 while ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) ++D;
b2e465d6 768 }
3de4647b
DK
769 }
770
771 for (APT::PackageSet::const_iterator Pkg = helper.virtualPkgs.begin();
772 Pkg != helper.virtualPkgs.end(); ++Pkg)
773 cout << '<' << Pkg.FullName(true) << '>' << endl;
774
3e94da1b
AL
775 return true;
776}
92fcbfc1 777 /*}}}*/
3de4647b
DK
778// Depends - Print out a dependency tree /*{{{*/
779// ---------------------------------------------------------------------
780/* */
c3ccac92 781static bool Depends(CommandLine &CmdL)
3de4647b
DK
782{
783 return ShowDepends(CmdL, false);
784}
785 /*}}}*/
786// RDepends - Print out a reverse dependency tree /*{{{*/
eba2b51d
AL
787// ---------------------------------------------------------------------
788/* */
c3ccac92 789static bool RDepends(CommandLine &CmdL)
eba2b51d 790{
3de4647b 791 return ShowDepends(CmdL, true);
eba2b51d 792}
3e94da1b 793 /*}}}*/
fff4b7f3
AL
794// xvcg - Generate a graph for xvcg /*{{{*/
795// ---------------------------------------------------------------------
796// Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
797
c3ccac92 798static bool XVcg(CommandLine &CmdL)
fff4b7f3 799{
d9eb210e
DK
800 pkgCacheFile CacheFile;
801 pkgCache *Cache = CacheFile.GetPkgCache();
802 if (unlikely(Cache == NULL))
803 return false;
804
fff4b7f3
AL
805 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
806
807 /* Normal packages are boxes
808 Pure Provides are triangles
809 Mixed are diamonds
810 rhomb are missing packages*/
811 const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
812
813 /* Initialize the list of packages to show.
814 1 = To Show
815 2 = To Show no recurse
816 3 = Emitted no recurse
817 4 = Emitted
818 0 = None */
819 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
820 enum TheFlags {ForceNR=(1<<0)};
d9eb210e
DK
821 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
822 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
823 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
fff4b7f3
AL
824
825 // Show everything if no arguments given
826 if (CmdL.FileList[1] == 0)
d9eb210e 827 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
fff4b7f3
AL
828 Show[I] = ToShow;
829 else
d9eb210e 830 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
fff4b7f3 831 Show[I] = None;
d9eb210e 832 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
fff4b7f3
AL
833
834 // Map the shapes
f7f0d6c7 835 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
fff4b7f3
AL
836 {
837 if (Pkg->VersionList == 0)
838 {
839 // Missing
840 if (Pkg->ProvidesList == 0)
841 ShapeMap[Pkg->ID] = 0;
842 else
843 ShapeMap[Pkg->ID] = 1;
844 }
845 else
846 {
847 // Normal
848 if (Pkg->ProvidesList == 0)
849 ShapeMap[Pkg->ID] = 2;
850 else
851 ShapeMap[Pkg->ID] = 3;
852 }
853 }
3c977245 854
fff4b7f3 855 // Load the list of packages from the command line into the show list
cd7bbc47 856 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
fdba4d53
DK
857 std::list<APT::CacheSetHelper::PkgModifier> mods;
858 mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
859 mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
3c977245 860 std::map<unsigned short, APT::PackageSet> pkgsets =
cd7bbc47 861 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
3c977245
DK
862
863 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
864 Pkg != pkgsets[0].end(); ++Pkg)
865 Show[Pkg->ID] = ToShow;
866 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
867 Pkg != pkgsets[1].end(); ++Pkg)
fff4b7f3 868 {
fff4b7f3 869 Show[Pkg->ID] = ToShow;
3c977245 870 Flags[Pkg->ID] |= ForceNR;
fff4b7f3 871 }
3c977245 872
fff4b7f3
AL
873 // Little header
874 cout << "graph: { title: \"packages\"" << endl <<
875 "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
876 "layout_downfactor: 8" << endl;
877
878 bool Act = true;
879 while (Act == true)
880 {
881 Act = false;
f7f0d6c7 882 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
fff4b7f3
AL
883 {
884 // See we need to show this package
885 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
886 continue;
887
888 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
889
890 // Colour as done
891 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
892 {
893 // Pure Provides and missing packages have no deps!
894 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
895 Show[Pkg->ID] = Done;
896 else
897 Show[Pkg->ID] = DoneNR;
898 }
899 else
900 Show[Pkg->ID] = Done;
901 Act = true;
902
903 // No deps to map out
904 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
905 continue;
906
907 pkgCache::VerIterator Ver = Pkg.VersionList();
f7f0d6c7 908 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
fff4b7f3
AL
909 {
910 // See if anything can meet this dep
911 // Walk along the actual package providing versions
912 bool Hit = false;
913 pkgCache::PkgIterator DPkg = D.TargetPkg();
914 for (pkgCache::VerIterator I = DPkg.VersionList();
f7f0d6c7 915 I.end() == false && Hit == false; ++I)
fff4b7f3 916 {
d9eb210e 917 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
fff4b7f3
AL
918 Hit = true;
919 }
920
921 // Follow all provides
922 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
f7f0d6c7 923 I.end() == false && Hit == false; ++I)
fff4b7f3 924 {
d9eb210e 925 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
fff4b7f3
AL
926 Hit = true;
927 }
928
929
930 // Only graph critical deps
931 if (D.IsCritical() == true)
932 {
75ce2062 933 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.FullName(true).c_str(), D.TargetPkg().FullName(true).c_str() );
fff4b7f3
AL
934
935 // Colour the node for recursion
936 if (Show[D.TargetPkg()->ID] <= DoneNR)
937 {
938 /* If a conflicts does not meet anything in the database
939 then show the relation but do not recurse */
359e46db 940 if (Hit == false && D.IsNegative() == true)
fff4b7f3
AL
941 {
942 if (Show[D.TargetPkg()->ID] == None &&
943 Show[D.TargetPkg()->ID] != ToShow)
944 Show[D.TargetPkg()->ID] = ToShowNR;
945 }
946 else
947 {
948 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
949 Show[D.TargetPkg()->ID] = ToShowNR;
950 else
951 Show[D.TargetPkg()->ID] = ToShow;
952 }
953 }
954
955 // Edge colour
956 switch(D->Type)
957 {
958 case pkgCache::Dep::Conflicts:
959 printf("label: \"conflicts\" color: lightgreen }\n");
960 break;
308c7d30
IJ
961 case pkgCache::Dep::DpkgBreaks:
962 printf("label: \"breaks\" color: lightgreen }\n");
963 break;
fff4b7f3
AL
964 case pkgCache::Dep::Obsoletes:
965 printf("label: \"obsoletes\" color: lightgreen }\n");
966 break;
967
968 case pkgCache::Dep::PreDepends:
969 printf("label: \"predepends\" color: blue }\n");
970 break;
971
972 default:
973 printf("}\n");
974 break;
975 }
976 }
977 }
978 }
979 }
980
981 /* Draw the box colours after the fact since we can not tell what colour
982 they should be until everything is finished drawing */
f7f0d6c7 983 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
fff4b7f3
AL
984 {
985 if (Show[Pkg->ID] < DoneNR)
986 continue;
987
988 if (Show[Pkg->ID] == DoneNR)
75ce2062 989 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
fff4b7f3
AL
990 Shapes[ShapeMap[Pkg->ID]]);
991 else
75ce2062 992 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
fff4b7f3
AL
993 Shapes[ShapeMap[Pkg->ID]]);
994
995 }
03496041
DK
996
997 delete[] Show;
998 delete[] Flags;
999 delete[] ShapeMap;
1000
fff4b7f3
AL
1001 printf("}\n");
1002 return true;
1003}
1004 /*}}}*/
3e94da1b
AL
1005// Dotty - Generate a graph for Dotty /*{{{*/
1006// ---------------------------------------------------------------------
1007/* Dotty is the graphvis program for generating graphs. It is a fairly
1008 simple queuing algorithm that just writes dependencies and nodes.
1009 http://www.research.att.com/sw/tools/graphviz/ */
c3ccac92 1010static bool Dotty(CommandLine &CmdL)
3e94da1b 1011{
d9eb210e
DK
1012 pkgCacheFile CacheFile;
1013 pkgCache *Cache = CacheFile.GetPkgCache();
1014 if (unlikely(Cache == NULL))
1015 return false;
1016
3e94da1b
AL
1017 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
1018
1019 /* Normal packages are boxes
1020 Pure Provides are triangles
1021 Mixed are diamonds
1022 Hexagons are missing packages*/
1023 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
1024
1025 /* Initialize the list of packages to show.
1026 1 = To Show
1027 2 = To Show no recurse
1028 3 = Emitted no recurse
1029 4 = Emitted
1030 0 = None */
1031 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
1032 enum TheFlags {ForceNR=(1<<0)};
d9eb210e
DK
1033 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
1034 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
1035 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
3e94da1b
AL
1036
1037 // Show everything if no arguments given
1038 if (CmdL.FileList[1] == 0)
d9eb210e 1039 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
3e94da1b
AL
1040 Show[I] = ToShow;
1041 else
d9eb210e 1042 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
3e94da1b 1043 Show[I] = None;
d9eb210e 1044 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
3e94da1b
AL
1045
1046 // Map the shapes
f7f0d6c7 1047 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
3e94da1b
AL
1048 {
1049 if (Pkg->VersionList == 0)
1050 {
1051 // Missing
1052 if (Pkg->ProvidesList == 0)
1053 ShapeMap[Pkg->ID] = 0;
1054 else
1055 ShapeMap[Pkg->ID] = 1;
1056 }
1057 else
1058 {
1059 // Normal
1060 if (Pkg->ProvidesList == 0)
1061 ShapeMap[Pkg->ID] = 2;
1062 else
1063 ShapeMap[Pkg->ID] = 3;
1064 }
1065 }
3c977245 1066
3e94da1b 1067 // Load the list of packages from the command line into the show list
cd7bbc47 1068 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
fdba4d53
DK
1069 std::list<APT::CacheSetHelper::PkgModifier> mods;
1070 mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
1071 mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
3c977245 1072 std::map<unsigned short, APT::PackageSet> pkgsets =
cd7bbc47 1073 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
3c977245
DK
1074
1075 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
1076 Pkg != pkgsets[0].end(); ++Pkg)
1077 Show[Pkg->ID] = ToShow;
1078 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
1079 Pkg != pkgsets[1].end(); ++Pkg)
3e94da1b 1080 {
3e94da1b 1081 Show[Pkg->ID] = ToShow;
3c977245 1082 Flags[Pkg->ID] |= ForceNR;
3e94da1b 1083 }
3c977245 1084
3e94da1b
AL
1085 // Little header
1086 printf("digraph packages {\n");
1087 printf("concentrate=true;\n");
1088 printf("size=\"30,40\";\n");
1089
1090 bool Act = true;
1091 while (Act == true)
1092 {
1093 Act = false;
f7f0d6c7 1094 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
3e94da1b
AL
1095 {
1096 // See we need to show this package
1097 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
1098 continue;
1099
1100 // Colour as done
1101 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
1102 {
1103 // Pure Provides and missing packages have no deps!
1104 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
1105 Show[Pkg->ID] = Done;
1106 else
1107 Show[Pkg->ID] = DoneNR;
1108 }
1109 else
1110 Show[Pkg->ID] = Done;
1111 Act = true;
1112
1113 // No deps to map out
1114 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
1115 continue;
1116
1117 pkgCache::VerIterator Ver = Pkg.VersionList();
f7f0d6c7 1118 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
3e94da1b
AL
1119 {
1120 // See if anything can meet this dep
1121 // Walk along the actual package providing versions
1122 bool Hit = false;
1123 pkgCache::PkgIterator DPkg = D.TargetPkg();
1124 for (pkgCache::VerIterator I = DPkg.VersionList();
f7f0d6c7 1125 I.end() == false && Hit == false; ++I)
3e94da1b 1126 {
d9eb210e 1127 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
3e94da1b
AL
1128 Hit = true;
1129 }
1130
1131 // Follow all provides
1132 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
f7f0d6c7 1133 I.end() == false && Hit == false; ++I)
3e94da1b 1134 {
d9eb210e 1135 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
3e94da1b
AL
1136 Hit = true;
1137 }
1138
1139 // Only graph critical deps
1140 if (D.IsCritical() == true)
1141 {
75ce2062 1142 printf("\"%s\" -> \"%s\"",Pkg.FullName(true).c_str(),D.TargetPkg().FullName(true).c_str());
3e94da1b
AL
1143
1144 // Colour the node for recursion
1145 if (Show[D.TargetPkg()->ID] <= DoneNR)
1146 {
1147 /* If a conflicts does not meet anything in the database
1148 then show the relation but do not recurse */
359e46db 1149 if (Hit == false && D.IsNegative() == true)
3e94da1b
AL
1150 {
1151 if (Show[D.TargetPkg()->ID] == None &&
1152 Show[D.TargetPkg()->ID] != ToShow)
1153 Show[D.TargetPkg()->ID] = ToShowNR;
1154 }
1155 else
1156 {
1157 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
1158 Show[D.TargetPkg()->ID] = ToShowNR;
1159 else
1160 Show[D.TargetPkg()->ID] = ToShow;
1161 }
1162 }
1163
1164 // Edge colour
1165 switch(D->Type)
1166 {
1167 case pkgCache::Dep::Conflicts:
b2e465d6 1168 case pkgCache::Dep::Obsoletes:
359e46db 1169 case pkgCache::Dep::DpkgBreaks:
3e94da1b
AL
1170 printf("[color=springgreen];\n");
1171 break;
1172
1173 case pkgCache::Dep::PreDepends:
1174 printf("[color=blue];\n");
1175 break;
1176
1177 default:
1178 printf(";\n");
1179 break;
1180 }
1181 }
1182 }
1183 }
1184 }
1185
1186 /* Draw the box colours after the fact since we can not tell what colour
1187 they should be until everything is finished drawing */
f7f0d6c7 1188 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
3e94da1b
AL
1189 {
1190 if (Show[Pkg->ID] < DoneNR)
1191 continue;
1192
1193 // Orange box for early recursion stoppage
1194 if (Show[Pkg->ID] == DoneNR)
75ce2062 1195 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.FullName(true).c_str(),
3e94da1b
AL
1196 Shapes[ShapeMap[Pkg->ID]]);
1197 else
75ce2062 1198 printf("\"%s\" [shape=%s];\n",Pkg.FullName(true).c_str(),
3e94da1b
AL
1199 Shapes[ShapeMap[Pkg->ID]]);
1200 }
1201
1202 printf("}\n");
6070a346
DK
1203 delete[] Show;
1204 delete[] Flags;
1205 delete[] ShapeMap;
ad00ae81 1206 return true;
7e2e2d5d
AL
1207}
1208 /*}}}*/
1209// DisplayRecord - Displays the complete record for the package /*{{{*/
1210// ---------------------------------------------------------------------
1211/* This displays the package record from the proper package index file.
1212 It is not used by DumpAvail for performance reasons. */
61843f53 1213
a02db58f 1214static APT_PURE unsigned char const* skipDescriptionFields(unsigned char const * DescP)
61843f53 1215{
922f0798
DK
1216 char const * const TagName = "\nDescription";
1217 size_t const TagLen = strlen(TagName);
61843f53
DK
1218 while ((DescP = (unsigned char*)strchr((char*)DescP, '\n')) != NULL)
1219 {
1220 if (DescP[1] == ' ')
1221 DescP += 2;
922f0798
DK
1222 else if (strncmp((char*)DescP, TagName, TagLen) == 0)
1223 DescP += TagLen;
61843f53
DK
1224 else
1225 break;
1226 }
1227 if (DescP != NULL)
1228 ++DescP;
1229 return DescP;
1230}
c3ccac92 1231static bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
7e2e2d5d 1232{
d9eb210e
DK
1233 pkgCache *Cache = CacheFile.GetPkgCache();
1234 if (unlikely(Cache == NULL))
1235 return false;
1236
7e2e2d5d
AL
1237 // Find an appropriate file
1238 pkgCache::VerFileIterator Vf = V.FileList();
f7f0d6c7 1239 for (; Vf.end() == false; ++Vf)
7e2e2d5d
AL
1240 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
1241 break;
1242 if (Vf.end() == true)
1243 Vf = V.FileList();
1244
1245 // Check and load the package list file
1246 pkgCache::PkgFileIterator I = Vf.File();
1247 if (I.IsOk() == false)
b2e465d6 1248 return _error->Error(_("Package file %s is out of sync."),I.FileName());
07c279d9
DK
1249
1250 FileFd PkgF;
468720c5 1251 if (PkgF.Open(I.FileName(), FileFd::ReadOnly, FileFd::Extension) == false)
7e2e2d5d 1252 return false;
07c279d9 1253
922f0798
DK
1254 // Read the record (and ensure that it ends with a newline and NUL)
1255 unsigned char *Buffer = new unsigned char[Cache->HeaderP->MaxVerFileSize+2];
1256 Buffer[Vf->Size] = '\n';
1257 Buffer[Vf->Size+1] = '\0';
1258 if (PkgF.Seek(Vf->Offset) == false ||
1259 PkgF.Read(Buffer,Vf->Size) == false)
7e2e2d5d
AL
1260 {
1261 delete [] Buffer;
1262 return false;
1263 }
a52f938b 1264
e5e2d176 1265 // Get a pointer to start of Description field
99359751
DK
1266 const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "\nDescription");
1267 if (DescP != NULL)
1268 ++DescP;
1269 else
922f0798 1270 DescP = Buffer + Vf->Size;
e5e2d176
MV
1271
1272 // Write all but Description
d832304e
DK
1273 size_t const length = DescP - Buffer;
1274 if (length != 0 && FileFd::Write(STDOUT_FILENO, Buffer, length) == false)
a52f938b
OS
1275 {
1276 delete [] Buffer;
1277 return false;
1278 }
1279
a52f938b 1280 // Show the right description
d9eb210e 1281 pkgRecords Recs(*Cache);
012b102a 1282 pkgCache::DescIterator Desc = V.TranslatedDescription();
99359751 1283 if (Desc.end() == false)
e011829d 1284 {
99359751
DK
1285 pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
1286 cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
1287 cout << std::endl << "Description-md5: " << Desc.md5() << std::endl;
1288
1289 // Find the first field after the description (if there is any)
61843f53 1290 DescP = skipDescriptionFields(DescP);
99359751 1291 }
61843f53 1292 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
e011829d 1293
61843f53
DK
1294 // write the rest of the buffer, but skip mixed in Descriptions* fields
1295 while (DescP != NULL)
99359751 1296 {
61843f53
DK
1297 const unsigned char * const Start = DescP;
1298 const unsigned char *End = (unsigned char*)strstr((char*)DescP, "\nDescription");
1299 if (End == NULL)
1300 {
922f0798 1301 End = &Buffer[Vf->Size];
61843f53
DK
1302 DescP = NULL;
1303 }
1304 else
1305 {
1306 ++End; // get the newline into the output
1307 DescP = skipDescriptionFields(End + strlen("Description"));
1308 }
1309 size_t const length = End - Start;
d832304e 1310 if (length != 0 && FileFd::Write(STDOUT_FILENO, Start, length) == false)
99359751
DK
1311 {
1312 delete [] Buffer;
1313 return false;
e011829d
MV
1314 }
1315 }
99359751 1316
61843f53 1317 // write a final newline after the last field
e011829d 1318 cout<<endl;
7e2e2d5d 1319
d832304e 1320 delete [] Buffer;
9dbb421f
AL
1321 return true;
1322}
1323 /*}}}*/
a52f938b 1324struct ExDescFile
b2e465d6 1325{
a52f938b 1326 pkgCache::DescFile *Df;
4ad8619b 1327 map_id_t ID;
b2e465d6
AL
1328};
1329
92fcbfc1
DK
1330// Search - Perform a search /*{{{*/
1331// ---------------------------------------------------------------------
1332/* This searches the package names and package descriptions for a pattern */
c3ccac92 1333static bool Search(CommandLine &CmdL)
9dbb421f 1334{
d5cc17d6
DK
1335 bool const ShowFull = _config->FindB("APT::Cache::ShowFull",false);
1336 bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
1337 unsigned int const NumPatterns = CmdL.FileSize() -1;
b2e465d6 1338
d9eb210e
DK
1339 pkgCacheFile CacheFile;
1340 pkgCache *Cache = CacheFile.GetPkgCache();
1341 pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
1342 if (unlikely(Cache == NULL || Plcy == NULL))
1343 return false;
1344
9dbb421f 1345 // Make sure there is at least one argument
b2e465d6 1346 if (NumPatterns < 1)
d5cc17d6 1347 return _error->Error(_("You must give at least one search pattern"));
9dbb421f
AL
1348
1349 // Compile the regex pattern
b2e465d6
AL
1350 regex_t *Patterns = new regex_t[NumPatterns];
1351 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
1352 for (unsigned I = 0; I != NumPatterns; I++)
1353 {
1354 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
1355 REG_NOSUB) != 0)
1356 {
1357 for (; I != 0; I--)
1358 regfree(&Patterns[I]);
1359 return _error->Error("Regex compilation error");
1360 }
1361 }
9dbb421f 1362
9dbb421f 1363 if (_error->PendingError() == true)
b2e465d6
AL
1364 {
1365 for (unsigned I = 0; I != NumPatterns; I++)
1366 regfree(&Patterns[I]);
9dbb421f 1367 return false;
b2e465d6 1368 }
9dbb421f 1369
8ba17539
DK
1370 size_t const descCount = Cache->HeaderP->GroupCount + 1;
1371 ExDescFile *DFList = new ExDescFile[descCount];
1372 memset(DFList,0,sizeof(*DFList) * descCount);
1373
09724809
MV
1374 bool *PatternMatch = new bool[descCount * NumPatterns];
1375 memset(PatternMatch,false,sizeof(*PatternMatch) * descCount * NumPatterns);
b2e465d6
AL
1376
1377 // Map versions that we want to write out onto the VerList array.
d9eb210e 1378 for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
9dbb421f 1379 {
8ba17539
DK
1380 size_t const PatternOffset = G->ID * NumPatterns;
1381 size_t unmatched = 0, matched = 0;
1382 for (unsigned I = 0; I < NumPatterns; ++I)
b2e465d6 1383 {
8ba17539
DK
1384 if (PatternMatch[PatternOffset + I] == true)
1385 ++matched;
1386 else if (regexec(&Patterns[I],G.Name(),0,0,0) == 0)
1387 PatternMatch[PatternOffset + I] = true;
1388 else
1389 ++unmatched;
b2e465d6 1390 }
8ba17539
DK
1391
1392 // already dealt with this package?
1393 if (matched == NumPatterns)
b2e465d6 1394 continue;
8ba17539
DK
1395
1396 // Doing names only, drop any that don't match..
1397 if (NamesOnly == true && unmatched == NumPatterns)
1398 continue;
1399
d5cc17d6
DK
1400 // Find the proper version to use
1401 pkgCache::PkgIterator P = G.FindPreferredPkg();
1402 if (P.end() == true)
1403 continue;
d9eb210e 1404 pkgCache::VerIterator V = Plcy->GetCandidateVer(P);
c29652b0 1405 if (V.end() == false)
8ba17539 1406 {
922f0798
DK
1407 pkgCache::DescIterator const D = V.TranslatedDescription();
1408 //FIXME: packages without a description can't be found
1409 if (D.end() == true)
1410 continue;
1411 DFList[G->ID].Df = D.FileList();
8ba17539
DK
1412 DFList[G->ID].ID = G->ID;
1413 }
d5cc17d6 1414
8ba17539 1415 if (unmatched == NumPatterns)
7e2e2d5d 1416 continue;
c29652b0 1417
d5cc17d6 1418 // Include all the packages that provide matching names too
f7f0d6c7 1419 for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; ++Prv)
c29652b0 1420 {
d9eb210e 1421 pkgCache::VerIterator V = Plcy->GetCandidateVer(Prv.OwnerPkg());
d5cc17d6
DK
1422 if (V.end() == true)
1423 continue;
1424
1425 unsigned long id = Prv.OwnerPkg().Group()->ID;
922f0798
DK
1426 pkgCache::DescIterator const D = V.TranslatedDescription();
1427 //FIXME: packages without a description can't be found
1428 if (D.end() == true)
1429 continue;
1430 DFList[id].Df = D.FileList();
8ba17539
DK
1431 DFList[id].ID = id;
1432
1433 size_t const PrvPatternOffset = id * NumPatterns;
1434 for (unsigned I = 0; I < NumPatterns; ++I)
1435 PatternMatch[PrvPatternOffset + I] = PatternMatch[PatternOffset + I];
c29652b0 1436 }
b2e465d6 1437 }
8ba17539 1438
d9eb210e 1439 LocalitySort(&DFList->Df,Cache->HeaderP->GroupCount,sizeof(*DFList));
7e2e2d5d 1440
d5cc17d6 1441 // Create the text record parser
d9eb210e 1442 pkgRecords Recs(*Cache);
b2e465d6 1443 // Iterate over all the version records and check them
8ba17539 1444 for (ExDescFile *J = DFList; J->Df != 0; ++J)
b2e465d6 1445 {
d9eb210e 1446 pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(*Cache,J->Df));
8ba17539 1447 size_t const PatternOffset = J->ID * NumPatterns;
0f2fa322 1448
8ba17539 1449 if (NamesOnly == false)
0f2fa322 1450 {
d5cc17d6 1451 string const LongDesc = P.LongDesc();
8ba17539 1452 for (unsigned I = 0; I < NumPatterns; ++I)
0f2fa322 1453 {
8ba17539 1454 if (PatternMatch[PatternOffset + I] == true)
d5cc17d6 1455 continue;
8ba17539
DK
1456 else if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
1457 PatternMatch[PatternOffset + I] = true;
0f2fa322
AL
1458 }
1459 }
8ba17539
DK
1460
1461 bool matchedAll = true;
1462 for (unsigned I = 0; I < NumPatterns; ++I)
1463 if (PatternMatch[PatternOffset + I] == false)
1464 {
1465 matchedAll = false;
1466 break;
1467 }
1468
1469 if (matchedAll == true)
9dbb421f 1470 {
7e2e2d5d 1471 if (ShowFull == true)
b2e465d6
AL
1472 {
1473 const char *Start;
1474 const char *End;
1475 P.GetRec(Start,End);
1476 fwrite(Start,End-Start,1,stdout);
1477 putc('\n',stdout);
1478 }
7e2e2d5d 1479 else
b2e465d6
AL
1480 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
1481 }
9dbb421f
AL
1482 }
1483
a52f938b 1484 delete [] DFList;
09724809 1485 delete [] PatternMatch;
b2e465d6
AL
1486 for (unsigned I = 0; I != NumPatterns; I++)
1487 regfree(&Patterns[I]);
3d8232bf 1488 delete [] Patterns;
b2e465d6
AL
1489 if (ferror(stdout))
1490 return _error->Error("Write to stdout failed");
1164783d
AL
1491 return true;
1492}
182a6a55
DK
1493 /*}}}*/
1494/* ShowAuto - show automatically installed packages (sorted) {{{*/
65512241 1495static bool ShowAuto(CommandLine &)
6007c1d4 1496{
d9eb210e
DK
1497 pkgCacheFile CacheFile;
1498 pkgCache *Cache = CacheFile.GetPkgCache();
1499 pkgDepCache *DepCache = CacheFile.GetDepCache();
1500 if (unlikely(Cache == NULL || DepCache == NULL))
1501 return false;
6007c1d4
JAK
1502
1503 std::vector<string> packages;
d9eb210e 1504 packages.reserve(Cache->HeaderP->PackageCount / 3);
6007c1d4 1505
f7f0d6c7 1506 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
d9eb210e 1507 if ((*DepCache)[P].Flags & pkgCache::Flag::Auto)
6007c1d4
JAK
1508 packages.push_back(P.Name());
1509
1510 std::sort(packages.begin(), packages.end());
1511
f7f0d6c7 1512 for (vector<string>::iterator I = packages.begin(); I != packages.end(); ++I)
6007c1d4
JAK
1513 cout << *I << "\n";
1514
182a6a55 1515 _error->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
6007c1d4
JAK
1516 return true;
1517}
1164783d 1518 /*}}}*/
7e2e2d5d
AL
1519// ShowPackage - Dump the package record to the screen /*{{{*/
1520// ---------------------------------------------------------------------
1521/* */
c3ccac92 1522static bool ShowPackage(CommandLine &CmdL)
d9eb210e
DK
1523{
1524 pkgCacheFile CacheFile;
65f81081 1525 CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
e6f0c9bc
DK
1526 APT::CacheSetHelper::VerSelector const select = _config->FindB("APT::Cache::AllVersions", true) ?
1527 APT::CacheSetHelper::ALL : APT::CacheSetHelper::CANDIDATE;
c4cca791
DK
1528 APT::VersionList const verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, select, helper);
1529 for (APT::VersionList::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver)
d9eb210e
DK
1530 if (DisplayRecord(CacheFile, Ver) == false)
1531 return false;
1532
65f81081
DK
1533 if (verset.empty() == true)
1534 {
1535 if (helper.virtualPkgs.empty() == true)
1536 return _error->Error(_("No packages found"));
1537 else
1538 _error->Notice(_("No packages found"));
1539 }
1540 return true;
7c1133fe
AL
1541}
1542 /*}}}*/
1543// ShowPkgNames - Show package names /*{{{*/
1544// ---------------------------------------------------------------------
1545/* This does a prefix match on the first argument */
c3ccac92 1546static bool ShowPkgNames(CommandLine &CmdL)
7c1133fe 1547{
d9eb210e
DK
1548 pkgCacheFile CacheFile;
1549 if (unlikely(CacheFile.BuildCaches(NULL, false) == false))
1550 return false;
1551 pkgCache::GrpIterator I = CacheFile.GetPkgCache()->GrpBegin();
6293e04f
DK
1552 bool const All = _config->FindB("APT::Cache::AllNames","false");
1553
7c1133fe
AL
1554 if (CmdL.FileList[1] != 0)
1555 {
f7f0d6c7 1556 for (;I.end() != true; ++I)
7c1133fe 1557 {
6293e04f
DK
1558 if (All == false && I->FirstPackage == 0)
1559 continue;
1560 if (I.FindPkg("any")->VersionList == 0)
7c1133fe 1561 continue;
7c1133fe
AL
1562 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1563 cout << I.Name() << endl;
1564 }
1565
1566 return true;
1567 }
1568
1569 // Show all pkgs
f7f0d6c7 1570 for (;I.end() != true; ++I)
7c1133fe 1571 {
6293e04f
DK
1572 if (All == false && I->FirstPackage == 0)
1573 continue;
1574 if (I.FindPkg("any")->VersionList == 0)
7c1133fe
AL
1575 continue;
1576 cout << I.Name() << endl;
1577 }
1578
7e2e2d5d
AL
1579 return true;
1580}
1581 /*}}}*/
f8f410f5
AL
1582// ShowSrcPackage - Show source package records /*{{{*/
1583// ---------------------------------------------------------------------
1584/* */
c3ccac92 1585static bool ShowSrcPackage(CommandLine &CmdL)
f8f410f5 1586{
d9eb210e
DK
1587 pkgCacheFile CacheFile;
1588 pkgSourceList *List = CacheFile.GetSourceList();
1589 if (unlikely(List == NULL))
1590 return false;
1591
f8f410f5 1592 // Create the text record parsers
d9eb210e 1593 pkgSrcRecords SrcRecs(*List);
f8f410f5
AL
1594 if (_error->PendingError() == true)
1595 return false;
1596
0458a811 1597 unsigned found = 0;
f8f410f5
AL
1598 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1599 {
aaee8293
AL
1600 SrcRecs.Restart();
1601
f8f410f5 1602 pkgSrcRecords::Parser *Parse;
0458a811
JAK
1603 unsigned found_this = 0;
1604 while ((Parse = SrcRecs.Find(*I,false)) != 0) {
1605 cout << Parse->AsStr() << endl;;
1606 found++;
1607 found_this++;
1608 }
1609 if (found_this == 0) {
1610 _error->Warning(_("Unable to locate package %s"),*I);
1611 continue;
1612 }
65f81081
DK
1613 }
1614 if (found == 0)
1615 _error->Notice(_("No packages found"));
1616 return true;
af87ab54
AL
1617}
1618 /*}}}*/
1619// Policy - Show the results of the preferences file /*{{{*/
1620// ---------------------------------------------------------------------
1621/* */
c3ccac92 1622static bool Policy(CommandLine &CmdL)
af87ab54 1623{
d9eb210e
DK
1624 pkgCacheFile CacheFile;
1625 pkgCache *Cache = CacheFile.GetPkgCache();
1626 pkgPolicy *Plcy = CacheFile.GetPolicy();
1627 pkgSourceList *SrcList = CacheFile.GetSourceList();
1628 if (unlikely(Cache == NULL || Plcy == NULL || SrcList == NULL))
af87ab54 1629 return false;
d9eb210e 1630
0588779f
DK
1631 /* Should the MultiArchKiller be run to see which pseudo packages for an
1632 arch all package are currently installed? Activating it gives a speed
1633 penality for no real gain beside enhanced debugging, so in general no. */
1634 if (_config->FindB("APT::Cache::Policy::DepCache", false) == true)
1635 CacheFile.GetDepCache();
1636
af87ab54
AL
1637 // Print out all of the package files
1638 if (CmdL.FileList[1] == 0)
1639 {
db0db9fe 1640 cout << _("Package files:") << endl;
f7f0d6c7 1641 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; ++F)
af87ab54 1642 {
d2cb5b15
DK
1643 if (F.Flagged(pkgCache::Flag::NoPackages))
1644 continue;
af87ab54
AL
1645 // Locate the associated index files so we can derive a description
1646 pkgIndexFile *Indx;
1647 if (SrcList->FindIndex(F,Indx) == false &&
1648 _system->FindIndex(F,Indx) == false)
1649 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
78acd650
MV
1650
1651 printf("%4i %s\n",
d9eb210e 1652 Plcy->GetPriority(F),Indx->Describe(true).c_str());
af87ab54
AL
1653
1654 // Print the reference information for the package
1655 string Str = F.RelStr();
1656 if (Str.empty() == false)
1657 printf(" release %s\n",F.RelStr().c_str());
1658 if (F.Site() != 0 && F.Site()[0] != 0)
1659 printf(" origin %s\n",F.Site());
1660 }
1661
1662 // Show any packages have explicit pins
db0db9fe 1663 cout << _("Pinned packages:") << endl;
d9eb210e 1664 pkgCache::PkgIterator I = Cache->PkgBegin();
f7f0d6c7 1665 for (;I.end() != true; ++I)
af87ab54 1666 {
d9eb210e 1667 if (Plcy->GetPriority(I) == 0)
af87ab54
AL
1668 continue;
1669
1670 // Print the package name and the version we are forcing to
75ce2062 1671 cout << " " << I.FullName(true) << " -> ";
af87ab54 1672
d9eb210e 1673 pkgCache::VerIterator V = Plcy->GetMatch(I);
af87ab54
AL
1674 if (V.end() == true)
1675 cout << _("(not found)") << endl;
1676 else
1677 cout << V.VerStr() << endl;
1678 }
1679
1680 return true;
1681 }
6293e04f 1682
ca964703
DK
1683 char const * const msgInstalled = _(" Installed: ");
1684 char const * const msgCandidate = _(" Candidate: ");
1685 short const InstalledLessCandidate =
1686 mbstowcs(NULL, msgInstalled, 0) - mbstowcs(NULL, msgCandidate, 0);
1687 short const deepInstalled =
1688 (InstalledLessCandidate < 0 ? (InstalledLessCandidate*-1) : 0) - 1;
1689 short const deepCandidate =
1690 (InstalledLessCandidate > 0 ? (InstalledLessCandidate) : 0) - 1;
6293e04f 1691
af87ab54 1692 // Print out detailed information for each package
cd7bbc47 1693 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
c4cca791
DK
1694 APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
1695 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
af87ab54 1696 {
75ce2062 1697 cout << Pkg.FullName(true) << ":" << endl;
6293e04f 1698
af87ab54 1699 // Installed version
ca964703 1700 cout << msgInstalled << OutputInDepth(deepInstalled, " ");
af87ab54
AL
1701 if (Pkg->CurrentVer == 0)
1702 cout << _("(none)") << endl;
1703 else
1704 cout << Pkg.CurrentVer().VerStr() << endl;
1705
1706 // Candidate Version
ca964703 1707 cout << msgCandidate << OutputInDepth(deepCandidate, " ");
d9eb210e 1708 pkgCache::VerIterator V = Plcy->GetCandidateVer(Pkg);
af87ab54
AL
1709 if (V.end() == true)
1710 cout << _("(none)") << endl;
1711 else
1712 cout << V.VerStr() << endl;
1713
1714 // Pinned version
d9eb210e 1715 if (Plcy->GetPriority(Pkg) != 0)
af87ab54 1716 {
db0db9fe 1717 cout << _(" Package pin: ");
d9eb210e 1718 V = Plcy->GetMatch(Pkg);
af87ab54
AL
1719 if (V.end() == true)
1720 cout << _("(not found)") << endl;
1721 else
1722 cout << V.VerStr() << endl;
1723 }
1724
1725 // Show the priority tables
db0db9fe 1726 cout << _(" Version table:") << endl;
f7f0d6c7 1727 for (V = Pkg.VersionList(); V.end() == false; ++V)
af87ab54
AL
1728 {
1729 if (Pkg.CurrentVer() == V)
1730 cout << " *** " << V.VerStr();
1731 else
1732 cout << " " << V.VerStr();
b44c21bd 1733 cout << " " << Plcy->GetPriority(V) << endl;
f7f0d6c7 1734 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; ++VF)
af87ab54
AL
1735 {
1736 // Locate the associated index files so we can derive a description
1737 pkgIndexFile *Indx;
1738 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1739 _system->FindIndex(VF.File(),Indx) == false)
1740 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
d9eb210e 1741 printf(" %4i %s\n",Plcy->GetPriority(VF.File()),
af87ab54 1742 Indx->Describe(true).c_str());
6293e04f
DK
1743 }
1744 }
af87ab54
AL
1745 }
1746
f8f410f5
AL
1747 return true;
1748}
bd3d53ef
AL
1749 /*}}}*/
1750// Madison - Look a bit like katie's madison /*{{{*/
1751// ---------------------------------------------------------------------
1752/* */
c3ccac92 1753static bool Madison(CommandLine &CmdL)
bd3d53ef 1754{
d9eb210e
DK
1755 pkgCacheFile CacheFile;
1756 pkgSourceList *SrcList = CacheFile.GetSourceList();
bd3d53ef 1757
d9eb210e
DK
1758 if (SrcList == 0)
1759 return false;
bd3d53ef 1760
03cd434b
MV
1761 // Create the src text record parsers and ignore errors about missing
1762 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
bd3d53ef
AL
1763 pkgSrcRecords SrcRecs(*SrcList);
1764 if (_error->PendingError() == true)
03cd434b 1765 _error->Discard();
bd3d53ef 1766
cd7bbc47 1767 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
dc67d95f 1768 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
bd3d53ef 1769 {
dc67d95f 1770 _error->PushToStack();
c4cca791
DK
1771 APT::PackageList pkgset = APT::PackageList::FromString(CacheFile, *I, helper);
1772 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
bd3d53ef 1773 {
f7f0d6c7 1774 for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; ++V)
bd3d53ef 1775 {
f7f0d6c7 1776 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; ++VF)
bd3d53ef 1777 {
a0e710af
AL
1778// This might be nice, but wouldn't uniquely identify the source -mdz
1779// if (VF.File().Archive() != 0)
1780// {
1781// cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1782// << VF.File().Archive() << endl;
1783// }
1784
1785 // Locate the associated index files so we can derive a description
f7f0d6c7 1786 for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S)
bd3d53ef 1787 {
7db98ffc
MZ
1788 vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
1789 for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
f7f0d6c7 1790 IF != Indexes->end(); ++IF)
7db98ffc
MZ
1791 {
1792 if ((*IF)->FindInCache(*(VF.File().Cache())) == VF.File())
1793 {
75ce2062 1794 cout << setw(10) << Pkg.FullName(true) << " | " << setw(10) << V.VerStr() << " | "
7db98ffc
MZ
1795 << (*IF)->Describe(true) << endl;
1796 }
1797 }
bd3d53ef
AL
1798 }
1799 }
1800 }
1801 }
1802
bd3d53ef
AL
1803 SrcRecs.Restart();
1804 pkgSrcRecords::Parser *SrcParser;
dc67d95f
DK
1805 bool foundSomething = false;
1806 while ((SrcParser = SrcRecs.Find(*I, false)) != 0)
bd3d53ef 1807 {
dc67d95f 1808 foundSomething = true;
bd3d53ef
AL
1809 // Maybe support Release info here too eventually
1810 cout << setw(10) << SrcParser->Package() << " | "
1811 << setw(10) << SrcParser->Version() << " | "
1812 << SrcParser->Index().Describe(true) << endl;
1813 }
dc67d95f
DK
1814 if (foundSomething == true)
1815 _error->RevertToStack();
1816 else
1817 _error->MergeWithStack();
bd3d53ef
AL
1818 }
1819
1820 return true;
1821}
f8f410f5 1822 /*}}}*/
880e9be4
AL
1823// GenCaches - Call the main cache generator /*{{{*/
1824// ---------------------------------------------------------------------
1825/* */
65512241 1826static bool GenCaches(CommandLine &)
880e9be4 1827{
0a8e3465 1828 OpTextProgress Progress(*_config);
d9eb210e
DK
1829
1830 pkgCacheFile CacheFile;
1831 return CacheFile.BuildCaches(&Progress, true);
880e9be4
AL
1832}
1833 /*}}}*/
e1b74f61
AL
1834// ShowHelp - Show a help screen /*{{{*/
1835// ---------------------------------------------------------------------
1836/* */
65512241 1837static bool ShowHelp(CommandLine &)
e1b74f61 1838{
249aec3b
JB
1839 ioprintf(cout, "%s %s (%s)\n", PACKAGE, PACKAGE_VERSION, COMMON_ARCH);
1840
b13af988
AL
1841 if (_config->FindB("version") == true)
1842 return true;
1843
b2e465d6
AL
1844 cout <<
1845 _("Usage: apt-cache [options] command\n"
b2e465d6 1846 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
2d425135 1847 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
b2e465d6 1848 "\n"
7fefa184
DK
1849 "apt-cache is a low-level tool used to query information\n"
1850 "from APT's binary cache files\n"
b2e465d6
AL
1851 "\n"
1852 "Commands:\n"
b2e465d6
AL
1853 " gencaches - Build both the package and source cache\n"
1854 " showpkg - Show some general information for a single package\n"
2d425135 1855 " showsrc - Show source records\n"
b2e465d6
AL
1856 " stats - Show some basic statistics\n"
1857 " dump - Show the entire file in a terse form\n"
1858 " dumpavail - Print an available file to stdout\n"
1859 " unmet - Show unmet dependencies\n"
b2e465d6
AL
1860 " search - Search the package list for a regex pattern\n"
1861 " show - Show a readable record for the package\n"
1862 " depends - Show raw dependency information for a package\n"
eba2b51d 1863 " rdepends - Show reverse dependency information for a package\n"
2c120e24
EL
1864 " pkgnames - List the names of all packages in the system\n"
1865 " dotty - Generate package graphs for GraphViz\n"
fff4b7f3 1866 " xvcg - Generate package graphs for xvcg\n"
eba05d54 1867 " policy - Show policy settings\n"
b2e465d6
AL
1868 "\n"
1869 "Options:\n"
1870 " -h This help text.\n"
1871 " -p=? The package cache.\n"
1872 " -s=? The source cache.\n"
1873 " -q Disable progress indicator.\n"
1874 " -i Show only important deps for the unmet command.\n"
1875 " -c=? Read this configuration file\n"
a2884e32 1876 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
b2e465d6
AL
1877 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1878 return true;
e1b74f61
AL
1879}
1880 /*}}}*/
92fcbfc1 1881int main(int argc,const char *argv[]) /*{{{*/
1164783d 1882{
b9179170 1883 CommandLine::Dispatch Cmds[] = {{"help",&ShowHelp},
b0b4efb9 1884 {"gencaches",&GenCaches},
f8f410f5 1885 {"showsrc",&ShowSrcPackage},
b9179170 1886 {"showpkg",&DumpPackage},
b0b4efb9
AL
1887 {"stats",&Stats},
1888 {"dump",&Dump},
1889 {"dumpavail",&DumpAvail},
1890 {"unmet",&UnMet},
9dbb421f 1891 {"search",&Search},
349cd3b8 1892 {"depends",&Depends},
eba2b51d 1893 {"rdepends",&RDepends},
3e94da1b 1894 {"dotty",&Dotty},
fff4b7f3 1895 {"xvcg",&XVcg},
7e2e2d5d 1896 {"show",&ShowPackage},
7c1133fe 1897 {"pkgnames",&ShowPkgNames},
6007c1d4 1898 {"showauto",&ShowAuto},
af87ab54 1899 {"policy",&Policy},
bd3d53ef 1900 {"madison",&Madison},
b0b4efb9 1901 {0,0}};
0a8e3465 1902
b9179170
MV
1903 std::vector<CommandLine::Args> Args = getCommandArgs("apt-cache", CommandLine::GetCommand(Cmds, argc, argv));
1904
67111687
AL
1905 // Set up gettext support
1906 setlocale(LC_ALL,"");
1907 textdomain(PACKAGE);
1908
e1b74f61 1909 // Parse the command line and initialize the package library
ad7e0941
DK
1910 CommandLine CmdL;
1911 ParseCommandLine(CmdL, Cmds, Args.data(), &_config, &_system, argc, argv, ShowHelp);
8efa2a3b 1912
d9e518c6 1913 InitOutput();
a9a5908d 1914
320352e0
DK
1915 if (_config->Exists("APT::Cache::Generate") == true)
1916 _config->Set("pkgCacheFile::Generate", _config->FindB("APT::Cache::Generate", true));
1917
b9179170
MV
1918 // Match the operation
1919 CmdL.DispatchArg(Cmds);
f8f410f5 1920
1164783d 1921 // Print any errors or warnings found during parsing
65beb572
DK
1922 bool const Errors = _error->PendingError();
1923 if (_config->FindI("quiet",0) > 0)
1164783d 1924 _error->DumpErrors();
65beb572
DK
1925 else
1926 _error->DumpErrors(GlobalError::DEBUG);
1927 return Errors == true ? 100 : 0;
1164783d 1928}
92fcbfc1 1929 /*}}}*/