]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
* apt-pkg/pkgcache.cc:
[apt.git] / cmdline / apt-cache.cc
CommitLineData
1164783d
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
ea7f6363 3// $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz 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>
6007c1d4 17#include <cassert>
1164783d 18#include <apt-pkg/pkgcachegen.h>
6007c1d4 19#include <apt-pkg/cachefile.h>
8efa2a3b 20#include <apt-pkg/init.h>
404ec98e 21#include <apt-pkg/progress.h>
880e9be4 22#include <apt-pkg/sourcelist.h>
08e8f724 23#include <apt-pkg/cmndline.h>
cdcc6d34 24#include <apt-pkg/strutl.h>
9dbb421f 25#include <apt-pkg/pkgrecords.h>
f8f410f5 26#include <apt-pkg/srcrecords.h>
3e94da1b 27#include <apt-pkg/version.h>
b2e465d6
AL
28#include <apt-pkg/policy.h>
29#include <apt-pkg/tagfile.h>
30#include <apt-pkg/algorithms.h>
31#include <apt-pkg/sptr.h>
78c32596 32#include <apt-pkg/packageset.h>
b2e465d6 33
43981212 34#include <config.h>
b2e465d6 35#include <apti18n.h>
1164783d 36
233c2b66 37#include <locale.h>
90f057fd 38#include <iostream>
cdb970c7 39#include <unistd.h>
43981212 40#include <errno.h>
9dbb421f 41#include <regex.h>
3e94da1b 42#include <stdio.h>
bd3d53ef
AL
43
44#include <iomanip>
1164783d
AL
45 /*}}}*/
46
8f312f45
AL
47using namespace std;
48
b0b4efb9 49pkgCache *GCache = 0;
af87ab54 50pkgSourceList *SrcList = 0;
b0b4efb9 51
b2e465d6
AL
52// LocalitySort - Sort a version list by package file locality /*{{{*/
53// ---------------------------------------------------------------------
54/* */
55int LocalityCompare(const void *a, const void *b)
56{
57 pkgCache::VerFile *A = *(pkgCache::VerFile **)a;
58 pkgCache::VerFile *B = *(pkgCache::VerFile **)b;
59
60 if (A == 0 && B == 0)
61 return 0;
62 if (A == 0)
63 return 1;
64 if (B == 0)
65 return -1;
66
67 if (A->File == B->File)
68 return A->Offset - B->Offset;
69 return A->File - B->File;
70}
71
72void LocalitySort(pkgCache::VerFile **begin,
73 unsigned long Count,size_t Size)
74{
75 qsort(begin,Count,Size,LocalityCompare);
76}
a52f938b
OS
77
78void LocalitySort(pkgCache::DescFile **begin,
79 unsigned long Count,size_t Size)
80{
81 qsort(begin,Count,Size,LocalityCompare);
82}
b2e465d6 83 /*}}}*/
cc718e9a
AL
84// UnMet - Show unmet dependencies /*{{{*/
85// ---------------------------------------------------------------------
86/* */
b0b4efb9 87bool UnMet(CommandLine &CmdL)
cc718e9a 88{
b0b4efb9 89 pkgCache &Cache = *GCache;
76fbce56 90 bool Important = _config->FindB("APT::Cache::Important",false);
018f1533 91
cc718e9a
AL
92 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
93 {
94 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
95 {
96 bool Header = false;
018f1533 97 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;)
cc718e9a
AL
98 {
99 // Collect or groups
100 pkgCache::DepIterator Start;
101 pkgCache::DepIterator End;
102 D.GlobOr(Start,End);
103
018f1533 104 // Skip conflicts and replaces
cc718e9a
AL
105 if (End->Type != pkgCache::Dep::PreDepends &&
106 End->Type != pkgCache::Dep::Depends &&
107 End->Type != pkgCache::Dep::Suggests &&
7146a53c 108 End->Type != pkgCache::Dep::Recommends)
cc718e9a
AL
109 continue;
110
018f1533
AL
111 // Important deps only
112 if (Important == true)
113 if (End->Type != pkgCache::Dep::PreDepends &&
7146a53c 114 End->Type != pkgCache::Dep::Depends)
018f1533
AL
115 continue;
116
cc718e9a
AL
117 // Verify the or group
118 bool OK = false;
119 pkgCache::DepIterator RealStart = Start;
120 do
121 {
122 // See if this dep is Ok
123 pkgCache::Version **VList = Start.AllTargets();
124 if (*VList != 0)
125 {
126 OK = true;
127 delete [] VList;
128 break;
129 }
130 delete [] VList;
131
132 if (Start == End)
133 break;
134 Start++;
135 }
136 while (1);
137
138 // The group is OK
139 if (OK == true)
140 continue;
141
142 // Oops, it failed..
143 if (Header == false)
b2e465d6 144 ioprintf(cout,_("Package %s version %s has an unmet dep:\n"),
75ce2062 145 P.FullName(true).c_str(),V.VerStr());
cc718e9a
AL
146 Header = true;
147
148 // Print out the dep type
149 cout << " " << End.DepType() << ": ";
150
151 // Show the group
152 Start = RealStart;
153 do
154 {
75ce2062 155 cout << Start.TargetPkg().FullName(true);
cc718e9a
AL
156 if (Start.TargetVer() != 0)
157 cout << " (" << Start.CompType() << " " << Start.TargetVer() <<
158 ")";
159 if (Start == End)
160 break;
161 cout << " | ";
162 Start++;
163 }
164 while (1);
165
166 cout << endl;
167 }
168 }
169 }
170 return true;
171}
172 /*}}}*/
1164783d
AL
173// DumpPackage - Show a dump of a package record /*{{{*/
174// ---------------------------------------------------------------------
175/* */
b0b4efb9 176bool DumpPackage(CommandLine &CmdL)
ad00ae81 177{
b0b4efb9 178 pkgCache &Cache = *GCache;
78c32596 179 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(Cache, CmdL.FileList);
1164783d 180
78c32596
DK
181 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
182 {
75ce2062 183 cout << "Package: " << Pkg.FullName(true) << endl;
b2e465d6 184 cout << "Versions: " << endl;
1164783d 185 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
03e39e59
AL
186 {
187 cout << Cur.VerStr();
188 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
a52f938b
OS
189 cout << " (" << Vf.File().FileName() << ")";
190 cout << endl;
191 for (pkgCache::DescIterator D = Cur.DescriptionList(); D.end() == false; D++)
192 {
193 cout << " Description Language: " << D.LanguageCode() << endl
194 << " File: " << D.FileList().File().FileName() << endl
195 << " MD5: " << D.md5() << endl;
196 }
b2e465d6 197 cout << endl;
03e39e59
AL
198 }
199
1164783d
AL
200 cout << endl;
201
202 cout << "Reverse Depends: " << endl;
203 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
b2e465d6 204 {
75ce2062 205 cout << " " << D.ParentPkg().FullName(true) << ',' << D.TargetPkg().FullName(true);
b2e465d6 206 if (D->Version != 0)
b1b663d1 207 cout << ' ' << DeNull(D.TargetVer()) << endl;
b2e465d6
AL
208 else
209 cout << endl;
210 }
211
1164783d
AL
212 cout << "Dependencies: " << endl;
213 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
214 {
215 cout << Cur.VerStr() << " - ";
216 for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
75ce2062 217 cout << Dep.TargetPkg().FullName(true) << " (" << (int)Dep->CompareOp << " " << DeNull(Dep.TargetVer()) << ") ";
1164783d
AL
218 cout << endl;
219 }
220
221 cout << "Provides: " << endl;
222 for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
223 {
224 cout << Cur.VerStr() << " - ";
225 for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
75ce2062 226 cout << Prv.ParentPkg().FullName(true) << " ";
1164783d 227 cout << endl;
8efa2a3b
AL
228 }
229 cout << "Reverse Provides: " << endl;
230 for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
75ce2062 231 cout << Prv.OwnerPkg().FullName(true) << " " << Prv.OwnerVer().VerStr() << endl;
1164783d
AL
232 }
233
234 return true;
235}
236 /*}}}*/
237// Stats - Dump some nice statistics /*{{{*/
238// ---------------------------------------------------------------------
239/* */
b0b4efb9 240bool Stats(CommandLine &Cmd)
1164783d 241{
b0b4efb9 242 pkgCache &Cache = *GCache;
173ae2a4
DK
243 cout << _("Total package names: ") << Cache.Head().GroupCount << " (" <<
244 SizeToStr(Cache.Head().GroupCount*Cache.Head().GroupSz) << ')' << endl
245 << _("Total package structures: ") << Cache.Head().PackageCount << " (" <<
f826cfaa 246 SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl;
b2e465d6 247
1164783d
AL
248 int Normal = 0;
249 int Virtual = 0;
250 int NVirt = 0;
251 int DVirt = 0;
252 int Missing = 0;
b2e465d6 253 pkgCache::PkgIterator I = Cache.PkgBegin();
1164783d
AL
254 for (;I.end() != true; I++)
255 {
256 if (I->VersionList != 0 && I->ProvidesList == 0)
257 {
258 Normal++;
259 continue;
260 }
261
262 if (I->VersionList != 0 && I->ProvidesList != 0)
263 {
264 NVirt++;
265 continue;
266 }
267
268 if (I->VersionList == 0 && I->ProvidesList != 0)
269 {
270 // Only 1 provides
271 if (I.ProvidesList()->NextProvides == 0)
272 {
273 DVirt++;
274 }
275 else
276 Virtual++;
277 continue;
278 }
279 if (I->VersionList == 0 && I->ProvidesList == 0)
280 {
281 Missing++;
282 continue;
283 }
284 }
db0db9fe
CP
285 cout << _(" Normal packages: ") << Normal << endl;
286 cout << _(" Pure virtual packages: ") << Virtual << endl;
287 cout << _(" Single virtual packages: ") << DVirt << endl;
288 cout << _(" Mixed virtual packages: ") << NVirt << endl;
b2e465d6 289 cout << _(" Missing: ") << Missing << endl;
1164783d 290
db0db9fe 291 cout << _("Total distinct versions: ") << Cache.Head().VersionCount << " (" <<
f826cfaa 292 SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
12bffed7 293 cout << _("Total distinct descriptions: ") << Cache.Head().DescriptionCount << " (" <<
a52f938b 294 SizeToStr(Cache.Head().DescriptionCount*Cache.Head().DescriptionSz) << ')' << endl;
db0db9fe 295 cout << _("Total dependencies: ") << Cache.Head().DependsCount << " (" <<
f826cfaa
AL
296 SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
297
db0db9fe 298 cout << _("Total ver/file relations: ") << Cache.Head().VerFileCount << " (" <<
a7e66b17 299 SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
a52f938b
OS
300 cout << _("Total Desc/File relations: ") << Cache.Head().DescFileCount << " (" <<
301 SizeToStr(Cache.Head().DescFileCount*Cache.Head().DescFileSz) << ')' << endl;
db0db9fe 302 cout << _("Total Provides mappings: ") << Cache.Head().ProvidesCount << " (" <<
a7e66b17 303 SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
f826cfaa
AL
304
305 // String list stats
306 unsigned long Size = 0;
307 unsigned long Count = 0;
308 for (pkgCache::StringItem *I = Cache.StringItemP + Cache.Head().StringList;
309 I!= Cache.StringItemP; I = Cache.StringItemP + I->NextItem)
310 {
311 Count++;
b2e465d6 312 Size += strlen(Cache.StrP + I->String) + 1;
f826cfaa 313 }
db0db9fe 314 cout << _("Total globbed strings: ") << Count << " (" << SizeToStr(Size) << ')' << endl;
b2e465d6
AL
315
316 unsigned long DepVerSize = 0;
317 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
318 {
319 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
320 {
321 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
322 {
323 if (D->Version != 0)
324 DepVerSize += strlen(D.TargetVer()) + 1;
325 }
326 }
327 }
db0db9fe 328 cout << _("Total dependency version space: ") << SizeToStr(DepVerSize) << endl;
b2e465d6 329
f826cfaa
AL
330 unsigned long Slack = 0;
331 for (int I = 0; I != 7; I++)
332 Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count;
db0db9fe 333 cout << _("Total slack space: ") << SizeToStr(Slack) << endl;
f826cfaa
AL
334
335 unsigned long Total = 0;
336 Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz +
337 Cache.Head().VersionCount*Cache.Head().VersionSz +
a7e66b17
AL
338 Cache.Head().PackageCount*Cache.Head().PackageSz +
339 Cache.Head().VerFileCount*Cache.Head().VerFileSz +
340 Cache.Head().ProvidesCount*Cache.Head().ProvidesSz;
db0db9fe 341 cout << _("Total space accounted for: ") << SizeToStr(Total) << endl;
f826cfaa 342
83d89a9f
AL
343 return true;
344}
345 /*}}}*/
1164783d
AL
346// Dump - show everything /*{{{*/
347// ---------------------------------------------------------------------
b2e465d6 348/* This is worthless except fer debugging things */
b0b4efb9 349bool Dump(CommandLine &Cmd)
1164783d 350{
b0b4efb9 351 pkgCache &Cache = *GCache;
b2e465d6
AL
352 cout << "Using Versioning System: " << Cache.VS->Label << endl;
353
1164783d
AL
354 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
355 {
75ce2062 356 cout << "Package: " << P.FullName(true) << endl;
1164783d
AL
357 for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
358 {
359 cout << " Version: " << V.VerStr() << endl;
360 cout << " File: " << V.FileList().File().FileName() << endl;
361 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
75ce2062 362 cout << " Depends: " << D.TargetPkg().FullName(true) << ' ' <<
076d01b0 363 DeNull(D.TargetVer()) << endl;
a52f938b
OS
364 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; D++)
365 {
366 cout << " Description Language: " << D.LanguageCode() << endl
367 << " File: " << D.FileList().File().FileName() << endl
368 << " MD5: " << D.md5() << endl;
369 }
1164783d
AL
370 }
371 }
372
b2e465d6 373 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
1164783d
AL
374 {
375 cout << "File: " << F.FileName() << endl;
b2e465d6 376 cout << " Type: " << F.IndexType() << endl;
1164783d
AL
377 cout << " Size: " << F->Size << endl;
378 cout << " ID: " << F->ID << endl;
379 cout << " Flags: " << F->Flags << endl;
b0b4efb9 380 cout << " Time: " << TimeRFC1123(F->mtime) << endl;
076d01b0
AL
381 cout << " Archive: " << DeNull(F.Archive()) << endl;
382 cout << " Component: " << DeNull(F.Component()) << endl;
383 cout << " Version: " << DeNull(F.Version()) << endl;
384 cout << " Origin: " << DeNull(F.Origin()) << endl;
385 cout << " Site: " << DeNull(F.Site()) << endl;
386 cout << " Label: " << DeNull(F.Label()) << endl;
387 cout << " Architecture: " << DeNull(F.Architecture()) << endl;
1164783d
AL
388 }
389
390 return true;
391}
392 /*}}}*/
393// DumpAvail - Print out the available list /*{{{*/
394// ---------------------------------------------------------------------
b2e465d6
AL
395/* This is needed to make dpkg --merge happy.. I spent a bit of time to
396 make this run really fast, perhaps I went a little overboard.. */
b0b4efb9 397bool DumpAvail(CommandLine &Cmd)
1164783d 398{
b0b4efb9 399 pkgCache &Cache = *GCache;
1164783d 400
b2e465d6 401 pkgPolicy Plcy(&Cache);
e68ca100 402 if (ReadPinFile(Plcy) == false || ReadPinDir(Plcy) == false)
b2e465d6
AL
403 return false;
404
fe648919
AL
405 unsigned long Count = Cache.HeaderP->PackageCount+1;
406 pkgCache::VerFile **VFList = new pkgCache::VerFile *[Count];
407 memset(VFList,0,sizeof(*VFList)*Count);
b2e465d6
AL
408
409 // Map versions that we want to write out onto the VerList array.
410 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
411 {
412 if (P->VersionList == 0)
5b8c90bf
AL
413 continue;
414
b2e465d6
AL
415 /* Find the proper version to use. If the policy says there are no
416 possible selections we return the installed version, if available..
417 This prevents dselect from making it obsolete. */
418 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
419 if (V.end() == true)
ad00ae81 420 {
b2e465d6
AL
421 if (P->CurrentVer == 0)
422 continue;
423 V = P.CurrentVer();
ad00ae81 424 }
1164783d 425
b2e465d6
AL
426 pkgCache::VerFileIterator VF = V.FileList();
427 for (; VF.end() == false ; VF++)
428 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
429 break;
430
431 /* Okay, here we have a bit of a problem.. The policy has selected the
432 currently installed package - however it only exists in the
433 status file.. We need to write out something or dselect will mark
434 the package as obsolete! Thus we emit the status file entry, but
435 below we remove the status line to make it valid for the
436 available file. However! We only do this if their do exist *any*
437 non-source versions of the package - that way the dselect obsolete
438 handling works OK. */
439 if (VF.end() == true)
1164783d 440 {
b2e465d6
AL
441 for (pkgCache::VerIterator Cur = P.VersionList(); Cur.end() != true; Cur++)
442 {
443 for (VF = Cur.FileList(); VF.end() == false; VF++)
444 {
445 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 0)
446 {
447 VF = V.FileList();
448 break;
449 }
450 }
451
452 if (VF.end() == false)
453 break;
454 }
ad00ae81 455 }
b2e465d6
AL
456
457 VFList[P->ID] = VF;
458 }
459
fe648919 460 LocalitySort(VFList,Count,sizeof(*VFList));
ad00ae81 461
b2e465d6
AL
462 // Iterate over all the package files and write them out.
463 char *Buffer = new char[Cache.HeaderP->MaxVerFileSize+10];
464 for (pkgCache::VerFile **J = VFList; *J != 0;)
465 {
466 pkgCache::PkgFileIterator File(Cache,(*J)->File + Cache.PkgFileP);
467 if (File.IsOk() == false)
ad00ae81 468 {
b2e465d6
AL
469 _error->Error(_("Package file %s is out of sync."),File.FileName());
470 break;
471 }
bd432be3 472
b2e465d6
AL
473 FileFd PkgF(File.FileName(),FileFd::ReadOnly);
474 if (_error->PendingError() == true)
475 break;
476
477 /* Write all of the records from this package file, since we
478 already did locality sorting we can now just seek through the
479 file in read order. We apply 1 more optimization here, since often
480 there will be < 1 byte gaps between records (for the \n) we read that
481 into the next buffer and offset a bit.. */
482 unsigned long Pos = 0;
483 for (; *J != 0; J++)
484 {
485 if ((*J)->File + Cache.PkgFileP != File)
486 break;
bd432be3 487
b2e465d6
AL
488 const pkgCache::VerFile &VF = **J;
489
bd432be3 490 // Read the record and then write it out again.
b2e465d6
AL
491 unsigned long Jitter = VF.Offset - Pos;
492 if (Jitter > 8)
1164783d 493 {
b2e465d6
AL
494 if (PkgF.Seek(VF.Offset) == false)
495 break;
496 Jitter = 0;
497 }
498
499 if (PkgF.Read(Buffer,VF.Size + Jitter) == false)
500 break;
501 Buffer[VF.Size + Jitter] = '\n';
502
503 // See above..
504 if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource)
505 {
506 pkgTagSection Tags;
e8cbb49f 507 TFRewriteData RW[] = {{"Status",0},{"Config-Version",0},{}};
b2e465d6
AL
508 const char *Zero = 0;
509 if (Tags.Scan(Buffer+Jitter,VF.Size+1) == false ||
510 TFRewrite(stdout,Tags,&Zero,RW) == false)
511 {
512 _error->Error("Internal Error, Unable to parse a package record");
513 break;
514 }
515 fputc('\n',stdout);
516 }
517 else
518 {
519 if (fwrite(Buffer+Jitter,VF.Size+1,1,stdout) != 1)
520 break;
521 }
522
523 Pos = VF.Offset + VF.Size;
1164783d 524 }
b2e465d6
AL
525
526 fflush(stdout);
527 if (_error->PendingError() == true)
528 break;
ad00ae81
AL
529 }
530
b2e465d6
AL
531 delete [] Buffer;
532 delete [] VFList;
533 return !_error->PendingError();
349cd3b8
AL
534}
535 /*}}}*/
4b1b89c5 536// Depends - Print out a dependency tree /*{{{*/
349cd3b8
AL
537// ---------------------------------------------------------------------
538/* */
539bool Depends(CommandLine &CmdL)
540{
541 pkgCache &Cache = *GCache;
b2e465d6
AL
542 SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
543 memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
78c32596
DK
544
545 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(Cache, CmdL.FileList);
546 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
b2e465d6 547 Colours[Pkg->ID] = 1;
78c32596 548
b2e465d6 549 bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
eba2b51d 550 bool Installed = _config->FindB("APT::Cache::Installed",false);
5aa95c86 551 bool Important = _config->FindB("APT::Cache::Important",false);
b2e465d6
AL
552 bool DidSomething;
553 do
554 {
555 DidSomething = false;
556 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
349cd3b8 557 {
b2e465d6
AL
558 if (Colours[Pkg->ID] != 1)
559 continue;
560 Colours[Pkg->ID] = 2;
561 DidSomething = true;
349cd3b8 562
b2e465d6
AL
563 pkgCache::VerIterator Ver = Pkg.VersionList();
564 if (Ver.end() == true)
349cd3b8 565 {
75ce2062 566 cout << '<' << Pkg.FullName(true) << '>' << endl;
b2e465d6 567 continue;
349cd3b8 568 }
b2e465d6 569
75ce2062 570 cout << Pkg.FullName(true) << endl;
b2e465d6
AL
571
572 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
573 {
5aa95c86
MV
574 // Important deps only
575 if (Important == true)
576 if (D->Type != pkgCache::Dep::PreDepends &&
577 D->Type != pkgCache::Dep::Depends)
578 continue;
579
b2e465d6 580 pkgCache::PkgIterator Trg = D.TargetPkg();
eba2b51d
AL
581
582 if((Installed && Trg->CurrentVer != 0) || !Installed)
583 {
584
585 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
586 cout << " |";
587 else
588 cout << " ";
b2e465d6 589
eba2b51d
AL
590 // Show the package
591 if (Trg->VersionList == 0)
75ce2062 592 cout << D.DepType() << ": <" << Trg.FullName(true) << ">" << endl;
eba2b51d 593 else
75ce2062 594 cout << D.DepType() << ": " << Trg.FullName(true) << endl;
eba2b51d
AL
595
596 if (Recurse == true)
597 Colours[D.TargetPkg()->ID]++;
598
599 }
b2e465d6
AL
600
601 // Display all solutions
602 SPtrArray<pkgCache::Version *> List = D.AllTargets();
603 pkgPrioSortList(Cache,List);
604 for (pkgCache::Version **I = List; *I != 0; I++)
605 {
606 pkgCache::VerIterator V(Cache,*I);
607 if (V != Cache.VerP + V.ParentPkg()->VersionList ||
608 V->ParentPkg == D->Package)
609 continue;
75ce2062 610 cout << " " << V.ParentPkg().FullName(true) << endl;
b2e465d6
AL
611
612 if (Recurse == true)
613 Colours[D.ParentPkg()->ID]++;
614 }
615 }
616 }
349cd3b8 617 }
b2e465d6 618 while (DidSomething == true);
349cd3b8 619
3e94da1b
AL
620 return true;
621}
92fcbfc1 622 /*}}}*/
eba2b51d
AL
623// RDepends - Print out a reverse dependency tree - mbc /*{{{*/
624// ---------------------------------------------------------------------
625/* */
626bool RDepends(CommandLine &CmdL)
627{
628 pkgCache &Cache = *GCache;
629 SPtrArray<unsigned> Colours = new unsigned[Cache.Head().PackageCount];
630 memset(Colours,0,sizeof(*Colours)*Cache.Head().PackageCount);
78c32596
DK
631
632 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(Cache, CmdL.FileList);
633 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
eba2b51d 634 Colours[Pkg->ID] = 1;
78c32596 635
eba2b51d
AL
636 bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
637 bool Installed = _config->FindB("APT::Cache::Installed",false);
638 bool DidSomething;
639 do
640 {
641 DidSomething = false;
642 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
643 {
644 if (Colours[Pkg->ID] != 1)
645 continue;
646 Colours[Pkg->ID] = 2;
647 DidSomething = true;
648
649 pkgCache::VerIterator Ver = Pkg.VersionList();
650 if (Ver.end() == true)
651 {
75ce2062 652 cout << '<' << Pkg.FullName(true) << '>' << endl;
eba2b51d
AL
653 continue;
654 }
655
75ce2062 656 cout << Pkg.FullName(true) << endl;
eba2b51d
AL
657
658 cout << "Reverse Depends:" << endl;
659 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() == false; D++)
660 {
661 // Show the package
662 pkgCache::PkgIterator Trg = D.ParentPkg();
663
664 if((Installed && Trg->CurrentVer != 0) || !Installed)
665 {
666
667 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
668 cout << " |";
669 else
670 cout << " ";
671
672 if (Trg->VersionList == 0)
75ce2062 673 cout << D.DepType() << ": <" << Trg.FullName(true) << ">" << endl;
eba2b51d 674 else
75ce2062 675 cout << Trg.FullName(true) << endl;
eba2b51d
AL
676
677 if (Recurse == true)
678 Colours[D.ParentPkg()->ID]++;
679
680 }
681
682 // Display all solutions
683 SPtrArray<pkgCache::Version *> List = D.AllTargets();
684 pkgPrioSortList(Cache,List);
685 for (pkgCache::Version **I = List; *I != 0; I++)
686 {
687 pkgCache::VerIterator V(Cache,*I);
688 if (V != Cache.VerP + V.ParentPkg()->VersionList ||
689 V->ParentPkg == D->Package)
690 continue;
75ce2062 691 cout << " " << V.ParentPkg().FullName(true) << endl;
eba2b51d
AL
692
693 if (Recurse == true)
694 Colours[D.ParentPkg()->ID]++;
695 }
696 }
697 }
698 }
699 while (DidSomething == true);
700
701 return true;
702}
3e94da1b 703 /*}}}*/
fff4b7f3
AL
704// xvcg - Generate a graph for xvcg /*{{{*/
705// ---------------------------------------------------------------------
706// Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
707
708bool XVcg(CommandLine &CmdL)
709{
710 pkgCache &Cache = *GCache;
711 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
712
713 /* Normal packages are boxes
714 Pure Provides are triangles
715 Mixed are diamonds
716 rhomb are missing packages*/
717 const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
718
719 /* Initialize the list of packages to show.
720 1 = To Show
721 2 = To Show no recurse
722 3 = Emitted no recurse
723 4 = Emitted
724 0 = None */
725 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
726 enum TheFlags {ForceNR=(1<<0)};
727 unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
728 unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
729 unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
730
731 // Show everything if no arguments given
732 if (CmdL.FileList[1] == 0)
733 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
734 Show[I] = ToShow;
735 else
736 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
737 Show[I] = None;
738 memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
739
740 // Map the shapes
741 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
742 {
743 if (Pkg->VersionList == 0)
744 {
745 // Missing
746 if (Pkg->ProvidesList == 0)
747 ShapeMap[Pkg->ID] = 0;
748 else
749 ShapeMap[Pkg->ID] = 1;
750 }
751 else
752 {
753 // Normal
754 if (Pkg->ProvidesList == 0)
755 ShapeMap[Pkg->ID] = 2;
756 else
757 ShapeMap[Pkg->ID] = 3;
758 }
759 }
760
761 // Load the list of packages from the command line into the show list
762 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
763 {
764 // Process per-package flags
765 string P = *I;
766 bool Force = false;
767 if (P.length() > 3)
768 {
769 if (P.end()[-1] == '^')
770 {
771 Force = true;
772 P.erase(P.end()-1);
773 }
774
775 if (P.end()[-1] == ',')
776 P.erase(P.end()-1);
777 }
778
779 // Locate the package
780 pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
781 if (Pkg.end() == true)
782 {
783 _error->Warning(_("Unable to locate package %s"),*I);
784 continue;
785 }
786 Show[Pkg->ID] = ToShow;
787
788 if (Force == true)
789 Flags[Pkg->ID] |= ForceNR;
790 }
791
792 // Little header
793 cout << "graph: { title: \"packages\"" << endl <<
794 "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
795 "layout_downfactor: 8" << endl;
796
797 bool Act = true;
798 while (Act == true)
799 {
800 Act = false;
801 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
802 {
803 // See we need to show this package
804 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
805 continue;
806
807 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
808
809 // Colour as done
810 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
811 {
812 // Pure Provides and missing packages have no deps!
813 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
814 Show[Pkg->ID] = Done;
815 else
816 Show[Pkg->ID] = DoneNR;
817 }
818 else
819 Show[Pkg->ID] = Done;
820 Act = true;
821
822 // No deps to map out
823 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
824 continue;
825
826 pkgCache::VerIterator Ver = Pkg.VersionList();
827 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
828 {
829 // See if anything can meet this dep
830 // Walk along the actual package providing versions
831 bool Hit = false;
832 pkgCache::PkgIterator DPkg = D.TargetPkg();
833 for (pkgCache::VerIterator I = DPkg.VersionList();
834 I.end() == false && Hit == false; I++)
835 {
836 if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
837 Hit = true;
838 }
839
840 // Follow all provides
841 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
842 I.end() == false && Hit == false; I++)
843 {
844 if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
845 Hit = true;
846 }
847
848
849 // Only graph critical deps
850 if (D.IsCritical() == true)
851 {
75ce2062 852 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.FullName(true).c_str(), D.TargetPkg().FullName(true).c_str() );
fff4b7f3
AL
853
854 // Colour the node for recursion
855 if (Show[D.TargetPkg()->ID] <= DoneNR)
856 {
857 /* If a conflicts does not meet anything in the database
858 then show the relation but do not recurse */
859 if (Hit == false &&
860 (D->Type == pkgCache::Dep::Conflicts ||
308c7d30 861 D->Type == pkgCache::Dep::DpkgBreaks ||
fff4b7f3
AL
862 D->Type == pkgCache::Dep::Obsoletes))
863 {
864 if (Show[D.TargetPkg()->ID] == None &&
865 Show[D.TargetPkg()->ID] != ToShow)
866 Show[D.TargetPkg()->ID] = ToShowNR;
867 }
868 else
869 {
870 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
871 Show[D.TargetPkg()->ID] = ToShowNR;
872 else
873 Show[D.TargetPkg()->ID] = ToShow;
874 }
875 }
876
877 // Edge colour
878 switch(D->Type)
879 {
880 case pkgCache::Dep::Conflicts:
881 printf("label: \"conflicts\" color: lightgreen }\n");
882 break;
308c7d30
IJ
883 case pkgCache::Dep::DpkgBreaks:
884 printf("label: \"breaks\" color: lightgreen }\n");
885 break;
fff4b7f3
AL
886 case pkgCache::Dep::Obsoletes:
887 printf("label: \"obsoletes\" color: lightgreen }\n");
888 break;
889
890 case pkgCache::Dep::PreDepends:
891 printf("label: \"predepends\" color: blue }\n");
892 break;
893
894 default:
895 printf("}\n");
896 break;
897 }
898 }
899 }
900 }
901 }
902
903 /* Draw the box colours after the fact since we can not tell what colour
904 they should be until everything is finished drawing */
905 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
906 {
907 if (Show[Pkg->ID] < DoneNR)
908 continue;
909
910 if (Show[Pkg->ID] == DoneNR)
75ce2062 911 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
fff4b7f3
AL
912 Shapes[ShapeMap[Pkg->ID]]);
913 else
75ce2062 914 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
fff4b7f3
AL
915 Shapes[ShapeMap[Pkg->ID]]);
916
917 }
03496041
DK
918
919 delete[] Show;
920 delete[] Flags;
921 delete[] ShapeMap;
922
fff4b7f3
AL
923 printf("}\n");
924 return true;
925}
926 /*}}}*/
3e94da1b
AL
927// Dotty - Generate a graph for Dotty /*{{{*/
928// ---------------------------------------------------------------------
929/* Dotty is the graphvis program for generating graphs. It is a fairly
930 simple queuing algorithm that just writes dependencies and nodes.
931 http://www.research.att.com/sw/tools/graphviz/ */
932bool Dotty(CommandLine &CmdL)
933{
934 pkgCache &Cache = *GCache;
935 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
936
937 /* Normal packages are boxes
938 Pure Provides are triangles
939 Mixed are diamonds
940 Hexagons are missing packages*/
941 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
942
943 /* Initialize the list of packages to show.
944 1 = To Show
945 2 = To Show no recurse
946 3 = Emitted no recurse
947 4 = Emitted
948 0 = None */
949 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
950 enum TheFlags {ForceNR=(1<<0)};
951 unsigned char *Show = new unsigned char[Cache.Head().PackageCount];
952 unsigned char *Flags = new unsigned char[Cache.Head().PackageCount];
953 unsigned char *ShapeMap = new unsigned char[Cache.Head().PackageCount];
954
955 // Show everything if no arguments given
956 if (CmdL.FileList[1] == 0)
957 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
958 Show[I] = ToShow;
959 else
960 for (unsigned long I = 0; I != Cache.Head().PackageCount; I++)
961 Show[I] = None;
962 memset(Flags,0,sizeof(*Flags)*Cache.Head().PackageCount);
963
964 // Map the shapes
965 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
966 {
967 if (Pkg->VersionList == 0)
968 {
969 // Missing
970 if (Pkg->ProvidesList == 0)
971 ShapeMap[Pkg->ID] = 0;
972 else
973 ShapeMap[Pkg->ID] = 1;
974 }
975 else
976 {
977 // Normal
978 if (Pkg->ProvidesList == 0)
979 ShapeMap[Pkg->ID] = 2;
980 else
981 ShapeMap[Pkg->ID] = 3;
982 }
983 }
984
985 // Load the list of packages from the command line into the show list
986 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
987 {
988 // Process per-package flags
989 string P = *I;
990 bool Force = false;
991 if (P.length() > 3)
992 {
993 if (P.end()[-1] == '^')
994 {
995 Force = true;
996 P.erase(P.end()-1);
997 }
998
999 if (P.end()[-1] == ',')
1000 P.erase(P.end()-1);
1001 }
1002
1003 // Locate the package
1004 pkgCache::PkgIterator Pkg = Cache.FindPkg(P);
1005 if (Pkg.end() == true)
1006 {
b2e465d6 1007 _error->Warning(_("Unable to locate package %s"),*I);
3e94da1b
AL
1008 continue;
1009 }
1010 Show[Pkg->ID] = ToShow;
1011
1012 if (Force == true)
1013 Flags[Pkg->ID] |= ForceNR;
1014 }
1015
1016 // Little header
1017 printf("digraph packages {\n");
1018 printf("concentrate=true;\n");
1019 printf("size=\"30,40\";\n");
1020
1021 bool Act = true;
1022 while (Act == true)
1023 {
1024 Act = false;
1025 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
1026 {
1027 // See we need to show this package
1028 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
1029 continue;
1030
1031 // Colour as done
1032 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
1033 {
1034 // Pure Provides and missing packages have no deps!
1035 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
1036 Show[Pkg->ID] = Done;
1037 else
1038 Show[Pkg->ID] = DoneNR;
1039 }
1040 else
1041 Show[Pkg->ID] = Done;
1042 Act = true;
1043
1044 // No deps to map out
1045 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
1046 continue;
1047
1048 pkgCache::VerIterator Ver = Pkg.VersionList();
1049 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
1050 {
1051 // See if anything can meet this dep
1052 // Walk along the actual package providing versions
1053 bool Hit = false;
1054 pkgCache::PkgIterator DPkg = D.TargetPkg();
1055 for (pkgCache::VerIterator I = DPkg.VersionList();
1056 I.end() == false && Hit == false; I++)
1057 {
b2e465d6 1058 if (Cache.VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
3e94da1b
AL
1059 Hit = true;
1060 }
1061
1062 // Follow all provides
1063 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
1064 I.end() == false && Hit == false; I++)
1065 {
b2e465d6 1066 if (Cache.VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
3e94da1b
AL
1067 Hit = true;
1068 }
1069
1070 // Only graph critical deps
1071 if (D.IsCritical() == true)
1072 {
75ce2062 1073 printf("\"%s\" -> \"%s\"",Pkg.FullName(true).c_str(),D.TargetPkg().FullName(true).c_str());
3e94da1b
AL
1074
1075 // Colour the node for recursion
1076 if (Show[D.TargetPkg()->ID] <= DoneNR)
1077 {
1078 /* If a conflicts does not meet anything in the database
1079 then show the relation but do not recurse */
b2e465d6
AL
1080 if (Hit == false &&
1081 (D->Type == pkgCache::Dep::Conflicts ||
1082 D->Type == pkgCache::Dep::Obsoletes))
3e94da1b
AL
1083 {
1084 if (Show[D.TargetPkg()->ID] == None &&
1085 Show[D.TargetPkg()->ID] != ToShow)
1086 Show[D.TargetPkg()->ID] = ToShowNR;
1087 }
1088 else
1089 {
1090 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
1091 Show[D.TargetPkg()->ID] = ToShowNR;
1092 else
1093 Show[D.TargetPkg()->ID] = ToShow;
1094 }
1095 }
1096
1097 // Edge colour
1098 switch(D->Type)
1099 {
1100 case pkgCache::Dep::Conflicts:
b2e465d6 1101 case pkgCache::Dep::Obsoletes:
3e94da1b
AL
1102 printf("[color=springgreen];\n");
1103 break;
1104
1105 case pkgCache::Dep::PreDepends:
1106 printf("[color=blue];\n");
1107 break;
1108
1109 default:
1110 printf(";\n");
1111 break;
1112 }
1113 }
1114 }
1115 }
1116 }
1117
1118 /* Draw the box colours after the fact since we can not tell what colour
1119 they should be until everything is finished drawing */
1120 for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
1121 {
1122 if (Show[Pkg->ID] < DoneNR)
1123 continue;
1124
1125 // Orange box for early recursion stoppage
1126 if (Show[Pkg->ID] == DoneNR)
75ce2062 1127 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.FullName(true).c_str(),
3e94da1b
AL
1128 Shapes[ShapeMap[Pkg->ID]]);
1129 else
75ce2062 1130 printf("\"%s\" [shape=%s];\n",Pkg.FullName(true).c_str(),
3e94da1b
AL
1131 Shapes[ShapeMap[Pkg->ID]]);
1132 }
1133
1134 printf("}\n");
ad00ae81
AL
1135 return true;
1136}
1137 /*}}}*/
1138// DoAdd - Perform an adding operation /*{{{*/
1139// ---------------------------------------------------------------------
1140/* */
e1b74f61 1141bool DoAdd(CommandLine &CmdL)
ad00ae81 1142{
b2e465d6
AL
1143 return _error->Error("Unimplemented");
1144#if 0
e1b74f61
AL
1145 // Make sure there is at least one argument
1146 if (CmdL.FileSize() <= 1)
1147 return _error->Error("You must give at least one file name");
ad00ae81
AL
1148
1149 // Open the cache
018f1533 1150 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
ad00ae81
AL
1151 if (_error->PendingError() == true)
1152 return false;
1153
1154 DynamicMMap Map(CacheF,MMap::Public);
1155 if (_error->PendingError() == true)
1156 return false;
404ec98e 1157
0a8e3465 1158 OpTextProgress Progress(*_config);
404ec98e 1159 pkgCacheGenerator Gen(Map,Progress);
ad00ae81
AL
1160 if (_error->PendingError() == true)
1161 return false;
1162
e1b74f61
AL
1163 unsigned long Length = CmdL.FileSize() - 1;
1164 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
ad00ae81 1165 {
e1b74f61 1166 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
018f1533
AL
1167 Progress.SubProgress(Length);
1168
ad00ae81 1169 // Do the merge
e1b74f61 1170 FileFd TagF(*I,FileFd::ReadOnly);
ad00ae81
AL
1171 debListParser Parser(TagF);
1172 if (_error->PendingError() == true)
e1b74f61 1173 return _error->Error("Problem opening %s",*I);
ad00ae81 1174
b2e465d6 1175 if (Gen.SelectFile(*I,"") == false)
ad00ae81
AL
1176 return _error->Error("Problem with SelectFile");
1177
1178 if (Gen.MergeList(Parser) == false)
1179 return _error->Error("Problem with MergeList");
1164783d 1180 }
404ec98e
AL
1181
1182 Progress.Done();
b0b4efb9
AL
1183 GCache = &Gen.GetCache();
1184 Stats(CmdL);
ad00ae81 1185
7e2e2d5d 1186 return true;
b2e465d6 1187#endif
7e2e2d5d
AL
1188}
1189 /*}}}*/
1190// DisplayRecord - Displays the complete record for the package /*{{{*/
1191// ---------------------------------------------------------------------
1192/* This displays the package record from the proper package index file.
1193 It is not used by DumpAvail for performance reasons. */
1194bool DisplayRecord(pkgCache::VerIterator V)
1195{
1196 // Find an appropriate file
1197 pkgCache::VerFileIterator Vf = V.FileList();
1198 for (; Vf.end() == false; Vf++)
1199 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
1200 break;
1201 if (Vf.end() == true)
1202 Vf = V.FileList();
1203
1204 // Check and load the package list file
1205 pkgCache::PkgFileIterator I = Vf.File();
1206 if (I.IsOk() == false)
b2e465d6 1207 return _error->Error(_("Package file %s is out of sync."),I.FileName());
7e2e2d5d
AL
1208
1209 FileFd PkgF(I.FileName(),FileFd::ReadOnly);
1210 if (_error->PendingError() == true)
1211 return false;
1212
a52f938b 1213 // Read the record
b2e465d6
AL
1214 unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
1215 Buffer[V.FileList()->Size] = '\n';
7e2e2d5d 1216 if (PkgF.Seek(V.FileList()->Offset) == false ||
a52f938b 1217 PkgF.Read(Buffer,V.FileList()->Size) == false)
7e2e2d5d
AL
1218 {
1219 delete [] Buffer;
1220 return false;
1221 }
a52f938b 1222
e5e2d176 1223 // Get a pointer to start of Description field
e011829d 1224 const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "Description:");
e5e2d176
MV
1225
1226 // Write all but Description
487d7faa 1227 if (fwrite(Buffer,1,DescP - Buffer,stdout) < (size_t)(DescP - Buffer))
a52f938b
OS
1228 {
1229 delete [] Buffer;
1230 return false;
1231 }
1232
a52f938b
OS
1233 // Show the right description
1234 pkgRecords Recs(*GCache);
012b102a 1235 pkgCache::DescIterator Desc = V.TranslatedDescription();
a52f938b 1236 pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
e011829d 1237 cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
a52f938b 1238
e011829d
MV
1239 // Find the first field after the description (if there is any)
1240 for(DescP++;DescP != &Buffer[V.FileList()->Size];DescP++)
1241 {
1242 if(*DescP == '\n' && *(DescP+1) != ' ')
1243 {
1244 // write the rest of the buffer
1245 const unsigned char *end=&Buffer[V.FileList()->Size];
1246 if (fwrite(DescP,1,end-DescP,stdout) < (size_t)(end-DescP))
1247 {
1248 delete [] Buffer;
1249 return false;
1250 }
1251
1252 break;
1253 }
1254 }
1255 // write a final newline (after the description)
1256 cout<<endl;
7e2e2d5d
AL
1257 delete [] Buffer;
1258
9dbb421f
AL
1259 return true;
1260}
1261 /*}}}*/
92fcbfc1 1262
a52f938b 1263struct ExDescFile
b2e465d6 1264{
a52f938b 1265 pkgCache::DescFile *Df;
b2e465d6
AL
1266 bool NameMatch;
1267};
1268
92fcbfc1
DK
1269// Search - Perform a search /*{{{*/
1270// ---------------------------------------------------------------------
1271/* This searches the package names and package descriptions for a pattern */
9dbb421f
AL
1272bool Search(CommandLine &CmdL)
1273{
1274 pkgCache &Cache = *GCache;
7e2e2d5d
AL
1275 bool ShowFull = _config->FindB("APT::Cache::ShowFull",false);
1276 bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
b2e465d6
AL
1277 unsigned NumPatterns = CmdL.FileSize() -1;
1278
1279 pkgDepCache::Policy Plcy;
9dbb421f
AL
1280
1281 // Make sure there is at least one argument
b2e465d6
AL
1282 if (NumPatterns < 1)
1283 return _error->Error(_("You must give exactly one pattern"));
9dbb421f
AL
1284
1285 // Compile the regex pattern
b2e465d6
AL
1286 regex_t *Patterns = new regex_t[NumPatterns];
1287 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
1288 for (unsigned I = 0; I != NumPatterns; I++)
1289 {
1290 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
1291 REG_NOSUB) != 0)
1292 {
1293 for (; I != 0; I--)
1294 regfree(&Patterns[I]);
1295 return _error->Error("Regex compilation error");
1296 }
1297 }
9dbb421f
AL
1298
1299 // Create the text record parser
1300 pkgRecords Recs(Cache);
1301 if (_error->PendingError() == true)
b2e465d6
AL
1302 {
1303 for (unsigned I = 0; I != NumPatterns; I++)
1304 regfree(&Patterns[I]);
9dbb421f 1305 return false;
b2e465d6 1306 }
9dbb421f 1307
a52f938b
OS
1308 ExDescFile *DFList = new ExDescFile[Cache.HeaderP->PackageCount+1];
1309 memset(DFList,0,sizeof(*DFList)*Cache.HeaderP->PackageCount+1);
b2e465d6
AL
1310
1311 // Map versions that we want to write out onto the VerList array.
1312 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
9dbb421f 1313 {
a52f938b 1314 DFList[P->ID].NameMatch = NumPatterns != 0;
b2e465d6
AL
1315 for (unsigned I = 0; I != NumPatterns; I++)
1316 {
1317 if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
a52f938b 1318 DFList[P->ID].NameMatch &= true;
0f2fa322 1319 else
a52f938b 1320 DFList[P->ID].NameMatch = false;
b2e465d6 1321 }
c29652b0 1322
b2e465d6 1323 // Doing names only, drop any that dont match..
a52f938b 1324 if (NamesOnly == true && DFList[P->ID].NameMatch == false)
b2e465d6
AL
1325 continue;
1326
1327 // Find the proper version to use.
1328 pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
c29652b0 1329 if (V.end() == false)
a52f938b 1330 DFList[P->ID].Df = V.DescriptionList().FileList();
c29652b0
AL
1331 }
1332
1333 // Include all the packages that provide matching names too
1334 for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
1335 {
a52f938b 1336 if (DFList[P->ID].NameMatch == false)
7e2e2d5d 1337 continue;
c29652b0
AL
1338
1339 for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
1340 {
1341 pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
1342 if (V.end() == false)
1343 {
a52f938b
OS
1344 DFList[Prv.OwnerPkg()->ID].Df = V.DescriptionList().FileList();
1345 DFList[Prv.OwnerPkg()->ID].NameMatch = true;
c29652b0
AL
1346 }
1347 }
b2e465d6 1348 }
a52f938b
OS
1349
1350 LocalitySort(&DFList->Df,Cache.HeaderP->PackageCount,sizeof(*DFList));
7e2e2d5d 1351
b2e465d6 1352 // Iterate over all the version records and check them
a52f938b 1353 for (ExDescFile *J = DFList; J->Df != 0; J++)
b2e465d6 1354 {
a52f938b 1355 pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(Cache,J->Df));
0f2fa322
AL
1356
1357 bool Match = true;
1358 if (J->NameMatch == false)
1359 {
1360 string LongDesc = P.LongDesc();
1361 Match = NumPatterns != 0;
1362 for (unsigned I = 0; I != NumPatterns; I++)
1363 {
1364 if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
1365 Match &= true;
1366 else
1367 Match = false;
1368 }
1369 }
b2e465d6
AL
1370
1371 if (Match == true)
9dbb421f 1372 {
7e2e2d5d 1373 if (ShowFull == true)
b2e465d6
AL
1374 {
1375 const char *Start;
1376 const char *End;
1377 P.GetRec(Start,End);
1378 fwrite(Start,End-Start,1,stdout);
1379 putc('\n',stdout);
1380 }
7e2e2d5d 1381 else
b2e465d6
AL
1382 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
1383 }
9dbb421f
AL
1384 }
1385
a52f938b 1386 delete [] DFList;
b2e465d6
AL
1387 for (unsigned I = 0; I != NumPatterns; I++)
1388 regfree(&Patterns[I]);
1389 if (ferror(stdout))
1390 return _error->Error("Write to stdout failed");
1164783d
AL
1391 return true;
1392}
6007c1d4
JAK
1393
1394
1395/* show automatically installed packages (sorted) */
1396bool ShowAuto(CommandLine &CmdL)
1397{
1398 OpProgress op;
1399 pkgDepCache DepCache(GCache);
1400 DepCache.Init(&op);
1401
1402 std::vector<string> packages;
1403 packages.reserve(GCache->HeaderP->PackageCount / 3);
1404
1405 for (pkgCache::PkgIterator P = GCache->PkgBegin(); P.end() == false; P++)
1406 if (DepCache[P].Flags & pkgCache::Flag::Auto)
1407 packages.push_back(P.Name());
1408
1409 std::sort(packages.begin(), packages.end());
1410
1411 for (vector<string>::iterator I = packages.begin(); I != packages.end(); I++)
1412 cout << *I << "\n";
1413
1414 return true;
1415}
1164783d 1416 /*}}}*/
7e2e2d5d
AL
1417// ShowPackage - Dump the package record to the screen /*{{{*/
1418// ---------------------------------------------------------------------
1419/* */
1420bool ShowPackage(CommandLine &CmdL)
1421{
1422 pkgCache &Cache = *GCache;
b2e465d6 1423 pkgDepCache::Policy Plcy;
9d366c89 1424
78c32596
DK
1425 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(Cache, CmdL.FileList);
1426 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
7e2e2d5d 1427 {
b2e465d6 1428 // Find the proper version to use.
648e3cb4
AL
1429 if (_config->FindB("APT::Cache::AllVersions","true") == true)
1430 {
1431 pkgCache::VerIterator V;
1432 for (V = Pkg.VersionList(); V.end() == false; V++)
1433 {
1434 if (DisplayRecord(V) == false)
1435 return false;
1436 }
1437 }
1438 else
1439 {
b2e465d6 1440 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
648e3cb4
AL
1441 if (V.end() == true || V.FileList().end() == true)
1442 continue;
1443 if (DisplayRecord(V) == false)
1444 return false;
1445 }
7e2e2d5d 1446 }
9d366c89 1447
78c32596 1448 if (pkgset.empty() == false)
9d366c89
AL
1449 return true;
1450 return _error->Error(_("No packages found"));
7c1133fe
AL
1451}
1452 /*}}}*/
1453// ShowPkgNames - Show package names /*{{{*/
1454// ---------------------------------------------------------------------
1455/* This does a prefix match on the first argument */
1456bool ShowPkgNames(CommandLine &CmdL)
1457{
1458 pkgCache &Cache = *GCache;
6293e04f
DK
1459 pkgCache::GrpIterator I = Cache.GrpBegin();
1460 bool const All = _config->FindB("APT::Cache::AllNames","false");
1461
7c1133fe
AL
1462 if (CmdL.FileList[1] != 0)
1463 {
1464 for (;I.end() != true; I++)
1465 {
6293e04f
DK
1466 if (All == false && I->FirstPackage == 0)
1467 continue;
1468 if (I.FindPkg("any")->VersionList == 0)
7c1133fe 1469 continue;
7c1133fe
AL
1470 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1471 cout << I.Name() << endl;
1472 }
1473
1474 return true;
1475 }
1476
1477 // Show all pkgs
1478 for (;I.end() != true; I++)
1479 {
6293e04f
DK
1480 if (All == false && I->FirstPackage == 0)
1481 continue;
1482 if (I.FindPkg("any")->VersionList == 0)
7c1133fe
AL
1483 continue;
1484 cout << I.Name() << endl;
1485 }
1486
7e2e2d5d
AL
1487 return true;
1488}
1489 /*}}}*/
f8f410f5
AL
1490// ShowSrcPackage - Show source package records /*{{{*/
1491// ---------------------------------------------------------------------
1492/* */
1493bool ShowSrcPackage(CommandLine &CmdL)
1494{
1495 pkgSourceList List;
1496 List.ReadMainList();
1497
1498 // Create the text record parsers
1499 pkgSrcRecords SrcRecs(List);
1500 if (_error->PendingError() == true)
1501 return false;
1502
0458a811 1503 unsigned found = 0;
f8f410f5
AL
1504 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1505 {
aaee8293
AL
1506 SrcRecs.Restart();
1507
f8f410f5 1508 pkgSrcRecords::Parser *Parse;
0458a811
JAK
1509 unsigned found_this = 0;
1510 while ((Parse = SrcRecs.Find(*I,false)) != 0) {
1511 cout << Parse->AsStr() << endl;;
1512 found++;
1513 found_this++;
1514 }
1515 if (found_this == 0) {
1516 _error->Warning(_("Unable to locate package %s"),*I);
1517 continue;
1518 }
f8f410f5 1519 }
0458a811
JAK
1520 if (found > 0)
1521 return true;
1522 return _error->Error(_("No packages found"));
af87ab54
AL
1523}
1524 /*}}}*/
1525// Policy - Show the results of the preferences file /*{{{*/
1526// ---------------------------------------------------------------------
1527/* */
1528bool Policy(CommandLine &CmdL)
1529{
1530 if (SrcList == 0)
1531 return _error->Error("Generate must be enabled for this function");
1532
1533 pkgCache &Cache = *GCache;
1534 pkgPolicy Plcy(&Cache);
e68ca100 1535 if (ReadPinFile(Plcy) == false || ReadPinDir(Plcy) == false)
af87ab54
AL
1536 return false;
1537
1538 // Print out all of the package files
1539 if (CmdL.FileList[1] == 0)
1540 {
db0db9fe 1541 cout << _("Package files:") << endl;
af87ab54
AL
1542 for (pkgCache::PkgFileIterator F = Cache.FileBegin(); F.end() == false; F++)
1543 {
1544 // Locate the associated index files so we can derive a description
1545 pkgIndexFile *Indx;
1546 if (SrcList->FindIndex(F,Indx) == false &&
1547 _system->FindIndex(F,Indx) == false)
1548 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
78acd650
MV
1549
1550 printf("%4i %s\n",
af87ab54
AL
1551 Plcy.GetPriority(F),Indx->Describe(true).c_str());
1552
1553 // Print the reference information for the package
1554 string Str = F.RelStr();
1555 if (Str.empty() == false)
1556 printf(" release %s\n",F.RelStr().c_str());
1557 if (F.Site() != 0 && F.Site()[0] != 0)
1558 printf(" origin %s\n",F.Site());
1559 }
1560
1561 // Show any packages have explicit pins
db0db9fe 1562 cout << _("Pinned packages:") << endl;
af87ab54
AL
1563 pkgCache::PkgIterator I = Cache.PkgBegin();
1564 for (;I.end() != true; I++)
1565 {
1566 if (Plcy.GetPriority(I) == 0)
1567 continue;
1568
1569 // Print the package name and the version we are forcing to
75ce2062 1570 cout << " " << I.FullName(true) << " -> ";
af87ab54
AL
1571
1572 pkgCache::VerIterator V = Plcy.GetMatch(I);
1573 if (V.end() == true)
1574 cout << _("(not found)") << endl;
1575 else
1576 cout << V.VerStr() << endl;
1577 }
1578
1579 return true;
1580 }
6293e04f
DK
1581
1582 string const myArch = _config->Find("APT::Architecture");
ca964703
DK
1583 char const * const msgInstalled = _(" Installed: ");
1584 char const * const msgCandidate = _(" Candidate: ");
1585 short const InstalledLessCandidate =
1586 mbstowcs(NULL, msgInstalled, 0) - mbstowcs(NULL, msgCandidate, 0);
1587 short const deepInstalled =
1588 (InstalledLessCandidate < 0 ? (InstalledLessCandidate*-1) : 0) - 1;
1589 short const deepCandidate =
1590 (InstalledLessCandidate > 0 ? (InstalledLessCandidate) : 0) - 1;
6293e04f 1591
af87ab54 1592 // Print out detailed information for each package
78c32596
DK
1593 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(Cache, CmdL.FileList);
1594 for (APT::PackageSet::const_iterator I = pkgset.begin(); I != pkgset.end(); ++I)
af87ab54 1595 {
78c32596 1596 pkgCache::PkgIterator Pkg = I.Group().FindPkg("any");
6293e04f 1597
4c265635 1598 for (; Pkg.end() != true; Pkg = I.Group().NextPkg(Pkg)) {
803ea2a8
DK
1599 if (strcmp(Pkg.Arch(),"all") == 0)
1600 continue;
6293e04f 1601
75ce2062 1602 cout << Pkg.FullName(true) << ":" << endl;
6293e04f 1603
af87ab54 1604 // Installed version
ca964703 1605 cout << msgInstalled << OutputInDepth(deepInstalled, " ");
af87ab54
AL
1606 if (Pkg->CurrentVer == 0)
1607 cout << _("(none)") << endl;
1608 else
1609 cout << Pkg.CurrentVer().VerStr() << endl;
1610
1611 // Candidate Version
ca964703 1612 cout << msgCandidate << OutputInDepth(deepCandidate, " ");
af87ab54
AL
1613 pkgCache::VerIterator V = Plcy.GetCandidateVer(Pkg);
1614 if (V.end() == true)
1615 cout << _("(none)") << endl;
1616 else
1617 cout << V.VerStr() << endl;
1618
1619 // Pinned version
1620 if (Plcy.GetPriority(Pkg) != 0)
1621 {
db0db9fe 1622 cout << _(" Package pin: ");
af87ab54
AL
1623 V = Plcy.GetMatch(Pkg);
1624 if (V.end() == true)
1625 cout << _("(not found)") << endl;
1626 else
1627 cout << V.VerStr() << endl;
1628 }
1629
1630 // Show the priority tables
db0db9fe 1631 cout << _(" Version table:") << endl;
af87ab54
AL
1632 for (V = Pkg.VersionList(); V.end() == false; V++)
1633 {
1634 if (Pkg.CurrentVer() == V)
1635 cout << " *** " << V.VerStr();
1636 else
1637 cout << " " << V.VerStr();
1638 cout << " " << Plcy.GetPriority(Pkg) << endl;
1639 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1640 {
1641 // Locate the associated index files so we can derive a description
1642 pkgIndexFile *Indx;
1643 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1644 _system->FindIndex(VF.File(),Indx) == false)
1645 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
46e39c8e 1646 printf(" %4i %s\n",Plcy.GetPriority(VF.File()),
af87ab54 1647 Indx->Describe(true).c_str());
6293e04f
DK
1648 }
1649 }
1650 }
af87ab54
AL
1651 }
1652
f8f410f5
AL
1653 return true;
1654}
bd3d53ef
AL
1655 /*}}}*/
1656// Madison - Look a bit like katie's madison /*{{{*/
1657// ---------------------------------------------------------------------
1658/* */
1659bool Madison(CommandLine &CmdL)
1660{
1661 if (SrcList == 0)
1662 return _error->Error("Generate must be enabled for this function");
1663
1664 SrcList->ReadMainList();
1665
1666 pkgCache &Cache = *GCache;
1667
03cd434b
MV
1668 // Create the src text record parsers and ignore errors about missing
1669 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
bd3d53ef
AL
1670 pkgSrcRecords SrcRecs(*SrcList);
1671 if (_error->PendingError() == true)
03cd434b 1672 _error->Discard();
bd3d53ef 1673
78c32596
DK
1674 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(Cache, CmdL.FileList);
1675 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
bd3d53ef 1676 {
bd3d53ef
AL
1677 if (Pkg.end() == false)
1678 {
1679 for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; V++)
1680 {
1681 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1682 {
a0e710af
AL
1683// This might be nice, but wouldn't uniquely identify the source -mdz
1684// if (VF.File().Archive() != 0)
1685// {
1686// cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1687// << VF.File().Archive() << endl;
1688// }
1689
1690 // Locate the associated index files so we can derive a description
1691 for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); S++)
bd3d53ef 1692 {
7db98ffc
MZ
1693 vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
1694 for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
1695 IF != Indexes->end(); IF++)
1696 {
1697 if ((*IF)->FindInCache(*(VF.File().Cache())) == VF.File())
1698 {
75ce2062 1699 cout << setw(10) << Pkg.FullName(true) << " | " << setw(10) << V.VerStr() << " | "
7db98ffc
MZ
1700 << (*IF)->Describe(true) << endl;
1701 }
1702 }
bd3d53ef
AL
1703 }
1704 }
1705 }
1706 }
1707
1708
1709 SrcRecs.Restart();
1710 pkgSrcRecords::Parser *SrcParser;
78c32596 1711 while ((SrcParser = SrcRecs.Find(Pkg.Name(),false)) != 0)
bd3d53ef
AL
1712 {
1713 // Maybe support Release info here too eventually
1714 cout << setw(10) << SrcParser->Package() << " | "
1715 << setw(10) << SrcParser->Version() << " | "
1716 << SrcParser->Index().Describe(true) << endl;
1717 }
1718 }
1719
1720 return true;
1721}
f8f410f5 1722 /*}}}*/
880e9be4
AL
1723// GenCaches - Call the main cache generator /*{{{*/
1724// ---------------------------------------------------------------------
1725/* */
b0b4efb9 1726bool GenCaches(CommandLine &Cmd)
880e9be4 1727{
0a8e3465
AL
1728 OpTextProgress Progress(*_config);
1729
880e9be4 1730 pkgSourceList List;
b2e465d6
AL
1731 if (List.ReadMainList() == false)
1732 return false;
0a8e3465 1733 return pkgMakeStatusCache(List,Progress);
880e9be4
AL
1734}
1735 /*}}}*/
e1b74f61
AL
1736// ShowHelp - Show a help screen /*{{{*/
1737// ---------------------------------------------------------------------
1738/* */
b0b4efb9 1739bool ShowHelp(CommandLine &Cmd)
e1b74f61 1740{
5b28c804
OS
1741 ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION,
1742 COMMON_ARCH,__DATE__,__TIME__);
e1b74f61 1743
b13af988
AL
1744 if (_config->FindB("version") == true)
1745 return true;
1746
b2e465d6
AL
1747 cout <<
1748 _("Usage: apt-cache [options] command\n"
b9d2ece3 1749 " apt-cache [options] add file1 [file2 ...]\n"
b2e465d6 1750 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
2d425135 1751 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
b2e465d6
AL
1752 "\n"
1753 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1754 "cache files, and query information from them\n"
1755 "\n"
1756 "Commands:\n"
bac2e715 1757 " add - Add a package file to the source cache\n"
b2e465d6
AL
1758 " gencaches - Build both the package and source cache\n"
1759 " showpkg - Show some general information for a single package\n"
2d425135 1760 " showsrc - Show source records\n"
b2e465d6
AL
1761 " stats - Show some basic statistics\n"
1762 " dump - Show the entire file in a terse form\n"
1763 " dumpavail - Print an available file to stdout\n"
1764 " unmet - Show unmet dependencies\n"
b2e465d6
AL
1765 " search - Search the package list for a regex pattern\n"
1766 " show - Show a readable record for the package\n"
6007c1d4 1767 " showauto - Display a list of automatically installed packages\n"
b2e465d6 1768 " depends - Show raw dependency information for a package\n"
eba2b51d 1769 " rdepends - Show reverse dependency information for a package\n"
2c120e24
EL
1770 " pkgnames - List the names of all packages in the system\n"
1771 " dotty - Generate package graphs for GraphViz\n"
fff4b7f3 1772 " xvcg - Generate package graphs for xvcg\n"
eba05d54 1773 " policy - Show policy settings\n"
b2e465d6
AL
1774 "\n"
1775 "Options:\n"
1776 " -h This help text.\n"
1777 " -p=? The package cache.\n"
1778 " -s=? The source cache.\n"
1779 " -q Disable progress indicator.\n"
1780 " -i Show only important deps for the unmet command.\n"
1781 " -c=? Read this configuration file\n"
a2884e32 1782 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
b2e465d6
AL
1783 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1784 return true;
e1b74f61
AL
1785}
1786 /*}}}*/
0a8e3465
AL
1787// CacheInitialize - Initialize things for apt-cache /*{{{*/
1788// ---------------------------------------------------------------------
1789/* */
1790void CacheInitialize()
1791{
1792 _config->Set("quiet",0);
1793 _config->Set("help",false);
1794}
1795 /*}}}*/
92fcbfc1 1796int main(int argc,const char *argv[]) /*{{{*/
1164783d 1797{
08e8f724
AL
1798 CommandLine::Args Args[] = {
1799 {'h',"help","help",0},
04aa15a8 1800 {'v',"version","version",0},
e1b74f61
AL
1801 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
1802 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
1803 {'q',"quiet","quiet",CommandLine::IntLevel},
76fbce56 1804 {'i',"important","APT::Cache::Important",0},
7e2e2d5d 1805 {'f',"full","APT::Cache::ShowFull",0},
b2e465d6 1806 {'g',"generate","APT::Cache::Generate",0},
648e3cb4 1807 {'a',"all-versions","APT::Cache::AllVersions",0},
fe6fc1c2
AL
1808 {'n',"names-only","APT::Cache::NamesOnly",0},
1809 {0,"all-names","APT::Cache::AllNames",0},
b2e465d6 1810 {0,"recurse","APT::Cache::RecurseDepends",0},
e1b74f61
AL
1811 {'c',"config-file",0,CommandLine::ConfigFile},
1812 {'o',"option",0,CommandLine::ArbItem},
fe6fc1c2 1813 {0,"installed","APT::Cache::Installed",0},
08e8f724 1814 {0,0,0,0}};
b0b4efb9
AL
1815 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
1816 {"add",&DoAdd},
1817 {"gencaches",&GenCaches},
f8f410f5 1818 {"showsrc",&ShowSrcPackage},
b0b4efb9
AL
1819 {0,0}};
1820 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
1821 {"stats",&Stats},
1822 {"dump",&Dump},
1823 {"dumpavail",&DumpAvail},
1824 {"unmet",&UnMet},
9dbb421f 1825 {"search",&Search},
349cd3b8 1826 {"depends",&Depends},
eba2b51d 1827 {"rdepends",&RDepends},
3e94da1b 1828 {"dotty",&Dotty},
fff4b7f3 1829 {"xvcg",&XVcg},
7e2e2d5d 1830 {"show",&ShowPackage},
7c1133fe 1831 {"pkgnames",&ShowPkgNames},
6007c1d4 1832 {"showauto",&ShowAuto},
af87ab54 1833 {"policy",&Policy},
bd3d53ef 1834 {"madison",&Madison},
b0b4efb9 1835 {0,0}};
0a8e3465
AL
1836
1837 CacheInitialize();
67111687
AL
1838
1839 // Set up gettext support
1840 setlocale(LC_ALL,"");
1841 textdomain(PACKAGE);
1842
e1b74f61
AL
1843 // Parse the command line and initialize the package library
1844 CommandLine CmdL(Args,_config);
b2e465d6
AL
1845 if (pkgInitConfig(*_config) == false ||
1846 CmdL.Parse(argc,argv) == false ||
1847 pkgInitSystem(*_config,_system) == false)
08e8f724
AL
1848 {
1849 _error->DumpErrors();
1850 return 100;
1164783d 1851 }
8efa2a3b 1852
e1b74f61
AL
1853 // See if the help should be shown
1854 if (_config->FindB("help") == true ||
1855 CmdL.FileSize() == 0)
b2e465d6
AL
1856 {
1857 ShowHelp(CmdL);
1858 return 0;
1859 }
1860
a9a5908d 1861 // Deal with stdout not being a tty
a3f6ea20 1862 if (isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
a9a5908d
AL
1863 _config->Set("quiet","1");
1864
b0b4efb9 1865 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
4b1b89c5 1866 {
2a3f3893 1867 MMap *Map = 0;
b2e465d6 1868 if (_config->FindB("APT::Cache::Generate",true) == false)
4b1b89c5
AL
1869 {
1870 Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"),
1871 FileFd::ReadOnly),MMap::Public|MMap::ReadOnly);
1872 }
1873 else
1874 {
1875 // Open the cache file
af87ab54
AL
1876 SrcList = new pkgSourceList;
1877 SrcList->ReadMainList();
f8f410f5 1878
4b1b89c5
AL
1879 // Generate it and map it
1880 OpProgress Prog;
af87ab54 1881 pkgMakeStatusCache(*SrcList,Prog,&Map,true);
4b1b89c5
AL
1882 }
1883
b0b4efb9 1884 if (_error->PendingError() == false)
1164783d 1885 {
b2e465d6 1886 pkgCache Cache(Map);
b0b4efb9
AL
1887 GCache = &Cache;
1888 if (_error->PendingError() == false)
1889 CmdL.DispatchArg(CmdsB);
803fafcb
AL
1890 }
1891 delete Map;
1164783d
AL
1892 }
1893
1894 // Print any errors or warnings found during parsing
1895 if (_error->empty() == false)
1896 {
0a8e3465 1897 bool Errors = _error->PendingError();
1164783d 1898 _error->DumpErrors();
0a8e3465 1899 return Errors == true?100:0;
1164783d
AL
1900 }
1901
1902 return 0;
1903}
92fcbfc1 1904 /*}}}*/