X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/23c5897cbdb5a957788201a5178e963586dcdbc9..c8db3fff877f102dc6fb62c4e4c7f700160b68f5:/cmdline/apt-get.cc diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index eaf04eee7..d3ddcbfe8 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -40,11 +40,12 @@ #include #include #include - + #include #include #include "acqprogress.h" +#include "cacheset.h" #include #include @@ -90,14 +91,14 @@ class CacheFile : public pkgCacheFile bool BuildCaches(bool WithLock = true) { OpTextProgress Prog(*_config); - if (pkgCacheFile::BuildCaches(Prog,WithLock) == false) + if (pkgCacheFile::BuildCaches(&Prog,WithLock) == false) return false; return true; } bool Open(bool WithLock = true) { OpTextProgress Prog(*_config); - if (pkgCacheFile::Open(Prog,WithLock) == false) + if (pkgCacheFile::Open(&Prog,WithLock) == false) return false; Sort(); @@ -837,9 +838,9 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, return false; // Display statistics - double FetchBytes = Fetcher.FetchNeeded(); - double FetchPBytes = Fetcher.PartialPresent(); - double DebBytes = Fetcher.TotalNeeded(); + 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; @@ -1078,43 +1079,8 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, name matching it was split out.. */ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &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; - } - } // Handle the no-upgrade case if (_config->FindB("APT::Get::upgrade",true) == false && @@ -1243,49 +1209,12 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache, 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"))); - return true; } /*}}}*/ @@ -1623,60 +1552,87 @@ 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); +// 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; + +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()); + } + + virtual APT::VersionSet canNotFindCandInstVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + return tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDINST); + } + + virtual APT::VersionSet canNotFindInstCandVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + return tryVirtualPackage(Cache, Pkg, APT::VersionSet::INSTCAND); + } + + 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) { + if (select == APT::VersionSet::CANDINST) + return APT::CacheSetHelper::canNotFindCandInstVer(Cache, Pkg); + return APT::CacheSetHelper::canNotFindInstCandVer(Cache, Pkg); + } + + 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); + } + if (select == APT::VersionSet::CANDINST) + return APT::CacheSetHelper::canNotFindCandInstVer(Cache, Pkg); + return APT::CacheSetHelper::canNotFindInstCandVer(Cache, Pkg); + } + + inline bool allPkgNamedExplicitly() const { return explicitlyNamed; } - regfree(&Pattern); - return res; -} +}; /*}}}*/ // DoInstall - Install packages from the command line /*{{{*/ // --------------------------------------------------------------------- @@ -1694,166 +1650,90 @@ bool DoInstall(CommandLine &CmdL) 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; + } + + std::list mods; + mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+", + APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDINST)); + mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-", + APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::INSTCAND)); + CacheSetHelperAPTGet helper(c0out); + std::map verset = APT::VersionSet::GroupedFromCommandLine(Cache, + CmdL.FileList + 1, mods, fallback, helper); + + if (_error->PendingError() == true) + return false; + + 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; } + // new scope for the ActionGroup { pkgDepCache::ActionGroup group(Cache); - for (const char **I = CmdL.FileList + 1; *I != 0; I++) + for (unsigned short i = 0; order[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; - } - - while (Cache->FindPkg(S).end() == true) - { - // Handle an optional end tag indicating what to do - if (Length >= 1 && S[Length - 1] == '-') + if (order[i] == MOD_INSTALL) + for (APT::VersionSet::const_iterator Ver = verset[MOD_INSTALL].begin(); + Ver != verset[MOD_INSTALL].end(); ++Ver) { - 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) - { - // Check if the name is a regex - const char *I; - for (I = S; *I != 0; I++) - if (*I == '?' || *I == '*' || *I == '|' || - *I == '[' || *I == '^' || *I == '$') - break; - if (*I == 0) - return _error->Error(_("Couldn't find package %s"),S); + pkgCache::PkgIterator Pkg = Ver.ParentPkg(); + Cache->SetCandidateVersion(Ver); - // Regexs must always be confirmed - ExpectedInst += 1000; - - // Compile the regex pattern - regex_t Pattern; - int Res; - if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE | - REG_NOSUB)) != 0) - { - char Error[300]; - regerror(Res,&Pattern,Error,sizeof(Error)); - return _error->Error(_("Regex compilation error - %s"),Error); + if (TryToInstall(Pkg, Cache, Fix, false, BrokenFix) == 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 (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++; + } } - - // Run over the matches - bool Hit = false; - for (pkgCache::GrpIterator Grp = Cache->GrpBegin(); Grp.end() == false; ++Grp) + else if (order[i] == MOD_REMOVE) + for (APT::VersionSet::const_iterator Ver = verset[MOD_REMOVE].begin(); + Ver != verset[MOD_REMOVE].end(); ++Ver) { - if (regexec(&Pattern,Grp.Name(),0,0,0) != 0) - continue; - Pkg = Grp.FindPkg("native"); - if (unlikely(Pkg.end() == true)) - continue; + pkgCache::PkgIterator Pkg = Ver.ParentPkg(); - ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"), - Pkg.Name(),S); - - if (VerTag != 0) - if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false) - return false; - - Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix, - ExpectedInst,false); - } - regfree(&Pattern); - - if (Hit == false) - return _error->Error(_("Couldn't find package %s"),S); - } - else - { - if (VerTag != 0) - if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false) + if (TryToInstall(Pkg, Cache, Fix, true, BrokenFix) == 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++; } - } } + 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 */ @@ -1900,7 +1780,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; @@ -2026,7 +1906,8 @@ bool DoInstall(CommandLine &CmdL) 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); @@ -2389,9 +2270,9 @@ bool DoSource(CommandLine &CmdL) } // Display statistics - double FetchBytes = Fetcher.FetchNeeded(); - double FetchPBytes = Fetcher.PartialPresent(); - double DebBytes = Fetcher.TotalNeeded(); + unsigned long long FetchBytes = Fetcher.FetchNeeded(); + unsigned long long FetchPBytes = Fetcher.PartialPresent(); + unsigned long long DebBytes = Fetcher.TotalNeeded(); // Check for enough free space struct statvfs Buf; @@ -2610,7 +2491,6 @@ bool DoBuildDep(CommandLine &CmdL) } // Install the requested packages - unsigned int ExpectedInst = 0; vector ::iterator D; pkgProblemResolver Fix(Cache); bool skipAlternatives = false; // skip remaining alternatives in an or group @@ -2641,7 +2521,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); + TryToInstall(Pkg,Cache,Fix,true,false); } else // BuildDep || BuildDepIndep { @@ -2757,7 +2637,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 (TryToInstall(Pkg,Cache,Fix,false,false) == true) { // We successfully installed something; skip remaining alternatives skipAlternatives = hasAlternatives; @@ -3047,7 +2927,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 @@ -3068,13 +2948,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; } /*}}}*/