X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/2fd65468b3cb25c725a709f9b470ced0ab4823a6..22dcc318d978813b3c4d1ae1a1f41933d0e1d69b:/apt-pkg/packagemanager.cc diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 9e2eee969..71a0dd034 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: packagemanager.cc,v 1.16 1999/07/04 23:22:53 jgg Exp $ +// $Id: packagemanager.cc,v 1.30 2003/04/27 03:04:15 doogie Exp $ /* ###################################################################### Package Manager - Abstacts the package manager @@ -16,6 +16,7 @@ #ifdef __GNUG__ #pragma implementation "apt-pkg/packagemanager.h" #endif + #include #include #include @@ -24,12 +25,18 @@ #include #include #include +#include + +#include +#include /*}}}*/ +using namespace std; + // PM::PackageManager - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgPackageManager::pkgPackageManager(pkgDepCache &Cache) : Cache(Cache) +pkgPackageManager::pkgPackageManager(pkgDepCache *pCache) : Cache(*pCache) { FileNames = new string[Cache.Head().PackageCount]; List = 0; @@ -87,8 +94,8 @@ bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources, /* This is called to correct the installation when packages could not be downloaded. */ bool pkgPackageManager::FixMissing() -{ - pkgProblemResolver Resolve(Cache); +{ + pkgProblemResolver Resolve(&Cache); List->SetFileList(FileNames); bool Bad = false; @@ -101,6 +108,10 @@ bool pkgPackageManager::FixMissing() Bad = true; Cache.MarkKeep(I); } + + // We have to empty the list otherwise it will not have the new changes + delete List; + List = 0; if (Bad == false) return true; @@ -120,13 +131,17 @@ bool pkgPackageManager::CreateOrderList() return true; delete List; - List = new pkgOrderList(Cache); + List = new pkgOrderList(&Cache); - bool NoImmConfigure = _config->FindB("APT::Immediate-Configure",false); + bool NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true); // Generate the list of affected packages and sort it for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) { + // Ignore no-version packages + if (I->VersionList == 0) + continue; + // Mark the package and its dependends for immediate configuration if (((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential || (I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) && @@ -152,7 +167,10 @@ bool pkgPackageManager::CreateOrderList() // Not interesting if ((Cache[I].Keep() == true || Cache[I].InstVerIter(Cache) == I.CurrentVer()) && - I.State() == pkgCache::PkgIterator::NeedsNothing) + I.State() == pkgCache::PkgIterator::NeedsNothing && + (Cache[I].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall && + (I.Purge() != false || Cache[I].Mode != pkgDepCache::ModeDelete || + (Cache[I].iFlags & pkgDepCache::Purge) != pkgDepCache::Purge)) continue; // Append it to the list @@ -186,21 +204,25 @@ bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D, { for (;D.end() == false; D++) { - if (D->Type != pkgCache::Dep::Conflicts) + if (D->Type != pkgCache::Dep::Conflicts && + D->Type != pkgCache::Dep::Obsoletes) + continue; + + // The package hasnt been changed + if (List->IsNow(Pkg) == false) continue; - if (D.ParentPkg() == Pkg) + // Ignore self conflicts, ignore conflicts from irrelevent versions + if (D.ParentPkg() == Pkg || D.ParentVer() != D.ParentPkg().CurrentVer()) continue; - if (pkgCheckDep(D.TargetVer(),Ver,D->CompareOp) == false) + if (Cache.VS().CheckDep(Ver,D->CompareOp,D.TargetVer()) == false) continue; - if (List->IsNow(Pkg) == false) - continue; - if (EarlyRemove(D.ParentPkg()) == false) - return false; - } + return _error->Error("Reverse conflicts early remove for package '%s' failed", + Pkg.Name()); + } return true; } /*}}}*/ @@ -210,7 +232,7 @@ bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D, that the final configuration is valid. */ bool pkgPackageManager::ConfigureAll() { - pkgOrderList OList(Cache); + pkgOrderList OList(&Cache); // Populate the order list for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++) @@ -241,14 +263,14 @@ bool pkgPackageManager::ConfigureAll() of it's dependents. */ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg) { - pkgOrderList OList(Cache); + pkgOrderList OList(&Cache); if (DepAdd(OList,Pkg) == false) return false; if (OList.OrderConfigure() == false) return false; - + // Perform the configuring for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++) { @@ -278,8 +300,7 @@ bool pkgPackageManager::DepAdd(pkgOrderList &OList,PkgIterator Pkg,int Depth) return true; if (List->IsFlag(Pkg,pkgOrderList::UnPacked) == false) return false; - - + // Put the package on the list OList.push_back(Pkg); OList.Flag(Pkg,pkgOrderList::Added); @@ -304,7 +325,7 @@ bool pkgPackageManager::DepAdd(pkgOrderList &OList,PkgIterator Pkg,int Depth) if (Bad == false) continue; - Version **VList = D.AllTargets(); + SPtrArray VList = D.AllTargets(); for (Version **I = VList; *I != 0 && Bad == true; I++) { VerIterator Ver(Cache,*I); @@ -322,12 +343,12 @@ bool pkgPackageManager::DepAdd(pkgOrderList &OList,PkgIterator Pkg,int Depth) if (Cache[Pkg].InstallVer != *I || (Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing)) continue; + if (List->IsFlag(Pkg,pkgOrderList::UnPacked) == true) Bad = !DepAdd(OList,Pkg,Depth); if (List->IsFlag(Pkg,pkgOrderList::Configured) == true) Bad = false; } - delete [] VList; } if (Bad == true) @@ -358,6 +379,32 @@ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg) // Woops, it will not be re-installed! if (List->IsFlag(Pkg,pkgOrderList::InList) == false) return false; + + // Essential packages get special treatment + bool IsEssential = false; + if ((Pkg->Flags & pkgCache::Flag::Essential) != 0) + IsEssential = true; + + /* Check for packages that are the dependents of essential packages and + promote them too */ + if (Pkg->CurrentVer != 0) + { + for (DepIterator D = Pkg.RevDependsList(); D.end() == false && + IsEssential == false; D++) + if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends) + if ((D.ParentPkg()->Flags & pkgCache::Flag::Essential) != 0) + IsEssential = true; + } + + if (IsEssential == true) + { + if (_config->FindB("APT::Force-LoopBreak",false) == false) + return _error->Error(_("This installation run will require temporarily " + "removing the essential package %s due to a " + "Conflicts/Pre-Depends loop. This is often bad, " + "but if you really want to do it, activate the " + "APT::Force-LoopBreak option."),Pkg.Name()); + } bool Res = SmartRemove(Pkg); if (Cache[Pkg].Delete() == false) @@ -375,7 +422,7 @@ bool pkgPackageManager::SmartRemove(PkgIterator Pkg) return true; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); - return Remove(Pkg); + return Remove(Pkg,(Cache[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge); } /*}}}*/ // PM::SmartUnPack - Install helper /*{{{*/ @@ -390,19 +437,24 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States); if (List->IsFlag(Pkg,pkgOrderList::Immediate) == true) if (SmartConfigure(Pkg) == false) - return _error->Error("Internal Error, Could not perform immediate configuraton"); + return _error->Error("Internal Error, Could not perform immediate configuration (1) on %s",Pkg.Name()); return true; } /* See if this packages install version has any predependencies that are not met by 'now' packages. */ for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); - D.end() == false; D++) + D.end() == false; ) { - if (D->Type == pkgCache::Dep::PreDepends) + // Compute a single dependency element (glob or) + pkgCache::DepIterator Start; + pkgCache::DepIterator End; + D.GlobOr(Start,End); + + while (End->Type == pkgCache::Dep::PreDepends) { // Look for possible ok targets. - Version **VList = D.AllTargets(); + SPtrArray VList = Start.AllTargets(); bool Bad = true; for (Version **I = VList; *I != 0 && Bad == true; I++) { @@ -431,20 +483,28 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) Bad = !SmartConfigure(Pkg); } - - delete [] VList; - - if (Bad == true) - return _error->Error("Internal Error, Couldn't configure a pre-depend"); - continue; + /* If this or element did not match then continue on to the + next or element until a matching element is found */ + if (Bad == true) + { + // This triggers if someone make a pre-depends/depend loop. + if (Start == End) + return _error->Error("Couldn't configure pre-depend %s for %s, " + "probably a dependency cycle.", + End.TargetPkg().Name(),Pkg.Name()); + Start++; + } + else + break; } - if (D->Type == pkgCache::Dep::Conflicts) + if (End->Type == pkgCache::Dep::Conflicts || + End->Type == pkgCache::Dep::Obsoletes) { /* Look for conflicts. Two packages that are both in the install state cannot conflict so we don't check.. */ - Version **VList = D.AllTargets(); + SPtrArray VList = End.AllTargets(); for (Version **I = VList; *I != 0; I++) { VerIterator Ver(Cache,*I); @@ -457,13 +517,14 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) return _error->Error("Internal Error, Could not early remove %s",Pkg.Name()); } } - delete [] VList; } } // Check for reverse conflicts. - CheckRConflicts(Pkg,Pkg.RevDependsList(), - Cache[Pkg].InstVerIter(Cache).VerStr()); + if (CheckRConflicts(Pkg,Pkg.RevDependsList(), + Cache[Pkg].InstVerIter(Cache).VerStr()) == false) + return false; + for (PrvIterator P = Cache[Pkg].InstVerIter(Cache).ProvidesList(); P.end() == false; P++) CheckRConflicts(Pkg,P.ParentPkg().RevDependsList(),P.ProvideVersion()); @@ -476,7 +537,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) // Perform immedate configuration of the package. if (List->IsFlag(Pkg,pkgOrderList::Immediate) == true) if (SmartConfigure(Pkg) == false) - return _error->Error("Internal Error, Could not perform immediate configuraton"); + return _error->Error("Internal Error, Could not perform immediate configuration (2) on %s",Pkg.Name()); return true; } @@ -518,7 +579,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() if (List->IsMissing(Pkg) == true) { if (Debug == true) - clog << "Sequence completed at" << Pkg.Name() << endl; + clog << "Sequence completed at " << Pkg.Name() << endl; if (DoneSomething == false) { _error->Error("Internal Error, ordering was unable to handle the media swap"); @@ -528,7 +589,9 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() } // Sanity check - if (Cache[Pkg].Keep() == true && Pkg.State() == pkgCache::PkgIterator::NeedsNothing) + if (Cache[Pkg].Keep() == true && + Pkg.State() == pkgCache::PkgIterator::NeedsNothing && + (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall) { _error->Error("Internal Error, trying to manipulate a kept package"); return Failed; @@ -564,16 +627,3 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() return Completed; } /*}}}*/ -// PM::DoInstall - Does the installation /*{{{*/ -// --------------------------------------------------------------------- -/* This uses the filenames in FileNames and the information in the - DepCache to perform the installation of packages.*/ -pkgPackageManager::OrderResult pkgPackageManager::DoInstall() -{ - OrderResult Res = OrderInstall(); - if (Res != Failed) - if (Go() == false) - return Failed; - return Res; -} - /*}}}*/