X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/a99d02a86c5c25c4a36f06aa44c01709de8219c4..36a171e1e5b3e6a3baa4be6cfb52dbcd47324abb:/apt-pkg/packagemanager.cc diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 7a0f11d85..b9ef0f5d7 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -13,6 +13,8 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ +#include + #include #include #include @@ -22,10 +24,10 @@ #include #include #include - -#include + +#include #include -#include +#include /*}}}*/ using namespace std; @@ -65,7 +67,7 @@ bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources, if (ordering == false) return _error->Error("Internal ordering error"); - for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++) + for (pkgOrderList::iterator I = List->begin(); I != List->end(); ++I) { PkgIterator Pkg(Cache,*I); FileNames[Pkg->ID] = string(); @@ -101,7 +103,7 @@ bool pkgPackageManager::FixMissing() List->SetFileList(FileNames); bool Bad = false; - for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) + for (PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) { if (List->IsMissing(I) == false) continue; @@ -142,7 +144,7 @@ void pkgPackageManager::ImmediateAdd(PkgIterator I, bool UseInstallVer, unsigned D = I.CurrentVer().DependsList(); } - for ( /* nothing */ ; D.end() == false; D++) + for ( /* nothing */ ; D.end() == false; ++D) if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends) { if(!List->IsFlag(D.TargetPkg(), pkgOrderList::Immediate)) @@ -175,7 +177,7 @@ bool pkgPackageManager::CreateOrderList() clog << "CreateOrderList(): Adding Immediate flag for all packages because of APT::Immediate-Configure-All" << endl; // Generate the list of affected packages and sort it - for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) + for (PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) { // Ignore no-version packages if (I->VersionList == 0) @@ -237,7 +239,7 @@ bool pkgPackageManager::DepAlwaysTrue(DepIterator D) bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D, const char *Ver) { - for (;D.end() == false; D++) + for (;D.end() == false; ++D) { if (D->Type != pkgCache::Dep::Conflicts && D->Type != pkgCache::Dep::Obsoletes) @@ -271,7 +273,7 @@ bool pkgPackageManager::ConfigureAll() pkgOrderList OList(&Cache); // Populate the order list - for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++) + for (pkgOrderList::iterator I = List->begin(); I != List->end(); ++I) if (List->IsFlag(pkgCache::PkgIterator(Cache,*I), pkgOrderList::UnPacked) == true) OList.push_back(*I); @@ -283,7 +285,7 @@ bool pkgPackageManager::ConfigureAll() bool const ConfigurePkgs = (conf == "all"); // Perform the configuring - for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++) + for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); ++I) { PkgIterator Pkg(Cache,*I); @@ -291,7 +293,7 @@ bool pkgPackageManager::ConfigureAll() calls its self */ if (List->IsFlag(Pkg,pkgOrderList::Configured)) continue; - if (ConfigurePkgs == true && SmartConfigure(Pkg) == false) { + if (ConfigurePkgs == true && SmartConfigure(Pkg, 0) == false) { if (ImmConfigureAll) _error->Error(_("Could not perform immediate configuration on '%s'. " "Please see man 5 apt.conf under APT::Immediate-Configure for details. (%d)"),Pkg.Name(),1); @@ -318,16 +320,19 @@ bool pkgPackageManager::ConfigureAll() a error will only be reported if ConfigureAll fails. This is why some of the messages this function reports on failure (return false;) as just warnings only shown when debuging*/ -bool pkgPackageManager::SmartConfigure(PkgIterator Pkg) +bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) { + // If this is true, only check and correct and dependancies without the Loop flag + bool PkgLoop = List->IsFlag(Pkg,pkgOrderList::Loop); + if (Debug) { VerIterator InstallVer = VerIterator(Cache,Cache[Pkg].InstallVer); - clog << "SmartConfigure " << Pkg.Name() << InstallVer.VerStr() << endl; + clog << OutputInDepth(Depth) << "SmartConfigure " << Pkg.Name() << " (" << InstallVer.VerStr() << ")"; + if (PkgLoop) + clog << " (Only Correct Dependancies)"; + clog << endl; } - // If this is true, only check and correct and dependancies without the Loop flag - bool PkgLoop = List->IsFlag(Pkg,pkgOrderList::Loop); - VerIterator const instVer = Cache[Pkg].InstVerIter(Cache); /* Because of the ordered list, most dependancies should be unpacked, @@ -368,18 +373,27 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg) // Check if the version that is going to be installed will satisfy the dependancy if (Cache[DepPkg].InstallVer == *I) { if (List->IsFlag(DepPkg,pkgOrderList::UnPacked)) { - if (PkgLoop && List->IsFlag(DepPkg,pkgOrderList::Loop)) { + if (List->IsFlag(DepPkg,pkgOrderList::Loop) && PkgLoop) { // This dependancy has already been dealt with by another SmartConfigure on Pkg Bad = false; break; + } else if (List->IsFlag(Pkg,pkgOrderList::Loop)) { + /* Check for a loop to prevent one forming + If A depends on B and B depends on A, SmartConfigure will + just hop between them if this is not checked. Dont remove the + loop flag after finishing however as loop is already set. + This means that there is another SmartConfigure call for this + package and it will remove the loop flag */ + Bad = !SmartConfigure(DepPkg, Depth + 1); + } else { + /* Check for a loop to prevent one forming + If A depends on B and B depends on A, SmartConfigure will + just hop between them if this is not checked */ + List->Flag(Pkg,pkgOrderList::Loop); + Bad = !SmartConfigure(DepPkg, Depth + 1); + List->RmFlag(Pkg,pkgOrderList::Loop); } - /* Check for a loop to prevent one forming - If A depends on B and B depends on A, SmartConfigure will - just hop between them if this is not checked */ - List->Flag(Pkg,pkgOrderList::Loop); // If SmartConfigure was succesfull, Bad is false, so break - Bad = !SmartConfigure(DepPkg); - List->RmFlag(Pkg,pkgOrderList::Loop); if (!Bad) break; } else if (List->IsFlag(DepPkg,pkgOrderList::Configured)) { Bad = false; @@ -391,11 +405,11 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg) /* If the dependany is still not satisfied, try, if possible, unpacking a package to satisfy it */ if (InstallVer != 0 && Bad) { Bad = false; - if (!List->IsFlag(DepPkg,pkgOrderList::Loop)) { + if (List->IsNow(DepPkg) && !List->IsFlag(DepPkg,pkgOrderList::Loop)) { List->Flag(Pkg,pkgOrderList::Loop); if (Debug) - cout << " Unpacking " << DepPkg.Name() << " to avoid loop" << endl; - SmartUnPack(DepPkg, false); + cout << OutputInDepth(Depth) << "Unpacking " << DepPkg.Name() << " to avoid loop" << endl; + SmartUnPack(DepPkg, true, Depth + 1); List->RmFlag(Pkg,pkgOrderList::Loop); } } @@ -425,14 +439,14 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg) static bool const ConfigurePkgs = (conf == "all" || conf == "smart"); if (List->IsFlag(Pkg,pkgOrderList::Configured)) - return _error->Error("Internal configure error on '%s'. ",Pkg.Name(),1); + return _error->Error("Internal configure error on '%s'.", Pkg.Name()); if (ConfigurePkgs == true && Configure(Pkg) == false) return false; - + List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); - if (Cache[Pkg].InstVerIter(Cache)->MultiArch == pkgCache::Version::Same) + if ((Cache[Pkg].InstVerIter(Cache)->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) for (PkgIterator P = Pkg.Group().PackageList(); P.end() == false; P = Pkg.Group().NextPkg(P)) { @@ -440,7 +454,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg) Cache[P].InstallVer == 0 || (P.CurrentVer() == Cache[P].InstallVer && (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)) continue; - SmartConfigure(P); + SmartConfigure(P, (Depth +1)); } // Sanity Check @@ -476,7 +490,7 @@ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg) if (Pkg->CurrentVer != 0) { for (DepIterator D = Pkg.RevDependsList(); D.end() == false && - IsEssential == false; D++) + IsEssential == false; ++D) if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends) if ((D.ParentPkg()->Flags & pkgCache::Flag::Essential) != 0) IsEssential = true; @@ -519,32 +533,32 @@ bool pkgPackageManager::SmartRemove(PkgIterator Pkg) unpacked, or when it has been unpacked, if Immediate==true it configures it. */ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) { - return SmartUnPack(Pkg, true); + return SmartUnPack(Pkg, true, 0); } -bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate) +bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int const Depth) { + bool PkgLoop = List->IsFlag(Pkg,pkgOrderList::Loop); + if (Debug) { - clog << "SmartUnPack " << Pkg.Name(); + clog << OutputInDepth(Depth) << "SmartUnPack " << Pkg.Name(); VerIterator InstallVer = VerIterator(Cache,Cache[Pkg].InstallVer); if (Pkg.CurrentVer() == 0) - cout << "(install version " << InstallVer.VerStr() << ")" << endl; + cout << " (install version " << InstallVer.VerStr() << ")"; else - cout << "(replace version " << Pkg.CurrentVer().VerStr() << " with " << InstallVer.VerStr() << ")" << endl; + cout << " (replace version " << Pkg.CurrentVer().VerStr() << " with " << InstallVer.VerStr() << ")"; + if (PkgLoop) + cout << " (Only Perform PreUnpack Checks)"; + cout << endl; } // Check if it is already unpacked if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && Cache[Pkg].Keep() == true) { - List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States); - if (Immediate == true && - List->IsFlag(Pkg,pkgOrderList::Immediate) == true) - if (SmartConfigure(Pkg) == false) - _error->Warning(_("Could not perform immediate configuration on already unpacked '%s'. " - "Please see man 5 apt.conf under APT::Immediate-Configure for details."),Pkg.Name()); - return true; + cout << OutputInDepth(Depth) << "SmartUnPack called on Package " << Pkg.Name() << " but its unpacked" << endl; + return false; } - + VerIterator const instVer = Cache[Pkg].InstVerIter(Cache); /* PreUnpack Checks: This loop checks and attempts to rectify and problems that would prevent the package being unpacked. @@ -564,7 +578,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate) while (End->Type == pkgCache::Dep::PreDepends) { if (Debug) - clog << "PreDepends order for " << Pkg.Name() << std::endl; + clog << OutputInDepth(Depth) << "PreDepends order for " << Pkg.Name() << std::endl; // Look for possible ok targets. SPtrArray VList = Start.AllTargets(); @@ -580,7 +594,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate) { Bad = false; if (Debug) - clog << "Found ok package " << Pkg.Name() << endl; + clog << OutputInDepth(Depth) << "Found ok package " << Pkg.Name() << endl; continue; } } @@ -602,8 +616,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate) } if (Debug) - clog << "Trying to SmartConfigure " << Pkg.Name() << endl; - Bad = !SmartConfigure(Pkg); + clog << OutputInDepth(Depth) << "Trying to SmartConfigure " << Pkg.Name() << endl; + Bad = !SmartConfigure(Pkg, Depth + 1); } /* If this or element did not match then continue on to the @@ -615,7 +629,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate) return _error->Error("Couldn't configure pre-depend %s for %s, " "probably a dependency cycle.", End.TargetPkg().Name(),Pkg.Name()); - Start++; + ++Start; } else break; @@ -636,15 +650,15 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate) // See if the current version is conflicting if (ConflictPkg.CurrentVer() == Ver && List->IsNow(ConflictPkg)) { - cout << Pkg.Name() << " conflicts with " << ConflictPkg.Name() << endl; + cout << OutputInDepth(Depth) << Pkg.Name() << " conflicts with " << ConflictPkg.Name() << endl; /* If a loop is not present or has not yet been detected, attempt to unpack packages to resolve this conflict. If there is a loop present, remove packages to resolve this conflict */ if (!List->IsFlag(ConflictPkg,pkgOrderList::Loop)) { if (Cache[ConflictPkg].Keep() == 0 && Cache[ConflictPkg].InstallVer != 0) { if (Debug) - cout << "Unpacking " << ConflictPkg.Name() << " to prevent conflict" << endl; + cout << OutputInDepth(Depth) << OutputInDepth(Depth) << "Unpacking " << ConflictPkg.Name() << " to prevent conflict" << endl; List->Flag(Pkg,pkgOrderList::Loop); - SmartUnPack(ConflictPkg,false); + SmartUnPack(ConflictPkg,false, Depth + 1); // Remove loop to allow it to be used later if needed List->RmFlag(Pkg,pkgOrderList::Loop); } else { @@ -654,7 +668,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate) } else { if (!List->IsFlag(ConflictPkg,pkgOrderList::Removed)) { if (Debug) - cout << "Because of conficts knot, removing " << ConflictPkg.Name() << " to conflict violation" << endl; + cout << OutputInDepth(Depth) << "Because of conficts knot, removing " << ConflictPkg.Name() << " to conflict violation" << endl; if (EarlyRemove(ConflictPkg) == false) return _error->Error("Internal Error, Could not early remove %s",ConflictPkg.Name()); } @@ -674,19 +688,33 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate) // Check if it needs to be unpacked if (List->IsFlag(BrokenPkg,pkgOrderList::InList) && Cache[BrokenPkg].Delete() == false && - !List->IsFlag(BrokenPkg,pkgOrderList::Loop) && List->IsNow(BrokenPkg)) { - List->Flag(Pkg,pkgOrderList::Loop); - // Found a break, so unpack the package - if (Debug) - cout << " Unpacking " << BrokenPkg.Name() << " to avoid break" << endl; + List->IsNow(BrokenPkg)) { + if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) && PkgLoop) { + // This dependancy has already been dealt with by another SmartUnPack on Pkg + break; + } else if (List->IsFlag(Pkg,pkgOrderList::Loop)) { + /* Found a break, so unpack the package, but dont remove loop as already set. + This means that there is another SmartUnPack call for this + package and it will remove the loop flag. */ + if (Debug) + cout << OutputInDepth(Depth) << " Unpacking " << BrokenPkg.Name() << " to avoid break" << endl; + + SmartUnPack(BrokenPkg, false, Depth + 1); + } else { + List->Flag(Pkg,pkgOrderList::Loop); + // Found a break, so unpack the package + if (Debug) + cout << OutputInDepth(Depth) << " Unpacking " << BrokenPkg.Name() << " to avoid break" << endl; - SmartUnPack(BrokenPkg, false); - List->RmFlag(Pkg,pkgOrderList::Loop); + SmartUnPack(BrokenPkg, false, Depth + 1); + List->RmFlag(Pkg,pkgOrderList::Loop); + } } + // Check if a package needs to be removed if (Cache[BrokenPkg].Delete() == true && !List->IsFlag(BrokenPkg,pkgOrderList::Configured)) { if (Debug) - cout << " Removing " << BrokenPkg.Name() << " to avoid break" << endl; + cout << OutputInDepth(Depth) << " Removing " << BrokenPkg.Name() << " to avoid break" << endl; SmartRemove(BrokenPkg); } } @@ -699,29 +727,53 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate) return false; for (PrvIterator P = instVer.ProvidesList(); - P.end() == false; P++) - CheckRConflicts(Pkg,P.ParentPkg().RevDependsList(),P.ProvideVersion()); + P.end() == false; ++P) + if (Pkg->Group != P.OwnerPkg()->Group) + CheckRConflicts(Pkg,P.ParentPkg().RevDependsList(),P.ProvideVersion()); + + if (PkgLoop) + return true; List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States); - if (instVer->MultiArch == pkgCache::Version::Same) + if (Immediate == true && instVer->MultiArch == pkgCache::Version::Same) + { + /* Do lockstep M-A:same unpacking in two phases: + First unpack all installed architectures, then the not installed. + This way we avoid that M-A: enabled packages are installed before + their older non-M-A enabled packages are replaced by newer versions */ + bool const installed = Pkg->CurrentVer != 0; + if (installed == true && Install(Pkg,FileNames[Pkg->ID]) == false) + return false; for (PkgIterator P = Pkg.Group().PackageList(); - P.end() == false; P = Pkg.Group().NextPkg(P)) + P.end() == false; P = Pkg.Group().NextPkg(P)) { - if (Pkg == P || List->IsFlag(P,pkgOrderList::UnPacked) == true || - Cache[P].InstallVer == 0 || (P.CurrentVer() == Cache[P].InstallVer && - (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)) - continue; - SmartUnPack(P, false); + if (P->CurrentVer == 0 || P == Pkg || List->IsFlag(P,pkgOrderList::UnPacked) == true || + Cache[P].InstallVer == 0 || (P.CurrentVer() == Cache[P].InstallVer && + (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)) + continue; + if (SmartUnPack(P, false, Depth + 1) == false) + return false; } - - if(Install(Pkg,FileNames[Pkg->ID]) == false) + if (installed == false && Install(Pkg,FileNames[Pkg->ID]) == false) + return false; + for (PkgIterator P = Pkg.Group().PackageList(); + P.end() == false; P = Pkg.Group().NextPkg(P)) + { + if (P->CurrentVer != 0 || P == Pkg || List->IsFlag(P,pkgOrderList::UnPacked) == true || + Cache[P].InstallVer == 0 || (P.CurrentVer() == Cache[P].InstallVer && + (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)) + continue; + if (SmartUnPack(P, false, Depth + 1) == false) + return false; + } + } + else if (Install(Pkg,FileNames[Pkg->ID]) == false) return false; - if (Immediate == true && List->IsFlag(Pkg,pkgOrderList::Immediate) == true) { - + if (Immediate == true) { // Perform immedate configuration of the package. - if (SmartConfigure(Pkg) == false) + if (SmartConfigure(Pkg, Depth + 1) == false) _error->Warning(_("Could not perform immediate configuration on '%s'. " "Please see man 5 apt.conf under APT::Immediate-Configure for details. (%d)"),Pkg.Name(),2); } @@ -755,14 +807,14 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() clog << "Done ordering" << endl; bool DoneSomething = false; - for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++) + for (pkgOrderList::iterator I = List->begin(); I != List->end(); ++I) { PkgIterator Pkg(Cache,*I); if (List->IsNow(Pkg) == false) { if (!List->IsFlag(Pkg,pkgOrderList::Configured) && !NoImmConfigure) { - if (SmartConfigure(Pkg) == false && Debug) + if (SmartConfigure(Pkg, 0) == false && Debug) _error->Warning("Internal Error, Could not configure %s",Pkg.Name()); // FIXME: The above warning message might need changing } else { @@ -801,7 +853,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() return Failed; } else - if (SmartUnPack(Pkg) == false) + if (SmartUnPack(Pkg,List->IsFlag(Pkg,pkgOrderList::Immediate),0) == false) return Failed; DoneSomething = true; @@ -818,7 +870,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() return Failed; // Sanity check - for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++) + for (pkgOrderList::iterator I = List->begin(); I != List->end(); ++I) { if (List->IsFlag(*I,pkgOrderList::Configured) == false) {