X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/421c8d109932a2615b9327c8b69aad715d4b1162..00b47c98ca4a4349686a082eba6d77decbb03a4d:/apt-pkg/algorithms.cc diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index dd0928562..7f7cb204f 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.24 1999/09/30 06:30:34 jgg Exp $ +// $Id: algorithms.cc,v 1.31 2000/10/03 23:59:05 jgg Exp $ /* ###################################################################### Algorithms - A set of misc algorithms @@ -284,7 +284,7 @@ bool pkgDistUpgrade(pkgDepCache &Cache) pkgProblemResolver Fix(Cache); // Hold back held packages. - if (_config->FindB("APT::Ingore-Hold",false) == false) + if (_config->FindB("APT::Ignore-Hold",false) == false) { for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) { @@ -524,10 +524,11 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) pkgCache::DepIterator Start = D; pkgCache::DepIterator End = D; unsigned char State = 0; - for (bool LastOR = true; D.end() == false && LastOR == true; D++) + for (bool LastOR = true; D.end() == false && LastOR == true;) { State |= Cache[D]; LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; + D++; if (LastOR == true) End = D; } @@ -535,52 +536,58 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg) // We only worry about critical deps. if (End.IsCritical() != true) continue; - - // Dep is ok - if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) - continue; - - // Hm, the group is broken.. I have no idea how to handle this - if (Start != End) - { - clog << "Note, a broken or group was found in " << Pkg.Name() << "." << endl; - Fail = true; - break; - } - - // Do not change protected packages - PkgIterator P = Start.SmartTargetPkg(); - if ((Flags[P->ID] & Protected) == Protected) + + // Iterate over all the members in the or group + while (1) { - if (Debug == true) - clog << " Reinet Failed because of protected " << P.Name() << endl; - Fail = true; - break; - } - - // Upgrade the package if the candidate version will fix the problem. - if ((Cache[Start] & pkgDepCache::DepCVer) == pkgDepCache::DepCVer) - { - if (DoUpgrade(P) == false) + // Dep is ok now + if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) + break; + + // Do not change protected packages + PkgIterator P = Start.SmartTargetPkg(); + if ((Flags[P->ID] & Protected) == Protected) { if (Debug == true) - clog << " Reinst Failed because of " << P.Name() << endl; + clog << " Reinst Failed because of protected " << P.Name() << endl; Fail = true; + } + else + { + // Upgrade the package if the candidate version will fix the problem. + if ((Cache[Start] & pkgDepCache::DepCVer) == pkgDepCache::DepCVer) + { + if (DoUpgrade(P) == false) + { + if (Debug == true) + clog << " Reinst Failed because of " << P.Name() << endl; + Fail = true; + } + else + { + Fail = false; + break; + } + } + else + { + /* We let the algorithm deal with conflicts on its next iteration, + it is much smarter than us */ + if (Start->Type == pkgCache::Dep::Conflicts) + break; + + if (Debug == true) + clog << " Reinst Failed early because of " << Start.TargetPkg().Name() << endl; + Fail = true; + } + } + + if (Start == End) break; - } + Start++; } - else - { - /* We let the algorithm deal with conflicts on its next iteration, - it is much smarter than us */ - if (End->Type == pkgCache::Dep::Conflicts) - continue; - - if (Debug == true) - clog << " Reinst Failed early because of " << Start.TargetPkg().Name() << endl; - Fail = true; + if (Fail == true) break; - } } // Undo our operations - it might be smart to undo everything this did.. @@ -712,40 +719,63 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false) continue; + if (Debug == true) + cout << "Investigating " << I.Name() << endl; + // Isolate the problem dependency PackageKill KillList[100]; PackageKill *LEnd = KillList; bool InOr = false; pkgCache::DepIterator Start; pkgCache::DepIterator End; + PackageKill *OldEnd; + + enum {OrRemove,OrKeep} OrOp = OrRemove; for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false || InOr == true;) { + // We only worry about critical deps. + if (D.IsCritical() != true) + { + D++; + continue; + } + // Compute a single dependency element (glob or) - if (InOr == false) + if (Start == End) + { + // Decide what to do + if (InOr == true) + { + if (OldEnd == LEnd && OrOp == OrRemove) + { + if ((Flags[I->ID] & Protected) != Protected) + { + if (Debug == true) + clog << " Or group remove for " << I.Name() << endl; + Cache.MarkDelete(I); + } + } + if (OldEnd == LEnd && OrOp == OrKeep) + { + if (Debug == true) + clog << " Or group keep for " << I.Name() << endl; + Cache.MarkKeep(I); + } + } + + OrOp = OrRemove; D.GlobOr(Start,End); + InOr = Start != End; + cout << Start.TargetPkg().Name() << ',' << End.TargetPkg().Name() << ',' << InOr << endl; + OldEnd = LEnd; + } else Start++; - - // We only worry about critical deps. - if (End.IsCritical() != true) - continue; // Dep is ok 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 (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 " << Start.TargetPkg().Name() << endl; @@ -755,11 +785,18 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) 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 && + Start->Type != pkgCache::Dep::Conflicts && Cache[I].NowBroken() == false) - { + { + if (InOr == true) + { + /* No keep choice because the keep being OK could be the + result of another element in the OR group! */ + continue; + } + Change = true; - Cache.MarkKeep(I); + Cache.MarkKeep(I); break; } @@ -780,15 +817,28 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) if ((Flags[I->ID] & Protected) == Protected) { if (DoUpgrade(Pkg) == true) + { Scores[Pkg->ID] = Scores[I->ID]; + break; + } + continue; } /* See if a keep will do, unless the package is protected, - then installing it will be necessary */ + then installing it will be necessary */ + bool Installed = Cache[I].Install(); Cache.MarkKeep(I); if (Cache[I].InstBroken() == false) { + // Unwind operation will be keep now + if (OrOp == OrRemove) + OrOp = OrKeep; + + // Restore + if (InOr == true && Installed == true) + Cache.MarkInstall(I,false); + if (Debug == true) clog << " Holding Back " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl; } @@ -814,7 +864,9 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) } else { - // Skip this if it is protected + if (Debug == true) + clog << " Added " << Pkg.Name() << " to the remove list" << endl; + // Skip adding to the kill list if it is protected if ((Flags[Pkg->ID] & Protected) != 0) continue; @@ -829,11 +881,20 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) // Hm, nothing can possibly satisify this dep. Nuke it. if (VList[0] == 0 && Start->Type != pkgCache::Dep::Conflicts && - (Flags[I->ID] & Protected) != Protected && InOr == false) + (Flags[I->ID] & Protected) != Protected) { + bool Installed = Cache[I].Install(); Cache.MarkKeep(I); if (Cache[I].InstBroken() == false) { + // Unwind operation will be keep now + if (OrOp == OrRemove) + OrOp = OrKeep; + + // Restore + if (InOr == true && Installed == true) + Cache.MarkInstall(I,false); + if (Debug == true) clog << " Holding Back " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl; } @@ -841,47 +902,51 @@ bool pkgProblemResolver::Resolve(bool BrokenFix) { if (Debug == true) clog << " Removing " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl; - Cache.MarkDelete(I); + if (InOr == false) + Cache.MarkDelete(I); } Change = true; Done = true; } + delete [] VList; + // Try some more if (InOr == true) continue; - delete [] VList; if (Done == true) break; } // Apply the kill list now if (Cache[I].InstallVer != 0) + { for (PackageKill *J = KillList; J != LEnd; J++) - { - Change = true; - if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0) { - if (J->Dep->Type == pkgCache::Dep::Conflicts) + Change = true; + if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0) + { + if (J->Dep->Type == pkgCache::Dep::Conflicts) + { + if (Debug == true) + clog << " Fixing " << I.Name() << " via remove of " << J->Pkg.Name() << endl; + Cache.MarkDelete(J->Pkg); + } + } + else { if (Debug == true) - clog << " Fixing " << I.Name() << " via remove of " << J->Pkg.Name() << endl; - Cache.MarkDelete(J->Pkg); + clog << " Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl; + Cache.MarkKeep(J->Pkg); } - } - else - { - if (Debug == true) - clog << " Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl; - Cache.MarkKeep(J->Pkg); - } - - if (Counter > 1) - Scores[J->Pkg->ID] = Scores[I->ID]; - } - } + + if (Counter > 1) + Scores[J->Pkg->ID] = Scores[I->ID]; + } + } + } } if (Debug == true)