diff options
Diffstat (limited to 'cmdline/apt-get.cc')
-rw-r--r-- | cmdline/apt-get.cc | 709 |
1 files changed, 322 insertions, 387 deletions
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 0ada46c73..7cf760c27 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -40,12 +40,12 @@ #include <apt-pkg/sptr.h> #include <apt-pkg/md5.h> #include <apt-pkg/versionmatch.h> -#include <apt-pkg/cacheset.h> #include <config.h> #include <apti18n.h> #include "acqprogress.h" +#include "cacheset.h" #include <set> #include <locale.h> @@ -609,6 +609,253 @@ void Stats(ostream &out,pkgDepCache &Dep) Dep.BadCount()); } /*}}}*/ +// 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; + unsigned long AutoMarkChanged; + + TryToRemove(pkgCacheFile &Cache, pkgProblemResolver &PM) : Cache(&Cache), Fix(&PM) {}; + + void operator() (pkgCache::VerIterator const &Ver) + { + pkgCache::PkgIterator Pkg = Ver.ParentPkg(); + + Fix->Clear(Pkg); + Fix->Protect(Pkg); + Fix->Remove(Pkg); + + if (Pkg->CurrentVer == 0) + ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str()); + else + Cache->GetDepCache()->MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false)); + } +}; + /*}}}*/ // CacheFile::NameComp - QSort compare by name /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -1073,219 +1320,35 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, return true; } /*}}}*/ -// TryToInstall - Try to install a single package /*{{{*/ +// TryToInstallBuildDep - Try to install a single package /*{{{*/ // --------------------------------------------------------------------- /* This used to be inlined in DoInstall, but with the advent of regex package name matching it was split out.. */ -bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache, +bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache, pkgProblemResolver &Fix,bool Remove,bool BrokenFix, - unsigned int &ExpectedInst,bool AllowFail = true) + bool AllowFail = true) { - /* This is a pure virtual package and there is a single available - candidate providing it. */ if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0) { - 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(c1out,_("Note, selecting %s instead of %s\n"), - Prov.FullName(true).c_str(),Pkg.FullName(true).c_str()); - Pkg = Prov; - } + CacheSetHelperAPTGet helper(c1out); + helper.showErrors(AllowFail == false); + pkgCache::VerIterator Ver = helper.canNotFindNewestVer(Cache, Pkg); + if (Ver.end() == false) + Pkg = Ver.ParentPkg(); + else if (helper.showVirtualPackageErrors(Cache) == false) + return AllowFail; } - // Handle the no-upgrade case - if (_config->FindB("APT::Get::upgrade",true) == false && - Pkg->CurrentVer != 0) - { - if (AllowFail == true) - ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"), - Pkg.FullName(true).c_str()); - return true; - } - - // Ignore request for install if package would be new - if (_config->FindB("APT::Get::Only-Upgrade", false) == true && - Pkg->CurrentVer == 0) - { - if (AllowFail == true) - ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"), - Pkg.Name()); - return true; - } - - // Check if there is something at all to install - pkgDepCache::StateCache &State = Cache[Pkg]; - if (Remove == true && Pkg->CurrentVer == 0) - { - Fix.Clear(Pkg); - Fix.Protect(Pkg); - Fix.Remove(Pkg); - - /* We want to continue searching for regex hits, so we return false here - otherwise this is not really an error. */ - if (AllowFail == false) - return false; - - ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str()); - return true; - } - - if (State.CandidateVer == 0 && Remove == false) - { - if (AllowFail == false) - return false; - - 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()) - { - c1out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr(); - if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false) - c1out << _(" [Installed]"); - c1out << 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++) - c1out << " " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr() - << _(" [Not candidate version]") << endl; - else - c1out << _("You should explicitly select one to install.") << endl; - } - else - { - ioprintf(c1out, - _("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.Head().PackageCount]; - memset(Seen,0,Cache.Head().PackageCount*sizeof(*Seen)); - pkgCache::DepIterator Dep = Pkg.RevDependsList(); - for (; 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(c1out,_("However the following packages replace it:"),List,VersionsList); - } - - _error->Error(_("Package %s has no installation candidate"),Pkg.FullName(true).c_str()); - return false; - } - - Fix.Clear(Pkg); - Fix.Protect(Pkg); if (Remove == true) { - Fix.Remove(Pkg); - Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false)); - return true; - } - - // Install it - Cache.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.SetReInstall(Pkg,true); - } - else - { - if (AllowFail == true) - ioprintf(c1out,_("%s is already the newest version.\n"), - Pkg.FullName(true).c_str()); - } - } - else - ExpectedInst++; - - // Install it with autoinstalling enabled (if we not respect the minial - // required deps or the policy) - if ((State.InstBroken() == true || State.InstPolicyBroken() == true) && BrokenFix == false) - Cache.MarkInstall(Pkg,true); - - return true; -} - /*}}}*/ -// TryToChangeVer - Try to change a candidate version /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool TryToChangeVer(pkgCache::PkgIterator Pkg,pkgDepCache &Cache, - const char *VerTag,bool IsRel) -{ - pkgVersionMatch Match(VerTag,(IsRel == true?pkgVersionMatch::Release : - pkgVersionMatch::Version)); - - pkgCache::VerIterator Ver = Match.Find(Pkg); - - if (Ver.end() == true) - { - if (IsRel == true) - return _error->Error(_("Release '%s' for '%s' was not found"), - VerTag,Pkg.FullName(true).c_str()); - return _error->Error(_("Version '%s' for '%s' was not found"), - VerTag,Pkg.FullName(true).c_str()); - } - - if (strcmp(VerTag,Ver.VerStr()) != 0) - { - ioprintf(c1out,_("Selected version %s (%s) for %s\n"), - Ver.VerStr(),Ver.RelStr().c_str(),Pkg.FullName(true).c_str()); - } - - Cache.SetCandidateVersion(Ver); - - // Set the all package to the same candidate - if (Ver.Pseudo() == true) - Cache.SetCandidateVersion(Match.Find(Pkg.Group().FindPkg("all"))); + TryToRemove RemoveAction(Cache, Fix); + RemoveAction(Pkg.VersionList()); + } else if (Cache[Pkg].CandidateVer != 0) { + TryToInstall InstallAction(Cache, Fix, BrokenFix); + InstallAction(Cache[Pkg].CandidateVerIter(Cache)); + InstallAction.doAutoInstall(); + } else + return AllowFail; return true; } @@ -1624,61 +1687,6 @@ bool DoUpgrade(CommandLine &CmdL) return InstallPackages(Cache,true); } /*}}}*/ -// DoInstallTask - Install task from the command line /*{{{*/ -// --------------------------------------------------------------------- -/* Install named task */ -bool TryInstallTask(pkgDepCache &Cache, pkgProblemResolver &Fix, - bool BrokenFix, - unsigned int& ExpectedInst, - const char *taskname, - bool Remove) -{ - const char *start, *end; - pkgCache::PkgIterator Pkg; - char buf[64*1024]; - regex_t Pattern; - - // get the records - pkgRecords Recs(Cache); - - // build regexp for the task - char S[300]; - snprintf(S, sizeof(S), "^Task:.*[, ]%s([, ]|$)", taskname); - if(regcomp(&Pattern,S, REG_EXTENDED | REG_NOSUB | REG_NEWLINE) != 0) - return _error->Error("Failed to compile task regexp"); - - bool found = false; - bool res = true; - - // two runs, first ignore dependencies, second install any missing - for(int IgnoreBroken=1; IgnoreBroken >= 0; IgnoreBroken--) - { - for (Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++) - { - pkgCache::VerIterator ver = Cache[Pkg].CandidateVerIter(Cache); - if(ver.end()) - continue; - pkgRecords::Parser &parser = Recs.Lookup(ver.FileList()); - parser.GetRec(start,end); - strncpy(buf, start, end-start); - buf[end-start] = 0x0; - if (regexec(&Pattern,buf,0,0,0) != 0) - continue; - res &= TryToInstall(Pkg,Cache,Fix,Remove,IgnoreBroken,ExpectedInst); - found = true; - } - } - - // now let the problem resolver deal with any issues - Fix.Resolve(true); - - if(!found) - _error->Error(_("Couldn't find task %s"),taskname); - - regfree(&Pattern); - return res; -} - /*}}}*/ // DoInstall - Install packages from the command line /*{{{*/ // --------------------------------------------------------------------- /* Install named packages */ @@ -1694,140 +1702,69 @@ bool DoInstall(CommandLine &CmdL) if (Cache->BrokenCount() != 0) BrokenFix = true; - unsigned int AutoMarkChanged = 0; - unsigned int ExpectedInst = 0; - unsigned int Packages = 0; pkgProblemResolver Fix(Cache); - - bool DefRemove = false; + + static const unsigned short MOD_REMOVE = 1; + static const unsigned short MOD_INSTALL = 2; + + unsigned short fallback = MOD_INSTALL; if (strcasecmp(CmdL.FileList[0],"remove") == 0) - DefRemove = true; + fallback = MOD_REMOVE; else if (strcasecmp(CmdL.FileList[0], "purge") == 0) { _config->Set("APT::Get::Purge", true); - DefRemove = true; + fallback = MOD_REMOVE; } else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0) { _config->Set("APT::Get::AutomaticRemove", "true"); - DefRemove = true; + fallback = MOD_REMOVE; } - // new scope for the ActionGroup - { - pkgDepCache::ActionGroup group(Cache); - for (const char **I = CmdL.FileList + 1; *I != 0; I++) - { - // Duplicate the string - unsigned int Length = strlen(*I); - char S[300]; - if (Length >= sizeof(S)) - continue; - strcpy(S,*I); - - // See if we are removing and special indicators.. - bool Remove = DefRemove; - char *VerTag = 0; - bool VerIsRel = false; - // this is a task! - if (Length >= 1 && S[Length - 1] == '^') - { - S[--Length] = 0; - // tasks must always be confirmed - ExpectedInst += 1000; - // see if we can install it - TryInstallTask(Cache, Fix, BrokenFix, ExpectedInst, S, Remove); - continue; - } + std::list<APT::VersionSet::Modifier> mods; + mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+", + APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE)); + mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-", + APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST)); + CacheSetHelperAPTGet helper(c0out); + std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache, + CmdL.FileList + 1, mods, fallback, helper); - while (Cache->FindPkg(S).end() == true) - { - // Handle an optional end tag indicating what to do - if (Length >= 1 && S[Length - 1] == '-') - { - Remove = true; - S[--Length] = 0; - continue; - } - - if (Length >= 1 && S[Length - 1] == '+') - { - Remove = false; - S[--Length] = 0; - continue; - } - - char *Slash = strchr(S,'='); - if (Slash != 0) - { - VerIsRel = false; - *Slash = 0; - VerTag = Slash + 1; - } - - Slash = strchr(S,'/'); - if (Slash != 0) - { - VerIsRel = true; - *Slash = 0; - VerTag = Slash + 1; - } - - break; - } - - // Locate the package - pkgCache::PkgIterator Pkg = Cache->FindPkg(S); - Packages++; - if (Pkg.end() == true) - { - APT::PackageSet pkgset = APT::PackageSet::FromRegEx(Cache, S, c1out); - if (pkgset.empty() == true) - return _error->Error(_("Couldn't find package %s"),S); + if (_error->PendingError() == true) + { + helper.showVirtualPackageErrors(Cache); + return false; + } - // Regexs must always be confirmed - ExpectedInst += 1000; + unsigned short order[] = { 0, 0, 0 }; + if (fallback == MOD_INSTALL) { + order[0] = MOD_INSTALL; + order[1] = MOD_REMOVE; + } else { + order[0] = MOD_REMOVE; + order[1] = MOD_INSTALL; + } - bool Hit = false; - for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) - { - if (VerTag != 0) - if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false) - return false; + TryToInstall InstallAction(Cache, Fix, BrokenFix); + TryToRemove RemoveAction(Cache, Fix); - Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix, - ExpectedInst,false); - } + // new scope for the ActionGroup + { + pkgDepCache::ActionGroup group(Cache); - if (Hit == false) - return _error->Error(_("Couldn't find package %s"),S); + for (unsigned short i = 0; order[i] != 0; ++i) + { + if (order[i] == MOD_INSTALL) { + InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction); + InstallAction.doAutoInstall(); } - else - { - if (VerTag != 0) - if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false) - return false; - if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false) - return false; - - // see if we need to fix the auto-mark flag - // e.g. apt-get install foo - // where foo is marked automatic - if(!Remove && - Cache[Pkg].Install() == false && - (Cache[Pkg].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->MarkAuto(Pkg,false); - AutoMarkChanged++; - } - } + else if (order[i] == MOD_REMOVE) + RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction); } + if (_error->PendingError() == true) + return false; + /* If we are in the Broken fixing mode we do not attempt to fix the problems. This is if the user invoked install without -f and gave packages */ @@ -1874,7 +1811,7 @@ bool DoInstall(CommandLine &CmdL) /* Print out a list of packages that are going to be installed extra to what the user asked */ - if (Cache->InstCount() != ExpectedInst) + if (Cache->InstCount() != verset[MOD_INSTALL].size()) { string List; string VersionsList; @@ -1993,14 +1930,15 @@ bool DoInstall(CommandLine &CmdL) // if nothing changed in the cache, but only the automark information // we write the StateFile here, otherwise it will be written in // cache.commit() - if (AutoMarkChanged > 0 && + if (InstallAction.AutoMarkChanged > 0 && Cache->DelCount() == 0 && Cache->InstCount() == 0 && Cache->BadCount() == 0 && _config->FindB("APT::Get::Simulate",false) == false) Cache->writeStateFile(NULL); // See if we need to prompt - if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0) + // FIXME: check if really the packages in the set are going to be installed + if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0) return InstallPackages(Cache,false,false); return InstallPackages(Cache,false); @@ -2584,7 +2522,6 @@ bool DoBuildDep(CommandLine &CmdL) } // Install the requested packages - unsigned int ExpectedInst = 0; vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D; pkgProblemResolver Fix(Cache); bool skipAlternatives = false; // skip remaining alternatives in an or group @@ -2615,7 +2552,7 @@ bool DoBuildDep(CommandLine &CmdL) */ if (IV.end() == false && Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true) - TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst); + TryToInstallBuildDep(Pkg,Cache,Fix,true,false); } else // BuildDep || BuildDepIndep { @@ -2731,7 +2668,7 @@ bool DoBuildDep(CommandLine &CmdL) if (_config->FindB("Debug::BuildDeps",false) == true) cout << " Trying to install " << (*D).Package << endl; - if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true) + if (TryToInstallBuildDep(Pkg,Cache,Fix,false,false) == true) { // We successfully installed something; skip remaining alternatives skipAlternatives = hasAlternatives; @@ -3021,7 +2958,7 @@ int main(int argc,const char *argv[]) /*{{{*/ } // Deal with stdout not being a tty - if (!isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1) + if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1) _config->Set("quiet","1"); // Setup the output streams @@ -3042,13 +2979,11 @@ int main(int argc,const char *argv[]) /*{{{*/ CmdL.DispatchArg(Cmds); // Print any errors or warnings found during parsing - if (_error->empty() == false) - { - bool Errors = _error->PendingError(); + bool const Errors = _error->PendingError(); + if (_config->FindI("quiet",0) > 0) _error->DumpErrors(); - return Errors == true?100:0; - } - - return 0; + else + _error->DumpErrors(GlobalError::DEBUG); + return Errors == true ? 100 : 0; } /*}}}*/ |