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