3 #include <apt-pkg/cachefile.h>
4 #include <apt-pkg/pkgcache.h>
5 #include <apt-pkg/depcache.h>
6 #include <apt-pkg/cacheiterators.h>
7 #include <apt-pkg/cachefilter.h>
8 #include <apt-pkg/aptconfiguration.h>
9 #include <apt-pkg/configuration.h>
10 #include <apt-pkg/progress.h>
11 #include <apt-pkg/policy.h>
12 #include <apt-pkg/strutl.h>
14 #include <apt-private/private-cacheset.h>
20 bool GetLocalitySortedVersionSet(pkgCacheFile
&CacheFile
, /*{{{*/
21 APT::VersionContainerInterface
* const vci
,
22 OpProgress
* const progress
)
24 Matcher null_matcher
= Matcher();
25 return GetLocalitySortedVersionSet(CacheFile
, vci
,
26 null_matcher
, progress
);
28 bool GetLocalitySortedVersionSet(pkgCacheFile
&CacheFile
,
29 APT::VersionContainerInterface
* const vci
,
31 OpProgress
* const progress
)
33 pkgCache
* const Cache
= CacheFile
.GetPkgCache();
34 if (unlikely(Cache
== nullptr))
36 if (progress
!= nullptr)
37 progress
->SubProgress(Cache
->Head().PackageCount
, _("Sorting"));
39 pkgDepCache
* const DepCache
= CacheFile
.GetDepCache();
40 if (unlikely(DepCache
== nullptr))
42 APT::CacheSetHelper
helper(false);
46 bool const insertCurrentVer
= _config
->FindB("APT::Cmd::Installed", false);
47 bool const insertUpgradable
= _config
->FindB("APT::Cmd::Upgradable", false);
48 bool const insertManualInstalled
= _config
->FindB("APT::Cmd::Manual-Installed", false);
50 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
55 progress
->Progress(Done
);
59 // exclude virtual pkgs
60 if (P
->VersionList
== 0)
63 if ((matcher
)(P
) == false)
66 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
67 if (insertCurrentVer
== true)
69 if (P
->CurrentVer
!= 0)
70 vci
->FromPackage(vci
, CacheFile
, P
, APT::CacheSetHelper::INSTALLED
, helper
);
72 else if (insertUpgradable
== true)
74 if(P
.CurrentVer() && state
.Upgradable())
75 vci
->FromPackage(vci
, CacheFile
, P
, APT::CacheSetHelper::CANDIDATE
, helper
);
77 else if (insertManualInstalled
== true)
80 ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
) == false)
81 vci
->FromPackage(vci
, CacheFile
, P
, APT::CacheSetHelper::CANDIDATE
, helper
);
85 if (vci
->FromPackage(vci
, CacheFile
, P
, APT::CacheSetHelper::CANDIDATE
, helper
) == false)
87 // no candidate, this may happen for packages in
88 // dpkg "deinstall ok config-file" state - we pick the first ver
89 // (which should be the only one)
90 vci
->insert(P
.VersionList());
100 // CacheSetHelper saving virtual packages /*{{{*/
101 pkgCache::VerIterator
CacheSetHelperVirtuals::canNotGetVersion(
102 enum CacheSetHelper::VerSelector
const select
,
104 pkgCache::PkgIterator
const &Pkg
)
106 if (select
== NEWEST
|| select
== CANDIDATE
|| select
== ALL
)
107 virtualPkgs
.insert(Pkg
);
108 return CacheSetHelper::canNotGetVersion(select
, Cache
, Pkg
);
110 void CacheSetHelperVirtuals::canNotFindVersion(
111 enum CacheSetHelper::VerSelector
const select
,
112 APT::VersionContainerInterface
* vci
,
114 pkgCache::PkgIterator
const &Pkg
)
116 if (select
== NEWEST
|| select
== CANDIDATE
|| select
== ALL
)
117 virtualPkgs
.insert(Pkg
);
118 return CacheSetHelper::canNotFindVersion(select
, vci
, Cache
, Pkg
);
120 static pkgCache::PkgIterator
canNotFindPkgName_impl(pkgCacheFile
&Cache
, std::string
const &str
)
122 std::string pkg
= str
;
123 size_t const archfound
= pkg
.find_last_of(':');
125 if (archfound
!= std::string::npos
) {
126 arch
= pkg
.substr(archfound
+1);
127 pkg
.erase(archfound
);
128 if (arch
== "all" || arch
== "native")
129 arch
= _config
->Find("APT::Architecture");
132 // If we don't find 'foo:amd64' look for 'foo:amd64:any'.
133 // Note: we prepare for an error here as if foo:amd64 does not exist,
134 // but foo:amd64:any it means that this package is only referenced in a
135 // (architecture specific) dependency. We do not add to virtualPkgs directly
136 // as we can't decide from here which error message has to be printed.
137 // FIXME: This doesn't match 'barbarian' architectures
138 pkgCache::PkgIterator
Pkg(Cache
, 0);
139 std::vector
<std::string
> const archs
= APT::Configuration::getArchitectures();
140 if (archfound
== std::string::npos
)
142 for (auto const &a
: archs
)
144 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
+ ':' + a
, "any");
145 if (Pkg
.end() == false && Pkg
->ProvidesList
!= 0)
148 if (Pkg
.end() == true)
149 for (auto const &a
: archs
)
151 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
+ ':' + a
, "any");
152 if (Pkg
.end() == false)
158 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
+ ':' + arch
, "any");
159 if (Pkg
.end() == true)
161 APT::CacheFilter::PackageArchitectureMatchesSpecification
pams(arch
);
162 for (auto const &a
: archs
)
164 if (pams(a
.c_str()) == false)
166 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
+ ':' + a
, "any");
167 if (Pkg
.end() == false)
174 pkgCache::PkgIterator
CacheSetHelperVirtuals::canNotFindPkgName(pkgCacheFile
&Cache
, std::string
const &str
)
176 pkgCache::PkgIterator
const Pkg
= canNotFindPkgName_impl(Cache
, str
);
178 return APT::CacheSetHelper::canNotFindPkgName(Cache
, str
);
181 CacheSetHelperVirtuals::CacheSetHelperVirtuals(bool const ShowErrors
, GlobalError::MsgType
const &ErrorType
) :
182 CacheSetHelper
{ShowErrors
, ErrorType
}
186 // CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/
187 CacheSetHelperAPTGet::CacheSetHelperAPTGet(std::ostream
&pout
) :
188 APT::CacheSetHelper
{true}, out(pout
)
190 explicitlyNamed
= true;
192 void CacheSetHelperAPTGet::showTaskSelection(pkgCache::PkgIterator
const &Pkg
, std::string
const &pattern
)
194 ioprintf(out
, _("Note, selecting '%s' for task '%s'\n"),
195 Pkg
.FullName(true).c_str(), pattern
.c_str());
196 explicitlyNamed
= false;
198 void CacheSetHelperAPTGet::showFnmatchSelection(pkgCache::PkgIterator
const &Pkg
, std::string
const &pattern
)
200 ioprintf(out
, _("Note, selecting '%s' for glob '%s'\n"),
201 Pkg
.FullName(true).c_str(), pattern
.c_str());
202 explicitlyNamed
= false;
204 void CacheSetHelperAPTGet::showRegExSelection(pkgCache::PkgIterator
const &Pkg
, std::string
const &pattern
)
206 ioprintf(out
, _("Note, selecting '%s' for regex '%s'\n"),
207 Pkg
.FullName(true).c_str(), pattern
.c_str());
208 explicitlyNamed
= false;
210 void CacheSetHelperAPTGet::showSelectedVersion(pkgCache::PkgIterator
const &/*Pkg*/, pkgCache::VerIterator
const Ver
,
211 std::string
const &ver
, bool const /*verIsRel*/)
213 if (ver
== Ver
.VerStr())
215 selectedByRelease
.push_back(make_pair(Ver
, ver
));
217 bool CacheSetHelperAPTGet::showVirtualPackageErrors(pkgCacheFile
&Cache
)
219 if (virtualPkgs
.empty() == true)
221 for (APT::PackageSet::const_iterator Pkg
= virtualPkgs
.begin();
222 Pkg
!= virtualPkgs
.end(); ++Pkg
) {
223 if (Pkg
->ProvidesList
!= 0) {
224 ioprintf(c1out
,_("Package %s is a virtual package provided by:\n"),
225 Pkg
.FullName(true).c_str());
227 pkgCache::PrvIterator I
= Pkg
.ProvidesList();
228 unsigned short provider
= 0;
229 for (; I
.end() == false; ++I
) {
230 pkgCache::PkgIterator Pkg
= I
.OwnerPkg();
232 if (Cache
[Pkg
].CandidateVerIter(Cache
) == I
.OwnerVer()) {
233 c1out
<< " " << Pkg
.FullName(true) << " " << I
.OwnerVer().VerStr();
234 if (Cache
[Pkg
].Install() == true && Cache
[Pkg
].NewInstall() == false)
235 c1out
<< _(" [Installed]");
240 // if we found no candidate which provide this package, show non-candidates
242 for (I
= Pkg
.ProvidesList(); I
.end() == false; ++I
)
243 c1out
<< " " << I
.OwnerPkg().FullName(true) << " " << I
.OwnerVer().VerStr()
244 << _(" [Not candidate version]") << std::endl
;
246 out
<< _("You should explicitly select one to install.") << std::endl
;
249 _("Package %s is not available, but is referred to by another package.\n"
250 "This may mean that the package is missing, has been obsoleted, or\n"
251 "is only available from another source\n"),Pkg
.FullName(true).c_str());
253 std::vector
<bool> Seen(Cache
.GetPkgCache()->Head().PackageCount
, false);
254 APT::PackageList pkglist
;
255 for (pkgCache::DepIterator Dep
= Pkg
.RevDependsList();
256 Dep
.end() == false; ++Dep
) {
257 if (Dep
->Type
!= pkgCache::Dep::Replaces
)
259 pkgCache::PkgIterator
const DP
= Dep
.ParentPkg();
260 if (Seen
[DP
->ID
] == true)
265 ShowList(c1out
, _("However the following packages replace it:"), pkglist
,
266 &AlwaysTrue
, &PrettyFullName
, &EmptyString
);
272 pkgCache::VerIterator
CacheSetHelperAPTGet::canNotFindCandidateVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
)
274 APT::VersionSet
const verset
= tryVirtualPackage(Cache
, Pkg
, CacheSetHelper::CANDIDATE
);
275 if (verset
.empty() == false)
276 return *(verset
.begin());
277 else if (ShowError
== true) {
278 _error
->Error(_("Package '%s' has no installation candidate"),Pkg
.FullName(true).c_str());
279 virtualPkgs
.insert(Pkg
);
281 return pkgCache::VerIterator(Cache
, 0);
283 pkgCache::VerIterator
CacheSetHelperAPTGet::canNotFindNewestVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
)
285 if (Pkg
->ProvidesList
!= 0)
287 APT::VersionSet
const verset
= tryVirtualPackage(Cache
, Pkg
, CacheSetHelper::NEWEST
);
288 if (verset
.empty() == false)
289 return *(verset
.begin());
290 if (ShowError
== true)
291 ioprintf(out
, _("Virtual packages like '%s' can't be removed\n"), Pkg
.FullName(true).c_str());
295 pkgCache::GrpIterator Grp
= Pkg
.Group();
296 pkgCache::PkgIterator P
= Grp
.PackageList();
297 for (; P
.end() != true; P
= Grp
.NextPkg(P
))
301 if (P
->CurrentVer
!= 0) {
302 // TRANSLATORS: Note, this is not an interactive question
303 ioprintf(c1out
,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
304 Pkg
.FullName(true).c_str(), P
.FullName(true).c_str());
309 ioprintf(c1out
,_("Package '%s' is not installed, so not removed\n"),Pkg
.FullName(true).c_str());
311 return pkgCache::VerIterator(Cache
, 0);
313 APT::VersionSet
CacheSetHelperAPTGet::tryVirtualPackage(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
,
314 CacheSetHelper::VerSelector
const select
)
316 /* This is a pure virtual package and there is a single available
317 candidate providing it. */
318 if (unlikely(Cache
[Pkg
].CandidateVer
!= 0) || Pkg
->ProvidesList
== 0)
319 return APT::VersionSet();
321 pkgCache::PkgIterator Prov
;
322 bool found_one
= false;
323 for (pkgCache::PrvIterator P
= Pkg
.ProvidesList(); P
; ++P
) {
324 pkgCache::VerIterator
const PVer
= P
.OwnerVer();
325 pkgCache::PkgIterator
const PPkg
= PVer
.ParentPkg();
327 /* Ignore versions that are not a candidate. */
328 if (Cache
[PPkg
].CandidateVer
!= PVer
)
331 if (found_one
== false) {
334 } else if (PPkg
!= Prov
) {
335 // same group, so it's a foreign package
336 if (PPkg
->Group
== Prov
->Group
) {
337 // do we already have the requested arch?
338 if (strcmp(Pkg
.Arch(), Prov
.Arch()) == 0 ||
339 strcmp(Prov
.Arch(), "all") == 0 ||
340 unlikely(strcmp(PPkg
.Arch(), Prov
.Arch()) == 0)) // packages have only on candidate, but just to be sure
342 // see which architecture we prefer more and switch to it
343 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
344 if (std::find(archs
.begin(), archs
.end(), PPkg
.Arch()) < std::find(archs
.begin(), archs
.end(), Prov
.Arch()))
348 found_one
= false; // we found at least two
353 if (found_one
== true) {
354 ioprintf(out
, _("Note, selecting '%s' instead of '%s'\n"),
355 Prov
.FullName(true).c_str(), Pkg
.FullName(true).c_str());
356 return APT::VersionSet::FromPackage(Cache
, Prov
, select
, *this);
358 return APT::VersionSet();
360 pkgCache::PkgIterator
CacheSetHelperAPTGet::canNotFindPkgName(pkgCacheFile
&Cache
, std::string
const &str
)
362 pkgCache::PkgIterator
const Pkg
= canNotFindPkgName_impl(Cache
, str
);
364 return APT::CacheSetHelper::canNotFindPkgName(Cache
, str
);