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