]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
New changelog
[apt.git] / cmdline / apt-cache.cc
CommitLineData
1164783d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
349cd3b8 3// $Id: apt-cache.cc,v 1.37 1999/07/15 03:15:49 jgg Exp $
1164783d
AL
4/* ######################################################################
5
e1b74f61 6 apt-cache - Manages the cache files
1164783d 7
e1b74f61
AL
8 apt-cache provides some functions fo manipulating the cache files.
9 It uses the command line interface common to all the APT tools. The
10 only really usefull function right now is dumpavail which is used
82297457 11 by the dselect method. Everything else is meant as a debug aide.
1164783d
AL
12
13 Returns 100 on failure, 0 on success.
14
15 ##################################################################### */
16 /*}}}*/
17// Include Files /*{{{*/
18#include <apt-pkg/error.h>
19#include <apt-pkg/pkgcachegen.h>
20#include <apt-pkg/deblistparser.h>
8efa2a3b 21#include <apt-pkg/init.h>
404ec98e 22#include <apt-pkg/progress.h>
880e9be4 23#include <apt-pkg/sourcelist.h>
08e8f724 24#include <apt-pkg/cmndline.h>
cdcc6d34 25#include <apt-pkg/strutl.h>
9dbb421f 26#include <apt-pkg/pkgrecords.h>
43981212 27#include <config.h>
1164783d
AL
28
29#include <iostream.h>
cdb970c7 30#include <unistd.h>
43981212 31#include <errno.h>
9dbb421f 32#include <regex.h>
1164783d
AL
33 /*}}}*/
34
b0b4efb9
AL
35pkgCache *GCache = 0;
36
cc718e9a
AL
37// UnMet - Show unmet dependencies /*{{{*/
38// ---------------------------------------------------------------------
39/* */
b0b4efb9 40bool UnMet(CommandLine &CmdL)
cc718e9a 41{
b0b4efb9 42 pkgCache &Cache = *GCache;
76fbce56 43 bool Important = _config->FindB("APT::Cache::Important",false);
018f1533 44
cc718e9a
AL
45 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
46 {
47 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
48 {
49 bool Header = false;
018f1533 50 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
cc718e9a
AL
51 {
52 // Collect or groups
53 pkgCache::DepIterator Start;
54 pkgCache::DepIterator End;
55 D.GlobOr(Start,End);
56
018f1533
AL
57/* cout << "s: Check " << Start.TargetPkg().Name() << ',' <<
58 End.TargetPkg().Name() << endl;*/
59
60 // Skip conflicts and replaces
cc718e9a
AL
61 if (End->Type != pkgCache::Dep::PreDepends &&
62 End->Type != pkgCache::Dep::Depends &&
63 End->Type != pkgCache::Dep::Suggests &&
64 End->Type != pkgCache::Dep::Recommends)
65 continue;
66
018f1533
AL
67 // Important deps only
68 if (Important == true)
69 if (End->Type != pkgCache::Dep::PreDepends &&
70 End->Type != pkgCache::Dep::Depends)
71 continue;
72
cc718e9a
AL
73 // Verify the or group
74 bool OK = false;
75 pkgCache::DepIterator RealStart = Start;
76 do
77 {
78 // See if this dep is Ok
79 pkgCache::Version **VList = Start.AllTargets();
80 if (*VList != 0)
81 {
82 OK = true;
83 delete [] VList;
84 break;
85 }
86 delete [] VList;
87
88 if (Start == End)
89 break;
90 Start++;
91 }
92 while (1);
93
94 // The group is OK
95 if (OK == true)
96 continue;
97
98 // Oops, it failed..
99 if (Header == false)
100 cout << "Package " << P.Name() << " version " <<
101 V.VerStr() << " has an unmet dep:" << endl;
102 Header = true;
103
104 // Print out the dep type
105 cout << " " << End.DepType() << ": ";
106
107 // Show the group
108 Start = RealStart;
109 do
110 {
111 cout << Start.TargetPkg().Name();
112 if (Start.TargetVer() != 0)
113 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
114 ")";
115 if (Start == End)
116 break;
117 cout << " | ";
118 Start++;
119 }
120 while (1);
121
122 cout << endl;
123 }
124 }
125 }
126 return true;
127}
128 /*}}}*/
1164783d
AL
129// DumpPackage - Show a dump of a package record /*{{{*/
130// ---------------------------------------------------------------------
131/* */
b0b4efb9 132bool DumpPackage(CommandLine &CmdL)
ad00ae81 133{
b0b4efb9 134 pkgCache &Cache = *GCache;
e1b74f61 135 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1164783d 136 {
e1b74f61 137 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1164783d
AL
138 if (Pkg.end() == true)
139 {
e1b74f61 140 _error->Warning("Unable to locate package %s",*I);
1164783d
AL
141 continue;
142 }
143
144 cout << "Package: " << Pkg.Name() << endl;
145 cout << "Versions: ";
146 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
03e39e59
AL
147 {
148 cout << Cur.VerStr();
149 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
150 cout << "(" << Vf.File().FileName() << ")";
151 cout << ',';
152 }
153
1164783d
AL
154 cout << endl;
155
156 cout << "Reverse Depends: " << endl;
157 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
158 cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name() << endl;
159
160 cout << "Dependencies: " << endl;
161 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
162 {
163 cout << Cur.VerStr() << " - ";
164 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
165 cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << Dep.TargetVer() << ") ";
166 cout << endl;
167 }
168
169 cout << "Provides: " << endl;
170 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
171 {
172 cout << Cur.VerStr() << " - ";
173 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
174 cout << Prv.ParentPkg().Name() << " ";
175 cout << endl;
8efa2a3b
AL
176 }
177 cout << "Reverse Provides: " << endl;
178 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
2d6751b9 179 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr() << endl;
1164783d
AL
180 }
181
182 return true;
183}
184 /*}}}*/
185// Stats - Dump some nice statistics /*{{{*/
186// ---------------------------------------------------------------------
187/* */
b0b4efb9 188bool Stats(CommandLine &Cmd)
1164783d 189{
b0b4efb9 190 pkgCache &Cache = *GCache;
f826cfaa
AL
191 cout << "Total Package Names : " << Cache.Head().PackageCount << " (" <<
192 SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
1164783d
AL
193 pkgCache::PkgIterator I = Cache.PkgBegin();
194
195 int Normal = 0;
196 int Virtual = 0;
197 int NVirt = 0;
198 int DVirt = 0;
199 int Missing = 0;
200 for (;I.end() != true; I++)
201 {
202 if (I->VersionList != 0 && I->ProvidesList == 0)
203 {
204 Normal++;
205 continue;
206 }
207
208 if (I->VersionList != 0 && I->ProvidesList != 0)
209 {
210 NVirt++;
211 continue;
212 }
213
214 if (I->VersionList == 0 && I->ProvidesList != 0)
215 {
216 // Only 1 provides
217 if (I.ProvidesList()->NextProvides == 0)
218 {
219 DVirt++;
220 }
221 else
222 Virtual++;
223 continue;
224 }
225 if (I->VersionList == 0 && I->ProvidesList == 0)
226 {
227 Missing++;
228 continue;
229 }
230 }
231 cout << " Normal Packages: " << Normal << endl;
232 cout << " Pure Virtual Packages: " << Virtual << endl;
233 cout << " Single Virtual Packages: " << DVirt << endl;
234 cout << " Mixed Virtual Packages: " << NVirt << endl;
235 cout << " Missing: " << Missing << endl;
236
f826cfaa
AL
237 cout << "Total Distinct Versions: " << Cache.Head().VersionCount << " (" <<
238 SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
239 cout << "Total Dependencies: " << Cache.Head().DependsCount << " (" <<
240 SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
241
a7e66b17
AL
242 cout << "Total Ver/File relations: " << Cache.Head().VerFileCount << " (" <<
243 SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
244 cout << "Total Provides Mappings: " << Cache.Head().ProvidesCount << " (" <<
245 SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
f826cfaa
AL
246
247 // String list stats
248 unsigned long Size = 0;
249 unsigned long Count = 0;
250 for (pkgCache::StringItem *I = Cache.StringItemP + Cache.Head().StringList;
251 I!= Cache.StringItemP; I = Cache.StringItemP + I->NextItem)
252 {
253 Count++;
254 Size += strlen(Cache.StrP + I->String);
255 }
256 cout << "Total Globbed Strings: " << Count << " (" << SizeToStr(Size) << ')' << endl;
257
258 unsigned long Slack = 0;
259 for (int I = 0; I != 7; I++)
260 Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count;
261 cout << "Total Slack space: " << SizeToStr(Slack) << endl;
262
263 unsigned long Total = 0;
264 Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz +
265 Cache.Head().VersionCount*Cache.Head().VersionSz +
a7e66b17
AL
266 Cache.Head().PackageCount*Cache.Head().PackageSz +
267 Cache.Head().VerFileCount*Cache.Head().VerFileSz +
268 Cache.Head().ProvidesCount*Cache.Head().ProvidesSz;
f826cfaa
AL
269 cout << "Total Space Accounted for: " << SizeToStr(Total) << endl;
270
1164783d
AL
271 return true;
272}
273 /*}}}*/
83d89a9f
AL
274// Check - Check some things about the cache /*{{{*/
275// ---------------------------------------------------------------------
276/* Debug aide mostly */
b0b4efb9 277bool Check(CommandLine &Cmd)
83d89a9f 278{
b0b4efb9 279 pkgCache &Cache = *GCache;
83d89a9f
AL
280 pkgCache::PkgIterator Pkg = Cache.PkgBegin();
281 for (;Pkg.end() != true; Pkg++)
282 {
283 if (Pkg.Section() == 0 && Pkg->VersionList != 0)
284 cout << "Bad section " << Pkg.Name() << endl;
285
286 for (pkgCache::VerIterator Cur = Pkg.VersionList();
287 Cur.end() != true; Cur++)
288 {
289 if (Cur->Priority < 1 || Cur->Priority > 5)
290 cout << "Bad prio " << Pkg.Name() << ',' << Cur.VerStr() << " == " << (int)Cur->Priority << endl;
291 }
292 }
293 return true;
294}
295 /*}}}*/
1164783d
AL
296// Dump - show everything /*{{{*/
297// ---------------------------------------------------------------------
298/* */
b0b4efb9 299bool Dump(CommandLine &Cmd)
1164783d 300{
b0b4efb9 301 pkgCache &Cache = *GCache;
1164783d
AL
302 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
303 {
304 cout << "Package: " << P.Name() << endl;
305 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
306 {
307 cout << " Version: " << V.VerStr() << endl;
308 cout << " File: " << V.FileList().File().FileName() << endl;
309 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
310 cout << " Depends: " << D.TargetPkg().Name() << ' ' << D.TargetVer() << endl;
311 }
312 }
313
314 for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
315 {
316 cout << "File: " << F.FileName() << endl;
317 cout << " Size: " << F->Size << endl;
318 cout << " ID: " << F->ID << endl;
319 cout << " Flags: " << F->Flags << endl;
b0b4efb9
AL
320 cout << " Time: " << TimeRFC1123(F->mtime) << endl;
321 cout << " Archive: " << F.Archive() << endl;
322 cout << " Component: " << F.Component() << endl;
323 cout << " Version: " << F.Version() << endl;
324 cout << " Origin: " << F.Origin() << endl;
325 cout << " Label: " << F.Label() << endl;
326 cout << " Architecture: " << F.Architecture() << endl;
1164783d
AL
327 }
328
329 return true;
330}
331 /*}}}*/
332// DumpAvail - Print out the available list /*{{{*/
333// ---------------------------------------------------------------------
334/* This is needed to make dpkg --merge happy */
b0b4efb9 335bool DumpAvail(CommandLine &Cmd)
1164783d 336{
b0b4efb9 337 pkgCache &Cache = *GCache;
ad00ae81 338 unsigned char *Buffer = new unsigned char[Cache.HeaderP->MaxVerFileSize];
1164783d 339
ad00ae81 340 for (pkgCache::PkgFileIterator I = Cache.FileBegin(); I.end() == false; I++)
1164783d 341 {
5b8c90bf
AL
342 if ((I->Flags & pkgCache::Flag::NotSource) != 0)
343 continue;
344
ad00ae81
AL
345 if (I.IsOk() == false)
346 {
347 delete [] Buffer;
348 return _error->Error("Package file %s is out of sync.",I.FileName());
349 }
1164783d 350
8e06abb2 351 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
ad00ae81 352 if (_error->PendingError() == true)
1164783d 353 {
ad00ae81
AL
354 delete [] Buffer;
355 return false;
356 }
357
358 /* Write all of the records from this package file, we search the entire
359 structure to find them */
360 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
361 {
bd432be3 362 // Find the proper version to use. We should probably use the DepCache.
1fcbfcb8 363 pkgCache::VerIterator V = Cache.GetCandidateVer(P,false);
bd432be3
AL
364
365 if (V.end() == true || V.FileList().File() != I)
366 continue;
367
368 // Read the record and then write it out again.
369 if (PkgF.Seek(V.FileList()->Offset) == false ||
370 PkgF.Read(Buffer,V.FileList()->Size) == false ||
371 write(STDOUT_FILENO,Buffer,V.FileList()->Size) != V.FileList()->Size)
1164783d 372 {
bd432be3
AL
373 delete [] Buffer;
374 return false;
375 }
1164783d 376 }
ad00ae81
AL
377 }
378
349cd3b8
AL
379 return true;
380}
381 /*}}}*/
382// Depends - Print out a dependency tree /*{{{*/
383// ---------------------------------------------------------------------
384/* */
385bool Depends(CommandLine &CmdL)
386{
387 pkgCache &Cache = *GCache;
388
389 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
390 {
391 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
392 if (Pkg.end() == true)
393 {
394 _error->Warning("Unable to locate package %s",*I);
395 continue;
396 }
397
398 pkgCache::VerIterator Ver = Pkg.VersionList();
399 if (Ver.end() == true)
400 {
401 cout << '<' << Pkg.Name() << '>' << endl;
402 continue;
403 }
404
405 cout << Pkg.Name() << endl;
406
407 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
408 {
409 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
410 cout << " |";
411 else
412 cout << " ";
413
414 // Show the package
415 pkgCache::PkgIterator Trg = D.TargetPkg();
416 if (Trg->VersionList == 0)
417 cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
418 else
419 cout << D.DepType() << ": " << Trg.Name() << endl;
420
421 // Display all solutions
422 pkgCache::Version **List = D.AllTargets();
423 for (pkgCache::Version **I = List; *I != 0; I++)
424 {
425 pkgCache::VerIterator V(Cache,*I);
426 if (V != Cache.VerP + V.ParentPkg()->VersionList ||
427 V->ParentPkg == D->Package)
428 continue;
429 cout << " " << V.ParentPkg().Name() << endl;
430 }
431 delete [] List;
432 }
433 }
434
ad00ae81
AL
435 return true;
436}
437 /*}}}*/
438// DoAdd - Perform an adding operation /*{{{*/
439// ---------------------------------------------------------------------
440/* */
e1b74f61 441bool DoAdd(CommandLine &CmdL)
ad00ae81 442{
e1b74f61
AL
443 // Make sure there is at least one argument
444 if (CmdL.FileSize() <= 1)
445 return _error->Error("You must give at least one file name");
ad00ae81
AL
446
447 // Open the cache
018f1533 448 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
ad00ae81
AL
449 if (_error->PendingError() == true)
450 return false;
451
452 DynamicMMap Map(CacheF,MMap::Public);
453 if (_error->PendingError() == true)
454 return false;
404ec98e 455
0a8e3465 456 OpTextProgress Progress(*_config);
404ec98e 457 pkgCacheGenerator Gen(Map,Progress);
ad00ae81
AL
458 if (_error->PendingError() == true)
459 return false;
460
e1b74f61
AL
461 unsigned long Length = CmdL.FileSize() - 1;
462 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
ad00ae81 463 {
e1b74f61 464 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
018f1533
AL
465 Progress.SubProgress(Length);
466
ad00ae81 467 // Do the merge
e1b74f61 468 FileFd TagF(*I,FileFd::ReadOnly);
ad00ae81
AL
469 debListParser Parser(TagF);
470 if (_error->PendingError() == true)
e1b74f61 471 return _error->Error("Problem opening %s",*I);
ad00ae81 472
e1b74f61 473 if (Gen.SelectFile(*I) == false)
ad00ae81
AL
474 return _error->Error("Problem with SelectFile");
475
476 if (Gen.MergeList(Parser) == false)
477 return _error->Error("Problem with MergeList");
1164783d 478 }
404ec98e
AL
479
480 Progress.Done();
b0b4efb9
AL
481 GCache = &Gen.GetCache();
482 Stats(CmdL);
ad00ae81 483
7e2e2d5d
AL
484 return true;
485}
486 /*}}}*/
487// DisplayRecord - Displays the complete record for the package /*{{{*/
488// ---------------------------------------------------------------------
489/* This displays the package record from the proper package index file.
490 It is not used by DumpAvail for performance reasons. */
491bool DisplayRecord(pkgCache::VerIterator V)
492{
493 // Find an appropriate file
494 pkgCache::VerFileIterator Vf = V.FileList();
495 for (; Vf.end() == false; Vf++)
496 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
497 break;
498 if (Vf.end() == true)
499 Vf = V.FileList();
500
501 // Check and load the package list file
502 pkgCache::PkgFileIterator I = Vf.File();
503 if (I.IsOk() == false)
504 return _error->Error("Package file %s is out of sync.",I.FileName());
505
506 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
507 if (_error->PendingError() == true)
508 return false;
509
510 // Read the record and then write it out again.
511 unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize];
512 if (PkgF.Seek(V.FileList()->Offset) == false ||
513 PkgF.Read(Buffer,V.FileList()->Size) == false ||
514 write(STDOUT_FILENO,Buffer,V.FileList()->Size) != V.FileList()->Size)
515 {
516 delete [] Buffer;
517 return false;
518 }
519
520 delete [] Buffer;
521
9dbb421f
AL
522 return true;
523}
524 /*}}}*/
525// Search - Perform a search /*{{{*/
526// ---------------------------------------------------------------------
527/* This searches the package names and pacakge descriptions for a pattern */
528bool Search(CommandLine &CmdL)
529{
530 pkgCache &Cache = *GCache;
7e2e2d5d
AL
531 bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
532 bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
9dbb421f
AL
533
534 // Make sure there is at least one argument
535 if (CmdL.FileSize() != 2)
536 return _error->Error("You must give exactly one pattern");
537
538 // Compile the regex pattern
539 regex_t Pattern;
540 if (regcomp(&Pattern,CmdL.FileList[1],REG_EXTENDED | REG_ICASE |
541 REG_NOSUB) != 0)
542 return _error->Error("Regex compilation error");
543
544 // Create the text record parser
545 pkgRecords Recs(Cache);
546 if (_error->PendingError() == true)
547 return false;
548
549 // Search package names
550 pkgCache::PkgIterator I = Cache.PkgBegin();
551 for (;I.end() != true; I++)
552 {
7e2e2d5d 553 // We search against the install version as that makes the most sense..
1fcbfcb8 554 pkgCache::VerIterator V = Cache.GetCandidateVer(I);
7e2e2d5d
AL
555 if (V.end() == true)
556 continue;
557
558 pkgRecords::Parser &P = Recs.Lookup(V.FileList());
559
560 if (regexec(&Pattern,I.Name(),0,0,0) == 0 ||
561 (NamesOnly == false &&
562 regexec(&Pattern,P.LongDesc().c_str(),0,0,0) == 0))
9dbb421f 563 {
7e2e2d5d
AL
564 if (ShowFull == true)
565 DisplayRecord(V);
566 else
567 cout << I.Name() << " - " << P.ShortDesc() << endl;
9dbb421f
AL
568 }
569 }
570
571 regfree(&Pattern);
1164783d
AL
572 return true;
573}
574 /*}}}*/
7e2e2d5d
AL
575// ShowPackage - Dump the package record to the screen /*{{{*/
576// ---------------------------------------------------------------------
577/* */
578bool ShowPackage(CommandLine &CmdL)
579{
580 pkgCache &Cache = *GCache;
581 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
582 {
583 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
584 if (Pkg.end() == true)
585 {
586 _error->Warning("Unable to locate package %s",*I);
587 continue;
588 }
589
590 // Find the proper version to use. We should probably use the DepCache.
1fcbfcb8 591 pkgCache::VerIterator V = Cache.GetCandidateVer(Pkg);
7e2e2d5d
AL
592 if (V.end() == true || V.FileList().end() == true)
593 continue;
594 if (DisplayRecord(V) == false)
595 return false;
596 }
597 return true;
598}
599 /*}}}*/
880e9be4
AL
600// GenCaches - Call the main cache generator /*{{{*/
601// ---------------------------------------------------------------------
602/* */
b0b4efb9 603bool GenCaches(CommandLine &Cmd)
880e9be4 604{
0a8e3465
AL
605 OpTextProgress Progress(*_config);
606
880e9be4
AL
607 pkgSourceList List;
608 List.ReadMainList();
0a8e3465 609 return pkgMakeStatusCache(List,Progress);
880e9be4
AL
610}
611 /*}}}*/
e1b74f61
AL
612// ShowHelp - Show a help screen /*{{{*/
613// ---------------------------------------------------------------------
614/* */
b0b4efb9 615bool ShowHelp(CommandLine &Cmd)
e1b74f61
AL
616{
617 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
618 " compiled on " << __DATE__ << " " << __TIME__ << endl;
04aa15a8
AL
619 if (_config->FindB("version") == true)
620 return 100;
e1b74f61
AL
621
622 cout << "Usage: apt-cache [options] command" << endl;
623 cout << " apt-cache [options] add file1 [file1 ...]" << endl;
0a8e3465 624 cout << " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl;
e1b74f61
AL
625 cout << endl;
626 cout << "apt-cache is a low-level tool used to manipulate APT's binary" << endl;
303a1703 627 cout << "cache files stored in " << _config->FindFile("Dir::Cache") << endl;
82297457 628 cout << "It is not meant for ordinary use only as a debug aide." << endl;
e1b74f61
AL
629 cout << endl;
630 cout << "Commands:" << endl;
631 cout << " add - Add an package file to the source cache" << endl;
632 cout << " gencaches - Build both the package and source cache" << endl;
633 cout << " showpkg - Show some general information for a single package" << endl;
634 cout << " stats - Show some basic statistics" << endl;
635 cout << " dump - Show the entire file in a terse form" << endl;
636 cout << " dumpavail - Print an available file to stdout" << endl;
cc718e9a 637 cout << " unmet - Show unmet dependencies" << endl;
83d89a9f 638 cout << " check - Check the cache a bit" << endl;
9dbb421f 639 cout << " search - Search the package list for a regex pattern" << endl;
7e2e2d5d 640 cout << " show - Show a readable record for the package" << endl;
349cd3b8 641 cout << " depends - Show raw dependency information for a package" << endl;
e1b74f61
AL
642 cout << endl;
643 cout << "Options:" << endl;
644 cout << " -h This help text." << endl;
303a1703
AL
645 cout << " -p=? The package cache. [" << _config->FindFile("Dir::Cache::pkgcache") << ']' << endl;
646 cout << " -s=? The source cache. [" << _config->FindFile("Dir::Cache::srcpkgcache") << ']' << endl;
85f72a56
AL
647 cout << " -q Disable progress indicator." << endl;
648 cout << " -i Show only important deps for the unmet command." << endl;
e1b74f61 649 cout << " -c=? Read this configuration file" << endl;
7974b907 650 cout << " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp" << endl;
21ae3cae 651 cout << "See the apt-cache(8) and apt.conf(5) manual pages for more information." << endl;
e1b74f61
AL
652 return 100;
653}
654 /*}}}*/
0a8e3465
AL
655// CacheInitialize - Initialize things for apt-cache /*{{{*/
656// ---------------------------------------------------------------------
657/* */
658void CacheInitialize()
659{
660 _config->Set("quiet",0);
661 _config->Set("help",false);
662}
663 /*}}}*/
1164783d 664
08e8f724 665int main(int argc,const char *argv[])
1164783d 666{
08e8f724
AL
667 CommandLine::Args Args[] = {
668 {'h',"help","help",0},
04aa15a8 669 {'v',"version","version",0},
e1b74f61
AL
670 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
671 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
672 {'q',"quiet","quiet",CommandLine::IntLevel},
76fbce56 673 {'i',"important","APT::Cache::Important",0},
7e2e2d5d
AL
674 {'f',"full","APT::Cache::ShowFull",0},
675 {0,"names-only","APT::Cache::NamesOnly",0},
e1b74f61
AL
676 {'c',"config-file",0,CommandLine::ConfigFile},
677 {'o',"option",0,CommandLine::ArbItem},
08e8f724 678 {0,0,0,0}};
b0b4efb9
AL
679 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
680 {"add",&DoAdd},
681 {"gencaches",&GenCaches},
682 {0,0}};
683 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
684 {"stats",&Stats},
685 {"dump",&Dump},
686 {"dumpavail",&DumpAvail},
687 {"unmet",&UnMet},
688 {"check",&Check},
9dbb421f 689 {"search",&Search},
349cd3b8 690 {"depends",&Depends},
7e2e2d5d 691 {"show",&ShowPackage},
b0b4efb9 692 {0,0}};
0a8e3465
AL
693
694 CacheInitialize();
e1b74f61
AL
695
696 // Parse the command line and initialize the package library
697 CommandLine CmdL(Args,_config);
08e8f724 698 if (pkgInitialize(*_config) == false ||
e1b74f61 699 CmdL.Parse(argc,argv) == false)
08e8f724
AL
700 {
701 _error->DumpErrors();
702 return 100;
1164783d 703 }
8efa2a3b 704
e1b74f61
AL
705 // See if the help should be shown
706 if (_config->FindB("help") == true ||
707 CmdL.FileSize() == 0)
b0b4efb9 708 return ShowHelp(CmdL);
880e9be4 709
a9a5908d
AL
710 // Deal with stdout not being a tty
711 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
712 _config->Set("quiet","1");
713
b0b4efb9
AL
714 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
715 {
ad00ae81 716 // Open the cache file
803fafcb
AL
717 pkgSourceList List;
718 List.ReadMainList();
719
720 // Generate it and map it
721 OpProgress Prog;
722 MMap *Map = pkgMakeStatusCacheMem(List,Prog);
b0b4efb9 723 if (_error->PendingError() == false)
1164783d 724 {
803fafcb 725 pkgCache Cache(*Map);
b0b4efb9
AL
726 GCache = &Cache;
727 if (_error->PendingError() == false)
728 CmdL.DispatchArg(CmdsB);
803fafcb
AL
729 }
730 delete Map;
1164783d
AL
731 }
732
733 // Print any errors or warnings found during parsing
734 if (_error->empty() == false)
735 {
0a8e3465 736 bool Errors = _error->PendingError();
1164783d 737 _error->DumpErrors();
0a8e3465 738 return Errors == true?100:0;
1164783d
AL
739 }
740
741 return 0;
742}