]>
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 /*{{{*/
16 #include <apt-pkg/error.h>
18 #include <apt-pkg/pkgcachegen.h>
19 #include <apt-pkg/cachefile.h>
20 #include <apt-pkg/init.h>
21 #include <apt-pkg/progress.h>
22 #include <apt-pkg/sourcelist.h>
23 #include <apt-pkg/cmndline.h>
24 #include <apt-pkg/strutl.h>
25 #include <apt-pkg/pkgrecords.h>
26 #include <apt-pkg/srcrecords.h>
27 #include <apt-pkg/version.h>
28 #include <apt-pkg/policy.h>
29 #include <apt-pkg/tagfile.h>
30 #include <apt-pkg/algorithms.h>
31 #include <apt-pkg/sptr.h>
50 // LocalitySort - Sort a version list by package file locality /*{{{*/
51 // ---------------------------------------------------------------------
53 int LocalityCompare(const void *a
, const void *b
)
55 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
56 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
65 if (A
->File
== B
->File
)
66 return A
->Offset
- B
->Offset
;
67 return A
->File
- B
->File
;
70 void LocalitySort(pkgCache::VerFile
**begin
,
71 unsigned long Count
,size_t Size
)
73 qsort(begin
,Count
,Size
,LocalityCompare
);
76 void LocalitySort(pkgCache::DescFile
**begin
,
77 unsigned long Count
,size_t Size
)
79 qsort(begin
,Count
,Size
,LocalityCompare
);
82 // UnMet - Show unmet dependencies /*{{{*/
83 // ---------------------------------------------------------------------
85 bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const &Important
)
88 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
91 pkgCache::DepIterator Start
;
92 pkgCache::DepIterator End
;
95 // Important deps only
96 if (Important
== true)
97 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
98 End
->Type
!= pkgCache::Dep::Depends
)
101 // Skip conflicts and replaces
102 if (End
->Type
== pkgCache::Dep::DpkgBreaks
||
103 End
->Type
== pkgCache::Dep::Replaces
||
104 End
->Type
== pkgCache::Dep::Conflicts
)
107 // Verify the or group
109 pkgCache::DepIterator RealStart
= Start
;
112 // See if this dep is Ok
113 pkgCache::Version
**VList
= Start
.AllTargets();
134 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
135 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
138 // Print out the dep type
139 cout
<< " " << End
.DepType() << ": ";
145 cout
<< Start
.TargetPkg().FullName(true);
146 if (Start
.TargetVer() != 0)
147 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
160 bool UnMet(CommandLine
&CmdL
)
162 bool const Important
= _config
->FindB("APT::Cache::Important",false);
164 pkgCacheFile CacheFile
;
165 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
168 if (CmdL
.FileSize() <= 1)
170 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; P
++)
171 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
172 if (ShowUnMet(V
, Important
) == false)
177 APT::VersionSet verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
178 for (APT::VersionSet::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
179 if (ShowUnMet(V
, Important
) == false)
185 // DumpPackage - Show a dump of a package record /*{{{*/
186 // ---------------------------------------------------------------------
188 bool DumpPackage(CommandLine
&CmdL
)
190 pkgCacheFile CacheFile
;
191 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
193 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
195 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
196 cout
<< "Versions: " << endl
;
197 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
199 cout
<< Cur
.VerStr();
200 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
201 cout
<< " (" << Vf
.File().FileName() << ")";
203 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; D
++)
205 cout
<< " Description Language: " << D
.LanguageCode() << endl
206 << " File: " << D
.FileList().File().FileName() << endl
207 << " MD5: " << D
.md5() << endl
;
214 cout
<< "Reverse Depends: " << endl
;
215 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
217 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
219 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
224 cout
<< "Dependencies: " << endl
;
225 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
227 cout
<< Cur
.VerStr() << " - ";
228 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
229 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
233 cout
<< "Provides: " << endl
;
234 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
236 cout
<< Cur
.VerStr() << " - ";
237 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
238 cout
<< Prv
.ParentPkg().FullName(true) << " ";
241 cout
<< "Reverse Provides: " << endl
;
242 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
243 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
249 // Stats - Dump some nice statistics /*{{{*/
250 // ---------------------------------------------------------------------
252 bool Stats(CommandLine
&Cmd
)
254 pkgCacheFile CacheFile
;
255 pkgCache
*Cache
= CacheFile
.GetPkgCache();
256 if (unlikely(Cache
== NULL
))
259 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
260 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
261 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
262 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
269 pkgCache::PkgIterator I
= Cache
->PkgBegin();
270 for (;I
.end() != true; I
++)
272 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
278 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
284 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
287 if (I
.ProvidesList()->NextProvides
== 0)
295 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
301 cout
<< _(" Normal packages: ") << Normal
<< endl
;
302 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
303 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
304 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
305 cout
<< _(" Missing: ") << Missing
<< endl
;
307 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
308 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
309 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
310 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
311 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
312 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
314 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
315 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
316 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
317 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
318 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
319 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
322 unsigned long Size
= 0;
323 unsigned long Count
= 0;
324 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
325 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
328 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
330 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
332 unsigned long DepVerSize
= 0;
333 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
335 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
337 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
340 DepVerSize
+= strlen(D
.TargetVer()) + 1;
344 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
346 unsigned long Slack
= 0;
347 for (int I
= 0; I
!= 7; I
++)
348 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
349 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
351 unsigned long Total
= 0;
352 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
353 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
354 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
355 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
356 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
357 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
362 // Dump - show everything /*{{{*/
363 // ---------------------------------------------------------------------
364 /* This is worthless except fer debugging things */
365 bool Dump(CommandLine
&Cmd
)
367 pkgCacheFile CacheFile
;
368 pkgCache
*Cache
= CacheFile
.GetPkgCache();
369 if (unlikely(Cache
== NULL
))
372 cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< endl
;
374 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
376 cout
<< "Package: " << P
.FullName(true) << endl
;
377 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
379 cout
<< " Version: " << V
.VerStr() << endl
;
380 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
381 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
382 cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
383 DeNull(D
.TargetVer()) << endl
;
384 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; D
++)
386 cout
<< " Description Language: " << D
.LanguageCode() << endl
387 << " File: " << D
.FileList().File().FileName() << endl
388 << " MD5: " << D
.md5() << endl
;
393 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
395 cout
<< "File: " << F
.FileName() << endl
;
396 cout
<< " Type: " << F
.IndexType() << endl
;
397 cout
<< " Size: " << F
->Size
<< endl
;
398 cout
<< " ID: " << F
->ID
<< endl
;
399 cout
<< " Flags: " << F
->Flags
<< endl
;
400 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
401 cout
<< " Archive: " << DeNull(F
.Archive()) << endl
;
402 cout
<< " Component: " << DeNull(F
.Component()) << endl
;
403 cout
<< " Version: " << DeNull(F
.Version()) << endl
;
404 cout
<< " Origin: " << DeNull(F
.Origin()) << endl
;
405 cout
<< " Site: " << DeNull(F
.Site()) << endl
;
406 cout
<< " Label: " << DeNull(F
.Label()) << endl
;
407 cout
<< " Architecture: " << DeNull(F
.Architecture()) << endl
;
413 // DumpAvail - Print out the available list /*{{{*/
414 // ---------------------------------------------------------------------
415 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
416 make this run really fast, perhaps I went a little overboard.. */
417 bool DumpAvail(CommandLine
&Cmd
)
419 pkgCacheFile CacheFile
;
420 pkgCache
*Cache
= CacheFile
.GetPkgCache();
421 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
424 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
425 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
426 memset(VFList
,0,sizeof(*VFList
)*Count
);
428 // Map versions that we want to write out onto the VerList array.
429 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
431 if (P
->VersionList
== 0)
434 /* Find the proper version to use. If the policy says there are no
435 possible selections we return the installed version, if available..
436 This prevents dselect from making it obsolete. */
437 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
440 if (P
->CurrentVer
== 0)
445 pkgCache::VerFileIterator VF
= V
.FileList();
446 for (; VF
.end() == false ; VF
++)
447 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
450 /* Okay, here we have a bit of a problem.. The policy has selected the
451 currently installed package - however it only exists in the
452 status file.. We need to write out something or dselect will mark
453 the package as obsolete! Thus we emit the status file entry, but
454 below we remove the status line to make it valid for the
455 available file. However! We only do this if their do exist *any*
456 non-source versions of the package - that way the dselect obsolete
457 handling works OK. */
458 if (VF
.end() == true)
460 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
462 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
464 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
471 if (VF
.end() == false)
479 LocalitySort(VFList
,Count
,sizeof(*VFList
));
481 // Iterate over all the package files and write them out.
482 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
483 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
485 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
486 if (File
.IsOk() == false)
488 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
492 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
493 if (_error
->PendingError() == true)
496 /* Write all of the records from this package file, since we
497 already did locality sorting we can now just seek through the
498 file in read order. We apply 1 more optimization here, since often
499 there will be < 1 byte gaps between records (for the \n) we read that
500 into the next buffer and offset a bit.. */
501 unsigned long Pos
= 0;
504 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
507 const pkgCache::VerFile
&VF
= **J
;
509 // Read the record and then write it out again.
510 unsigned long Jitter
= VF
.Offset
- Pos
;
513 if (PkgF
.Seek(VF
.Offset
) == false)
518 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
520 Buffer
[VF
.Size
+ Jitter
] = '\n';
523 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
526 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
527 const char *Zero
= 0;
528 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
529 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
531 _error
->Error("Internal Error, Unable to parse a package record");
538 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
542 Pos
= VF
.Offset
+ VF
.Size
;
546 if (_error
->PendingError() == true)
552 return !_error
->PendingError();
555 // Depends - Print out a dependency tree /*{{{*/
556 // ---------------------------------------------------------------------
558 bool Depends(CommandLine
&CmdL
)
560 pkgCacheFile CacheFile
;
561 pkgCache
*Cache
= CacheFile
.GetPkgCache();
562 if (unlikely(Cache
== NULL
))
565 SPtrArray
<unsigned> Colours
= new unsigned[Cache
->Head().PackageCount
];
566 memset(Colours
,0,sizeof(*Colours
)*Cache
->Head().PackageCount
);
568 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
569 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
570 Colours
[Pkg
->ID
] = 1;
572 bool Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
573 bool Installed
= _config
->FindB("APT::Cache::Installed",false);
574 bool Important
= _config
->FindB("APT::Cache::Important",false);
578 DidSomething
= false;
579 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
581 if (Colours
[Pkg
->ID
] != 1)
583 Colours
[Pkg
->ID
] = 2;
586 pkgCache::VerIterator Ver
= Pkg
.VersionList();
587 if (Ver
.end() == true)
589 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
593 cout
<< Pkg
.FullName(true) << endl
;
595 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
597 // Important deps only
598 if (Important
== true)
599 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
600 D
->Type
!= pkgCache::Dep::Depends
)
603 pkgCache::PkgIterator Trg
= D
.TargetPkg();
605 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
608 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
614 if (Trg
->VersionList
== 0)
615 cout
<< D
.DepType() << ": <" << Trg
.FullName(true) << ">" << endl
;
617 cout
<< D
.DepType() << ": " << Trg
.FullName(true) << endl
;
620 Colours
[D
.TargetPkg()->ID
]++;
624 // Display all solutions
625 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
626 pkgPrioSortList(*Cache
,List
);
627 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
629 pkgCache::VerIterator
V(*Cache
,*I
);
630 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
631 V
->ParentPkg
== D
->Package
)
633 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
636 Colours
[D
.ParentPkg()->ID
]++;
641 while (DidSomething
== true);
646 // RDepends - Print out a reverse dependency tree - mbc /*{{{*/
647 // ---------------------------------------------------------------------
649 bool RDepends(CommandLine
&CmdL
)
651 pkgCacheFile CacheFile
;
652 pkgCache
*Cache
= CacheFile
.GetPkgCache();
653 if (unlikely(Cache
== NULL
))
656 SPtrArray
<unsigned> Colours
= new unsigned[Cache
->Head().PackageCount
];
657 memset(Colours
,0,sizeof(*Colours
)*Cache
->Head().PackageCount
);
659 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
660 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
661 Colours
[Pkg
->ID
] = 1;
663 bool Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
664 bool Installed
= _config
->FindB("APT::Cache::Installed",false);
668 DidSomething
= false;
669 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
671 if (Colours
[Pkg
->ID
] != 1)
673 Colours
[Pkg
->ID
] = 2;
676 pkgCache::VerIterator Ver
= Pkg
.VersionList();
677 if (Ver
.end() == true)
679 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
683 cout
<< Pkg
.FullName(true) << endl
;
685 cout
<< "Reverse Depends:" << endl
;
686 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() == false; D
++)
689 pkgCache::PkgIterator Trg
= D
.ParentPkg();
691 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
694 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
699 if (Trg
->VersionList
== 0)
700 cout
<< D
.DepType() << ": <" << Trg
.FullName(true) << ">" << endl
;
702 cout
<< Trg
.FullName(true) << endl
;
705 Colours
[D
.ParentPkg()->ID
]++;
709 // Display all solutions
710 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
711 pkgPrioSortList(*Cache
,List
);
712 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
714 pkgCache::VerIterator
V(*Cache
,*I
);
715 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
716 V
->ParentPkg
== D
->Package
)
718 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
721 Colours
[D
.ParentPkg()->ID
]++;
726 while (DidSomething
== true);
731 // xvcg - Generate a graph for xvcg /*{{{*/
732 // ---------------------------------------------------------------------
733 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
735 bool XVcg(CommandLine
&CmdL
)
737 pkgCacheFile CacheFile
;
738 pkgCache
*Cache
= CacheFile
.GetPkgCache();
739 if (unlikely(Cache
== NULL
))
742 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
744 /* Normal packages are boxes
745 Pure Provides are triangles
747 rhomb are missing packages*/
748 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
750 /* Initialize the list of packages to show.
752 2 = To Show no recurse
753 3 = Emitted no recurse
756 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
757 enum TheFlags
{ForceNR
=(1<<0)};
758 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
759 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
760 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
762 // Show everything if no arguments given
763 if (CmdL
.FileList
[1] == 0)
764 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
767 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
769 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
772 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
774 if (Pkg
->VersionList
== 0)
777 if (Pkg
->ProvidesList
== 0)
778 ShapeMap
[Pkg
->ID
] = 0;
780 ShapeMap
[Pkg
->ID
] = 1;
785 if (Pkg
->ProvidesList
== 0)
786 ShapeMap
[Pkg
->ID
] = 2;
788 ShapeMap
[Pkg
->ID
] = 3;
792 // Load the list of packages from the command line into the show list
793 std::list
<APT::PackageSet::Modifier
> mods
;
794 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
795 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
796 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
797 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0);
799 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
800 Pkg
!= pkgsets
[0].end(); ++Pkg
)
801 Show
[Pkg
->ID
] = ToShow
;
802 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
803 Pkg
!= pkgsets
[1].end(); ++Pkg
)
805 Show
[Pkg
->ID
] = ToShow
;
806 Flags
[Pkg
->ID
] |= ForceNR
;
810 cout
<< "graph: { title: \"packages\"" << endl
<<
811 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
812 "layout_downfactor: 8" << endl
;
818 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
820 // See we need to show this package
821 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
824 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
827 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
829 // Pure Provides and missing packages have no deps!
830 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
831 Show
[Pkg
->ID
] = Done
;
833 Show
[Pkg
->ID
] = DoneNR
;
836 Show
[Pkg
->ID
] = Done
;
839 // No deps to map out
840 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
843 pkgCache::VerIterator Ver
= Pkg
.VersionList();
844 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
846 // See if anything can meet this dep
847 // Walk along the actual package providing versions
849 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
850 for (pkgCache::VerIterator I
= DPkg
.VersionList();
851 I
.end() == false && Hit
== false; I
++)
853 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
857 // Follow all provides
858 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
859 I
.end() == false && Hit
== false; I
++)
861 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
866 // Only graph critical deps
867 if (D
.IsCritical() == true)
869 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
871 // Colour the node for recursion
872 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
874 /* If a conflicts does not meet anything in the database
875 then show the relation but do not recurse */
877 (D
->Type
== pkgCache::Dep::Conflicts
||
878 D
->Type
== pkgCache::Dep::DpkgBreaks
||
879 D
->Type
== pkgCache::Dep::Obsoletes
))
881 if (Show
[D
.TargetPkg()->ID
] == None
&&
882 Show
[D
.TargetPkg()->ID
] != ToShow
)
883 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
887 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
888 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
890 Show
[D
.TargetPkg()->ID
] = ToShow
;
897 case pkgCache::Dep::Conflicts
:
898 printf("label: \"conflicts\" color: lightgreen }\n");
900 case pkgCache::Dep::DpkgBreaks
:
901 printf("label: \"breaks\" color: lightgreen }\n");
903 case pkgCache::Dep::Obsoletes
:
904 printf("label: \"obsoletes\" color: lightgreen }\n");
907 case pkgCache::Dep::PreDepends
:
908 printf("label: \"predepends\" color: blue }\n");
920 /* Draw the box colours after the fact since we can not tell what colour
921 they should be until everything is finished drawing */
922 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
924 if (Show
[Pkg
->ID
] < DoneNR
)
927 if (Show
[Pkg
->ID
] == DoneNR
)
928 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
929 Shapes
[ShapeMap
[Pkg
->ID
]]);
931 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
932 Shapes
[ShapeMap
[Pkg
->ID
]]);
944 // Dotty - Generate a graph for Dotty /*{{{*/
945 // ---------------------------------------------------------------------
946 /* Dotty is the graphvis program for generating graphs. It is a fairly
947 simple queuing algorithm that just writes dependencies and nodes.
948 http://www.research.att.com/sw/tools/graphviz/ */
949 bool Dotty(CommandLine
&CmdL
)
951 pkgCacheFile CacheFile
;
952 pkgCache
*Cache
= CacheFile
.GetPkgCache();
953 if (unlikely(Cache
== NULL
))
956 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
958 /* Normal packages are boxes
959 Pure Provides are triangles
961 Hexagons are missing packages*/
962 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
964 /* Initialize the list of packages to show.
966 2 = To Show no recurse
967 3 = Emitted no recurse
970 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
971 enum TheFlags
{ForceNR
=(1<<0)};
972 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
973 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
974 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
976 // Show everything if no arguments given
977 if (CmdL
.FileList
[1] == 0)
978 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
981 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
983 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
986 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
988 if (Pkg
->VersionList
== 0)
991 if (Pkg
->ProvidesList
== 0)
992 ShapeMap
[Pkg
->ID
] = 0;
994 ShapeMap
[Pkg
->ID
] = 1;
999 if (Pkg
->ProvidesList
== 0)
1000 ShapeMap
[Pkg
->ID
] = 2;
1002 ShapeMap
[Pkg
->ID
] = 3;
1006 // Load the list of packages from the command line into the show list
1007 std::list
<APT::PackageSet::Modifier
> mods
;
1008 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1009 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1010 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1011 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0);
1013 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1014 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1015 Show
[Pkg
->ID
] = ToShow
;
1016 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1017 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1019 Show
[Pkg
->ID
] = ToShow
;
1020 Flags
[Pkg
->ID
] |= ForceNR
;
1024 printf("digraph packages {\n");
1025 printf("concentrate=true;\n");
1026 printf("size=\"30,40\";\n");
1032 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1034 // See we need to show this package
1035 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1039 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1041 // Pure Provides and missing packages have no deps!
1042 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1043 Show
[Pkg
->ID
] = Done
;
1045 Show
[Pkg
->ID
] = DoneNR
;
1048 Show
[Pkg
->ID
] = Done
;
1051 // No deps to map out
1052 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1055 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1056 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
1058 // See if anything can meet this dep
1059 // Walk along the actual package providing versions
1061 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1062 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1063 I
.end() == false && Hit
== false; I
++)
1065 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1069 // Follow all provides
1070 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1071 I
.end() == false && Hit
== false; I
++)
1073 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1077 // Only graph critical deps
1078 if (D
.IsCritical() == true)
1080 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1082 // Colour the node for recursion
1083 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1085 /* If a conflicts does not meet anything in the database
1086 then show the relation but do not recurse */
1088 (D
->Type
== pkgCache::Dep::Conflicts
||
1089 D
->Type
== pkgCache::Dep::Obsoletes
))
1091 if (Show
[D
.TargetPkg()->ID
] == None
&&
1092 Show
[D
.TargetPkg()->ID
] != ToShow
)
1093 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1097 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1098 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1100 Show
[D
.TargetPkg()->ID
] = ToShow
;
1107 case pkgCache::Dep::Conflicts
:
1108 case pkgCache::Dep::Obsoletes
:
1109 printf("[color=springgreen];\n");
1112 case pkgCache::Dep::PreDepends
:
1113 printf("[color=blue];\n");
1125 /* Draw the box colours after the fact since we can not tell what colour
1126 they should be until everything is finished drawing */
1127 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1129 if (Show
[Pkg
->ID
] < DoneNR
)
1132 // Orange box for early recursion stoppage
1133 if (Show
[Pkg
->ID
] == DoneNR
)
1134 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1135 Shapes
[ShapeMap
[Pkg
->ID
]]);
1137 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1138 Shapes
[ShapeMap
[Pkg
->ID
]]);
1145 // DoAdd - Perform an adding operation /*{{{*/
1146 // ---------------------------------------------------------------------
1148 bool DoAdd(CommandLine
&CmdL
)
1150 return _error
->Error("Unimplemented");
1152 // Make sure there is at least one argument
1153 if (CmdL
.FileSize() <= 1)
1154 return _error
->Error("You must give at least one file name");
1157 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
1158 if (_error
->PendingError() == true)
1161 DynamicMMap
Map(CacheF
,MMap::Public
);
1162 if (_error
->PendingError() == true)
1165 OpTextProgress
Progress(*_config
);
1166 pkgCacheGenerator
Gen(Map
,Progress
);
1167 if (_error
->PendingError() == true)
1170 unsigned long Length
= CmdL
.FileSize() - 1;
1171 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1173 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
1174 Progress
.SubProgress(Length
);
1177 FileFd
TagF(*I
,FileFd::ReadOnly
);
1178 debListParser
Parser(TagF
);
1179 if (_error
->PendingError() == true)
1180 return _error
->Error("Problem opening %s",*I
);
1182 if (Gen
.SelectFile(*I
,"") == false)
1183 return _error
->Error("Problem with SelectFile");
1185 if (Gen
.MergeList(Parser
) == false)
1186 return _error
->Error("Problem with MergeList");
1190 GCache
= &Gen
.GetCache();
1197 // DisplayRecord - Displays the complete record for the package /*{{{*/
1198 // ---------------------------------------------------------------------
1199 /* This displays the package record from the proper package index file.
1200 It is not used by DumpAvail for performance reasons. */
1201 bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1203 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1204 if (unlikely(Cache
== NULL
))
1207 // Find an appropriate file
1208 pkgCache::VerFileIterator Vf
= V
.FileList();
1209 for (; Vf
.end() == false; Vf
++)
1210 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1212 if (Vf
.end() == true)
1215 // Check and load the package list file
1216 pkgCache::PkgFileIterator I
= Vf
.File();
1217 if (I
.IsOk() == false)
1218 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1221 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnlyGzip
) == false)
1225 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+1];
1226 Buffer
[V
.FileList()->Size
] = '\n';
1227 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
1228 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false)
1234 // Get a pointer to start of Description field
1235 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "Description:");
1237 // Write all but Description
1238 if (fwrite(Buffer
,1,DescP
- Buffer
,stdout
) < (size_t)(DescP
- Buffer
))
1244 // Show the right description
1245 pkgRecords
Recs(*Cache
);
1246 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1247 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1248 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1250 // Find the first field after the description (if there is any)
1251 for(DescP
++;DescP
!= &Buffer
[V
.FileList()->Size
];DescP
++)
1253 if(*DescP
== '\n' && *(DescP
+1) != ' ')
1255 // write the rest of the buffer
1256 const unsigned char *end
=&Buffer
[V
.FileList()->Size
];
1257 if (fwrite(DescP
,1,end
-DescP
,stdout
) < (size_t)(end
-DescP
))
1266 // write a final newline (after the description)
1276 pkgCache::DescFile
*Df
;
1280 // Search - Perform a search /*{{{*/
1281 // ---------------------------------------------------------------------
1282 /* This searches the package names and package descriptions for a pattern */
1283 bool Search(CommandLine
&CmdL
)
1285 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1286 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1287 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1289 pkgCacheFile CacheFile
;
1290 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1291 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1292 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1295 // Make sure there is at least one argument
1296 if (NumPatterns
< 1)
1297 return _error
->Error(_("You must give at least one search pattern"));
1299 // Compile the regex pattern
1300 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1301 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1302 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1304 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1308 regfree(&Patterns
[I
]);
1309 return _error
->Error("Regex compilation error");
1313 if (_error
->PendingError() == true)
1315 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1316 regfree(&Patterns
[I
]);
1320 ExDescFile
*DFList
= new ExDescFile
[Cache
->HeaderP
->GroupCount
+1];
1321 memset(DFList
,0,sizeof(*DFList
)*Cache
->HeaderP
->GroupCount
+1);
1323 // Map versions that we want to write out onto the VerList array.
1324 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1326 if (DFList
[G
->ID
].NameMatch
== true)
1329 DFList
[G
->ID
].NameMatch
= true;
1330 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1332 if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1334 DFList
[G
->ID
].NameMatch
= false;
1338 // Doing names only, drop any that dont match..
1339 if (NamesOnly
== true && DFList
[G
->ID
].NameMatch
== false)
1342 // Find the proper version to use
1343 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1344 if (P
.end() == true)
1346 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1347 if (V
.end() == false)
1348 DFList
[G
->ID
].Df
= V
.DescriptionList().FileList();
1350 if (DFList
[G
->ID
].NameMatch
== false)
1353 // Include all the packages that provide matching names too
1354 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; Prv
++)
1356 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1357 if (V
.end() == true)
1360 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1361 DFList
[id
].Df
= V
.DescriptionList().FileList();
1362 DFList
[id
].NameMatch
= true;
1366 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1368 // Create the text record parser
1369 pkgRecords
Recs(*Cache
);
1370 // Iterate over all the version records and check them
1371 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; J
++)
1373 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1375 if (J
->NameMatch
== false && NamesOnly
== false)
1377 string
const LongDesc
= P
.LongDesc();
1378 J
->NameMatch
= true;
1379 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1381 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1383 J
->NameMatch
= false;
1388 if (J
->NameMatch
== true)
1390 if (ShowFull
== true)
1394 P
.GetRec(Start
,End
);
1395 fwrite(Start
,End
-Start
,1,stdout
);
1399 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1404 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1405 regfree(&Patterns
[I
]);
1407 return _error
->Error("Write to stdout failed");
1412 /* show automatically installed packages (sorted) */
1413 bool ShowAuto(CommandLine
&CmdL
)
1415 pkgCacheFile CacheFile
;
1416 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1417 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1418 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1421 std::vector
<string
> packages
;
1422 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1424 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
1425 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1426 packages
.push_back(P
.Name());
1428 std::sort(packages
.begin(), packages
.end());
1430 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); I
++)
1436 // ShowPackage - Dump the package record to the screen /*{{{*/
1437 // ---------------------------------------------------------------------
1439 bool ShowPackage(CommandLine
&CmdL
)
1441 pkgCacheFile CacheFile
;
1442 APT::VersionSet::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1443 APT::VersionSet::ALL
: APT::VersionSet::CANDIDATE
;
1444 APT::VersionSet
const verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
);
1445 for (APT::VersionSet::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1446 if (DisplayRecord(CacheFile
, Ver
) == false)
1449 if (verset
.empty() == false)
1451 return _error
->Error(_("No packages found"));
1454 // ShowPkgNames - Show package names /*{{{*/
1455 // ---------------------------------------------------------------------
1456 /* This does a prefix match on the first argument */
1457 bool ShowPkgNames(CommandLine
&CmdL
)
1459 pkgCacheFile CacheFile
;
1460 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1462 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1463 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1465 if (CmdL
.FileList
[1] != 0)
1467 for (;I
.end() != true; I
++)
1469 if (All
== false && I
->FirstPackage
== 0)
1471 if (I
.FindPkg("any")->VersionList
== 0)
1473 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1474 cout
<< I
.Name() << endl
;
1481 for (;I
.end() != true; I
++)
1483 if (All
== false && I
->FirstPackage
== 0)
1485 if (I
.FindPkg("any")->VersionList
== 0)
1487 cout
<< I
.Name() << endl
;
1493 // ShowSrcPackage - Show source package records /*{{{*/
1494 // ---------------------------------------------------------------------
1496 bool ShowSrcPackage(CommandLine
&CmdL
)
1498 pkgCacheFile CacheFile
;
1499 pkgSourceList
*List
= CacheFile
.GetSourceList();
1500 if (unlikely(List
== NULL
))
1503 // Create the text record parsers
1504 pkgSrcRecords
SrcRecs(*List
);
1505 if (_error
->PendingError() == true)
1509 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1513 pkgSrcRecords::Parser
*Parse
;
1514 unsigned found_this
= 0;
1515 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1516 cout
<< Parse
->AsStr() << endl
;;
1520 if (found_this
== 0) {
1521 _error
->Warning(_("Unable to locate package %s"),*I
);
1527 return _error
->Error(_("No packages found"));
1530 // Policy - Show the results of the preferences file /*{{{*/
1531 // ---------------------------------------------------------------------
1533 bool Policy(CommandLine
&CmdL
)
1535 pkgCacheFile CacheFile
;
1536 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1537 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1538 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1539 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1542 /* Should the MultiArchKiller be run to see which pseudo packages for an
1543 arch all package are currently installed? Activating it gives a speed
1544 penality for no real gain beside enhanced debugging, so in general no. */
1545 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1546 CacheFile
.GetDepCache();
1548 // Print out all of the package files
1549 if (CmdL
.FileList
[1] == 0)
1551 cout
<< _("Package files:") << endl
;
1552 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
1554 // Locate the associated index files so we can derive a description
1556 if (SrcList
->FindIndex(F
,Indx
) == false &&
1557 _system
->FindIndex(F
,Indx
) == false)
1558 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1561 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1563 // Print the reference information for the package
1564 string Str
= F
.RelStr();
1565 if (Str
.empty() == false)
1566 printf(" release %s\n",F
.RelStr().c_str());
1567 if (F
.Site() != 0 && F
.Site()[0] != 0)
1568 printf(" origin %s\n",F
.Site());
1571 // Show any packages have explicit pins
1572 cout
<< _("Pinned packages:") << endl
;
1573 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1574 for (;I
.end() != true; I
++)
1576 if (Plcy
->GetPriority(I
) == 0)
1579 // Print the package name and the version we are forcing to
1580 cout
<< " " << I
.FullName(true) << " -> ";
1582 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1583 if (V
.end() == true)
1584 cout
<< _("(not found)") << endl
;
1586 cout
<< V
.VerStr() << endl
;
1592 string
const myArch
= _config
->Find("APT::Architecture");
1593 char const * const msgInstalled
= _(" Installed: ");
1594 char const * const msgCandidate
= _(" Candidate: ");
1595 short const InstalledLessCandidate
=
1596 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1597 short const deepInstalled
=
1598 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1599 short const deepCandidate
=
1600 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1602 // Print out detailed information for each package
1603 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
1604 for (APT::PackageSet::const_iterator I
= pkgset
.begin(); I
!= pkgset
.end(); ++I
)
1606 pkgCache::PkgIterator Pkg
= I
.Group().FindPkg("any");
1608 for (; Pkg
.end() != true; Pkg
= I
.Group().NextPkg(Pkg
)) {
1609 if (strcmp(Pkg
.Arch(),"all") == 0)
1612 cout
<< Pkg
.FullName(true) << ":" << endl
;
1614 // Installed version
1615 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1616 if (Pkg
->CurrentVer
== 0)
1617 cout
<< _("(none)") << endl
;
1619 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1621 // Candidate Version
1622 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1623 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1624 if (V
.end() == true)
1625 cout
<< _("(none)") << endl
;
1627 cout
<< V
.VerStr() << endl
;
1630 if (Plcy
->GetPriority(Pkg
) != 0)
1632 cout
<< _(" Package pin: ");
1633 V
= Plcy
->GetMatch(Pkg
);
1634 if (V
.end() == true)
1635 cout
<< _("(not found)") << endl
;
1637 cout
<< V
.VerStr() << endl
;
1640 // Show the priority tables
1641 cout
<< _(" Version table:") << endl
;
1642 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1644 if (Pkg
.CurrentVer() == V
)
1645 cout
<< " *** " << V
.VerStr();
1647 cout
<< " " << V
.VerStr();
1648 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1649 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1651 // Locate the associated index files so we can derive a description
1653 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1654 _system
->FindIndex(VF
.File(),Indx
) == false)
1655 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1656 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1657 Indx
->Describe(true).c_str());
1666 // Madison - Look a bit like katie's madison /*{{{*/
1667 // ---------------------------------------------------------------------
1669 bool Madison(CommandLine
&CmdL
)
1671 pkgCacheFile CacheFile
;
1672 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1677 // Create the src text record parsers and ignore errors about missing
1678 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1679 pkgSrcRecords
SrcRecs(*SrcList
);
1680 if (_error
->PendingError() == true)
1683 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
1684 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1686 if (Pkg
.end() == false)
1688 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; V
++)
1690 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1692 // This might be nice, but wouldn't uniquely identify the source -mdz
1693 // if (VF.File().Archive() != 0)
1695 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1696 // << VF.File().Archive() << endl;
1699 // Locate the associated index files so we can derive a description
1700 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); S
++)
1702 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1703 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1704 IF
!= Indexes
->end(); IF
++)
1706 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1708 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1709 << (*IF
)->Describe(true) << endl
;
1719 pkgSrcRecords::Parser
*SrcParser
;
1720 while ((SrcParser
= SrcRecs
.Find(Pkg
.Name(),false)) != 0)
1722 // Maybe support Release info here too eventually
1723 cout
<< setw(10) << SrcParser
->Package() << " | "
1724 << setw(10) << SrcParser
->Version() << " | "
1725 << SrcParser
->Index().Describe(true) << endl
;
1732 // GenCaches - Call the main cache generator /*{{{*/
1733 // ---------------------------------------------------------------------
1735 bool GenCaches(CommandLine
&Cmd
)
1737 OpTextProgress
Progress(*_config
);
1739 pkgCacheFile CacheFile
;
1740 return CacheFile
.BuildCaches(&Progress
, true);
1743 // ShowHelp - Show a help screen /*{{{*/
1744 // ---------------------------------------------------------------------
1746 bool ShowHelp(CommandLine
&Cmd
)
1748 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1749 COMMON_ARCH
,__DATE__
,__TIME__
);
1751 if (_config
->FindB("version") == true)
1755 _("Usage: apt-cache [options] command\n"
1756 " apt-cache [options] add file1 [file2 ...]\n"
1757 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1758 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1760 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1761 "cache files, and query information from them\n"
1764 " add - Add a package file to the source cache\n"
1765 " gencaches - Build both the package and source cache\n"
1766 " showpkg - Show some general information for a single package\n"
1767 " showsrc - Show source records\n"
1768 " stats - Show some basic statistics\n"
1769 " dump - Show the entire file in a terse form\n"
1770 " dumpavail - Print an available file to stdout\n"
1771 " unmet - Show unmet dependencies\n"
1772 " search - Search the package list for a regex pattern\n"
1773 " show - Show a readable record for the package\n"
1774 " showauto - Display a list of automatically installed packages\n"
1775 " depends - Show raw dependency information for a package\n"
1776 " rdepends - Show reverse dependency information for a package\n"
1777 " pkgnames - List the names of all packages in the system\n"
1778 " dotty - Generate package graphs for GraphViz\n"
1779 " xvcg - Generate package graphs for xvcg\n"
1780 " policy - Show policy settings\n"
1783 " -h This help text.\n"
1784 " -p=? The package cache.\n"
1785 " -s=? The source cache.\n"
1786 " -q Disable progress indicator.\n"
1787 " -i Show only important deps for the unmet command.\n"
1788 " -c=? Read this configuration file\n"
1789 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1790 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1794 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1795 // ---------------------------------------------------------------------
1797 void CacheInitialize()
1799 _config
->Set("quiet",0);
1800 _config
->Set("help",false);
1803 int main(int argc
,const char *argv
[]) /*{{{*/
1805 CommandLine::Args Args
[] = {
1806 {'h',"help","help",0},
1807 {'v',"version","version",0},
1808 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1809 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1810 {'q',"quiet","quiet",CommandLine::IntLevel
},
1811 {'i',"important","APT::Cache::Important",0},
1812 {'f',"full","APT::Cache::ShowFull",0},
1813 {'g',"generate","APT::Cache::Generate",0},
1814 {'a',"all-versions","APT::Cache::AllVersions",0},
1815 {'n',"names-only","APT::Cache::NamesOnly",0},
1816 {0,"all-names","APT::Cache::AllNames",0},
1817 {0,"recurse","APT::Cache::RecurseDepends",0},
1818 {'t',"target-release","APT::Default-Release",CommandLine::HasArg
},
1819 {'t',"default-release","APT::Default-Release",CommandLine::HasArg
},
1820 {'c',"config-file",0,CommandLine::ConfigFile
},
1821 {'o',"option",0,CommandLine::ArbItem
},
1822 {0,"installed","APT::Cache::Installed",0},
1824 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1826 {"gencaches",&GenCaches
},
1827 {"showsrc",&ShowSrcPackage
},
1829 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1832 {"dumpavail",&DumpAvail
},
1835 {"depends",&Depends
},
1836 {"rdepends",&RDepends
},
1839 {"show",&ShowPackage
},
1840 {"pkgnames",&ShowPkgNames
},
1841 {"showauto",&ShowAuto
},
1843 {"madison",&Madison
},
1848 // Set up gettext support
1849 setlocale(LC_ALL
,"");
1850 textdomain(PACKAGE
);
1852 // Parse the command line and initialize the package library
1853 CommandLine
CmdL(Args
,_config
);
1854 if (pkgInitConfig(*_config
) == false ||
1855 CmdL
.Parse(argc
,argv
) == false ||
1856 pkgInitSystem(*_config
,_system
) == false)
1858 _error
->DumpErrors();
1862 // See if the help should be shown
1863 if (_config
->FindB("help") == true ||
1864 CmdL
.FileSize() == 0)
1870 // Deal with stdout not being a tty
1871 if (!isatty(STDOUT_FILENO
) && _config
->FindI("quiet", -1) == -1)
1872 _config
->Set("quiet","1");
1874 if (_config
->Exists("APT::Cache::Generate") == true)
1875 _config
->Set("pkgCacheFile::Generate", _config
->FindB("APT::Cache::Generate", true));
1877 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1878 CmdL
.DispatchArg(CmdsB
);
1880 // Print any errors or warnings found during parsing
1881 bool const Errors
= _error
->PendingError();
1882 if (_config
->FindI("quiet",0) > 0)
1883 _error
->DumpErrors();
1885 _error
->DumpErrors(GlobalError::DEBUG
);
1886 return Errors
== true ? 100 : 0;