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