1 #ifndef APT_PRIVATE_CACHESET_H
2 #define APT_PRIVATE_CACHESET_H
4 #include <apt-pkg/aptconfiguration.h>
5 #include <apt-pkg/cachefile.h>
6 #include <apt-pkg/cacheset.h>
7 #include <apt-pkg/sptr.h>
8 #include <apt-pkg/strutl.h>
9 #include <apt-pkg/depcache.h>
10 #include <apt-pkg/error.h>
11 #include <apt-pkg/pkgcache.h>
12 #include <apt-pkg/cacheiterators.h>
13 #include <apt-pkg/macros.h>
24 #include "private-output.h"
30 struct VersionSortDescriptionLocality
32 bool operator () (const pkgCache::VerIterator
&v_lhs
,
33 const pkgCache::VerIterator
&v_rhs
)
35 pkgCache::DescFile
const *A
= NULL
;
36 pkgCache::DescFile
const *B
= NULL
;
37 if (v_lhs
->DescriptionList
!= 0)
38 A
= v_lhs
.TranslatedDescription().FileList();
39 if (v_rhs
->DescriptionList
!= 0)
40 B
= v_rhs
.TranslatedDescription().FileList();
51 if (A
->File
== B
->File
)
52 return A
->Offset
< B
->Offset
;
54 return A
->File
< B
->File
;
58 // sorted by locality which makes iterating much faster
59 typedef APT::VersionContainer
<
60 std::set
<pkgCache::VerIterator
,
61 VersionSortDescriptionLocality
> > LocalitySortedVersionSet
;
65 virtual bool operator () (const pkgCache::PkgIterator
&/*P*/) {
69 // FIXME: add default argument for OpProgress (or overloaded function)
70 bool GetLocalitySortedVersionSet(pkgCacheFile
&CacheFile
,
71 APT::VersionContainerInterface
* const vci
,
73 OpProgress
* const progress
);
74 bool GetLocalitySortedVersionSet(pkgCacheFile
&CacheFile
,
75 APT::VersionContainerInterface
* const vci
,
76 OpProgress
* const progress
);
79 // CacheSetHelper saving virtual packages /*{{{*/
80 class CacheSetHelperVirtuals
: public APT::CacheSetHelper
{
82 APT::PackageSet virtualPkgs
;
84 virtual pkgCache::VerIterator
canNotGetVersion(enum CacheSetHelper::VerSelector
const select
, pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) APT_OVERRIDE
{
85 if (select
== NEWEST
|| select
== CANDIDATE
|| select
== ALL
)
86 virtualPkgs
.insert(Pkg
);
87 return CacheSetHelper::canNotGetVersion(select
, Cache
, Pkg
);
90 virtual void canNotFindVersion(enum CacheSetHelper::VerSelector
const select
, APT::VersionContainerInterface
* vci
, pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) APT_OVERRIDE
{
91 if (select
== NEWEST
|| select
== CANDIDATE
|| select
== ALL
)
92 virtualPkgs
.insert(Pkg
);
93 return CacheSetHelper::canNotFindVersion(select
, vci
, Cache
, Pkg
);
96 CacheSetHelperVirtuals(bool const ShowErrors
= true, GlobalError::MsgType
const &ErrorType
= GlobalError::NOTICE
) : CacheSetHelper(ShowErrors
, ErrorType
) {}
100 // CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/
101 class CacheSetHelperAPTGet
: public APT::CacheSetHelper
{
102 /** \brief stream message should be printed to */
104 /** \brief were things like Task or RegEx used to select packages? */
105 bool explicitlyNamed
;
107 APT::PackageSet virtualPkgs
;
110 std::list
<std::pair
<pkgCache::VerIterator
, std::string
> > selectedByRelease
;
112 CacheSetHelperAPTGet(std::ostream
&out
) : APT::CacheSetHelper(true), out(out
) {
113 explicitlyNamed
= true;
116 virtual void showTaskSelection(pkgCache::PkgIterator
const &Pkg
, std::string
const &pattern
) APT_OVERRIDE
{
117 ioprintf(out
, _("Note, selecting '%s' for task '%s'\n"),
118 Pkg
.FullName(true).c_str(), pattern
.c_str());
119 explicitlyNamed
= false;
121 virtual void showFnmatchSelection(pkgCache::PkgIterator
const &Pkg
, std::string
const &pattern
) APT_OVERRIDE
{
122 ioprintf(out
, _("Note, selecting '%s' for glob '%s'\n"),
123 Pkg
.FullName(true).c_str(), pattern
.c_str());
124 explicitlyNamed
= false;
126 virtual void showRegExSelection(pkgCache::PkgIterator
const &Pkg
, std::string
const &pattern
) APT_OVERRIDE
{
127 ioprintf(out
, _("Note, selecting '%s' for regex '%s'\n"),
128 Pkg
.FullName(true).c_str(), pattern
.c_str());
129 explicitlyNamed
= false;
131 virtual void showSelectedVersion(pkgCache::PkgIterator
const &/*Pkg*/, pkgCache::VerIterator
const Ver
,
132 std::string
const &ver
, bool const /*verIsRel*/) APT_OVERRIDE
{
133 if (ver
== Ver
.VerStr())
135 selectedByRelease
.push_back(make_pair(Ver
, ver
));
138 bool showVirtualPackageErrors(pkgCacheFile
&Cache
) {
139 if (virtualPkgs
.empty() == true)
141 for (APT::PackageSet::const_iterator Pkg
= virtualPkgs
.begin();
142 Pkg
!= virtualPkgs
.end(); ++Pkg
) {
143 if (Pkg
->ProvidesList
!= 0) {
144 ioprintf(c1out
,_("Package %s is a virtual package provided by:\n"),
145 Pkg
.FullName(true).c_str());
147 pkgCache::PrvIterator I
= Pkg
.ProvidesList();
148 unsigned short provider
= 0;
149 for (; I
.end() == false; ++I
) {
150 pkgCache::PkgIterator Pkg
= I
.OwnerPkg();
152 if (Cache
[Pkg
].CandidateVerIter(Cache
) == I
.OwnerVer()) {
153 c1out
<< " " << Pkg
.FullName(true) << " " << I
.OwnerVer().VerStr();
154 if (Cache
[Pkg
].Install() == true && Cache
[Pkg
].NewInstall() == false)
155 c1out
<< _(" [Installed]");
160 // if we found no candidate which provide this package, show non-candidates
162 for (I
= Pkg
.ProvidesList(); I
.end() == false; ++I
)
163 c1out
<< " " << I
.OwnerPkg().FullName(true) << " " << I
.OwnerVer().VerStr()
164 << _(" [Not candidate version]") << std::endl
;
166 out
<< _("You should explicitly select one to install.") << std::endl
;
169 _("Package %s is not available, but is referred to by another package.\n"
170 "This may mean that the package is missing, has been obsoleted, or\n"
171 "is only available from another source\n"),Pkg
.FullName(true).c_str());
174 std::string VersionsList
;
175 SPtrArray
<bool> Seen
= new bool[Cache
.GetPkgCache()->Head().PackageCount
];
176 memset(Seen
,0,Cache
.GetPkgCache()->Head().PackageCount
*sizeof(*Seen
));
177 for (pkgCache::DepIterator Dep
= Pkg
.RevDependsList();
178 Dep
.end() == false; ++Dep
) {
179 if (Dep
->Type
!= pkgCache::Dep::Replaces
)
181 if (Seen
[Dep
.ParentPkg()->ID
] == true)
183 Seen
[Dep
.ParentPkg()->ID
] = true;
184 List
+= Dep
.ParentPkg().FullName(true) + " ";
185 //VersionsList += std::string(Dep.ParentPkg().CurVersion) + "\n"; ???
187 ShowList(c1out
,_("However the following packages replace it:"),List
,VersionsList
);
194 virtual pkgCache::VerIterator
canNotFindCandidateVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) APT_OVERRIDE
{
195 APT::VersionSet
const verset
= tryVirtualPackage(Cache
, Pkg
, CacheSetHelper::CANDIDATE
);
196 if (verset
.empty() == false)
197 return *(verset
.begin());
198 else if (ShowError
== true) {
199 _error
->Error(_("Package '%s' has no installation candidate"),Pkg
.FullName(true).c_str());
200 virtualPkgs
.insert(Pkg
);
202 return pkgCache::VerIterator(Cache
, 0);
205 virtual pkgCache::VerIterator
canNotFindNewestVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
) APT_OVERRIDE
{
206 if (Pkg
->ProvidesList
!= 0)
208 APT::VersionSet
const verset
= tryVirtualPackage(Cache
, Pkg
, CacheSetHelper::NEWEST
);
209 if (verset
.empty() == false)
210 return *(verset
.begin());
211 if (ShowError
== true)
212 ioprintf(out
, _("Virtual packages like '%s' can't be removed\n"), Pkg
.FullName(true).c_str());
216 pkgCache::GrpIterator Grp
= Pkg
.Group();
217 pkgCache::PkgIterator P
= Grp
.PackageList();
218 for (; P
.end() != true; P
= Grp
.NextPkg(P
))
222 if (P
->CurrentVer
!= 0) {
223 // TRANSLATORS: Note, this is not an interactive question
224 ioprintf(c1out
,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
225 Pkg
.FullName(true).c_str(), P
.FullName(true).c_str());
230 ioprintf(c1out
,_("Package '%s' is not installed, so not removed\n"),Pkg
.FullName(true).c_str());
232 return pkgCache::VerIterator(Cache
, 0);
235 APT::VersionSet
tryVirtualPackage(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
,
236 CacheSetHelper::VerSelector
const select
) {
237 /* This is a pure virtual package and there is a single available
238 candidate providing it. */
239 if (unlikely(Cache
[Pkg
].CandidateVer
!= 0) || Pkg
->ProvidesList
== 0)
240 return APT::VersionSet();
242 pkgCache::PkgIterator Prov
;
243 bool found_one
= false;
244 for (pkgCache::PrvIterator P
= Pkg
.ProvidesList(); P
; ++P
) {
245 pkgCache::VerIterator
const PVer
= P
.OwnerVer();
246 pkgCache::PkgIterator
const PPkg
= PVer
.ParentPkg();
248 /* Ignore versions that are not a candidate. */
249 if (Cache
[PPkg
].CandidateVer
!= PVer
)
252 if (found_one
== false) {
255 } else if (PPkg
!= Prov
) {
256 // same group, so it's a foreign package
257 if (PPkg
->Group
== Prov
->Group
) {
258 // do we already have the requested arch?
259 if (strcmp(Pkg
.Arch(), Prov
.Arch()) == 0 ||
260 strcmp(Prov
.Arch(), "all") == 0 ||
261 unlikely(strcmp(PPkg
.Arch(), Prov
.Arch()) == 0)) // packages have only on candidate, but just to be sure
263 // see which architecture we prefer more and switch to it
264 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
265 if (std::find(archs
.begin(), archs
.end(), PPkg
.Arch()) < std::find(archs
.begin(), archs
.end(), Prov
.Arch()))
269 found_one
= false; // we found at least two
274 if (found_one
== true) {
275 ioprintf(out
, _("Note, selecting '%s' instead of '%s'\n"),
276 Prov
.FullName(true).c_str(), Pkg
.FullName(true).c_str());
277 return APT::VersionSet::FromPackage(Cache
, Prov
, select
, *this);
279 return APT::VersionSet();
282 inline bool allPkgNamedExplicitly() const { return explicitlyNamed
; }