]>
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
<< " Average entries: " << Entries
/(double)NumBuckets
<< std::endl
;
176 cout
<< " Longest: " << LongestBucket
<< std::endl
;
177 cout
<< " Shortest: " << ShortestBucket
<< std::endl
;
180 // Stats - Dump some nice statistics /*{{{*/
181 // ---------------------------------------------------------------------
183 static bool Stats(CommandLine
&CmdL
)
185 if (CmdL
.FileSize() > 1) {
186 _error
->Error(_("apt-cache stats does not take any arguments"));
190 pkgCacheFile CacheFile
;
191 pkgCache
*Cache
= CacheFile
.GetPkgCache();
193 if (unlikely(Cache
== NULL
))
196 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
197 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
198 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
199 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
206 pkgCache::PkgIterator I
= Cache
->PkgBegin();
207 for (;I
.end() != true; ++I
)
209 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
215 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
221 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
224 if (I
.ProvidesList()->NextProvides
== 0)
232 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
238 cout
<< _(" Normal packages: ") << Normal
<< endl
;
239 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
240 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
241 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
242 cout
<< _(" Missing: ") << Missing
<< endl
;
244 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
245 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
246 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
247 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
248 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< "/" << Cache
->Head().DependsDataCount
<< " (" <<
249 SizeToStr((Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) +
250 (Cache
->Head().DependsDataCount
*Cache
->Head().DependencyDataSz
)) << ')' << endl
;
251 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
252 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
253 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
254 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
255 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
256 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
259 std::set
<map_stringitem_t
> stritems
;
260 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
261 stritems
.insert(G
->Name
);
262 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
264 stritems
.insert(P
->Arch
);
265 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
268 stritems
.insert(V
->VerStr
);
270 stritems
.insert(V
->Section
);
271 stritems
.insert(V
->SourcePkgName
);
272 stritems
.insert(V
->SourceVerStr
);
273 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
276 stritems
.insert(D
->Version
);
278 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
280 stritems
.insert(D
->md5sum
);
281 stritems
.insert(D
->language_code
);
284 for (pkgCache::PrvIterator Prv
= P
.ProvidesList(); Prv
.end() == false; ++Prv
)
286 if (Prv
->ProvideVersion
!= 0)
287 stritems
.insert(Prv
->ProvideVersion
);
290 for (pkgCache::RlsFileIterator F
= Cache
->RlsFileBegin(); F
!= Cache
->RlsFileEnd(); ++F
)
292 stritems
.insert(F
->FileName
);
293 stritems
.insert(F
->Archive
);
294 stritems
.insert(F
->Codename
);
295 stritems
.insert(F
->Version
);
296 stritems
.insert(F
->Origin
);
297 stritems
.insert(F
->Label
);
298 stritems
.insert(F
->Site
);
300 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
!= Cache
->FileEnd(); ++F
)
302 stritems
.insert(F
->FileName
);
303 stritems
.insert(F
->Architecture
);
304 stritems
.insert(F
->Component
);
305 stritems
.insert(F
->IndexType
);
308 unsigned long Size
= 0;
309 for (std::set
<map_stringitem_t
>::const_iterator i
= stritems
.begin(); i
!= stritems
.end(); ++i
)
310 Size
+= strlen(Cache
->StrP
+ *i
) + 1;
311 cout
<< _("Total globbed strings: ") << stritems
.size() << " (" << SizeToStr(Size
) << ')' << endl
;
314 unsigned long Slack
= 0;
315 for (int I
= 0; I
!= 7; I
++)
316 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
317 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
319 unsigned long Total
= 0;
320 #define APT_CACHESIZE(X,Y) (Cache->Head().X * Cache->Head().Y)
321 Total
= Slack
+ Size
+
322 APT_CACHESIZE(GroupCount
, GroupSz
) +
323 APT_CACHESIZE(PackageCount
, PackageSz
) +
324 APT_CACHESIZE(VersionCount
, VersionSz
) +
325 APT_CACHESIZE(DescriptionCount
, DescriptionSz
) +
326 APT_CACHESIZE(DependsCount
, DependencySz
) +
327 APT_CACHESIZE(DependsDataCount
, DependencyDataSz
) +
328 APT_CACHESIZE(ReleaseFileCount
, ReleaseFileSz
) +
329 APT_CACHESIZE(PackageFileCount
, PackageFileSz
) +
330 APT_CACHESIZE(VerFileCount
, VerFileSz
) +
331 APT_CACHESIZE(DescFileCount
, DescFileSz
) +
332 APT_CACHESIZE(ProvidesCount
, ProvidesSz
) +
333 (2 * Cache
->Head().GetHashTableSize() * sizeof(map_id_t
));
334 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
338 ShowHashTableStats
<pkgCache::Package
>("PkgHashTable", Cache
->PkgP
, Cache
->Head().PkgHashTableP(), Cache
->Head().GetHashTableSize(), PackageNext
);
339 ShowHashTableStats
<pkgCache::Group
>("GrpHashTable", Cache
->GrpP
, Cache
->Head().GrpHashTableP(), Cache
->Head().GetHashTableSize(), GroupNext
);
344 // Dump - show everything /*{{{*/
345 // ---------------------------------------------------------------------
346 /* This is worthless except fer debugging things */
347 static bool Dump(CommandLine
&)
349 pkgCacheFile CacheFile
;
350 pkgCache
*Cache
= CacheFile
.GetPkgCache();
351 if (unlikely(Cache
== NULL
))
354 std::cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< std::endl
;
356 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
358 std::cout
<< "Package: " << P
.FullName(true) << std::endl
;
359 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
361 std::cout
<< " Version: " << V
.VerStr() << std::endl
;
362 std::cout
<< " File: " << V
.FileList().File().FileName() << std::endl
;
363 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; ++D
)
364 std::cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
365 DeNull(D
.TargetVer()) << std::endl
;
366 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; ++D
)
368 std::cout
<< " Description Language: " << D
.LanguageCode() << std::endl
369 << " File: " << D
.FileList().File().FileName() << std::endl
370 << " MD5: " << D
.md5() << std::endl
;
375 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; ++F
)
377 std::cout
<< "File: " << F
.FileName() << std::endl
;
378 std::cout
<< " Type: " << F
.IndexType() << std::endl
;
379 std::cout
<< " Size: " << F
->Size
<< std::endl
;
380 std::cout
<< " ID: " << F
->ID
<< std::endl
;
381 std::cout
<< " Flags: " << F
->Flags
<< std::endl
;
382 std::cout
<< " Time: " << TimeRFC1123(F
->mtime
) << std::endl
;
383 std::cout
<< " Archive: " << DeNull(F
.Archive()) << std::endl
;
384 std::cout
<< " Component: " << DeNull(F
.Component()) << std::endl
;
385 std::cout
<< " Version: " << DeNull(F
.Version()) << std::endl
;
386 std::cout
<< " Origin: " << DeNull(F
.Origin()) << std::endl
;
387 std::cout
<< " Site: " << DeNull(F
.Site()) << std::endl
;
388 std::cout
<< " Label: " << DeNull(F
.Label()) << std::endl
;
389 std::cout
<< " Architecture: " << DeNull(F
.Architecture()) << std::endl
;
395 // DumpAvail - Print out the available list /*{{{*/
396 // ---------------------------------------------------------------------
397 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
398 make this run really fast, perhaps I went a little overboard.. */
399 static bool DumpAvail(CommandLine
&)
401 pkgCacheFile CacheFile
;
402 pkgCache
*Cache
= CacheFile
.GetPkgCache();
403 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
406 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
407 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
408 memset(VFList
,0,sizeof(*VFList
)*Count
);
410 // Map versions that we want to write out onto the VerList array.
411 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
413 if (P
->VersionList
== 0)
416 /* Find the proper version to use. If the policy says there are no
417 possible selections we return the installed version, if available..
418 This prevents dselect from making it obsolete. */
419 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
422 if (P
->CurrentVer
== 0)
427 pkgCache::VerFileIterator VF
= V
.FileList();
428 for (; VF
.end() == false ; ++VF
)
429 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
432 /* Okay, here we have a bit of a problem.. The policy has selected the
433 currently installed package - however it only exists in the
434 status file.. We need to write out something or dselect will mark
435 the package as obsolete! Thus we emit the status file entry, but
436 below we remove the status line to make it valid for the
437 available file. However! We only do this if their do exist *any*
438 non-source versions of the package - that way the dselect obsolete
439 handling works OK. */
440 if (VF
.end() == true)
442 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; ++Cur
)
444 for (VF
= Cur
.FileList(); VF
.end() == false; ++VF
)
446 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
453 if (VF
.end() == false)
461 LocalitySort(VFList
,Count
,sizeof(*VFList
));
463 std::vector
<pkgTagSection::Tag
> RW
;
464 RW
.push_back(pkgTagSection::Tag::Remove("Status"));
465 RW
.push_back(pkgTagSection::Tag::Remove("Config-Version"));
467 stdoutfd
.OpenDescriptor(STDOUT_FILENO
, FileFd::WriteOnly
, false);
469 // Iterate over all the package files and write them out.
470 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
471 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
473 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
474 if (File
.IsOk() == false)
476 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
480 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
, FileFd::Extension
);
481 if (_error
->PendingError() == true)
484 /* Write all of the records from this package file, since we
485 already did locality sorting we can now just seek through the
486 file in read order. We apply 1 more optimization here, since often
487 there will be < 1 byte gaps between records (for the \n) we read that
488 into the next buffer and offset a bit.. */
489 unsigned long Pos
= 0;
492 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
495 const pkgCache::VerFile
&VF
= **J
;
497 // Read the record and then write it out again.
498 unsigned long Jitter
= VF
.Offset
- Pos
;
501 if (PkgF
.Seek(VF
.Offset
) == false)
506 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
508 Buffer
[VF
.Size
+ Jitter
] = '\n';
511 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
514 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
515 Tags
.Write(stdoutfd
, NULL
, RW
) == false ||
516 stdoutfd
.Write("\n", 1) == false)
518 _error
->Error("Internal Error, Unable to parse a package record");
524 if (stdoutfd
.Write(Buffer
+ Jitter
, VF
.Size
+ 1) == false)
528 Pos
= VF
.Offset
+ VF
.Size
;
531 if (_error
->PendingError() == true)
537 return !_error
->PendingError();
540 // xvcg - Generate a graph for xvcg /*{{{*/
541 // ---------------------------------------------------------------------
542 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
544 static bool XVcg(CommandLine
&CmdL
)
546 pkgCacheFile CacheFile
;
547 pkgCache
*Cache
= CacheFile
.GetPkgCache();
548 if (unlikely(Cache
== NULL
))
551 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
553 /* Normal packages are boxes
554 Pure Provides are triangles
556 rhomb are missing packages*/
557 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
559 /* Initialize the list of packages to show.
561 2 = To Show no recurse
562 3 = Emitted no recurse
565 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
566 enum TheFlags
{ForceNR
=(1<<0)};
567 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
568 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
569 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
571 // Show everything if no arguments given
572 if (CmdL
.FileList
[1] == 0)
573 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
576 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
578 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
581 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
583 if (Pkg
->VersionList
== 0)
586 if (Pkg
->ProvidesList
== 0)
587 ShapeMap
[Pkg
->ID
] = 0;
589 ShapeMap
[Pkg
->ID
] = 1;
594 if (Pkg
->ProvidesList
== 0)
595 ShapeMap
[Pkg
->ID
] = 2;
597 ShapeMap
[Pkg
->ID
] = 3;
601 // Load the list of packages from the command line into the show list
602 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
603 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
604 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
605 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
606 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
607 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
609 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
610 Pkg
!= pkgsets
[0].end(); ++Pkg
)
611 Show
[Pkg
->ID
] = ToShow
;
612 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
613 Pkg
!= pkgsets
[1].end(); ++Pkg
)
615 Show
[Pkg
->ID
] = ToShow
;
616 Flags
[Pkg
->ID
] |= ForceNR
;
620 cout
<< "graph: { title: \"packages\"" << endl
<<
621 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
622 "layout_downfactor: 8" << endl
;
628 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
630 // See we need to show this package
631 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
634 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
637 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
639 // Pure Provides and missing packages have no deps!
640 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
641 Show
[Pkg
->ID
] = Done
;
643 Show
[Pkg
->ID
] = DoneNR
;
646 Show
[Pkg
->ID
] = Done
;
649 // No deps to map out
650 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
653 pkgCache::VerIterator Ver
= Pkg
.VersionList();
654 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
656 // See if anything can meet this dep
657 // Walk along the actual package providing versions
659 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
660 for (pkgCache::VerIterator I
= DPkg
.VersionList();
661 I
.end() == false && Hit
== false; ++I
)
663 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
667 // Follow all provides
668 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
669 I
.end() == false && Hit
== false; ++I
)
671 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
676 // Only graph critical deps
677 if (D
.IsCritical() == true)
679 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
681 // Colour the node for recursion
682 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
684 /* If a conflicts does not meet anything in the database
685 then show the relation but do not recurse */
686 if (Hit
== false && D
.IsNegative() == true)
688 if (Show
[D
.TargetPkg()->ID
] == None
&&
689 Show
[D
.TargetPkg()->ID
] != ToShow
)
690 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
694 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
695 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
697 Show
[D
.TargetPkg()->ID
] = ToShow
;
704 case pkgCache::Dep::Conflicts
:
705 printf("label: \"conflicts\" color: lightgreen }\n");
707 case pkgCache::Dep::DpkgBreaks
:
708 printf("label: \"breaks\" color: lightgreen }\n");
710 case pkgCache::Dep::Obsoletes
:
711 printf("label: \"obsoletes\" color: lightgreen }\n");
714 case pkgCache::Dep::PreDepends
:
715 printf("label: \"predepends\" color: blue }\n");
727 /* Draw the box colours after the fact since we can not tell what colour
728 they should be until everything is finished drawing */
729 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
731 if (Show
[Pkg
->ID
] < DoneNR
)
734 if (Show
[Pkg
->ID
] == DoneNR
)
735 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
736 Shapes
[ShapeMap
[Pkg
->ID
]]);
738 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
739 Shapes
[ShapeMap
[Pkg
->ID
]]);
751 // Dotty - Generate a graph for Dotty /*{{{*/
752 // ---------------------------------------------------------------------
753 /* Dotty is the graphvis program for generating graphs. It is a fairly
754 simple queuing algorithm that just writes dependencies and nodes.
755 http://www.research.att.com/sw/tools/graphviz/ */
756 static bool Dotty(CommandLine
&CmdL
)
758 pkgCacheFile CacheFile
;
759 pkgCache
*Cache
= CacheFile
.GetPkgCache();
760 if (unlikely(Cache
== NULL
))
763 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
765 /* Normal packages are boxes
766 Pure Provides are triangles
768 Hexagons are missing packages*/
769 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
771 /* Initialize the list of packages to show.
773 2 = To Show no recurse
774 3 = Emitted no recurse
777 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
778 enum TheFlags
{ForceNR
=(1<<0)};
779 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
780 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
781 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
783 // Show everything if no arguments given
784 if (CmdL
.FileList
[1] == 0)
785 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
788 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
790 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
793 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
795 if (Pkg
->VersionList
== 0)
798 if (Pkg
->ProvidesList
== 0)
799 ShapeMap
[Pkg
->ID
] = 0;
801 ShapeMap
[Pkg
->ID
] = 1;
806 if (Pkg
->ProvidesList
== 0)
807 ShapeMap
[Pkg
->ID
] = 2;
809 ShapeMap
[Pkg
->ID
] = 3;
813 // Load the list of packages from the command line into the show list
814 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
815 std::list
<APT::CacheSetHelper::PkgModifier
> mods
;
816 mods
.push_back(APT::CacheSetHelper::PkgModifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
817 mods
.push_back(APT::CacheSetHelper::PkgModifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
818 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
819 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0, helper
);
821 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
822 Pkg
!= pkgsets
[0].end(); ++Pkg
)
823 Show
[Pkg
->ID
] = ToShow
;
824 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
825 Pkg
!= pkgsets
[1].end(); ++Pkg
)
827 Show
[Pkg
->ID
] = ToShow
;
828 Flags
[Pkg
->ID
] |= ForceNR
;
832 printf("digraph packages {\n");
833 printf("concentrate=true;\n");
834 printf("size=\"30,40\";\n");
840 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
842 // See we need to show this package
843 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
847 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
849 // Pure Provides and missing packages have no deps!
850 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
851 Show
[Pkg
->ID
] = Done
;
853 Show
[Pkg
->ID
] = DoneNR
;
856 Show
[Pkg
->ID
] = Done
;
859 // No deps to map out
860 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
863 pkgCache::VerIterator Ver
= Pkg
.VersionList();
864 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
866 // See if anything can meet this dep
867 // Walk along the actual package providing versions
869 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
870 for (pkgCache::VerIterator I
= DPkg
.VersionList();
871 I
.end() == false && Hit
== false; ++I
)
873 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
877 // Follow all provides
878 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
879 I
.end() == false && Hit
== false; ++I
)
881 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
885 // Only graph critical deps
886 if (D
.IsCritical() == true)
888 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
890 // Colour the node for recursion
891 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
893 /* If a conflicts does not meet anything in the database
894 then show the relation but do not recurse */
895 if (Hit
== false && D
.IsNegative() == true)
897 if (Show
[D
.TargetPkg()->ID
] == None
&&
898 Show
[D
.TargetPkg()->ID
] != ToShow
)
899 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
903 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
904 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
906 Show
[D
.TargetPkg()->ID
] = ToShow
;
913 case pkgCache::Dep::Conflicts
:
914 case pkgCache::Dep::Obsoletes
:
915 case pkgCache::Dep::DpkgBreaks
:
916 printf("[color=springgreen];\n");
919 case pkgCache::Dep::PreDepends
:
920 printf("[color=blue];\n");
932 /* Draw the box colours after the fact since we can not tell what colour
933 they should be until everything is finished drawing */
934 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; ++Pkg
)
936 if (Show
[Pkg
->ID
] < DoneNR
)
939 // Orange box for early recursion stoppage
940 if (Show
[Pkg
->ID
] == DoneNR
)
941 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
942 Shapes
[ShapeMap
[Pkg
->ID
]]);
944 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
945 Shapes
[ShapeMap
[Pkg
->ID
]]);
955 /* ShowAuto - show automatically installed packages (sorted) {{{*/
956 static bool ShowAuto(CommandLine
&)
958 pkgCacheFile CacheFile
;
959 pkgCache
*Cache
= CacheFile
.GetPkgCache();
960 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
961 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
964 std::vector
<string
> packages
;
965 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
967 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
968 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
969 packages
.push_back(P
.Name());
971 std::sort(packages
.begin(), packages
.end());
973 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); ++I
)
976 _error
->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead."));
980 // ShowPkgNames - Show package names /*{{{*/
981 // ---------------------------------------------------------------------
982 /* This does a prefix match on the first argument */
983 static bool ShowPkgNames(CommandLine
&CmdL
)
985 pkgCacheFile CacheFile
;
986 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
988 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
989 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
991 if (CmdL
.FileList
[1] != 0)
993 for (;I
.end() != true; ++I
)
995 if (All
== false && I
->FirstPackage
== 0)
997 if (I
.FindPkg("any")->VersionList
== 0)
999 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1000 cout
<< I
.Name() << endl
;
1007 for (;I
.end() != true; ++I
)
1009 if (All
== false && I
->FirstPackage
== 0)
1011 if (I
.FindPkg("any")->VersionList
== 0)
1013 cout
<< I
.Name() << endl
;
1019 // Madison - Look a bit like katie's madison /*{{{*/
1020 // ---------------------------------------------------------------------
1022 static bool Madison(CommandLine
&CmdL
)
1024 pkgCacheFile CacheFile
;
1025 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1030 // Create the src text record parsers and ignore errors about missing
1031 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1032 pkgSrcRecords
SrcRecs(*SrcList
);
1033 if (_error
->PendingError() == true)
1036 APT::CacheSetHelper
helper(true, GlobalError::NOTICE
);
1037 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1039 _error
->PushToStack();
1040 APT::PackageList pkgset
= APT::PackageList::FromString(CacheFile
, *I
, helper
);
1041 for (APT::PackageList::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1043 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; ++V
)
1045 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; ++VF
)
1047 // This might be nice, but wouldn't uniquely identify the source -mdz
1048 // if (VF.File().Archive() != 0)
1050 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1051 // << VF.File().Archive() << endl;
1054 // Locate the associated index files so we can derive a description
1055 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
1057 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1058 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1059 IF
!= Indexes
->end(); ++IF
)
1061 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1063 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1064 << (*IF
)->Describe(true) << endl
;
1073 pkgSrcRecords::Parser
*SrcParser
;
1074 bool foundSomething
= false;
1075 while ((SrcParser
= SrcRecs
.Find(*I
, false)) != 0)
1077 foundSomething
= true;
1078 // Maybe support Release info here too eventually
1079 cout
<< setw(10) << SrcParser
->Package() << " | "
1080 << setw(10) << SrcParser
->Version() << " | "
1081 << SrcParser
->Index().Describe(true) << endl
;
1083 if (foundSomething
== true)
1084 _error
->RevertToStack();
1086 _error
->MergeWithStack();
1092 // GenCaches - Call the main cache generator /*{{{*/
1093 // ---------------------------------------------------------------------
1095 static bool GenCaches(CommandLine
&)
1097 OpTextProgress
Progress(*_config
);
1099 pkgCacheFile CacheFile
;
1100 return CacheFile
.BuildCaches(&Progress
, true);
1103 static bool ShowHelp(CommandLine
&) /*{{{*/
1106 _("Usage: apt-cache [options] command\n"
1107 " apt-cache [options] show pkg1 [pkg2 ...]\n"
1109 "apt-cache queries and displays available information about installed\n"
1110 "and installable packages. It works exclusively on the data acquired\n"
1111 "into the local cache via the 'update' command of e.g. apt-get. The\n"
1112 "displayed information may therefore be outdated if the last update was\n"
1113 "too long ago, but in exchange apt-cache works independently of the\n"
1114 "availability of the configured sources (e.g. offline).\n");
1118 static std::vector
<aptDispatchWithHelp
> GetCommands() /*{{{*/
1121 {"gencaches",&GenCaches
, nullptr},
1122 {"showsrc",&ShowSrcPackage
, _("Show source records")},
1123 {"showpkg",&DumpPackage
, nullptr},
1124 {"stats",&Stats
, nullptr},
1125 {"dump",&Dump
, nullptr},
1126 {"dumpavail",&DumpAvail
, nullptr},
1127 {"unmet",&UnMet
, nullptr},
1128 {"search",&DoSearch
, _("Search the package list for a regex pattern")},
1129 {"depends",&Depends
, _("Show raw dependency information for a package")},
1130 {"rdepends",&RDepends
, _("Show reverse dependency information for a package")},
1131 {"dotty",&Dotty
, nullptr},
1132 {"xvcg",&XVcg
, nullptr},
1133 {"show",&ShowPackage
, _("Show a readable record for the package")},
1134 {"pkgnames",&ShowPkgNames
, _("List the names of all packages in the system")},
1135 {"showauto",&ShowAuto
, nullptr},
1136 {"policy",&Policy
, _("Show policy settings")},
1137 {"madison",&Madison
, nullptr},
1138 {nullptr, nullptr, nullptr}
1142 int main(int argc
,const char *argv
[]) /*{{{*/
1146 // Parse the command line and initialize the package library
1148 auto const Cmds
= ParseCommandLine(CmdL
, APT_CMD::APT_CACHE
, &_config
, &_system
, argc
, argv
, &ShowHelp
, &GetCommands
);
1152 if (_config
->Exists("APT::Cache::Generate") == true)
1153 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1155 return DispatchCommandLine(CmdL
, Cmds
);