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