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