X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/3b5421b4c75f5c85b48cbb61bf22642ff52a6352..2abbf30efbba4f652cfa47acc3e88ff9ed1f1889:/apt-pkg/algorithms.cc?ds=inline diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 755474e15..dd0928562 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: algorithms.cc,v 1.6 1998/10/20 02:39:17 jgg Exp $ +// $Id: algorithms.cc,v 1.24 1999/09/30 06:30:34 jgg Exp $ /* ###################################################################### Algorithms - A set of misc algorithms @@ -29,10 +29,15 @@ pkgProblemResolver *pkgProblemResolver::This = 0; // --------------------------------------------------------------------- /* */ pkgSimulate::pkgSimulate(pkgDepCache &Cache) : pkgPackageManager(Cache), - Sim(Cache) + Sim(Cache.GetMap()) { Flags = new unsigned char[Cache.HeaderP->PackageCount]; memset(Flags,0,sizeof(*Flags)*Cache.HeaderP->PackageCount); + + // Fake a filename so as not to activate the media swapping + string Jnk = "SIMULATE"; + for (unsigned int I = 0; I != Cache.Head().PackageCount; I++) + FileNames[I] = Jnk; } /*}}}*/ // Simulate::Install - Simulate unpacking of a package /*{{{*/ @@ -44,7 +49,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/) PkgIterator Pkg = Sim.FindPkg(iPkg.Name()); Flags[Pkg->ID] = 1; - clog << "Inst " << Pkg.Name(); + cout << "Inst " << Pkg.Name(); Sim.MarkInstall(Pkg,false); // Look for broken conflicts+predepends. @@ -58,7 +63,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/) { if ((Sim[D] & pkgDepCache::DepInstall) == 0) { - clog << " [" << I.Name() << " on " << D.TargetPkg().Name() << ']'; + cout << " [" << I.Name() << " on " << D.TargetPkg().Name() << ']'; if (D->Type == pkgCache::Dep::Conflicts) _error->Error("Fatal, conflicts violated %s",I.Name()); } @@ -68,7 +73,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/) if (Sim.BrokenCount() != 0) ShortBreaks(); else - clog << endl; + cout << endl; return true; } /*}}}*/ @@ -86,7 +91,7 @@ bool pkgSimulate::Configure(PkgIterator iPkg) // Sim.MarkInstall(Pkg,false); if (Sim[Pkg].InstBroken() == true) { - clog << "Conf " << Pkg.Name() << " broken" << endl; + cout << "Conf " << Pkg.Name() << " broken" << endl; Sim.Update(); @@ -98,21 +103,21 @@ bool pkgSimulate::Configure(PkgIterator iPkg) continue; if (D->Type == pkgCache::Dep::Conflicts) - clog << " Conflicts:" << D.TargetPkg().Name(); + cout << " Conflicts:" << D.TargetPkg().Name(); else - clog << " Depends:" << D.TargetPkg().Name(); + cout << " Depends:" << D.TargetPkg().Name(); } - clog << endl; + cout << endl; _error->Error("Conf Broken %s",Pkg.Name()); } else - clog << "Conf " << Pkg.Name(); + cout << "Conf " << Pkg.Name(); if (Sim.BrokenCount() != 0) ShortBreaks(); else - clog << endl; + cout << endl; return true; } @@ -120,19 +125,22 @@ bool pkgSimulate::Configure(PkgIterator iPkg) // Simulate::Remove - Simulate the removal of a package /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgSimulate::Remove(PkgIterator iPkg) +bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge) { // Adapt the iterator PkgIterator Pkg = Sim.FindPkg(iPkg.Name()); Flags[Pkg->ID] = 3; Sim.MarkDelete(Pkg); - clog << "Remv " << Pkg.Name(); + if (Purge == true) + cout << "Purg " << Pkg.Name(); + else + cout << "Remv " << Pkg.Name(); if (Sim.BrokenCount() != 0) ShortBreaks(); else - clog << endl; + cout << endl; return true; } @@ -142,18 +150,18 @@ bool pkgSimulate::Remove(PkgIterator iPkg) /* */ void pkgSimulate::ShortBreaks() { - clog << " ["; + cout << " ["; for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++) { if (Sim[I].InstBroken() == true) { if (Flags[I->ID] == 0) - clog << I.Name() << ' '; + cout << I.Name() << ' '; /* else - clog << I.Name() << "! ";*/ + cout << I.Name() << "! ";*/ } } - clog << ']' << endl; + cout << ']' << endl; } /*}}}*/ // ApplyStatus - Adjust for non-ok packages /*{{{*/ @@ -165,12 +173,41 @@ bool pkgApplyStatus(pkgDepCache &Cache) { for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) { + // Only choice for a ReInstReq package is to reinstall + if (I->InstState == pkgCache::State::ReInstReq || + I->InstState == pkgCache::State::HoldReInstReq) + { + if (I.CurrentVer().Downloadable() == true) + Cache.MarkKeep(I); + else + { + // Is this right? Will dpkg choke on an upgrade? + if (Cache[I].CandidateVerIter(Cache).Downloadable() == true) + Cache.MarkInstall(I); + else + return _error->Error("The package %s needs to be reinstalled, " + "but I can't find an archive for it.",I.Name()); + } + + continue; + } + switch (I->CurrentState) { - // This means installation failed somehow + /* This means installation failed somehow - it does not need to be + re-unpacked (probably) */ case pkgCache::State::UnPacked: case pkgCache::State::HalfConfigured: - Cache.MarkKeep(I); + if (I.CurrentVer().Downloadable() == true || + I.State() != pkgCache::PkgIterator::NeedsUnpack) + Cache.MarkKeep(I); + else + { + if (Cache[I].CandidateVerIter(Cache).Downloadable() == true) + Cache.MarkInstall(I); + else + Cache.MarkDelete(I); + } break; // This means removal failed @@ -245,14 +282,17 @@ bool pkgDistUpgrade(pkgDepCache &Cache) Cache.MarkInstall(I,false); pkgProblemResolver Fix(Cache); - + // Hold back held packages. - for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) + if (_config->FindB("APT::Ingore-Hold",false) == false) { - if (I->SelectedState == pkgCache::State::Hold) + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) { - Fix.Protect(I); - Cache.MarkKeep(I); + if (I->SelectedState == pkgCache::State::Hold) + { + Fix.Protect(I); + Cache.MarkKeep(I); + } } } @@ -277,8 +317,9 @@ bool pkgAllUpgrade(pkgDepCache &Cache) if (Cache[I].Install() == true) Fix.Protect(I); - if (I->SelectedState == pkgCache::State::Hold) - continue; + if (_config->FindB("APT::Ingore-Hold",false) == false) + if (I->SelectedState == pkgCache::State::Hold) + continue; if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) Cache.MarkInstall(I,false); @@ -299,6 +340,7 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache) // We loop indefinately to get the minimal set size. bool Change = false; + unsigned int Count = 0; do { Change = false; @@ -307,16 +349,21 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache) // Not interesting if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) continue; - + // Keep it and see if that is OK Cache.MarkKeep(I); if (Cache.BrokenCount() != 0) Cache.MarkInstall(I,false); else - Change = true; + { + // If keep didnt actually do anything then there was no change.. + if (Cache[I].Upgrade() == false) + Change = true; + } } + Count++; } - while (Change == true); + while (Change == true && Count < 10); if (Cache.BrokenCount() != 0) return _error->Error("Internal Error in pkgMinimizeUpgrade"); @@ -441,8 +488,12 @@ void pkgProblemResolver::MakeScores() /* Protected things are pushed really high up. This number should put them ahead of everything */ for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) + { if ((Flags[I->ID] & Protected) != 0) Scores[I->ID] += 10000; + if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) + Scores[I->ID] += 5000; + } delete [] OldScores; } @@ -640,7 +691,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) { if (Debug == true) clog << " Try to Re-Instate " << I.Name() << endl; - int OldBreaks = Cache.BrokenCount(); + unsigned long OldBreaks = Cache.BrokenCount(); pkgCache::Version *OldVer = Cache[I].InstallVer; Flags[I->ID] &= ReInstateTried; @@ -664,20 +715,18 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) // Isolate the problem dependency PackageKill KillList[100]; PackageKill *LEnd = KillList; - for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;) + bool InOr = false; + pkgCache::DepIterator Start; + pkgCache::DepIterator End; + for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); + D.end() == false || InOr == true;) { // Compute a single dependency element (glob or) - pkgCache::DepIterator Start = D; - pkgCache::DepIterator End = D; - unsigned char State = 0; - for (bool LastOR = true; D.end() == false && LastOR == true; D++) - { - State |= Cache[D]; - LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; - if (LastOR == true) - End = D; - } - + if (InOr == false) + D.GlobOr(Start,End); + else + Start++; + // We only worry about critical deps. if (End.IsCritical() != true) continue; @@ -686,20 +735,34 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) continue; + InOr = Start != End; + // Hm, the group is broken.. I have no idea how to handle this - if (Start != End) +/* if (Start != End) { - clog << "Note, a broken or group was found in " << I.Name() << "." << endl; - Cache.MarkDelete(I); + if (Debug == true) + clog << "Note, a broken or group was found in " << I.Name() << "." << endl; + if ((Flags[I->ID] & Protected) != Protected) + Cache.MarkDelete(I); break; - } + }*/ if (Debug == true) - clog << "Package " << I.Name() << " has broken dep on " << End.TargetPkg().Name() << endl; + clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl; + + /* Look across the version list. If there are no possible + targets then we keep the package and bail. This is necessary + if a package has a dep on another package that cant be found */ + pkgCache::Version **VList = Start.AllTargets(); + if (*VList == 0 && (Flags[I->ID] & Protected) != Protected && + Start->Type != pkgCache::Dep::Conflicts && + Cache[I].NowBroken() == false) + { + Change = true; + Cache.MarkKeep(I); + break; + } - /* Conflicts is simple, decide if we should remove this package - or the conflicted one */ - pkgCache::Version **VList = End.AllTargets(); bool Done = false; for (pkgCache::Version **V = VList; *V != 0; V++) { @@ -707,34 +770,44 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) pkgCache::PkgIterator Pkg = Ver.ParentPkg(); if (Debug == true) - clog << " Considering " << Pkg.Name() << ' ' << (int)Scores[Pkg->ID] << + clog << " Considering " << Pkg.Name() << ' ' << (int)Scores[Pkg->ID] << " as a solution to " << I.Name() << ' ' << (int)Scores[I->ID] << endl; if (Scores[I->ID] <= Scores[Pkg->ID] || - ((Cache[End] & pkgDepCache::DepGNow) == 0 && + ((Cache[Start] & pkgDepCache::DepNow) == 0 && End->Type != pkgCache::Dep::Conflicts)) { + // Try a little harder to fix protected packages.. if ((Flags[I->ID] & Protected) == Protected) + { + if (DoUpgrade(Pkg) == true) + Scores[Pkg->ID] = Scores[I->ID]; continue; - - // See if a keep will do + } + + /* See if a keep will do, unless the package is protected, + then installing it will be necessary */ Cache.MarkKeep(I); if (Cache[I].InstBroken() == false) { if (Debug == true) - clog << " Holding Back " << I.Name() << " rather than change " << End.TargetPkg().Name() << endl; + clog << " Holding Back " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl; } else - { + { if (BrokenFix == false || DoUpgrade(I) == false) { - if (Debug == true) - clog << " Removing " << I.Name() << " rather than change " << End.TargetPkg().Name() << endl; - Cache.MarkDelete(I); - if (Counter > 1) - Scores[I->ID] = Scores[Pkg->ID]; + // Consider other options + if (InOr == false) + { + if (Debug == true) + clog << " Removing " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl; + Cache.MarkDelete(I); + if (Counter > 1) + Scores[I->ID] = Scores[Pkg->ID]; + } } } - + Change = true; Done = true; break; @@ -749,25 +822,25 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) LEnd->Dep = End; LEnd++; - if (End->Type != pkgCache::Dep::Conflicts) + if (Start->Type != pkgCache::Dep::Conflicts) break; } } // Hm, nothing can possibly satisify this dep. Nuke it. - if (VList[0] == 0 && End->Type != pkgCache::Dep::Conflicts && - (Flags[I->ID] & Protected) != Protected) + if (VList[0] == 0 && Start->Type != pkgCache::Dep::Conflicts && + (Flags[I->ID] & Protected) != Protected && InOr == false) { Cache.MarkKeep(I); if (Cache[I].InstBroken() == false) { if (Debug == true) - clog << " Holding Back " << I.Name() << " because I can't find " << End.TargetPkg().Name() << endl; + clog << " Holding Back " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl; } else { if (Debug == true) - clog << " Removing " << I.Name() << " because I can't find " << End.TargetPkg().Name() << endl; + clog << " Removing " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl; Cache.MarkDelete(I); } @@ -775,6 +848,10 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) Done = true; } + // Try some more + if (InOr == true) + continue; + delete [] VList; if (Done == true) break; @@ -814,8 +891,19 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) delete [] PList; if (Cache.BrokenCount() != 0) - return _error->Error("Internal error, pkgProblemResolver::Resolve generated breaks."); - + { + // See if this is the result of a hold + pkgCache::PkgIterator I = Cache.PkgBegin(); + for (;I.end() != true; I++) + { + if (Cache[I].InstBroken() == false) + continue; + if ((Flags[I->ID] & Protected) != Protected) + return _error->Error("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."); + } + return _error->Error("Unable to correct problems, you have held broken packages."); + } + return true; } /*}}}*/ @@ -904,7 +992,6 @@ bool pkgProblemResolver::ResolveByKeep() // Look at all the possible provides on this package pkgCache::Version **VList = End.AllTargets(); - bool Done = false; for (pkgCache::Version **V = VList; *V != 0; V++) { pkgCache::VerIterator Ver(Cache,*V);