]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
G++3 fixes from Randolph
[apt.git] / cmdline / apt-cache.cc
CommitLineData
1164783d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
af87ab54 3// $Id: apt-cache.cc,v 1.47 2001/04/29 05:13:51 jgg 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
AL
33
34#include <iostream.h>
cdb970c7 35#include <unistd.h>
43981212 36#include <errno.h>
9dbb421f 37#include <regex.h>
3e94da1b 38#include <stdio.h>
1164783d
AL
39 /*}}}*/
40
b0b4efb9 41pkgCache *GCache = 0;
af87ab54 42pkgSourceList *SrcList = 0;
b0b4efb9 43
b2e465d6
AL
44// LocalitySort - Sort a version list by package file locality /*{{{*/
45// ---------------------------------------------------------------------
46/* */
47int LocalityCompare(const void *a, const void *b)
48{
49 pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
50 pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
51
52 if (A == 0 && B == 0)
53 return 0;
54 if (A == 0)
55 return 1;
56 if (B == 0)
57 return -1;
58
59 if (A->File == B->File)
60 return A->Offset - B->Offset;
61 return A->File - B->File;
62}
63
64void LocalitySort(pkgCache::VerFile **begin,
65 unsigned long Count,size_t Size)
66{
67 qsort(begin,Count,Size,LocalityCompare);
68}
69 /*}}}*/
cc718e9a
AL
70// UnMet - Show unmet dependencies /*{{{*/
71// ---------------------------------------------------------------------
72/* */
b0b4efb9 73bool UnMet(CommandLine &CmdL)
cc718e9a 74{
b0b4efb9 75 pkgCache &Cache = *GCache;
76fbce56 76 bool Important = _config->FindB("APT::Cache::Important",false);
018f1533 77
cc718e9a
AL
78 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
79 {
80 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
81 {
82 bool Header = false;
018f1533 83 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
cc718e9a
AL
84 {
85 // Collect or groups
86 pkgCache::DepIterator Start;
87 pkgCache::DepIterator End;
88 D.GlobOr(Start,End);
89
018f1533 90 // Skip conflicts and replaces
cc718e9a
AL
91 if (End->Type != pkgCache::Dep::PreDepends &&
92 End->Type != pkgCache::Dep::Depends &&
93 End->Type != pkgCache::Dep::Suggests &&
94 End->Type != pkgCache::Dep::Recommends)
95 continue;
96
018f1533
AL
97 // Important deps only
98 if (Important == true)
99 if (End->Type != pkgCache::Dep::PreDepends &&
100 End->Type != pkgCache::Dep::Depends)
101 continue;
102
cc718e9a
AL
103 // Verify the or group
104 bool OK = false;
105 pkgCache::DepIterator RealStart = Start;
106 do
107 {
108 // See if this dep is Ok
109 pkgCache::Version **VList = Start.AllTargets();
110 if (*VList != 0)
111 {
112 OK = true;
113 delete [] VList;
114 break;
115 }
116 delete [] VList;
117
118 if (Start == End)
119 break;
120 Start++;
121 }
122 while (1);
123
124 // The group is OK
125 if (OK == true)
126 continue;
127
128 // Oops, it failed..
129 if (Header == false)
b2e465d6
AL
130 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
131 P.Name(),V.VerStr());
cc718e9a
AL
132 Header = true;
133
134 // Print out the dep type
135 cout << " " << End.DepType() << ": ";
136
137 // Show the group
138 Start = RealStart;
139 do
140 {
141 cout << Start.TargetPkg().Name();
142 if (Start.TargetVer() != 0)
143 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
144 ")";
145 if (Start == End)
146 break;
147 cout << " | ";
148 Start++;
149 }
150 while (1);
151
152 cout << endl;
153 }
154 }
155 }
156 return true;
157}
158 /*}}}*/
1164783d
AL
159// DumpPackage - Show a dump of a package record /*{{{*/
160// ---------------------------------------------------------------------
161/* */
b0b4efb9 162bool DumpPackage(CommandLine &CmdL)
ad00ae81 163{
b0b4efb9 164 pkgCache &Cache = *GCache;
e1b74f61 165 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1164783d 166 {
e1b74f61 167 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1164783d
AL
168 if (Pkg.end() == true)
169 {
b2e465d6 170 _error->Warning(_("Unable to locate package %s"),*I);
1164783d
AL
171 continue;
172 }
173
174 cout << "Package: " << Pkg.Name() << endl;
b2e465d6 175 cout << "Versions: " << endl;
1164783d 176 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
03e39e59
AL
177 {
178 cout << Cur.VerStr();
179 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
180 cout << "(" << Vf.File().FileName() << ")";
b2e465d6 181 cout << endl;
03e39e59
AL
182 }
183
1164783d
AL
184 cout << endl;
185
186 cout << "Reverse Depends: " << endl;
187 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
b2e465d6
AL
188 {
189 cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name();
190 if (D->Version != 0)
191 cout << ' ' << D.TargetVer() << endl;
192 else
193 cout << endl;
194 }
195
1164783d
AL
196 cout << "Dependencies: " << endl;
197 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
198 {
199 cout << Cur.VerStr() << " - ";
200 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
201 cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << Dep.TargetVer() << ") ";
202 cout << endl;
203 }
204
205 cout << "Provides: " << endl;
206 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
207 {
208 cout << Cur.VerStr() << " - ";
209 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
210 cout << Prv.ParentPkg().Name() << " ";
211 cout << endl;
8efa2a3b
AL
212 }
213 cout << "Reverse Provides: " << endl;
214 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
2d6751b9 215 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr() << endl;
1164783d
AL
216 }
217
218 return true;
219}
220 /*}}}*/
221// Stats - Dump some nice statistics /*{{{*/
222// ---------------------------------------------------------------------
223/* */
b0b4efb9 224bool Stats(CommandLine &Cmd)
1164783d 225{
b0b4efb9 226 pkgCache &Cache = *GCache;
b2e465d6 227 cout << _("Total Package Names : ") << Cache.Head().PackageCount << " (" <<
f826cfaa 228 SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
b2e465d6 229
1164783d
AL
230 int Normal = 0;
231 int Virtual = 0;
232 int NVirt = 0;
233 int DVirt = 0;
234 int Missing = 0;
b2e465d6 235 pkgCache::PkgIterator I = Cache.PkgBegin();
1164783d
AL
236 for (;I.end() != true; I++)
237 {
238 if (I->VersionList != 0 && I->ProvidesList == 0)
239 {
240 Normal++;
241 continue;
242 }
243
244 if (I->VersionList != 0 && I->ProvidesList != 0)
245 {
246 NVirt++;
247 continue;
248 }
249
250 if (I->VersionList == 0 && I->ProvidesList != 0)
251 {
252 // Only 1 provides
253 if (I.ProvidesList()->NextProvides == 0)
254 {
255 DVirt++;
256 }
257 else
258 Virtual++;
259 continue;
260 }
261 if (I->VersionList == 0 && I->ProvidesList == 0)
262 {
263 Missing++;
264 continue;
265 }
266 }
b2e465d6
AL
267 cout << _(" Normal Packages: ") << Normal << endl;
268 cout << _(" Pure Virtual Packages: ") << Virtual << endl;
269 cout << _(" Single Virtual Packages: ") << DVirt << endl;
270 cout << _(" Mixed Virtual Packages: ") << NVirt << endl;
271 cout << _(" Missing: ") << Missing << endl;
1164783d 272
b2e465d6 273 cout << _("Total Distinct Versions: ") << Cache.Head().VersionCount << " (" <<
f826cfaa 274 SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
b2e465d6 275 cout << _("Total Dependencies: ") << Cache.Head().DependsCount << " (" <<
f826cfaa
AL
276 SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
277
b2e465d6 278 cout << _("Total Ver/File relations: ") << Cache.Head().VerFileCount << " (" <<
a7e66b17 279 SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
b2e465d6 280 cout << _("Total Provides Mappings: ") << Cache.Head().ProvidesCount << " (" <<
a7e66b17 281 SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
f826cfaa
AL
282
283 // String list stats
284 unsigned long Size = 0;
285 unsigned long Count = 0;
286 for (pkgCache::StringItem *I = Cache.StringItemP + Cache.Head().StringList;
287 I!= Cache.StringItemP; I = Cache.StringItemP + I->NextItem)
288 {
289 Count++;
b2e465d6 290 Size += strlen(Cache.StrP + I->String) + 1;
f826cfaa 291 }
b2e465d6
AL
292 cout << _("Total Globbed Strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
293
294 unsigned long DepVerSize = 0;
295 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
296 {
297 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
298 {
299 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
300 {
301 if (D->Version != 0)
302 DepVerSize += strlen(D.TargetVer()) + 1;
303 }
304 }
305 }
306 cout << _("Total Dependency Version space: ") << SizeToStr(DepVerSize) << endl;
307
f826cfaa
AL
308 unsigned long Slack = 0;
309 for (int I = 0; I != 7; I++)
310 Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count;
b2e465d6 311 cout << _("Total Slack space: ") << SizeToStr(Slack) << endl;
f826cfaa
AL
312
313 unsigned long Total = 0;
314 Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz +
315 Cache.Head().VersionCount*Cache.Head().VersionSz +
a7e66b17
AL
316 Cache.Head().PackageCount*Cache.Head().PackageSz +
317 Cache.Head().VerFileCount*Cache.Head().VerFileSz +
318 Cache.Head().ProvidesCount*Cache.Head().ProvidesSz;
b2e465d6 319 cout << _("Total Space Accounted for: ") << SizeToStr(Total) << endl;
f826cfaa 320
83d89a9f
AL
321 return true;
322}
323 /*}}}*/
1164783d
AL
324// Dump - show everything /*{{{*/
325// ---------------------------------------------------------------------
b2e465d6 326/* This is worthless except fer debugging things */
b0b4efb9 327bool Dump(CommandLine &Cmd)
1164783d 328{
b0b4efb9 329 pkgCache &Cache = *GCache;
b2e465d6
AL
330 cout << "Using Versioning System: " << Cache.VS->Label << endl;
331
1164783d
AL
332 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
333 {
334 cout << "Package: " << P.Name() << endl;
335 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
336 {
337 cout << " Version: " << V.VerStr() << endl;
338 cout << " File: " << V.FileList().File().FileName() << endl;
339 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
340 cout << " Depends: " << D.TargetPkg().Name() << ' ' << D.TargetVer() << endl;
341 }
342 }
343
b2e465d6 344 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
1164783d
AL
345 {
346 cout << "File: " << F.FileName() << endl;
b2e465d6 347 cout << " Type: " << F.IndexType() << endl;
1164783d
AL
348 cout << " Size: " << F->Size << endl;
349 cout << " ID: " << F->ID << endl;
350 cout << " Flags: " << F->Flags << endl;
b0b4efb9
AL
351 cout << " Time: " << TimeRFC1123(F->mtime) << endl;
352 cout << " Archive: " << F.Archive() << endl;
353 cout << " Component: " << F.Component() << endl;
354 cout << " Version: " << F.Version() << endl;
355 cout << " Origin: " << F.Origin() << endl;
b2e465d6 356 cout << " Site: " << F.Site() << endl;
b0b4efb9
AL
357 cout << " Label: " << F.Label() << endl;
358 cout << " Architecture: " << F.Architecture() << endl;
1164783d
AL
359 }
360
361 return true;
362}
363 /*}}}*/
364// DumpAvail - Print out the available list /*{{{*/
365// ---------------------------------------------------------------------
b2e465d6
AL
366/* This is needed to make dpkg --merge happy.. I spent a bit of time to
367 make this run really fast, perhaps I went a little overboard.. */
b0b4efb9 368bool DumpAvail(CommandLine &Cmd)
1164783d 369{
b0b4efb9 370 pkgCache &Cache = *GCache;
1164783d 371
b2e465d6
AL
372 pkgPolicy Plcy(&Cache);
373 if (ReadPinFile(Plcy) == false)
374 return false;
375
376 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Cache.HeaderP->PackageCount];
377 memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount);
378
379 // Map versions that we want to write out onto the VerList array.
380 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
381 {
382 if (P->VersionList == 0)
5b8c90bf
AL
383 continue;
384
b2e465d6
AL
385 /* Find the proper version to use. If the policy says there are no
386 possible selections we return the installed version, if available..
387 This prevents dselect from making it obsolete. */
388 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
389 if (V.end() == true)
ad00ae81 390 {
b2e465d6
AL
391 if (P->CurrentVer == 0)
392 continue;
393 V = P.CurrentVer();
ad00ae81 394 }
1164783d 395
b2e465d6
AL
396 pkgCache::VerFileIterator VF = V.FileList();
397 for (; VF.end() == false ; VF++)
398 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
399 break;
400
401 /* Okay, here we have a bit of a problem.. The policy has selected the
402 currently installed package - however it only exists in the
403 status file.. We need to write out something or dselect will mark
404 the package as obsolete! Thus we emit the status file entry, but
405 below we remove the status line to make it valid for the
406 available file. However! We only do this if their do exist *any*
407 non-source versions of the package - that way the dselect obsolete
408 handling works OK. */
409 if (VF.end() == true)
1164783d 410 {
b2e465d6
AL
411 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; Cur++)
412 {
413 for (VF = Cur.FileList(); VF.end() == false; VF++)
414 {
415 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
416 {
417 VF = V.FileList();
418 break;
419 }
420 }
421
422 if (VF.end() == false)
423 break;
424 }
ad00ae81 425 }
b2e465d6
AL
426
427 VFList[P->ID] = VF;
428 }
429
430 LocalitySort(VFList,Cache.HeaderP->PackageCount,sizeof(*VFList));
ad00ae81 431
b2e465d6
AL
432 // Iterate over all the package files and write them out.
433 char *Buffer = new char[Cache.HeaderP->MaxVerFileSize+10];
434 for (pkgCache::VerFile **J = VFList; *J != 0;)
435 {
436 pkgCache::PkgFileIterator File(Cache,(*J)->File + Cache.PkgFileP);
437 if (File.IsOk() == false)
ad00ae81 438 {
b2e465d6
AL
439 _error->Error(_("Package file %s is out of sync."),File.FileName());
440 break;
441 }
bd432be3 442
b2e465d6
AL
443 FileFd PkgF(File.FileName(),FileFd::ReadOnly);
444 if (_error->PendingError() == true)
445 break;
446
447 /* Write all of the records from this package file, since we
448 already did locality sorting we can now just seek through the
449 file in read order. We apply 1 more optimization here, since often
450 there will be < 1 byte gaps between records (for the \n) we read that
451 into the next buffer and offset a bit.. */
452 unsigned long Pos = 0;
453 for (; *J != 0; J++)
454 {
455 if ((*J)->File + Cache.PkgFileP != File)
456 break;
bd432be3 457
b2e465d6
AL
458 const pkgCache::VerFile &VF = **J;
459
bd432be3 460 // Read the record and then write it out again.
b2e465d6
AL
461 unsigned long Jitter = VF.Offset - Pos;
462 if (Jitter > 8)
1164783d 463 {
b2e465d6
AL
464 if (PkgF.Seek(VF.Offset) == false)
465 break;
466 Jitter = 0;
467 }
468
469 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
470 break;
471 Buffer[VF.Size + Jitter] = '\n';
472
473 // See above..
474 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
475 {
476 pkgTagSection Tags;
477 TFRewriteData RW[] = {{"Status",0},{}};
478 const char *Zero = 0;
479 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
480 TFRewrite(stdout,Tags,&Zero,RW) == false)
481 {
482 _error->Error("Internal Error, Unable to parse a package record");
483 break;
484 }
485 fputc('\n',stdout);
486 }
487 else
488 {
489 if (fwrite(Buffer+Jitter,VF.Size+1,1,stdout) != 1)
490 break;
491 }
492
493 Pos = VF.Offset + VF.Size;
1164783d 494 }
b2e465d6
AL
495
496 fflush(stdout);
497 if (_error->PendingError() == true)
498 break;
ad00ae81
AL
499 }
500
b2e465d6
AL
501 delete [] Buffer;
502 delete [] VFList;
503 return !_error->PendingError();
349cd3b8
AL
504}
505 /*}}}*/
4b1b89c5 506// Depends - Print out a dependency tree /*{{{*/
349cd3b8
AL
507// ---------------------------------------------------------------------
508/* */
509bool Depends(CommandLine &CmdL)
510{
511 pkgCache &Cache = *GCache;
b2e465d6
AL
512 SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
513 memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
349cd3b8
AL
514
515 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
516 {
517 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
518 if (Pkg.end() == true)
519 {
b2e465d6 520 _error->Warning(_("Unable to locate package %s"),*I);
349cd3b8
AL
521 continue;
522 }
b2e465d6
AL
523 Colours[Pkg->ID] = 1;
524 }
525
526 bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
527 bool DidSomething;
528 do
529 {
530 DidSomething = false;
531 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
349cd3b8 532 {
b2e465d6
AL
533 if (Colours[Pkg->ID] != 1)
534 continue;
535 Colours[Pkg->ID] = 2;
536 DidSomething = true;
349cd3b8 537
b2e465d6
AL
538 pkgCache::VerIterator Ver = Pkg.VersionList();
539 if (Ver.end() == true)
349cd3b8 540 {
b2e465d6
AL
541 cout << '<' << Pkg.Name() << '>' << endl;
542 continue;
349cd3b8 543 }
b2e465d6
AL
544
545 cout << Pkg.Name() << endl;
546
547 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
548 {
549 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
550 cout << " |";
551 else
552 cout << " ";
553
554 // Show the package
555 pkgCache::PkgIterator Trg = D.TargetPkg();
556 if (Trg->VersionList == 0)
557 cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
558 else
559 cout << D.DepType() << ": " << Trg.Name() << endl;
560
561 if (Recurse == true)
562 Colours[D.TargetPkg()->ID]++;
563
564 // Display all solutions
565 SPtrArray<pkgCache::Version *> List = D.AllTargets();
566 pkgPrioSortList(Cache,List);
567 for (pkgCache::Version **I = List; *I != 0; I++)
568 {
569 pkgCache::VerIterator V(Cache,*I);
570 if (V != Cache.VerP + V.ParentPkg()->VersionList ||
571 V->ParentPkg == D->Package)
572 continue;
573 cout << " " << V.ParentPkg().Name() << endl;
574
575 if (Recurse == true)
576 Colours[D.ParentPkg()->ID]++;
577 }
578 }
579 }
349cd3b8 580 }
b2e465d6 581 while (DidSomething == true);
349cd3b8 582
3e94da1b
AL
583 return true;
584}
585 /*}}}*/
586// Dotty - Generate a graph for Dotty /*{{{*/
587// ---------------------------------------------------------------------
588/* Dotty is the graphvis program for generating graphs. It is a fairly
589 simple queuing algorithm that just writes dependencies and nodes.
590 http://www.research.att.com/sw/tools/graphviz/ */
591bool Dotty(CommandLine &CmdL)
592{
593 pkgCache &Cache = *GCache;
594 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
595
596 /* Normal packages are boxes
597 Pure Provides are triangles
598 Mixed are diamonds
599 Hexagons are missing packages*/
600 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
601
602 /* Initialize the list of packages to show.
603 1 = To Show
604 2 = To Show no recurse
605 3 = Emitted no recurse
606 4 = Emitted
607 0 = None */
608 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
609 enum TheFlags {ForceNR=(1<<0)};
610 unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
611 unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
612 unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
613
614 // Show everything if no arguments given
615 if (CmdL.FileList[1] == 0)
616 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
617 Show[I] = ToShow;
618 else
619 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
620 Show[I] = None;
621 memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
622
623 // Map the shapes
624 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
625 {
626 if (Pkg->VersionList == 0)
627 {
628 // Missing
629 if (Pkg->ProvidesList == 0)
630 ShapeMap[Pkg->ID] = 0;
631 else
632 ShapeMap[Pkg->ID] = 1;
633 }
634 else
635 {
636 // Normal
637 if (Pkg->ProvidesList == 0)
638 ShapeMap[Pkg->ID] = 2;
639 else
640 ShapeMap[Pkg->ID] = 3;
641 }
642 }
643
644 // Load the list of packages from the command line into the show list
645 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
646 {
647 // Process per-package flags
648 string P = *I;
649 bool Force = false;
650 if (P.length() > 3)
651 {
652 if (P.end()[-1] == '^')
653 {
654 Force = true;
655 P.erase(P.end()-1);
656 }
657
658 if (P.end()[-1] == ',')
659 P.erase(P.end()-1);
660 }
661
662 // Locate the package
663 pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
664 if (Pkg.end() == true)
665 {
b2e465d6 666 _error->Warning(_("Unable to locate package %s"),*I);
3e94da1b
AL
667 continue;
668 }
669 Show[Pkg->ID] = ToShow;
670
671 if (Force == true)
672 Flags[Pkg->ID] |= ForceNR;
673 }
674
675 // Little header
676 printf("digraph packages {\n");
677 printf("concentrate=true;\n");
678 printf("size=\"30,40\";\n");
679
680 bool Act = true;
681 while (Act == true)
682 {
683 Act = false;
684 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
685 {
686 // See we need to show this package
687 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
688 continue;
689
690 // Colour as done
691 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
692 {
693 // Pure Provides and missing packages have no deps!
694 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
695 Show[Pkg->ID] = Done;
696 else
697 Show[Pkg->ID] = DoneNR;
698 }
699 else
700 Show[Pkg->ID] = Done;
701 Act = true;
702
703 // No deps to map out
704 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
705 continue;
706
707 pkgCache::VerIterator Ver = Pkg.VersionList();
708 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
709 {
710 // See if anything can meet this dep
711 // Walk along the actual package providing versions
712 bool Hit = false;
713 pkgCache::PkgIterator DPkg = D.TargetPkg();
714 for (pkgCache::VerIterator I = DPkg.VersionList();
715 I.end() == false && Hit == false; I++)
716 {
b2e465d6 717 if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
3e94da1b
AL
718 Hit = true;
719 }
720
721 // Follow all provides
722 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
723 I.end() == false && Hit == false; I++)
724 {
b2e465d6 725 if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
3e94da1b
AL
726 Hit = true;
727 }
728
729 // Only graph critical deps
730 if (D.IsCritical() == true)
731 {
732 printf("\"%s\" -> \"%s\"",Pkg.Name(),D.TargetPkg().Name());
733
734 // Colour the node for recursion
735 if (Show[D.TargetPkg()->ID] <= DoneNR)
736 {
737 /* If a conflicts does not meet anything in the database
738 then show the relation but do not recurse */
b2e465d6
AL
739 if (Hit == false &&
740 (D->Type == pkgCache::Dep::Conflicts ||
741 D->Type == pkgCache::Dep::Obsoletes))
3e94da1b
AL
742 {
743 if (Show[D.TargetPkg()->ID] == None &&
744 Show[D.TargetPkg()->ID] != ToShow)
745 Show[D.TargetPkg()->ID] = ToShowNR;
746 }
747 else
748 {
749 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
750 Show[D.TargetPkg()->ID] = ToShowNR;
751 else
752 Show[D.TargetPkg()->ID] = ToShow;
753 }
754 }
755
756 // Edge colour
757 switch(D->Type)
758 {
759 case pkgCache::Dep::Conflicts:
b2e465d6 760 case pkgCache::Dep::Obsoletes:
3e94da1b
AL
761 printf("[color=springgreen];\n");
762 break;
763
764 case pkgCache::Dep::PreDepends:
765 printf("[color=blue];\n");
766 break;
767
768 default:
769 printf(";\n");
770 break;
771 }
772 }
773 }
774 }
775 }
776
777 /* Draw the box colours after the fact since we can not tell what colour
778 they should be until everything is finished drawing */
779 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
780 {
781 if (Show[Pkg->ID] < DoneNR)
782 continue;
783
784 // Orange box for early recursion stoppage
785 if (Show[Pkg->ID] == DoneNR)
786 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.Name(),
787 Shapes[ShapeMap[Pkg->ID]]);
788 else
789 printf("\"%s\" [shape=%s];\n",Pkg.Name(),
790 Shapes[ShapeMap[Pkg->ID]]);
791 }
792
793 printf("}\n");
ad00ae81
AL
794 return true;
795}
796 /*}}}*/
797// DoAdd - Perform an adding operation /*{{{*/
798// ---------------------------------------------------------------------
799/* */
e1b74f61 800bool DoAdd(CommandLine &CmdL)
ad00ae81 801{
b2e465d6
AL
802 return _error->Error("Unimplemented");
803#if 0
e1b74f61
AL
804 // Make sure there is at least one argument
805 if (CmdL.FileSize() <= 1)
806 return _error->Error("You must give at least one file name");
ad00ae81
AL
807
808 // Open the cache
018f1533 809 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
ad00ae81
AL
810 if (_error->PendingError() == true)
811 return false;
812
813 DynamicMMap Map(CacheF,MMap::Public);
814 if (_error->PendingError() == true)
815 return false;
404ec98e 816
0a8e3465 817 OpTextProgress Progress(*_config);
404ec98e 818 pkgCacheGenerator Gen(Map,Progress);
ad00ae81
AL
819 if (_error->PendingError() == true)
820 return false;
821
e1b74f61
AL
822 unsigned long Length = CmdL.FileSize() - 1;
823 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
ad00ae81 824 {
e1b74f61 825 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
018f1533
AL
826 Progress.SubProgress(Length);
827
ad00ae81 828 // Do the merge
e1b74f61 829 FileFd TagF(*I,FileFd::ReadOnly);
ad00ae81
AL
830 debListParser Parser(TagF);
831 if (_error->PendingError() == true)
e1b74f61 832 return _error->Error("Problem opening %s",*I);
ad00ae81 833
b2e465d6 834 if (Gen.SelectFile(*I,"") == false)
ad00ae81
AL
835 return _error->Error("Problem with SelectFile");
836
837 if (Gen.MergeList(Parser) == false)
838 return _error->Error("Problem with MergeList");
1164783d 839 }
404ec98e
AL
840
841 Progress.Done();
b0b4efb9
AL
842 GCache = &Gen.GetCache();
843 Stats(CmdL);
ad00ae81 844
7e2e2d5d 845 return true;
b2e465d6 846#endif
7e2e2d5d
AL
847}
848 /*}}}*/
849// DisplayRecord - Displays the complete record for the package /*{{{*/
850// ---------------------------------------------------------------------
851/* This displays the package record from the proper package index file.
852 It is not used by DumpAvail for performance reasons. */
853bool DisplayRecord(pkgCache::VerIterator V)
854{
855 // Find an appropriate file
856 pkgCache::VerFileIterator Vf = V.FileList();
857 for (; Vf.end() == false; Vf++)
858 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
859 break;
860 if (Vf.end() == true)
861 Vf = V.FileList();
862
863 // Check and load the package list file
864 pkgCache::PkgFileIterator I = Vf.File();
865 if (I.IsOk() == false)
b2e465d6 866 return _error->Error(_("Package file %s is out of sync."),I.FileName());
7e2e2d5d
AL
867
868 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
869 if (_error->PendingError() == true)
870 return false;
871
872 // Read the record and then write it out again.
b2e465d6
AL
873 unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
874 Buffer[V.FileList()->Size] = '\n';
7e2e2d5d
AL
875 if (PkgF.Seek(V.FileList()->Offset) == false ||
876 PkgF.Read(Buffer,V.FileList()->Size) == false ||
b2e465d6 877 write(STDOUT_FILENO,Buffer,V.FileList()->Size+1) != V.FileList()->Size+1)
7e2e2d5d
AL
878 {
879 delete [] Buffer;
880 return false;
881 }
882
883 delete [] Buffer;
884
9dbb421f
AL
885 return true;
886}
887 /*}}}*/
888// Search - Perform a search /*{{{*/
889// ---------------------------------------------------------------------
890/* This searches the package names and pacakge descriptions for a pattern */
b2e465d6
AL
891struct ExVerFile
892{
893 pkgCache::VerFile *Vf;
894 bool NameMatch;
895};
896
9dbb421f
AL
897bool Search(CommandLine &CmdL)
898{
899 pkgCache &Cache = *GCache;
7e2e2d5d
AL
900 bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
901 bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
b2e465d6
AL
902 unsigned NumPatterns = CmdL.FileSize() -1;
903
904 pkgDepCache::Policy Plcy;
9dbb421f
AL
905
906 // Make sure there is at least one argument
b2e465d6
AL
907 if (NumPatterns < 1)
908 return _error->Error(_("You must give exactly one pattern"));
9dbb421f
AL
909
910 // Compile the regex pattern
b2e465d6
AL
911 regex_t *Patterns = new regex_t[NumPatterns];
912 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
913 for (unsigned I = 0; I != NumPatterns; I++)
914 {
915 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
916 REG_NOSUB) != 0)
917 {
918 for (; I != 0; I--)
919 regfree(&Patterns[I]);
920 return _error->Error("Regex compilation error");
921 }
922 }
9dbb421f
AL
923
924 // Create the text record parser
925 pkgRecords Recs(Cache);
926 if (_error->PendingError() == true)
b2e465d6
AL
927 {
928 for (unsigned I = 0; I != NumPatterns; I++)
929 regfree(&Patterns[I]);
9dbb421f 930 return false;
b2e465d6 931 }
9dbb421f 932
b2e465d6
AL
933 ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
934 memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
935
936 // Map versions that we want to write out onto the VerList array.
937 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
9dbb421f 938 {
0f2fa322 939 VFList[P->ID].NameMatch = NumPatterns != 0;
b2e465d6
AL
940 for (unsigned I = 0; I != NumPatterns; I++)
941 {
942 if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
0f2fa322
AL
943 VFList[P->ID].NameMatch &= true;
944 else
945 VFList[P->ID].NameMatch = false;
b2e465d6
AL
946 }
947
948 // Doing names only, drop any that dont match..
949 if (NamesOnly == true && VFList[P->ID].NameMatch == false)
950 continue;
951
952 // Find the proper version to use.
953 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
7e2e2d5d
AL
954 if (V.end() == true)
955 continue;
b2e465d6
AL
956 VFList[P->ID].Vf = V.FileList();
957 }
958
959 LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
7e2e2d5d 960
b2e465d6
AL
961 // Iterate over all the version records and check them
962 for (ExVerFile *J = VFList; J->Vf != 0; J++)
963 {
964 pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
0f2fa322
AL
965
966 bool Match = true;
967 if (J->NameMatch == false)
968 {
969 string LongDesc = P.LongDesc();
970 Match = NumPatterns != 0;
971 for (unsigned I = 0; I != NumPatterns; I++)
972 {
973 if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
974 Match &= true;
975 else
976 Match = false;
977 }
978 }
b2e465d6
AL
979
980 if (Match == true)
9dbb421f 981 {
7e2e2d5d 982 if (ShowFull == true)
b2e465d6
AL
983 {
984 const char *Start;
985 const char *End;
986 P.GetRec(Start,End);
987 fwrite(Start,End-Start,1,stdout);
988 putc('\n',stdout);
989 }
7e2e2d5d 990 else
b2e465d6
AL
991 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
992 }
9dbb421f
AL
993 }
994
b2e465d6
AL
995 delete [] VFList;
996 for (unsigned I = 0; I != NumPatterns; I++)
997 regfree(&Patterns[I]);
998 if (ferror(stdout))
999 return _error->Error("Write to stdout failed");
1164783d
AL
1000 return true;
1001}
1002 /*}}}*/
7e2e2d5d
AL
1003// ShowPackage - Dump the package record to the screen /*{{{*/
1004// ---------------------------------------------------------------------
1005/* */
1006bool ShowPackage(CommandLine &CmdL)
1007{
1008 pkgCache &Cache = *GCache;
b2e465d6
AL
1009 pkgDepCache::Policy Plcy;
1010
7e2e2d5d
AL
1011 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1012 {
1013 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1014 if (Pkg.end() == true)
1015 {
b2e465d6 1016 _error->Warning(_("Unable to locate package %s"),*I);
7e2e2d5d
AL
1017 continue;
1018 }
b2e465d6
AL
1019
1020 // Find the proper version to use.
648e3cb4
AL
1021 if (_config->FindB("APT::Cache::AllVersions","true") == true)
1022 {
1023 pkgCache::VerIterator V;
1024 for (V = Pkg.VersionList(); V.end() == false; V++)
1025 {
1026 if (DisplayRecord(V) == false)
1027 return false;
1028 }
1029 }
1030 else
1031 {
b2e465d6 1032 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
648e3cb4
AL
1033 if (V.end() == true || V.FileList().end() == true)
1034 continue;
1035 if (DisplayRecord(V) == false)
1036 return false;
1037 }
7e2e2d5d 1038 }
7c1133fe
AL
1039 return true;
1040}
1041 /*}}}*/
1042// ShowPkgNames - Show package names /*{{{*/
1043// ---------------------------------------------------------------------
1044/* This does a prefix match on the first argument */
1045bool ShowPkgNames(CommandLine &CmdL)
1046{
1047 pkgCache &Cache = *GCache;
1048 pkgCache::PkgIterator I = Cache.PkgBegin();
1049 bool All = _config->FindB("APT::Cache::AllNames","false");
1050
1051 if (CmdL.FileList[1] != 0)
1052 {
1053 for (;I.end() != true; I++)
1054 {
1055 if (All == false && I->VersionList == 0)
1056 continue;
1057
1058 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1059 cout << I.Name() << endl;
1060 }
1061
1062 return true;
1063 }
1064
1065 // Show all pkgs
1066 for (;I.end() != true; I++)
1067 {
1068 if (All == false && I->VersionList == 0)
1069 continue;
1070 cout << I.Name() << endl;
1071 }
1072
7e2e2d5d
AL
1073 return true;
1074}
1075 /*}}}*/
f8f410f5
AL
1076// ShowSrcPackage - Show source package records /*{{{*/
1077// ---------------------------------------------------------------------
1078/* */
1079bool ShowSrcPackage(CommandLine &CmdL)
1080{
1081 pkgSourceList List;
1082 List.ReadMainList();
1083
1084 // Create the text record parsers
1085 pkgSrcRecords SrcRecs(List);
1086 if (_error->PendingError() == true)
1087 return false;
1088
1089 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1090 {
aaee8293
AL
1091 SrcRecs.Restart();
1092
f8f410f5
AL
1093 pkgSrcRecords::Parser *Parse;
1094 while ((Parse = SrcRecs.Find(*I,false)) != 0)
b2e465d6 1095 cout << Parse->AsStr() << endl;;
f8f410f5 1096 }
af87ab54
AL
1097 return true;
1098}
1099 /*}}}*/
1100// Policy - Show the results of the preferences file /*{{{*/
1101// ---------------------------------------------------------------------
1102/* */
1103bool Policy(CommandLine &CmdL)
1104{
1105 if (SrcList == 0)
1106 return _error->Error("Generate must be enabled for this function");
1107
1108 pkgCache &Cache = *GCache;
1109 pkgPolicy Plcy(&Cache);
1110 if (ReadPinFile(Plcy) == false)
1111 return false;
1112
1113 // Print out all of the package files
1114 if (CmdL.FileList[1] == 0)
1115 {
1116 cout << _("Package Files:") << endl;
1117 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
1118 {
1119 // Locate the associated index files so we can derive a description
1120 pkgIndexFile *Indx;
1121 if (SrcList->FindIndex(F,Indx) == false &&
1122 _system->FindIndex(F,Indx) == false)
1123 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1124 printf(_("%4i %s\n"),
1125 Plcy.GetPriority(F),Indx->Describe(true).c_str());
1126
1127 // Print the reference information for the package
1128 string Str = F.RelStr();
1129 if (Str.empty() == false)
1130 printf(" release %s\n",F.RelStr().c_str());
1131 if (F.Site() != 0 && F.Site()[0] != 0)
1132 printf(" origin %s\n",F.Site());
1133 }
1134
1135 // Show any packages have explicit pins
1136 cout << _("Pinned Packages:") << endl;
1137 pkgCache::PkgIterator I = Cache.PkgBegin();
1138 for (;I.end() != true; I++)
1139 {
1140 if (Plcy.GetPriority(I) == 0)
1141 continue;
1142
1143 // Print the package name and the version we are forcing to
1144 cout << " " << I.Name() << " -> ";
1145
1146 pkgCache::VerIterator V = Plcy.GetMatch(I);
1147 if (V.end() == true)
1148 cout << _("(not found)") << endl;
1149 else
1150 cout << V.VerStr() << endl;
1151 }
1152
1153 return true;
1154 }
1155
1156 // Print out detailed information for each package
1157 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1158 {
1159 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1160 if (Pkg.end() == true)
1161 {
1162 _error->Warning(_("Unable to locate package %s"),*I);
1163 continue;
1164 }
1165
1166 cout << Pkg.Name() << ":" << endl;
1167
1168 // Installed version
1169 cout << _(" Installed: ");
1170 if (Pkg->CurrentVer == 0)
1171 cout << _("(none)") << endl;
1172 else
1173 cout << Pkg.CurrentVer().VerStr() << endl;
1174
1175 // Candidate Version
1176 cout << _(" Candidate: ");
1177 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
1178 if (V.end() == true)
1179 cout << _("(none)") << endl;
1180 else
1181 cout << V.VerStr() << endl;
1182
1183 // Pinned version
1184 if (Plcy.GetPriority(Pkg) != 0)
1185 {
1186 cout << _(" Package Pin: ");
1187 V = Plcy.GetMatch(Pkg);
1188 if (V.end() == true)
1189 cout << _("(not found)") << endl;
1190 else
1191 cout << V.VerStr() << endl;
1192 }
1193
1194 // Show the priority tables
1195 cout << _(" Version Table:") << endl;
1196 for (V = Pkg.VersionList(); V.end() == false; V++)
1197 {
1198 if (Pkg.CurrentVer() == V)
1199 cout << " *** " << V.VerStr();
1200 else
1201 cout << " " << V.VerStr();
1202 cout << " " << Plcy.GetPriority(Pkg) << endl;
1203 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1204 {
1205 // Locate the associated index files so we can derive a description
1206 pkgIndexFile *Indx;
1207 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1208 _system->FindIndex(VF.File(),Indx) == false)
1209 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1210 printf(_(" %4i %s\n"),Plcy.GetPriority(VF.File()),
1211 Indx->Describe(true).c_str());
1212 }
1213 }
1214 }
1215
f8f410f5
AL
1216 return true;
1217}
1218 /*}}}*/
880e9be4
AL
1219// GenCaches - Call the main cache generator /*{{{*/
1220// ---------------------------------------------------------------------
1221/* */
b0b4efb9 1222bool GenCaches(CommandLine &Cmd)
880e9be4 1223{
0a8e3465
AL
1224 OpTextProgress Progress(*_config);
1225
880e9be4 1226 pkgSourceList List;
b2e465d6
AL
1227 if (List.ReadMainList() == false)
1228 return false;
0a8e3465 1229 return pkgMakeStatusCache(List,Progress);
880e9be4
AL
1230}
1231 /*}}}*/
e1b74f61
AL
1232// ShowHelp - Show a help screen /*{{{*/
1233// ---------------------------------------------------------------------
1234/* */
b0b4efb9 1235bool ShowHelp(CommandLine &Cmd)
e1b74f61 1236{
b2e465d6
AL
1237 ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
1238 COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
e1b74f61 1239
b2e465d6
AL
1240 cout <<
1241 _("Usage: apt-cache [options] command\n"
1242 " apt-cache [options] add file1 [file1 ...]\n"
1243 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1244 "\n"
1245 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1246 "cache files, and query information from them\n"
1247 "\n"
1248 "Commands:\n"
1249 " add - Add an package file to the source cache\n"
1250 " gencaches - Build both the package and source cache\n"
1251 " showpkg - Show some general information for a single package\n"
1252 " stats - Show some basic statistics\n"
1253 " dump - Show the entire file in a terse form\n"
1254 " dumpavail - Print an available file to stdout\n"
1255 " unmet - Show unmet dependencies\n"
b2e465d6
AL
1256 " search - Search the package list for a regex pattern\n"
1257 " show - Show a readable record for the package\n"
1258 " depends - Show raw dependency information for a package\n"
1259 " pkgnames - List the names of all packages\n"
1260 " dotty - Generate package graphs for GraphVis\n"
1261 "\n"
1262 "Options:\n"
1263 " -h This help text.\n"
1264 " -p=? The package cache.\n"
1265 " -s=? The source cache.\n"
1266 " -q Disable progress indicator.\n"
1267 " -i Show only important deps for the unmet command.\n"
1268 " -c=? Read this configuration file\n"
1269 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
1270 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1271 return true;
e1b74f61
AL
1272}
1273 /*}}}*/
0a8e3465
AL
1274// CacheInitialize - Initialize things for apt-cache /*{{{*/
1275// ---------------------------------------------------------------------
1276/* */
1277void CacheInitialize()
1278{
1279 _config->Set("quiet",0);
1280 _config->Set("help",false);
1281}
1282 /*}}}*/
1164783d 1283
08e8f724 1284int main(int argc,const char *argv[])
1164783d 1285{
08e8f724
AL
1286 CommandLine::Args Args[] = {
1287 {'h',"help","help",0},
04aa15a8 1288 {'v',"version","version",0},
e1b74f61
AL
1289 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
1290 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
1291 {'q',"quiet","quiet",CommandLine::IntLevel},
76fbce56 1292 {'i',"important","APT::Cache::Important",0},
7e2e2d5d 1293 {'f',"full","APT::Cache::ShowFull",0},
b2e465d6 1294 {'g',"generate","APT::Cache::Generate",0},
648e3cb4 1295 {'a',"all-versions","APT::Cache::AllVersions",0},
7e2e2d5d 1296 {0,"names-only","APT::Cache::NamesOnly",0},
7c1133fe 1297 {0,"all-names","APT::Cache::AllNames",0},
b2e465d6 1298 {0,"recurse","APT::Cache::RecurseDepends",0},
e1b74f61
AL
1299 {'c',"config-file",0,CommandLine::ConfigFile},
1300 {'o',"option",0,CommandLine::ArbItem},
08e8f724 1301 {0,0,0,0}};
b0b4efb9
AL
1302 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
1303 {"add",&DoAdd},
1304 {"gencaches",&GenCaches},
f8f410f5 1305 {"showsrc",&ShowSrcPackage},
b0b4efb9
AL
1306 {0,0}};
1307 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
1308 {"stats",&Stats},
1309 {"dump",&Dump},
1310 {"dumpavail",&DumpAvail},
1311 {"unmet",&UnMet},
9dbb421f 1312 {"search",&Search},
349cd3b8 1313 {"depends",&Depends},
3e94da1b 1314 {"dotty",&Dotty},
7e2e2d5d 1315 {"show",&ShowPackage},
7c1133fe 1316 {"pkgnames",&ShowPkgNames},
af87ab54 1317 {"policy",&Policy},
b0b4efb9 1318 {0,0}};
0a8e3465
AL
1319
1320 CacheInitialize();
e1b74f61
AL
1321
1322 // Parse the command line and initialize the package library
1323 CommandLine CmdL(Args,_config);
b2e465d6
AL
1324 if (pkgInitConfig(*_config) == false ||
1325 CmdL.Parse(argc,argv) == false ||
1326 pkgInitSystem(*_config,_system) == false)
08e8f724
AL
1327 {
1328 _error->DumpErrors();
1329 return 100;
1164783d 1330 }
8efa2a3b 1331
e1b74f61
AL
1332 // See if the help should be shown
1333 if (_config->FindB("help") == true ||
1334 CmdL.FileSize() == 0)
b2e465d6
AL
1335 {
1336 ShowHelp(CmdL);
1337 return 0;
1338 }
1339
a9a5908d
AL
1340 // Deal with stdout not being a tty
1341 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
1342 _config->Set("quiet","1");
1343
b0b4efb9 1344 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
4b1b89c5
AL
1345 {
1346 MMap *Map;
b2e465d6 1347 if (_config->FindB("APT::Cache::Generate",true) == false)
4b1b89c5
AL
1348 {
1349 Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
1350 FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
1351 }
1352 else
1353 {
1354 // Open the cache file
af87ab54
AL
1355 SrcList = new pkgSourceList;
1356 SrcList->ReadMainList();
f8f410f5 1357
4b1b89c5
AL
1358 // Generate it and map it
1359 OpProgress Prog;
af87ab54 1360 pkgMakeStatusCache(*SrcList,Prog,&Map,true);
4b1b89c5
AL
1361 }
1362
b0b4efb9 1363 if (_error->PendingError() == false)
1164783d 1364 {
b2e465d6 1365 pkgCache Cache(Map);
b0b4efb9
AL
1366 GCache = &Cache;
1367 if (_error->PendingError() == false)
1368 CmdL.DispatchArg(CmdsB);
803fafcb
AL
1369 }
1370 delete Map;
1164783d
AL
1371 }
1372
1373 // Print any errors or warnings found during parsing
1374 if (_error->empty() == false)
1375 {
0a8e3465 1376 bool Errors = _error->PendingError();
1164783d 1377 _error->DumpErrors();
0a8e3465 1378 return Errors == true?100:0;
1164783d
AL
1379 }
1380
1381 return 0;
1382}