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