]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
Small tweaks to no install candidate warning
[apt.git] / cmdline / apt-cache.cc
CommitLineData
1164783d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
cc718e9a 3// $Id: apt-cache.cc,v 1.12 1998/11/14 07:20:29 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
11 by the dselect method. Everything else is ment 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>
1164783d
AL
25
26#include <iostream.h>
e1b74f61 27#include <config.h>
1164783d
AL
28 /*}}}*/
29
cc718e9a
AL
30// UnMet - Show unmet dependencies /*{{{*/
31// ---------------------------------------------------------------------
32/* */
33bool UnMet(pkgCache &Cache)
34{
35 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
36 {
37 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
38 {
39 bool Header = false;
40 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
41 {
42 // Collect or groups
43 pkgCache::DepIterator Start;
44 pkgCache::DepIterator End;
45 D.GlobOr(Start,End);
46
47 // Skip everything but depends
48 if (End->Type != pkgCache::Dep::PreDepends &&
49 End->Type != pkgCache::Dep::Depends &&
50 End->Type != pkgCache::Dep::Suggests &&
51 End->Type != pkgCache::Dep::Recommends)
52 continue;
53
54 // Verify the or group
55 bool OK = false;
56 pkgCache::DepIterator RealStart = Start;
57 do
58 {
59 // See if this dep is Ok
60 pkgCache::Version **VList = Start.AllTargets();
61 if (*VList != 0)
62 {
63 OK = true;
64 delete [] VList;
65 break;
66 }
67 delete [] VList;
68
69 if (Start == End)
70 break;
71 Start++;
72 }
73 while (1);
74
75 // The group is OK
76 if (OK == true)
77 continue;
78
79 // Oops, it failed..
80 if (Header == false)
81 cout << "Package " << P.Name() << " version " <<
82 V.VerStr() << " has an unmet dep:" << endl;
83 Header = true;
84
85 // Print out the dep type
86 cout << " " << End.DepType() << ": ";
87
88 // Show the group
89 Start = RealStart;
90 do
91 {
92 cout << Start.TargetPkg().Name();
93 if (Start.TargetVer() != 0)
94 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
95 ")";
96 if (Start == End)
97 break;
98 cout << " | ";
99 Start++;
100 }
101 while (1);
102
103 cout << endl;
104 }
105 }
106 }
107 return true;
108}
109 /*}}}*/
1164783d
AL
110// DumpPackage - Show a dump of a package record /*{{{*/
111// ---------------------------------------------------------------------
112/* */
e1b74f61 113bool DumpPackage(pkgCache &Cache,CommandLine &CmdL)
ad00ae81 114{
e1b74f61 115 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1164783d 116 {
e1b74f61 117 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1164783d
AL
118 if (Pkg.end() == true)
119 {
e1b74f61 120 _error->Warning("Unable to locate package %s",*I);
1164783d
AL
121 continue;
122 }
123
124 cout << "Package: " << Pkg.Name() << endl;
125 cout << "Versions: ";
126 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
03e39e59
AL
127 {
128 cout << Cur.VerStr();
129 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
130 cout << "(" << Vf.File().FileName() << ")";
131 cout << ',';
132 }
133
1164783d
AL
134 cout << endl;
135
136 cout << "Reverse Depends: " << endl;
137 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
138 cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name() << endl;
139
140 cout << "Dependencies: " << endl;
141 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
142 {
143 cout << Cur.VerStr() << " - ";
144 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
145 cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << Dep.TargetVer() << ") ";
146 cout << endl;
147 }
148
149 cout << "Provides: " << endl;
150 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
151 {
152 cout << Cur.VerStr() << " - ";
153 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
154 cout << Prv.ParentPkg().Name() << " ";
155 cout << endl;
8efa2a3b
AL
156 }
157 cout << "Reverse Provides: " << endl;
158 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
159 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr();
160 cout << endl;
03e39e59 161
1164783d
AL
162 }
163
164 return true;
165}
166 /*}}}*/
167// Stats - Dump some nice statistics /*{{{*/
168// ---------------------------------------------------------------------
169/* */
ad00ae81 170bool Stats(pkgCache &Cache)
1164783d 171{
1164783d
AL
172 cout << "Total Package Names : " << Cache.Head().PackageCount << endl;
173 pkgCache::PkgIterator I = Cache.PkgBegin();
174
175 int Normal = 0;
176 int Virtual = 0;
177 int NVirt = 0;
178 int DVirt = 0;
179 int Missing = 0;
180 for (;I.end() != true; I++)
181 {
182 if (I->VersionList != 0 && I->ProvidesList == 0)
183 {
184 Normal++;
185 continue;
186 }
187
188 if (I->VersionList != 0 && I->ProvidesList != 0)
189 {
190 NVirt++;
191 continue;
192 }
193
194 if (I->VersionList == 0 && I->ProvidesList != 0)
195 {
196 // Only 1 provides
197 if (I.ProvidesList()->NextProvides == 0)
198 {
199 DVirt++;
200 }
201 else
202 Virtual++;
203 continue;
204 }
205 if (I->VersionList == 0 && I->ProvidesList == 0)
206 {
207 Missing++;
208 continue;
209 }
210 }
211 cout << " Normal Packages: " << Normal << endl;
212 cout << " Pure Virtual Packages: " << Virtual << endl;
213 cout << " Single Virtual Packages: " << DVirt << endl;
214 cout << " Mixed Virtual Packages: " << NVirt << endl;
215 cout << " Missing: " << Missing << endl;
216
217 cout << "Total Distinct Versions: " << Cache.Head().VersionCount << endl;
218 cout << "Total Dependencies: " << Cache.Head().DependsCount << endl;
219 return true;
220}
221 /*}}}*/
222// Dump - show everything /*{{{*/
223// ---------------------------------------------------------------------
224/* */
ad00ae81 225bool Dump(pkgCache &Cache)
1164783d 226{
1164783d
AL
227 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
228 {
229 cout << "Package: " << P.Name() << endl;
230 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
231 {
232 cout << " Version: " << V.VerStr() << endl;
233 cout << " File: " << V.FileList().File().FileName() << endl;
234 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
235 cout << " Depends: " << D.TargetPkg().Name() << ' ' << D.TargetVer() << endl;
236 }
237 }
238
239 for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
240 {
241 cout << "File: " << F.FileName() << endl;
242 cout << " Size: " << F->Size << endl;
243 cout << " ID: " << F->ID << endl;
244 cout << " Flags: " << F->Flags << endl;
245 cout << " Time: " << ctime(&F->mtime) << endl;
246 }
247
248 return true;
249}
250 /*}}}*/
251// DumpAvail - Print out the available list /*{{{*/
252// ---------------------------------------------------------------------
253/* This is needed to make dpkg --merge happy */
ad00ae81 254bool DumpAvail(pkgCache &Cache)
1164783d 255{
ad00ae81 256 unsigned char *Buffer = new unsigned char[Cache.HeaderP->MaxVerFileSize];
1164783d 257
ad00ae81 258 for (pkgCache::PkgFileIterator I = Cache.FileBegin(); I.end() == false; I++)
1164783d 259 {
ad00ae81 260 if ((I->Flags & pkgCache::Flag::NotSource) != 0)
1164783d
AL
261 continue;
262
ad00ae81
AL
263 if (I.IsOk() == false)
264 {
265 delete [] Buffer;
266 return _error->Error("Package file %s is out of sync.",I.FileName());
267 }
1164783d 268
8e06abb2 269 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
ad00ae81 270 if (_error->PendingError() == true)
1164783d 271 {
ad00ae81
AL
272 delete [] Buffer;
273 return false;
274 }
275
276 /* Write all of the records from this package file, we search the entire
277 structure to find them */
278 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
279 {
280 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
1164783d 281 {
ad00ae81
AL
282 if (V->FileList == 0)
283 continue;
284 if (V.FileList().File() != I)
285 continue;
286
287 // Read the record and then write it out again.
288 if (PkgF.Seek(V.FileList()->Offset) == false ||
289 PkgF.Read(Buffer,V.FileList()->Size) == false ||
290 write(STDOUT_FILENO,Buffer,V.FileList()->Size) != V.FileList()->Size)
291 {
292 delete [] Buffer;
293 return false;
294 }
1164783d 295 }
1164783d 296 }
ad00ae81
AL
297 }
298
299 return true;
300}
301 /*}}}*/
302// DoAdd - Perform an adding operation /*{{{*/
303// ---------------------------------------------------------------------
304/* */
e1b74f61 305bool DoAdd(CommandLine &CmdL)
ad00ae81 306{
e1b74f61
AL
307 // Make sure there is at least one argument
308 if (CmdL.FileSize() <= 1)
309 return _error->Error("You must give at least one file name");
ad00ae81
AL
310
311 // Open the cache
303a1703 312 FileFd CacheF(_config->FindFile("Dir::Cache::srcpkgcache"),FileFd::WriteAny);
ad00ae81
AL
313 if (_error->PendingError() == true)
314 return false;
315
316 DynamicMMap Map(CacheF,MMap::Public);
317 if (_error->PendingError() == true)
318 return false;
404ec98e 319
0a8e3465 320 OpTextProgress Progress(*_config);
404ec98e 321 pkgCacheGenerator Gen(Map,Progress);
ad00ae81
AL
322 if (_error->PendingError() == true)
323 return false;
324
e1b74f61
AL
325 unsigned long Length = CmdL.FileSize() - 1;
326 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
ad00ae81 327 {
e1b74f61 328 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
1164783d 329
ad00ae81 330 // Do the merge
e1b74f61 331 FileFd TagF(*I,FileFd::ReadOnly);
ad00ae81
AL
332 debListParser Parser(TagF);
333 if (_error->PendingError() == true)
e1b74f61 334 return _error->Error("Problem opening %s",*I);
ad00ae81 335
e1b74f61 336 if (Gen.SelectFile(*I) == false)
ad00ae81
AL
337 return _error->Error("Problem with SelectFile");
338
339 if (Gen.MergeList(Parser) == false)
340 return _error->Error("Problem with MergeList");
1164783d 341 }
404ec98e
AL
342
343 Progress.Done();
ad00ae81
AL
344 Stats(Gen.GetCache());
345
1164783d
AL
346 return true;
347}
348 /*}}}*/
880e9be4
AL
349// GenCaches - Call the main cache generator /*{{{*/
350// ---------------------------------------------------------------------
351/* */
352bool GenCaches()
353{
0a8e3465
AL
354 OpTextProgress Progress(*_config);
355
880e9be4
AL
356 pkgSourceList List;
357 List.ReadMainList();
0a8e3465 358 return pkgMakeStatusCache(List,Progress);
880e9be4
AL
359}
360 /*}}}*/
e1b74f61
AL
361// ShowHelp - Show a help screen /*{{{*/
362// ---------------------------------------------------------------------
363/* */
364int ShowHelp()
365{
366 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
367 " compiled on " << __DATE__ << " " << __TIME__ << endl;
368
369 cout << "Usage: apt-cache [options] command" << endl;
370 cout << " apt-cache [options] add file1 [file1 ...]" << endl;
0a8e3465 371 cout << " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl;
e1b74f61
AL
372 cout << endl;
373 cout << "apt-cache is a low-level tool used to manipulate APT's binary" << endl;
303a1703 374 cout << "cache files stored in " << _config->FindFile("Dir::Cache") << endl;
e1b74f61
AL
375 cout << "It is not ment for ordinary use only as a debug aide." << endl;
376 cout << endl;
377 cout << "Commands:" << endl;
378 cout << " add - Add an package file to the source cache" << endl;
379 cout << " gencaches - Build both the package and source cache" << endl;
380 cout << " showpkg - Show some general information for a single package" << endl;
381 cout << " stats - Show some basic statistics" << endl;
382 cout << " dump - Show the entire file in a terse form" << endl;
383 cout << " dumpavail - Print an available file to stdout" << endl;
cc718e9a 384 cout << " unmet - Show unmet dependencies" << endl;
e1b74f61
AL
385 cout << endl;
386 cout << "Options:" << endl;
387 cout << " -h This help text." << endl;
303a1703
AL
388 cout << " -p=? The package cache. [" << _config->FindFile("Dir::Cache::pkgcache") << ']' << endl;
389 cout << " -s=? The source cache. [" << _config->FindFile("Dir::Cache::srcpkgcache") << ']' << endl;
e1b74f61
AL
390 cout << " -q Disable progress indicator. " << endl;
391 cout << " -c=? Read this configuration file" << endl;
392 cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl;
393 cout << "See the apt-cache(8) and apt.conf(8) manual pages for more information." << endl;
394 return 100;
395}
396 /*}}}*/
0a8e3465
AL
397// CacheInitialize - Initialize things for apt-cache /*{{{*/
398// ---------------------------------------------------------------------
399/* */
400void CacheInitialize()
401{
402 _config->Set("quiet",0);
403 _config->Set("help",false);
404}
405 /*}}}*/
1164783d 406
08e8f724 407int main(int argc,const char *argv[])
1164783d 408{
08e8f724
AL
409 CommandLine::Args Args[] = {
410 {'h',"help","help",0},
e1b74f61
AL
411 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
412 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
413 {'q',"quiet","quiet",CommandLine::IntLevel},
414 {'c',"config-file",0,CommandLine::ConfigFile},
415 {'o',"option",0,CommandLine::ArbItem},
08e8f724 416 {0,0,0,0}};
0a8e3465
AL
417
418 CacheInitialize();
e1b74f61
AL
419
420 // Parse the command line and initialize the package library
421 CommandLine CmdL(Args,_config);
08e8f724 422 if (pkgInitialize(*_config) == false ||
e1b74f61 423 CmdL.Parse(argc,argv) == false)
08e8f724
AL
424 {
425 _error->DumpErrors();
426 return 100;
1164783d 427 }
8efa2a3b 428
e1b74f61
AL
429 // See if the help should be shown
430 if (_config->FindB("help") == true ||
431 CmdL.FileSize() == 0)
432 return ShowHelp();
433
1164783d
AL
434 while (1)
435 {
e1b74f61 436 if (strcmp(CmdL.FileList[0],"add") == 0)
1164783d 437 {
e1b74f61 438 DoAdd(CmdL);
1164783d
AL
439 break;
440 }
ad00ae81 441
e1b74f61 442 if (strcmp(CmdL.FileList[0],"gencaches") == 0)
880e9be4
AL
443 {
444 GenCaches();
445 break;
446 }
447
ad00ae81 448 // Open the cache file
303a1703 449 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly);
ad00ae81
AL
450 if (_error->PendingError() == true)
451 break;
452
453 MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
454 if (_error->PendingError() == true)
455 break;
456
457 pkgCache Cache(Map);
458 if (_error->PendingError() == true)
459 break;
1164783d 460
e1b74f61 461 if (strcmp(CmdL.FileList[0],"showpkg") == 0)
1164783d 462 {
e1b74f61 463 DumpPackage(Cache,CmdL);
1164783d
AL
464 break;
465 }
466
e1b74f61 467 if (strcmp(CmdL.FileList[0],"stats") == 0)
1164783d 468 {
ad00ae81 469 Stats(Cache);
1164783d
AL
470 break;
471 }
472
e1b74f61 473 if (strcmp(CmdL.FileList[0],"dump") == 0)
1164783d 474 {
ad00ae81 475 Dump(Cache);
1164783d
AL
476 break;
477 }
478
e1b74f61 479 if (strcmp(CmdL.FileList[0],"dumpavail") == 0)
1164783d 480 {
ad00ae81 481 DumpAvail(Cache);
1164783d
AL
482 break;
483 }
cc718e9a
AL
484
485 if (strcmp(CmdL.FileList[0],"unmet") == 0)
486 {
487 UnMet(Cache);
488 break;
489 }
880e9be4 490
e1b74f61 491 _error->Error("Invalid operation %s", CmdL.FileList[0]);
1164783d
AL
492 break;
493 }
494
495 // Print any errors or warnings found during parsing
496 if (_error->empty() == false)
497 {
0a8e3465 498 bool Errors = _error->PendingError();
1164783d 499 _error->DumpErrors();
0a8e3465 500 return Errors == true?100:0;
1164783d
AL
501 }
502
503 return 0;
504}