diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc index 4130dc1a..cf1a92a6 100644 --- a/apt-pkg/cachefile.cc +++ b/apt-pkg/cachefile.cc @@ -1295,6 +1295,36 @@ void Stats(std::ostream &out, std::ostream &l_c3out, pkgDepCache &Dep, pkgDepCac } } /*}}}*/ +// IsVirtualPackage - Check if package is virtual (no versions, has providers) /*{{{*/ +// --------------------------------------------------------------------- +/* Virtual packages have no actual versions but are provided by other packages */ +static inline bool IsVirtualPackage(pkgCache::PkgIterator const &Pkg) +{ + return (Pkg->VersionList == 0) && (Pkg->ProvidesList != 0); +} + /*}}}*/ +// GetInstalledProviders - Get installed providers of a virtual package /*{{{*/ +// --------------------------------------------------------------------- +/* Returns list of all installed packages that provide the given virtual pkg */ +static std::vector GetInstalledProviders( + pkgCache::PkgIterator const &VirtualPkg, + pkgDepCache &Dep) +{ + std::vector Providers; + + for (pkgCache::PrvIterator Prv = VirtualPkg.ProvidesList(); + not Prv.end(); ++Prv) + { + pkgCache::PkgIterator Provider = Prv.OwnerPkg(); + if ((Provider->CurrentState == pkgCache::State::Installed) || + Dep[Provider].Install()) + { + Providers.push_back(Provider); + } + } + + return Providers; +} bool pkgDoAuto(std::ostream &c1out, const CommandLine &CmdL, int &auto_mark_changed, pkgDepCache &Dep) { @@ -1309,40 +1339,89 @@ bool pkgDoAuto(std::ostream &c1out, const CommandLine &CmdL, int &auto_mark_chan for (const char **I = CmdL.FileList + 1; *I != 0; ++I) { auto pkgiter = Dep.FindPkg(*I); - if (!pkgiter.end()) + if (pkgiter.end()) + { + continue; + } + + // Handle virtual packages: apply to all installed providers + if (IsVirtualPackage(pkgiter)) { - if ((pkgiter->CurrentState == pkgCache::State::NotInstalled) && (!Dep[pkgiter].NewInstall())) + std::vector Providers = GetInstalledProviders(pkgiter, Dep); + + if (Providers.empty()) { - ioprintf(c1out, _("%s can not be marked as it is not installed.\n"), pkgiter.Name()); + ioprintf(c1out, _("%s is a virtual package with no installed providers.\n"), pkgiter.Name()); continue; } - else if (((Dep[pkgiter].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == MarkAuto) + // Apply to each installed provider + for (auto const &Provider : Providers) { + if (((Dep[Provider].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == MarkAuto) + { + if (!MarkAuto) + { + ioprintf(c1out, _("%s (provider of %s) was already set to manually installed.\n"), + Provider.Name(), pkgiter.Name()); + } + else + { + ioprintf(c1out, _("%s (provider of %s) was already set to automatically installed.\n"), + Provider.Name(), pkgiter.Name()); + } + continue; + } + if (!MarkAuto) { - ioprintf(c1out,_("%s was already set to manually installed.\n"), pkgiter.Name()); + ioprintf(c1out, _("%s (provider of %s) set to manually installed.\n"), + Provider.Name(), pkgiter.Name()); } else { - ioprintf(c1out,_("%s was already set to automatically installed.\n"), pkgiter.Name()); + ioprintf(c1out, _("%s (provider of %s) set to automatically installed.\n"), + Provider.Name(), pkgiter.Name()); } - continue; + Dep.MarkAuto(Provider, MarkAuto ? pkgDepCache::AutoMarkFlag::Auto : pkgDepCache::AutoMarkFlag::Manual); + ++AutoMarkChanged; } + continue; + } + // Handle real packages (existing logic) + if ((pkgiter->CurrentState == pkgCache::State::NotInstalled) && (!Dep[pkgiter].NewInstall())) + { + ioprintf(c1out, _("%s can not be marked as it is not installed.\n"), pkgiter.Name()); + continue; + } + + if (((Dep[pkgiter].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == MarkAuto) + { if (!MarkAuto) { - ioprintf(c1out,_("%s set to manually installed.\n"), pkgiter.Name()); + ioprintf(c1out,_("%s was already set to manually installed.\n"), pkgiter.Name()); } else { - ioprintf(c1out,_("%s set to automatically installed.\n"), pkgiter.Name()); + ioprintf(c1out,_("%s was already set to automatically installed.\n"), pkgiter.Name()); } - Dep.MarkAuto(pkgiter, MarkAuto ? pkgDepCache::AutoMarkFlag::Auto : pkgDepCache::AutoMarkFlag::Manual); - ++AutoMarkChanged; + continue; } + + if (!MarkAuto) + { + ioprintf(c1out,_("%s set to manually installed.\n"), pkgiter.Name()); + } + else + { + ioprintf(c1out,_("%s set to automatically installed.\n"), pkgiter.Name()); + } + + Dep.MarkAuto(pkgiter, MarkAuto ? pkgDepCache::AutoMarkFlag::Auto : pkgDepCache::AutoMarkFlag::Manual); + ++AutoMarkChanged; } auto_mark_changed = AutoMarkChanged; @@ -1394,22 +1473,47 @@ bool pkgDoShowAuto(std::ostream &cout, const CommandLine &CmdL, pkgDepCache &Dep for (const char **I = CmdL.FileList + 1; *I != 0; ++I) { auto pkgiter = Dep.FindPkg(*I); - if (!pkgiter.end()) + if (pkgiter.end()) + { + continue; + } + + // Handle virtual packages: show state of all installed providers + if (IsVirtualPackage(pkgiter)) { - if ((pkgiter->CurrentState == pkgCache::State::Installed) || (Dep[pkgiter].Install())) + std::vector Providers = GetInstalledProviders(pkgiter, Dep); + + for (auto const &Provider : Providers) { - bool current_state_is_auto = ((Dep[pkgiter].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto); + bool current_state_is_auto = ((Dep[Provider].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto); if (ShowState) { std::stringstream str; - str << pkgiter.Name() << " " << (current_state_is_auto ? "auto" : "manual"); + str << Provider.Name() << " " << (current_state_is_auto ? "auto" : "manual"); packages.push_back(str.str()); } else if (current_state_is_auto == ShowAuto) { - packages.push_back(pkgiter.Name()); + packages.push_back(Provider.Name()); } } + continue; + } + + // Handle real packages (existing logic) + if ((pkgiter->CurrentState == pkgCache::State::Installed) || (Dep[pkgiter].Install())) + { + bool current_state_is_auto = ((Dep[pkgiter].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto); + if (ShowState) + { + std::stringstream str; + str << pkgiter.Name() << " " << (current_state_is_auto ? "auto" : "manual"); + packages.push_back(str.str()); + } + else if (current_state_is_auto == ShowAuto) + { + packages.push_back(pkgiter.Name()); + } } } }