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