X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/981d20eb7e036152b04238036d1ce215b9b75ccf..4d055c05ce287dabd9e224af5c71d690a44b2db6:/apt-pkg/depcache.cc diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 7f9ded720..507416217 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: depcache.cc,v 1.10 1998/12/08 01:34:07 jgg Exp $ +// $Id: depcache.cc,v 1.24 2001/04/25 06:17:00 jgg Exp $ /* ###################################################################### Dependency Cache - Caches Dependency information. @@ -12,25 +12,24 @@ #pragma implementation "apt-pkg/depcache.h" #endif #include - #include #include +#include +#include + +#include /*}}}*/ // DepCache::pkgDepCache - Constructors /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgDepCache::pkgDepCache(MMap &Map,OpProgress &Prog) : - pkgCache(Map), PkgState(0), DepState(0) -{ - if (_error->PendingError() == false) - Init(&Prog); -} -pkgDepCache::pkgDepCache(MMap &Map) : - pkgCache(Map), PkgState(0), DepState(0) +pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) : + Cache(pCache), PkgState(0), DepState(0) { - if (_error->PendingError() == false) - Init(0); + delLocalPolicy = 0; + LocalPolicy = Plcy; + if (LocalPolicy == 0) + delLocalPolicy = LocalPolicy = new Policy; } /*}}}*/ // DepCache::~pkgDepCache - Destructor /*{{{*/ @@ -40,6 +39,7 @@ pkgDepCache::~pkgDepCache() { delete [] PkgState; delete [] DepState; + delete delLocalPolicy; } /*}}}*/ // DepCache::Init - Generate the initial extra structures. /*{{{*/ @@ -53,12 +53,12 @@ bool pkgDepCache::Init(OpProgress *Prog) DepState = new unsigned char[Head().DependsCount]; memset(PkgState,0,sizeof(*PkgState)*Head().PackageCount); memset(DepState,0,sizeof(*DepState)*Head().DependsCount); - + if (Prog != 0) { Prog->OverallProgress(0,2*Head().PackageCount,Head().PackageCount, - "Building Dependency Tree"); - Prog->SubProgress(Head().PackageCount,"Candidate Versions"); + _("Building Dependency Tree")); + Prog->SubProgress(Head().PackageCount,_("Candidate Versions")); } /* Set the current state of everything. In this state all of the @@ -86,8 +86,8 @@ bool pkgDepCache::Init(OpProgress *Prog) Prog->OverallProgress(Head().PackageCount,2*Head().PackageCount, Head().PackageCount, - "Building Dependency Tree"); - Prog->SubProgress(Head().PackageCount,"Dependency Generation"); + _("Building Dependency Tree")); + Prog->SubProgress(Head().PackageCount,_("Dependency Generation")); } Update(Prog); @@ -95,40 +95,6 @@ bool pkgDepCache::Init(OpProgress *Prog) return true; } /*}}}*/ -// DepCache::GetCandidateVer - Returns the Candidate install version /*{{{*/ -// --------------------------------------------------------------------- -/* The default just returns the target version if it exists or the - highest version. */ -pkgDepCache::VerIterator pkgDepCache::GetCandidateVer(PkgIterator Pkg) -{ - // Try to use an explicit target - if (Pkg->TargetVer == 0) - { - /* Not source versions cannot be a candidate version unless they - are already installed */ - for (VerIterator I = Pkg.VersionList(); I.end() == false; I++) - { - if (Pkg.CurrentVer() == I) - return I; - for (VerFileIterator J = I.FileList(); J.end() == false; J++) - if ((J.File()->Flags & Flag::NotSource) == 0) - return I; - } - - return VerIterator(*this,0); - } - else - return Pkg.TargetVer(); -} - /*}}}*/ -// DepCache::IsImportantDep - True if the dependency is important /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool pkgDepCache::IsImportantDep(DepIterator Dep) -{ - return Dep.IsCritical(); -} - /*}}}*/ // DepCache::CheckDep - Checks a single dependency /*{{{*/ // --------------------------------------------------------------------- @@ -143,28 +109,30 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) /* Check simple depends. A depends -should- never self match but we allow it anyhow because dpkg does. Technically it is a packaging bug. Conflicts may never self match */ - if (Dep.TargetPkg() != Dep.ParentPkg() || Dep->Type != Dep::Conflicts) + if (Dep.TargetPkg() != Dep.ParentPkg() || + (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes)) { PkgIterator Pkg = Dep.TargetPkg(); // Check the base package if (Type == NowVersion && Pkg->CurrentVer != 0) - if (pkgCheckDep(Dep.TargetVer(), - Pkg.CurrentVer().VerStr(),Dep->CompareOp) == true) + if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep->CompareOp, + Dep.TargetVer()) == true) return true; if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0) - if (pkgCheckDep(Dep.TargetVer(), - PkgState[Pkg->ID].InstVerIter(*this).VerStr(), - Dep->CompareOp) == true) + if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(), + Dep->CompareOp,Dep.TargetVer()) == true) return true; if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0) - if (pkgCheckDep(Dep.TargetVer(), - PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(), - Dep->CompareOp) == true) + if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(), + Dep->CompareOp,Dep.TargetVer()) == true) return true; } + if (Dep->Type == Dep::Obsoletes) + return false; + // Check the providing packages PrvIterator P = Dep.TargetPkg().ProvidesList(); PkgIterator Pkg = Dep.ParentPkg(); @@ -197,7 +165,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) } // Compare the versions. - if (pkgCheckDep(Dep.TargetVer(),P.ProvideVersion(),Dep->CompareOp) == true) + if (VS().CheckDep(P.ProvideVersion(),Dep->CompareOp,Dep.TargetVer()) == true) { Res = P.OwnerPkg(); return true; @@ -210,31 +178,30 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) // DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/ // --------------------------------------------------------------------- /* Call with Mult = -1 to preform the inverse opration */ -void pkgDepCache::AddSizes(const PkgIterator &Pkg,long Mult) +void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult) { StateCache &P = PkgState[Pkg->ID]; - if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure) - { - iUsrSize += Mult*P.InstVerIter(*this)->InstalledSize; + if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && + P.Keep() == true) return; - } // Compute the size data if (P.NewInstall() == true) { - iUsrSize += Mult*P.InstVerIter(*this)->InstalledSize; - iDownloadSize += Mult*P.InstVerIter(*this)->Size; + iUsrSize += (signed)(Mult*P.InstVerIter(*this)->InstalledSize); + iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size); return; } // Upgrading - if (Pkg->CurrentVer != 0 && P.InstallVer != (Version *)Pkg.CurrentVer() && - P.InstallVer != 0) + if (Pkg->CurrentVer != 0 && + (P.InstallVer != (Version *)Pkg.CurrentVer() || + (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0) { - iUsrSize += Mult*((signed)P.InstVerIter(*this)->InstalledSize - - (signed)Pkg.CurrentVer()->InstalledSize); - iDownloadSize += Mult*P.InstVerIter(*this)->Size; + iUsrSize += (signed)(Mult*((signed)P.InstVerIter(*this)->InstalledSize - + (signed)Pkg.CurrentVer()->InstalledSize)); + iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size); return; } @@ -242,14 +209,14 @@ void pkgDepCache::AddSizes(const PkgIterator &Pkg,long Mult) if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack && P.Delete() == false) { - iDownloadSize += Mult*P.InstVerIter(*this)->Size; + iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size); return; } // Removing if (Pkg->CurrentVer != 0 && P.InstallVer == 0) { - iUsrSize -= Mult*Pkg.CurrentVer()->InstalledSize; + iUsrSize -= (signed)(Mult*Pkg.CurrentVer()->InstalledSize); return; } } @@ -277,16 +244,24 @@ void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add) // Not installed if (Pkg->CurrentVer == 0) { + if (State.Mode == ModeDelete && + (State.iFlags | Purge) == Purge && Pkg.Purge() == false) + iDelCount += Add; + if (State.Mode == ModeInstall) iInstCount += Add; return; } // Installed, no upgrade - if (State.Upgradable() == false) - { + if (State.Status == 0) + { if (State.Mode == ModeDelete) iDelCount += Add; + else + if ((State.iFlags & ReInstall) == ReInstall) + iInstCount += Add; + return; } @@ -314,7 +289,7 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V) /* Invert for Conflicts. We have to do this twice to get the right sense for a conflicts group */ - if (D->Type == Dep::Conflicts) + if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes) State = ~State; // Add to the group if we are within an or.. @@ -325,7 +300,7 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V) Group = 0; // Invert for Conflicts - if (D->Type == Dep::Conflicts) + if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes) State = ~State; } } @@ -449,7 +424,7 @@ void pkgDepCache::Update(OpProgress *Prog) { // Build the dependency state. unsigned char &State = DepState[D->ID]; - State = DependencyState(D);; + State = DependencyState(D); // Add to the group if we are within an or.. Group |= State; @@ -458,7 +433,7 @@ void pkgDepCache::Update(OpProgress *Prog) Group = 0; // Invert for Conflicts - if (D->Type == Dep::Conflicts) + if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes) State = ~State; } } @@ -486,9 +461,9 @@ void pkgDepCache::Update(DepIterator D) State = DependencyState(D); // Invert for Conflicts - if (D->Type == Dep::Conflicts) + if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes) State = ~State; - + RemoveStates(D.ParentPkg()); BuildGroupOrs(D.ParentVer()); UpdateVerState(D.ParentPkg()); @@ -501,7 +476,7 @@ void pkgDepCache::Update(DepIterator D) /* This is called whenever the state of a package changes. It updates all cached dependencies related to this package. */ void pkgDepCache::Update(PkgIterator const &Pkg) -{ +{ // Recompute the dep of the package RemoveStates(Pkg); UpdateVerState(Pkg); @@ -517,9 +492,10 @@ void pkgDepCache::Update(PkgIterator const &Pkg) Update(P.ParentPkg().RevDependsList()); // Update the provides map for the candidate ver - for (PrvIterator P = PkgState[Pkg->ID].CandidateVerIter(*this).ProvidesList(); - P.end() != true; P++) - Update(P.ParentPkg().RevDependsList()); + if (PkgState[Pkg->ID].CandidateVer != 0) + for (PrvIterator P = PkgState[Pkg->ID].CandidateVerIter(*this).ProvidesList(); + P.end() != true; P++) + Update(P.ParentPkg().RevDependsList()); } /*}}}*/ @@ -532,6 +508,12 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft) // Simplifies other routines. if (Pkg.end() == true) return; + + /* Reject an attempt to keep a non-source broken installed package, those + must be upgraded */ + if (Pkg.State() == PkgIterator::NeedsUnpack && + Pkg.CurrentVer().Downloadable() == false) + return; /* We changed the soft state all the time so the UI is a bit nicer to use */ @@ -569,7 +551,7 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft) // DepCache::MarkDelete - Put the package in the delete state /*{{{*/ // --------------------------------------------------------------------- /* */ -void pkgDepCache::MarkDelete(PkgIterator const &Pkg) +void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge) { // Simplifies other routines. if (Pkg.end() == true) @@ -577,10 +559,14 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg) // Check that it is not already marked for delete StateCache &P = PkgState[Pkg->ID]; - P.iFlags &= ~AutoKept; - if (P.Mode == ModeDelete || P.InstallVer == 0) + P.iFlags &= ~(AutoKept | Purge); + if (rPurge == true) + P.iFlags |= Purge; + + if ((P.Mode == ModeDelete || P.InstallVer == 0) && + (Pkg.Purge() == true || rPurge == false)) return; - + // We dont even try to delete virtual packages.. if (Pkg->VersionList == 0) return; @@ -588,7 +574,10 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg) RemoveSizes(Pkg); RemoveStates(Pkg); - P.Mode = ModeDelete; + if (Pkg->CurrentVer == 0 && (Pkg.Purge() == true || rPurge == false)) + P.Mode = ModeKeep; + else + P.Mode = ModeDelete; P.InstallVer = 0; P.Flags &= Flag::Auto; @@ -600,8 +589,12 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg) // DepCache::MarkInstall - Put the package in the install state /*{{{*/ // --------------------------------------------------------------------- /* */ -void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst) -{ +void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, + unsigned long Depth) +{ + if (Depth > 100) + return; + // Simplifies other routines. if (Pkg.end() == true) return; @@ -617,6 +610,10 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst) MarkKeep(Pkg); return; } + + // See if there is even any possible instalation candidate + if (P.CandidateVer == 0) + return; // We dont even try to install virtual packages.. if (Pkg->VersionList == 0) @@ -647,7 +644,8 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst) // Grok or groups DepIterator Start = Dep; bool Result = true; - for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++) + unsigned Ors = 0; + for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++,Ors++) { LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or; @@ -666,24 +664,62 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst) continue; if (Pkg->CurrentVer != 0 && Start.IsCritical() == false) continue; - - // Now we have to take action... - PkgIterator P = Start.SmartTargetPkg(); + + /* If we are in an or group locate the first or that can + succeed. We have already cached this.. */ + for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; Ors--) + Start++; + + /* This bit is for processing the possibilty of an install/upgrade + fixing the problem */ + SPtrArray List = Start.AllTargets(); if ((DepState[Start->ID] & DepCVer) == DepCVer) { - MarkInstall(P,true); + // Right, find the best version to install.. + Version **Cur = List; + PkgIterator P = Start.TargetPkg(); + PkgIterator InstPkg(*Cache,0); + + // See if there are direct matches (at the start of the list) + for (; *Cur != 0 && (*Cur)->ParentPkg == P.Index(); Cur++) + { + PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg); + if (PkgState[Pkg->ID].CandidateVer != *Cur) + continue; + InstPkg = Pkg; + break; + } + + // Select the highest priority providing package + if (InstPkg.end() == true) + { + pkgPrioSortList(*Cache,Cur); + for (; *Cur != 0; Cur++) + { + PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg); + if (PkgState[Pkg->ID].CandidateVer != *Cur) + continue; + InstPkg = Pkg; + break; + } + } - // Set the autoflag, after MarkInstall because MarkInstall unsets it - if (P->CurrentVer == 0) - PkgState[P->ID].Flags |= Flag::Auto; + if (InstPkg.end() == false) + { + MarkInstall(InstPkg,true,Depth + 1); + // Set the autoflag, after MarkInstall because MarkInstall unsets it + if (P->CurrentVer == 0) + PkgState[InstPkg->ID].Flags |= Flag::Auto; + } + continue; } - // For conflicts we just de-install the package and mark as auto - if (Start->Type == Dep::Conflicts) + /* For conflicts we just de-install the package and mark as auto, + Conflicts may not have or groups */ + if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes) { - Version **List = Start.AllTargets(); for (Version **I = List; *I != 0; I++) { VerIterator Ver(*this,*I); @@ -692,13 +728,50 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst) MarkDelete(Pkg); PkgState[Pkg->ID].Flags |= Flag::Auto; } - delete [] List; continue; } } } /*}}}*/ +// DepCache::SetReInstall - Set the reinstallation flag /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To) +{ + RemoveSizes(Pkg); + RemoveStates(Pkg); + + StateCache &P = PkgState[Pkg->ID]; + if (To == true) + P.iFlags |= ReInstall; + else + P.iFlags &= ~ReInstall; + + AddStates(Pkg); + AddSizes(Pkg); +} + /*}}}*/ +// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void pkgDepCache::SetCandidateVersion(VerIterator TargetVer) +{ + pkgCache::PkgIterator Pkg = TargetVer.ParentPkg(); + StateCache &P = PkgState[Pkg->ID]; + + RemoveSizes(Pkg); + RemoveStates(Pkg); + if (P.CandidateVer == P.InstallVer) + P.InstallVer = (Version *)TargetVer; + P.CandidateVer = (Version *)TargetVer; + P.Update(Pkg,*this); + + AddStates(Pkg); + Update(Pkg); + AddSizes(Pkg); +} + /*}}}*/ // StateCache::Update - Compute the various static display things /*{{{*/ // --------------------------------------------------------------------- /* This is called whenever the Candidate version changes. */ @@ -743,3 +816,48 @@ const char *pkgDepCache::StateCache::StripEpoch(const char *Ver) return Ver; } /*}}}*/ + +// Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/ +// --------------------------------------------------------------------- +/* The default just returns the highest available version that is not + a source and automatic. */ +pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg) +{ + /* Not source/not automatic versions cannot be a candidate version + unless they are already installed */ + VerIterator Last(*(pkgCache *)this,0); + + for (VerIterator I = Pkg.VersionList(); I.end() == false; I++) + { + if (Pkg.CurrentVer() == I) + return I; + + for (VerFileIterator J = I.FileList(); J.end() == false; J++) + { + if ((J.File()->Flags & Flag::NotSource) != 0) + continue; + + /* Stash the highest version of a not-automatic source, we use it + if there is nothing better */ + if ((J.File()->Flags & Flag::NotAutomatic) != 0) + { + if (Last.end() == true) + Last = I; + continue; + } + + return I; + } + } + + return Last; +} + /*}}}*/ +// Policy::IsImportantDep - True if the dependency is important /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep) +{ + return Dep.IsCritical(); +} + /*}}}*/