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