]>
git.saurik.com Git - apt.git/blob - cmdline/apt-cache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-cache.cc,v 1.72 2004/04/30 04:34:03 mdz Exp $
4 /* ######################################################################
6 apt-cache - Manages the cache files
8 apt-cache provides some functions fo manipulating the cache files.
9 It uses the command line interface common to all the APT tools.
11 Returns 100 on failure, 0 on success.
13 ##################################################################### */
15 // Include Files /*{{{*/
18 #include <apt-pkg/algorithms.h>
19 #include <apt-pkg/cachefile.h>
20 #include <apt-pkg/cacheset.h>
21 #include <apt-pkg/cmndline.h>
22 #include <apt-pkg/error.h>
23 #include <apt-pkg/fileutl.h>
24 #include <apt-pkg/indexfile.h>
25 #include <apt-pkg/init.h>
26 #include <apt-pkg/metaindex.h>
27 #include <apt-pkg/pkgrecords.h>
28 #include <apt-pkg/pkgsystem.h>
29 #include <apt-pkg/policy.h>
30 #include <apt-pkg/progress.h>
31 #include <apt-pkg/sourcelist.h>
32 #include <apt-pkg/sptr.h>
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>
44 #include <apt-private/private-cacheset.h>
45 #include <apt-private/private-cmndline.h>
46 #include <apt-private/private-depends.h>
47 #include <apt-private/private-show.h>
48 #include <apt-private/private-search.h>
49 #include <apt-private/private-unmet.h>
50 #include <apt-private/private-main.h>
72 // DumpPackage - Show a dump of a package record /*{{{*/
73 // ---------------------------------------------------------------------
75 static bool DumpPackage(CommandLine
&CmdL
)
77 pkgCacheFile CacheFile
;
78 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
79 APT::PackageList pkgset
= APT::PackageList::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, helper
);
81 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
83 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
84 cout
<< "Versions: " << endl
;
85 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
88 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; ++Vf
)
89 cout
<< " (" << Vf
.File().FileName() << ")";
91 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; ++D
)
93 cout
<< " Description Language: " << D
.LanguageCode() << endl
94 << " File: " << D
.FileList().File().FileName() << endl
95 << " MD5: " << D
.md5() << endl
;
102 cout
<< "Reverse Depends: " << endl
;
103 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; ++D
)
105 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
107 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
112 cout
<< "Dependencies: " << endl
;
113 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
115 cout
<< Cur
.VerStr() << " - ";
116 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; ++Dep
)
117 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
121 cout
<< "Provides: " << endl
;
122 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; ++Cur
)
124 cout
<< Cur
.VerStr() << " - ";
125 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; ++Prv
)
126 cout
<< Prv
.ParentPkg().FullName(true) << " (= " << (Prv
->ProvideVersion
== 0 ? "" : Prv
.ProvideVersion()) << ") ";
129 cout
<< "Reverse Provides: " << endl
;
130 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; ++Prv
)
131 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << " (= " << (Prv
->ProvideVersion
== 0 ? "" : Prv
.ProvideVersion()) << ")"<< endl
;
137 // ShowHashTableStats - Show stats about a hashtable /*{{{*/
138 // ---------------------------------------------------------------------
140 static map_pointer_t
PackageNext(pkgCache::Package
const * const P
) { return P
->NextPackage
; }
141 static map_pointer_t
GroupNext(pkgCache::Group
const * const G
) { return G
->Next
; }
143 static void ShowHashTableStats(std::string Type
,
145 map_pointer_t
*Hashtable
,
147 map_pointer_t(*Next
)(T
const * const))
149 // hashtable stats for the HashTable
150 unsigned long NumBuckets
= Size
;
151 unsigned long UsedBuckets
= 0;
152 unsigned long UnusedBuckets
= 0;
153 unsigned long LongestBucket
= 0;
154 unsigned long ShortestBucket
= NumBuckets
;
155 unsigned long Entries
= 0;
156 for (unsigned int i
=0; i
< NumBuckets
; ++i
)
158 T
*P
= StartP
+ Hashtable
[i
];
159 if(P
== 0 || P
== StartP
)
165 unsigned long ThisBucketSize
= 0;
166 for (; P
!= StartP
; P
= StartP
+ Next(P
))
168 Entries
+= ThisBucketSize
;
169 LongestBucket
= std::max(ThisBucketSize
, LongestBucket
);
170 ShortestBucket
= std::min(ThisBucketSize
, ShortestBucket
);
172 cout
<< "Total buckets in " << Type
<< ": " << NumBuckets
<< std::endl
;
173 cout
<< " Unused: " << UnusedBuckets
<< std::endl
;
174 cout
<< " Used: " << UsedBuckets
<< std::endl
;
175 cout
<< " Utilization: " << 100.0 * UsedBuckets
/NumBuckets
<< "%" << std::endl
;
176 cout
<< " Average entries: " << Entries
/(double)UsedBuckets
<< std::endl
;
177 cout
<< " Longest: " << LongestBucket
<< std::endl
;
178 cout
<< " Shortest: " << ShortestBucket
<< std::endl
;
181 // Stats - Dump some nice statistics /*{{{*/
182 // ---------------------------------------------------------------------
184 static bool Stats(CommandLine
&CmdL
)
186 if (CmdL
.FileSize() > 1) {
187 _error
->Error(_("apt-cache stats does not take any arguments"));
191 pkgCacheFile CacheFile
;
192 pkgCache
*Cache
= CacheFile
.GetPkgCache();
194 if (unlikely(Cache
== NULL
))
197 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
198 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
199 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
200 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
207 pkgCache::PkgIterator I
= Cache
->PkgBegin();
208 for (;I
.end() != true; ++I
)
210 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
216 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
222 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
225 if (I
.ProvidesList()->NextProvides
== 0)
233 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
239 cout
<< _(" Normal packages: ") << Normal
<< endl
;
240 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
241 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
242 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
243 cout
<< _(" Missing: ") << Missing
<< endl
;
245 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
246 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
247 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
248 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
249 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< "/" << Cache
->Head().DependsDataCount
<< " (" <<
250 SizeToStr((Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) +
251 (Cache
->Head().DependsDataCount
*Cache
->Head().DependencyDataSz
)) << ')' << endl
;
252 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
253 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
254 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
255 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
256 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
257 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
260 std::set
<map_stringitem_t
> stritems
;
261 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
262 stritems
.insert(G
->Name
);
263 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
265 stritems
.insert(P
->Arch
);
266 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
269 stritems
.insert(V
->VerStr
);
271 stritems
.insert(V
->Section
);
272 stritems
.insert(V
->SourcePkgName
);
273 stritems
.insert(V
->SourceVerStr
);
274 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
277 stritems
.insert(D
->Version
);
279 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
281 stritems
.insert(D
->md5sum
);
282 stritems
.insert(D
->language_code
);
285 for (pkgCache::PrvIterator Prv
= P
.ProvidesList(); Prv
.end() == false; ++Prv
)
287 if (Prv
->ProvideVersion
!= 0)
288 stritems
.insert(Prv
->ProvideVersion
);
291 for (pkgCache::RlsFileIterator F
= Cache
->RlsFileBegin(); F
!= Cache
->RlsFileEnd(); ++F
)
293 stritems
.insert(F
->FileName
);
294 stritems
.insert(F
->Archive
);
295 stritems
.insert(F
->Codename
);
296 stritems
.insert(F
->Version
);
297 stritems
.insert(F
->Origin
);
298 stritems
.insert(F
->Label
);
299 stritems
.insert(F
->Site
);
301 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
!= Cache
->FileEnd(); ++F
)
303 stritems
.insert(F
->FileName
);
304 stritems
.insert(F
->Architecture
);
305 stritems
.insert(F
->Component
);
306 stritems
.insert(F
->IndexType
);
309 unsigned long Size
= 0;
310 for (std::set
<map_stringitem_t
>::const_iterator i
= stritems
.begin(); i
!= stritems
.end(); ++i
)
311 Size
+= strlen(Cache
->StrP
+ *i
) + 1;
312 cout
<< _("Total globbed strings: ") << stritems
.size() << " (" << SizeToStr(Size
) << ')' << endl
;
315 unsigned long Slack
= 0;
316 for (int I
= 0; I
!= 7; I
++)
317 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
318 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
320 unsigned long Total
= 0;
321 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
322 Total
= Slack
+ Size
+
323 APT_CACHESIZE(GroupCount
, GroupSz
) +
324 APT_CACHESIZE(PackageCount
, PackageSz
) +
325 APT_CACHESIZE(VersionCount
, VersionSz
) +
326 APT_CACHESIZE(DescriptionCount
, DescriptionSz
) +
327 APT_CACHESIZE(DependsCount
, DependencySz
) +
328 APT_CACHESIZE(DependsDataCount
, DependencyDataSz
) +
329 APT_CACHESIZE(ReleaseFileCount
, ReleaseFileSz
) +
330 APT_CACHESIZE(PackageFileCount
, PackageFileSz
) +
331 APT_CACHESIZE(VerFileCount
, VerFileSz
) +
332 APT_CACHESIZE(DescFileCount
, DescFileSz
) +
333 APT_CACHESIZE(ProvidesCount
, ProvidesSz
) +
334 (2 * Cache
->Head().GetHashTableSize() * sizeof(map_id_t
));
335 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
339 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->Head().PkgHashTableP(), Cache
->Head().GetHashTableSize(), PackageNext
);
340 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->Head().GrpHashTableP(), Cache
->Head().GetHashTableSize(), GroupNext
);
345 // Dump - show everything /*{{{*/
346 // ---------------------------------------------------------------------
347 /* This is worthless except fer debugging things */
348 static bool Dump(CommandLine
&)
350 pkgCacheFile CacheFile
;
351 pkgCache
*Cache
= CacheFile
.GetPkgCache();
352 if (unlikely(Cache
== NULL
))
355 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
357 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
359 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
360 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
362 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
363 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
364 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
365 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
366 DeNull(D
.TargetVer()) << std::endl
;
367 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
369 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
370 << " File: " << D
.FileList().File().FileName() << std::endl
371 << " MD5: " << D
.md5() << std::endl
;
376 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
378 std::cout
<< "File: " << F
.FileName() << std::endl
;
379 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
380 std::cout
<< " Size: " << F
->Size
<< std::endl
;
381 std::cout
<< " ID: " << F
->ID
<< std::endl
;
382 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
383 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
, true) << std::endl
;
384 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
385 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
386 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
387 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
388 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
389 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
390 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
396 // DumpAvail - Print out the available list /*{{{*/
397 // ---------------------------------------------------------------------
398 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
399 make this run really fast, perhaps I went a little overboard.. */
400 static bool DumpAvail(CommandLine
&)
402 pkgCacheFile CacheFile
;
403 pkgCache
*Cache
= CacheFile
.GetPkgCache();
404 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
407 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
408 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
409 memset(VFList
,0,sizeof(*VFList
)*Count
);
411 // Map versions that we want to write out onto the VerList array.
412 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
414 if (P
->VersionList
== 0)
417 /* Find the proper version to use. If the policy says there are no
418 possible selections we return the installed version, if available..
419 This prevents dselect from making it obsolete. */
420 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
423 if (P
->CurrentVer
== 0)
428 pkgCache::VerFileIterator VF
= V
.FileList();
429 for (; VF
.end() == false ; ++VF
)
430 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
433 /* Okay, here we have a bit of a problem.. The policy has selected the
434 currently installed package - however it only exists in the
435 status file.. We need to write out something or dselect will mark
436 the package as obsolete! Thus we emit the status file entry, but
437 below we remove the status line to make it valid for the
438 available file. However! We only do this if their do exist *any*
439 non-source versions of the package - that way the dselect obsolete
440 handling works OK. */
441 if (VF
.end() == true)
443 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
445 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
447 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
454 if (VF
.end() == false)
462 LocalitySort(VFList
,Count
,sizeof(*VFList
));
464 std::vector
<pkgTagSection::Tag
> RW
;
465 RW
.push_back(pkgTagSection::Tag::Remove("Status"));
466 RW
.push_back(pkgTagSection::Tag::Remove("Config-Version"));
468 stdoutfd
.OpenDescriptor(STDOUT_FILENO
, FileFd::WriteOnly
, false);
470 // Iterate over all the package files and write them out.
471 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
472 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
474 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
475 if (File
.IsOk() == false)
477 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
481 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
482 if (_error
->PendingError() == true)
485 /* Write all of the records from this package file, since we
486 already did locality sorting we can now just seek through the
487 file in read order. We apply 1 more optimization here, since often
488 there will be < 1 byte gaps between records (for the \n) we read that
489 into the next buffer and offset a bit.. */
490 unsigned long Pos
= 0;
493 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
496 const pkgCache::VerFile
&VF
= **J
;
498 // Read the record and then write it out again.
499 unsigned long Jitter
= VF
.Offset
- Pos
;
502 if (PkgF
.Seek(VF
.Offset
) == false)
507 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
509 Buffer
[VF
.Size
+ Jitter
] = '\n';
512 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
515 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
516 Tags
.Write(stdoutfd
, NULL
, RW
) == false ||
517 stdoutfd
.Write("\n", 1) == false)
519 _error
->Error("Internal Error, Unable to parse a package record");
525 if (stdoutfd
.Write(Buffer
+ Jitter
, VF
.Size
+ 1) == false)
529 Pos
= VF
.Offset
+ VF
.Size
;
532 if (_error
->PendingError() == true)
538 return !_error
->PendingError();
541 // xvcg - Generate a graph for xvcg /*{{{*/
542 // ---------------------------------------------------------------------
543 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
545 static bool XVcg(CommandLine
&CmdL
)
547 pkgCacheFile CacheFile
;
548 pkgCache
*Cache
= CacheFile
.GetPkgCache();
549 if (unlikely(Cache
== NULL
))
552 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
554 /* Normal packages are boxes
555 Pure Provides are triangles
557 rhomb are missing packages*/
558 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
560 /* Initialize the list of packages to show.
562 2 = To Show no recurse
563 3 = Emitted no recurse
566 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
567 enum TheFlags
{ForceNR
=(1<<0)};
568 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
569 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
570 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
572 // Show everything if no arguments given
573 if (CmdL
.FileList
[1] == 0)
574 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
577 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
579 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
582 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
584 if (Pkg
->VersionList
== 0)
587 if (Pkg
->ProvidesList
== 0)
588 ShapeMap
[Pkg
->ID
] = 0;
590 ShapeMap
[Pkg
->ID
] = 1;
595 if (Pkg
->ProvidesList
== 0)
596 ShapeMap
[Pkg
->ID
] = 2;
598 ShapeMap
[Pkg
->ID
] = 3;
602 // Load the list of packages from the command line into the show list
603 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
604 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
605 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
606 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
607 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
608 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
610 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
611 Pkg
!= pkgsets
[0].end(); ++Pkg
)
612 Show
[Pkg
->ID
] = ToShow
;
613 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
614 Pkg
!= pkgsets
[1].end(); ++Pkg
)
616 Show
[Pkg
->ID
] = ToShow
;
617 Flags
[Pkg
->ID
] |= ForceNR
;
621 cout
<< "graph: { title: \"packages\"" << endl
<<
622 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
623 "layout_downfactor: 8" << endl
;
629 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
631 // See we need to show this package
632 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
635 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
638 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
640 // Pure Provides and missing packages have no deps!
641 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
642 Show
[Pkg
->ID
] = Done
;
644 Show
[Pkg
->ID
] = DoneNR
;
647 Show
[Pkg
->ID
] = Done
;
650 // No deps to map out
651 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
654 pkgCache::VerIterator Ver
= Pkg
.VersionList();
655 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
657 // See if anything can meet this dep
658 // Walk along the actual package providing versions
660 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
661 for (pkgCache::VerIterator I
= DPkg
.VersionList();
662 I
.end() == false && Hit
== false; ++I
)
664 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
668 // Follow all provides
669 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
670 I
.end() == false && Hit
== false; ++I
)
672 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
677 // Only graph critical deps
678 if (D
.IsCritical() == true)
680 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
682 // Colour the node for recursion
683 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
685 /* If a conflicts does not meet anything in the database
686 then show the relation but do not recurse */
687 if (Hit
== false && D
.IsNegative() == true)
689 if (Show
[D
.TargetPkg()->ID
] == None
&&
690 Show
[D
.TargetPkg()->ID
] != ToShow
)
691 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
695 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
696 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
698 Show
[D
.TargetPkg()->ID
] = ToShow
;
705 case pkgCache::Dep::Conflicts
:
706 printf("label: \"conflicts\" color: lightgreen }\n");
708 case pkgCache::Dep::DpkgBreaks
:
709 printf("label: \"breaks\" color: lightgreen }\n");
711 case pkgCache::Dep::Obsoletes
:
712 printf("label: \"obsoletes\" color: lightgreen }\n");
715 case pkgCache::Dep::PreDepends
:
716 printf("label: \"predepends\" color: blue }\n");
728 /* Draw the box colours after the fact since we can not tell what colour
729 they should be until everything is finished drawing */
730 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
732 if (Show
[Pkg
->ID
] < DoneNR
)
735 if (Show
[Pkg
->ID
] == DoneNR
)
736 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
737 Shapes
[ShapeMap
[Pkg
->ID
]]);
739 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
740 Shapes
[ShapeMap
[Pkg
->ID
]]);
752 // Dotty - Generate a graph for Dotty /*{{{*/
753 // ---------------------------------------------------------------------
754 /* Dotty is the graphvis program for generating graphs. It is a fairly
755 simple queuing algorithm that just writes dependencies and nodes.
756 http://www.research.att.com/sw/tools/graphviz/ */
757 static bool Dotty(CommandLine
&CmdL
)
759 pkgCacheFile CacheFile
;
760 pkgCache
*Cache
= CacheFile
.GetPkgCache();
761 if (unlikely(Cache
== NULL
))
764 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
766 /* Normal packages are boxes
767 Pure Provides are triangles
769 Hexagons are missing packages*/
770 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
772 /* Initialize the list of packages to show.
774 2 = To Show no recurse
775 3 = Emitted no recurse
778 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
779 enum TheFlags
{ForceNR
=(1<<0)};
780 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
781 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
782 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
784 // Show everything if no arguments given
785 if (CmdL
.FileList
[1] == 0)
786 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
789 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
791 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
794 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
796 if (Pkg
->VersionList
== 0)
799 if (Pkg
->ProvidesList
== 0)
800 ShapeMap
[Pkg
->ID
] = 0;
802 ShapeMap
[Pkg
->ID
] = 1;
807 if (Pkg
->ProvidesList
== 0)
808 ShapeMap
[Pkg
->ID
] = 2;
810 ShapeMap
[Pkg
->ID
] = 3;
814 // Load the list of packages from the command line into the show list
815 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
816 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
817 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
818 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
819 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
820 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
822 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
823 Pkg
!= pkgsets
[0].end(); ++Pkg
)
824 Show
[Pkg
->ID
] = ToShow
;
825 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
826 Pkg
!= pkgsets
[1].end(); ++Pkg
)
828 Show
[Pkg
->ID
] = ToShow
;
829 Flags
[Pkg
->ID
] |= ForceNR
;
833 printf("digraph packages {\n");
834 printf("concentrate=true;\n");
835 printf("size=\"30,40\";\n");
841 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
843 // See we need to show this package
844 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
848 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
850 // Pure Provides and missing packages have no deps!
851 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
852 Show
[Pkg
->ID
] = Done
;
854 Show
[Pkg
->ID
] = DoneNR
;
857 Show
[Pkg
->ID
] = Done
;
860 // No deps to map out
861 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
864 pkgCache::VerIterator Ver
= Pkg
.VersionList();
865 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
867 // See if anything can meet this dep
868 // Walk along the actual package providing versions
870 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
871 for (pkgCache::VerIterator I
= DPkg
.VersionList();
872 I
.end() == false && Hit
== false; ++I
)
874 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
878 // Follow all provides
879 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
880 I
.end() == false && Hit
== false; ++I
)
882 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
886 // Only graph critical deps
887 if (D
.IsCritical() == true)
889 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
891 // Colour the node for recursion
892 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
894 /* If a conflicts does not meet anything in the database
895 then show the relation but do not recurse */
896 if (Hit
== false && D
.IsNegative() == true)
898 if (Show
[D
.TargetPkg()->ID
] == None
&&
899 Show
[D
.TargetPkg()->ID
] != ToShow
)
900 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
904 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
905 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
907 Show
[D
.TargetPkg()->ID
] = ToShow
;
914 case pkgCache::Dep::Conflicts
:
915 case pkgCache::Dep::Obsoletes
:
916 case pkgCache::Dep::DpkgBreaks
:
917 printf("[color=springgreen];\n");
920 case pkgCache::Dep::PreDepends
:
921 printf("[color=blue];\n");
933 /* Draw the box colours after the fact since we can not tell what colour
934 they should be until everything is finished drawing */
935 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
937 if (Show
[Pkg
->ID
] < DoneNR
)
940 // Orange box for early recursion stoppage
941 if (Show
[Pkg
->ID
] == DoneNR
)
942 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
943 Shapes
[ShapeMap
[Pkg
->ID
]]);
945 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
946 Shapes
[ShapeMap
[Pkg
->ID
]]);
956 /* ShowAuto - show automatically installed packages (sorted) {{{*/
957 static bool ShowAuto(CommandLine
&)
959 pkgCacheFile CacheFile
;
960 pkgCache
*Cache
= CacheFile
.GetPkgCache();
961 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
962 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
965 std::vector
<string
> packages
;
966 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
968 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
969 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
970 packages
.push_back(P
.Name());
972 std::sort(packages
.begin(), packages
.end());
974 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
977 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
981 // ShowPkgNames - Show package names /*{{{*/
982 // ---------------------------------------------------------------------
983 /* This does a prefix match on the first argument */
984 static bool ShowPkgNames(CommandLine
&CmdL
)
986 pkgCacheFile CacheFile
;
987 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
989 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
990 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
992 if (CmdL
.FileList
[1] != 0)
994 for (;I
.end() != true; ++I
)
996 if (All
== false && I
->FirstPackage
== 0)
998 if (I
.FindPkg("any")->VersionList
== 0)
1000 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1001 cout
<< I
.Name() << endl
;
1008 for (;I
.end() != true; ++I
)
1010 if (All
== false && I
->FirstPackage
== 0)
1012 if (I
.FindPkg("any")->VersionList
== 0)
1014 cout
<< I
.Name() << endl
;
1020 // Madison - Look a bit like katie's madison /*{{{*/
1021 // ---------------------------------------------------------------------
1023 static bool Madison(CommandLine
&CmdL
)
1025 pkgCacheFile CacheFile
;
1026 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1031 // Create the src text record parsers and ignore errors about missing
1032 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1033 pkgSrcRecords
SrcRecs(*SrcList
);
1034 if (_error
->PendingError() == true)
1037 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1038 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1040 _error
->PushToStack();
1041 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1042 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1044 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1046 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1048 // This might be nice, but wouldn't uniquely identify the source -mdz
1049 // if (VF.File().Archive() != 0)
1051 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1052 // << VF.File().Archive() << endl;
1055 // Locate the associated index files so we can derive a description
1056 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1058 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1059 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1060 IF
!= Indexes
->end(); ++IF
)
1062 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1064 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1065 << (*IF
)->Describe(true) << endl
;
1074 pkgSrcRecords::Parser
*SrcParser
;
1075 bool foundSomething
= false;
1076 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1078 foundSomething
= true;
1079 // Maybe support Release info here too eventually
1080 cout
<< setw(10) << SrcParser
->Package() << " | "
1081 << setw(10) << SrcParser
->Version() << " | "
1082 << SrcParser
->Index().Describe(true) << endl
;
1084 if (foundSomething
== true)
1085 _error
->RevertToStack();
1087 _error
->MergeWithStack();
1093 // GenCaches - Call the main cache generator /*{{{*/
1094 // ---------------------------------------------------------------------
1096 static bool GenCaches(CommandLine
&)
1098 OpTextProgress
Progress(*_config
);
1100 pkgCacheFile CacheFile
;
1101 return CacheFile
.BuildCaches(&Progress
, true);
1104 static bool ShowHelp(CommandLine
&) /*{{{*/
1107 _("Usage: apt-cache [options] command\n"
1108 " apt-cache [options] show pkg1 [pkg2 ...]\n"
1110 "apt-cache queries and displays available information about installed\n"
1111 "and installable packages. It works exclusively on the data acquired\n"
1112 "into the local cache via the 'update' command of e.g. apt-get. The\n"
1113 "displayed information may therefore be outdated if the last update was\n"
1114 "too long ago, but in exchange apt-cache works independently of the\n"
1115 "availability of the configured sources (e.g. offline).\n");
1119 static std::vector
<aptDispatchWithHelp
> GetCommands() /*{{{*/
1122 {"gencaches",&GenCaches
, nullptr},
1123 {"showsrc",&ShowSrcPackage
, _("Show source records")},
1124 {"showpkg",&DumpPackage
, nullptr},
1125 {"stats",&Stats
, nullptr},
1126 {"dump",&Dump
, nullptr},
1127 {"dumpavail",&DumpAvail
, nullptr},
1128 {"unmet",&UnMet
, nullptr},
1129 {"search",&DoSearch
, _("Search the package list for a regex pattern")},
1130 {"depends",&Depends
, _("Show raw dependency information for a package")},
1131 {"rdepends",&RDepends
, _("Show reverse dependency information for a package")},
1132 {"dotty",&Dotty
, nullptr},
1133 {"xvcg",&XVcg
, nullptr},
1134 {"show",&ShowPackage
, _("Show a readable record for the package")},
1135 {"pkgnames",&ShowPkgNames
, _("List the names of all packages in the system")},
1136 {"showauto",&ShowAuto
, nullptr},
1137 {"policy",&Policy
, _("Show policy settings")},
1138 {"madison",&Madison
, nullptr},
1139 {nullptr, nullptr, nullptr}
1143 int main(int argc
,const char *argv
[]) /*{{{*/
1145 // Parse the command line and initialize the package library
1147 auto const Cmds
= ParseCommandLine(CmdL
, APT_CMD::APT_CACHE
, &_config
, &_system
, argc
, argv
, &ShowHelp
, &GetCommands
);
1151 if (_config
->Exists("APT::Cache::Generate") == true)
1152 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1154 return DispatchCommandLine(CmdL
, Cmds
);