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