+// CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/
+class CacheSetHelperAPTGet : public APT::CacheSetHelper {
+ /** \brief stream message should be printed to */
+ std::ostream &out;
+ /** \brief were things like Task or RegEx used to select packages? */
+ bool explicitlyNamed;
+
+ APT::PackageSet virtualPkgs;
+
+public:
+ CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) {
+ explicitlyNamed = true;
+ }
+
+ virtual void showTaskSelection(APT::PackageSet const &pkgset, string const &pattern) {
+ for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+ ioprintf(out, _("Note, selecting '%s' for task '%s'\n"),
+ Pkg.FullName(true).c_str(), pattern.c_str());
+ explicitlyNamed = false;
+ }
+ virtual void showRegExSelection(APT::PackageSet const &pkgset, string const &pattern) {
+ for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+ ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"),
+ Pkg.FullName(true).c_str(), pattern.c_str());
+ explicitlyNamed = false;
+ }
+ virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
+ string const &ver, bool const &verIsRel) {
+ if (ver != Ver.VerStr())
+ ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
+ Ver.VerStr(), Ver.RelStr().c_str(), Pkg.FullName(true).c_str());
+ }
+
+ bool showVirtualPackageErrors(pkgCacheFile &Cache) {
+ if (virtualPkgs.empty() == true)
+ return true;
+ for (APT::PackageSet::const_iterator Pkg = virtualPkgs.begin();
+ Pkg != virtualPkgs.end(); ++Pkg) {
+ if (Pkg->ProvidesList != 0) {
+ ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
+ Pkg.FullName(true).c_str());
+
+ pkgCache::PrvIterator I = Pkg.ProvidesList();
+ unsigned short provider = 0;
+ for (; I.end() == false; ++I) {
+ pkgCache::PkgIterator Pkg = I.OwnerPkg();
+
+ if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer()) {
+ out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr();
+ if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
+ out << _(" [Installed]");
+ out << endl;
+ ++provider;
+ }
+ }
+ // if we found no candidate which provide this package, show non-candidates
+ if (provider == 0)
+ for (I = Pkg.ProvidesList(); I.end() == false; I++)
+ out << " " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr()
+ << _(" [Not candidate version]") << endl;
+ else
+ out << _("You should explicitly select one to install.") << endl;
+ } else {
+ ioprintf(out,
+ _("Package %s is not available, but is referred to by another package.\n"
+ "This may mean that the package is missing, has been obsoleted, or\n"
+ "is only available from another source\n"),Pkg.FullName(true).c_str());
+
+ string List;
+ string VersionsList;
+ SPtrArray<bool> Seen = new bool[Cache.GetPkgCache()->Head().PackageCount];
+ memset(Seen,0,Cache.GetPkgCache()->Head().PackageCount*sizeof(*Seen));
+ for (pkgCache::DepIterator Dep = Pkg.RevDependsList();
+ Dep.end() == false; Dep++) {
+ if (Dep->Type != pkgCache::Dep::Replaces)
+ continue;
+ if (Seen[Dep.ParentPkg()->ID] == true)
+ continue;
+ Seen[Dep.ParentPkg()->ID] = true;
+ List += Dep.ParentPkg().FullName(true) + " ";
+ //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
+ }
+ ShowList(out,_("However the following packages replace it:"),List,VersionsList);
+ }
+ out << std::endl;
+ }
+ return false;
+ }
+
+ virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+ APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDIDATE);
+ if (verset.empty() == false)
+ return *(verset.begin());
+ if (ShowError == true) {
+ _error->Error(_("Package '%s' has no installation candidate"),Pkg.FullName(true).c_str());
+ virtualPkgs.insert(Pkg);
+ }
+ return pkgCache::VerIterator(Cache, 0);
+ }
+
+ virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+ APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST);
+ if (verset.empty() == false)
+ return *(verset.begin());
+ if (ShowError == true)
+ ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str());
+ return pkgCache::VerIterator(Cache, 0);
+ }
+
+ APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg,
+ APT::VersionSet::Version const &select) {
+ /* This is a pure virtual package and there is a single available
+ candidate providing it. */
+ if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0)
+ return APT::VersionSet();
+
+ pkgCache::PkgIterator Prov;
+ bool found_one = false;
+ for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; ++P) {
+ pkgCache::VerIterator const PVer = P.OwnerVer();
+ pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
+
+ /* Ignore versions that are not a candidate. */
+ if (Cache[PPkg].CandidateVer != PVer)
+ continue;
+
+ if (found_one == false) {
+ Prov = PPkg;
+ found_one = true;
+ } else if (PPkg != Prov) {
+ found_one = false; // we found at least two
+ break;
+ }
+ }
+
+ if (found_one == true) {
+ ioprintf(out, _("Note, selecting '%s' instead of '%s'\n"),
+ Prov.FullName(true).c_str(), Pkg.FullName(true).c_str());
+ return APT::VersionSet::FromPackage(Cache, Prov, select, *this);
+ }
+ return APT::VersionSet();
+ }
+
+ inline bool allPkgNamedExplicitly() const { return explicitlyNamed; }
+
+};
+ /*}}}*/
+// TryToInstall - Mark a package for installation /*{{{*/
+struct TryToInstall {
+ pkgCacheFile* Cache;
+ pkgProblemResolver* Fix;
+ bool FixBroken;
+ unsigned long AutoMarkChanged;
+ APT::PackageSet doAutoInstallLater;
+
+ TryToInstall(pkgCacheFile &Cache, pkgProblemResolver &PM, bool const &FixBroken) : Cache(&Cache), Fix(&PM),
+ FixBroken(FixBroken), AutoMarkChanged(0) {};
+
+ void operator() (pkgCache::VerIterator const &Ver) {
+ pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+
+ Cache->GetDepCache()->SetCandidateVersion(Ver);
+ pkgDepCache::StateCache &State = (*Cache)[Pkg];
+
+ // Handle the no-upgrade case
+ if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0)
+ ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
+ Pkg.FullName(true).c_str());
+ // Ignore request for install if package would be new
+ else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0)
+ ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
+ Pkg.FullName(true).c_str());
+ else {
+ Fix->Clear(Pkg);
+ Fix->Protect(Pkg);
+ Cache->GetDepCache()->MarkInstall(Pkg,false);
+
+ if (State.Install() == false) {
+ if (_config->FindB("APT::Get::ReInstall",false) == true) {
+ if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
+ ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
+ Pkg.FullName(true).c_str());
+ else
+ Cache->GetDepCache()->SetReInstall(Pkg, true);
+ } else
+ ioprintf(c1out,_("%s is already the newest version.\n"),
+ Pkg.FullName(true).c_str());
+ }
+
+ // Install it with autoinstalling enabled (if we not respect the minial
+ // required deps or the policy)
+ if (FixBroken == false)
+ doAutoInstallLater.insert(Pkg);
+ }
+
+ // see if we need to fix the auto-mark flag
+ // e.g. apt-get install foo
+ // where foo is marked automatic
+ if (State.Install() == false &&
+ (State.Flags & pkgCache::Flag::Auto) &&
+ _config->FindB("APT::Get::ReInstall",false) == false &&
+ _config->FindB("APT::Get::Only-Upgrade",false) == false &&
+ _config->FindB("APT::Get::Download-Only",false) == false)
+ {
+ ioprintf(c1out,_("%s set to manually installed.\n"),
+ Pkg.FullName(true).c_str());
+ Cache->GetDepCache()->MarkAuto(Pkg,false);
+ AutoMarkChanged++;
+ }
+ }
+
+ void doAutoInstall() {
+ for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
+ P != doAutoInstallLater.end(); ++P) {
+ pkgDepCache::StateCache &State = (*Cache)[P];
+ if (State.InstBroken() == false && State.InstPolicyBroken() == false)
+ continue;
+ Cache->GetDepCache()->MarkInstall(P, true);
+ }
+ doAutoInstallLater.clear();
+ }
+};
+ /*}}}*/
+// TryToRemove - Mark a package for removal /*{{{*/
+struct TryToRemove {
+ pkgCacheFile* Cache;
+ pkgProblemResolver* Fix;
+ bool FixBroken;
+ bool PurgePkgs;
+ unsigned long AutoMarkChanged;
+
+ TryToRemove(pkgCacheFile &Cache, pkgProblemResolver &PM) : Cache(&Cache), Fix(&PM),
+ PurgePkgs(_config->FindB("APT::Get::Purge", false)) {};
+
+ void operator() (pkgCache::VerIterator const &Ver)
+ {
+ pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+
+ Fix->Clear(Pkg);
+ Fix->Protect(Pkg);
+ Fix->Remove(Pkg);
+
+ if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
+ (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
+ ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str());
+ else
+ Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs);
+ }
+};
+ /*}}}*/