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