]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
Larger line buffer, #106591
[apt.git] / cmdline / apt-cache.cc
CommitLineData
1164783d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
c29652b0 3// $Id: apt-cache.cc,v 1.52 2001/07/02 00:10:32 jgg Exp $
1164783d
AL
4/* ######################################################################
5
e1b74f61 6 apt-cache - Manages the cache files
1164783d 7
e1b74f61 8 apt-cache provides some functions fo manipulating the cache files.
b2e465d6 9 It uses the command line interface common to all the APT tools.
1164783d
AL
10
11 Returns 100 on failure, 0 on success.
12
13 ##################################################################### */
14 /*}}}*/
15// Include Files /*{{{*/
16#include <apt-pkg/error.h>
17#include <apt-pkg/pkgcachegen.h>
8efa2a3b 18#include <apt-pkg/init.h>
404ec98e 19#include <apt-pkg/progress.h>
880e9be4 20#include <apt-pkg/sourcelist.h>
08e8f724 21#include <apt-pkg/cmndline.h>
cdcc6d34 22#include <apt-pkg/strutl.h>
9dbb421f 23#include <apt-pkg/pkgrecords.h>
f8f410f5 24#include <apt-pkg/srcrecords.h>
3e94da1b 25#include <apt-pkg/version.h>
b2e465d6
AL
26#include <apt-pkg/policy.h>
27#include <apt-pkg/tagfile.h>
28#include <apt-pkg/algorithms.h>
29#include <apt-pkg/sptr.h>
30
43981212 31#include <config.h>
b2e465d6 32#include <apti18n.h>
1164783d
AL
33
34#include <iostream.h>
cdb970c7 35#include <unistd.h>
43981212 36#include <errno.h>
9dbb421f 37#include <regex.h>
3e94da1b 38#include <stdio.h>
1164783d
AL
39 /*}}}*/
40
b0b4efb9 41pkgCache *GCache = 0;
af87ab54 42pkgSourceList *SrcList = 0;
b0b4efb9 43
b2e465d6
AL
44// LocalitySort - Sort a version list by package file locality /*{{{*/
45// ---------------------------------------------------------------------
46/* */
47int LocalityCompare(const void *a, const void *b)
48{
49 pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
50 pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
51
52 if (A == 0 && B == 0)
53 return 0;
54 if (A == 0)
55 return 1;
56 if (B == 0)
57 return -1;
58
59 if (A->File == B->File)
60 return A->Offset - B->Offset;
61 return A->File - B->File;
62}
63
64void LocalitySort(pkgCache::VerFile **begin,
65 unsigned long Count,size_t Size)
66{
67 qsort(begin,Count,Size,LocalityCompare);
68}
69 /*}}}*/
cc718e9a
AL
70// UnMet - Show unmet dependencies /*{{{*/
71// ---------------------------------------------------------------------
72/* */
b0b4efb9 73bool UnMet(CommandLine &CmdL)
cc718e9a 74{
b0b4efb9 75 pkgCache &Cache = *GCache;
76fbce56 76 bool Important = _config->FindB("APT::Cache::Important",false);
018f1533 77
cc718e9a
AL
78 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
79 {
80 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
81 {
82 bool Header = false;
018f1533 83 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
cc718e9a
AL
84 {
85 // Collect or groups
86 pkgCache::DepIterator Start;
87 pkgCache::DepIterator End;
88 D.GlobOr(Start,End);
89
018f1533 90 // Skip conflicts and replaces
cc718e9a
AL
91 if (End->Type != pkgCache::Dep::PreDepends &&
92 End->Type != pkgCache::Dep::Depends &&
93 End->Type != pkgCache::Dep::Suggests &&
94 End->Type != pkgCache::Dep::Recommends)
95 continue;
96
018f1533
AL
97 // Important deps only
98 if (Important == true)
99 if (End->Type != pkgCache::Dep::PreDepends &&
100 End->Type != pkgCache::Dep::Depends)
101 continue;
102
cc718e9a
AL
103 // Verify the or group
104 bool OK = false;
105 pkgCache::DepIterator RealStart = Start;
106 do
107 {
108 // See if this dep is Ok
109 pkgCache::Version **VList = Start.AllTargets();
110 if (*VList != 0)
111 {
112 OK = true;
113 delete [] VList;
114 break;
115 }
116 delete [] VList;
117
118 if (Start == End)
119 break;
120 Start++;
121 }
122 while (1);
123
124 // The group is OK
125 if (OK == true)
126 continue;
127
128 // Oops, it failed..
129 if (Header == false)
b2e465d6
AL
130 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
131 P.Name(),V.VerStr());
cc718e9a
AL
132 Header = true;
133
134 // Print out the dep type
135 cout << " " << End.DepType() << ": ";
136
137 // Show the group
138 Start = RealStart;
139 do
140 {
141 cout << Start.TargetPkg().Name();
142 if (Start.TargetVer() != 0)
143 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
144 ")";
145 if (Start == End)
146 break;
147 cout << " | ";
148 Start++;
149 }
150 while (1);
151
152 cout << endl;
153 }
154 }
155 }
156 return true;
157}
158 /*}}}*/
1164783d
AL
159// DumpPackage - Show a dump of a package record /*{{{*/
160// ---------------------------------------------------------------------
161/* */
b0b4efb9 162bool DumpPackage(CommandLine &CmdL)
ad00ae81 163{
b0b4efb9 164 pkgCache &Cache = *GCache;
e1b74f61 165 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1164783d 166 {
e1b74f61 167 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1164783d
AL
168 if (Pkg.end() == true)
169 {
b2e465d6 170 _error->Warning(_("Unable to locate package %s"),*I);
1164783d
AL
171 continue;
172 }
173
174 cout << "Package: " << Pkg.Name() << endl;
b2e465d6 175 cout << "Versions: " << endl;
1164783d 176 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
03e39e59
AL
177 {
178 cout << Cur.VerStr();
179 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
180 cout << "(" << Vf.File().FileName() << ")";
b2e465d6 181 cout << endl;
03e39e59
AL
182 }
183
1164783d
AL
184 cout << endl;
185
186 cout << "Reverse Depends: " << endl;
187 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
b2e465d6
AL
188 {
189 cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name();
190 if (D->Version != 0)
b1b663d1 191 cout << ' ' << DeNull(D.TargetVer()) << endl;
b2e465d6
AL
192 else
193 cout << endl;
194 }
195
1164783d
AL
196 cout << "Dependencies: " << endl;
197 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
198 {
199 cout << Cur.VerStr() << " - ";
200 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
b1b663d1 201 cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
1164783d
AL
202 cout << endl;
203 }
204
205 cout << "Provides: " << endl;
206 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
207 {
208 cout << Cur.VerStr() << " - ";
209 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
210 cout << Prv.ParentPkg().Name() << " ";
211 cout << endl;
8efa2a3b
AL
212 }
213 cout << "Reverse Provides: " << endl;
214 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
2d6751b9 215 cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr() << endl;
1164783d
AL
216 }
217
218 return true;
219}
220 /*}}}*/
221// Stats - Dump some nice statistics /*{{{*/
222// ---------------------------------------------------------------------
223/* */
b0b4efb9 224bool Stats(CommandLine &Cmd)
1164783d 225{
b0b4efb9 226 pkgCache &Cache = *GCache;
b2e465d6 227 cout << _("Total Package Names : ") << Cache.Head().PackageCount << " (" <<
f826cfaa 228 SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
b2e465d6 229
1164783d
AL
230 int Normal = 0;
231 int Virtual = 0;
232 int NVirt = 0;
233 int DVirt = 0;
234 int Missing = 0;
b2e465d6 235 pkgCache::PkgIterator I = Cache.PkgBegin();
1164783d
AL
236 for (;I.end() != true; I++)
237 {
238 if (I->VersionList != 0 && I->ProvidesList == 0)
239 {
240 Normal++;
241 continue;
242 }
243
244 if (I->VersionList != 0 && I->ProvidesList != 0)
245 {
246 NVirt++;
247 continue;
248 }
249
250 if (I->VersionList == 0 && I->ProvidesList != 0)
251 {
252 // Only 1 provides
253 if (I.ProvidesList()->NextProvides == 0)
254 {
255 DVirt++;
256 }
257 else
258 Virtual++;
259 continue;
260 }
261 if (I->VersionList == 0 && I->ProvidesList == 0)
262 {
263 Missing++;
264 continue;
265 }
266 }
b2e465d6
AL
267 cout << _(" Normal Packages: ") << Normal << endl;
268 cout << _(" Pure Virtual Packages: ") << Virtual << endl;
269 cout << _(" Single Virtual Packages: ") << DVirt << endl;
270 cout << _(" Mixed Virtual Packages: ") << NVirt << endl;
271 cout << _(" Missing: ") << Missing << endl;
1164783d 272
b2e465d6 273 cout << _("Total Distinct Versions: ") << Cache.Head().VersionCount << " (" <<
f826cfaa 274 SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
b2e465d6 275 cout << _("Total Dependencies: ") << Cache.Head().DependsCount << " (" <<
f826cfaa
AL
276 SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
277
b2e465d6 278 cout << _("Total Ver/File relations: ") << Cache.Head().VerFileCount << " (" <<
a7e66b17 279 SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
b2e465d6 280 cout << _("Total Provides Mappings: ") << Cache.Head().ProvidesCount << " (" <<
a7e66b17 281 SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
f826cfaa
AL
282
283 // String list stats
284 unsigned long Size = 0;
285 unsigned long Count = 0;
286 for (pkgCache::StringItem *I = Cache.StringItemP + Cache.Head().StringList;
287 I!= Cache.StringItemP; I = Cache.StringItemP + I->NextItem)
288 {
289 Count++;
b2e465d6 290 Size += strlen(Cache.StrP + I->String) + 1;
f826cfaa 291 }
b2e465d6
AL
292 cout << _("Total Globbed Strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
293
294 unsigned long DepVerSize = 0;
295 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
296 {
297 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
298 {
299 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
300 {
301 if (D->Version != 0)
302 DepVerSize += strlen(D.TargetVer()) + 1;
303 }
304 }
305 }
306 cout << _("Total Dependency Version space: ") << SizeToStr(DepVerSize) << endl;
307
f826cfaa
AL
308 unsigned long Slack = 0;
309 for (int I = 0; I != 7; I++)
310 Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count;
b2e465d6 311 cout << _("Total Slack space: ") << SizeToStr(Slack) << endl;
f826cfaa
AL
312
313 unsigned long Total = 0;
314 Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz +
315 Cache.Head().VersionCount*Cache.Head().VersionSz +
a7e66b17
AL
316 Cache.Head().PackageCount*Cache.Head().PackageSz +
317 Cache.Head().VerFileCount*Cache.Head().VerFileSz +
318 Cache.Head().ProvidesCount*Cache.Head().ProvidesSz;
b2e465d6 319 cout << _("Total Space Accounted for: ") << SizeToStr(Total) << endl;
f826cfaa 320
83d89a9f
AL
321 return true;
322}
323 /*}}}*/
1164783d
AL
324// Dump - show everything /*{{{*/
325// ---------------------------------------------------------------------
b2e465d6 326/* This is worthless except fer debugging things */
b0b4efb9 327bool Dump(CommandLine &Cmd)
1164783d 328{
b0b4efb9 329 pkgCache &Cache = *GCache;
b2e465d6
AL
330 cout << "Using Versioning System: " << Cache.VS->Label << endl;
331
1164783d
AL
332 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
333 {
334 cout << "Package: " << P.Name() << endl;
335 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
336 {
337 cout << " Version: " << V.VerStr() << endl;
338 cout << " File: " << V.FileList().File().FileName() << endl;
339 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
076d01b0
AL
340 cout << " Depends: " << D.TargetPkg().Name() << ' ' <<
341 DeNull(D.TargetVer()) << endl;
1164783d
AL
342 }
343 }
344
b2e465d6 345 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
1164783d
AL
346 {
347 cout << "File: " << F.FileName() << endl;
b2e465d6 348 cout << " Type: " << F.IndexType() << endl;
1164783d
AL
349 cout << " Size: " << F->Size << endl;
350 cout << " ID: " << F->ID << endl;
351 cout << " Flags: " << F->Flags << endl;
b0b4efb9 352 cout << " Time: " << TimeRFC1123(F->mtime) << endl;
076d01b0
AL
353 cout << " Archive: " << DeNull(F.Archive()) << endl;
354 cout << " Component: " << DeNull(F.Component()) << endl;
355 cout << " Version: " << DeNull(F.Version()) << endl;
356 cout << " Origin: " << DeNull(F.Origin()) << endl;
357 cout << " Site: " << DeNull(F.Site()) << endl;
358 cout << " Label: " << DeNull(F.Label()) << endl;
359 cout << " Architecture: " << DeNull(F.Architecture()) << endl;
1164783d
AL
360 }
361
362 return true;
363}
364 /*}}}*/
365// DumpAvail - Print out the available list /*{{{*/
366// ---------------------------------------------------------------------
b2e465d6
AL
367/* This is needed to make dpkg --merge happy.. I spent a bit of time to
368 make this run really fast, perhaps I went a little overboard.. */
b0b4efb9 369bool DumpAvail(CommandLine &Cmd)
1164783d 370{
b0b4efb9 371 pkgCache &Cache = *GCache;
1164783d 372
b2e465d6
AL
373 pkgPolicy Plcy(&Cache);
374 if (ReadPinFile(Plcy) == false)
375 return false;
376
377 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Cache.HeaderP->PackageCount];
378 memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount);
379
380 // Map versions that we want to write out onto the VerList array.
381 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
382 {
383 if (P->VersionList == 0)
5b8c90bf
AL
384 continue;
385
b2e465d6
AL
386 /* Find the proper version to use. If the policy says there are no
387 possible selections we return the installed version, if available..
388 This prevents dselect from making it obsolete. */
389 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
390 if (V.end() == true)
ad00ae81 391 {
b2e465d6
AL
392 if (P->CurrentVer == 0)
393 continue;
394 V = P.CurrentVer();
ad00ae81 395 }
1164783d 396
b2e465d6
AL
397 pkgCache::VerFileIterator VF = V.FileList();
398 for (; VF.end() == false ; VF++)
399 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
400 break;
401
402 /* Okay, here we have a bit of a problem.. The policy has selected the
403 currently installed package - however it only exists in the
404 status file.. We need to write out something or dselect will mark
405 the package as obsolete! Thus we emit the status file entry, but
406 below we remove the status line to make it valid for the
407 available file. However! We only do this if their do exist *any*
408 non-source versions of the package - that way the dselect obsolete
409 handling works OK. */
410 if (VF.end() == true)
1164783d 411 {
b2e465d6
AL
412 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; Cur++)
413 {
414 for (VF = Cur.FileList(); VF.end() == false; VF++)
415 {
416 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
417 {
418 VF = V.FileList();
419 break;
420 }
421 }
422
423 if (VF.end() == false)
424 break;
425 }
ad00ae81 426 }
b2e465d6
AL
427
428 VFList[P->ID] = VF;
429 }
430
431 LocalitySort(VFList,Cache.HeaderP->PackageCount,sizeof(*VFList));
ad00ae81 432
b2e465d6
AL
433 // Iterate over all the package files and write them out.
434 char *Buffer = new char[Cache.HeaderP->MaxVerFileSize+10];
435 for (pkgCache::VerFile **J = VFList; *J != 0;)
436 {
437 pkgCache::PkgFileIterator File(Cache,(*J)->File + Cache.PkgFileP);
438 if (File.IsOk() == false)
ad00ae81 439 {
b2e465d6
AL
440 _error->Error(_("Package file %s is out of sync."),File.FileName());
441 break;
442 }
bd432be3 443
b2e465d6
AL
444 FileFd PkgF(File.FileName(),FileFd::ReadOnly);
445 if (_error->PendingError() == true)
446 break;
447
448 /* Write all of the records from this package file, since we
449 already did locality sorting we can now just seek through the
450 file in read order. We apply 1 more optimization here, since often
451 there will be < 1 byte gaps between records (for the \n) we read that
452 into the next buffer and offset a bit.. */
453 unsigned long Pos = 0;
454 for (; *J != 0; J++)
455 {
456 if ((*J)->File + Cache.PkgFileP != File)
457 break;
bd432be3 458
b2e465d6
AL
459 const pkgCache::VerFile &VF = **J;
460
bd432be3 461 // Read the record and then write it out again.
b2e465d6
AL
462 unsigned long Jitter = VF.Offset - Pos;
463 if (Jitter > 8)
1164783d 464 {
b2e465d6
AL
465 if (PkgF.Seek(VF.Offset) == false)
466 break;
467 Jitter = 0;
468 }
469
470 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
471 break;
472 Buffer[VF.Size + Jitter] = '\n';
473
474 // See above..
475 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
476 {
477 pkgTagSection Tags;
e8cbb49f 478 TFRewriteData RW[] = {{"Status",0},{"Config-Version",0},{}};
b2e465d6
AL
479 const char *Zero = 0;
480 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
481 TFRewrite(stdout,Tags,&Zero,RW) == false)
482 {
483 _error->Error("Internal Error, Unable to parse a package record");
484 break;
485 }
486 fputc('\n',stdout);
487 }
488 else
489 {
490 if (fwrite(Buffer+Jitter,VF.Size+1,1,stdout) != 1)
491 break;
492 }
493
494 Pos = VF.Offset + VF.Size;
1164783d 495 }
b2e465d6
AL
496
497 fflush(stdout);
498 if (_error->PendingError() == true)
499 break;
ad00ae81
AL
500 }
501
b2e465d6
AL
502 delete [] Buffer;
503 delete [] VFList;
504 return !_error->PendingError();
349cd3b8
AL
505}
506 /*}}}*/
4b1b89c5 507// Depends - Print out a dependency tree /*{{{*/
349cd3b8
AL
508// ---------------------------------------------------------------------
509/* */
510bool Depends(CommandLine &CmdL)
511{
512 pkgCache &Cache = *GCache;
b2e465d6
AL
513 SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
514 memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
349cd3b8
AL
515
516 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
517 {
518 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
519 if (Pkg.end() == true)
520 {
b2e465d6 521 _error->Warning(_("Unable to locate package %s"),*I);
349cd3b8
AL
522 continue;
523 }
b2e465d6
AL
524 Colours[Pkg->ID] = 1;
525 }
526
527 bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
528 bool DidSomething;
529 do
530 {
531 DidSomething = false;
532 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
349cd3b8 533 {
b2e465d6
AL
534 if (Colours[Pkg->ID] != 1)
535 continue;
536 Colours[Pkg->ID] = 2;
537 DidSomething = true;
349cd3b8 538
b2e465d6
AL
539 pkgCache::VerIterator Ver = Pkg.VersionList();
540 if (Ver.end() == true)
349cd3b8 541 {
b2e465d6
AL
542 cout << '<' << Pkg.Name() << '>' << endl;
543 continue;
349cd3b8 544 }
b2e465d6
AL
545
546 cout << Pkg.Name() << endl;
547
548 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
549 {
550 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
551 cout << " |";
552 else
553 cout << " ";
554
555 // Show the package
556 pkgCache::PkgIterator Trg = D.TargetPkg();
557 if (Trg->VersionList == 0)
558 cout << D.DepType() << ": <" << Trg.Name() << ">" << endl;
559 else
560 cout << D.DepType() << ": " << Trg.Name() << endl;
561
562 if (Recurse == true)
563 Colours[D.TargetPkg()->ID]++;
564
565 // Display all solutions
566 SPtrArray<pkgCache::Version *> List = D.AllTargets();
567 pkgPrioSortList(Cache,List);
568 for (pkgCache::Version **I = List; *I != 0; I++)
569 {
570 pkgCache::VerIterator V(Cache,*I);
571 if (V != Cache.VerP + V.ParentPkg()->VersionList ||
572 V->ParentPkg == D->Package)
573 continue;
574 cout << " " << V.ParentPkg().Name() << endl;
575
576 if (Recurse == true)
577 Colours[D.ParentPkg()->ID]++;
578 }
579 }
580 }
349cd3b8 581 }
b2e465d6 582 while (DidSomething == true);
349cd3b8 583
3e94da1b
AL
584 return true;
585}
586 /*}}}*/
587// Dotty - Generate a graph for Dotty /*{{{*/
588// ---------------------------------------------------------------------
589/* Dotty is the graphvis program for generating graphs. It is a fairly
590 simple queuing algorithm that just writes dependencies and nodes.
591 http://www.research.att.com/sw/tools/graphviz/ */
592bool Dotty(CommandLine &CmdL)
593{
594 pkgCache &Cache = *GCache;
595 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
596
597 /* Normal packages are boxes
598 Pure Provides are triangles
599 Mixed are diamonds
600 Hexagons are missing packages*/
601 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
602
603 /* Initialize the list of packages to show.
604 1 = To Show
605 2 = To Show no recurse
606 3 = Emitted no recurse
607 4 = Emitted
608 0 = None */
609 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
610 enum TheFlags {ForceNR=(1<<0)};
611 unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
612 unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
613 unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
614
615 // Show everything if no arguments given
616 if (CmdL.FileList[1] == 0)
617 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
618 Show[I] = ToShow;
619 else
620 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
621 Show[I] = None;
622 memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
623
624 // Map the shapes
625 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
626 {
627 if (Pkg->VersionList == 0)
628 {
629 // Missing
630 if (Pkg->ProvidesList == 0)
631 ShapeMap[Pkg->ID] = 0;
632 else
633 ShapeMap[Pkg->ID] = 1;
634 }
635 else
636 {
637 // Normal
638 if (Pkg->ProvidesList == 0)
639 ShapeMap[Pkg->ID] = 2;
640 else
641 ShapeMap[Pkg->ID] = 3;
642 }
643 }
644
645 // Load the list of packages from the command line into the show list
646 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
647 {
648 // Process per-package flags
649 string P = *I;
650 bool Force = false;
651 if (P.length() > 3)
652 {
653 if (P.end()[-1] == '^')
654 {
655 Force = true;
656 P.erase(P.end()-1);
657 }
658
659 if (P.end()[-1] == ',')
660 P.erase(P.end()-1);
661 }
662
663 // Locate the package
664 pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
665 if (Pkg.end() == true)
666 {
b2e465d6 667 _error->Warning(_("Unable to locate package %s"),*I);
3e94da1b
AL
668 continue;
669 }
670 Show[Pkg->ID] = ToShow;
671
672 if (Force == true)
673 Flags[Pkg->ID] |= ForceNR;
674 }
675
676 // Little header
677 printf("digraph packages {\n");
678 printf("concentrate=true;\n");
679 printf("size=\"30,40\";\n");
680
681 bool Act = true;
682 while (Act == true)
683 {
684 Act = false;
685 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
686 {
687 // See we need to show this package
688 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
689 continue;
690
691 // Colour as done
692 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
693 {
694 // Pure Provides and missing packages have no deps!
695 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
696 Show[Pkg->ID] = Done;
697 else
698 Show[Pkg->ID] = DoneNR;
699 }
700 else
701 Show[Pkg->ID] = Done;
702 Act = true;
703
704 // No deps to map out
705 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
706 continue;
707
708 pkgCache::VerIterator Ver = Pkg.VersionList();
709 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
710 {
711 // See if anything can meet this dep
712 // Walk along the actual package providing versions
713 bool Hit = false;
714 pkgCache::PkgIterator DPkg = D.TargetPkg();
715 for (pkgCache::VerIterator I = DPkg.VersionList();
716 I.end() == false && Hit == false; I++)
717 {
b2e465d6 718 if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
3e94da1b
AL
719 Hit = true;
720 }
721
722 // Follow all provides
723 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
724 I.end() == false && Hit == false; I++)
725 {
b2e465d6 726 if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
3e94da1b
AL
727 Hit = true;
728 }
729
730 // Only graph critical deps
731 if (D.IsCritical() == true)
732 {
733 printf("\"%s\" -> \"%s\"",Pkg.Name(),D.TargetPkg().Name());
734
735 // Colour the node for recursion
736 if (Show[D.TargetPkg()->ID] <= DoneNR)
737 {
738 /* If a conflicts does not meet anything in the database
739 then show the relation but do not recurse */
b2e465d6
AL
740 if (Hit == false &&
741 (D->Type == pkgCache::Dep::Conflicts ||
742 D->Type == pkgCache::Dep::Obsoletes))
3e94da1b
AL
743 {
744 if (Show[D.TargetPkg()->ID] == None &&
745 Show[D.TargetPkg()->ID] != ToShow)
746 Show[D.TargetPkg()->ID] = ToShowNR;
747 }
748 else
749 {
750 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
751 Show[D.TargetPkg()->ID] = ToShowNR;
752 else
753 Show[D.TargetPkg()->ID] = ToShow;
754 }
755 }
756
757 // Edge colour
758 switch(D->Type)
759 {
760 case pkgCache::Dep::Conflicts:
b2e465d6 761 case pkgCache::Dep::Obsoletes:
3e94da1b
AL
762 printf("[color=springgreen];\n");
763 break;
764
765 case pkgCache::Dep::PreDepends:
766 printf("[color=blue];\n");
767 break;
768
769 default:
770 printf(";\n");
771 break;
772 }
773 }
774 }
775 }
776 }
777
778 /* Draw the box colours after the fact since we can not tell what colour
779 they should be until everything is finished drawing */
780 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
781 {
782 if (Show[Pkg->ID] < DoneNR)
783 continue;
784
785 // Orange box for early recursion stoppage
786 if (Show[Pkg->ID] == DoneNR)
787 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.Name(),
788 Shapes[ShapeMap[Pkg->ID]]);
789 else
790 printf("\"%s\" [shape=%s];\n",Pkg.Name(),
791 Shapes[ShapeMap[Pkg->ID]]);
792 }
793
794 printf("}\n");
ad00ae81
AL
795 return true;
796}
797 /*}}}*/
798// DoAdd - Perform an adding operation /*{{{*/
799// ---------------------------------------------------------------------
800/* */
e1b74f61 801bool DoAdd(CommandLine &CmdL)
ad00ae81 802{
b2e465d6
AL
803 return _error->Error("Unimplemented");
804#if 0
e1b74f61
AL
805 // Make sure there is at least one argument
806 if (CmdL.FileSize() <= 1)
807 return _error->Error("You must give at least one file name");
ad00ae81
AL
808
809 // Open the cache
018f1533 810 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
ad00ae81
AL
811 if (_error->PendingError() == true)
812 return false;
813
814 DynamicMMap Map(CacheF,MMap::Public);
815 if (_error->PendingError() == true)
816 return false;
404ec98e 817
0a8e3465 818 OpTextProgress Progress(*_config);
404ec98e 819 pkgCacheGenerator Gen(Map,Progress);
ad00ae81
AL
820 if (_error->PendingError() == true)
821 return false;
822
e1b74f61
AL
823 unsigned long Length = CmdL.FileSize() - 1;
824 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
ad00ae81 825 {
e1b74f61 826 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
018f1533
AL
827 Progress.SubProgress(Length);
828
ad00ae81 829 // Do the merge
e1b74f61 830 FileFd TagF(*I,FileFd::ReadOnly);
ad00ae81
AL
831 debListParser Parser(TagF);
832 if (_error->PendingError() == true)
e1b74f61 833 return _error->Error("Problem opening %s",*I);
ad00ae81 834
b2e465d6 835 if (Gen.SelectFile(*I,"") == false)
ad00ae81
AL
836 return _error->Error("Problem with SelectFile");
837
838 if (Gen.MergeList(Parser) == false)
839 return _error->Error("Problem with MergeList");
1164783d 840 }
404ec98e
AL
841
842 Progress.Done();
b0b4efb9
AL
843 GCache = &Gen.GetCache();
844 Stats(CmdL);
ad00ae81 845
7e2e2d5d 846 return true;
b2e465d6 847#endif
7e2e2d5d
AL
848}
849 /*}}}*/
850// DisplayRecord - Displays the complete record for the package /*{{{*/
851// ---------------------------------------------------------------------
852/* This displays the package record from the proper package index file.
853 It is not used by DumpAvail for performance reasons. */
854bool DisplayRecord(pkgCache::VerIterator V)
855{
856 // Find an appropriate file
857 pkgCache::VerFileIterator Vf = V.FileList();
858 for (; Vf.end() == false; Vf++)
859 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
860 break;
861 if (Vf.end() == true)
862 Vf = V.FileList();
863
864 // Check and load the package list file
865 pkgCache::PkgFileIterator I = Vf.File();
866 if (I.IsOk() == false)
b2e465d6 867 return _error->Error(_("Package file %s is out of sync."),I.FileName());
7e2e2d5d
AL
868
869 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
870 if (_error->PendingError() == true)
871 return false;
872
873 // Read the record and then write it out again.
b2e465d6
AL
874 unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
875 Buffer[V.FileList()->Size] = '\n';
7e2e2d5d
AL
876 if (PkgF.Seek(V.FileList()->Offset) == false ||
877 PkgF.Read(Buffer,V.FileList()->Size) == false ||
b2e465d6 878 write(STDOUT_FILENO,Buffer,V.FileList()->Size+1) != V.FileList()->Size+1)
7e2e2d5d
AL
879 {
880 delete [] Buffer;
881 return false;
882 }
883
884 delete [] Buffer;
885
9dbb421f
AL
886 return true;
887}
888 /*}}}*/
889// Search - Perform a search /*{{{*/
890// ---------------------------------------------------------------------
891/* This searches the package names and pacakge descriptions for a pattern */
b2e465d6
AL
892struct ExVerFile
893{
894 pkgCache::VerFile *Vf;
895 bool NameMatch;
896};
897
9dbb421f
AL
898bool Search(CommandLine &CmdL)
899{
900 pkgCache &Cache = *GCache;
7e2e2d5d
AL
901 bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
902 bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
b2e465d6
AL
903 unsigned NumPatterns = CmdL.FileSize() -1;
904
905 pkgDepCache::Policy Plcy;
9dbb421f
AL
906
907 // Make sure there is at least one argument
b2e465d6
AL
908 if (NumPatterns < 1)
909 return _error->Error(_("You must give exactly one pattern"));
9dbb421f
AL
910
911 // Compile the regex pattern
b2e465d6
AL
912 regex_t *Patterns = new regex_t[NumPatterns];
913 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
914 for (unsigned I = 0; I != NumPatterns; I++)
915 {
916 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
917 REG_NOSUB) != 0)
918 {
919 for (; I != 0; I--)
920 regfree(&Patterns[I]);
921 return _error->Error("Regex compilation error");
922 }
923 }
9dbb421f
AL
924
925 // Create the text record parser
926 pkgRecords Recs(Cache);
927 if (_error->PendingError() == true)
b2e465d6
AL
928 {
929 for (unsigned I = 0; I != NumPatterns; I++)
930 regfree(&Patterns[I]);
9dbb421f 931 return false;
b2e465d6 932 }
9dbb421f 933
b2e465d6
AL
934 ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
935 memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
936
937 // Map versions that we want to write out onto the VerList array.
938 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
9dbb421f 939 {
0f2fa322 940 VFList[P->ID].NameMatch = NumPatterns != 0;
b2e465d6
AL
941 for (unsigned I = 0; I != NumPatterns; I++)
942 {
943 if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
0f2fa322
AL
944 VFList[P->ID].NameMatch &= true;
945 else
946 VFList[P->ID].NameMatch = false;
b2e465d6 947 }
c29652b0 948
b2e465d6
AL
949 // Doing names only, drop any that dont match..
950 if (NamesOnly == true && VFList[P->ID].NameMatch == false)
951 continue;
952
953 // Find the proper version to use.
954 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
c29652b0
AL
955 if (V.end() == false)
956 VFList[P->ID].Vf = V.FileList();
957 }
958
959 // Include all the packages that provide matching names too
960 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
961 {
962 if (VFList[P->ID].NameMatch == false)
7e2e2d5d 963 continue;
c29652b0
AL
964
965 for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
966 {
967 pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
968 if (V.end() == false)
969 {
970 VFList[Prv.OwnerPkg()->ID].Vf = V.FileList();
971 VFList[Prv.OwnerPkg()->ID].NameMatch = true;
972 }
973 }
b2e465d6 974 }
c29652b0 975
b2e465d6 976 LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
7e2e2d5d 977
b2e465d6
AL
978 // Iterate over all the version records and check them
979 for (ExVerFile *J = VFList; J->Vf != 0; J++)
980 {
981 pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
0f2fa322
AL
982
983 bool Match = true;
984 if (J->NameMatch == false)
985 {
986 string LongDesc = P.LongDesc();
987 Match = NumPatterns != 0;
988 for (unsigned I = 0; I != NumPatterns; I++)
989 {
990 if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
991 Match &= true;
992 else
993 Match = false;
994 }
995 }
b2e465d6
AL
996
997 if (Match == true)
9dbb421f 998 {
7e2e2d5d 999 if (ShowFull == true)
b2e465d6
AL
1000 {
1001 const char *Start;
1002 const char *End;
1003 P.GetRec(Start,End);
1004 fwrite(Start,End-Start,1,stdout);
1005 putc('\n',stdout);
1006 }
7e2e2d5d 1007 else
b2e465d6
AL
1008 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
1009 }
9dbb421f
AL
1010 }
1011
b2e465d6
AL
1012 delete [] VFList;
1013 for (unsigned I = 0; I != NumPatterns; I++)
1014 regfree(&Patterns[I]);
1015 if (ferror(stdout))
1016 return _error->Error("Write to stdout failed");
1164783d
AL
1017 return true;
1018}
1019 /*}}}*/
7e2e2d5d
AL
1020// ShowPackage - Dump the package record to the screen /*{{{*/
1021// ---------------------------------------------------------------------
1022/* */
1023bool ShowPackage(CommandLine &CmdL)
1024{
1025 pkgCache &Cache = *GCache;
b2e465d6
AL
1026 pkgDepCache::Policy Plcy;
1027
7e2e2d5d
AL
1028 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1029 {
1030 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1031 if (Pkg.end() == true)
1032 {
b2e465d6 1033 _error->Warning(_("Unable to locate package %s"),*I);
7e2e2d5d
AL
1034 continue;
1035 }
b2e465d6
AL
1036
1037 // Find the proper version to use.
648e3cb4
AL
1038 if (_config->FindB("APT::Cache::AllVersions","true") == true)
1039 {
1040 pkgCache::VerIterator V;
1041 for (V = Pkg.VersionList(); V.end() == false; V++)
1042 {
1043 if (DisplayRecord(V) == false)
1044 return false;
1045 }
1046 }
1047 else
1048 {
b2e465d6 1049 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
648e3cb4
AL
1050 if (V.end() == true || V.FileList().end() == true)
1051 continue;
1052 if (DisplayRecord(V) == false)
1053 return false;
1054 }
7e2e2d5d 1055 }
7c1133fe
AL
1056 return true;
1057}
1058 /*}}}*/
1059// ShowPkgNames - Show package names /*{{{*/
1060// ---------------------------------------------------------------------
1061/* This does a prefix match on the first argument */
1062bool ShowPkgNames(CommandLine &CmdL)
1063{
1064 pkgCache &Cache = *GCache;
1065 pkgCache::PkgIterator I = Cache.PkgBegin();
1066 bool All = _config->FindB("APT::Cache::AllNames","false");
1067
1068 if (CmdL.FileList[1] != 0)
1069 {
1070 for (;I.end() != true; I++)
1071 {
1072 if (All == false && I->VersionList == 0)
1073 continue;
1074
1075 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1076 cout << I.Name() << endl;
1077 }
1078
1079 return true;
1080 }
1081
1082 // Show all pkgs
1083 for (;I.end() != true; I++)
1084 {
1085 if (All == false && I->VersionList == 0)
1086 continue;
1087 cout << I.Name() << endl;
1088 }
1089
7e2e2d5d
AL
1090 return true;
1091}
1092 /*}}}*/
f8f410f5
AL
1093// ShowSrcPackage - Show source package records /*{{{*/
1094// ---------------------------------------------------------------------
1095/* */
1096bool ShowSrcPackage(CommandLine &CmdL)
1097{
1098 pkgSourceList List;
1099 List.ReadMainList();
1100
1101 // Create the text record parsers
1102 pkgSrcRecords SrcRecs(List);
1103 if (_error->PendingError() == true)
1104 return false;
1105
1106 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1107 {
aaee8293
AL
1108 SrcRecs.Restart();
1109
f8f410f5
AL
1110 pkgSrcRecords::Parser *Parse;
1111 while ((Parse = SrcRecs.Find(*I,false)) != 0)
b2e465d6 1112 cout << Parse->AsStr() << endl;;
f8f410f5 1113 }
af87ab54
AL
1114 return true;
1115}
1116 /*}}}*/
1117// Policy - Show the results of the preferences file /*{{{*/
1118// ---------------------------------------------------------------------
1119/* */
1120bool Policy(CommandLine &CmdL)
1121{
1122 if (SrcList == 0)
1123 return _error->Error("Generate must be enabled for this function");
1124
1125 pkgCache &Cache = *GCache;
1126 pkgPolicy Plcy(&Cache);
1127 if (ReadPinFile(Plcy) == false)
1128 return false;
1129
1130 // Print out all of the package files
1131 if (CmdL.FileList[1] == 0)
1132 {
1133 cout << _("Package Files:") << endl;
1134 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
1135 {
1136 // Locate the associated index files so we can derive a description
1137 pkgIndexFile *Indx;
1138 if (SrcList->FindIndex(F,Indx) == false &&
1139 _system->FindIndex(F,Indx) == false)
1140 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1141 printf(_("%4i %s\n"),
1142 Plcy.GetPriority(F),Indx->Describe(true).c_str());
1143
1144 // Print the reference information for the package
1145 string Str = F.RelStr();
1146 if (Str.empty() == false)
1147 printf(" release %s\n",F.RelStr().c_str());
1148 if (F.Site() != 0 && F.Site()[0] != 0)
1149 printf(" origin %s\n",F.Site());
1150 }
1151
1152 // Show any packages have explicit pins
1153 cout << _("Pinned Packages:") << endl;
1154 pkgCache::PkgIterator I = Cache.PkgBegin();
1155 for (;I.end() != true; I++)
1156 {
1157 if (Plcy.GetPriority(I) == 0)
1158 continue;
1159
1160 // Print the package name and the version we are forcing to
1161 cout << " " << I.Name() << " -> ";
1162
1163 pkgCache::VerIterator V = Plcy.GetMatch(I);
1164 if (V.end() == true)
1165 cout << _("(not found)") << endl;
1166 else
1167 cout << V.VerStr() << endl;
1168 }
1169
1170 return true;
1171 }
1172
1173 // Print out detailed information for each package
1174 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1175 {
1176 pkgCache::PkgIterator Pkg = Cache.FindPkg(*I);
1177 if (Pkg.end() == true)
1178 {
1179 _error->Warning(_("Unable to locate package %s"),*I);
1180 continue;
1181 }
1182
1183 cout << Pkg.Name() << ":" << endl;
1184
1185 // Installed version
1186 cout << _(" Installed: ");
1187 if (Pkg->CurrentVer == 0)
1188 cout << _("(none)") << endl;
1189 else
1190 cout << Pkg.CurrentVer().VerStr() << endl;
1191
1192 // Candidate Version
1193 cout << _(" Candidate: ");
1194 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
1195 if (V.end() == true)
1196 cout << _("(none)") << endl;
1197 else
1198 cout << V.VerStr() << endl;
1199
1200 // Pinned version
1201 if (Plcy.GetPriority(Pkg) != 0)
1202 {
1203 cout << _(" Package Pin: ");
1204 V = Plcy.GetMatch(Pkg);
1205 if (V.end() == true)
1206 cout << _("(not found)") << endl;
1207 else
1208 cout << V.VerStr() << endl;
1209 }
1210
1211 // Show the priority tables
1212 cout << _(" Version Table:") << endl;
1213 for (V = Pkg.VersionList(); V.end() == false; V++)
1214 {
1215 if (Pkg.CurrentVer() == V)
1216 cout << " *** " << V.VerStr();
1217 else
1218 cout << " " << V.VerStr();
1219 cout << " " << Plcy.GetPriority(Pkg) << endl;
1220 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1221 {
1222 // Locate the associated index files so we can derive a description
1223 pkgIndexFile *Indx;
1224 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1225 _system->FindIndex(VF.File(),Indx) == false)
1226 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
1227 printf(_(" %4i %s\n"),Plcy.GetPriority(VF.File()),
1228 Indx->Describe(true).c_str());
1229 }
1230 }
1231 }
1232
f8f410f5
AL
1233 return true;
1234}
1235 /*}}}*/
880e9be4
AL
1236// GenCaches - Call the main cache generator /*{{{*/
1237// ---------------------------------------------------------------------
1238/* */
b0b4efb9 1239bool GenCaches(CommandLine &Cmd)
880e9be4 1240{
0a8e3465
AL
1241 OpTextProgress Progress(*_config);
1242
880e9be4 1243 pkgSourceList List;
b2e465d6
AL
1244 if (List.ReadMainList() == false)
1245 return false;
0a8e3465 1246 return pkgMakeStatusCache(List,Progress);
880e9be4
AL
1247}
1248 /*}}}*/
e1b74f61
AL
1249// ShowHelp - Show a help screen /*{{{*/
1250// ---------------------------------------------------------------------
1251/* */
b0b4efb9 1252bool ShowHelp(CommandLine &Cmd)
e1b74f61 1253{
b2e465d6
AL
1254 ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
1255 COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
e1b74f61 1256
b2e465d6
AL
1257 cout <<
1258 _("Usage: apt-cache [options] command\n"
1259 " apt-cache [options] add file1 [file1 ...]\n"
1260 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1261 "\n"
1262 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1263 "cache files, and query information from them\n"
1264 "\n"
1265 "Commands:\n"
1266 " add - Add an package file to the source cache\n"
1267 " gencaches - Build both the package and source cache\n"
1268 " showpkg - Show some general information for a single package\n"
1269 " stats - Show some basic statistics\n"
1270 " dump - Show the entire file in a terse form\n"
1271 " dumpavail - Print an available file to stdout\n"
1272 " unmet - Show unmet dependencies\n"
b2e465d6
AL
1273 " search - Search the package list for a regex pattern\n"
1274 " show - Show a readable record for the package\n"
1275 " depends - Show raw dependency information for a package\n"
1276 " pkgnames - List the names of all packages\n"
1277 " dotty - Generate package graphs for GraphVis\n"
eba05d54 1278 " policy - Show policy settings\n"
b2e465d6
AL
1279 "\n"
1280 "Options:\n"
1281 " -h This help text.\n"
1282 " -p=? The package cache.\n"
1283 " -s=? The source cache.\n"
1284 " -q Disable progress indicator.\n"
1285 " -i Show only important deps for the unmet command.\n"
1286 " -c=? Read this configuration file\n"
1287 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
1288 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1289 return true;
e1b74f61
AL
1290}
1291 /*}}}*/
0a8e3465
AL
1292// CacheInitialize - Initialize things for apt-cache /*{{{*/
1293// ---------------------------------------------------------------------
1294/* */
1295void CacheInitialize()
1296{
1297 _config->Set("quiet",0);
1298 _config->Set("help",false);
1299}
1300 /*}}}*/
1164783d 1301
08e8f724 1302int main(int argc,const char *argv[])
1164783d 1303{
08e8f724
AL
1304 CommandLine::Args Args[] = {
1305 {'h',"help","help",0},
04aa15a8 1306 {'v',"version","version",0},
e1b74f61
AL
1307 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
1308 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
1309 {'q',"quiet","quiet",CommandLine::IntLevel},
76fbce56 1310 {'i',"important","APT::Cache::Important",0},
7e2e2d5d 1311 {'f',"full","APT::Cache::ShowFull",0},
b2e465d6 1312 {'g',"generate","APT::Cache::Generate",0},
648e3cb4 1313 {'a',"all-versions","APT::Cache::AllVersions",0},
7e2e2d5d 1314 {0,"names-only","APT::Cache::NamesOnly",0},
7c1133fe 1315 {0,"all-names","APT::Cache::AllNames",0},
b2e465d6 1316 {0,"recurse","APT::Cache::RecurseDepends",0},
e1b74f61
AL
1317 {'c',"config-file",0,CommandLine::ConfigFile},
1318 {'o',"option",0,CommandLine::ArbItem},
08e8f724 1319 {0,0,0,0}};
b0b4efb9
AL
1320 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
1321 {"add",&DoAdd},
1322 {"gencaches",&GenCaches},
f8f410f5 1323 {"showsrc",&ShowSrcPackage},
b0b4efb9
AL
1324 {0,0}};
1325 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
1326 {"stats",&Stats},
1327 {"dump",&Dump},
1328 {"dumpavail",&DumpAvail},
1329 {"unmet",&UnMet},
9dbb421f 1330 {"search",&Search},
349cd3b8 1331 {"depends",&Depends},
3e94da1b 1332 {"dotty",&Dotty},
7e2e2d5d 1333 {"show",&ShowPackage},
7c1133fe 1334 {"pkgnames",&ShowPkgNames},
af87ab54 1335 {"policy",&Policy},
b0b4efb9 1336 {0,0}};
0a8e3465
AL
1337
1338 CacheInitialize();
e1b74f61
AL
1339
1340 // Parse the command line and initialize the package library
1341 CommandLine CmdL(Args,_config);
b2e465d6
AL
1342 if (pkgInitConfig(*_config) == false ||
1343 CmdL.Parse(argc,argv) == false ||
1344 pkgInitSystem(*_config,_system) == false)
08e8f724
AL
1345 {
1346 _error->DumpErrors();
1347 return 100;
1164783d 1348 }
8efa2a3b 1349
e1b74f61
AL
1350 // See if the help should be shown
1351 if (_config->FindB("help") == true ||
1352 CmdL.FileSize() == 0)
b2e465d6
AL
1353 {
1354 ShowHelp(CmdL);
1355 return 0;
1356 }
1357
a9a5908d
AL
1358 // Deal with stdout not being a tty
1359 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
1360 _config->Set("quiet","1");
1361
b0b4efb9 1362 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
4b1b89c5
AL
1363 {
1364 MMap *Map;
b2e465d6 1365 if (_config->FindB("APT::Cache::Generate",true) == false)
4b1b89c5
AL
1366 {
1367 Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
1368 FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
1369 }
1370 else
1371 {
1372 // Open the cache file
af87ab54
AL
1373 SrcList = new pkgSourceList;
1374 SrcList->ReadMainList();
f8f410f5 1375
4b1b89c5
AL
1376 // Generate it and map it
1377 OpProgress Prog;
af87ab54 1378 pkgMakeStatusCache(*SrcList,Prog,&Map,true);
4b1b89c5
AL
1379 }
1380
b0b4efb9 1381 if (_error->PendingError() == false)
1164783d 1382 {
b2e465d6 1383 pkgCache Cache(Map);
b0b4efb9
AL
1384 GCache = &Cache;
1385 if (_error->PendingError() == false)
1386 CmdL.DispatchArg(CmdsB);
803fafcb
AL
1387 }
1388 delete Map;
1164783d
AL
1389 }
1390
1391 // Print any errors or warnings found during parsing
1392 if (_error->empty() == false)
1393 {
0a8e3465 1394 bool Errors = _error->PendingError();
1164783d 1395 _error->DumpErrors();
0a8e3465 1396 return Errors == true?100:0;
1164783d
AL
1397 }
1398
1399 return 0;
1400}