X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/2ee50e0af732ddd94222ca7cbb120341651b02f0..55c04aa4c9f9704137822fac3a8392280667dfb6:/apt-pkg/packagemanager.cc diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 304d1c653..ac11b5d51 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -26,7 +26,7 @@ #include #include #include - + /*}}}*/ using namespace std; // PM::PackageManager - Constructor /*{{{*/ @@ -57,7 +57,10 @@ bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources, if (CreateOrderList() == false) return false; - if (List->OrderUnpack() == false) + bool const ordering = + _config->FindB("PackageManager::UnpackAll",true) ? + List->OrderUnpack() : List->OrderCritical(); + if (ordering == false) return _error->Error("Internal ordering error"); for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++) @@ -77,7 +80,7 @@ bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources, // Skip already processed packages if (List->IsNow(Pkg) == false) continue; - + new pkgAcqArchive(Owner,Sources,Recs,Cache[Pkg].InstVerIter(Cache), FileNames[Pkg->ID]); } @@ -117,13 +120,12 @@ bool pkgPackageManager::FixMissing() return Resolve.ResolveByKeep() == true && Cache.BrokenCount() == 0; } /*}}}*/ - // PM::ImmediateAdd - Add the immediate flag recursivly /*{{{*/ // --------------------------------------------------------------------- /* This adds the immediate flag to the pkg and recursively to the dependendies */ -void pkgPackageManager::ImmediateAdd(PkgIterator I, bool UseInstallVer) +void pkgPackageManager::ImmediateAdd(PkgIterator I, bool UseInstallVer, unsigned const int &Depth) { DepIterator D; @@ -144,15 +146,14 @@ void pkgPackageManager::ImmediateAdd(PkgIterator I, bool UseInstallVer) if(!List->IsFlag(D.TargetPkg(), pkgOrderList::Immediate)) { if(Debug) - clog << "ImmediateAdd(): Adding Immediate flag to " << I.Name() << endl; + clog << OutputInDepth(Depth) << "ImmediateAdd(): Adding Immediate flag to " << D.TargetPkg() << " cause of " << D.DepType() << " " << I.Name() << endl; List->Flag(D.TargetPkg(),pkgOrderList::Immediate); - ImmediateAdd(D.TargetPkg(), UseInstallVer); + ImmediateAdd(D.TargetPkg(), UseInstallVer, Depth + 1); } } return; } /*}}}*/ - // PM::CreateOrderList - Create the ordering class /*{{{*/ // --------------------------------------------------------------------- /* This populates the ordering list with all the packages that are @@ -165,7 +166,7 @@ bool pkgPackageManager::CreateOrderList() delete List; List = new pkgOrderList(&Cache); - bool NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true); + static bool const 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++) @@ -268,13 +269,16 @@ bool pkgPackageManager::ConfigureAll() if (OList.OrderConfigure() == false) return false; - + + std::string const conf = _config->Find("PackageManager::Configure","all"); + bool const ConfigurePkgs = (conf == "all"); + // Perform the configuring for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++) { PkgIterator Pkg(Cache,*I); - - if (Configure(Pkg) == false) + + if (ConfigurePkgs == true && VerifyAndConfigure(Pkg,OList) == false) return false; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); @@ -289,30 +293,134 @@ bool pkgPackageManager::ConfigureAll() of it's dependents. */ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg) { + if (Debug == true) + clog << "SmartConfigure " << Pkg.Name() << endl; + pkgOrderList OList(&Cache); if (DepAdd(OList,Pkg) == false) return false; - - if (OList.OrderConfigure() == false) - return false; - + + static std::string const conf = _config->Find("PackageManager::Configure","all"); + static bool const ConfigurePkgs = (conf == "all" || conf == "smart"); + + if (ConfigurePkgs == true) + if (OList.OrderConfigure() == false) + return false; + // Perform the configuring for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++) { PkgIterator Pkg(Cache,*I); - if (Configure(Pkg) == false) + if (ConfigurePkgs == true && VerifyAndConfigure(Pkg,OList) == false) return false; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); } + if (Cache[Pkg].InstVerIter(Cache)->MultiArch == pkgCache::Version::Same) + for (PkgIterator P = Pkg.Group().PackageList(); + P.end() == false; P = Pkg.Group().NextPkg(P)) + { + if (Pkg == P || List->IsFlag(P,pkgOrderList::Configured) == true || + Cache[P].InstallVer == 0 || (P.CurrentVer() == Cache[P].InstallVer && + (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)) + continue; + SmartConfigure(P); + } + // Sanity Check if (List->IsFlag(Pkg,pkgOrderList::Configured) == false) - return _error->Error("Internal error, could not immediate configure %s",Pkg.Name()); - + return _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); + return true; +} + +// PM::VerifyConfigure - Check configuration of dependancies /*{{{*/ +// --------------------------------------------------------------------- +/* This routine checks that all a packages dependancies have been + configured, before it is going to be configured. If this gives a warning + on a virtual package, it means that the package thats providing it is not + configured*/ +bool pkgPackageManager::VerifyConfigure(PkgIterator Pkg, pkgOrderList &OList) +{ + // If this is true at the end, then the package should not be configured + bool error=true; + // This holds the the OR status of the previous dependancy + bool previousOr=false; + + // First iterate through the dependancies of Pkg + for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false; D++) + { + + /* If the dependancy is of type Depends or PreDepends, we need to check it, but only if it is going to be + configured at some point */ + if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends) { + + /* If the previous package and this package are OR dependancies, and the previous package satisfied the dependancy + then skip this dependancy as it is not relevent, this will repeat for the next package if the situation is the + same */ + if (previousOr && !error) { // As error has not been reset, this refers to the previous dependancy + previousOr = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; + continue; + } + + // Reset error + error = true; + + // Check thorugh all possible versions of this dependancy (D) + SPtrArray VList = D.AllTargets(); + for (Version **I = VList; *I != 0; I++) + { + VerIterator DepVer(Cache,*I); + PkgIterator DepPkg = DepVer.ParentPkg(); + VerIterator DepInstallVer(Cache,Cache[DepPkg].InstallVer); + + if (DepPkg.CurrentVer() == DepVer && !List->IsFlag(DepPkg,pkgOrderList::UnPacked)) { + error=false; + break; + } + + if (Cache[DepPkg].InstallVer == DepVer && + (List->IsFlag(DepPkg,pkgOrderList::Configured) || OList.IsFlag(DepPkg,pkgOrderList::InList))) { + error=false; + break; + } + } + + /* Only worry here if this package is a OR with the next, as even though this package does not satisfy the OR + the next one might */ + if (error && !((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)) { + _error->Error("Package %s should not be configured because package %s is not configured",Pkg.Name(),D.TargetPkg().Name()); + return false; + /* If the previous package is a OR but not this package, but there is still an error then fail as it will not + be satisfied */ + } else if (error && previousOr && !((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)) { + _error->Error("Package %s should not be configured because package %s (or any alternatives) are not configured",Pkg.Name(),D.TargetPkg().Name()); + return false; + } + + previousOr = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; + } else { + previousOr=false; + } + } + return true; +} + +// PM::VerifyAndConfigure - Check configuration of dependancies /*{{{*/ +// --------------------------------------------------------------------- +/* This routine verifies if a package can be configured and if so + configures it */ +bool pkgPackageManager::VerifyAndConfigure(PkgIterator Pkg, pkgOrderList &OList) +{ + if (VerifyConfigure(Pkg, OList)) + return Configure(Pkg); + else + return false; + } /*}}}*/ // PM::DepAdd - Add all dependents to the oder list /*{{{*/ @@ -326,6 +434,9 @@ bool pkgPackageManager::DepAdd(pkgOrderList &OList,PkgIterator Pkg,int Depth) return true; if (List->IsFlag(Pkg,pkgOrderList::UnPacked) == false) return false; + + if (Debug) + std::clog << OutputInDepth(Depth) << "DepAdd: " << Pkg.Name() << std::endl; // Put the package on the list OList.push_back(Pkg); @@ -379,6 +490,8 @@ bool pkgPackageManager::DepAdd(pkgOrderList &OList,PkgIterator Pkg,int Depth) if (Bad == true) { + if (Debug) + std::clog << OutputInDepth(Depth) << "DepAdd FAILS on: " << Pkg.Name() << std::endl; OList.Flag(Pkg,0,pkgOrderList::Added); OList.pop_back(); Depth--; @@ -448,7 +561,9 @@ bool pkgPackageManager::SmartRemove(PkgIterator Pkg) return true; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); + return Remove(Pkg,(Cache[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge); + return true; } /*}}}*/ // PM::SmartUnPack - Install helper /*{{{*/ @@ -456,20 +571,31 @@ bool pkgPackageManager::SmartRemove(PkgIterator Pkg) /* This performs the task of handling pre-depends. */ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) { + return SmartUnPack(Pkg, true); +} +bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate) +{ + if (Debug == true) + clog << "SmartUnPack " << Pkg.Name() << 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 (List->IsFlag(Pkg,pkgOrderList::Immediate) == true) + if (Immediate == true && + List->IsFlag(Pkg,pkgOrderList::Immediate) == true) if (SmartConfigure(Pkg) == false) - return _error->Error("Internal Error, Could not perform immediate configuration (1) on %s",Pkg.Name()); + return _error->Error(_("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; } + VerIterator const instVer = Cache[Pkg].InstVerIter(Cache); + /* See if this packages install version has any predependencies that are not met by 'now' packages. */ - for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); + for (DepIterator D = instVer.DependsList(); D.end() == false; ) { // Compute a single dependency element (glob or) @@ -479,6 +605,9 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) while (End->Type == pkgCache::Dep::PreDepends) { + if (Debug == true) + clog << "PreDepends order for " << Pkg.Name() << std::endl; + // Look for possible ok targets. SPtrArray VList = Start.AllTargets(); bool Bad = true; @@ -492,6 +621,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) Pkg.State() == PkgIterator::NeedsNothing) { Bad = false; + if (Debug == true) + clog << "Found ok package " << Pkg.Name() << endl; continue; } } @@ -507,6 +638,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) (Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing)) continue; + if (Debug == true) + clog << "Trying to SmartConfigure " << Pkg.Name() << endl; Bad = !SmartConfigure(Pkg); } @@ -544,26 +677,54 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) } } } + + // Check for breaks + if (End->Type == pkgCache::Dep::DpkgBreaks) { + SPtrArray VList = End.AllTargets(); + for (Version **I = VList; *I != 0; I++) + { + VerIterator Ver(Cache,*I); + PkgIterator Pkg = Ver.ParentPkg(); + // Check if it needs to be unpacked + if (List->IsFlag(Pkg,pkgOrderList::InList) && Cache[Pkg].Delete() == false) { + // Found a break, so unpack the package + SmartUnPack(Pkg, false); + } + } + } } // Check for reverse conflicts. if (CheckRConflicts(Pkg,Pkg.RevDependsList(), - Cache[Pkg].InstVerIter(Cache).VerStr()) == false) + instVer.VerStr()) == false) return false; - for (PrvIterator P = Cache[Pkg].InstVerIter(Cache).ProvidesList(); + for (PrvIterator P = instVer.ProvidesList(); P.end() == false; P++) CheckRConflicts(Pkg,P.ParentPkg().RevDependsList(),P.ProvideVersion()); - - if (Install(Pkg,FileNames[Pkg->ID]) == false) - return false; - + List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States); - + + if (instVer->MultiArch == pkgCache::Version::Same) + for (PkgIterator P = Pkg.Group().PackageList(); + 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(Install(Pkg,FileNames[Pkg->ID]) == false) + return false; + // Perform immedate configuration of the package. - if (List->IsFlag(Pkg,pkgOrderList::Immediate) == true) + if (Immediate == true && + List->IsFlag(Pkg,pkgOrderList::Immediate) == true) if (SmartConfigure(Pkg) == false) - return _error->Error("Internal Error, Could not perform immediate configuration (2) on %s",Pkg.Name()); + return _error->Error(_("Could not perform immediate configuration on '%s'. " + "Please see man 5 apt.conf under APT::Immediate-Configure for details. (%d)"),Pkg.Name(),2); return true; } @@ -579,9 +740,12 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() Reset(); if (Debug == true) - clog << "Begining to order" << endl; + clog << "Beginning to order" << endl; - if (List->OrderUnpack(FileNames) == false) + bool const ordering = + _config->FindB("PackageManager::UnpackAll",true) ? + List->OrderUnpack(FileNames) : List->OrderCritical(); + if (ordering == false) { _error->Error("Internal ordering error"); return Failed; @@ -634,7 +798,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() return Failed; DoneSomething = true; } - + // Final run through the configure phase if (ConfigureAll() == false) return Failed;