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