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