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