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