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