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