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