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