]>
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>
32 #include <apt-pkg/cacheset.h>
49 // LocalitySort - Sort a version list by package file locality /*{{{*/
50 // ---------------------------------------------------------------------
52 int LocalityCompare(const void *a
, const void *b
)
54 pkgCache::VerFile
*A
= *(pkgCache::VerFile
**)a
;
55 pkgCache::VerFile
*B
= *(pkgCache::VerFile
**)b
;
64 if (A
->File
== B
->File
)
65 return A
->Offset
- B
->Offset
;
66 return A
->File
- B
->File
;
69 void LocalitySort(pkgCache::VerFile
**begin
,
70 unsigned long Count
,size_t Size
)
72 qsort(begin
,Count
,Size
,LocalityCompare
);
75 void LocalitySort(pkgCache::DescFile
**begin
,
76 unsigned long Count
,size_t Size
)
78 qsort(begin
,Count
,Size
,LocalityCompare
);
81 // UnMet - Show unmet dependencies /*{{{*/
82 // ---------------------------------------------------------------------
84 bool ShowUnMet(pkgCache::VerIterator
const &V
, bool const &Important
)
87 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false;)
90 pkgCache::DepIterator Start
;
91 pkgCache::DepIterator End
;
94 // Important deps only
95 if (Important
== true)
96 if (End
->Type
!= pkgCache::Dep::PreDepends
&&
97 End
->Type
!= pkgCache::Dep::Depends
)
100 // Skip conflicts and replaces
101 if (End
->Type
== pkgCache::Dep::DpkgBreaks
||
102 End
->Type
== pkgCache::Dep::Replaces
||
103 End
->Type
== pkgCache::Dep::Conflicts
)
106 // Verify the or group
108 pkgCache::DepIterator RealStart
= Start
;
111 // See if this dep is Ok
112 pkgCache::Version
**VList
= Start
.AllTargets();
133 ioprintf(cout
,_("Package %s version %s has an unmet dep:\n"),
134 V
.ParentPkg().FullName(true).c_str(),V
.VerStr());
137 // Print out the dep type
138 cout
<< " " << End
.DepType() << ": ";
144 cout
<< Start
.TargetPkg().FullName(true);
145 if (Start
.TargetVer() != 0)
146 cout
<< " (" << Start
.CompType() << " " << Start
.TargetVer() <<
159 bool UnMet(CommandLine
&CmdL
)
161 bool const Important
= _config
->FindB("APT::Cache::Important",false);
163 pkgCacheFile CacheFile
;
164 if (unlikely(CacheFile
.GetPkgCache() == NULL
))
167 if (CmdL
.FileSize() <= 1)
169 for (pkgCache::PkgIterator P
= CacheFile
.GetPkgCache()->PkgBegin(); P
.end() == false; P
++)
170 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
171 if (ShowUnMet(V
, Important
) == false)
176 APT::VersionSet verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
177 for (APT::VersionSet::iterator V
= verset
.begin(); V
!= verset
.end(); ++V
)
178 if (ShowUnMet(V
, Important
) == false)
184 // DumpPackage - Show a dump of a package record /*{{{*/
185 // ---------------------------------------------------------------------
187 bool DumpPackage(CommandLine
&CmdL
)
189 pkgCacheFile CacheFile
;
190 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
192 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
194 cout
<< "Package: " << Pkg
.FullName(true) << endl
;
195 cout
<< "Versions: " << endl
;
196 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
198 cout
<< Cur
.VerStr();
199 for (pkgCache::VerFileIterator Vf
= Cur
.FileList(); Vf
.end() == false; Vf
++)
200 cout
<< " (" << Vf
.File().FileName() << ")";
202 for (pkgCache::DescIterator D
= Cur
.DescriptionList(); D
.end() == false; D
++)
204 cout
<< " Description Language: " << D
.LanguageCode() << endl
205 << " File: " << D
.FileList().File().FileName() << endl
206 << " MD5: " << D
.md5() << endl
;
213 cout
<< "Reverse Depends: " << endl
;
214 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() != true; D
++)
216 cout
<< " " << D
.ParentPkg().FullName(true) << ',' << D
.TargetPkg().FullName(true);
218 cout
<< ' ' << DeNull(D
.TargetVer()) << endl
;
223 cout
<< "Dependencies: " << endl
;
224 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
226 cout
<< Cur
.VerStr() << " - ";
227 for (pkgCache::DepIterator Dep
= Cur
.DependsList(); Dep
.end() != true; Dep
++)
228 cout
<< Dep
.TargetPkg().FullName(true) << " (" << (int)Dep
->CompareOp
<< " " << DeNull(Dep
.TargetVer()) << ") ";
232 cout
<< "Provides: " << endl
;
233 for (pkgCache::VerIterator Cur
= Pkg
.VersionList(); Cur
.end() != true; Cur
++)
235 cout
<< Cur
.VerStr() << " - ";
236 for (pkgCache::PrvIterator Prv
= Cur
.ProvidesList(); Prv
.end() != true; Prv
++)
237 cout
<< Prv
.ParentPkg().FullName(true) << " ";
240 cout
<< "Reverse Provides: " << endl
;
241 for (pkgCache::PrvIterator Prv
= Pkg
.ProvidesList(); Prv
.end() != true; Prv
++)
242 cout
<< Prv
.OwnerPkg().FullName(true) << " " << Prv
.OwnerVer().VerStr() << endl
;
248 // Stats - Dump some nice statistics /*{{{*/
249 // ---------------------------------------------------------------------
251 bool Stats(CommandLine
&Cmd
)
253 pkgCacheFile CacheFile
;
254 pkgCache
*Cache
= CacheFile
.GetPkgCache();
255 if (unlikely(Cache
== NULL
))
258 cout
<< _("Total package names: ") << Cache
->Head().GroupCount
<< " (" <<
259 SizeToStr(Cache
->Head().GroupCount
*Cache
->Head().GroupSz
) << ')' << endl
260 << _("Total package structures: ") << Cache
->Head().PackageCount
<< " (" <<
261 SizeToStr(Cache
->Head().PackageCount
*Cache
->Head().PackageSz
) << ')' << endl
;
268 pkgCache::PkgIterator I
= Cache
->PkgBegin();
269 for (;I
.end() != true; I
++)
271 if (I
->VersionList
!= 0 && I
->ProvidesList
== 0)
277 if (I
->VersionList
!= 0 && I
->ProvidesList
!= 0)
283 if (I
->VersionList
== 0 && I
->ProvidesList
!= 0)
286 if (I
.ProvidesList()->NextProvides
== 0)
294 if (I
->VersionList
== 0 && I
->ProvidesList
== 0)
300 cout
<< _(" Normal packages: ") << Normal
<< endl
;
301 cout
<< _(" Pure virtual packages: ") << Virtual
<< endl
;
302 cout
<< _(" Single virtual packages: ") << DVirt
<< endl
;
303 cout
<< _(" Mixed virtual packages: ") << NVirt
<< endl
;
304 cout
<< _(" Missing: ") << Missing
<< endl
;
306 cout
<< _("Total distinct versions: ") << Cache
->Head().VersionCount
<< " (" <<
307 SizeToStr(Cache
->Head().VersionCount
*Cache
->Head().VersionSz
) << ')' << endl
;
308 cout
<< _("Total distinct descriptions: ") << Cache
->Head().DescriptionCount
<< " (" <<
309 SizeToStr(Cache
->Head().DescriptionCount
*Cache
->Head().DescriptionSz
) << ')' << endl
;
310 cout
<< _("Total dependencies: ") << Cache
->Head().DependsCount
<< " (" <<
311 SizeToStr(Cache
->Head().DependsCount
*Cache
->Head().DependencySz
) << ')' << endl
;
313 cout
<< _("Total ver/file relations: ") << Cache
->Head().VerFileCount
<< " (" <<
314 SizeToStr(Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
) << ')' << endl
;
315 cout
<< _("Total Desc/File relations: ") << Cache
->Head().DescFileCount
<< " (" <<
316 SizeToStr(Cache
->Head().DescFileCount
*Cache
->Head().DescFileSz
) << ')' << endl
;
317 cout
<< _("Total Provides mappings: ") << Cache
->Head().ProvidesCount
<< " (" <<
318 SizeToStr(Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
) << ')' << endl
;
321 unsigned long Size
= 0;
322 unsigned long Count
= 0;
323 for (pkgCache::StringItem
*I
= Cache
->StringItemP
+ Cache
->Head().StringList
;
324 I
!= Cache
->StringItemP
; I
= Cache
->StringItemP
+ I
->NextItem
)
327 Size
+= strlen(Cache
->StrP
+ I
->String
) + 1;
329 cout
<< _("Total globbed strings: ") << Count
<< " (" << SizeToStr(Size
) << ')' << endl
;
331 unsigned long DepVerSize
= 0;
332 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
334 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
336 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
339 DepVerSize
+= strlen(D
.TargetVer()) + 1;
343 cout
<< _("Total dependency version space: ") << SizeToStr(DepVerSize
) << endl
;
345 unsigned long Slack
= 0;
346 for (int I
= 0; I
!= 7; I
++)
347 Slack
+= Cache
->Head().Pools
[I
].ItemSize
*Cache
->Head().Pools
[I
].Count
;
348 cout
<< _("Total slack space: ") << SizeToStr(Slack
) << endl
;
350 unsigned long Total
= 0;
351 Total
= Slack
+ Size
+ Cache
->Head().DependsCount
*Cache
->Head().DependencySz
+
352 Cache
->Head().VersionCount
*Cache
->Head().VersionSz
+
353 Cache
->Head().PackageCount
*Cache
->Head().PackageSz
+
354 Cache
->Head().VerFileCount
*Cache
->Head().VerFileSz
+
355 Cache
->Head().ProvidesCount
*Cache
->Head().ProvidesSz
;
356 cout
<< _("Total space accounted for: ") << SizeToStr(Total
) << endl
;
361 // Dump - show everything /*{{{*/
362 // ---------------------------------------------------------------------
363 /* This is worthless except fer debugging things */
364 bool Dump(CommandLine
&Cmd
)
366 pkgCacheFile CacheFile
;
367 pkgCache
*Cache
= CacheFile
.GetPkgCache();
368 if (unlikely(Cache
== NULL
))
371 cout
<< "Using Versioning System: " << Cache
->VS
->Label
<< endl
;
373 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
375 cout
<< "Package: " << P
.FullName(true) << endl
;
376 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; V
++)
378 cout
<< " Version: " << V
.VerStr() << endl
;
379 cout
<< " File: " << V
.FileList().File().FileName() << endl
;
380 for (pkgCache::DepIterator D
= V
.DependsList(); D
.end() == false; D
++)
381 cout
<< " Depends: " << D
.TargetPkg().FullName(true) << ' ' <<
382 DeNull(D
.TargetVer()) << endl
;
383 for (pkgCache::DescIterator D
= V
.DescriptionList(); D
.end() == false; D
++)
385 cout
<< " Description Language: " << D
.LanguageCode() << endl
386 << " File: " << D
.FileList().File().FileName() << endl
387 << " MD5: " << D
.md5() << endl
;
392 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
394 cout
<< "File: " << F
.FileName() << endl
;
395 cout
<< " Type: " << F
.IndexType() << endl
;
396 cout
<< " Size: " << F
->Size
<< endl
;
397 cout
<< " ID: " << F
->ID
<< endl
;
398 cout
<< " Flags: " << F
->Flags
<< endl
;
399 cout
<< " Time: " << TimeRFC1123(F
->mtime
) << endl
;
400 cout
<< " Archive: " << DeNull(F
.Archive()) << endl
;
401 cout
<< " Component: " << DeNull(F
.Component()) << endl
;
402 cout
<< " Version: " << DeNull(F
.Version()) << endl
;
403 cout
<< " Origin: " << DeNull(F
.Origin()) << endl
;
404 cout
<< " Site: " << DeNull(F
.Site()) << endl
;
405 cout
<< " Label: " << DeNull(F
.Label()) << endl
;
406 cout
<< " Architecture: " << DeNull(F
.Architecture()) << endl
;
412 // DumpAvail - Print out the available list /*{{{*/
413 // ---------------------------------------------------------------------
414 /* This is needed to make dpkg --merge happy.. I spent a bit of time to
415 make this run really fast, perhaps I went a little overboard.. */
416 bool DumpAvail(CommandLine
&Cmd
)
418 pkgCacheFile CacheFile
;
419 pkgCache
*Cache
= CacheFile
.GetPkgCache();
420 if (unlikely(Cache
== NULL
|| CacheFile
.BuildPolicy() == false))
423 unsigned long Count
= Cache
->HeaderP
->PackageCount
+1;
424 pkgCache::VerFile
**VFList
= new pkgCache::VerFile
*[Count
];
425 memset(VFList
,0,sizeof(*VFList
)*Count
);
427 // Map versions that we want to write out onto the VerList array.
428 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
430 if (P
->VersionList
== 0)
433 /* Find the proper version to use. If the policy says there are no
434 possible selections we return the installed version, if available..
435 This prevents dselect from making it obsolete. */
436 pkgCache::VerIterator V
= CacheFile
.GetPolicy()->GetCandidateVer(P
);
439 if (P
->CurrentVer
== 0)
444 pkgCache::VerFileIterator VF
= V
.FileList();
445 for (; VF
.end() == false ; VF
++)
446 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
449 /* Okay, here we have a bit of a problem.. The policy has selected the
450 currently installed package - however it only exists in the
451 status file.. We need to write out something or dselect will mark
452 the package as obsolete! Thus we emit the status file entry, but
453 below we remove the status line to make it valid for the
454 available file. However! We only do this if their do exist *any*
455 non-source versions of the package - that way the dselect obsolete
456 handling works OK. */
457 if (VF
.end() == true)
459 for (pkgCache::VerIterator Cur
= P
.VersionList(); Cur
.end() != true; Cur
++)
461 for (VF
= Cur
.FileList(); VF
.end() == false; VF
++)
463 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
470 if (VF
.end() == false)
478 LocalitySort(VFList
,Count
,sizeof(*VFList
));
480 // Iterate over all the package files and write them out.
481 char *Buffer
= new char[Cache
->HeaderP
->MaxVerFileSize
+10];
482 for (pkgCache::VerFile
**J
= VFList
; *J
!= 0;)
484 pkgCache::PkgFileIterator
File(*Cache
,(*J
)->File
+ Cache
->PkgFileP
);
485 if (File
.IsOk() == false)
487 _error
->Error(_("Package file %s is out of sync."),File
.FileName());
491 FileFd
PkgF(File
.FileName(),FileFd::ReadOnly
);
492 if (_error
->PendingError() == true)
495 /* Write all of the records from this package file, since we
496 already did locality sorting we can now just seek through the
497 file in read order. We apply 1 more optimization here, since often
498 there will be < 1 byte gaps between records (for the \n) we read that
499 into the next buffer and offset a bit.. */
500 unsigned long Pos
= 0;
503 if ((*J
)->File
+ Cache
->PkgFileP
!= File
)
506 const pkgCache::VerFile
&VF
= **J
;
508 // Read the record and then write it out again.
509 unsigned long Jitter
= VF
.Offset
- Pos
;
512 if (PkgF
.Seek(VF
.Offset
) == false)
517 if (PkgF
.Read(Buffer
,VF
.Size
+ Jitter
) == false)
519 Buffer
[VF
.Size
+ Jitter
] = '\n';
522 if ((File
->Flags
& pkgCache::Flag::NotSource
) == pkgCache::Flag::NotSource
)
525 TFRewriteData RW
[] = {{"Status",0},{"Config-Version",0},{}};
526 const char *Zero
= 0;
527 if (Tags
.Scan(Buffer
+Jitter
,VF
.Size
+1) == false ||
528 TFRewrite(stdout
,Tags
,&Zero
,RW
) == false)
530 _error
->Error("Internal Error, Unable to parse a package record");
537 if (fwrite(Buffer
+Jitter
,VF
.Size
+1,1,stdout
) != 1)
541 Pos
= VF
.Offset
+ VF
.Size
;
545 if (_error
->PendingError() == true)
551 return !_error
->PendingError();
554 // Depends - Print out a dependency tree /*{{{*/
555 // ---------------------------------------------------------------------
557 bool Depends(CommandLine
&CmdL
)
559 pkgCacheFile CacheFile
;
560 pkgCache
*Cache
= CacheFile
.GetPkgCache();
561 if (unlikely(Cache
== NULL
))
564 SPtrArray
<unsigned> Colours
= new unsigned[Cache
->Head().PackageCount
];
565 memset(Colours
,0,sizeof(*Colours
)*Cache
->Head().PackageCount
);
567 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
568 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
569 Colours
[Pkg
->ID
] = 1;
571 bool Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
572 bool Installed
= _config
->FindB("APT::Cache::Installed",false);
573 bool Important
= _config
->FindB("APT::Cache::Important",false);
577 DidSomething
= false;
578 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
580 if (Colours
[Pkg
->ID
] != 1)
582 Colours
[Pkg
->ID
] = 2;
585 pkgCache::VerIterator Ver
= Pkg
.VersionList();
586 if (Ver
.end() == true)
588 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
592 cout
<< Pkg
.FullName(true) << endl
;
594 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
596 // Important deps only
597 if (Important
== true)
598 if (D
->Type
!= pkgCache::Dep::PreDepends
&&
599 D
->Type
!= pkgCache::Dep::Depends
)
602 pkgCache::PkgIterator Trg
= D
.TargetPkg();
604 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
607 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
613 if (Trg
->VersionList
== 0)
614 cout
<< D
.DepType() << ": <" << Trg
.FullName(true) << ">" << endl
;
616 cout
<< D
.DepType() << ": " << Trg
.FullName(true) << endl
;
619 Colours
[D
.TargetPkg()->ID
]++;
623 // Display all solutions
624 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
625 pkgPrioSortList(*Cache
,List
);
626 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
628 pkgCache::VerIterator
V(*Cache
,*I
);
629 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
630 V
->ParentPkg
== D
->Package
)
632 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
635 Colours
[D
.ParentPkg()->ID
]++;
640 while (DidSomething
== true);
645 // RDepends - Print out a reverse dependency tree - mbc /*{{{*/
646 // ---------------------------------------------------------------------
648 bool RDepends(CommandLine
&CmdL
)
650 pkgCacheFile CacheFile
;
651 pkgCache
*Cache
= CacheFile
.GetPkgCache();
652 if (unlikely(Cache
== NULL
))
655 SPtrArray
<unsigned> Colours
= new unsigned[Cache
->Head().PackageCount
];
656 memset(Colours
,0,sizeof(*Colours
)*Cache
->Head().PackageCount
);
658 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
659 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
660 Colours
[Pkg
->ID
] = 1;
662 bool Recurse
= _config
->FindB("APT::Cache::RecurseDepends",false);
663 bool Installed
= _config
->FindB("APT::Cache::Installed",false);
667 DidSomething
= false;
668 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
670 if (Colours
[Pkg
->ID
] != 1)
672 Colours
[Pkg
->ID
] = 2;
675 pkgCache::VerIterator Ver
= Pkg
.VersionList();
676 if (Ver
.end() == true)
678 cout
<< '<' << Pkg
.FullName(true) << '>' << endl
;
682 cout
<< Pkg
.FullName(true) << endl
;
684 cout
<< "Reverse Depends:" << endl
;
685 for (pkgCache::DepIterator D
= Pkg
.RevDependsList(); D
.end() == false; D
++)
688 pkgCache::PkgIterator Trg
= D
.ParentPkg();
690 if((Installed
&& Trg
->CurrentVer
!= 0) || !Installed
)
693 if ((D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
698 if (Trg
->VersionList
== 0)
699 cout
<< D
.DepType() << ": <" << Trg
.FullName(true) << ">" << endl
;
701 cout
<< Trg
.FullName(true) << endl
;
704 Colours
[D
.ParentPkg()->ID
]++;
708 // Display all solutions
709 SPtrArray
<pkgCache::Version
*> List
= D
.AllTargets();
710 pkgPrioSortList(*Cache
,List
);
711 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
713 pkgCache::VerIterator
V(*Cache
,*I
);
714 if (V
!= Cache
->VerP
+ V
.ParentPkg()->VersionList
||
715 V
->ParentPkg
== D
->Package
)
717 cout
<< " " << V
.ParentPkg().FullName(true) << endl
;
720 Colours
[D
.ParentPkg()->ID
]++;
725 while (DidSomething
== true);
730 // xvcg - Generate a graph for xvcg /*{{{*/
731 // ---------------------------------------------------------------------
732 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
734 bool XVcg(CommandLine
&CmdL
)
736 pkgCacheFile CacheFile
;
737 pkgCache
*Cache
= CacheFile
.GetPkgCache();
738 if (unlikely(Cache
== NULL
))
741 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
743 /* Normal packages are boxes
744 Pure Provides are triangles
746 rhomb are missing packages*/
747 const char *Shapes
[] = {"ellipse","triangle","box","rhomb"};
749 /* Initialize the list of packages to show.
751 2 = To Show no recurse
752 3 = Emitted no recurse
755 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
756 enum TheFlags
{ForceNR
=(1<<0)};
757 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
758 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
759 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
761 // Show everything if no arguments given
762 if (CmdL
.FileList
[1] == 0)
763 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
766 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
768 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
771 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
773 if (Pkg
->VersionList
== 0)
776 if (Pkg
->ProvidesList
== 0)
777 ShapeMap
[Pkg
->ID
] = 0;
779 ShapeMap
[Pkg
->ID
] = 1;
784 if (Pkg
->ProvidesList
== 0)
785 ShapeMap
[Pkg
->ID
] = 2;
787 ShapeMap
[Pkg
->ID
] = 3;
791 // Load the list of packages from the command line into the show list
792 std::list
<APT::PackageSet::Modifier
> mods
;
793 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
794 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
795 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
796 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0);
798 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
799 Pkg
!= pkgsets
[0].end(); ++Pkg
)
800 Show
[Pkg
->ID
] = ToShow
;
801 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
802 Pkg
!= pkgsets
[1].end(); ++Pkg
)
804 Show
[Pkg
->ID
] = ToShow
;
805 Flags
[Pkg
->ID
] |= ForceNR
;
809 cout
<< "graph: { title: \"packages\"" << endl
<<
810 "xmax: 700 ymax: 700 x: 30 y: 30" << endl
<<
811 "layout_downfactor: 8" << endl
;
817 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
819 // See we need to show this package
820 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
823 //printf ("node: { title: \"%s\" label: \"%s\" }\n", Pkg.Name(), Pkg.Name());
826 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
828 // Pure Provides and missing packages have no deps!
829 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
830 Show
[Pkg
->ID
] = Done
;
832 Show
[Pkg
->ID
] = DoneNR
;
835 Show
[Pkg
->ID
] = Done
;
838 // No deps to map out
839 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
842 pkgCache::VerIterator Ver
= Pkg
.VersionList();
843 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
845 // See if anything can meet this dep
846 // Walk along the actual package providing versions
848 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
849 for (pkgCache::VerIterator I
= DPkg
.VersionList();
850 I
.end() == false && Hit
== false; I
++)
852 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
856 // Follow all provides
857 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
858 I
.end() == false && Hit
== false; I
++)
860 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
865 // Only graph critical deps
866 if (D
.IsCritical() == true)
868 printf ("edge: { sourcename: \"%s\" targetname: \"%s\" class: 2 ",Pkg
.FullName(true).c_str(), D
.TargetPkg().FullName(true).c_str() );
870 // Colour the node for recursion
871 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
873 /* If a conflicts does not meet anything in the database
874 then show the relation but do not recurse */
876 (D
->Type
== pkgCache::Dep::Conflicts
||
877 D
->Type
== pkgCache::Dep::DpkgBreaks
||
878 D
->Type
== pkgCache::Dep::Obsoletes
))
880 if (Show
[D
.TargetPkg()->ID
] == None
&&
881 Show
[D
.TargetPkg()->ID
] != ToShow
)
882 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
886 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
887 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
889 Show
[D
.TargetPkg()->ID
] = ToShow
;
896 case pkgCache::Dep::Conflicts
:
897 printf("label: \"conflicts\" color: lightgreen }\n");
899 case pkgCache::Dep::DpkgBreaks
:
900 printf("label: \"breaks\" color: lightgreen }\n");
902 case pkgCache::Dep::Obsoletes
:
903 printf("label: \"obsoletes\" color: lightgreen }\n");
906 case pkgCache::Dep::PreDepends
:
907 printf("label: \"predepends\" color: blue }\n");
919 /* Draw the box colours after the fact since we can not tell what colour
920 they should be until everything is finished drawing */
921 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
923 if (Show
[Pkg
->ID
] < DoneNR
)
926 if (Show
[Pkg
->ID
] == DoneNR
)
927 printf("node: { title: \"%s\" label: \"%s\" color: orange shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
928 Shapes
[ShapeMap
[Pkg
->ID
]]);
930 printf("node: { title: \"%s\" label: \"%s\" shape: %s }\n", Pkg
.FullName(true).c_str(), Pkg
.FullName(true).c_str(),
931 Shapes
[ShapeMap
[Pkg
->ID
]]);
943 // Dotty - Generate a graph for Dotty /*{{{*/
944 // ---------------------------------------------------------------------
945 /* Dotty is the graphvis program for generating graphs. It is a fairly
946 simple queuing algorithm that just writes dependencies and nodes.
947 http://www.research.att.com/sw/tools/graphviz/ */
948 bool Dotty(CommandLine
&CmdL
)
950 pkgCacheFile CacheFile
;
951 pkgCache
*Cache
= CacheFile
.GetPkgCache();
952 if (unlikely(Cache
== NULL
))
955 bool GivenOnly
= _config
->FindB("APT::Cache::GivenOnly",false);
957 /* Normal packages are boxes
958 Pure Provides are triangles
960 Hexagons are missing packages*/
961 const char *Shapes
[] = {"hexagon","triangle","box","diamond"};
963 /* Initialize the list of packages to show.
965 2 = To Show no recurse
966 3 = Emitted no recurse
969 enum States
{None
=0, ToShow
, ToShowNR
, DoneNR
, Done
};
970 enum TheFlags
{ForceNR
=(1<<0)};
971 unsigned char *Show
= new unsigned char[Cache
->Head().PackageCount
];
972 unsigned char *Flags
= new unsigned char[Cache
->Head().PackageCount
];
973 unsigned char *ShapeMap
= new unsigned char[Cache
->Head().PackageCount
];
975 // Show everything if no arguments given
976 if (CmdL
.FileList
[1] == 0)
977 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
980 for (unsigned long I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
982 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
985 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
987 if (Pkg
->VersionList
== 0)
990 if (Pkg
->ProvidesList
== 0)
991 ShapeMap
[Pkg
->ID
] = 0;
993 ShapeMap
[Pkg
->ID
] = 1;
998 if (Pkg
->ProvidesList
== 0)
999 ShapeMap
[Pkg
->ID
] = 2;
1001 ShapeMap
[Pkg
->ID
] = 3;
1005 // Load the list of packages from the command line into the show list
1006 std::list
<APT::PackageSet::Modifier
> mods
;
1007 mods
.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX
));
1008 mods
.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX
));
1009 std::map
<unsigned short, APT::PackageSet
> pkgsets
=
1010 APT::PackageSet::GroupedFromCommandLine(CacheFile
, CmdL
.FileList
+ 1, mods
, 0);
1012 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[0].begin();
1013 Pkg
!= pkgsets
[0].end(); ++Pkg
)
1014 Show
[Pkg
->ID
] = ToShow
;
1015 for (APT::PackageSet::const_iterator Pkg
= pkgsets
[1].begin();
1016 Pkg
!= pkgsets
[1].end(); ++Pkg
)
1018 Show
[Pkg
->ID
] = ToShow
;
1019 Flags
[Pkg
->ID
] |= ForceNR
;
1023 printf("digraph packages {\n");
1024 printf("concentrate=true;\n");
1025 printf("size=\"30,40\";\n");
1031 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1033 // See we need to show this package
1034 if (Show
[Pkg
->ID
] == None
|| Show
[Pkg
->ID
] >= DoneNR
)
1038 if (Show
[Pkg
->ID
] == ToShowNR
|| (Flags
[Pkg
->ID
] & ForceNR
) == ForceNR
)
1040 // Pure Provides and missing packages have no deps!
1041 if (ShapeMap
[Pkg
->ID
] == 0 || ShapeMap
[Pkg
->ID
] == 1)
1042 Show
[Pkg
->ID
] = Done
;
1044 Show
[Pkg
->ID
] = DoneNR
;
1047 Show
[Pkg
->ID
] = Done
;
1050 // No deps to map out
1051 if (Pkg
->VersionList
== 0 || Show
[Pkg
->ID
] == DoneNR
)
1054 pkgCache::VerIterator Ver
= Pkg
.VersionList();
1055 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
1057 // See if anything can meet this dep
1058 // Walk along the actual package providing versions
1060 pkgCache::PkgIterator DPkg
= D
.TargetPkg();
1061 for (pkgCache::VerIterator I
= DPkg
.VersionList();
1062 I
.end() == false && Hit
== false; I
++)
1064 if (Cache
->VS
->CheckDep(I
.VerStr(),D
->CompareOp
,D
.TargetVer()) == true)
1068 // Follow all provides
1069 for (pkgCache::PrvIterator I
= DPkg
.ProvidesList();
1070 I
.end() == false && Hit
== false; I
++)
1072 if (Cache
->VS
->CheckDep(I
.ProvideVersion(),D
->CompareOp
,D
.TargetVer()) == false)
1076 // Only graph critical deps
1077 if (D
.IsCritical() == true)
1079 printf("\"%s\" -> \"%s\"",Pkg
.FullName(true).c_str(),D
.TargetPkg().FullName(true).c_str());
1081 // Colour the node for recursion
1082 if (Show
[D
.TargetPkg()->ID
] <= DoneNR
)
1084 /* If a conflicts does not meet anything in the database
1085 then show the relation but do not recurse */
1087 (D
->Type
== pkgCache::Dep::Conflicts
||
1088 D
->Type
== pkgCache::Dep::Obsoletes
))
1090 if (Show
[D
.TargetPkg()->ID
] == None
&&
1091 Show
[D
.TargetPkg()->ID
] != ToShow
)
1092 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1096 if (GivenOnly
== true && Show
[D
.TargetPkg()->ID
] != ToShow
)
1097 Show
[D
.TargetPkg()->ID
] = ToShowNR
;
1099 Show
[D
.TargetPkg()->ID
] = ToShow
;
1106 case pkgCache::Dep::Conflicts
:
1107 case pkgCache::Dep::Obsoletes
:
1108 printf("[color=springgreen];\n");
1111 case pkgCache::Dep::PreDepends
:
1112 printf("[color=blue];\n");
1124 /* Draw the box colours after the fact since we can not tell what colour
1125 they should be until everything is finished drawing */
1126 for (pkgCache::PkgIterator Pkg
= Cache
->PkgBegin(); Pkg
.end() == false; Pkg
++)
1128 if (Show
[Pkg
->ID
] < DoneNR
)
1131 // Orange box for early recursion stoppage
1132 if (Show
[Pkg
->ID
] == DoneNR
)
1133 printf("\"%s\" [color=orange,shape=%s];\n",Pkg
.FullName(true).c_str(),
1134 Shapes
[ShapeMap
[Pkg
->ID
]]);
1136 printf("\"%s\" [shape=%s];\n",Pkg
.FullName(true).c_str(),
1137 Shapes
[ShapeMap
[Pkg
->ID
]]);
1144 // DoAdd - Perform an adding operation /*{{{*/
1145 // ---------------------------------------------------------------------
1147 bool DoAdd(CommandLine
&CmdL
)
1149 return _error
->Error("Unimplemented");
1151 // Make sure there is at least one argument
1152 if (CmdL
.FileSize() <= 1)
1153 return _error
->Error("You must give at least one file name");
1156 FileFd
CacheF(_config
->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny
);
1157 if (_error
->PendingError() == true)
1160 DynamicMMap
Map(CacheF
,MMap::Public
);
1161 if (_error
->PendingError() == true)
1164 OpTextProgress
Progress(*_config
);
1165 pkgCacheGenerator
Gen(Map
,Progress
);
1166 if (_error
->PendingError() == true)
1169 unsigned long Length
= CmdL
.FileSize() - 1;
1170 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1172 Progress
.OverallProgress(I
- CmdL
.FileList
,Length
,1,"Generating cache");
1173 Progress
.SubProgress(Length
);
1176 FileFd
TagF(*I
,FileFd::ReadOnly
);
1177 debListParser
Parser(TagF
);
1178 if (_error
->PendingError() == true)
1179 return _error
->Error("Problem opening %s",*I
);
1181 if (Gen
.SelectFile(*I
,"") == false)
1182 return _error
->Error("Problem with SelectFile");
1184 if (Gen
.MergeList(Parser
) == false)
1185 return _error
->Error("Problem with MergeList");
1189 GCache
= &Gen
.GetCache();
1196 // DisplayRecord - Displays the complete record for the package /*{{{*/
1197 // ---------------------------------------------------------------------
1198 /* This displays the package record from the proper package index file.
1199 It is not used by DumpAvail for performance reasons. */
1200 bool DisplayRecord(pkgCacheFile
&CacheFile
, pkgCache::VerIterator V
)
1202 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1203 if (unlikely(Cache
== NULL
))
1206 // Find an appropriate file
1207 pkgCache::VerFileIterator Vf
= V
.FileList();
1208 for (; Vf
.end() == false; Vf
++)
1209 if ((Vf
.File()->Flags
& pkgCache::Flag::NotSource
) == 0)
1211 if (Vf
.end() == true)
1214 // Check and load the package list file
1215 pkgCache::PkgFileIterator I
= Vf
.File();
1216 if (I
.IsOk() == false)
1217 return _error
->Error(_("Package file %s is out of sync."),I
.FileName());
1220 if (PkgF
.Open(I
.FileName(), FileFd::ReadOnly
) == false)
1224 unsigned char *Buffer
= new unsigned char[Cache
->HeaderP
->MaxVerFileSize
+1];
1225 Buffer
[V
.FileList()->Size
] = '\n';
1226 if (PkgF
.Seek(V
.FileList()->Offset
) == false ||
1227 PkgF
.Read(Buffer
,V
.FileList()->Size
) == false)
1233 // Get a pointer to start of Description field
1234 const unsigned char *DescP
= (unsigned char*)strstr((char*)Buffer
, "Description:");
1236 // Write all but Description
1237 if (fwrite(Buffer
,1,DescP
- Buffer
,stdout
) < (size_t)(DescP
- Buffer
))
1243 // Show the right description
1244 pkgRecords
Recs(*Cache
);
1245 pkgCache::DescIterator Desc
= V
.TranslatedDescription();
1246 pkgRecords::Parser
&P
= Recs
.Lookup(Desc
.FileList());
1247 cout
<< "Description" << ( (strcmp(Desc
.LanguageCode(),"") != 0) ? "-" : "" ) << Desc
.LanguageCode() << ": " << P
.LongDesc();
1249 // Find the first field after the description (if there is any)
1250 for(DescP
++;DescP
!= &Buffer
[V
.FileList()->Size
];DescP
++)
1252 if(*DescP
== '\n' && *(DescP
+1) != ' ')
1254 // write the rest of the buffer
1255 const unsigned char *end
=&Buffer
[V
.FileList()->Size
];
1256 if (fwrite(DescP
,1,end
-DescP
,stdout
) < (size_t)(end
-DescP
))
1265 // write a final newline (after the description)
1275 pkgCache::DescFile
*Df
;
1279 // Search - Perform a search /*{{{*/
1280 // ---------------------------------------------------------------------
1281 /* This searches the package names and package descriptions for a pattern */
1282 bool Search(CommandLine
&CmdL
)
1284 bool const ShowFull
= _config
->FindB("APT::Cache::ShowFull",false);
1285 bool const NamesOnly
= _config
->FindB("APT::Cache::NamesOnly",false);
1286 unsigned int const NumPatterns
= CmdL
.FileSize() -1;
1288 pkgCacheFile CacheFile
;
1289 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1290 pkgDepCache::Policy
*Plcy
= CacheFile
.GetPolicy();
1291 if (unlikely(Cache
== NULL
|| Plcy
== NULL
))
1294 // Make sure there is at least one argument
1295 if (NumPatterns
< 1)
1296 return _error
->Error(_("You must give at least one search pattern"));
1298 // Compile the regex pattern
1299 regex_t
*Patterns
= new regex_t
[NumPatterns
];
1300 memset(Patterns
,0,sizeof(*Patterns
)*NumPatterns
);
1301 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1303 if (regcomp(&Patterns
[I
],CmdL
.FileList
[I
+1],REG_EXTENDED
| REG_ICASE
|
1307 regfree(&Patterns
[I
]);
1308 return _error
->Error("Regex compilation error");
1312 if (_error
->PendingError() == true)
1314 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1315 regfree(&Patterns
[I
]);
1319 ExDescFile
*DFList
= new ExDescFile
[Cache
->HeaderP
->GroupCount
+1];
1320 memset(DFList
,0,sizeof(*DFList
)*Cache
->HeaderP
->GroupCount
+1);
1322 // Map versions that we want to write out onto the VerList array.
1323 for (pkgCache::GrpIterator G
= Cache
->GrpBegin(); G
.end() == false; ++G
)
1325 if (DFList
[G
->ID
].NameMatch
== true)
1328 DFList
[G
->ID
].NameMatch
= true;
1329 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1331 if (regexec(&Patterns
[I
],G
.Name(),0,0,0) == 0)
1333 DFList
[G
->ID
].NameMatch
= false;
1337 // Doing names only, drop any that dont match..
1338 if (NamesOnly
== true && DFList
[G
->ID
].NameMatch
== false)
1341 // Find the proper version to use
1342 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
1343 if (P
.end() == true)
1345 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(P
);
1346 if (V
.end() == false)
1347 DFList
[G
->ID
].Df
= V
.DescriptionList().FileList();
1349 if (DFList
[G
->ID
].NameMatch
== false)
1352 // Include all the packages that provide matching names too
1353 for (pkgCache::PrvIterator Prv
= P
.ProvidesList() ; Prv
.end() == false; Prv
++)
1355 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Prv
.OwnerPkg());
1356 if (V
.end() == true)
1359 unsigned long id
= Prv
.OwnerPkg().Group()->ID
;
1360 DFList
[id
].Df
= V
.DescriptionList().FileList();
1361 DFList
[id
].NameMatch
= true;
1365 LocalitySort(&DFList
->Df
,Cache
->HeaderP
->GroupCount
,sizeof(*DFList
));
1367 // Create the text record parser
1368 pkgRecords
Recs(*Cache
);
1369 // Iterate over all the version records and check them
1370 for (ExDescFile
*J
= DFList
; J
->Df
!= 0; J
++)
1372 pkgRecords::Parser
&P
= Recs
.Lookup(pkgCache::DescFileIterator(*Cache
,J
->Df
));
1374 if (J
->NameMatch
== false && NamesOnly
== false)
1376 string
const LongDesc
= P
.LongDesc();
1377 J
->NameMatch
= true;
1378 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1380 if (regexec(&Patterns
[I
],LongDesc
.c_str(),0,0,0) == 0)
1382 J
->NameMatch
= false;
1387 if (J
->NameMatch
== true)
1389 if (ShowFull
== true)
1393 P
.GetRec(Start
,End
);
1394 fwrite(Start
,End
-Start
,1,stdout
);
1398 printf("%s - %s\n",P
.Name().c_str(),P
.ShortDesc().c_str());
1403 for (unsigned I
= 0; I
!= NumPatterns
; I
++)
1404 regfree(&Patterns
[I
]);
1406 return _error
->Error("Write to stdout failed");
1411 /* show automatically installed packages (sorted) */
1412 bool ShowAuto(CommandLine
&CmdL
)
1414 pkgCacheFile CacheFile
;
1415 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1416 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
1417 if (unlikely(Cache
== NULL
|| DepCache
== NULL
))
1420 std::vector
<string
> packages
;
1421 packages
.reserve(Cache
->HeaderP
->PackageCount
/ 3);
1423 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; P
++)
1424 if ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
)
1425 packages
.push_back(P
.Name());
1427 std::sort(packages
.begin(), packages
.end());
1429 for (vector
<string
>::iterator I
= packages
.begin(); I
!= packages
.end(); I
++)
1435 // ShowPackage - Dump the package record to the screen /*{{{*/
1436 // ---------------------------------------------------------------------
1438 bool ShowPackage(CommandLine
&CmdL
)
1440 pkgCacheFile CacheFile
;
1441 APT::VersionSet::Version
const select
= _config
->FindB("APT::Cache::AllVersions", true) ?
1442 APT::VersionSet::ALL
: APT::VersionSet::CANDIDATE
;
1443 APT::VersionSet
const verset
= APT::VersionSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1, select
);
1444 for (APT::VersionSet::const_iterator Ver
= verset
.begin(); Ver
!= verset
.end(); ++Ver
)
1445 if (DisplayRecord(CacheFile
, Ver
) == false)
1448 if (verset
.empty() == false)
1450 return _error
->Error(_("No packages found"));
1453 // ShowPkgNames - Show package names /*{{{*/
1454 // ---------------------------------------------------------------------
1455 /* This does a prefix match on the first argument */
1456 bool ShowPkgNames(CommandLine
&CmdL
)
1458 pkgCacheFile CacheFile
;
1459 if (unlikely(CacheFile
.BuildCaches(NULL
, false) == false))
1461 pkgCache::GrpIterator I
= CacheFile
.GetPkgCache()->GrpBegin();
1462 bool const All
= _config
->FindB("APT::Cache::AllNames","false");
1464 if (CmdL
.FileList
[1] != 0)
1466 for (;I
.end() != true; I
++)
1468 if (All
== false && I
->FirstPackage
== 0)
1470 if (I
.FindPkg("any")->VersionList
== 0)
1472 if (strncmp(I
.Name(),CmdL
.FileList
[1],strlen(CmdL
.FileList
[1])) == 0)
1473 cout
<< I
.Name() << endl
;
1480 for (;I
.end() != true; I
++)
1482 if (All
== false && I
->FirstPackage
== 0)
1484 if (I
.FindPkg("any")->VersionList
== 0)
1486 cout
<< I
.Name() << endl
;
1492 // ShowSrcPackage - Show source package records /*{{{*/
1493 // ---------------------------------------------------------------------
1495 bool ShowSrcPackage(CommandLine
&CmdL
)
1497 pkgCacheFile CacheFile
;
1498 pkgSourceList
*List
= CacheFile
.GetSourceList();
1499 if (unlikely(List
== NULL
))
1502 // Create the text record parsers
1503 pkgSrcRecords
SrcRecs(*List
);
1504 if (_error
->PendingError() == true)
1508 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
1512 pkgSrcRecords::Parser
*Parse
;
1513 unsigned found_this
= 0;
1514 while ((Parse
= SrcRecs
.Find(*I
,false)) != 0) {
1515 cout
<< Parse
->AsStr() << endl
;;
1519 if (found_this
== 0) {
1520 _error
->Warning(_("Unable to locate package %s"),*I
);
1526 return _error
->Error(_("No packages found"));
1529 // Policy - Show the results of the preferences file /*{{{*/
1530 // ---------------------------------------------------------------------
1532 bool Policy(CommandLine
&CmdL
)
1534 pkgCacheFile CacheFile
;
1535 pkgCache
*Cache
= CacheFile
.GetPkgCache();
1536 pkgPolicy
*Plcy
= CacheFile
.GetPolicy();
1537 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1538 if (unlikely(Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
1541 /* Should the MultiArchKiller be run to see which pseudo packages for an
1542 arch all package are currently installed? Activating it gives a speed
1543 penality for no real gain beside enhanced debugging, so in general no. */
1544 if (_config
->FindB("APT::Cache::Policy::DepCache", false) == true)
1545 CacheFile
.GetDepCache();
1547 // Print out all of the package files
1548 if (CmdL
.FileList
[1] == 0)
1550 cout
<< _("Package files:") << endl
;
1551 for (pkgCache::PkgFileIterator F
= Cache
->FileBegin(); F
.end() == false; F
++)
1553 // Locate the associated index files so we can derive a description
1555 if (SrcList
->FindIndex(F
,Indx
) == false &&
1556 _system
->FindIndex(F
,Indx
) == false)
1557 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1560 Plcy
->GetPriority(F
),Indx
->Describe(true).c_str());
1562 // Print the reference information for the package
1563 string Str
= F
.RelStr();
1564 if (Str
.empty() == false)
1565 printf(" release %s\n",F
.RelStr().c_str());
1566 if (F
.Site() != 0 && F
.Site()[0] != 0)
1567 printf(" origin %s\n",F
.Site());
1570 // Show any packages have explicit pins
1571 cout
<< _("Pinned packages:") << endl
;
1572 pkgCache::PkgIterator I
= Cache
->PkgBegin();
1573 for (;I
.end() != true; I
++)
1575 if (Plcy
->GetPriority(I
) == 0)
1578 // Print the package name and the version we are forcing to
1579 cout
<< " " << I
.FullName(true) << " -> ";
1581 pkgCache::VerIterator V
= Plcy
->GetMatch(I
);
1582 if (V
.end() == true)
1583 cout
<< _("(not found)") << endl
;
1585 cout
<< V
.VerStr() << endl
;
1591 string
const myArch
= _config
->Find("APT::Architecture");
1592 char const * const msgInstalled
= _(" Installed: ");
1593 char const * const msgCandidate
= _(" Candidate: ");
1594 short const InstalledLessCandidate
=
1595 mbstowcs(NULL
, msgInstalled
, 0) - mbstowcs(NULL
, msgCandidate
, 0);
1596 short const deepInstalled
=
1597 (InstalledLessCandidate
< 0 ? (InstalledLessCandidate
*-1) : 0) - 1;
1598 short const deepCandidate
=
1599 (InstalledLessCandidate
> 0 ? (InstalledLessCandidate
) : 0) - 1;
1601 // Print out detailed information for each package
1602 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
1603 for (APT::PackageSet::const_iterator I
= pkgset
.begin(); I
!= pkgset
.end(); ++I
)
1605 pkgCache::PkgIterator Pkg
= I
.Group().FindPkg("any");
1607 for (; Pkg
.end() != true; Pkg
= I
.Group().NextPkg(Pkg
)) {
1608 if (strcmp(Pkg
.Arch(),"all") == 0)
1611 cout
<< Pkg
.FullName(true) << ":" << endl
;
1613 // Installed version
1614 cout
<< msgInstalled
<< OutputInDepth(deepInstalled
, " ");
1615 if (Pkg
->CurrentVer
== 0)
1616 cout
<< _("(none)") << endl
;
1618 cout
<< Pkg
.CurrentVer().VerStr() << endl
;
1620 // Candidate Version
1621 cout
<< msgCandidate
<< OutputInDepth(deepCandidate
, " ");
1622 pkgCache::VerIterator V
= Plcy
->GetCandidateVer(Pkg
);
1623 if (V
.end() == true)
1624 cout
<< _("(none)") << endl
;
1626 cout
<< V
.VerStr() << endl
;
1629 if (Plcy
->GetPriority(Pkg
) != 0)
1631 cout
<< _(" Package pin: ");
1632 V
= Plcy
->GetMatch(Pkg
);
1633 if (V
.end() == true)
1634 cout
<< _("(not found)") << endl
;
1636 cout
<< V
.VerStr() << endl
;
1639 // Show the priority tables
1640 cout
<< _(" Version table:") << endl
;
1641 for (V
= Pkg
.VersionList(); V
.end() == false; V
++)
1643 if (Pkg
.CurrentVer() == V
)
1644 cout
<< " *** " << V
.VerStr();
1646 cout
<< " " << V
.VerStr();
1647 cout
<< " " << Plcy
->GetPriority(Pkg
) << endl
;
1648 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1650 // Locate the associated index files so we can derive a description
1652 if (SrcList
->FindIndex(VF
.File(),Indx
) == false &&
1653 _system
->FindIndex(VF
.File(),Indx
) == false)
1654 return _error
->Error(_("Cache is out of sync, can't x-ref a package file"));
1655 printf(" %4i %s\n",Plcy
->GetPriority(VF
.File()),
1656 Indx
->Describe(true).c_str());
1665 // Madison - Look a bit like katie's madison /*{{{*/
1666 // ---------------------------------------------------------------------
1668 bool Madison(CommandLine
&CmdL
)
1670 pkgCacheFile CacheFile
;
1671 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
1676 // Create the src text record parsers and ignore errors about missing
1677 // deb-src lines that are generated from pkgSrcRecords::pkgSrcRecords
1678 pkgSrcRecords
SrcRecs(*SrcList
);
1679 if (_error
->PendingError() == true)
1682 APT::PackageSet pkgset
= APT::PackageSet::FromCommandLine(CacheFile
, CmdL
.FileList
+ 1);
1683 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
)
1685 if (Pkg
.end() == false)
1687 for (pkgCache::VerIterator V
= Pkg
.VersionList(); V
.end() == false; V
++)
1689 for (pkgCache::VerFileIterator VF
= V
.FileList(); VF
.end() == false; VF
++)
1691 // This might be nice, but wouldn't uniquely identify the source -mdz
1692 // if (VF.File().Archive() != 0)
1694 // cout << setw(10) << Pkg.Name() << " | " << setw(10) << V.VerStr() << " | "
1695 // << VF.File().Archive() << endl;
1698 // Locate the associated index files so we can derive a description
1699 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); S
++)
1701 vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
1702 for (vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
1703 IF
!= Indexes
->end(); IF
++)
1705 if ((*IF
)->FindInCache(*(VF
.File().Cache())) == VF
.File())
1707 cout
<< setw(10) << Pkg
.FullName(true) << " | " << setw(10) << V
.VerStr() << " | "
1708 << (*IF
)->Describe(true) << endl
;
1718 pkgSrcRecords::Parser
*SrcParser
;
1719 while ((SrcParser
= SrcRecs
.Find(Pkg
.Name(),false)) != 0)
1721 // Maybe support Release info here too eventually
1722 cout
<< setw(10) << SrcParser
->Package() << " | "
1723 << setw(10) << SrcParser
->Version() << " | "
1724 << SrcParser
->Index().Describe(true) << endl
;
1731 // GenCaches - Call the main cache generator /*{{{*/
1732 // ---------------------------------------------------------------------
1734 bool GenCaches(CommandLine
&Cmd
)
1736 OpTextProgress
Progress(*_config
);
1738 pkgCacheFile CacheFile
;
1739 return CacheFile
.BuildCaches(&Progress
, true);
1742 // ShowHelp - Show a help screen /*{{{*/
1743 // ---------------------------------------------------------------------
1745 bool ShowHelp(CommandLine
&Cmd
)
1747 ioprintf(cout
,_("%s %s for %s compiled on %s %s\n"),PACKAGE
,VERSION
,
1748 COMMON_ARCH
,__DATE__
,__TIME__
);
1750 if (_config
->FindB("version") == true)
1754 _("Usage: apt-cache [options] command\n"
1755 " apt-cache [options] add file1 [file2 ...]\n"
1756 " apt-cache [options] showpkg pkg1 [pkg2 ...]\n"
1757 " apt-cache [options] showsrc pkg1 [pkg2 ...]\n"
1759 "apt-cache is a low-level tool used to manipulate APT's binary\n"
1760 "cache files, and query information from them\n"
1763 " add - Add a package file to the source cache\n"
1764 " gencaches - Build both the package and source cache\n"
1765 " showpkg - Show some general information for a single package\n"
1766 " showsrc - Show source records\n"
1767 " stats - Show some basic statistics\n"
1768 " dump - Show the entire file in a terse form\n"
1769 " dumpavail - Print an available file to stdout\n"
1770 " unmet - Show unmet dependencies\n"
1771 " search - Search the package list for a regex pattern\n"
1772 " show - Show a readable record for the package\n"
1773 " showauto - Display a list of automatically installed packages\n"
1774 " depends - Show raw dependency information for a package\n"
1775 " rdepends - Show reverse dependency information for a package\n"
1776 " pkgnames - List the names of all packages in the system\n"
1777 " dotty - Generate package graphs for GraphViz\n"
1778 " xvcg - Generate package graphs for xvcg\n"
1779 " policy - Show policy settings\n"
1782 " -h This help text.\n"
1783 " -p=? The package cache.\n"
1784 " -s=? The source cache.\n"
1785 " -q Disable progress indicator.\n"
1786 " -i Show only important deps for the unmet command.\n"
1787 " -c=? Read this configuration file\n"
1788 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1789 "See the apt-cache(8) and apt.conf(5) manual pages for more information.\n");
1793 // CacheInitialize - Initialize things for apt-cache /*{{{*/
1794 // ---------------------------------------------------------------------
1796 void CacheInitialize()
1798 _config
->Set("quiet",0);
1799 _config
->Set("help",false);
1802 int main(int argc
,const char *argv
[]) /*{{{*/
1804 CommandLine::Args Args
[] = {
1805 {'h',"help","help",0},
1806 {'v',"version","version",0},
1807 {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg
},
1808 {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg
},
1809 {'q',"quiet","quiet",CommandLine::IntLevel
},
1810 {'i',"important","APT::Cache::Important",0},
1811 {'f',"full","APT::Cache::ShowFull",0},
1812 {'g',"generate","APT::Cache::Generate",0},
1813 {'a',"all-versions","APT::Cache::AllVersions",0},
1814 {'n',"names-only","APT::Cache::NamesOnly",0},
1815 {0,"all-names","APT::Cache::AllNames",0},
1816 {0,"recurse","APT::Cache::RecurseDepends",0},
1817 {'t',"target-release","APT::Default-Release",CommandLine::HasArg
},
1818 {'t',"default-release","APT::Default-Release",CommandLine::HasArg
},
1819 {'c',"config-file",0,CommandLine::ConfigFile
},
1820 {'o',"option",0,CommandLine::ArbItem
},
1821 {0,"installed","APT::Cache::Installed",0},
1823 CommandLine::Dispatch CmdsA
[] = {{"help",&ShowHelp
},
1825 {"gencaches",&GenCaches
},
1826 {"showsrc",&ShowSrcPackage
},
1828 CommandLine::Dispatch CmdsB
[] = {{"showpkg",&DumpPackage
},
1831 {"dumpavail",&DumpAvail
},
1834 {"depends",&Depends
},
1835 {"rdepends",&RDepends
},
1838 {"show",&ShowPackage
},
1839 {"pkgnames",&ShowPkgNames
},
1840 {"showauto",&ShowAuto
},
1842 {"madison",&Madison
},
1847 // Set up gettext support
1848 setlocale(LC_ALL
,"");
1849 textdomain(PACKAGE
);
1851 // Parse the command line and initialize the package library
1852 CommandLine
CmdL(Args
,_config
);
1853 if (pkgInitConfig(*_config
) == false ||
1854 CmdL
.Parse(argc
,argv
) == false ||
1855 pkgInitSystem(*_config
,_system
) == false)
1857 _error
->DumpErrors();
1861 // See if the help should be shown
1862 if (_config
->FindB("help") == true ||
1863 CmdL
.FileSize() == 0)
1869 // Deal with stdout not being a tty
1870 if (isatty(STDOUT_FILENO
) && _config
->FindI("quiet",0) < 1)
1871 _config
->Set("quiet","1");
1873 // if (_config->FindB("APT::Cache::Generate",true) == false)
1874 if (CmdL
.DispatchArg(CmdsA
,false) == false && _error
->PendingError() == false)
1875 CmdL
.DispatchArg(CmdsB
);
1877 // Print any errors or warnings found during parsing
1878 if (_error
->empty() == false)
1880 bool Errors
= _error
->PendingError();
1881 _error
->DumpErrors();
1882 return Errors
== true?100:0;