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