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
*Cache
= CacheFile
.GetPkgCache();
34 pkgDepCache
*DepCache
= CacheFile
.GetDepCache();
35 APT::CacheSetHelper
helper(false);
39 progress
->SubProgress(Cache
->Head().PackageCount
, _("Sorting"));
41 bool const insertCurrentVer
= _config
->FindB("APT::Cmd::Installed", false);
42 bool const insertUpgradable
= _config
->FindB("APT::Cmd::Upgradable", false);
43 bool const insertManualInstalled
= _config
->FindB("APT::Cmd::Manual-Installed", false);
45 for (pkgCache::PkgIterator P
= Cache
->PkgBegin(); P
.end() == false; ++P
)
50 progress
->Progress(Done
);
54 // exclude virtual pkgs
55 if (P
->VersionList
== 0)
58 if ((matcher
)(P
) == false)
61 pkgDepCache::StateCache
&state
= (*DepCache
)[P
];
62 if (insertCurrentVer
== true)
64 if (P
->CurrentVer
!= 0)
65 vci
->FromPackage(vci
, CacheFile
, P
, APT::CacheSetHelper::INSTALLED
, helper
);
67 else if (insertUpgradable
== true)
69 if(P
.CurrentVer() && state
.Upgradable())
70 vci
->FromPackage(vci
, CacheFile
, P
, APT::CacheSetHelper::CANDIDATE
, helper
);
72 else if (insertManualInstalled
== true)
75 ((*DepCache
)[P
].Flags
& pkgCache::Flag::Auto
) == false)
76 vci
->FromPackage(vci
, CacheFile
, P
, APT::CacheSetHelper::CANDIDATE
, helper
);
80 if (vci
->FromPackage(vci
, CacheFile
, P
, APT::CacheSetHelper::CANDIDATE
, helper
) == false)
82 // no candidate, this may happen for packages in
83 // dpkg "deinstall ok config-file" state - we pick the first ver
84 // (which should be the only one)
85 vci
->insert(P
.VersionList());
95 // CacheSetHelper saving virtual packages /*{{{*/
96 pkgCache::VerIterator
CacheSetHelperVirtuals::canNotGetVersion(
97 enum CacheSetHelper::VerSelector
const select
,
99 pkgCache::PkgIterator
const &Pkg
)
101 if (select
== NEWEST
|| select
== CANDIDATE
|| select
== ALL
)
102 virtualPkgs
.insert(Pkg
);
103 return CacheSetHelper::canNotGetVersion(select
, Cache
, Pkg
);
105 void CacheSetHelperVirtuals::canNotFindVersion(
106 enum CacheSetHelper::VerSelector
const select
,
107 APT::VersionContainerInterface
* vci
,
109 pkgCache::PkgIterator
const &Pkg
)
111 if (select
== NEWEST
|| select
== CANDIDATE
|| select
== ALL
)
112 virtualPkgs
.insert(Pkg
);
113 return CacheSetHelper::canNotFindVersion(select
, vci
, Cache
, Pkg
);
115 static pkgCache::PkgIterator
canNotFindPkgName_impl(pkgCacheFile
&Cache
, std::string
const &str
)
117 std::string pkg
= str
;
118 size_t const archfound
= pkg
.find_last_of(':');
120 if (archfound
!= std::string::npos
) {
121 arch
= pkg
.substr(archfound
+1);
122 pkg
.erase(archfound
);
123 if (arch
== "all" || arch
== "native")
124 arch
= _config
->Find("APT::Architecture");
127 // If we don't find 'foo:amd64' look for 'foo:amd64:any'.
128 // Note: we prepare for an error here as if foo:amd64 does not exist,
129 // but foo:amd64:any it means that this package is only referenced in a
130 // (architecture specific) dependency. We do not add to virtualPkgs directly
131 // as we can't decide from here which error message has to be printed.
132 // FIXME: This doesn't match 'barbarian' architectures
133 pkgCache::PkgIterator
Pkg(Cache
, 0);
134 std::vector
<std::string
> const archs
= APT::Configuration::getArchitectures();
135 if (archfound
== std::string::npos
)
137 for (auto const &a
: archs
)
139 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
+ ':' + a
, "any");
140 if (Pkg
.end() == false && Pkg
->ProvidesList
!= 0)
143 if (Pkg
.end() == true)
144 for (auto const &a
: archs
)
146 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
+ ':' + a
, "any");
147 if (Pkg
.end() == false)
153 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
+ ':' + arch
, "any");
154 if (Pkg
.end() == true)
156 APT::CacheFilter::PackageArchitectureMatchesSpecification
pams(arch
);
157 for (auto const &a
: archs
)
159 if (pams(a
.c_str()) == false)
161 Pkg
= Cache
.GetPkgCache()->FindPkg(pkg
+ ':' + a
, "any");
162 if (Pkg
.end() == false)
169 pkgCache::PkgIterator
CacheSetHelperVirtuals::canNotFindPkgName(pkgCacheFile
&Cache
, std::string
const &str
)
171 pkgCache::PkgIterator
const Pkg
= canNotFindPkgName_impl(Cache
, str
);
173 return APT::CacheSetHelper::canNotFindPkgName(Cache
, str
);
176 CacheSetHelperVirtuals::CacheSetHelperVirtuals(bool const ShowErrors
, GlobalError::MsgType
const &ErrorType
) :
177 CacheSetHelper
{ShowErrors
, ErrorType
}
181 // CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/
182 CacheSetHelperAPTGet::CacheSetHelperAPTGet(std::ostream
&pout
) :
183 APT::CacheSetHelper
{true}, out(pout
)
185 explicitlyNamed
= true;
187 void CacheSetHelperAPTGet::showTaskSelection(pkgCache::PkgIterator
const &Pkg
, std::string
const &pattern
)
189 ioprintf(out
, _("Note, selecting '%s' for task '%s'\n"),
190 Pkg
.FullName(true).c_str(), pattern
.c_str());
191 explicitlyNamed
= false;
193 void CacheSetHelperAPTGet::showFnmatchSelection(pkgCache::PkgIterator
const &Pkg
, std::string
const &pattern
)
195 ioprintf(out
, _("Note, selecting '%s' for glob '%s'\n"),
196 Pkg
.FullName(true).c_str(), pattern
.c_str());
197 explicitlyNamed
= false;
199 void CacheSetHelperAPTGet::showRegExSelection(pkgCache::PkgIterator
const &Pkg
, std::string
const &pattern
)
201 ioprintf(out
, _("Note, selecting '%s' for regex '%s'\n"),
202 Pkg
.FullName(true).c_str(), pattern
.c_str());
203 explicitlyNamed
= false;
205 void CacheSetHelperAPTGet::showSelectedVersion(pkgCache::PkgIterator
const &/*Pkg*/, pkgCache::VerIterator
const Ver
,
206 std::string
const &ver
, bool const /*verIsRel*/)
208 if (ver
== Ver
.VerStr())
210 selectedByRelease
.push_back(make_pair(Ver
, ver
));
212 bool CacheSetHelperAPTGet::showVirtualPackageErrors(pkgCacheFile
&Cache
)
214 if (virtualPkgs
.empty() == true)
216 for (APT::PackageSet::const_iterator Pkg
= virtualPkgs
.begin();
217 Pkg
!= virtualPkgs
.end(); ++Pkg
) {
218 if (Pkg
->ProvidesList
!= 0) {
219 ioprintf(c1out
,_("Package %s is a virtual package provided by:\n"),
220 Pkg
.FullName(true).c_str());
222 pkgCache::PrvIterator I
= Pkg
.ProvidesList();
223 unsigned short provider
= 0;
224 for (; I
.end() == false; ++I
) {
225 pkgCache::PkgIterator Pkg
= I
.OwnerPkg();
227 if (Cache
[Pkg
].CandidateVerIter(Cache
) == I
.OwnerVer()) {
228 c1out
<< " " << Pkg
.FullName(true) << " " << I
.OwnerVer().VerStr();
229 if (Cache
[Pkg
].Install() == true && Cache
[Pkg
].NewInstall() == false)
230 c1out
<< _(" [Installed]");
235 // if we found no candidate which provide this package, show non-candidates
237 for (I
= Pkg
.ProvidesList(); I
.end() == false; ++I
)
238 c1out
<< " " << I
.OwnerPkg().FullName(true) << " " << I
.OwnerVer().VerStr()
239 << _(" [Not candidate version]") << std::endl
;
241 out
<< _("You should explicitly select one to install.") << std::endl
;
244 _("Package %s is not available, but is referred to by another package.\n"
245 "This may mean that the package is missing, has been obsoleted, or\n"
246 "is only available from another source\n"),Pkg
.FullName(true).c_str());
248 std::vector
<bool> Seen(Cache
.GetPkgCache()->Head().PackageCount
, false);
249 APT::PackageList pkglist
;
250 for (pkgCache::DepIterator Dep
= Pkg
.RevDependsList();
251 Dep
.end() == false; ++Dep
) {
252 if (Dep
->Type
!= pkgCache::Dep::Replaces
)
254 pkgCache::PkgIterator
const DP
= Dep
.ParentPkg();
255 if (Seen
[DP
->ID
] == true)
260 ShowList(c1out
, _("However the following packages replace it:"), pkglist
,
261 &AlwaysTrue
, &PrettyFullName
, &EmptyString
);
267 pkgCache::VerIterator
CacheSetHelperAPTGet::canNotFindCandidateVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
)
269 APT::VersionSet
const verset
= tryVirtualPackage(Cache
, Pkg
, CacheSetHelper::CANDIDATE
);
270 if (verset
.empty() == false)
271 return *(verset
.begin());
272 else if (ShowError
== true) {
273 _error
->Error(_("Package '%s' has no installation candidate"),Pkg
.FullName(true).c_str());
274 virtualPkgs
.insert(Pkg
);
276 return pkgCache::VerIterator(Cache
, 0);
278 pkgCache::VerIterator
CacheSetHelperAPTGet::canNotFindNewestVer(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
)
280 if (Pkg
->ProvidesList
!= 0)
282 APT::VersionSet
const verset
= tryVirtualPackage(Cache
, Pkg
, CacheSetHelper::NEWEST
);
283 if (verset
.empty() == false)
284 return *(verset
.begin());
285 if (ShowError
== true)
286 ioprintf(out
, _("Virtual packages like '%s' can't be removed\n"), Pkg
.FullName(true).c_str());
290 pkgCache::GrpIterator Grp
= Pkg
.Group();
291 pkgCache::PkgIterator P
= Grp
.PackageList();
292 for (; P
.end() != true; P
= Grp
.NextPkg(P
))
296 if (P
->CurrentVer
!= 0) {
297 // TRANSLATORS: Note, this is not an interactive question
298 ioprintf(c1out
,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
299 Pkg
.FullName(true).c_str(), P
.FullName(true).c_str());
304 ioprintf(c1out
,_("Package '%s' is not installed, so not removed\n"),Pkg
.FullName(true).c_str());
306 return pkgCache::VerIterator(Cache
, 0);
308 APT::VersionSet
CacheSetHelperAPTGet::tryVirtualPackage(pkgCacheFile
&Cache
, pkgCache::PkgIterator
const &Pkg
,
309 CacheSetHelper::VerSelector
const select
)
311 /* This is a pure virtual package and there is a single available
312 candidate providing it. */
313 if (unlikely(Cache
[Pkg
].CandidateVer
!= 0) || Pkg
->ProvidesList
== 0)
314 return APT::VersionSet();
316 pkgCache::PkgIterator Prov
;
317 bool found_one
= false;
318 for (pkgCache::PrvIterator P
= Pkg
.ProvidesList(); P
; ++P
) {
319 pkgCache::VerIterator
const PVer
= P
.OwnerVer();
320 pkgCache::PkgIterator
const PPkg
= PVer
.ParentPkg();
322 /* Ignore versions that are not a candidate. */
323 if (Cache
[PPkg
].CandidateVer
!= PVer
)
326 if (found_one
== false) {
329 } else if (PPkg
!= Prov
) {
330 // same group, so it's a foreign package
331 if (PPkg
->Group
== Prov
->Group
) {
332 // do we already have the requested arch?
333 if (strcmp(Pkg
.Arch(), Prov
.Arch()) == 0 ||
334 strcmp(Prov
.Arch(), "all") == 0 ||
335 unlikely(strcmp(PPkg
.Arch(), Prov
.Arch()) == 0)) // packages have only on candidate, but just to be sure
337 // see which architecture we prefer more and switch to it
338 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
339 if (std::find(archs
.begin(), archs
.end(), PPkg
.Arch()) < std::find(archs
.begin(), archs
.end(), Prov
.Arch()))
343 found_one
= false; // we found at least two
348 if (found_one
== true) {
349 ioprintf(out
, _("Note, selecting '%s' instead of '%s'\n"),
350 Prov
.FullName(true).c_str(), Pkg
.FullName(true).c_str());
351 return APT::VersionSet::FromPackage(Cache
, Prov
, select
, *this);
353 return APT::VersionSet();
355 pkgCache::PkgIterator
CacheSetHelperAPTGet::canNotFindPkgName(pkgCacheFile
&Cache
, std::string
const &str
)
357 pkgCache::PkgIterator
const Pkg
= canNotFindPkgName_impl(Cache
, str
);
359 return APT::CacheSetHelper::canNotFindPkgName(Cache
, str
);