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