Working cache generator
[ntk/apt.git] / cmdline / apt-cache.cc
CommitLineData
1164783d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
8efa2a3b 3// $Id: apt-cache.cc,v 1.2 1998/07/16 06:08:43 jgg Exp $
1164783d
AL
4/* ######################################################################
5
6 apt-cache - Manages the cache file.
7
8 This program should eventually handle both low and high level
9 manipulation of the cache file. Depending how far things go it
10 might get quite a sophisticated UI.
11
12 Currently the command line is as follows:
13 apt-cache add cache file1:dist:ver file2:dist:ver ...
14 ie:
15 apt-cache add ./cache Pacakges:hamm:1.0
16
17 A usefull feature is 'upgradable' ie
18 apt-cache upgradable ./cache
19 will list .debs that should be installed to make all packages the latest
20 version.
21
22 Returns 100 on failure, 0 on success.
23
24 ##################################################################### */
25 /*}}}*/
26// Include Files /*{{{*/
27#include <apt-pkg/error.h>
28#include <apt-pkg/pkgcachegen.h>
29#include <apt-pkg/deblistparser.h>
8efa2a3b 30#include <apt-pkg/init.h>
1164783d
AL
31
32#include <iostream.h>
33#include <fstream.h>
34
35 /*}}}*/
36
37string CacheFile;
38
39// SplitArg - Split the triple /*{{{*/
40// ---------------------------------------------------------------------
41/* */
42bool SplitArg(const char *Arg,string &File,string &Dist,string Ver)
43{
44 const char *Start = Arg;
45 const char *I = Arg;
46 for (;*I != 0 && *I != ':'; I++);
47 if (*I != ':')
48 return _error->Error("Malformed argument %s, must be in file:dist:rev form",Arg);
49 File = string(Start,I - Start);
50
51 I++;
52 Start = I;
53 for (;*I != 0 && *I != ':'; I++);
54 if (*I != ':')
55 return _error->Error("Malformed argument %s, must be in file:dist:rev form",Arg);
56 Dist = string(Start,I - Start);
57
58 I++;
59 Start = I;
60 for (;*I != 0 && *I != ':'; I++);
61 if (I == Start)
62 return _error->Error("Malformed argument %s, must be in file:dist:rev form",Arg);
63 Ver = string(Start,I - Start);
64
65 return true;
66}
67 /*}}}*/
68// DoAdd - Perform an adding operation /*{{{*/
69// ---------------------------------------------------------------------
70/* */
71bool DoAdd(int argc,char *argv[])
72{
73 string FileName;
74 string Dist;
75 string Ver;
76
77 File CacheF(CacheFile,File::WriteEmpty);
78 if (_error->PendingError() == true)
79 return false;
80
81 DynamicMMap Map(CacheF,MMap::Public);
82 if (_error->PendingError() == true)
83 return false;
84
85 pkgCacheGenerator Gen(Map);
86 if (_error->PendingError() == true)
87 return false;
88
89 for (int I = 0; I != argc; I++)
90 {
91 if (SplitArg(argv[I],FileName,Dist,Ver) == false)
92 return false;
8efa2a3b 93 cout << FileName << endl;
1164783d
AL
94
95 // Do the merge
96 File TagF(FileName.c_str(),File::ReadOnly);
97 debListParser Parser(TagF);
98 if (_error->PendingError() == true)
8efa2a3b
AL
99 return _error->Error("Problem opening %s",FileName.c_str());
100
1164783d 101 if (Gen.SelectFile(FileName) == false)
8efa2a3b 102 return _error->Error("Problem with SelectFile");
1164783d
AL
103
104 if (Gen.MergeList(Parser) == false)
8efa2a3b 105 return _error->Error("Problem with MergeList");
1164783d
AL
106 }
107
108 return true;
109}
110 /*}}}*/
111// DumpPackage - Show a dump of a package record /*{{{*/
112// ---------------------------------------------------------------------
113/* */
114bool DumpPackage(int argc,char *argv[])
115{
116 File CacheF(CacheFile,File::ReadOnly);
117 if (_error->PendingError() == true)
118 return false;
119
120 MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
121 if (_error->PendingError() == true)
122 return false;
123
124 pkgCache Cache(Map);
125 if (_error->PendingError() == true)
126 return false;
127
128 for (int I = 0; I != argc; I++)
129 {
130 pkgCache::PkgIterator Pkg = Cache.FindPkg(argv[I]);
131 if (Pkg.end() == true)
132 {
133 _error->Warning("Unable to locate package %s",argv[0]);
134 continue;
135 }
136
137 cout << "Package: " << Pkg.Name() << endl;
138 cout << "Versions: ";
139 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
140 cout << Cur.VerStr() << ',';
141 cout << endl;
142
143 cout << "Reverse Depends: " << endl;
144 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
145 cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name() << endl;
146
147 cout << "Dependencies: " << endl;
148 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
149 {
150 cout << Cur.VerStr() << " - ";
151 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
152 cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << Dep.TargetVer() << ") ";
153 cout << endl;
154 }
155
156 cout << "Provides: " << endl;
157 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
158 {
159 cout << Cur.VerStr() << " - ";
160 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
161 cout << Prv.ParentPkg().Name() << " ";
162 cout << endl;
8efa2a3b
AL
163 }
164 cout << "Reverse Provides: " << endl;
165 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
166 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr();
167 cout << endl;
1164783d
AL
168 }
169
170 return true;
171}
172 /*}}}*/
173// Stats - Dump some nice statistics /*{{{*/
174// ---------------------------------------------------------------------
175/* */
176bool Stats(const char *FileName)
177{
178 File CacheF(FileName,File::ReadOnly);
179 if (_error->PendingError() == true)
180 return false;
181
182 MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
183 if (_error->PendingError() == true)
184 return false;
185
186 pkgCache Cache(Map);
187 if (_error->PendingError() == true)
188 return false;
189
190 cout << "Total Package Names : " << Cache.Head().PackageCount << endl;
191 pkgCache::PkgIterator I = Cache.PkgBegin();
192
193 int Normal = 0;
194 int Virtual = 0;
195 int NVirt = 0;
196 int DVirt = 0;
197 int Missing = 0;
198 for (;I.end() != true; I++)
199 {
200 if (I->VersionList != 0 && I->ProvidesList == 0)
201 {
202 Normal++;
203 continue;
204 }
205
206 if (I->VersionList != 0 && I->ProvidesList != 0)
207 {
208 NVirt++;
209 continue;
210 }
211
212 if (I->VersionList == 0 && I->ProvidesList != 0)
213 {
214 // Only 1 provides
215 if (I.ProvidesList()->NextProvides == 0)
216 {
217 DVirt++;
218 }
219 else
220 Virtual++;
221 continue;
222 }
223 if (I->VersionList == 0 && I->ProvidesList == 0)
224 {
225 Missing++;
226 continue;
227 }
228 }
229 cout << " Normal Packages: " << Normal << endl;
230 cout << " Pure Virtual Packages: " << Virtual << endl;
231 cout << " Single Virtual Packages: " << DVirt << endl;
232 cout << " Mixed Virtual Packages: " << NVirt << endl;
233 cout << " Missing: " << Missing << endl;
234
235 cout << "Total Distinct Versions: " << Cache.Head().VersionCount << endl;
236 cout << "Total Dependencies: " << Cache.Head().DependsCount << endl;
237 return true;
238}
239 /*}}}*/
240// Dump - show everything /*{{{*/
241// ---------------------------------------------------------------------
242/* */
243bool Dump()
244{
245 File CacheF(CacheFile,File::ReadOnly);
246 if (_error->PendingError() == true)
247 return false;
248
249 MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
250 if (_error->PendingError() == true)
251 return false;
252
253 pkgCache Cache(Map);
254 if (_error->PendingError() == true)
255 return false;
256
257 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
258 {
259 cout << "Package: " << P.Name() << endl;
260 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
261 {
262 cout << " Version: " << V.VerStr() << endl;
263 cout << " File: " << V.FileList().File().FileName() << endl;
264 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
265 cout << " Depends: " << D.TargetPkg().Name() << ' ' << D.TargetVer() << endl;
266 }
267 }
268
269 for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
270 {
271 cout << "File: " << F.FileName() << endl;
272 cout << " Size: " << F->Size << endl;
273 cout << " ID: " << F->ID << endl;
274 cout << " Flags: " << F->Flags << endl;
275 cout << " Time: " << ctime(&F->mtime) << endl;
276 }
277
278 return true;
279}
280 /*}}}*/
281// DumpAvail - Print out the available list /*{{{*/
282// ---------------------------------------------------------------------
283/* This is needed to make dpkg --merge happy */
284bool DumpAvail()
285{
286#if 0
287 pkgCache Cache(CacheFile,true,true);
288 if (_error->PendingError() == true)
289 return false;
290
291 pkgControlCache CCache(Cache);
292 if (_error->PendingError() == true)
293 return false;
294
295 vector<string> Lines;
296 Lines.reserve(30);
297
298 pkgCache::PkgIterator I = Cache.PkgBegin();
299 for (;I.end() != true; I++)
300 {
301 if (I->VersionList == 0)
302 continue;
303
304 pkgSPkgCtrlInfo Inf = CCache[I.VersionList()];
305 if (Inf.isNull() == true)
306 return _error->Error("Couldn't locate info record");
307
308 // Iterate over each element
309 pkgPkgCtrlInfo::const_iterator Elm = Inf->begin();
310 for (; Elm != Inf->end(); Elm++)
311 {
312 // Write the tag: value
313 cout << (*Elm)->Tag() << ": " << (*Elm)->Value() << endl;
314
315 // Write the multiline
316 (*Elm)->GetLines(Lines);
317 for (vector<string>::iterator j = Lines.begin(); j != Lines.end(); j++)
318 {
319 if ((*j).length() == 0)
320 cout << " ." << endl;
321 else
322 cout << " " << *j << endl;
323 }
324
325 Lines.erase(Lines.begin(),Lines.end());
326 }
327
328 cout << endl;
329 }
330#endif
331 return true;
332}
333 /*}}}*/
334
335int main(int argc, char *argv[])
336{
337 // Check arguments.
338 if (argc < 3)
339 {
340 cerr << "Usage is apt-cache add cache file1:dist:ver file2:dist:ver ..." << endl;
341 return 100;
342 }
8efa2a3b
AL
343
344 pkgInitialize(*_config);
1164783d
AL
345 while (1)
346 {
347 if (strcmp(argv[1],"add") == 0)
348 {
349 CacheFile = argv[2];
350 if (DoAdd(argc - 3,argv + 3) == true)
351 Stats(argv[2]);
352 break;
353 }
354
355 if (strcmp(argv[1],"showpkg") == 0)
356 {
357 CacheFile = argv[2];
358 DumpPackage(argc - 3,argv + 3);
359 break;
360 }
361
362 if (strcmp(argv[1],"stats") == 0)
363 {
364 Stats(argv[2]);
365 break;
366 }
367
368 if (strcmp(argv[1],"dump") == 0)
369 {
370 CacheFile = argv[2];
371 Dump();
372 break;
373 }
374
375 if (strcmp(argv[1],"dumpavail") == 0)
376 {
377 CacheFile = argv[2];
378 DumpAvail();
379 break;
380 }
381
382 _error->Error("Invalid operation %s", argv[1]);
383 break;
384 }
385
386 // Print any errors or warnings found during parsing
387 if (_error->empty() == false)
388 {
389 _error->DumpErrors();
390 return 100;
391 }
392
393 return 0;
394}