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