]> git.saurik.com Git - apt.git/blame - cmdline/apt-cache.cc
remove the "typename" from the const_iterators as gcc-4.4 doesn't like
[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>
7959c5ed 32#include <apt-pkg/cacheset.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
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 /*}}}*/
4b1b89c5 554// Depends - Print out a dependency tree /*{{{*/
349cd3b8
AL
555// ---------------------------------------------------------------------
556/* */
557bool Depends(CommandLine &CmdL)
558{
d9eb210e
DK
559 pkgCacheFile CacheFile;
560 pkgCache *Cache = CacheFile.GetPkgCache();
561 if (unlikely(Cache == NULL))
562 return false;
78c32596 563
d9eb210e
DK
564 SPtrArray<unsigned> Colours = new unsigned[Cache->Head().PackageCount];
565 memset(Colours,0,sizeof(*Colours)*Cache->Head().PackageCount);
566
9f1f17cc 567 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
78c32596 568 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
b2e465d6 569 Colours[Pkg->ID] = 1;
78c32596 570
b2e465d6 571 bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
eba2b51d 572 bool Installed = _config->FindB("APT::Cache::Installed",false);
5aa95c86 573 bool Important = _config->FindB("APT::Cache::Important",false);
b2e465d6
AL
574 bool DidSomething;
575 do
576 {
577 DidSomething = false;
d9eb210e 578 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
349cd3b8 579 {
b2e465d6
AL
580 if (Colours[Pkg->ID] != 1)
581 continue;
582 Colours[Pkg->ID] = 2;
583 DidSomething = true;
349cd3b8 584
b2e465d6
AL
585 pkgCache::VerIterator Ver = Pkg.VersionList();
586 if (Ver.end() == true)
349cd3b8 587 {
75ce2062 588 cout << '<' << Pkg.FullName(true) << '>' << endl;
b2e465d6 589 continue;
349cd3b8 590 }
b2e465d6 591
75ce2062 592 cout << Pkg.FullName(true) << endl;
b2e465d6
AL
593
594 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
595 {
5aa95c86
MV
596 // Important deps only
597 if (Important == true)
598 if (D->Type != pkgCache::Dep::PreDepends &&
599 D->Type != pkgCache::Dep::Depends)
600 continue;
601
b2e465d6 602 pkgCache::PkgIterator Trg = D.TargetPkg();
eba2b51d
AL
603
604 if((Installed && Trg->CurrentVer != 0) || !Installed)
605 {
606
607 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
608 cout << " |";
609 else
610 cout << " ";
b2e465d6 611
eba2b51d
AL
612 // Show the package
613 if (Trg->VersionList == 0)
75ce2062 614 cout << D.DepType() << ": <" << Trg.FullName(true) << ">" << endl;
eba2b51d 615 else
75ce2062 616 cout << D.DepType() << ": " << Trg.FullName(true) << endl;
eba2b51d
AL
617
618 if (Recurse == true)
619 Colours[D.TargetPkg()->ID]++;
620
621 }
b2e465d6
AL
622
623 // Display all solutions
624 SPtrArray<pkgCache::Version *> List = D.AllTargets();
d9eb210e 625 pkgPrioSortList(*Cache,List);
b2e465d6
AL
626 for (pkgCache::Version **I = List; *I != 0; I++)
627 {
d9eb210e
DK
628 pkgCache::VerIterator V(*Cache,*I);
629 if (V != Cache->VerP + V.ParentPkg()->VersionList ||
b2e465d6
AL
630 V->ParentPkg == D->Package)
631 continue;
75ce2062 632 cout << " " << V.ParentPkg().FullName(true) << endl;
b2e465d6
AL
633
634 if (Recurse == true)
635 Colours[D.ParentPkg()->ID]++;
636 }
637 }
638 }
349cd3b8 639 }
b2e465d6 640 while (DidSomething == true);
349cd3b8 641
3e94da1b
AL
642 return true;
643}
92fcbfc1 644 /*}}}*/
eba2b51d
AL
645// RDepends - Print out a reverse dependency tree - mbc /*{{{*/
646// ---------------------------------------------------------------------
647/* */
648bool RDepends(CommandLine &CmdL)
649{
d9eb210e
DK
650 pkgCacheFile CacheFile;
651 pkgCache *Cache = CacheFile.GetPkgCache();
652 if (unlikely(Cache == NULL))
653 return false;
78c32596 654
d9eb210e
DK
655 SPtrArray<unsigned> Colours = new unsigned[Cache->Head().PackageCount];
656 memset(Colours,0,sizeof(*Colours)*Cache->Head().PackageCount);
657
9f1f17cc 658 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
78c32596 659 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
eba2b51d 660 Colours[Pkg->ID] = 1;
78c32596 661
eba2b51d
AL
662 bool Recurse = _config->FindB("APT::Cache::RecurseDepends",false);
663 bool Installed = _config->FindB("APT::Cache::Installed",false);
664 bool DidSomething;
665 do
666 {
667 DidSomething = false;
d9eb210e 668 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
eba2b51d
AL
669 {
670 if (Colours[Pkg->ID] != 1)
671 continue;
672 Colours[Pkg->ID] = 2;
673 DidSomething = true;
674
675 pkgCache::VerIterator Ver = Pkg.VersionList();
676 if (Ver.end() == true)
677 {
75ce2062 678 cout << '<' << Pkg.FullName(true) << '>' << endl;
eba2b51d
AL
679 continue;
680 }
681
75ce2062 682 cout << Pkg.FullName(true) << endl;
eba2b51d
AL
683
684 cout << "Reverse Depends:" << endl;
685 for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() == false; D++)
686 {
687 // Show the package
688 pkgCache::PkgIterator Trg = D.ParentPkg();
689
690 if((Installed && Trg->CurrentVer != 0) || !Installed)
691 {
692
693 if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
694 cout << " |";
695 else
696 cout << " ";
697
698 if (Trg->VersionList == 0)
75ce2062 699 cout << D.DepType() << ": <" << Trg.FullName(true) << ">" << endl;
eba2b51d 700 else
75ce2062 701 cout << Trg.FullName(true) << endl;
eba2b51d
AL
702
703 if (Recurse == true)
704 Colours[D.ParentPkg()->ID]++;
705
706 }
707
708 // Display all solutions
709 SPtrArray<pkgCache::Version *> List = D.AllTargets();
d9eb210e 710 pkgPrioSortList(*Cache,List);
eba2b51d
AL
711 for (pkgCache::Version **I = List; *I != 0; I++)
712 {
d9eb210e
DK
713 pkgCache::VerIterator V(*Cache,*I);
714 if (V != Cache->VerP + V.ParentPkg()->VersionList ||
eba2b51d
AL
715 V->ParentPkg == D->Package)
716 continue;
75ce2062 717 cout << " " << V.ParentPkg().FullName(true) << endl;
eba2b51d
AL
718
719 if (Recurse == true)
720 Colours[D.ParentPkg()->ID]++;
721 }
722 }
723 }
724 }
725 while (DidSomething == true);
726
727 return true;
728}
3e94da1b 729 /*}}}*/
fff4b7f3
AL
730// xvcg - Generate a graph for xvcg /*{{{*/
731// ---------------------------------------------------------------------
732// Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
733
734bool XVcg(CommandLine &CmdL)
735{
d9eb210e
DK
736 pkgCacheFile CacheFile;
737 pkgCache *Cache = CacheFile.GetPkgCache();
738 if (unlikely(Cache == NULL))
739 return false;
740
fff4b7f3
AL
741 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
742
743 /* Normal packages are boxes
744 Pure Provides are triangles
745 Mixed are diamonds
746 rhomb are missing packages*/
747 const char *Shapes[] = {"ellipse","triangle","box","rhomb"};
748
749 /* Initialize the list of packages to show.
750 1 = To Show
751 2 = To Show no recurse
752 3 = Emitted no recurse
753 4 = Emitted
754 0 = None */
755 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
756 enum TheFlags {ForceNR=(1<<0)};
d9eb210e
DK
757 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
758 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
759 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
fff4b7f3
AL
760
761 // Show everything if no arguments given
762 if (CmdL.FileList[1] == 0)
d9eb210e 763 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
fff4b7f3
AL
764 Show[I] = ToShow;
765 else
d9eb210e 766 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
fff4b7f3 767 Show[I] = None;
d9eb210e 768 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
fff4b7f3
AL
769
770 // Map the shapes
d9eb210e 771 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
fff4b7f3
AL
772 {
773 if (Pkg->VersionList == 0)
774 {
775 // Missing
776 if (Pkg->ProvidesList == 0)
777 ShapeMap[Pkg->ID] = 0;
778 else
779 ShapeMap[Pkg->ID] = 1;
780 }
781 else
782 {
783 // Normal
784 if (Pkg->ProvidesList == 0)
785 ShapeMap[Pkg->ID] = 2;
786 else
787 ShapeMap[Pkg->ID] = 3;
788 }
789 }
3c977245 790
fff4b7f3 791 // Load the list of packages from the command line into the show list
3c977245
DK
792 std::list<APT::PackageSet::Modifier> mods;
793 mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
794 mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
795 std::map<unsigned short, APT::PackageSet> pkgsets =
796 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0);
797
798 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
799 Pkg != pkgsets[0].end(); ++Pkg)
800 Show[Pkg->ID] = ToShow;
801 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
802 Pkg != pkgsets[1].end(); ++Pkg)
fff4b7f3 803 {
fff4b7f3 804 Show[Pkg->ID] = ToShow;
3c977245 805 Flags[Pkg->ID] |= ForceNR;
fff4b7f3 806 }
3c977245 807
fff4b7f3
AL
808 // Little header
809 cout << "graph: { title: \"packages\"" << endl <<
810 "xmax: 700 ymax: 700 x: 30 y: 30" << endl <<
811 "layout_downfactor: 8" << endl;
812
813 bool Act = true;
814 while (Act == true)
815 {
816 Act = false;
d9eb210e 817 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
fff4b7f3
AL
818 {
819 // See we need to show this package
820 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
821 continue;
822
823 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
824
825 // Colour as done
826 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
827 {
828 // Pure Provides and missing packages have no deps!
829 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
830 Show[Pkg->ID] = Done;
831 else
832 Show[Pkg->ID] = DoneNR;
833 }
834 else
835 Show[Pkg->ID] = Done;
836 Act = true;
837
838 // No deps to map out
839 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
840 continue;
841
842 pkgCache::VerIterator Ver = Pkg.VersionList();
843 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
844 {
845 // See if anything can meet this dep
846 // Walk along the actual package providing versions
847 bool Hit = false;
848 pkgCache::PkgIterator DPkg = D.TargetPkg();
849 for (pkgCache::VerIterator I = DPkg.VersionList();
850 I.end() == false && Hit == false; I++)
851 {
d9eb210e 852 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
fff4b7f3
AL
853 Hit = true;
854 }
855
856 // Follow all provides
857 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
858 I.end() == false && Hit == false; I++)
859 {
d9eb210e 860 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
fff4b7f3
AL
861 Hit = true;
862 }
863
864
865 // Only graph critical deps
866 if (D.IsCritical() == true)
867 {
75ce2062 868 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg.FullName(true).c_str(), D.TargetPkg().FullName(true).c_str() );
fff4b7f3
AL
869
870 // Colour the node for recursion
871 if (Show[D.TargetPkg()->ID] <= DoneNR)
872 {
873 /* If a conflicts does not meet anything in the database
874 then show the relation but do not recurse */
875 if (Hit == false &&
876 (D->Type == pkgCache::Dep::Conflicts ||
308c7d30 877 D->Type == pkgCache::Dep::DpkgBreaks ||
fff4b7f3
AL
878 D->Type == pkgCache::Dep::Obsoletes))
879 {
880 if (Show[D.TargetPkg()->ID] == None &&
881 Show[D.TargetPkg()->ID] != ToShow)
882 Show[D.TargetPkg()->ID] = ToShowNR;
883 }
884 else
885 {
886 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
887 Show[D.TargetPkg()->ID] = ToShowNR;
888 else
889 Show[D.TargetPkg()->ID] = ToShow;
890 }
891 }
892
893 // Edge colour
894 switch(D->Type)
895 {
896 case pkgCache::Dep::Conflicts:
897 printf("label: \"conflicts\" color: lightgreen }\n");
898 break;
308c7d30
IJ
899 case pkgCache::Dep::DpkgBreaks:
900 printf("label: \"breaks\" color: lightgreen }\n");
901 break;
fff4b7f3
AL
902 case pkgCache::Dep::Obsoletes:
903 printf("label: \"obsoletes\" color: lightgreen }\n");
904 break;
905
906 case pkgCache::Dep::PreDepends:
907 printf("label: \"predepends\" color: blue }\n");
908 break;
909
910 default:
911 printf("}\n");
912 break;
913 }
914 }
915 }
916 }
917 }
918
919 /* Draw the box colours after the fact since we can not tell what colour
920 they should be until everything is finished drawing */
d9eb210e 921 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
fff4b7f3
AL
922 {
923 if (Show[Pkg->ID] < DoneNR)
924 continue;
925
926 if (Show[Pkg->ID] == DoneNR)
75ce2062 927 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
fff4b7f3
AL
928 Shapes[ShapeMap[Pkg->ID]]);
929 else
75ce2062 930 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg.FullName(true).c_str(), Pkg.FullName(true).c_str(),
fff4b7f3
AL
931 Shapes[ShapeMap[Pkg->ID]]);
932
933 }
03496041
DK
934
935 delete[] Show;
936 delete[] Flags;
937 delete[] ShapeMap;
938
fff4b7f3
AL
939 printf("}\n");
940 return true;
941}
942 /*}}}*/
3e94da1b
AL
943// Dotty - Generate a graph for Dotty /*{{{*/
944// ---------------------------------------------------------------------
945/* Dotty is the graphvis program for generating graphs. It is a fairly
946 simple queuing algorithm that just writes dependencies and nodes.
947 http://www.research.att.com/sw/tools/graphviz/ */
948bool Dotty(CommandLine &CmdL)
949{
d9eb210e
DK
950 pkgCacheFile CacheFile;
951 pkgCache *Cache = CacheFile.GetPkgCache();
952 if (unlikely(Cache == NULL))
953 return false;
954
3e94da1b
AL
955 bool GivenOnly = _config->FindB("APT::Cache::GivenOnly",false);
956
957 /* Normal packages are boxes
958 Pure Provides are triangles
959 Mixed are diamonds
960 Hexagons are missing packages*/
961 const char *Shapes[] = {"hexagon","triangle","box","diamond"};
962
963 /* Initialize the list of packages to show.
964 1 = To Show
965 2 = To Show no recurse
966 3 = Emitted no recurse
967 4 = Emitted
968 0 = None */
969 enum States {None=0, ToShow, ToShowNR, DoneNR, Done};
970 enum TheFlags {ForceNR=(1<<0)};
d9eb210e
DK
971 unsigned char *Show = new unsigned char[Cache->Head().PackageCount];
972 unsigned char *Flags = new unsigned char[Cache->Head().PackageCount];
973 unsigned char *ShapeMap = new unsigned char[Cache->Head().PackageCount];
3e94da1b
AL
974
975 // Show everything if no arguments given
976 if (CmdL.FileList[1] == 0)
d9eb210e 977 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
3e94da1b
AL
978 Show[I] = ToShow;
979 else
d9eb210e 980 for (unsigned long I = 0; I != Cache->Head().PackageCount; I++)
3e94da1b 981 Show[I] = None;
d9eb210e 982 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
3e94da1b
AL
983
984 // Map the shapes
d9eb210e 985 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
3e94da1b
AL
986 {
987 if (Pkg->VersionList == 0)
988 {
989 // Missing
990 if (Pkg->ProvidesList == 0)
991 ShapeMap[Pkg->ID] = 0;
992 else
993 ShapeMap[Pkg->ID] = 1;
994 }
995 else
996 {
997 // Normal
998 if (Pkg->ProvidesList == 0)
999 ShapeMap[Pkg->ID] = 2;
1000 else
1001 ShapeMap[Pkg->ID] = 3;
1002 }
1003 }
3c977245 1004
3e94da1b 1005 // Load the list of packages from the command line into the show list
3c977245
DK
1006 std::list<APT::PackageSet::Modifier> mods;
1007 mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX));
1008 mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX));
1009 std::map<unsigned short, APT::PackageSet> pkgsets =
1010 APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0);
1011
1012 for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin();
1013 Pkg != pkgsets[0].end(); ++Pkg)
1014 Show[Pkg->ID] = ToShow;
1015 for (APT::PackageSet::const_iterator Pkg = pkgsets[1].begin();
1016 Pkg != pkgsets[1].end(); ++Pkg)
3e94da1b 1017 {
3e94da1b 1018 Show[Pkg->ID] = ToShow;
3c977245 1019 Flags[Pkg->ID] |= ForceNR;
3e94da1b 1020 }
3c977245 1021
3e94da1b
AL
1022 // Little header
1023 printf("digraph packages {\n");
1024 printf("concentrate=true;\n");
1025 printf("size=\"30,40\";\n");
1026
1027 bool Act = true;
1028 while (Act == true)
1029 {
1030 Act = false;
d9eb210e 1031 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
3e94da1b
AL
1032 {
1033 // See we need to show this package
1034 if (Show[Pkg->ID] == None || Show[Pkg->ID] >= DoneNR)
1035 continue;
1036
1037 // Colour as done
1038 if (Show[Pkg->ID] == ToShowNR || (Flags[Pkg->ID] & ForceNR) == ForceNR)
1039 {
1040 // Pure Provides and missing packages have no deps!
1041 if (ShapeMap[Pkg->ID] == 0 || ShapeMap[Pkg->ID] == 1)
1042 Show[Pkg->ID] = Done;
1043 else
1044 Show[Pkg->ID] = DoneNR;
1045 }
1046 else
1047 Show[Pkg->ID] = Done;
1048 Act = true;
1049
1050 // No deps to map out
1051 if (Pkg->VersionList == 0 || Show[Pkg->ID] == DoneNR)
1052 continue;
1053
1054 pkgCache::VerIterator Ver = Pkg.VersionList();
1055 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
1056 {
1057 // See if anything can meet this dep
1058 // Walk along the actual package providing versions
1059 bool Hit = false;
1060 pkgCache::PkgIterator DPkg = D.TargetPkg();
1061 for (pkgCache::VerIterator I = DPkg.VersionList();
1062 I.end() == false && Hit == false; I++)
1063 {
d9eb210e 1064 if (Cache->VS->CheckDep(I.VerStr(),D->CompareOp,D.TargetVer()) == true)
3e94da1b
AL
1065 Hit = true;
1066 }
1067
1068 // Follow all provides
1069 for (pkgCache::PrvIterator I = DPkg.ProvidesList();
1070 I.end() == false && Hit == false; I++)
1071 {
d9eb210e 1072 if (Cache->VS->CheckDep(I.ProvideVersion(),D->CompareOp,D.TargetVer()) == false)
3e94da1b
AL
1073 Hit = true;
1074 }
1075
1076 // Only graph critical deps
1077 if (D.IsCritical() == true)
1078 {
75ce2062 1079 printf("\"%s\" -> \"%s\"",Pkg.FullName(true).c_str(),D.TargetPkg().FullName(true).c_str());
3e94da1b
AL
1080
1081 // Colour the node for recursion
1082 if (Show[D.TargetPkg()->ID] <= DoneNR)
1083 {
1084 /* If a conflicts does not meet anything in the database
1085 then show the relation but do not recurse */
b2e465d6
AL
1086 if (Hit == false &&
1087 (D->Type == pkgCache::Dep::Conflicts ||
1088 D->Type == pkgCache::Dep::Obsoletes))
3e94da1b
AL
1089 {
1090 if (Show[D.TargetPkg()->ID] == None &&
1091 Show[D.TargetPkg()->ID] != ToShow)
1092 Show[D.TargetPkg()->ID] = ToShowNR;
1093 }
1094 else
1095 {
1096 if (GivenOnly == true && Show[D.TargetPkg()->ID] != ToShow)
1097 Show[D.TargetPkg()->ID] = ToShowNR;
1098 else
1099 Show[D.TargetPkg()->ID] = ToShow;
1100 }
1101 }
1102
1103 // Edge colour
1104 switch(D->Type)
1105 {
1106 case pkgCache::Dep::Conflicts:
b2e465d6 1107 case pkgCache::Dep::Obsoletes:
3e94da1b
AL
1108 printf("[color=springgreen];\n");
1109 break;
1110
1111 case pkgCache::Dep::PreDepends:
1112 printf("[color=blue];\n");
1113 break;
1114
1115 default:
1116 printf(";\n");
1117 break;
1118 }
1119 }
1120 }
1121 }
1122 }
1123
1124 /* Draw the box colours after the fact since we can not tell what colour
1125 they should be until everything is finished drawing */
d9eb210e 1126 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
3e94da1b
AL
1127 {
1128 if (Show[Pkg->ID] < DoneNR)
1129 continue;
1130
1131 // Orange box for early recursion stoppage
1132 if (Show[Pkg->ID] == DoneNR)
75ce2062 1133 printf("\"%s\" [color=orange,shape=%s];\n",Pkg.FullName(true).c_str(),
3e94da1b
AL
1134 Shapes[ShapeMap[Pkg->ID]]);
1135 else
75ce2062 1136 printf("\"%s\" [shape=%s];\n",Pkg.FullName(true).c_str(),
3e94da1b
AL
1137 Shapes[ShapeMap[Pkg->ID]]);
1138 }
1139
1140 printf("}\n");
ad00ae81
AL
1141 return true;
1142}
1143 /*}}}*/
1144// DoAdd - Perform an adding operation /*{{{*/
1145// ---------------------------------------------------------------------
1146/* */
e1b74f61 1147bool DoAdd(CommandLine &CmdL)
ad00ae81 1148{
b2e465d6
AL
1149 return _error->Error("Unimplemented");
1150#if 0
e1b74f61
AL
1151 // Make sure there is at least one argument
1152 if (CmdL.FileSize() <= 1)
1153 return _error->Error("You must give at least one file name");
ad00ae81
AL
1154
1155 // Open the cache
018f1533 1156 FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny);
ad00ae81
AL
1157 if (_error->PendingError() == true)
1158 return false;
1159
1160 DynamicMMap Map(CacheF,MMap::Public);
1161 if (_error->PendingError() == true)
1162 return false;
404ec98e 1163
0a8e3465 1164 OpTextProgress Progress(*_config);
404ec98e 1165 pkgCacheGenerator Gen(Map,Progress);
ad00ae81
AL
1166 if (_error->PendingError() == true)
1167 return false;
1168
e1b74f61
AL
1169 unsigned long Length = CmdL.FileSize() - 1;
1170 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
ad00ae81 1171 {
e1b74f61 1172 Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache");
018f1533
AL
1173 Progress.SubProgress(Length);
1174
ad00ae81 1175 // Do the merge
e1b74f61 1176 FileFd TagF(*I,FileFd::ReadOnly);
ad00ae81
AL
1177 debListParser Parser(TagF);
1178 if (_error->PendingError() == true)
e1b74f61 1179 return _error->Error("Problem opening %s",*I);
ad00ae81 1180
b2e465d6 1181 if (Gen.SelectFile(*I,"") == false)
ad00ae81
AL
1182 return _error->Error("Problem with SelectFile");
1183
1184 if (Gen.MergeList(Parser) == false)
1185 return _error->Error("Problem with MergeList");
1164783d 1186 }
404ec98e
AL
1187
1188 Progress.Done();
b0b4efb9
AL
1189 GCache = &Gen.GetCache();
1190 Stats(CmdL);
ad00ae81 1191
7e2e2d5d 1192 return true;
b2e465d6 1193#endif
7e2e2d5d
AL
1194}
1195 /*}}}*/
1196// DisplayRecord - Displays the complete record for the package /*{{{*/
1197// ---------------------------------------------------------------------
1198/* This displays the package record from the proper package index file.
1199 It is not used by DumpAvail for performance reasons. */
d9eb210e 1200bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
7e2e2d5d 1201{
d9eb210e
DK
1202 pkgCache *Cache = CacheFile.GetPkgCache();
1203 if (unlikely(Cache == NULL))
1204 return false;
1205
7e2e2d5d
AL
1206 // Find an appropriate file
1207 pkgCache::VerFileIterator Vf = V.FileList();
1208 for (; Vf.end() == false; Vf++)
1209 if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
1210 break;
1211 if (Vf.end() == true)
1212 Vf = V.FileList();
1213
1214 // Check and load the package list file
1215 pkgCache::PkgFileIterator I = Vf.File();
1216 if (I.IsOk() == false)
b2e465d6 1217 return _error->Error(_("Package file %s is out of sync."),I.FileName());
07c279d9
DK
1218
1219 FileFd PkgF;
1220 if (PkgF.Open(I.FileName(), FileFd::ReadOnly) == false)
7e2e2d5d 1221 return false;
07c279d9 1222
a52f938b 1223 // Read the record
d9eb210e 1224 unsigned char *Buffer = new unsigned char[Cache->HeaderP->MaxVerFileSize+1];
b2e465d6 1225 Buffer[V.FileList()->Size] = '\n';
7e2e2d5d 1226 if (PkgF.Seek(V.FileList()->Offset) == false ||
a52f938b 1227 PkgF.Read(Buffer,V.FileList()->Size) == false)
7e2e2d5d
AL
1228 {
1229 delete [] Buffer;
1230 return false;
1231 }
a52f938b 1232
e5e2d176 1233 // Get a pointer to start of Description field
e011829d 1234 const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "Description:");
e5e2d176
MV
1235
1236 // Write all but Description
487d7faa 1237 if (fwrite(Buffer,1,DescP - Buffer,stdout) < (size_t)(DescP - Buffer))
a52f938b
OS
1238 {
1239 delete [] Buffer;
1240 return false;
1241 }
1242
a52f938b 1243 // Show the right description
d9eb210e 1244 pkgRecords Recs(*Cache);
012b102a 1245 pkgCache::DescIterator Desc = V.TranslatedDescription();
a52f938b 1246 pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
e011829d 1247 cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
a52f938b 1248
e011829d
MV
1249 // Find the first field after the description (if there is any)
1250 for(DescP++;DescP != &Buffer[V.FileList()->Size];DescP++)
1251 {
1252 if(*DescP == '\n' && *(DescP+1) != ' ')
1253 {
1254 // write the rest of the buffer
1255 const unsigned char *end=&Buffer[V.FileList()->Size];
1256 if (fwrite(DescP,1,end-DescP,stdout) < (size_t)(end-DescP))
1257 {
1258 delete [] Buffer;
1259 return false;
1260 }
1261
1262 break;
1263 }
1264 }
1265 // write a final newline (after the description)
1266 cout<<endl;
7e2e2d5d
AL
1267 delete [] Buffer;
1268
9dbb421f
AL
1269 return true;
1270}
1271 /*}}}*/
92fcbfc1 1272
a52f938b 1273struct ExDescFile
b2e465d6 1274{
a52f938b 1275 pkgCache::DescFile *Df;
b2e465d6
AL
1276 bool NameMatch;
1277};
1278
92fcbfc1
DK
1279// Search - Perform a search /*{{{*/
1280// ---------------------------------------------------------------------
1281/* This searches the package names and package descriptions for a pattern */
9dbb421f
AL
1282bool Search(CommandLine &CmdL)
1283{
d5cc17d6
DK
1284 bool const ShowFull = _config->FindB("APT::Cache::ShowFull",false);
1285 bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly",false);
1286 unsigned int const NumPatterns = CmdL.FileSize() -1;
b2e465d6 1287
d9eb210e
DK
1288 pkgCacheFile CacheFile;
1289 pkgCache *Cache = CacheFile.GetPkgCache();
1290 pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
1291 if (unlikely(Cache == NULL || Plcy == NULL))
1292 return false;
1293
9dbb421f 1294 // Make sure there is at least one argument
b2e465d6 1295 if (NumPatterns < 1)
d5cc17d6 1296 return _error->Error(_("You must give at least one search pattern"));
9dbb421f
AL
1297
1298 // Compile the regex pattern
b2e465d6
AL
1299 regex_t *Patterns = new regex_t[NumPatterns];
1300 memset(Patterns,0,sizeof(*Patterns)*NumPatterns);
1301 for (unsigned I = 0; I != NumPatterns; I++)
1302 {
1303 if (regcomp(&Patterns[I],CmdL.FileList[I+1],REG_EXTENDED | REG_ICASE |
1304 REG_NOSUB) != 0)
1305 {
1306 for (; I != 0; I--)
1307 regfree(&Patterns[I]);
1308 return _error->Error("Regex compilation error");
1309 }
1310 }
9dbb421f 1311
9dbb421f 1312 if (_error->PendingError() == true)
b2e465d6
AL
1313 {
1314 for (unsigned I = 0; I != NumPatterns; I++)
1315 regfree(&Patterns[I]);
9dbb421f 1316 return false;
b2e465d6 1317 }
9dbb421f 1318
d9eb210e
DK
1319 ExDescFile *DFList = new ExDescFile[Cache->HeaderP->GroupCount+1];
1320 memset(DFList,0,sizeof(*DFList)*Cache->HeaderP->GroupCount+1);
b2e465d6
AL
1321
1322 // Map versions that we want to write out onto the VerList array.
d9eb210e 1323 for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
9dbb421f 1324 {
d5cc17d6
DK
1325 if (DFList[G->ID].NameMatch == true)
1326 continue;
1327
1328 DFList[G->ID].NameMatch = true;
b2e465d6
AL
1329 for (unsigned I = 0; I != NumPatterns; I++)
1330 {
d5cc17d6
DK
1331 if (regexec(&Patterns[I],G.Name(),0,0,0) == 0)
1332 continue;
1333 DFList[G->ID].NameMatch = false;
1334 break;
b2e465d6 1335 }
c29652b0 1336
b2e465d6 1337 // Doing names only, drop any that dont match..
d5cc17d6 1338 if (NamesOnly == true && DFList[G->ID].NameMatch == false)
b2e465d6
AL
1339 continue;
1340
d5cc17d6
DK
1341 // Find the proper version to use
1342 pkgCache::PkgIterator P = G.FindPreferredPkg();
1343 if (P.end() == true)
1344 continue;
d9eb210e 1345 pkgCache::VerIterator V = Plcy->GetCandidateVer(P);
c29652b0 1346 if (V.end() == false)
d5cc17d6
DK
1347 DFList[G->ID].Df = V.DescriptionList().FileList();
1348
1349 if (DFList[G->ID].NameMatch == false)
7e2e2d5d 1350 continue;
c29652b0 1351
d5cc17d6 1352 // Include all the packages that provide matching names too
c29652b0
AL
1353 for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
1354 {
d9eb210e 1355 pkgCache::VerIterator V = Plcy->GetCandidateVer(Prv.OwnerPkg());
d5cc17d6
DK
1356 if (V.end() == true)
1357 continue;
1358
1359 unsigned long id = Prv.OwnerPkg().Group()->ID;
1360 DFList[id].Df = V.DescriptionList().FileList();
1361 DFList[id].NameMatch = true;
c29652b0 1362 }
b2e465d6 1363 }
a52f938b 1364
d9eb210e 1365 LocalitySort(&DFList->Df,Cache->HeaderP->GroupCount,sizeof(*DFList));
7e2e2d5d 1366
d5cc17d6 1367 // Create the text record parser
d9eb210e 1368 pkgRecords Recs(*Cache);
b2e465d6 1369 // Iterate over all the version records and check them
a52f938b 1370 for (ExDescFile *J = DFList; J->Df != 0; J++)
b2e465d6 1371 {
d9eb210e 1372 pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(*Cache,J->Df));
0f2fa322 1373
d5cc17d6 1374 if (J->NameMatch == false && NamesOnly == false)
0f2fa322 1375 {
d5cc17d6
DK
1376 string const LongDesc = P.LongDesc();
1377 J->NameMatch = true;
0f2fa322
AL
1378 for (unsigned I = 0; I != NumPatterns; I++)
1379 {
1380 if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
d5cc17d6
DK
1381 continue;
1382 J->NameMatch = false;
1383 break;
0f2fa322
AL
1384 }
1385 }
b2e465d6 1386
d5cc17d6 1387 if (J->NameMatch == true)
9dbb421f 1388 {
7e2e2d5d 1389 if (ShowFull == true)
b2e465d6
AL
1390 {
1391 const char *Start;
1392 const char *End;
1393 P.GetRec(Start,End);
1394 fwrite(Start,End-Start,1,stdout);
1395 putc('\n',stdout);
1396 }
7e2e2d5d 1397 else
b2e465d6
AL
1398 printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
1399 }
9dbb421f
AL
1400 }
1401
a52f938b 1402 delete [] DFList;
b2e465d6
AL
1403 for (unsigned I = 0; I != NumPatterns; I++)
1404 regfree(&Patterns[I]);
1405 if (ferror(stdout))
1406 return _error->Error("Write to stdout failed");
1164783d
AL
1407 return true;
1408}
6007c1d4
JAK
1409
1410
1411/* show automatically installed packages (sorted) */
1412bool ShowAuto(CommandLine &CmdL)
1413{
d9eb210e
DK
1414 pkgCacheFile CacheFile;
1415 pkgCache *Cache = CacheFile.GetPkgCache();
1416 pkgDepCache *DepCache = CacheFile.GetDepCache();
1417 if (unlikely(Cache == NULL || DepCache == NULL))
1418 return false;
6007c1d4
JAK
1419
1420 std::vector<string> packages;
d9eb210e 1421 packages.reserve(Cache->HeaderP->PackageCount / 3);
6007c1d4 1422
d9eb210e
DK
1423 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; P++)
1424 if ((*DepCache)[P].Flags & pkgCache::Flag::Auto)
6007c1d4
JAK
1425 packages.push_back(P.Name());
1426
1427 std::sort(packages.begin(), packages.end());
1428
1429 for (vector<string>::iterator I = packages.begin(); I != packages.end(); I++)
1430 cout << *I << "\n";
1431
1432 return true;
1433}
1164783d 1434 /*}}}*/
7e2e2d5d
AL
1435// ShowPackage - Dump the package record to the screen /*{{{*/
1436// ---------------------------------------------------------------------
1437/* */
1438bool ShowPackage(CommandLine &CmdL)
d9eb210e
DK
1439{
1440 pkgCacheFile CacheFile;
1441 APT::VersionSet::Version const select = _config->FindB("APT::Cache::AllVersions", true) ?
292f5b87 1442 APT::VersionSet::ALL : APT::VersionSet::CANDIDATE;
9f1f17cc 1443 APT::VersionSet const verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1, select);
d9eb210e
DK
1444 for (APT::VersionSet::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver)
1445 if (DisplayRecord(CacheFile, Ver) == false)
1446 return false;
1447
1448 if (verset.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{
d9eb210e
DK
1458 pkgCacheFile CacheFile;
1459 if (unlikely(CacheFile.BuildCaches(NULL, false) == false))
1460 return false;
1461 pkgCache::GrpIterator I = CacheFile.GetPkgCache()->GrpBegin();
6293e04f
DK
1462 bool const All = _config->FindB("APT::Cache::AllNames","false");
1463
7c1133fe
AL
1464 if (CmdL.FileList[1] != 0)
1465 {
1466 for (;I.end() != true; I++)
1467 {
6293e04f
DK
1468 if (All == false && I->FirstPackage == 0)
1469 continue;
1470 if (I.FindPkg("any")->VersionList == 0)
7c1133fe 1471 continue;
7c1133fe
AL
1472 if (strncmp(I.Name(),CmdL.FileList[1],strlen(CmdL.FileList[1])) == 0)
1473 cout << I.Name() << endl;
1474 }
1475
1476 return true;
1477 }
1478
1479 // Show all pkgs
1480 for (;I.end() != true; I++)
1481 {
6293e04f
DK
1482 if (All == false && I->FirstPackage == 0)
1483 continue;
1484 if (I.FindPkg("any")->VersionList == 0)
7c1133fe
AL
1485 continue;
1486 cout << I.Name() << endl;
1487 }
1488
7e2e2d5d
AL
1489 return true;
1490}
1491 /*}}}*/
f8f410f5
AL
1492// ShowSrcPackage - Show source package records /*{{{*/
1493// ---------------------------------------------------------------------
1494/* */
1495bool ShowSrcPackage(CommandLine &CmdL)
1496{
d9eb210e
DK
1497 pkgCacheFile CacheFile;
1498 pkgSourceList *List = CacheFile.GetSourceList();
1499 if (unlikely(List == NULL))
1500 return false;
1501
f8f410f5 1502 // Create the text record parsers
d9eb210e 1503 pkgSrcRecords SrcRecs(*List);
f8f410f5
AL
1504 if (_error->PendingError() == true)
1505 return false;
1506
0458a811 1507 unsigned found = 0;
f8f410f5
AL
1508 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1509 {
aaee8293
AL
1510 SrcRecs.Restart();
1511
f8f410f5 1512 pkgSrcRecords::Parser *Parse;
0458a811
JAK
1513 unsigned found_this = 0;
1514 while ((Parse = SrcRecs.Find(*I,false)) != 0) {
1515 cout << Parse->AsStr() << endl;;
1516 found++;
1517 found_this++;
1518 }
1519 if (found_this == 0) {
1520 _error->Warning(_("Unable to locate package %s"),*I);
1521 continue;
1522 }
f8f410f5 1523 }
0458a811
JAK
1524 if (found > 0)
1525 return true;
1526 return _error->Error(_("No packages found"));
af87ab54
AL
1527}
1528 /*}}}*/
1529// Policy - Show the results of the preferences file /*{{{*/
1530// ---------------------------------------------------------------------
1531/* */
1532bool Policy(CommandLine &CmdL)
1533{
d9eb210e
DK
1534 pkgCacheFile CacheFile;
1535 pkgCache *Cache = CacheFile.GetPkgCache();
1536 pkgPolicy *Plcy = CacheFile.GetPolicy();
1537 pkgSourceList *SrcList = CacheFile.GetSourceList();
1538 if (unlikely(Cache == NULL || Plcy == NULL || SrcList == NULL))
af87ab54 1539 return false;
d9eb210e 1540
0588779f
DK
1541 /* Should the MultiArchKiller be run to see which pseudo packages for an
1542 arch all package are currently installed? Activating it gives a speed
1543 penality for no real gain beside enhanced debugging, so in general no. */
1544 if (_config->FindB("APT::Cache::Policy::DepCache", false) == true)
1545 CacheFile.GetDepCache();
1546
af87ab54
AL
1547 // Print out all of the package files
1548 if (CmdL.FileList[1] == 0)
1549 {
db0db9fe 1550 cout << _("Package files:") << endl;
d9eb210e 1551 for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F.end() == false; F++)
af87ab54
AL
1552 {
1553 // Locate the associated index files so we can derive a description
1554 pkgIndexFile *Indx;
1555 if (SrcList->FindIndex(F,Indx) == false &&
1556 _system->FindIndex(F,Indx) == false)
1557 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
78acd650
MV
1558
1559 printf("%4i %s\n",
d9eb210e 1560 Plcy->GetPriority(F),Indx->Describe(true).c_str());
af87ab54
AL
1561
1562 // Print the reference information for the package
1563 string Str = F.RelStr();
1564 if (Str.empty() == false)
1565 printf(" release %s\n",F.RelStr().c_str());
1566 if (F.Site() != 0 && F.Site()[0] != 0)
1567 printf(" origin %s\n",F.Site());
1568 }
1569
1570 // Show any packages have explicit pins
db0db9fe 1571 cout << _("Pinned packages:") << endl;
d9eb210e 1572 pkgCache::PkgIterator I = Cache->PkgBegin();
af87ab54
AL
1573 for (;I.end() != true; I++)
1574 {
d9eb210e 1575 if (Plcy->GetPriority(I) == 0)
af87ab54
AL
1576 continue;
1577
1578 // Print the package name and the version we are forcing to
75ce2062 1579 cout << " " << I.FullName(true) << " -> ";
af87ab54 1580
d9eb210e 1581 pkgCache::VerIterator V = Plcy->GetMatch(I);
af87ab54
AL
1582 if (V.end() == true)
1583 cout << _("(not found)") << endl;
1584 else
1585 cout << V.VerStr() << endl;
1586 }
1587
1588 return true;
1589 }
6293e04f
DK
1590
1591 string const myArch = _config->Find("APT::Architecture");
ca964703
DK
1592 char const * const msgInstalled = _(" Installed: ");
1593 char const * const msgCandidate = _(" Candidate: ");
1594 short const InstalledLessCandidate =
1595 mbstowcs(NULL, msgInstalled, 0) - mbstowcs(NULL, msgCandidate, 0);
1596 short const deepInstalled =
1597 (InstalledLessCandidate < 0 ? (InstalledLessCandidate*-1) : 0) - 1;
1598 short const deepCandidate =
1599 (InstalledLessCandidate > 0 ? (InstalledLessCandidate) : 0) - 1;
6293e04f 1600
af87ab54 1601 // Print out detailed information for each package
9f1f17cc 1602 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
78c32596 1603 for (APT::PackageSet::const_iterator I = pkgset.begin(); I != pkgset.end(); ++I)
af87ab54 1604 {
78c32596 1605 pkgCache::PkgIterator Pkg = I.Group().FindPkg("any");
6293e04f 1606
4c265635 1607 for (; Pkg.end() != true; Pkg = I.Group().NextPkg(Pkg)) {
803ea2a8
DK
1608 if (strcmp(Pkg.Arch(),"all") == 0)
1609 continue;
6293e04f 1610
75ce2062 1611 cout << Pkg.FullName(true) << ":" << endl;
6293e04f 1612
af87ab54 1613 // Installed version
ca964703 1614 cout << msgInstalled << OutputInDepth(deepInstalled, " ");
af87ab54
AL
1615 if (Pkg->CurrentVer == 0)
1616 cout << _("(none)") << endl;
1617 else
1618 cout << Pkg.CurrentVer().VerStr() << endl;
1619
1620 // Candidate Version
ca964703 1621 cout << msgCandidate << OutputInDepth(deepCandidate, " ");
d9eb210e 1622 pkgCache::VerIterator V = Plcy->GetCandidateVer(Pkg);
af87ab54
AL
1623 if (V.end() == true)
1624 cout << _("(none)") << endl;
1625 else
1626 cout << V.VerStr() << endl;
1627
1628 // Pinned version
d9eb210e 1629 if (Plcy->GetPriority(Pkg) != 0)
af87ab54 1630 {
db0db9fe 1631 cout << _(" Package pin: ");
d9eb210e 1632 V = Plcy->GetMatch(Pkg);
af87ab54
AL
1633 if (V.end() == true)
1634 cout << _("(not found)") << endl;
1635 else
1636 cout << V.VerStr() << endl;
1637 }
1638
1639 // Show the priority tables
db0db9fe 1640 cout << _(" Version table:") << endl;
af87ab54
AL
1641 for (V = Pkg.VersionList(); V.end() == false; V++)
1642 {
1643 if (Pkg.CurrentVer() == V)
1644 cout << " *** " << V.VerStr();
1645 else
1646 cout << " " << V.VerStr();
d9eb210e 1647 cout << " " << Plcy->GetPriority(Pkg) << endl;
af87ab54
AL
1648 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1649 {
1650 // Locate the associated index files so we can derive a description
1651 pkgIndexFile *Indx;
1652 if (SrcList->FindIndex(VF.File(),Indx) == false &&
1653 _system->FindIndex(VF.File(),Indx) == false)
1654 return _error->Error(_("Cache is out of sync, can't x-ref a package file"));
d9eb210e 1655 printf(" %4i %s\n",Plcy->GetPriority(VF.File()),
af87ab54 1656 Indx->Describe(true).c_str());
6293e04f
DK
1657 }
1658 }
1659 }
af87ab54
AL
1660 }
1661
f8f410f5
AL
1662 return true;
1663}
bd3d53ef
AL
1664 /*}}}*/
1665// Madison - Look a bit like katie's madison /*{{{*/
1666// ---------------------------------------------------------------------
1667/* */
1668bool Madison(CommandLine &CmdL)
1669{
d9eb210e
DK
1670 pkgCacheFile CacheFile;
1671 pkgSourceList *SrcList = CacheFile.GetSourceList();
bd3d53ef 1672
d9eb210e
DK
1673 if (SrcList == 0)
1674 return false;
bd3d53ef 1675
03cd434b
MV
1676 // Create the src text record parsers and ignore errors about missing
1677 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
bd3d53ef
AL
1678 pkgSrcRecords SrcRecs(*SrcList);
1679 if (_error->PendingError() == true)
03cd434b 1680 _error->Discard();
bd3d53ef 1681
9f1f17cc 1682 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
78c32596 1683 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
bd3d53ef 1684 {
bd3d53ef
AL
1685 if (Pkg.end() == false)
1686 {
1687 for (pkgCache::VerIterator V = Pkg.VersionList(); V.end() == false; V++)
1688 {
1689 for (pkgCache::VerFileIterator VF = V.FileList(); VF.end() == false; VF++)
1690 {
a0e710af
AL
1691// This might be nice, but wouldn't uniquely identify the source -mdz
1692// if (VF.File().Archive() != 0)
1693// {
1694// cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1695// << VF.File().Archive() << endl;
1696// }
1697
1698 // Locate the associated index files so we can derive a description
1699 for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); S++)
bd3d53ef 1700 {
7db98ffc
MZ
1701 vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
1702 for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
1703 IF != Indexes->end(); IF++)
1704 {
1705 if ((*IF)->FindInCache(*(VF.File().Cache())) == VF.File())
1706 {
75ce2062 1707 cout << setw(10) << Pkg.FullName(true) << " | " << setw(10) << V.VerStr() << " | "
7db98ffc
MZ
1708 << (*IF)->Describe(true) << endl;
1709 }
1710 }
bd3d53ef
AL
1711 }
1712 }
1713 }
1714 }
1715
1716
1717 SrcRecs.Restart();
1718 pkgSrcRecords::Parser *SrcParser;
78c32596 1719 while ((SrcParser = SrcRecs.Find(Pkg.Name(),false)) != 0)
bd3d53ef
AL
1720 {
1721 // Maybe support Release info here too eventually
1722 cout << setw(10) << SrcParser->Package() << " | "
1723 << setw(10) << SrcParser->Version() << " | "
1724 << SrcParser->Index().Describe(true) << endl;
1725 }
1726 }
1727
1728 return true;
1729}
f8f410f5 1730 /*}}}*/
880e9be4
AL
1731// GenCaches - Call the main cache generator /*{{{*/
1732// ---------------------------------------------------------------------
1733/* */
b0b4efb9 1734bool GenCaches(CommandLine &Cmd)
880e9be4 1735{
0a8e3465 1736 OpTextProgress Progress(*_config);
d9eb210e
DK
1737
1738 pkgCacheFile CacheFile;
1739 return CacheFile.BuildCaches(&Progress, true);
880e9be4
AL
1740}
1741 /*}}}*/
e1b74f61
AL
1742// ShowHelp - Show a help screen /*{{{*/
1743// ---------------------------------------------------------------------
1744/* */
b0b4efb9 1745bool ShowHelp(CommandLine &Cmd)
e1b74f61 1746{
5b28c804
OS
1747 ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION,
1748 COMMON_ARCH,__DATE__,__TIME__);
e1b74f61 1749
b13af988
AL
1750 if (_config->FindB("version") == true)
1751 return true;
1752
b2e465d6
AL
1753 cout <<
1754 _("Usage: apt-cache [options] command\n"
b9d2ece3 1755 " apt-cache [options] add file1 [file2 ...]\n"
b2e465d6 1756 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
2d425135 1757 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
b2e465d6
AL
1758 "\n"
1759 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1760 "cache files, and query information from them\n"
1761 "\n"
1762 "Commands:\n"
bac2e715 1763 " add - Add a package file to the source cache\n"
b2e465d6
AL
1764 " gencaches - Build both the package and source cache\n"
1765 " showpkg - Show some general information for a single package\n"
2d425135 1766 " showsrc - Show source records\n"
b2e465d6
AL
1767 " stats - Show some basic statistics\n"
1768 " dump - Show the entire file in a terse form\n"
1769 " dumpavail - Print an available file to stdout\n"
1770 " unmet - Show unmet dependencies\n"
b2e465d6
AL
1771 " search - Search the package list for a regex pattern\n"
1772 " show - Show a readable record for the package\n"
6007c1d4 1773 " showauto - Display a list of automatically installed packages\n"
b2e465d6 1774 " depends - Show raw dependency information for a package\n"
eba2b51d 1775 " rdepends - Show reverse dependency information for a package\n"
2c120e24
EL
1776 " pkgnames - List the names of all packages in the system\n"
1777 " dotty - Generate package graphs for GraphViz\n"
fff4b7f3 1778 " xvcg - Generate package graphs for xvcg\n"
eba05d54 1779 " policy - Show policy settings\n"
b2e465d6
AL
1780 "\n"
1781 "Options:\n"
1782 " -h This help text.\n"
1783 " -p=? The package cache.\n"
1784 " -s=? The source cache.\n"
1785 " -q Disable progress indicator.\n"
1786 " -i Show only important deps for the unmet command.\n"
1787 " -c=? Read this configuration file\n"
a2884e32 1788 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
b2e465d6
AL
1789 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1790 return true;
e1b74f61
AL
1791}
1792 /*}}}*/
0a8e3465
AL
1793// CacheInitialize - Initialize things for apt-cache /*{{{*/
1794// ---------------------------------------------------------------------
1795/* */
1796void CacheInitialize()
1797{
1798 _config->Set("quiet",0);
1799 _config->Set("help",false);
1800}
1801 /*}}}*/
92fcbfc1 1802int main(int argc,const char *argv[]) /*{{{*/
1164783d 1803{
08e8f724
AL
1804 CommandLine::Args Args[] = {
1805 {'h',"help","help",0},
04aa15a8 1806 {'v',"version","version",0},
e1b74f61
AL
1807 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg},
1808 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg},
1809 {'q',"quiet","quiet",CommandLine::IntLevel},
76fbce56 1810 {'i',"important","APT::Cache::Important",0},
7e2e2d5d 1811 {'f',"full","APT::Cache::ShowFull",0},
b2e465d6 1812 {'g',"generate","APT::Cache::Generate",0},
648e3cb4 1813 {'a',"all-versions","APT::Cache::AllVersions",0},
fe6fc1c2
AL
1814 {'n',"names-only","APT::Cache::NamesOnly",0},
1815 {0,"all-names","APT::Cache::AllNames",0},
b2e465d6 1816 {0,"recurse","APT::Cache::RecurseDepends",0},
f44a05ff
DK
1817 {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
1818 {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
e1b74f61
AL
1819 {'c',"config-file",0,CommandLine::ConfigFile},
1820 {'o',"option",0,CommandLine::ArbItem},
fe6fc1c2 1821 {0,"installed","APT::Cache::Installed",0},
08e8f724 1822 {0,0,0,0}};
b0b4efb9
AL
1823 CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp},
1824 {"add",&DoAdd},
1825 {"gencaches",&GenCaches},
f8f410f5 1826 {"showsrc",&ShowSrcPackage},
b0b4efb9
AL
1827 {0,0}};
1828 CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage},
1829 {"stats",&Stats},
1830 {"dump",&Dump},
1831 {"dumpavail",&DumpAvail},
1832 {"unmet",&UnMet},
9dbb421f 1833 {"search",&Search},
349cd3b8 1834 {"depends",&Depends},
eba2b51d 1835 {"rdepends",&RDepends},
3e94da1b 1836 {"dotty",&Dotty},
fff4b7f3 1837 {"xvcg",&XVcg},
7e2e2d5d 1838 {"show",&ShowPackage},
7c1133fe 1839 {"pkgnames",&ShowPkgNames},
6007c1d4 1840 {"showauto",&ShowAuto},
af87ab54 1841 {"policy",&Policy},
bd3d53ef 1842 {"madison",&Madison},
b0b4efb9 1843 {0,0}};
0a8e3465
AL
1844
1845 CacheInitialize();
67111687
AL
1846
1847 // Set up gettext support
1848 setlocale(LC_ALL,"");
1849 textdomain(PACKAGE);
1850
e1b74f61
AL
1851 // Parse the command line and initialize the package library
1852 CommandLine CmdL(Args,_config);
b2e465d6
AL
1853 if (pkgInitConfig(*_config) == false ||
1854 CmdL.Parse(argc,argv) == false ||
1855 pkgInitSystem(*_config,_system) == false)
08e8f724
AL
1856 {
1857 _error->DumpErrors();
1858 return 100;
1164783d 1859 }
8efa2a3b 1860
e1b74f61
AL
1861 // See if the help should be shown
1862 if (_config->FindB("help") == true ||
1863 CmdL.FileSize() == 0)
b2e465d6
AL
1864 {
1865 ShowHelp(CmdL);
1866 return 0;
1867 }
1868
a9a5908d 1869 // Deal with stdout not being a tty
a3f6ea20 1870 if (isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
a9a5908d
AL
1871 _config->Set("quiet","1");
1872
d9eb210e 1873// if (_config->FindB("APT::Cache::Generate",true) == false)
b0b4efb9 1874 if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false)
d9eb210e 1875 CmdL.DispatchArg(CmdsB);
f8f410f5 1876
1164783d
AL
1877 // Print any errors or warnings found during parsing
1878 if (_error->empty() == false)
1879 {
0a8e3465 1880 bool Errors = _error->PendingError();
1164783d 1881 _error->DumpErrors();
0a8e3465 1882 return Errors == true?100:0;
1164783d
AL
1883 }
1884
1885 return 0;
1886}
92fcbfc1 1887 /*}}}*/