diff options
Diffstat (limited to 'cmdline/apt-get.cc')
-rw-r--r-- | cmdline/apt-get.cc | 1988 |
1 files changed, 29 insertions, 1959 deletions
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 4b7691d93..06dbbce5b 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -50,7 +50,16 @@ #include <apt-pkg/pkgrecords.h> #include <apt-pkg/indexfile.h> -#include "acqprogress.h" + +#include <apt-private/private-install.h> +#include <apt-private/private-upgrade.h> +#include <apt-private/private-output.h> +#include <apt-private/private-cacheset.h> +#include <apt-private/private-update.h> +#include <apt-private/private-cmndline.h> +#include <apt-private/private-moo.h> + +#include <apt-private/acqprogress.h> #include <set> #include <locale.h> @@ -69,1391 +78,17 @@ #include <sys/wait.h> #include <sstream> +#include <apt-private/private-output.h> +#include <apt-private/private-main.h> + #include <apti18n.h> /*}}}*/ -#define RAMFS_MAGIC 0x858458f6 using namespace std; -ostream c0out(0); -ostream c1out(0); -ostream c2out(0); -ofstream devnull("/dev/null"); -unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */ - -// class CacheFile - Cover class for some dependency cache functions /*{{{*/ -// --------------------------------------------------------------------- -/* */ -class CacheFile : public pkgCacheFile -{ - static pkgCache *SortCache; - static int NameComp(const void *a,const void *b); - - public: - pkgCache::Package **List; - - void Sort(); - bool CheckDeps(bool AllowBroken = false); - bool BuildCaches(bool WithLock = true) - { - OpTextProgress Prog(*_config); - if (pkgCacheFile::BuildCaches(&Prog,WithLock) == false) - return false; - return true; - } - bool Open(bool WithLock = true) - { - OpTextProgress Prog(*_config); - if (pkgCacheFile::Open(&Prog,WithLock) == false) - return false; - Sort(); - - return true; - }; - bool OpenForInstall() - { - if (_config->FindB("APT::Get::Print-URIs") == true) - return Open(false); - else - return Open(true); - } - CacheFile() : List(0) {}; - ~CacheFile() { - delete[] List; - } -}; - /*}}}*/ - -// YnPrompt - Yes No Prompt. /*{{{*/ -// --------------------------------------------------------------------- -/* Returns true on a Yes.*/ -bool YnPrompt(bool Default=true) -{ - /* nl_langinfo does not support LANGUAGE setting, so we unset it here - to have the help-message (hopefully) match the expected characters */ - char * language = getenv("LANGUAGE"); - if (language != NULL) - language = strdup(language); - if (language != NULL) - unsetenv("LANGUAGE"); - - if (Default == true) - // TRANSLATOR: Yes/No question help-text: defaulting to Y[es] - // e.g. "Do you want to continue? [Y/n] " - // The user has to answer with an input matching the - // YESEXPR/NOEXPR defined in your l10n. - c2out << " " << _("[Y/n]") << " " << std::flush; - else - // TRANSLATOR: Yes/No question help-text: defaulting to N[o] - // e.g. "Should this file be removed? [y/N] " - // The user has to answer with an input matching the - // YESEXPR/NOEXPR defined in your l10n. - c2out << " " << _("[y/N]") << " " << std::flush; - - if (language != NULL) - { - setenv("LANGUAGE", language, 0); - free(language); - } - - if (_config->FindB("APT::Get::Assume-Yes",false) == true) - { - // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set - c1out << _("Y") << endl; - return true; - } - else if (_config->FindB("APT::Get::Assume-No",false) == true) - { - // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set - c1out << _("N") << endl; - return false; - } - - char response[1024] = ""; - cin.getline(response, sizeof(response)); - - if (!cin) - return false; - - if (strlen(response) == 0) - return Default; - - regex_t Pattern; - int Res; - - Res = regcomp(&Pattern, nl_langinfo(YESEXPR), - REG_EXTENDED|REG_ICASE|REG_NOSUB); - - if (Res != 0) { - char Error[300]; - regerror(Res,&Pattern,Error,sizeof(Error)); - return _error->Error(_("Regex compilation error - %s"),Error); - } - - Res = regexec(&Pattern, response, 0, NULL, 0); - if (Res == 0) - return true; - return false; -} - /*}}}*/ -// AnalPrompt - Annoying Yes No Prompt. /*{{{*/ -// --------------------------------------------------------------------- -/* Returns true on a Yes.*/ -bool AnalPrompt(const char *Text) -{ - char Buf[1024]; - cin.getline(Buf,sizeof(Buf)); - if (strcmp(Buf,Text) == 0) - return true; - return false; -} - /*}}}*/ -// ShowList - Show a list /*{{{*/ -// --------------------------------------------------------------------- -/* This prints out a string of space separated words with a title and - a two space indent line wraped to the current screen width. */ -bool ShowList(ostream &out,string Title,string List,string VersionsList) -{ - if (List.empty() == true) - return true; - // trim trailing space - int NonSpace = List.find_last_not_of(' '); - if (NonSpace != -1) - { - List = List.erase(NonSpace + 1); - if (List.empty() == true) - return true; - } - - // Acount for the leading space - int ScreenWidth = ::ScreenWidth - 3; - - out << Title << endl; - string::size_type Start = 0; - string::size_type VersionsStart = 0; - while (Start < List.size()) - { - if(_config->FindB("APT::Get::Show-Versions",false) == true && - VersionsList.size() > 0) { - string::size_type End; - string::size_type VersionsEnd; - - End = List.find(' ',Start); - VersionsEnd = VersionsList.find('\n', VersionsStart); - - out << " " << string(List,Start,End - Start) << " (" << - string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) << - ")" << endl; - - if (End == string::npos || End < Start) - End = Start + ScreenWidth; - - Start = End + 1; - VersionsStart = VersionsEnd + 1; - } else { - string::size_type End; - - if (Start + ScreenWidth >= List.size()) - End = List.size(); - else - End = List.rfind(' ',Start+ScreenWidth); - - if (End == string::npos || End < Start) - End = Start + ScreenWidth; - out << " " << string(List,Start,End - Start) << endl; - Start = End + 1; - } - } - - return false; -} - /*}}}*/ -// ShowBroken - Debugging aide /*{{{*/ -// --------------------------------------------------------------------- -/* This prints out the names of all the packages that are broken along - with the name of each each broken dependency and a quite version - description. - - The output looks like: - The following packages have unmet dependencies: - exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed - Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed - Depends: libsasl7 but it is not going to be installed - */ -void ShowBroken(ostream &out,CacheFile &Cache,bool Now) -{ - if (Cache->BrokenCount() == 0) - return; - - out << _("The following packages have unmet dependencies:") << endl; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - if (Now == true) - { - if (Cache[I].NowBroken() == false) - continue; - } - else - { - if (Cache[I].InstBroken() == false) - continue; - } - - // Print out each package and the failed dependencies - out << " " << I.FullName(true) << " :"; - unsigned const Indent = I.FullName(true).size() + 3; - bool First = true; - pkgCache::VerIterator Ver; - - if (Now == true) - Ver = I.CurrentVer(); - else - Ver = Cache[I].InstVerIter(Cache); - - if (Ver.end() == true) - { - out << endl; - continue; - } - - for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;) - { - // Compute a single dependency element (glob or) - pkgCache::DepIterator Start; - pkgCache::DepIterator End; - D.GlobOr(Start,End); // advances D - - if (Cache->IsImportantDep(End) == false) - continue; - - if (Now == true) - { - if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow) - continue; - } - else - { - if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) - continue; - } - - bool FirstOr = true; - while (1) - { - if (First == false) - for (unsigned J = 0; J != Indent; J++) - out << ' '; - First = false; - - if (FirstOr == false) - { - for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++) - out << ' '; - } - else - out << ' ' << End.DepType() << ": "; - FirstOr = false; - - out << Start.TargetPkg().FullName(true); - - // Show a quick summary of the version requirements - if (Start.TargetVer() != 0) - out << " (" << Start.CompType() << " " << Start.TargetVer() << ")"; - - /* Show a summary of the target package if possible. In the case - of virtual packages we show nothing */ - pkgCache::PkgIterator Targ = Start.TargetPkg(); - if (Targ->ProvidesList == 0) - { - out << ' '; - pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache); - if (Now == true) - Ver = Targ.CurrentVer(); - - if (Ver.end() == false) - { - if (Now == true) - ioprintf(out,_("but %s is installed"),Ver.VerStr()); - else - ioprintf(out,_("but %s is to be installed"),Ver.VerStr()); - } - else - { - if (Cache[Targ].CandidateVerIter(Cache).end() == true) - { - if (Targ->ProvidesList == 0) - out << _("but it is not installable"); - else - out << _("but it is a virtual package"); - } - else - out << (Now?_("but it is not installed"):_("but it is not going to be installed")); - } - } - - if (Start != End) - out << _(" or"); - out << endl; - - if (Start == End) - break; - ++Start; - } - } - } -} - /*}}}*/ -// ShowNew - Show packages to newly install /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void ShowNew(ostream &out,CacheFile &Cache) -{ - /* Print out a list of packages that are going to be installed extra - to what the user asked */ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].NewInstall() == true) { - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CandVersion) + "\n"; - } - } - - ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList); -} - /*}}}*/ -// ShowDel - Show packages to delete /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void ShowDel(ostream &out,CacheFile &Cache) -{ - /* Print out a list of packages that are going to be removed extra - to what the user asked */ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].Delete() == true) - { - if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge) - List += I.FullName(true) + "* "; - else - List += I.FullName(true) + " "; - - VersionsList += string(Cache[I].CandVersion)+ "\n"; - } - } - - ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList); -} - /*}}}*/ -// ShowKept - Show kept packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void ShowKept(ostream &out,CacheFile &Cache) -{ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false || - I->CurrentVer == 0 || Cache[I].Delete() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - ShowList(out,_("The following packages have been kept back:"),List,VersionsList); -} - /*}}}*/ -// ShowUpgraded - Show upgraded packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void ShowUpgraded(ostream &out,CacheFile &Cache) -{ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - ShowList(out,_("The following packages will be upgraded:"),List,VersionsList); -} - /*}}}*/ -// ShowDowngraded - Show downgraded packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool ShowDowngraded(ostream &out,CacheFile &Cache) -{ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList); -} - /*}}}*/ -// ShowHold - Show held but changed packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool ShowHold(ostream &out,CacheFile &Cache) -{ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() && - I->SelectedState == pkgCache::State::Hold) { - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - } - - return ShowList(out,_("The following held packages will be changed:"),List,VersionsList); -} - /*}}}*/ -// ShowEssential - Show an essential package warning /*{{{*/ -// --------------------------------------------------------------------- -/* This prints out a warning message that is not to be ignored. It shows - all essential packages and their dependents that are to be removed. - It is insanely risky to remove the dependents of an essential package! */ -bool ShowEssential(ostream &out,CacheFile &Cache) -{ - string List; - string VersionsList; - bool *Added = new bool[Cache->Head().PackageCount]; - for (unsigned int I = 0; I != Cache->Head().PackageCount; I++) - Added[I] = false; - - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential && - (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important) - continue; - - // The essential package is being removed - if (Cache[I].Delete() == true) - { - if (Added[I->ID] == false) - { - Added[I->ID] = true; - List += I.FullName(true) + " "; - //VersionsList += string(Cache[I].CurVersion) + "\n"; ??? - } - } - else - continue; - - if (I->CurrentVer == 0) - continue; - - // Print out any essential package depenendents that are to be removed - for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D) - { - // Skip everything but depends - if (D->Type != pkgCache::Dep::PreDepends && - D->Type != pkgCache::Dep::Depends) - continue; - - pkgCache::PkgIterator P = D.SmartTargetPkg(); - if (Cache[P].Delete() == true) - { - if (Added[P->ID] == true) - continue; - Added[P->ID] = true; - - char S[300]; - snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str()); - List += S; - //VersionsList += "\n"; ??? - } - } - } - - delete [] Added; - return ShowList(out,_("WARNING: The following essential packages will be removed.\n" - "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList); -} - - /*}}}*/ -// Stats - Show some statistics /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void Stats(ostream &out,pkgDepCache &Dep) -{ - unsigned long Upgrade = 0; - unsigned long Downgrade = 0; - unsigned long Install = 0; - unsigned long ReInstall = 0; - for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I) - { - if (Dep[I].NewInstall() == true) - Install++; - else - { - if (Dep[I].Upgrade() == true) - Upgrade++; - else - if (Dep[I].Downgrade() == true) - Downgrade++; - } - - if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall) - ReInstall++; - } - - ioprintf(out,_("%lu upgraded, %lu newly installed, "), - Upgrade,Install); - - if (ReInstall != 0) - ioprintf(out,_("%lu reinstalled, "),ReInstall); - if (Downgrade != 0) - ioprintf(out,_("%lu downgraded, "),Downgrade); - - ioprintf(out,_("%lu to remove and %lu not upgraded.\n"), - Dep.DelCount(),Dep.KeepCount()); - - if (Dep.BadCount() != 0) - ioprintf(out,_("%lu not fully installed or removed.\n"), - 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: - std::list<std::pair<pkgCache::VerIterator, std::string> > selectedByRelease; - - CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) { - explicitlyNamed = true; - } - - virtual void showTaskSelection(pkgCache::PkgIterator const &Pkg, string const &pattern) { - ioprintf(out, _("Note, selecting '%s' for task '%s'\n"), - Pkg.FullName(true).c_str(), pattern.c_str()); - explicitlyNamed = false; - } - virtual void showRegExSelection(pkgCache::PkgIterator const &Pkg, string const &pattern) { - 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()) - return; - selectedByRelease.push_back(make_pair(Ver, ver)); - } - - 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()) { - 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 - out << _("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.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(c1out,_("However the following packages replace it:"),List,VersionsList); - } - c1out << 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()); - else 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) { - if (Pkg->ProvidesList != 0) - { - 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()); - } - else - { - pkgCache::GrpIterator Grp = Pkg.Group(); - pkgCache::PkgIterator P = Grp.PackageList(); - for (; P.end() != true; P = Grp.NextPkg(P)) - { - if (P == Pkg) - continue; - if (P->CurrentVer != 0) { - // TRANSLATORS: Note, this is not an interactive question - ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"), - Pkg.FullName(true).c_str(), P.FullName(true).c_str()); - break; - } - } - if (P.end() == true) - ioprintf(c1out,_("Package '%s' is not installed, so not 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) { - // same group, so it's a foreign package - if (PPkg->Group == Prov->Group) { - // do we already have the requested arch? - if (strcmp(Pkg.Arch(), Prov.Arch()) == 0 || - strcmp(Prov.Arch(), "all") == 0 || - unlikely(strcmp(PPkg.Arch(), Prov.Arch()) == 0)) // packages have only on candidate, but just to be sure - continue; - // see which architecture we prefer more and switch to it - std::vector<std::string> archs = APT::Configuration::getArchitectures(); - if (std::find(archs.begin(), archs.end(), PPkg.Arch()) < std::find(archs.begin(), archs.end(), Prov.Arch())) - Prov = PPkg; - continue; - } - 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 { - if (Fix != NULL) { - 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++; - } - } - - bool propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > start, std::ostream &out) - { - for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin(); - s != start.end(); ++s) - Cache->GetDepCache()->SetCandidateVersion(s->first); - - bool Success = true; - std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed; - for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin(); - s != start.end(); ++s) - { - Changed.push_back(std::make_pair(s->first, pkgCache::VerIterator(*Cache))); - // We continue here even if it failed to enhance the ShowBroken output - Success &= Cache->GetDepCache()->SetCandidateRelease(s->first, s->second, Changed); - } - for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin(); - c != Changed.end(); ++c) - { - if (c->second.end() == true) - ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"), - c->first.VerStr(), c->first.RelStr().c_str(), c->first.ParentPkg().FullName(true).c_str()); - else if (c->first.ParentPkg()->Group != c->second.ParentPkg()->Group) - { - pkgCache::VerIterator V = (*Cache)[c->first.ParentPkg()].CandidateVerIter(*Cache); - ioprintf(out, _("Selected version '%s' (%s) for '%s' because of '%s'\n"), V.VerStr(), - V.RelStr().c_str(), V.ParentPkg().FullName(true).c_str(), c->second.ParentPkg().FullName(true).c_str()); - } - } - return Success; - } - - 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 PurgePkgs; - - 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(); - - if (Fix != NULL) - { - Fix->Clear(Pkg); - Fix->Protect(Pkg); - Fix->Remove(Pkg); - } - - if ((Pkg->CurrentVer == 0 && PurgePkgs == false) || - (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled)) - { - pkgCache::GrpIterator Grp = Pkg.Group(); - pkgCache::PkgIterator P = Grp.PackageList(); - for (; P.end() != true; P = Grp.NextPkg(P)) - { - if (P == Pkg) - continue; - if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled)) - { - // TRANSLATORS: Note, this is not an interactive question - ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"), - Pkg.FullName(true).c_str(), P.FullName(true).c_str()); - break; - } - } - if (P.end() == true) - ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str()); - - // MarkInstall refuses to install packages on hold - Pkg->SelectedState = pkgCache::State::Hold; - } - else - Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs); - } -}; - /*}}}*/ -// CacheFile::NameComp - QSort compare by name /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache *CacheFile::SortCache = 0; -int CacheFile::NameComp(const void *a,const void *b) -{ - if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0) - return *(pkgCache::Package **)a - *(pkgCache::Package **)b; - - const pkgCache::Package &A = **(pkgCache::Package **)a; - const pkgCache::Package &B = **(pkgCache::Package **)b; - - return strcmp(SortCache->StrP + A.Name,SortCache->StrP + B.Name); -} - /*}}}*/ -// CacheFile::Sort - Sort by name /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void CacheFile::Sort() -{ - delete [] List; - List = new pkgCache::Package *[Cache->Head().PackageCount]; - memset(List,0,sizeof(*List)*Cache->Head().PackageCount); - pkgCache::PkgIterator I = Cache->PkgBegin(); - for (;I.end() != true; ++I) - List[I->ID] = I; - - SortCache = *this; - qsort(List,Cache->Head().PackageCount,sizeof(*List),NameComp); -} - /*}}}*/ -// CacheFile::CheckDeps - Open the cache file /*{{{*/ -// --------------------------------------------------------------------- -/* This routine generates the caches and then opens the dependency cache - and verifies that the system is OK. */ -bool CacheFile::CheckDeps(bool AllowBroken) -{ - bool FixBroken = _config->FindB("APT::Get::Fix-Broken",false); - - if (_error->PendingError() == true) - return false; - - // Check that the system is OK - if (DCache->DelCount() != 0 || DCache->InstCount() != 0) - return _error->Error("Internal error, non-zero counts"); - - // Apply corrections for half-installed packages - if (pkgApplyStatus(*DCache) == false) - return false; - - if (_config->FindB("APT::Get::Fix-Policy-Broken",false) == true) - { - FixBroken = true; - if ((DCache->PolicyBrokenCount() > 0)) - { - // upgrade all policy-broken packages with ForceImportantDeps=True - for (pkgCache::PkgIterator I = Cache->PkgBegin(); !I.end(); ++I) - if ((*DCache)[I].NowPolicyBroken() == true) - DCache->MarkInstall(I,true,0, false, true); - } - } - - // Nothing is broken - if (DCache->BrokenCount() == 0 || AllowBroken == true) - return true; - - // Attempt to fix broken things - if (FixBroken == true) - { - c1out << _("Correcting dependencies...") << flush; - if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0) - { - c1out << _(" failed.") << endl; - ShowBroken(c1out,*this,true); - - return _error->Error(_("Unable to correct dependencies")); - } - if (pkgMinimizeUpgrade(*DCache) == false) - return _error->Error(_("Unable to minimize the upgrade set")); - - c1out << _(" Done") << endl; - } - else - { - c1out << _("You might want to run 'apt-get -f install' to correct these.") << endl; - ShowBroken(c1out,*this,true); - - return _error->Error(_("Unmet dependencies. Try using -f.")); - } - - return true; -} - /*}}}*/ -// CheckAuth - check if each download comes form a trusted source /*{{{*/ -// --------------------------------------------------------------------- -/* */ -static bool CheckAuth(pkgAcquire& Fetcher) -{ - string UntrustedList; - for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I) - { - if (!(*I)->IsTrusted()) - { - UntrustedList += string((*I)->ShortDesc()) + " "; - } - } - - if (UntrustedList == "") - { - return true; - } - - ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,""); - - if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true) - { - c2out << _("Authentication warning overridden.\n"); - return true; - } - - if (_config->FindI("quiet",0) < 2 - && _config->FindB("APT::Get::Assume-Yes",false) == false) - { - c2out << _("Install these packages without verification?") << flush; - if (!YnPrompt(false)) - return _error->Error(_("Some packages could not be authenticated")); - - return true; - } - else if (_config->FindB("APT::Get::Force-Yes",false) == true) - { - return true; - } - - return _error->Error(_("There are problems and -y was used without --force-yes")); -} - /*}}}*/ -// InstallPackages - Actually download and install the packages /*{{{*/ -// --------------------------------------------------------------------- -/* This displays the informative messages describing what is going to - happen and then calls the download routines */ -bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, - bool Safety = true) -{ - if (_config->FindB("APT::Get::Purge",false) == true) - { - pkgCache::PkgIterator I = Cache->PkgBegin(); - for (; I.end() == false; ++I) - { - if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete) - Cache->MarkDelete(I,true); - } - } - - bool Fail = false; - bool Essential = false; - - // Show all the various warning indicators - ShowDel(c1out,Cache); - ShowNew(c1out,Cache); - if (ShwKept == true) - ShowKept(c1out,Cache); - Fail |= !ShowHold(c1out,Cache); - if (_config->FindB("APT::Get::Show-Upgraded",true) == true) - ShowUpgraded(c1out,Cache); - Fail |= !ShowDowngraded(c1out,Cache); - if (_config->FindB("APT::Get::Download-Only",false) == false) - Essential = !ShowEssential(c1out,Cache); - Fail |= Essential; - Stats(c1out,Cache); - - // Sanity check - if (Cache->BrokenCount() != 0) - { - ShowBroken(c1out,Cache,false); - return _error->Error(_("Internal error, InstallPackages was called with broken packages!")); - } - - if (Cache->DelCount() == 0 && Cache->InstCount() == 0 && - Cache->BadCount() == 0) - return true; - - // No remove flag - if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false) - return _error->Error(_("Packages need to be removed but remove is disabled.")); - - // Run the simulator .. - if (_config->FindB("APT::Get::Simulate") == true) - { - pkgSimulate PM(Cache); - int status_fd = _config->FindI("APT::Status-Fd",-1); - pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd); - if (Res == pkgPackageManager::Failed) - return false; - if (Res != pkgPackageManager::Completed) - return _error->Error(_("Internal error, Ordering didn't finish")); - return true; - } - - // Create the text record parser - pkgRecords Recs(Cache); - if (_error->PendingError() == true) - return false; - - // Create the download object - pkgAcquire Fetcher; - AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); - if (_config->FindB("APT::Get::Print-URIs", false) == true) - { - // force a hashsum for compatibility reasons - _config->CndSet("Acquire::ForceHash", "md5sum"); - } - else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false) - return false; - // Read the source list - if (Cache.BuildSourceList() == false) - return false; - pkgSourceList *List = Cache.GetSourceList(); - - // Create the package manager and prepare to download - SPtr<pkgPackageManager> PM= _system->CreatePM(Cache); - if (PM->GetArchives(&Fetcher,List,&Recs) == false || - _error->PendingError() == true) - return false; - // Display statistics - unsigned long long FetchBytes = Fetcher.FetchNeeded(); - unsigned long long FetchPBytes = Fetcher.PartialPresent(); - unsigned long long DebBytes = Fetcher.TotalNeeded(); - if (DebBytes != Cache->DebSize()) - { - c0out << DebBytes << ',' << Cache->DebSize() << endl; - c0out << _("How odd.. The sizes didn't match, email apt@packages.debian.org") << endl; - } - - // Number of bytes - if (DebBytes != FetchBytes) - //TRANSLATOR: The required space between number and unit is already included - // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB - ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"), - SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str()); - else if (DebBytes != 0) - //TRANSLATOR: The required space between number and unit is already included - // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB - ioprintf(c1out,_("Need to get %sB of archives.\n"), - SizeToStr(DebBytes).c_str()); - - // Size delta - if (Cache->UsrSize() >= 0) - //TRANSLATOR: The required space between number and unit is already included - // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB - ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"), - SizeToStr(Cache->UsrSize()).c_str()); - else - //TRANSLATOR: The required space between number and unit is already included - // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB - ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"), - SizeToStr(-1*Cache->UsrSize()).c_str()); - - if (_error->PendingError() == true) - return false; - - /* Check for enough free space, but only if we are actually going to - download */ - if (_config->FindB("APT::Get::Print-URIs") == false && - _config->FindB("APT::Get::Download",true) == true) - { - struct statvfs Buf; - string OutputDir = _config->FindDir("Dir::Cache::Archives"); - if (statvfs(OutputDir.c_str(),&Buf) != 0) { - if (errno == EOVERFLOW) - return _error->WarningE("statvfs",_("Couldn't determine free space in %s"), - OutputDir.c_str()); - else - return _error->Errno("statvfs",_("Couldn't determine free space in %s"), - OutputDir.c_str()); - } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize) - { - struct statfs Stat; - if (statfs(OutputDir.c_str(),&Stat) != 0 -#if HAVE_STRUCT_STATFS_F_TYPE - || unsigned(Stat.f_type) != RAMFS_MAGIC -#endif - ) - return _error->Error(_("You don't have enough free space in %s."), - OutputDir.c_str()); - } - } - - // Fail safe check - if (_config->FindI("quiet",0) >= 2 || - _config->FindB("APT::Get::Assume-Yes",false) == true) - { - if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false) - return _error->Error(_("There are problems and -y was used without --force-yes")); - } - - if (Essential == true && Safety == true) - { - if (_config->FindB("APT::Get::Trivial-Only",false) == true) - return _error->Error(_("Trivial Only specified but this is not a trivial operation.")); - - // TRANSLATOR: This string needs to be typed by the user as a confirmation, so be - // careful with hard to type or special characters (like non-breaking spaces) - const char *Prompt = _("Yes, do as I say!"); - ioprintf(c2out, - _("You are about to do something potentially harmful.\n" - "To continue type in the phrase '%s'\n" - " ?] "),Prompt); - c2out << flush; - if (AnalPrompt(Prompt) == false) - { - c2out << _("Abort.") << endl; - exit(1); - } - } - else - { - // Prompt to continue - if (Ask == true || Fail == true) - { - if (_config->FindB("APT::Get::Trivial-Only",false) == true) - return _error->Error(_("Trivial Only specified but this is not a trivial operation.")); - - if (_config->FindI("quiet",0) < 2 && - _config->FindB("APT::Get::Assume-Yes",false) == false) - { - c2out << _("Do you want to continue?") << flush; - - if (YnPrompt() == false) - { - c2out << _("Abort.") << endl; - exit(1); - } - } - } - } - - // Just print out the uris an exit if the --print-uris flag was used - if (_config->FindB("APT::Get::Print-URIs") == true) - { - pkgAcquire::UriIterator I = Fetcher.UriBegin(); - for (; I != Fetcher.UriEnd(); ++I) - cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << - I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl; - return true; - } - - if (!CheckAuth(Fetcher)) - return false; - - /* Unlock the dpkg lock if we are not going to be doing an install - after. */ - if (_config->FindB("APT::Get::Download-Only",false) == true) - _system->UnLock(); - - // Run it - while (1) - { - bool Transient = false; - if (_config->FindB("APT::Get::Download",true) == false) - { - for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();) - { - if ((*I)->Local == true) - { - ++I; - continue; - } - - // Close the item and check if it was found in cache - (*I)->Finished(); - if ((*I)->Complete == false) - Transient = true; - - // Clear it out of the fetch list - delete *I; - I = Fetcher.ItemsBegin(); - } - } - - if (Fetcher.Run() == pkgAcquire::Failed) - return false; - - // Print out errors - bool Failed = false; - for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) - { - if ((*I)->Status == pkgAcquire::Item::StatDone && - (*I)->Complete == true) - continue; - - if ((*I)->Status == pkgAcquire::Item::StatIdle) - { - Transient = true; - // Failed = true; - continue; - } - - fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(), - (*I)->ErrorText.c_str()); - Failed = true; - } - - /* If we are in no download mode and missing files and there were - 'failures' then the user must specify -m. Furthermore, there - is no such thing as a transient error in no-download mode! */ - if (Transient == true && - _config->FindB("APT::Get::Download",true) == false) - { - Transient = false; - Failed = true; - } - - if (_config->FindB("APT::Get::Download-Only",false) == true) - { - if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false) - return _error->Error(_("Some files failed to download")); - c1out << _("Download complete and in download only mode") << endl; - return true; - } - - if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false) - { - return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?")); - } - - if (Transient == true && Failed == true) - return _error->Error(_("--fix-missing and media swapping is not currently supported")); - - // Try to deal with missing package files - if (Failed == true && PM->FixMissing() == false) - { - cerr << _("Unable to correct missing packages.") << endl; - return _error->Error(_("Aborting install.")); - } - - _system->UnLock(); - int status_fd = _config->FindI("APT::Status-Fd",-1); - pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd); - if (Res == pkgPackageManager::Failed || _error->PendingError() == true) - return false; - if (Res == pkgPackageManager::Completed) - break; - - // Reload the fetcher object and loop again for media swapping - Fetcher.Shutdown(); - if (PM->GetArchives(&Fetcher,List,&Recs) == false) - return false; - - _system->Lock(); - } - - std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages(); - if (disappearedPkgs.empty() == true) - return true; - - string disappear; - for (std::set<std::string>::const_iterator d = disappearedPkgs.begin(); - d != disappearedPkgs.end(); ++d) - disappear.append(*d).append(" "); - - ShowList(c1out, P_("The following package disappeared from your system as\n" - "all files have been overwritten by other packages:", - "The following packages disappeared from your system as\n" - "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, ""); - c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl; - - return true; -} - /*}}}*/ // TryToInstallBuildDep - Try to install a single package /*{{{*/ // --------------------------------------------------------------------- /* This used to be inlined in DoInstall, but with the advent of regex package @@ -1667,497 +302,6 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, return Last; } /*}}}*/ -// DoUpdate - Update the package lists /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool DoUpdate(CommandLine &CmdL) -{ - if (CmdL.FileSize() != 1) - return _error->Error(_("The update command takes no arguments")); - - CacheFile Cache; - - // Get the source list - if (Cache.BuildSourceList() == false) - return false; - pkgSourceList *List = Cache.GetSourceList(); - - // Create the progress - AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); - - // Just print out the uris an exit if the --print-uris flag was used - if (_config->FindB("APT::Get::Print-URIs") == true) - { - // force a hashsum for compatibility reasons - _config->CndSet("Acquire::ForceHash", "md5sum"); - - // get a fetcher - pkgAcquire Fetcher; - if (Fetcher.Setup(&Stat) == false) - return false; - - // Populate it with the source selection and get all Indexes - // (GetAll=true) - if (List->GetIndexes(&Fetcher,true) == false) - return false; - - pkgAcquire::UriIterator I = Fetcher.UriBegin(); - for (; I != Fetcher.UriEnd(); ++I) - cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << - I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl; - return true; - } - - // do the work - if (_config->FindB("APT::Get::Download",true) == true) - ListUpdate(Stat, *List); - - // Rebuild the cache. - if (_config->FindB("pkgCacheFile::Generate", true) == true) - { - pkgCacheFile::RemoveCaches(); - if (Cache.BuildCaches() == false) - return false; - } - - return true; -} - /*}}}*/ -// DoAutomaticRemove - Remove all automatic unused packages /*{{{*/ -// --------------------------------------------------------------------- -/* Remove unused automatic packages */ -bool DoAutomaticRemove(CacheFile &Cache) -{ - bool Debug = _config->FindI("Debug::pkgAutoRemove",false); - bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false); - bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove"); - - pkgDepCache::ActionGroup group(*Cache); - if(Debug) - std::cout << "DoAutomaticRemove()" << std::endl; - - if (doAutoRemove == true && - _config->FindB("APT::Get::Remove",true) == false) - { - c1out << _("We are not supposed to delete stuff, can't start " - "AutoRemover") << std::endl; - return false; - } - - bool purgePkgs = _config->FindB("APT::Get::Purge", false); - bool smallList = (hideAutoRemove == false && - strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0); - - unsigned long autoRemoveCount = 0; - APT::PackageSet tooMuch; - APT::PackageList autoRemoveList; - // look over the cache to see what can be removed - for (unsigned J = 0; J < Cache->Head().PackageCount; ++J) - { - pkgCache::PkgIterator Pkg(Cache,Cache.List[J]); - if (Cache[Pkg].Garbage) - { - if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install()) - if(Debug) - std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl; - - if (doAutoRemove) - { - if(Pkg.CurrentVer() != 0 && - Pkg->CurrentState != pkgCache::State::ConfigFiles) - Cache->MarkDelete(Pkg, purgePkgs, 0, false); - else - Cache->MarkKeep(Pkg, false, false); - } - else - { - if (hideAutoRemove == false && Cache[Pkg].Delete() == false) - autoRemoveList.insert(Pkg); - // if the package is a new install and already garbage we don't need to - // install it in the first place, so nuke it instead of show it - if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0) - { - if (Pkg.CandVersion() != 0) - tooMuch.insert(Pkg); - Cache->MarkDelete(Pkg, false, 0, false); - } - // only show stuff in the list that is not yet marked for removal - else if(hideAutoRemove == false && Cache[Pkg].Delete() == false) - ++autoRemoveCount; - } - } - } - - // we could have removed a new dependency of a garbage package, - // so check if a reverse depends is broken and if so install it again. - if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0)) - { - bool Changed; - do { - Changed = false; - for (APT::PackageSet::const_iterator Pkg = tooMuch.begin(); - Pkg != tooMuch.end() && Changed == false; ++Pkg) - { - APT::PackageSet too; - too.insert(*Pkg); - for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList(); - Prv.end() == false; ++Prv) - too.insert(Prv.ParentPkg()); - for (APT::PackageSet::const_iterator P = too.begin(); - P != too.end() && Changed == false; ++P) { - for (pkgCache::DepIterator R = P.RevDependsList(); - R.end() == false; ++R) - { - if (R.IsNegative() == true || - Cache->IsImportantDep(R) == false) - continue; - pkgCache::PkgIterator N = R.ParentPkg(); - if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false)) - continue; - if (Debug == true) - std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl; - Cache->MarkInstall(Pkg, false, 0, false); - if (hideAutoRemove == false) - ++autoRemoveCount; - tooMuch.erase(Pkg); - Changed = true; - break; - } - } - } - } while (Changed == true); - } - - std::string autoremovelist, autoremoveversions; - if (smallList == false && autoRemoveCount != 0) - { - for (APT::PackageList::const_iterator Pkg = autoRemoveList.begin(); Pkg != autoRemoveList.end(); ++Pkg) - { - if (Cache[Pkg].Garbage == false) - continue; - autoremovelist += Pkg.FullName(true) + " "; - autoremoveversions += string(Cache[Pkg].CandVersion) + "\n"; - } - } - - // Now see if we had destroyed anything (if we had done anything) - if (Cache->BrokenCount() != 0) - { - c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n" - "shouldn't happen. Please file a bug report against apt.") << endl; - c1out << endl; - c1out << _("The following information may help to resolve the situation:") << endl; - c1out << endl; - ShowBroken(c1out,Cache,false); - - return _error->Error(_("Internal Error, AutoRemover broke stuff")); - } - - // if we don't remove them, we should show them! - if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0)) - { - if (smallList == false) - ShowList(c1out, P_("The following package was automatically installed and is no longer required:", - "The following packages were automatically installed and are no longer required:", - autoRemoveCount), autoremovelist, autoremoveversions); - else - ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n", - "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount); - c1out << P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount) << std::endl; - } - return true; -} - /*}}}*/ -// DoUpgrade - Upgrade all packages /*{{{*/ -// --------------------------------------------------------------------- -/* Upgrade all packages without installing new packages or erasing old - packages */ -bool DoUpgrade(CommandLine &CmdL) -{ - CacheFile Cache; - if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) - return false; - - // Do the upgrade - if (pkgAllUpgrade(Cache) == false) - { - ShowBroken(c1out,Cache,false); - return _error->Error(_("Internal error, AllUpgrade broke stuff")); - } - - return InstallPackages(Cache,true); -} - /*}}}*/ -// DoInstall - Install packages from the command line /*{{{*/ -// --------------------------------------------------------------------- -/* Install named packages */ -bool DoInstall(CommandLine &CmdL) -{ - CacheFile Cache; - if (Cache.OpenForInstall() == false || - Cache.CheckDeps(CmdL.FileSize() != 1) == false) - return false; - - // Enter the special broken fixing mode if the user specified arguments - bool BrokenFix = false; - if (Cache->BrokenCount() != 0) - BrokenFix = true; - - pkgProblemResolver* Fix = NULL; - if (_config->FindB("APT::Get::CallResolver", true) == true) - Fix = new pkgProblemResolver(Cache); - - 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) - fallback = MOD_REMOVE; - else if (strcasecmp(CmdL.FileList[0], "purge") == 0) - { - _config->Set("APT::Get::Purge", true); - fallback = MOD_REMOVE; - } - else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0) - { - _config->Set("APT::Get::AutomaticRemove", "true"); - fallback = MOD_REMOVE; - } - - 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); - - if (_error->PendingError() == true) - { - helper.showVirtualPackageErrors(Cache); - if (Fix != NULL) - delete Fix; - return false; - } - - - TryToInstall InstallAction(Cache, Fix, BrokenFix); - TryToRemove RemoveAction(Cache, Fix); - - // new scope for the ActionGroup - { - pkgDepCache::ActionGroup group(Cache); - unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 }; - - 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); - else if (order[i] == MOD_REMOVE) - RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction); - } - - if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true) - { - for (unsigned short i = 0; order[i] != 0; ++i) - { - if (order[i] != MOD_INSTALL) - continue; - InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out); - InstallAction.doAutoInstall(); - } - } - - if (_error->PendingError() == true) - { - if (Fix != NULL) - delete Fix; - 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 */ - if (BrokenFix == true && Cache->BrokenCount() != 0) - { - c1out << _("You might want to run 'apt-get -f install' to correct these:") << endl; - ShowBroken(c1out,Cache,false); - if (Fix != NULL) - delete Fix; - return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).")); - } - - if (Fix != NULL) - { - // Call the scored problem resolver - Fix->Resolve(true); - delete Fix; - } - - // Now we check the state of the packages, - if (Cache->BrokenCount() != 0) - { - c1out << - _("Some packages could not be installed. This may mean that you have\n" - "requested an impossible situation or if you are using the unstable\n" - "distribution that some required packages have not yet been created\n" - "or been moved out of Incoming.") << endl; - /* - if (Packages == 1) - { - c1out << endl; - c1out << - _("Since you only requested a single operation it is extremely likely that\n" - "the package is simply not installable and a bug report against\n" - "that package should be filed.") << endl; - } - */ - - c1out << _("The following information may help to resolve the situation:") << endl; - c1out << endl; - ShowBroken(c1out,Cache,false); - if (_error->PendingError() == true) - return false; - else - return _error->Error(_("Broken packages")); - } - } - if (!DoAutomaticRemove(Cache)) - return false; - - /* Print out a list of packages that are going to be installed extra - to what the user asked */ - if (Cache->InstCount() != verset[MOD_INSTALL].size()) - { - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if ((*Cache)[I].Install() == false) - continue; - pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache); - - if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end()) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CandVersion) + "\n"; - } - - ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList); - } - - /* Print out a list of suggested and recommended packages */ - { - string SuggestsList, RecommendsList; - string SuggestsVersions, RecommendsVersions; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator Pkg(Cache,Cache.List[J]); - - /* Just look at the ones we want to install */ - if ((*Cache)[Pkg].Install() == false) - continue; - - // get the recommends/suggests for the candidate ver - pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache); - for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; ) - { - pkgCache::DepIterator Start; - pkgCache::DepIterator End; - D.GlobOr(Start,End); // advances D - - // FIXME: we really should display a or-group as a or-group to the user - // the problem is that ShowList is incapable of doing this - string RecommendsOrList,RecommendsOrVersions; - string SuggestsOrList,SuggestsOrVersions; - bool foundInstalledInOrGroup = false; - for(;;) - { - /* Skip if package is installed already, or is about to be */ - string target = Start.TargetPkg().FullName(true) + " "; - pkgCache::PkgIterator const TarPkg = Start.TargetPkg(); - if (TarPkg->SelectedState == pkgCache::State::Install || - TarPkg->SelectedState == pkgCache::State::Hold || - Cache[Start.TargetPkg()].Install()) - { - foundInstalledInOrGroup=true; - break; - } - - /* Skip if we already saw it */ - if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1) - { - foundInstalledInOrGroup=true; - break; - } - - // this is a dep on a virtual pkg, check if any package that provides it - // should be installed - if(Start.TargetPkg().ProvidesList() != 0) - { - pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList(); - for (; I.end() == false; ++I) - { - pkgCache::PkgIterator Pkg = I.OwnerPkg(); - if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() && - Pkg.CurrentVer() != 0) - foundInstalledInOrGroup=true; - } - } - - if (Start->Type == pkgCache::Dep::Suggests) - { - SuggestsOrList += target; - SuggestsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n"; - } - - if (Start->Type == pkgCache::Dep::Recommends) - { - RecommendsOrList += target; - RecommendsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n"; - } - - if (Start >= End) - break; - ++Start; - } - - if(foundInstalledInOrGroup == false) - { - RecommendsList += RecommendsOrList; - RecommendsVersions += RecommendsOrVersions; - SuggestsList += SuggestsOrList; - SuggestsVersions += SuggestsOrVersions; - } - - } - } - - ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions); - ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions); - - } - - // 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 (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 - // 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); -} - /*}}}*/ /* mark packages as automatically/manually installed. {{{*/ bool DoMarkAuto(CommandLine &CmdL) { @@ -2585,7 +729,7 @@ bool DoSource(CommandLine &CmdL) if(queued.find(Last->Index().ArchiveURI(I->Path)) != queued.end()) continue; queued.insert(Last->Index().ArchiveURI(I->Path)); - + // check if we have a file with that md5 sum already localy if(!I->MD5Hash.empty() && FileExists(flNotDir(I->Path))) { @@ -3367,23 +1511,6 @@ bool DoChangelog(CommandLine &CmdL) return true; } /*}}}*/ -// DoMoo - Never Ask, Never Tell /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool DoMoo(CommandLine &CmdL) -{ - cout << - " (__) \n" - " (oo) \n" - " /------\\/ \n" - " / | || \n" - " * /\\---/\\ \n" - " ~~ ~~ \n" - "....\"Have you mooed today?\"...\n"; - - return true; -} - /*}}}*/ // ShowHelp - Show a help screen /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -3494,58 +1621,17 @@ void SigWinch(int) #endif } /*}}}*/ + +bool DoUpgrade(CommandLine &CmdL) +{ + if (_config->FindB("APT::Get::UpgradeAllowNew", false) == true) + return DoUpgradeWithAllowNewPackages(CmdL); + else + return DoUpgradeNoNewPackages(CmdL); +} + int main(int argc,const char *argv[]) /*{{{*/ { - CommandLine::Args Args[] = { - {'h',"help","help",0}, - {'v',"version","version",0}, - {'V',"verbose-versions","APT::Get::Show-Versions",0}, - {'q',"quiet","quiet",CommandLine::IntLevel}, - {'q',"silent","quiet",CommandLine::IntLevel}, - {'d',"download-only","APT::Get::Download-Only",0}, - {'b',"compile","APT::Get::Compile",0}, - {'b',"build","APT::Get::Compile",0}, - {'s',"simulate","APT::Get::Simulate",0}, - {'s',"just-print","APT::Get::Simulate",0}, - {'s',"recon","APT::Get::Simulate",0}, - {'s',"dry-run","APT::Get::Simulate",0}, - {'s',"no-act","APT::Get::Simulate",0}, - {'y',"yes","APT::Get::Assume-Yes",0}, - {'y',"assume-yes","APT::Get::Assume-Yes",0}, - {0,"assume-no","APT::Get::Assume-No",0}, - {'f',"fix-broken","APT::Get::Fix-Broken",0}, - {'u',"show-upgraded","APT::Get::Show-Upgraded",0}, - {'m',"ignore-missing","APT::Get::Fix-Missing",0}, - {'t',"target-release","APT::Default-Release",CommandLine::HasArg}, - {'t',"default-release","APT::Default-Release",CommandLine::HasArg}, - {'a',"host-architecture","APT::Get::Host-Architecture",CommandLine::HasArg}, - {0,"download","APT::Get::Download",0}, - {0,"fix-missing","APT::Get::Fix-Missing",0}, - {0,"ignore-hold","APT::Ignore-Hold",0}, - {0,"upgrade","APT::Get::upgrade",0}, - {0,"only-upgrade","APT::Get::Only-Upgrade",0}, - {0,"force-yes","APT::Get::force-yes",0}, - {0,"print-uris","APT::Get::Print-URIs",0}, - {0,"diff-only","APT::Get::Diff-Only",0}, - {0,"debian-only","APT::Get::Diff-Only",0}, - {0,"tar-only","APT::Get::Tar-Only",0}, - {0,"dsc-only","APT::Get::Dsc-Only",0}, - {0,"purge","APT::Get::Purge",0}, - {0,"list-cleanup","APT::Get::List-Cleanup",0}, - {0,"reinstall","APT::Get::ReInstall",0}, - {0,"trivial-only","APT::Get::Trivial-Only",0}, - {0,"remove","APT::Get::Remove",0}, - {0,"only-source","APT::Get::Only-Source",0}, - {0,"arch-only","APT::Get::Arch-Only",0}, - {0,"auto-remove","APT::Get::AutomaticRemove",0}, - {0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0}, - {0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean}, - {0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean}, - {0,"fix-policy","APT::Get::Fix-Policy-Broken",0}, - {0,"solver","APT::Solver",CommandLine::HasArg}, - {'c',"config-file",0,CommandLine::ConfigFile}, - {'o',"option",0,CommandLine::ArbItem}, - {0,0,0,0}}; CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate}, {"upgrade",&DoUpgrade}, {"install",&DoInstall}, @@ -3567,12 +1653,14 @@ int main(int argc,const char *argv[]) /*{{{*/ {"help",&ShowHelp}, {0,0}}; + std::vector<CommandLine::Args> Args = getCommandArgs("apt-get", CommandLine::GetCommand(Cmds, argc, argv)); + // Set up gettext support setlocale(LC_ALL,""); textdomain(PACKAGE); // Parse the command line and initialize the package library - CommandLine CmdL(Args,_config); + CommandLine CmdL(Args.data(),_config); if (pkgInitConfig(*_config) == false || CmdL.Parse(argc,argv) == false || pkgInitSystem(*_config,_system) == false) @@ -3593,33 +1681,15 @@ int main(int argc,const char *argv[]) /*{{{*/ return 0; } - // simulate user-friendly if apt-get has no root privileges - if (getuid() != 0 && _config->FindB("APT::Get::Simulate") == true && - (CmdL.FileSize() == 0 || - (strcmp(CmdL.FileList[0], "source") != 0 && strcmp(CmdL.FileList[0], "download") != 0 && - strcmp(CmdL.FileList[0], "changelog") != 0))) - { - if (_config->FindB("APT::Get::Show-User-Simulation-Note",true) == true) - cout << _("NOTE: This is only a simulation!\n" - " apt-get needs root privileges for real execution.\n" - " Keep also in mind that locking is deactivated,\n" - " so don't depend on the relevance to the real current situation!" - ) << std::endl; - _config->Set("Debug::NoLocking",true); - } + // see if we are in simulate mode + CheckSimulateMode(CmdL); // Deal with stdout not being a tty if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1) _config->Set("quiet","1"); // Setup the output streams - c0out.rdbuf(cout.rdbuf()); - c1out.rdbuf(cout.rdbuf()); - c2out.rdbuf(cout.rdbuf()); - if (_config->FindI("quiet",0) > 0) - c0out.rdbuf(devnull.rdbuf()); - if (_config->FindI("quiet",0) > 1) - c1out.rdbuf(devnull.rdbuf()); + InitOutput(); // Setup the signals signal(SIGPIPE,SIG_IGN); |