]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
review of new/changed translatable program strings
[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>
9055d5e6 46#include <apt-private/private-depends.h>
501cd23e 47#include <apt-private/private-show.h>
631800b1 48#include <apt-private/private-search.h>
e7e10e47 49#include <apt-private/private-main.h>
b9179170 50
9dbb421f 51#include <regex.h>
453b82a3 52#include <stddef.h>
3e94da1b 53#include <stdio.h>
453b82a3
DK
54#include <stdlib.h>
55#include <unistd.h>
472ff00e 56#include <algorithm>
453b82a3
DK
57#include <cstring>
58#include <iomanip>
59#include <iostream>
60#include <list>
61#include <map>
62#include <set>
63#include <string>
64#include <vector>
ea542140
DK
65
66#include <apti18n.h>
1164783d
AL
67 /*}}}*/
68
8f312f45
AL
69using namespace std;
70
cc718e9a
AL
71// UnMet - Show unmet dependencies /*{{{*/
72// ---------------------------------------------------------------------
73/* */
c3ccac92 74static bool ShowUnMet(pkgCache::VerIterator const &V, bool const Important)
cc718e9a 75{
cc718e9a 76 bool Header = false;
018f1533 77 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
cc718e9a
AL
78 {
79 // Collect or groups
80 pkgCache::DepIterator Start;
81 pkgCache::DepIterator End;
82 D.GlobOr(Start,End);
cc718e9a 83
018f1533
AL
84 // Important deps only
85 if (Important == true)
86 if (End->Type != pkgCache::Dep::PreDepends &&
7146a53c 87 End->Type != pkgCache::Dep::Depends)
018f1533 88 continue;
6ebaae9a
DK
89
90 // Skip conflicts and replaces
081c9d44 91 if (End.IsNegative() == true || End->Type == pkgCache::Dep::Replaces)
6ebaae9a
DK
92 continue;
93
cc718e9a
AL
94 // Verify the or group
95 bool OK = false;
96 pkgCache::DepIterator RealStart = Start;
97 do
98 {
99 // See if this dep is Ok
100 pkgCache::Version **VList = Start.AllTargets();
101 if (*VList != 0)
102 {
103 OK = true;
104 delete [] VList;
105 break;
106 }
107 delete [] VList;
081c9d44 108
cc718e9a
AL
109 if (Start == End)
110 break;
f7f0d6c7 111 ++Start;
cc718e9a
AL
112 }
113 while (1);
114
115 // The group is OK
116 if (OK == true)
117 continue;
118
119 // Oops, it failed..
120 if (Header == false)
b2e465d6 121 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
6ebaae9a 122 V.ParentPkg().FullName(true).c_str(),V.VerStr());
cc718e9a
AL
123 Header = true;
124
125 // Print out the dep type
126 cout << " " << End.DepType() << ": ";
127
128 // Show the group
129 Start = RealStart;
130 do
131 {
75ce2062 132 cout << Start.TargetPkg().FullName(true);
cc718e9a
AL
133 if (Start.TargetVer() != 0)
134 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
135 ")";
136 if (Start == End)
137 break;
138 cout << " | ";
f7f0d6c7 139 ++Start;
cc718e9a
AL
140 }
141 while (1);
142
143 cout << endl;
6ebaae9a
DK
144 }
145 return true;
146}
c3ccac92 147static bool UnMet(CommandLine &CmdL)
6ebaae9a
DK
148{
149 bool const Important = _config->FindB("APT::Cache::Important",false);
150
151 pkgCacheFile CacheFile;
152 if (unlikely(CacheFile.GetPkgCache() == NULL))
153 return false;
154
155 if (CmdL.FileSize() <= 1)
156 {
f7f0d6c7 157 for (pkgCache::PkgIterator P = CacheFile.GetPkgCache()->PkgBegin(); P.end() == false; ++P)
6ebaae9a
DK
158 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
159 if (ShowUnMet(V, Important) == false)
160 return false;
161 }
162 else
163 {
65f81081 164 CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
c4cca791 165 APT::VersionList verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1,
e6f0c9bc 166 APT::CacheSetHelper::CANDIDATE, helper);
c4cca791 167 for (APT::VersionList::iterator V = verset.begin(); V != verset.end(); ++V)
6ebaae9a
DK
168 if (ShowUnMet(V, Important) == false)
169 return false;
170 }
cc718e9a
AL
171 return true;
172}
173 /*}}}*/
1164783d
AL
174// DumpPackage - Show a dump of a package record /*{{{*/
175// ---------------------------------------------------------------------
176/* */
c3ccac92 177static bool DumpPackage(CommandLine &CmdL)
d9eb210e
DK
178{
179 pkgCacheFile CacheFile;
cd7bbc47 180 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
c4cca791 181 APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
1164783d 182
c4cca791 183 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
78c32596 184 {
75ce2062 185 cout << "Package: " << Pkg.FullName(true) << endl;
b2e465d6 186 cout << "Versions: " << endl;
f7f0d6c7 187 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
03e39e59
AL
188 {
189 cout << Cur.VerStr();
f7f0d6c7 190 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; ++Vf)
a52f938b
OS
191 cout << " (" << Vf.File().FileName() << ")";
192 cout << endl;
f7f0d6c7 193 for (pkgCache::DescIterator D = Cur.DescriptionList(); D.end() == false; ++D)
a52f938b
OS
194 {
195 cout << " Description Language: " << D.LanguageCode() << endl
196 << " File: " << D.FileList().File().FileName() << endl
197 << " MD5: " << D.md5() << endl;
198 }
b2e465d6 199 cout << endl;
03e39e59
AL
200 }
201
1164783d
AL
202 cout << endl;
203
204 cout << "Reverse Depends: " << endl;
f7f0d6c7 205 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; ++D)
b2e465d6 206 {
75ce2062 207 cout << " " << D.ParentPkg().FullName(true) << ',' << D.TargetPkg().FullName(true);
b2e465d6 208 if (D->Version != 0)
b1b663d1 209 cout << ' ' << DeNull(D.TargetVer()) << endl;
b2e465d6
AL
210 else
211 cout << endl;
212 }
213
1164783d 214 cout << "Dependencies: " << endl;
f7f0d6c7 215 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
1164783d
AL
216 {
217 cout << Cur.VerStr() << " - ";
f7f0d6c7 218 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; ++Dep)
75ce2062 219 cout << Dep.TargetPkg().FullName(true) << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
1164783d
AL
220 cout << endl;
221 }
222
223 cout << "Provides: " << endl;
f7f0d6c7 224 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; ++Cur)
1164783d
AL
225 {
226 cout << Cur.VerStr() << " - ";
f7f0d6c7 227 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; ++Prv)
ecc138f8 228 cout << Prv.ParentPkg().FullName(true) << " (= " << (Prv->ProvideVersion == 0 ? "" : Prv.ProvideVersion()) << ") ";
1164783d 229 cout << endl;
8efa2a3b
AL
230 }
231 cout << "Reverse Provides: " << endl;
f7f0d6c7 232 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; ++Prv)
ecc138f8 233 cout << Prv.OwnerPkg().FullName(true) << " " << Prv.OwnerVer().VerStr() << " (= " << (Prv->ProvideVersion == 0 ? "" : Prv.ProvideVersion()) << ")"<< endl;
1164783d
AL
234 }
235
236 return true;
237}
238 /*}}}*/
637c3b23
MV
239// ShowHashTableStats - Show stats about a hashtable /*{{{*/
240// ---------------------------------------------------------------------
241/* */
32ab4bd0
DK
242static map_pointer_t PackageNext(pkgCache::Package const * const P) { return P->NextPackage; }
243static map_pointer_t GroupNext(pkgCache::Group const * const G) { return G->Next; }
637c3b23
MV
244template<class T>
245static void ShowHashTableStats(std::string Type,
246 T *StartP,
ac2c559b 247 map_pointer_t *Hashtable,
32ab4bd0
DK
248 unsigned long Size,
249 map_pointer_t(*Next)(T const * const))
637c3b23
MV
250{
251 // hashtable stats for the HashTable
ac2c559b
DK
252 unsigned long NumBuckets = Size;
253 unsigned long UsedBuckets = 0;
254 unsigned long UnusedBuckets = 0;
255 unsigned long LongestBucket = 0;
256 unsigned long ShortestBucket = NumBuckets;
257 unsigned long Entries = 0;
637c3b23
MV
258 for (unsigned int i=0; i < NumBuckets; ++i)
259 {
260 T *P = StartP + Hashtable[i];
261 if(P == 0 || P == StartP)
262 {
ac2c559b 263 ++UnusedBuckets;
637c3b23
MV
264 continue;
265 }
ac2c559b
DK
266 ++UsedBuckets;
267 unsigned long ThisBucketSize = 0;
32ab4bd0 268 for (; P != StartP; P = StartP + Next(P))
ac2c559b
DK
269 ++ThisBucketSize;
270 Entries += ThisBucketSize;
637c3b23
MV
271 LongestBucket = std::max(ThisBucketSize, LongestBucket);
272 ShortestBucket = std::min(ThisBucketSize, ShortestBucket);
637c3b23 273 }
ac2c559b
DK
274 cout << "Total buckets in " << Type << ": " << NumBuckets << std::endl;
275 cout << " Unused: " << UnusedBuckets << std::endl;
637c3b23 276 cout << " Used: " << UsedBuckets << std::endl;
ac2c559b 277 cout << " Average entries: " << Entries/(double)NumBuckets << std::endl;
637c3b23
MV
278 cout << " Longest: " << LongestBucket << std::endl;
279 cout << " Shortest: " << ShortestBucket << std::endl;
280}
281 /*}}}*/
1164783d
AL
282// Stats - Dump some nice statistics /*{{{*/
283// ---------------------------------------------------------------------
284/* */
714c23a7 285static bool Stats(CommandLine &CmdL)
1164783d 286{
714c23a7
JAK
287 if (CmdL.FileSize() > 1) {
288 _error->Error(_("apt-cache stats does not take any arguments"));
289 return false;
290 }
7414af7f
DK
291
292 pkgCacheFile CacheFile;
293 pkgCache *Cache = CacheFile.GetPkgCache();
294
d9eb210e
DK
295 if (unlikely(Cache == NULL))
296 return false;
297
298 cout << _("Total package names: ") << Cache->Head().GroupCount << " (" <<
299 SizeToStr(Cache->Head().GroupCount*Cache->Head().GroupSz) << ')' << endl
300 << _("Total package structures: ") << Cache->Head().PackageCount << " (" <<
301 SizeToStr(Cache->Head().PackageCount*Cache->Head().PackageSz) << ')' << endl;
b2e465d6 302
1164783d
AL
303 int Normal = 0;
304 int Virtual = 0;
305 int NVirt = 0;
306 int DVirt = 0;
307 int Missing = 0;
d9eb210e 308 pkgCache::PkgIterator I = Cache->PkgBegin();
f7f0d6c7 309 for (;I.end() != true; ++I)
1164783d
AL
310 {
311 if (I->VersionList != 0 && I->ProvidesList == 0)
312 {
313 Normal++;
314 continue;
315 }
316
317 if (I->VersionList != 0 && I->ProvidesList != 0)
318 {
319 NVirt++;
320 continue;
321 }
322
323 if (I->VersionList == 0 && I->ProvidesList != 0)
324 {
325 // Only 1 provides
326 if (I.ProvidesList()->NextProvides == 0)
327 {
328 DVirt++;
329 }
330 else
331 Virtual++;
332 continue;
333 }
334 if (I->VersionList == 0 && I->ProvidesList == 0)
335 {
336 Missing++;
337 continue;
338 }
339 }
db0db9fe
CP
340 cout << _(" Normal packages: ") << Normal << endl;
341 cout << _(" Pure virtual packages: ") << Virtual << endl;
342 cout << _(" Single virtual packages: ") << DVirt << endl;
343 cout << _(" Mixed virtual packages: ") << NVirt << endl;
b2e465d6 344 cout << _(" Missing: ") << Missing << endl;
71c9e95b 345
d9eb210e
DK
346 cout << _("Total distinct versions: ") << Cache->Head().VersionCount << " (" <<
347 SizeToStr(Cache->Head().VersionCount*Cache->Head().VersionSz) << ')' << endl;
348 cout << _("Total distinct descriptions: ") << Cache->Head().DescriptionCount << " (" <<
349 SizeToStr(Cache->Head().DescriptionCount*Cache->Head().DescriptionSz) << ')' << endl;
71c9e95b
DK
350 cout << _("Total dependencies: ") << Cache->Head().DependsCount << "/" << Cache->Head().DependsDataCount << " (" <<
351 SizeToStr((Cache->Head().DependsCount*Cache->Head().DependencySz) +
352 (Cache->Head().DependsDataCount*Cache->Head().DependencyDataSz)) << ')' << endl;
d9eb210e
DK
353 cout << _("Total ver/file relations: ") << Cache->Head().VerFileCount << " (" <<
354 SizeToStr(Cache->Head().VerFileCount*Cache->Head().VerFileSz) << ')' << endl;
355 cout << _("Total Desc/File relations: ") << Cache->Head().DescFileCount << " (" <<
356 SizeToStr(Cache->Head().DescFileCount*Cache->Head().DescFileSz) << ')' << endl;
357 cout << _("Total Provides mappings: ") << Cache->Head().ProvidesCount << " (" <<
358 SizeToStr(Cache->Head().ProvidesCount*Cache->Head().ProvidesSz) << ')' << endl;
b2e465d6 359
a3a91fd7
DK
360 // String list stats
361 std::set<map_stringitem_t> stritems;
362 for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
363 stritems.insert(G->Name);
f7f0d6c7 364 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
b2e465d6 365 {
a3a91fd7 366 stritems.insert(P->Arch);
f7f0d6c7 367 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
b2e465d6 368 {
a3a91fd7
DK
369 if (V->VerStr != 0)
370 stritems.insert(V->VerStr);
371 if (V->Section != 0)
372 stritems.insert(V->Section);
a221efc3
DK
373 stritems.insert(V->SourcePkgName);
374 stritems.insert(V->SourceVerStr);
f7f0d6c7 375 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
b2e465d6
AL
376 {
377 if (D->Version != 0)
a3a91fd7
DK
378 stritems.insert(D->Version);
379 }
380 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
381 {
382 stritems.insert(D->md5sum);
383 stritems.insert(D->language_code);
b2e465d6
AL
384 }
385 }
a3a91fd7
DK
386 for (pkgCache::PrvIterator Prv = P.ProvidesList(); Prv.end() == false; ++Prv)
387 {
388 if (Prv->ProvideVersion != 0)
389 stritems.insert(Prv->ProvideVersion);
390 }
b2e465d6 391 }
b07aeb1a 392 for (pkgCache::RlsFileIterator F = Cache->RlsFileBegin(); F != Cache->RlsFileEnd(); ++F)
a3a91fd7
DK
393 {
394 stritems.insert(F->FileName);
395 stritems.insert(F->Archive);
396 stritems.insert(F->Codename);
a3a91fd7
DK
397 stritems.insert(F->Version);
398 stritems.insert(F->Origin);
399 stritems.insert(F->Label);
a3a91fd7 400 stritems.insert(F->Site);
b07aeb1a
DK
401 }
402 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F)
403 {
404 stritems.insert(F->FileName);
405 stritems.insert(F->Architecture);
406 stritems.insert(F->Component);
a3a91fd7
DK
407 stritems.insert(F->IndexType);
408 }
4dc77823 409
a3a91fd7
DK
410 unsigned long Size = 0;
411 for (std::set<map_stringitem_t>::const_iterator i = stritems.begin(); i != stritems.end(); ++i)
412 Size += strlen(Cache->StrP + *i) + 1;
a3a91fd7
DK
413 cout << _("Total globbed strings: ") << stritems.size() << " (" << SizeToStr(Size) << ')' << endl;
414 stritems.clear();
ac2c559b 415
f826cfaa
AL
416 unsigned long Slack = 0;
417 for (int I = 0; I != 7; I++)
d9eb210e 418 Slack += Cache->Head().Pools[I].ItemSize*Cache->Head().Pools[I].Count;
db0db9fe 419 cout << _("Total slack space: ") << SizeToStr(Slack) << endl;
ac2c559b 420
f826cfaa 421 unsigned long Total = 0;
ac2c559b
DK
422#define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
423 Total = Slack + Size +
424 APT_CACHESIZE(GroupCount, GroupSz) +
425 APT_CACHESIZE(PackageCount, PackageSz) +
426 APT_CACHESIZE(VersionCount, VersionSz) +
427 APT_CACHESIZE(DescriptionCount, DescriptionSz) +
428 APT_CACHESIZE(DependsCount, DependencySz) +
71c9e95b 429 APT_CACHESIZE(DependsDataCount, DependencyDataSz) +
b07aeb1a 430 APT_CACHESIZE(ReleaseFileCount, ReleaseFileSz) +
ac2c559b
DK
431 APT_CACHESIZE(PackageFileCount, PackageFileSz) +
432 APT_CACHESIZE(VerFileCount, VerFileSz) +
433 APT_CACHESIZE(DescFileCount, DescFileSz) +
434 APT_CACHESIZE(ProvidesCount, ProvidesSz) +
32ab4bd0 435 (2 * Cache->Head().GetHashTableSize() * sizeof(map_id_t));
db0db9fe 436 cout << _("Total space accounted for: ") << SizeToStr(Total) << endl;
ac2c559b 437#undef APT_CACHESIZE
a93a32b5 438
637c3b23 439 // hashtable stats
32ab4bd0
DK
440 ShowHashTableStats<pkgCache::Package>("PkgHashTable", Cache->PkgP, Cache->Head().PkgHashTableP(), Cache->Head().GetHashTableSize(), PackageNext);
441 ShowHashTableStats<pkgCache::Group>("GrpHashTable", Cache->GrpP, Cache->Head().GrpHashTableP(), Cache->Head().GetHashTableSize(), GroupNext);
a93a32b5 442
83d89a9f
AL
443 return true;
444}
445 /*}}}*/
1164783d
AL
446// Dump - show everything /*{{{*/
447// ---------------------------------------------------------------------
b2e465d6 448/* This is worthless except fer debugging things */
65512241 449static bool Dump(CommandLine &)
1164783d 450{
d9eb210e
DK
451 pkgCacheFile CacheFile;
452 pkgCache *Cache = CacheFile.GetPkgCache();
453 if (unlikely(Cache == NULL))
454 return false;
455
b9179170 456 std::cout << "Using Versioning System: " << Cache->VS->Label << std::endl;
b2e465d6 457
f7f0d6c7 458 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
1164783d 459 {
b9179170 460 std::cout << "Package: " << P.FullName(true) << std::endl;
f7f0d6c7 461 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
1164783d 462 {
b9179170
MV
463 std::cout << " Version: " << V.VerStr() << std::endl;
464 std::cout << " File: " << V.FileList().File().FileName() << std::endl;
f7f0d6c7 465 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ++D)
b9179170
MV
466 std::cout << " Depends: " << D.TargetPkg().FullName(true) << ' ' <<
467 DeNull(D.TargetVer()) << std::endl;
f7f0d6c7 468 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; ++D)
a52f938b 469 {
b9179170
MV
470 std::cout << " Description Language: " << D.LanguageCode() << std::endl
471 << " File: " << D.FileList().File().FileName() << std::endl
472 << " MD5: " << D.md5() << std::endl;
a52f938b 473 }
1164783d
AL
474 }
475 }
476
f7f0d6c7 477 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; ++F)
1164783d 478 {
b9179170
MV
479 std::cout << "File: " << F.FileName() << std::endl;
480 std::cout << " Type: " << F.IndexType() << std::endl;
481 std::cout << " Size: " << F->Size << std::endl;
482 std::cout << " ID: " << F->ID << std::endl;
483 std::cout << " Flags: " << F->Flags << std::endl;
484 std::cout << " Time: " << TimeRFC1123(F->mtime) << std::endl;
485 std::cout << " Archive: " << DeNull(F.Archive()) << std::endl;
486 std::cout << " Component: " << DeNull(F.Component()) << std::endl;
487 std::cout << " Version: " << DeNull(F.Version()) << std::endl;
488 std::cout << " Origin: " << DeNull(F.Origin()) << std::endl;
489 std::cout << " Site: " << DeNull(F.Site()) << std::endl;
490 std::cout << " Label: " << DeNull(F.Label()) << std::endl;
491 std::cout << " Architecture: " << DeNull(F.Architecture()) << std::endl;
1164783d
AL
492 }
493
494 return true;
495}
496 /*}}}*/
497// DumpAvail - Print out the available list /*{{{*/
498// ---------------------------------------------------------------------
b2e465d6
AL
499/* This is needed to make dpkg --merge happy.. I spent a bit of time to
500 make this run really fast, perhaps I went a little overboard.. */
65512241 501static bool DumpAvail(CommandLine &)
1164783d 502{
d9eb210e
DK
503 pkgCacheFile CacheFile;
504 pkgCache *Cache = CacheFile.GetPkgCache();
505 if (unlikely(Cache == NULL || CacheFile.BuildPolicy() == false))
b2e465d6 506 return false;
d9eb210e
DK
507
508 unsigned long Count = Cache->HeaderP->PackageCount+1;
fe648919
AL
509 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
510 memset(VFList,0,sizeof(*VFList)*Count);
b2e465d6
AL
511
512 // Map versions that we want to write out onto the VerList array.
f7f0d6c7 513 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
b2e465d6
AL
514 {
515 if (P->VersionList == 0)
5b8c90bf
AL
516 continue;
517
b2e465d6
AL
518 /* Find the proper version to use. If the policy says there are no
519 possible selections we return the installed version, if available..
520 This prevents dselect from making it obsolete. */
d9eb210e 521 pkgCache::VerIterator V = CacheFile.GetPolicy()->GetCandidateVer(P);
b2e465d6 522 if (V.end() == true)
ad00ae81 523 {
b2e465d6
AL
524 if (P->CurrentVer == 0)
525 continue;
526 V = P.CurrentVer();
ad00ae81 527 }
1164783d 528
b2e465d6 529 pkgCache::VerFileIterator VF = V.FileList();
f7f0d6c7 530 for (; VF.end() == false ; ++VF)
b2e465d6
AL
531 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
532 break;
533
534 /* Okay, here we have a bit of a problem.. The policy has selected the
535 currently installed package - however it only exists in the
536 status file.. We need to write out something or dselect will mark
537 the package as obsolete! Thus we emit the status file entry, but
538 below we remove the status line to make it valid for the
539 available file. However! We only do this if their do exist *any*
540 non-source versions of the package - that way the dselect obsolete
541 handling works OK. */
542 if (VF.end() == true)
1164783d 543 {
f7f0d6c7 544 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; ++Cur)
b2e465d6 545 {
f7f0d6c7 546 for (VF = Cur.FileList(); VF.end() == false; ++VF)
b2e465d6
AL
547 {
548 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
549 {
550 VF = V.FileList();
551 break;
552 }
553 }
554
555 if (VF.end() == false)
556 break;
557 }
ad00ae81 558 }
b2e465d6
AL
559
560 VFList[P->ID] = VF;
561 }
562
fe648919 563 LocalitySort(VFList,Count,sizeof(*VFList));
ad00ae81 564
88593886
DK
565 std::vector<pkgTagSection::Tag> RW;
566 RW.push_back(pkgTagSection::Tag::Remove("Status"));
567 RW.push_back(pkgTagSection::Tag::Remove("Config-Version"));
568 FileFd stdoutfd;
569 stdoutfd.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly, false);
570
b2e465d6 571 // Iterate over all the package files and write them out.
d9eb210e 572 char *Buffer = new char[Cache->HeaderP->MaxVerFileSize+10];
b2e465d6
AL
573 for (pkgCache::VerFile **J = VFList; *J != 0;)
574 {
d9eb210e 575 pkgCache::PkgFileIterator File(*Cache,(*J)->File + Cache->PkgFileP);
b2e465d6 576 if (File.IsOk() == false)
ad00ae81 577 {
b2e465d6
AL
578 _error->Error(_("Package file %s is out of sync."),File.FileName());
579 break;
580 }
bd432be3 581
4dde2b42 582 FileFd PkgF(File.FileName(),FileFd::ReadOnly, FileFd::Extension);
b2e465d6
AL
583 if (_error->PendingError() == true)
584 break;
585
586 /* Write all of the records from this package file, since we
587 already did locality sorting we can now just seek through the
588 file in read order. We apply 1 more optimization here, since often
589 there will be < 1 byte gaps between records (for the \n) we read that
590 into the next buffer and offset a bit.. */
591 unsigned long Pos = 0;
592 for (; *J != 0; J++)
593 {
d9eb210e 594 if ((*J)->File + Cache->PkgFileP != File)
b2e465d6 595 break;
bd432be3 596
b2e465d6
AL
597 const pkgCache::VerFile &VF = **J;
598
bd432be3 599 // Read the record and then write it out again.
b2e465d6
AL
600 unsigned long Jitter = VF.Offset - Pos;
601 if (Jitter > 8)
1164783d 602 {
b2e465d6
AL
603 if (PkgF.Seek(VF.Offset) == false)
604 break;
605 Jitter = 0;
606 }
607
608 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
609 break;
610 Buffer[VF.Size + Jitter] = '\n';
88593886 611
b2e465d6
AL
612 // See above..
613 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
614 {
615 pkgTagSection Tags;
b2e465d6 616 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
88593886
DK
617 Tags.Write(stdoutfd, NULL, RW) == false ||
618 stdoutfd.Write("\n", 1) == false)
b2e465d6
AL
619 {
620 _error->Error("Internal Error, Unable to parse a package record");
621 break;
622 }
b2e465d6
AL
623 }
624 else
625 {
88593886 626 if (stdoutfd.Write(Buffer + Jitter, VF.Size + 1) == false)
b2e465d6
AL
627 break;
628 }
88593886 629
b2e465d6 630 Pos = VF.Offset + VF.Size;
1164783d 631 }
b2e465d6 632
b2e465d6
AL
633 if (_error->PendingError() == true)
634 break;
ad00ae81 635 }
88593886 636
b2e465d6
AL
637 delete [] Buffer;
638 delete [] VFList;
639 return !_error->PendingError();
349cd3b8
AL
640}
641 /*}}}*/
fff4b7f3
AL
642// xvcg - Generate a graph for xvcg /*{{{*/
643// ---------------------------------------------------------------------
644// Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
645
c3ccac92 646static bool XVcg(CommandLine &CmdL)
fff4b7f3 647{
d9eb210e
DK
648 pkgCacheFile CacheFile;
649 pkgCache *Cache = CacheFile.GetPkgCache();
650 if (unlikely(Cache == NULL))
651 return false;
652
fff4b7f3
AL
653 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
654
655 /* Normal packages are boxes
656 Pure Provides are triangles
657 Mixed are diamonds
658 rhomb are missing packages*/
659 const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
660
661 /* Initialize the list of packages to show.
662 1 = To Show
663 2 = To Show no recurse
664 3 = Emitted no recurse
665 4 = Emitted
666 0 = None */
667 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
668 enum TheFlags {ForceNR=(1<<0)};
d9eb210e
DK
669 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
670 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
671 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
fff4b7f3
AL
672
673 // Show everything if no arguments given
674 if (CmdL.FileList[1] == 0)
d9eb210e 675 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
fff4b7f3
AL
676 Show[I] = ToShow;
677 else
d9eb210e 678 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
fff4b7f3 679 Show[I] = None;
d9eb210e 680 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
fff4b7f3
AL
681
682 // Map the shapes
f7f0d6c7 683 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
fff4b7f3
AL
684 {
685 if (Pkg->VersionList == 0)
686 {
687 // Missing
688 if (Pkg->ProvidesList == 0)
689 ShapeMap[Pkg->ID] = 0;
690 else
691 ShapeMap[Pkg->ID] = 1;
692 }
693 else
694 {
695 // Normal
696 if (Pkg->ProvidesList == 0)
697 ShapeMap[Pkg->ID] = 2;
698 else
699 ShapeMap[Pkg->ID] = 3;
700 }
701 }
3c977245 702
fff4b7f3 703 // Load the list of packages from the command line into the show list
cd7bbc47 704 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
fdba4d53
DK
705 std::list<APT::CacheSetHelper::PkgModifier> mods;
706 mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
707 mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
3c977245 708 std::map<unsigned short, APT::PackageSet> pkgsets =
cd7bbc47 709 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
3c977245
DK
710
711 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
712 Pkg != pkgsets[0].end(); ++Pkg)
713 Show[Pkg->ID] = ToShow;
714 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
715 Pkg != pkgsets[1].end(); ++Pkg)
fff4b7f3 716 {
fff4b7f3 717 Show[Pkg->ID] = ToShow;
3c977245 718 Flags[Pkg->ID] |= ForceNR;
fff4b7f3 719 }
3c977245 720
fff4b7f3
AL
721 // Little header
722 cout << "graph: { title: \"packages\"" << endl <<
723 "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
724 "layout_downfactor: 8" << endl;
725
726 bool Act = true;
727 while (Act == true)
728 {
729 Act = false;
f7f0d6c7 730 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
fff4b7f3
AL
731 {
732 // See we need to show this package
733 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
734 continue;
735
736 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
737
738 // Colour as done
739 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
740 {
741 // Pure Provides and missing packages have no deps!
742 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
743 Show[Pkg->ID] = Done;
744 else
745 Show[Pkg->ID] = DoneNR;
746 }
747 else
748 Show[Pkg->ID] = Done;
749 Act = true;
750
751 // No deps to map out
752 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
753 continue;
754
755 pkgCache::VerIterator Ver = Pkg.VersionList();
f7f0d6c7 756 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
fff4b7f3
AL
757 {
758 // See if anything can meet this dep
759 // Walk along the actual package providing versions
760 bool Hit = false;
761 pkgCache::PkgIterator DPkg = D.TargetPkg();
762 for (pkgCache::VerIterator I = DPkg.VersionList();
f7f0d6c7 763 I.end() == false && Hit == false; ++I)
fff4b7f3 764 {
d9eb210e 765 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
fff4b7f3
AL
766 Hit = true;
767 }
768
769 // Follow all provides
770 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
f7f0d6c7 771 I.end() == false && Hit == false; ++I)
fff4b7f3 772 {
d9eb210e 773 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
fff4b7f3
AL
774 Hit = true;
775 }
776
777
778 // Only graph critical deps
779 if (D.IsCritical() == true)
780 {
75ce2062 781 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.FullName(true).c_str(), D.TargetPkg().FullName(true).c_str() );
fff4b7f3
AL
782
783 // Colour the node for recursion
784 if (Show[D.TargetPkg()->ID] <= DoneNR)
785 {
786 /* If a conflicts does not meet anything in the database
787 then show the relation but do not recurse */
359e46db 788 if (Hit == false && D.IsNegative() == true)
fff4b7f3
AL
789 {
790 if (Show[D.TargetPkg()->ID] == None &&
791 Show[D.TargetPkg()->ID] != ToShow)
792 Show[D.TargetPkg()->ID] = ToShowNR;
793 }
794 else
795 {
796 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
797 Show[D.TargetPkg()->ID] = ToShowNR;
798 else
799 Show[D.TargetPkg()->ID] = ToShow;
800 }
801 }
802
803 // Edge colour
804 switch(D->Type)
805 {
806 case pkgCache::Dep::Conflicts:
807 printf("label: \"conflicts\" color: lightgreen }\n");
808 break;
308c7d30
IJ
809 case pkgCache::Dep::DpkgBreaks:
810 printf("label: \"breaks\" color: lightgreen }\n");
811 break;
fff4b7f3
AL
812 case pkgCache::Dep::Obsoletes:
813 printf("label: \"obsoletes\" color: lightgreen }\n");
814 break;
815
816 case pkgCache::Dep::PreDepends:
817 printf("label: \"predepends\" color: blue }\n");
818 break;
819
820 default:
821 printf("}\n");
822 break;
823 }
824 }
825 }
826 }
827 }
828
829 /* Draw the box colours after the fact since we can not tell what colour
830 they should be until everything is finished drawing */
f7f0d6c7 831 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
fff4b7f3
AL
832 {
833 if (Show[Pkg->ID] < DoneNR)
834 continue;
835
836 if (Show[Pkg->ID] == DoneNR)
75ce2062 837 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
fff4b7f3
AL
838 Shapes[ShapeMap[Pkg->ID]]);
839 else
75ce2062 840 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
fff4b7f3
AL
841 Shapes[ShapeMap[Pkg->ID]]);
842
843 }
03496041
DK
844
845 delete[] Show;
846 delete[] Flags;
847 delete[] ShapeMap;
848
fff4b7f3
AL
849 printf("}\n");
850 return true;
851}
852 /*}}}*/
3e94da1b
AL
853// Dotty - Generate a graph for Dotty /*{{{*/
854// ---------------------------------------------------------------------
855/* Dotty is the graphvis program for generating graphs. It is a fairly
856 simple queuing algorithm that just writes dependencies and nodes.
857 http://www.research.att.com/sw/tools/graphviz/ */
c3ccac92 858static bool Dotty(CommandLine &CmdL)
3e94da1b 859{
d9eb210e
DK
860 pkgCacheFile CacheFile;
861 pkgCache *Cache = CacheFile.GetPkgCache();
862 if (unlikely(Cache == NULL))
863 return false;
864
3e94da1b
AL
865 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
866
867 /* Normal packages are boxes
868 Pure Provides are triangles
869 Mixed are diamonds
870 Hexagons are missing packages*/
871 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
872
873 /* Initialize the list of packages to show.
874 1 = To Show
875 2 = To Show no recurse
876 3 = Emitted no recurse
877 4 = Emitted
878 0 = None */
879 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
880 enum TheFlags {ForceNR=(1<<0)};
d9eb210e
DK
881 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
882 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
883 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
3e94da1b
AL
884
885 // Show everything if no arguments given
886 if (CmdL.FileList[1] == 0)
d9eb210e 887 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
3e94da1b
AL
888 Show[I] = ToShow;
889 else
d9eb210e 890 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
3e94da1b 891 Show[I] = None;
d9eb210e 892 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
3e94da1b
AL
893
894 // Map the shapes
f7f0d6c7 895 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
3e94da1b
AL
896 {
897 if (Pkg->VersionList == 0)
898 {
899 // Missing
900 if (Pkg->ProvidesList == 0)
901 ShapeMap[Pkg->ID] = 0;
902 else
903 ShapeMap[Pkg->ID] = 1;
904 }
905 else
906 {
907 // Normal
908 if (Pkg->ProvidesList == 0)
909 ShapeMap[Pkg->ID] = 2;
910 else
911 ShapeMap[Pkg->ID] = 3;
912 }
913 }
3c977245 914
3e94da1b 915 // Load the list of packages from the command line into the show list
cd7bbc47 916 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
fdba4d53
DK
917 std::list<APT::CacheSetHelper::PkgModifier> mods;
918 mods.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
919 mods.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
3c977245 920 std::map<unsigned short, APT::PackageSet> pkgsets =
cd7bbc47 921 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper);
3c977245
DK
922
923 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
924 Pkg != pkgsets[0].end(); ++Pkg)
925 Show[Pkg->ID] = ToShow;
926 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
927 Pkg != pkgsets[1].end(); ++Pkg)
3e94da1b 928 {
3e94da1b 929 Show[Pkg->ID] = ToShow;
3c977245 930 Flags[Pkg->ID] |= ForceNR;
3e94da1b 931 }
3c977245 932
3e94da1b
AL
933 // Little header
934 printf("digraph packages {\n");
935 printf("concentrate=true;\n");
936 printf("size=\"30,40\";\n");
937
938 bool Act = true;
939 while (Act == true)
940 {
941 Act = false;
f7f0d6c7 942 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
3e94da1b
AL
943 {
944 // See we need to show this package
945 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
946 continue;
947
948 // Colour as done
949 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
950 {
951 // Pure Provides and missing packages have no deps!
952 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
953 Show[Pkg->ID] = Done;
954 else
955 Show[Pkg->ID] = DoneNR;
956 }
957 else
958 Show[Pkg->ID] = Done;
959 Act = true;
960
961 // No deps to map out
962 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
963 continue;
964
965 pkgCache::VerIterator Ver = Pkg.VersionList();
f7f0d6c7 966 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
3e94da1b
AL
967 {
968 // See if anything can meet this dep
969 // Walk along the actual package providing versions
970 bool Hit = false;
971 pkgCache::PkgIterator DPkg = D.TargetPkg();
972 for (pkgCache::VerIterator I = DPkg.VersionList();
f7f0d6c7 973 I.end() == false && Hit == false; ++I)
3e94da1b 974 {
d9eb210e 975 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
3e94da1b
AL
976 Hit = true;
977 }
978
979 // Follow all provides
980 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
f7f0d6c7 981 I.end() == false && Hit == false; ++I)
3e94da1b 982 {
d9eb210e 983 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
3e94da1b
AL
984 Hit = true;
985 }
986
987 // Only graph critical deps
988 if (D.IsCritical() == true)
989 {
75ce2062 990 printf("\"%s\" -> \"%s\"",Pkg.FullName(true).c_str(),D.TargetPkg().FullName(true).c_str());
3e94da1b
AL
991
992 // Colour the node for recursion
993 if (Show[D.TargetPkg()->ID] <= DoneNR)
994 {
995 /* If a conflicts does not meet anything in the database
996 then show the relation but do not recurse */
359e46db 997 if (Hit == false && D.IsNegative() == true)
3e94da1b
AL
998 {
999 if (Show[D.TargetPkg()->ID] == None &&
1000 Show[D.TargetPkg()->ID] != ToShow)
1001 Show[D.TargetPkg()->ID] = ToShowNR;
1002 }
1003 else
1004 {
1005 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
1006 Show[D.TargetPkg()->ID] = ToShowNR;
1007 else
1008 Show[D.TargetPkg()->ID] = ToShow;
1009 }
1010 }
1011
1012 // Edge colour
1013 switch(D->Type)
1014 {
1015 case pkgCache::Dep::Conflicts:
b2e465d6 1016 case pkgCache::Dep::Obsoletes:
359e46db 1017 case pkgCache::Dep::DpkgBreaks:
3e94da1b
AL
1018 printf("[color=springgreen];\n");
1019 break;
1020
1021 case pkgCache::Dep::PreDepends:
1022 printf("[color=blue];\n");
1023 break;
1024
1025 default:
1026 printf(";\n");
1027 break;
1028 }
1029 }
1030 }
1031 }
1032 }
1033
1034 /* Draw the box colours after the fact since we can not tell what colour
1035 they should be until everything is finished drawing */
f7f0d6c7 1036 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
3e94da1b
AL
1037 {
1038 if (Show[Pkg->ID] < DoneNR)
1039 continue;
1040
1041 // Orange box for early recursion stoppage
1042 if (Show[Pkg->ID] == DoneNR)
75ce2062 1043 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.FullName(true).c_str(),
3e94da1b
AL
1044 Shapes[ShapeMap[Pkg->ID]]);
1045 else
75ce2062 1046 printf("\"%s\" [shape=%s];\n",Pkg.FullName(true).c_str(),
3e94da1b
AL
1047 Shapes[ShapeMap[Pkg->ID]]);
1048 }
1049
1050 printf("}\n");
6070a346
DK
1051 delete[] Show;
1052 delete[] Flags;
1053 delete[] ShapeMap;
ad00ae81 1054 return true;
7e2e2d5d
AL
1055}
1056 /*}}}*/
182a6a55 1057/* ShowAuto - show automatically installed packages (sorted) {{{*/
65512241 1058static bool ShowAuto(CommandLine &)
6007c1d4 1059{
d9eb210e
DK
1060 pkgCacheFile CacheFile;
1061 pkgCache *Cache = CacheFile.GetPkgCache();
1062 pkgDepCache *DepCache = CacheFile.GetDepCache();
1063 if (unlikely(Cache == NULL || DepCache == NULL))
1064 return false;
6007c1d4
JAK
1065
1066 std::vector<string> packages;
d9eb210e 1067 packages.reserve(Cache->HeaderP->PackageCount / 3);
6007c1d4 1068
f7f0d6c7 1069 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
d9eb210e 1070 if ((*DepCache)[P].Flags & pkgCache::Flag::Auto)
6007c1d4
JAK
1071 packages.push_back(P.Name());
1072
1073 std::sort(packages.begin(), packages.end());
1074
f7f0d6c7 1075 for (vector<string>::iterator I = packages.begin(); I != packages.end(); ++I)
6007c1d4
JAK
1076 cout << *I << "\n";
1077
182a6a55 1078 _error->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
6007c1d4
JAK
1079 return true;
1080}
1164783d 1081 /*}}}*/
7c1133fe
AL
1082// ShowPkgNames - Show package names /*{{{*/
1083// ---------------------------------------------------------------------
1084/* This does a prefix match on the first argument */
c3ccac92 1085static bool ShowPkgNames(CommandLine &CmdL)
7c1133fe 1086{
d9eb210e
DK
1087 pkgCacheFile CacheFile;
1088 if (unlikely(CacheFile.BuildCaches(NULL, false) == false))
1089 return false;
1090 pkgCache::GrpIterator I = CacheFile.GetPkgCache()->GrpBegin();
6293e04f
DK
1091 bool const All = _config->FindB("APT::Cache::AllNames","false");
1092
7c1133fe
AL
1093 if (CmdL.FileList[1] != 0)
1094 {
f7f0d6c7 1095 for (;I.end() != true; ++I)
7c1133fe 1096 {
6293e04f
DK
1097 if (All == false && I->FirstPackage == 0)
1098 continue;
1099 if (I.FindPkg("any")->VersionList == 0)
7c1133fe 1100 continue;
7c1133fe
AL
1101 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1102 cout << I.Name() << endl;
1103 }
1104
1105 return true;
1106 }
1107
1108 // Show all pkgs
f7f0d6c7 1109 for (;I.end() != true; ++I)
7c1133fe 1110 {
6293e04f
DK
1111 if (All == false && I->FirstPackage == 0)
1112 continue;
1113 if (I.FindPkg("any")->VersionList == 0)
7c1133fe
AL
1114 continue;
1115 cout << I.Name() << endl;
1116 }
1117
f8f410f5
AL
1118 return true;
1119}
bd3d53ef
AL
1120 /*}}}*/
1121// Madison - Look a bit like katie's madison /*{{{*/
1122// ---------------------------------------------------------------------
1123/* */
c3ccac92 1124static bool Madison(CommandLine &CmdL)
bd3d53ef 1125{
d9eb210e
DK
1126 pkgCacheFile CacheFile;
1127 pkgSourceList *SrcList = CacheFile.GetSourceList();
bd3d53ef 1128
d9eb210e
DK
1129 if (SrcList == 0)
1130 return false;
bd3d53ef 1131
03cd434b
MV
1132 // Create the src text record parsers and ignore errors about missing
1133 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
bd3d53ef
AL
1134 pkgSrcRecords SrcRecs(*SrcList);
1135 if (_error->PendingError() == true)
03cd434b 1136 _error->Discard();
bd3d53ef 1137
cd7bbc47 1138 APT::CacheSetHelper helper(true, GlobalError::NOTICE);
dc67d95f 1139 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
bd3d53ef 1140 {
dc67d95f 1141 _error->PushToStack();
c4cca791
DK
1142 APT::PackageList pkgset = APT::PackageList::FromString(CacheFile, *I, helper);
1143 for (APT::PackageList::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
bd3d53ef 1144 {
f7f0d6c7 1145 for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; ++V)
bd3d53ef 1146 {
f7f0d6c7 1147 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; ++VF)
bd3d53ef 1148 {
a0e710af
AL
1149// This might be nice, but wouldn't uniquely identify the source -mdz
1150// if (VF.File().Archive() != 0)
1151// {
1152// cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1153// << VF.File().Archive() << endl;
1154// }
1155
1156 // Locate the associated index files so we can derive a description
f7f0d6c7 1157 for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S)
bd3d53ef 1158 {
7db98ffc
MZ
1159 vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
1160 for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
f7f0d6c7 1161 IF != Indexes->end(); ++IF)
7db98ffc
MZ
1162 {
1163 if ((*IF)->FindInCache(*(VF.File().Cache())) == VF.File())
1164 {
75ce2062 1165 cout << setw(10) << Pkg.FullName(true) << " | " << setw(10) << V.VerStr() << " | "
7db98ffc
MZ
1166 << (*IF)->Describe(true) << endl;
1167 }
1168 }
bd3d53ef
AL
1169 }
1170 }
1171 }
1172 }
1173
bd3d53ef
AL
1174 SrcRecs.Restart();
1175 pkgSrcRecords::Parser *SrcParser;
dc67d95f
DK
1176 bool foundSomething = false;
1177 while ((SrcParser = SrcRecs.Find(*I, false)) != 0)
bd3d53ef 1178 {
dc67d95f 1179 foundSomething = true;
bd3d53ef
AL
1180 // Maybe support Release info here too eventually
1181 cout << setw(10) << SrcParser->Package() << " | "
1182 << setw(10) << SrcParser->Version() << " | "
1183 << SrcParser->Index().Describe(true) << endl;
1184 }
dc67d95f
DK
1185 if (foundSomething == true)
1186 _error->RevertToStack();
1187 else
1188 _error->MergeWithStack();
bd3d53ef
AL
1189 }
1190
1191 return true;
1192}
f8f410f5 1193 /*}}}*/
880e9be4
AL
1194// GenCaches - Call the main cache generator /*{{{*/
1195// ---------------------------------------------------------------------
1196/* */
65512241 1197static bool GenCaches(CommandLine &)
880e9be4 1198{
0a8e3465 1199 OpTextProgress Progress(*_config);
d9eb210e
DK
1200
1201 pkgCacheFile CacheFile;
1202 return CacheFile.BuildCaches(&Progress, true);
880e9be4
AL
1203}
1204 /*}}}*/
8561c2fe 1205bool ShowHelp(CommandLine &) /*{{{*/
e1b74f61 1206{
cbbee23e 1207 std::cout <<
b2e465d6 1208 _("Usage: apt-cache [options] command\n"
cbbee23e 1209 " apt-cache [options] show pkg1 [pkg2 ...]\n"
b2e465d6 1210 "\n"
8561c2fe 1211 "apt-cache queries and displays available information about installed\n"
d04e44ac
JR
1212 "and installable packages. It works exclusively on the data acquired\n"
1213 "into the local cache via the 'update' command of e.g. apt-get. The\n"
1214 "displayed information may therefore be outdated if the last update was\n"
1215 "too long ago, but in exchange apt-cache works independently of the\n"
8561c2fe 1216 "availability of the configured sources (e.g. offline).\n");
b2e465d6 1217 return true;
e1b74f61
AL
1218}
1219 /*}}}*/
6079b276 1220std::vector<aptDispatchWithHelp> GetCommands() /*{{{*/
1164783d 1221{
011188e3 1222 return {
cbbee23e
DK
1223 {"gencaches",&GenCaches, nullptr},
1224 {"showsrc",&ShowSrcPackage, _("Show source records")},
1225 {"showpkg",&DumpPackage, nullptr},
1226 {"stats",&Stats, nullptr},
1227 {"dump",&Dump, nullptr},
1228 {"dumpavail",&DumpAvail, nullptr},
1229 {"unmet",&UnMet, nullptr},
1230 {"search",&DoSearch, _("Search the package list for a regex pattern")},
1231 {"depends",&Depends, _("Show raw dependency information for a package")},
1232 {"rdepends",&RDepends, _("Show reverse dependency information for a package")},
1233 {"dotty",&Dotty, nullptr},
1234 {"xvcg",&XVcg, nullptr},
1235 {"show",&ShowPackage, _("Show a readable record for the package")},
1236 {"pkgnames",&ShowPkgNames, _("List the names of all packages in the system")},
1237 {"showauto",&ShowAuto, nullptr},
1238 {"policy",&Policy, _("Show policy settings")},
1239 {"madison",&Madison, nullptr},
1240 {nullptr, nullptr, nullptr}
1241 };
011188e3
DK
1242}
1243 /*}}}*/
1244int main(int argc,const char *argv[]) /*{{{*/
1245{
1246 InitLocale();
0a8e3465 1247
e1b74f61 1248 // Parse the command line and initialize the package library
ad7e0941 1249 CommandLine CmdL;
011188e3 1250 auto const Cmds = ParseCommandLine(CmdL, APT_CMD::APT_CACHE, &_config, &_system, argc, argv);
8efa2a3b 1251
d9e518c6 1252 InitOutput();
a9a5908d 1253
320352e0
DK
1254 if (_config->Exists("APT::Cache::Generate") == true)
1255 _config->Set("pkgCacheFile::Generate", _config->FindB("APT::Cache::Generate", true));
1256
e7e10e47 1257 return DispatchCommandLine(CmdL, Cmds);
1164783d 1258}
92fcbfc1 1259 /*}}}*/