X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/e9afbeb9df95b582aac76bb44b5ae2b766ab8fd5..2ae2e04d97028b558bfe954e55a80513e0202889:/cmdline/apt-get.cc diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 304757569..96e974acb 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -629,6 +629,8 @@ void CacheFile::Sort() 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; @@ -640,12 +642,24 @@ bool CacheFile::CheckDeps(bool AllowBroken) 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,true); + } + } + // Nothing is broken if (DCache->BrokenCount() == 0 || AllowBroken == true) return true; // Attempt to fix broken things - if (_config->FindB("APT::Get::Fix-Broken",false) == true) + if (FixBroken == true) { c1out << _("Correcting dependencies...") << flush; if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0) @@ -1146,9 +1160,11 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache, else ExpectedInst++; - // Install it with autoinstalling enabled. - if (State.InstBroken() == true && BrokenFix == false) + // 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; } /*}}}*/ @@ -1487,159 +1503,162 @@ bool DoInstall(CommandLine &CmdL) if (strcasecmp(CmdL.FileList[0],"remove") == 0) DefRemove = true; else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0) - { - _config->Set("APT::Get::AutomaticRemove", "true"); - DefRemove = true; - } + { + _config->Set("APT::Get::AutomaticRemove", "true"); + DefRemove = true; + } - for (const char **I = CmdL.FileList + 1; *I != 0; I++) + // new scope for the ActionGroup { - // 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; - while (Cache->FindPkg(S).end() == true) + pkgDepCache::ActionGroup group(Cache); + for (const char **I = CmdL.FileList + 1; *I != 0; I++) { - // Handle an optional end tag indicating what to do - if (Length >= 1 && S[Length - 1] == '-') - { - Remove = true; - S[--Length] = 0; + // Duplicate the string + unsigned int Length = strlen(*I); + char S[300]; + if (Length >= sizeof(S)) continue; - } - - if (Length >= 1 && S[Length - 1] == '+') + strcpy(S,*I); + + // See if we are removing and special indicators.. + bool Remove = DefRemove; + char *VerTag = 0; + bool VerIsRel = false; + while (Cache->FindPkg(S).end() == true) { - Remove = false; - S[--Length] = 0; - continue; - } + // Handle an optional end tag indicating what to do + if (Length >= 1 && S[Length - 1] == '-') + { + Remove = true; + S[--Length] = 0; + continue; + } - char *Slash = strchr(S,'='); - if (Slash != 0) - { - VerIsRel = false; - *Slash = 0; - VerTag = Slash + 1; - } + if (Length >= 1 && S[Length - 1] == '+') + { + Remove = false; + S[--Length] = 0; + continue; + } - Slash = strchr(S,'/'); - if (Slash != 0) - { - VerIsRel = true; - *Slash = 0; - VerTag = Slash + 1; - } + char *Slash = strchr(S,'='); + if (Slash != 0) + { + VerIsRel = false; + *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); - - // Regexs must always be confirmed - ExpectedInst += 1000; + Slash = strchr(S,'/'); + if (Slash != 0) + { + VerIsRel = true; + *Slash = 0; + VerTag = Slash + 1; + } - // 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); + break; } - - // Run over the matches - bool Hit = false; - for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++) + + // Locate the package + pkgCache::PkgIterator Pkg = Cache->FindPkg(S); + Packages++; + if (Pkg.end() == true) { - if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0) - continue; + // 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); + + // 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); + } + + // Run over the matches + bool Hit = false; + for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++) + { + if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0) + continue; - ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"), - Pkg.Name(),S); + 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) 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,Remove,BrokenFix,ExpectedInst) == false) return false; - if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false) - 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 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); - return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).")); - } + return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).")); + } - // Call the scored problem resolver - Fix.InstallProtect(); - if (Fix.Resolve(true) == false) - _error->Discard(); + // Call the scored problem resolver + Fix.InstallProtect(); + if (Fix.Resolve(true) == false) + _error->Discard(); - // 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) + // Now we check the state of the packages, + if (Cache->BrokenCount() != 0) { - 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; - } + _("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); - return _error->Error(_("Broken packages")); - } - + c1out << _("The following information may help to resolve the situation:") << endl; + c1out << endl; + ShowBroken(c1out,Cache,false); + return _error->Error(_("Broken packages")); + } + } if (_config->FindB("APT::Get::AutomaticRemove")) { if (!DoAutomaticRemove(Cache)) return false; @@ -1677,68 +1696,86 @@ bool DoInstall(CommandLine &CmdL) string SuggestsVersions, RecommendsVersions; for (unsigned J = 0; J < Cache->Head().PackageCount; J++) { - pkgCache::PkgIterator I(Cache,Cache.List[J]); + pkgCache::PkgIterator Pkg(Cache,Cache.List[J]); /* Just look at the ones we want to install */ - if ((*Cache)[I].Install() == false) + if ((*Cache)[Pkg].Install() == false) continue; - for (pkgCache::VerIterator V = I.VersionList(); V.end() == false; V++) - { - for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; ) - { - pkgCache::DepIterator Start; - pkgCache::DepIterator End; - D.GlobOr(Start,End); // advances D - - /* - * If this is a virtual package, we need to check the list of - * packages that provide it and see if any of those are - * installed - */ - - bool providedBySomething = false; - for (pkgCache::PrvIterator Prv = Start.TargetPkg().ProvidesList(); - Prv.end() != true; - Prv++) - if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false) - { - providedBySomething = true; - break; - } - - if (providedBySomething) continue; - - for(;;) - { - /* Skip if package is installed already, or is about to be */ - string target = string(Start.TargetPkg().Name()) + " "; - - if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install - || Cache[Start.TargetPkg()].Install()) - break; - - /* Skip if we already saw it */ - if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1) - break; - - if (Start->Type == pkgCache::Dep::Suggests) { - SuggestsList += target; - SuggestsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n"; - } - - if (Start->Type == pkgCache::Dep::Recommends) { - RecommendsList += target; - RecommendsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n"; - } - - if (Start >= End) - break; - Start++; - } - } - } + // 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 = string(Start.TargetPkg().Name()) + " "; + + if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install + || 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); @@ -1782,6 +1819,8 @@ bool DoDSelectUpgrade(CommandLine &CmdL) if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) return false; + pkgDepCache::ActionGroup group(Cache); + // Install everything with the install flag set pkgCache::PkgIterator I = Cache->PkgBegin(); for (;I.end() != true; I++) @@ -2592,6 +2631,8 @@ int main(int argc,const char *argv[]) {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,"fix-policy","APT::Get::Fix-Policy-Broken",0}, {'c',"config-file",0,CommandLine::ConfigFile}, {'o',"option",0,CommandLine::ArbItem}, {0,0,0,0}};