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