X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/6c139d6e362f04a1582e8a8f511f8aeab031fecf..b57c0e355d7f27a74c860ed73700cf9241cb4e61:/apt-pkg/packagemanager.cc?ds=inline diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index ebf67b5ee..4c655cb7b 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.1 1998/07/07 04:17:01 jgg Exp $ +// $Id: packagemanager.cc,v 1.30 2003/04/27 03:04:15 doogie Exp $ /* ###################################################################### Package Manager - Abstacts the package manager @@ -13,26 +13,30 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#ifdef __GNUG__ -#pragma implementation "pkglib/packagemanager.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#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; + Debug = _config->FindB("Debug::pkgPackageManager",false); } /*}}}*/ // PM::PackageManager - Destructor /*{{{*/ @@ -44,70 +48,41 @@ pkgPackageManager::~pkgPackageManager() delete [] FileNames; } /*}}}*/ -// PM::GetArchives - Puts the install archives in the aquire list /*{{{*/ +// PM::GetArchives - Queue the archives for download /*{{{*/ // --------------------------------------------------------------------- -/* The Source list is used to convert the packages to install into - URNs which are then passed to Aquire to convert to FileNames. */ -bool pkgPackageManager::GetArchives(pkgSourceList &List,pkgAquire &Engine) +/* */ +bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources, + pkgRecords *Recs) { - pkgControlCache CCache(Cache); - if (_error->PendingError() == true) + if (CreateOrderList() == false) return false; + + bool const ordering = + _config->FindB("PackageManager::UnpackAll",true) ? + List->OrderUnpack() : List->OrderCritical(); + if (ordering == false) + return _error->Error("Internal ordering error"); - Engine.OutputDir(PKG_DEB_CA_ARCHIVES); - pkgCache::PkgIterator I = Cache.PkgBegin(); - for (;I.end() != true; I++) + for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++) { - // Not interesting - if ((Cache[I].InstallVer == (pkgCache::Version *)I.CurrentVer() && - I.State() != pkgCache::PkgIterator::NeedsUnpack) || - Cache[I].Delete() == true) - continue; + PkgIterator Pkg(Cache,*I); + FileNames[Pkg->ID] = string(); - // Cross match with the source list. - pkgSourceList::const_iterator Dist = List.MatchPkgFile(Cache[I].InstVerIter(Cache)); - if (Dist == List.end()) - { - _error->Warning("Couldn't locate an archive source for package %s",I.Name()); + // Skip packages to erase + if (Cache[Pkg].Delete() == true) continue; - } - // Read in the info record - pkgSPkgCtrlInfo Inf = CCache[Cache[I].InstVerIter(Cache)]; - if (Inf.isNull() == true) - { - _error->Warning("Couldn't locate info for package %s",I.Name()); + // Skip Packages that need configure only. + if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && + Cache[Pkg].Keep() == true) continue; - } - // Isolate the filename - string File = Inf->Find("Filename")->Value(); - if (File.empty() == true) - { - _error->Warning("Couldn't locate an archive for package %s",I.Name()); + // Skip already processed packages + if (List->IsNow(Pkg) == false) continue; - } - // Generate the get request. - string URI = Dist->ArchiveURI(File); - - // Output file - unsigned int Pos = File.rfind('/'); - if (Pos == File.length()) - return _error->Error("Malformed file line in package %s",I.Name()); - - // Null pos isnt used in present package files - if (Pos == string::npos) - Pos = 0; - else - Pos++; - - if (Engine.Get(URI,string(File,Pos), - Dist->ArchiveInfo(Cache[I].InstVerIter(Cache)), - Cache[I].InstVerIter(Cache)->Size, - Inf->Find("MD5sum")->Value(), - &FileNames[I->ID]) == false) - return false; + new pkgAcqArchive(Owner,Sources,Recs,Cache[Pkg].InstVerIter(Cache), + FileNames[Pkg->ID]); } return true; @@ -118,31 +93,120 @@ bool pkgPackageManager::GetArchives(pkgSourceList &List,pkgAquire &Engine) /* This is called to correct the installation when packages could not be downloaded. */ bool pkgPackageManager::FixMissing() -{ - unsigned char *Touch = new unsigned char[Cache.Head().PackageCount]; +{ + pkgDepCache::ActionGroup group(Cache); + pkgProblemResolver Resolve(&Cache); + List->SetFileList(FileNames); + + bool Bad = false; for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) { - // Create the status list that ResolveConflicts needs - if ((Cache[I].DepState & pkgDepCache::DepNowMin) == pkgDepCache::DepNowMin) - Touch[I->ID] = (1 << 0) | (1 << 1); - else - Touch[I->ID] = 1 << 1; - - if (Cache[I].Keep() == true) - continue; - if (FileNames[I->ID].empty() == false || Cache[I].Delete() == true) + if (List->IsMissing(I) == false) continue; - Cache.MarkKeep(I); + + // Okay, this file is missing and we need it. Mark it for keep + Bad = true; + Cache.MarkKeep(I, false, false); } + + // We have to empty the list otherwise it will not have the new changes + delete List; + List = 0; + + if (Bad == false) + return true; // Now downgrade everything that is broken - Cache.ResolveConflicts(Touch); - delete [] Touch; + 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, unsigned const int &Depth) +{ + DepIterator D; + + if(UseInstallVer) + { + if(Cache[I].InstallVer == 0) + return; + D = Cache[I].InstVerIter(Cache).DependsList(); + } else { + if (I->CurrentVer == 0) + return; + D = I.CurrentVer().DependsList(); + } - return Cache.BrokenCount() == 0; + for ( /* nothing */ ; D.end() == false; D++) + if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends) + { + if(!List->IsFlag(D.TargetPkg(), pkgOrderList::Immediate)) + { + if(Debug) + 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, Depth + 1); + } + } + return; } /*}}}*/ +// PM::CreateOrderList - Create the ordering class /*{{{*/ +// --------------------------------------------------------------------- +/* This populates the ordering list with all the packages that are + going to change. */ +bool pkgPackageManager::CreateOrderList() +{ + if (List != 0) + return true; + + delete List; + List = new pkgOrderList(&Cache); + + 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++) + { + // 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) && + NoImmConfigure == false) + { + if(Debug) + clog << "CreateOrderList(): Adding Immediate flag for " << I.Name() << endl; + List->Flag(I,pkgOrderList::Immediate); + // Look for other install packages to make immediate configurea + ImmediateAdd(I, true); + + // And again with the current version. + ImmediateAdd(I, false); + } + + // Not interesting + if ((Cache[I].Keep() == true || + Cache[I].InstVerIter(Cache) == I.CurrentVer()) && + 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 + List->push_back(I); + } + + return true; +} + /*}}}*/ // PM::DepAlwaysTrue - Returns true if this dep is irrelevent /*{{{*/ // --------------------------------------------------------------------- /* The restriction on provides is to eliminate the case when provides @@ -167,21 +231,25 @@ bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D, { for (;D.end() == false; D++) { - if (D->Type != pkgDEP_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; } /*}}}*/ @@ -191,7 +259,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++) @@ -201,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 && Configure(Pkg) == false) return false; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); @@ -222,20 +293,27 @@ bool pkgPackageManager::ConfigureAll() of it's dependents. */ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg) { - pkgOrderList OList(Cache); + 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 && Configure(Pkg) == false) return false; List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States); @@ -243,8 +321,9 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg) // 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; } /*}}}*/ @@ -259,8 +338,10 @@ 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); OList.Flag(Pkg,pkgOrderList::Added); @@ -270,7 +351,7 @@ bool pkgPackageManager::DepAdd(pkgOrderList &OList,PkgIterator Pkg,int Depth) bool Bad = false; for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false;) { - if (D->Type != pkgDEP_Depends && D->Type != pkgDEP_PreDepends) + if (D->Type != pkgCache::Dep::Depends && D->Type != pkgCache::Dep::PreDepends) { D++; continue; @@ -280,12 +361,12 @@ bool pkgPackageManager::DepAdd(pkgOrderList &OList,PkgIterator Pkg,int Depth) Bad = true; for (bool LastOR = true; D.end() == false && LastOR == true; D++) { - LastOR = (D->CompareOp & pkgOP_OR) == pkgOP_OR; + LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; 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); @@ -303,16 +384,18 @@ 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) { + if (Debug) + std::clog << OutputInDepth(Depth) << "DepAdd FAILS on: " << Pkg.Name() << std::endl; OList.Flag(Pkg,0,pkgOrderList::Added); OList.pop_back(); Depth--; @@ -339,6 +422,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) @@ -356,7 +465,9 @@ 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); + return true; } /*}}}*/ // PM::SmartUnPack - Install helper /*{{{*/ @@ -371,19 +482,28 @@ 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(_("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; } - + /* 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 == pkgDEP_PreDepends) + // Compute a single dependency element (glob or) + pkgCache::DepIterator Start; + pkgCache::DepIterator End; + D.GlobOr(Start,End); + + while (End->Type == pkgCache::Dep::PreDepends) { + if (Debug == true) + clog << "PreDepends order for " << Pkg.Name() << std::endl; + // 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++) { @@ -395,6 +515,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) Pkg.State() == PkgIterator::NeedsNothing) { Bad = false; + if (Debug == true) + clog << "Found ok package " << Pkg.Name() << endl; continue; } } @@ -410,22 +532,32 @@ 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); } - - 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 == pkgDEP_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); @@ -438,26 +570,28 @@ 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()); - - if (Install(Pkg,FileNames[Pkg->ID]) == false) + + if(Install(Pkg,FileNames[Pkg->ID]) == false) return false; - + List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States); // 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(_("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; } @@ -465,84 +599,116 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg) // PM::OrderInstall - Installation ordering routine /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgPackageManager::OrderInstall() +pkgPackageManager::OrderResult pkgPackageManager::OrderInstall() { - delete List; - List = new pkgOrderList(Cache); + if (CreateOrderList() == false) + return Failed; + + Reset(); - // Generate the list of affected packages and sort it - for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++) + if (Debug == true) + clog << "Beginning to order" << endl; + + bool const ordering = + _config->FindB("PackageManager::UnpackAll",true) ? + List->OrderUnpack(FileNames) : List->OrderCritical(); + if (ordering == false) { - // Consider all depends - if ((I->Flags & pkgFLAG_Essential) == pkgFLAG_Essential) - { - List->Flag(I,pkgOrderList::Immediate); - if (Cache[I].InstallVer != 0) - for (DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); - D.end() == false; D++) - if (D->Type == pkgDEP_Depends || D->Type == pkgDEP_PreDepends) - List->Flag(D.TargetPkg(),pkgOrderList::Immediate); - if (I->CurrentVer != 0) - for (DepIterator D = I.CurrentVer().DependsList(); - D.end() == false; D++) - if (D->Type == pkgDEP_Depends || D->Type == pkgDEP_PreDepends) - List->Flag(D.TargetPkg(),pkgOrderList::Immediate); - } - - // Not interesting - if ((Cache[I].Keep() == true || - Cache[I].InstVerIter(Cache) == I.CurrentVer()) && - I.State() == pkgCache::PkgIterator::NeedsNothing) - continue; - - // Append it to the list - List->push_back(I); - - if ((I->Flags & pkgFLAG_ImmediateConf) == pkgFLAG_ImmediateConf) - List->Flag(I,pkgOrderList::Immediate); + _error->Error("Internal ordering error"); + return Failed; } - if (List->OrderUnpack() == false) - return _error->Error("Internal ordering error"); + if (Debug == true) + clog << "Done ordering" << endl; + bool DoneSomething = false; for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++) { PkgIterator Pkg(Cache,*I); + + if (List->IsNow(Pkg) == false) + { + if (Debug == true) + clog << "Skipping already done " << Pkg.Name() << endl; + continue; + } + + if (List->IsMissing(Pkg) == true) + { + if (Debug == true) + clog << "Sequence completed at " << Pkg.Name() << endl; + if (DoneSomething == false) + { + _error->Error("Internal Error, ordering was unable to handle the media swap"); + return Failed; + } + return Incomplete; + } // Sanity check - if (Cache[Pkg].Keep() == true && Pkg.State() == pkgCache::PkgIterator::NeedsNothing) - return _error->Error("Internal Error, trying to manipulate a kept package"); + 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 (%s)",Pkg.Name()); + return Failed; + } // Perform a delete or an install if (Cache[Pkg].Delete() == true) { if (SmartRemove(Pkg) == false) - return false; + return Failed; } else if (SmartUnPack(Pkg) == false) - return false; + return Failed; + DoneSomething = true; } - + // Final run through the configure phase if (ConfigureAll() == false) - return false; + return Failed; // Sanity check for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++) + { if (List->IsFlag(*I,pkgOrderList::Configured) == false) - return _error->Error("Internal error, packages left unconfigured. %s", - PkgIterator(Cache,*I).Name()); - - return true; + { + _error->Error("Internal error, packages left unconfigured. %s", + PkgIterator(Cache,*I).Name()); + return Failed; + } + } + + return Completed; } /*}}}*/ +// PM::DoInstallPostFork - Does install part that happens after the fork /*{{{*/ +// --------------------------------------------------------------------- +pkgPackageManager::OrderResult +pkgPackageManager::DoInstallPostFork(int statusFd) +{ + if(statusFd > 0) + // FIXME: use SetCloseExec here once it taught about throwing + // exceptions instead of doing _exit(100) on failure + fcntl(statusFd,F_SETFD,FD_CLOEXEC); + bool goResult = Go(statusFd); + if(goResult == false) + return Failed; + + return Res; +}; + // PM::DoInstall - Does the installation /*{{{*/ // --------------------------------------------------------------------- /* This uses the filenames in FileNames and the information in the DepCache to perform the installation of packages.*/ -bool pkgPackageManager::DoInstall() +pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd) { - return OrderInstall() && Go(); + if(DoInstallPreFork() == Failed) + return Failed; + + return DoInstallPostFork(statusFd); } /*}}}*/