X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/bc03039d0f532b6463de33bff60c7d876af6ea5e..dd09a217ac0d331f4a0324cf42559da5d35edc9a:/cmdline/apt-get.cc diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 54c464a37..cb0690bdf 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ #include "acqprogress.h" +#include #include #include #include @@ -627,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; @@ -638,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, false, 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) @@ -1144,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; } /*}}}*/ @@ -1367,7 +1385,7 @@ bool DoUpdate(CommandLine &CmdL) } // Clean out any old list files - if (_config->FindB("APT::Get::List-Cleanup",true) == true) + if (!Failed && _config->FindB("APT::Get::List-Cleanup",true) == true) { if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false || Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false) @@ -1451,20 +1469,56 @@ bool DoUpgrade(CommandLine &CmdL) return InstallPackages(Cache,true); } /*}}}*/ -// DoInstall - Install packages from the command line /*{{{*/ +// DoInstallTask - Install task from the command line /*{{{*/ // --------------------------------------------------------------------- -/* Install named packages */ -bool DoInstall(CommandLine &CmdL) +/* Install named task */ +bool TryInstallTask(pkgDepCache &Cache, pkgProblemResolver &Fix, + bool BrokenFix, + unsigned int& ExpectedInst, + const char *taskname) { - // Lock the list directory - FileFd Lock; - if (_config->FindB("Debug::NoLocking",false) == false) + 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:.*[^a-z]%s[^a-z].*\n", taskname); + regcomp(&Pattern,S, REG_EXTENDED | REG_NOSUB | REG_NEWLINE); + + bool found = false; + bool res = true; + for (Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++) { - Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock")); - if (_error->PendingError() == true) - return _error->Error(_("Unable to lock the list directory")); + 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,false,BrokenFix,ExpectedInst); + found = true; } + if(!found) + _error->Error(_("Couldn't find task %s"),taskname); + + regfree(&Pattern); + return res; +} + +// DoInstall - Install packages from the command line /*{{{*/ +// --------------------------------------------------------------------- +/* Install named packages */ +bool DoInstall(CommandLine &CmdL) +{ CacheFile Cache; if (Cache.OpenForInstall() == false || Cache.CheckDeps(CmdL.FileSize() != 1) == false) @@ -1501,6 +1555,18 @@ bool DoInstall(CommandLine &CmdL) 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); + continue; + } + while (Cache->FindPkg(S).end() == true) { // Handle an optional end tag indicating what to do @@ -1517,7 +1583,7 @@ bool DoInstall(CommandLine &CmdL) S[--Length] = 0; continue; } - + char *Slash = strchr(S,'='); if (Slash != 0) { @@ -1673,68 +1739,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); @@ -1778,6 +1862,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++) @@ -1956,6 +2042,9 @@ bool DoSource(CommandLine &CmdL) DscFile *Dsc = new DscFile[CmdL.FileSize()]; + // insert all downloaded uris into this set to avoid downloading them + // twice + set queued; // Load the requestd sources into the fetcher unsigned J = 0; for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) @@ -1992,7 +2081,28 @@ bool DoSource(CommandLine &CmdL) if (_config->FindB("APT::Get::Tar-Only",false) == true && I->Type != "tar") continue; - + + // don't download the same uri twice (should this be moved to + // the fetcher interface itself?) + 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))) + { + FileFd Fd(flNotDir(I->Path), FileFd::ReadOnly); + MD5Summation sum; + sum.AddFD(Fd.Fd(), Fd.Size()); + Fd.Close(); + if((string)sum.Result() == I->MD5Hash) + { + ioprintf(c1out,_("Skipping already downloaded file '%s'\n"), + flNotDir(I->Path).c_str()); + continue; + } + } + new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path), I->MD5Hash,I->Size, Last->Index().SourceInfo(*Last,*I),Src); @@ -2564,6 +2674,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}};