// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: depcache.cc,v 1.1 1998/07/07 04:17:01 jgg Exp $
+// $Id: depcache.cc,v 1.25 2001/05/27 05:36:04 jgg Exp $
/* ######################################################################
Dependency Cache - Caches Dependency information.
/*}}}*/
// Include Files /*{{{*/
#ifdef __GNUG__
-#pragma implementation "pkglib/depcache.h"
+#pragma implementation "apt-pkg/depcache.h"
#endif
-#include <pkglib/depcache.h>
-
-#include <pkglib/version.h>
-#include <pkglib/error.h>
+#include <apt-pkg/depcache.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/sptr.h>
+#include <apt-pkg/algorithms.h>
+
+#include <apti18n.h>
/*}}}*/
// DepCache::pkgDepCache - Constructors /*{{{*/
// ---------------------------------------------------------------------
/* */
-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();
+ delLocalPolicy = 0;
+ LocalPolicy = Plcy;
+ if (LocalPolicy == 0)
+ delLocalPolicy = LocalPolicy = new Policy;
}
/*}}}*/
// DepCache::~pkgDepCache - Destructor /*{{{*/
{
delete [] PkgState;
delete [] DepState;
-}
- /*}}}*/
-// DepCache::ReMap - Regenerate the extra data for the new cache /*{{{*/
-// ---------------------------------------------------------------------
-/* pkgCache's constructors call this function, but because the object is not
- fully constructed at that point it will not result in this function being
- called but pkgCache::ReMap will be instead.*/
-bool pkgDepCache::ReMap()
-{
- if (pkgCache::ReMap() == false)
- return false;
-
- return Init();
+ delete delLocalPolicy;
}
/*}}}*/
// DepCache::Init - Generate the initial extra structures. /*{{{*/
// ---------------------------------------------------------------------
/* This allocats the extension buffers and initializes them. */
-bool pkgDepCache::Init()
+bool pkgDepCache::Init(OpProgress *Prog)
{
delete [] PkgState;
delete [] DepState;
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"));
+ }
/* Set the current state of everything. In this state all of the
packages are kept exactly as is. See AllUpgrade */
- for (PkgIterator I = PkgBegin(); I.end() != true; I++)
+ int Done = 0;
+ for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
{
+ if (Prog != 0)
+ Prog->Progress(Done);
+
// Find the proper cache slot
StateCache &State = PkgState[I->ID];
State.iFlags = 0;
State.Update(I,*this);
}
- Update();
+ if (Prog != 0)
+ {
+
+ Prog->OverallProgress(Head().PackageCount,2*Head().PackageCount,
+ Head().PackageCount,
+ _("Building Dependency Tree"));
+ Prog->SubProgress(Head().PackageCount,_("Dependency Generation"));
+ }
+
+ Update(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 /*{{{*/
// ---------------------------------------------------------------------
/* 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();
}
// 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;
// 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->VersionList == 0)
+ return;
+
+ 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*(P.InstVerIter(*this)->InstalledSize -
- 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;
+ }
+
+ // Reinstall
+ if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
+ P.Delete() == false)
+ {
+ 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;
+ }
}
/*}}}*/
// DepCache::AddStates - Add the package to the state counter /*{{{*/
// 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;
}
/* 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..
+ State &= 0x7;
Group |= State;
State |= Group << 3;
if ((D->CompareOp & Dep::Or) != Dep::Or)
Group = 0;
// Invert for Conflicts
- if (D->Type == Dep::Conflicts)
+ if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
State = ~State;
}
}
// ---------------------------------------------------------------------
/* This will figure out the state of all the packages and all the
dependencies based on the current policy. */
-void pkgDepCache::Update()
+void pkgDepCache::Update(OpProgress *Prog)
{
iUsrSize = 0;
iDownloadSize = 0;
iBadCount = 0;
// Perform the depends pass
- for (PkgIterator I = PkgBegin(); I.end() != true; I++)
+ int Done = 0;
+ for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
{
+ if (Prog != 0 && Done%20 == 0)
+ Prog->Progress(Done);
for (VerIterator V = I.VersionList(); V.end() != true; V++)
{
unsigned char Group = 0;
{
// 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;
Group = 0;
// Invert for Conflicts
- if (D->Type == Dep::Conflicts)
+ if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
State = ~State;
}
}
UpdateVerState(I);
AddStates(I);
}
+
+ if (Prog != 0)
+ Prog->Progress(Done);
}
/*}}}*/
// DepCache::Update - Update the deps list of a package /*{{{*/
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());
/* 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);
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());
}
/*}}}*/
// 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 */
// 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)
// 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;
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;
// 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;
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)
// 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;
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<Version *> 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);
MarkDelete(Pkg);
PkgState[Pkg->ID].Flags |= Flag::Auto;
}
- delete [] List;
continue;
}
}
}
/*}}}*/
-
-#if 0
-// DepCache::ResolveConflicts - Figure the auto upgrades /*{{{*/
+// DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
// ---------------------------------------------------------------------
-/* This routine attempts to resolve conflicts generated by automatic
- upgrading. It is known as 'Stage 1' but that name isn't as proper anymore.
-
- It's most important function is during the initial load of APT. The
- loading code will mark every package for upgrade to it's candidate version
- and then call this routine. This routine will then 'soft keep' every
- package that causes conflict, is conflicted, or so on. It is a bit
- agressive in that it may unselect more packages in some odd cases
- than are strictly necessary but in the case where no packages were
- conflicting before it will always produce a system with no packages
- conflicting after.
-
- This routine is also used during state changes that require autoupgrade
- scanning. That is, if a new package is marked for install then all packages
- that have been soft kept are reconsidered for upgrade.
-
- It is called with state information about what can be un-upgraded and
- what the pre-upgrade install state was. It is expected that the caller
- has already marked the desired packages to the install state. Bit 0 is
- the original install state and Bit 1 is controls whether the package
- should be touched.
-*/
-void pkgDepCache::ResolveConflicts(unsigned char *Touched)
-{
- bool Again = false;
- do
- {
- Again = false;
- for (PkgIterator I = PkgBegin(); I.end() != true; I++)
- {
- // The package will install OK
- if ((PkgState[I->ID].DepState & DepInstMin) == DepInstMin)
- continue;
-
- /* The package was broken before and this upgrade will not
- make things better. We simply mark the package for keep
- and assume an upgrade attempt will be hopeless. This might
- not be ideal. */
- if ((Touched[I->ID] & (1 << 0)) != (1 << 0))
- {
- // The package isnt to be touched
- if ((Touched[I->ID] & (1 << 1)) == (1 << 1))
- MarkKeep(I,true);
-
- continue;
- }
-
- // Check to see if not upgrading it will solve the problem
- if (I->CurrentVer != 0)
- {
- // The package isnt to be touched
- if ((Touched[I->ID] & (1 << 1)) == (1 << 1))
- {
- if (PkgState[I->ID].Mode != ModeKeep)
- Again = true;
-
- MarkKeep(I,true);
- }
-
- /* Check if the package is sill broken. If so then we cant leave
- it as is and get a working system. Lets try marking some
- depends for 'keep'. This is brutal, it keeps everything in
- sight to fix the problem. */
- DepIterator D = I.CurrentVer().DependsList();
- for (;(PkgState[I->ID].DepState & DepInstMin) != DepInstMin &&
- D.end() != true; D++)
- {
- // We only worry about critical deps.
- if (D.IsCritical() != true)
- continue;
-
- unsigned char State = DepState[D->ID];
-
- // This dep never was set before so we dont need to set it now
- if ((State & DepNow) != DepNow)
- continue;
-
- // The dep is okay now no worries.
- if ((State & DepInstall) == DepInstall)
- continue;
-
- // Locate a target to keep
- PkgIterator P(*this);
- if (CheckDep(D,NowVersion,P) == true)
- {
- // We cant touch this package
- if ((Touched[P->ID] & (1 << 1)) == (1 << 1))
- MarkKeep(P,true);
- }
- }
- }
- }
- }
- while (Again == true);
-}
- /*}}}*/
-// DepCache::PromoteAutoKeep - Gentler version of the above /*{{{*/
-// ---------------------------------------------------------------------
-/* This is used when installing packages, all it does is attempt to promote
- everything that has been auto-kept. It simply promotes everything
- irregardless of it having a chance to work and then runs ResolveConflicts
- on the result. This allows circular depends loops to work but isn't
- terribly fast. */
-void pkgDepCache::PromoteAutoKeep()
+/* */
+void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
{
- /* Initialize the touchd array. Bit 0 is the old install state bit 1
- is the touch value */
- unsigned char *Touch = new unsigned char[Head().PackageCount];
- for (unsigned int I = 0; I != Head().PackageCount; I++)
- {
- if ((PkgState[I].DepState & DepInstMin) == DepInstMin)
- Touch[I] = 1 << 0;
- else
- Touch[I] = 0;
- }
-
- // This allows circular depends to work
- for (PkgIterator I = PkgBegin(); I.end() != true; I++)
- {
- /* It wasnt installed before or it is not autokept or it is not
- upgradeable */
- StateCache &P = PkgState[I->ID];
- if (I->CurrentVer == 0 || P.Mode != ModeKeep || I->VersionList == 0 ||
- P.CandidateVer == (Version *)I.CurrentVer() ||
- (P.iFlags & AutoKept) != AutoKept)
- continue;
-
- P.Mode = ModeInstall;
- P.InstallVer = P.CandidateVer;
- if (P.CandidateVer == (Version *)I.CurrentVer())
- P.Mode = ModeKeep;
-
- // Okay autoupgrade it.
- Touch[I->ID] |= 1 << 1;
- }
+ RemoveSizes(Pkg);
+ RemoveStates(Pkg);
- Update();
- ResolveConflicts(Touch);
+ StateCache &P = PkgState[Pkg->ID];
+ if (To == true)
+ P.iFlags |= ReInstall;
+ else
+ P.iFlags &= ~ReInstall;
- delete [] Touch;
+ AddStates(Pkg);
+ AddSizes(Pkg);
}
/*}}}*/
-// DepCache::AllUpgrade - Try to upgrade everything /*{{{*/
+// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
// ---------------------------------------------------------------------
/* */
-void pkgDepCache::AllUpgrade()
+void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
{
- // Set everything to an upgrade mode
- for (PkgIterator I = PkgBegin(); I.end() != true; I++)
- {
- StateCache &State = PkgState[I->ID];
-
- /* We dont upgrade packages marked for deletion or that are
- not installed or that don't have an upgrade */
- if (State.Mode == ModeDelete || I->CurrentVer == 0 ||
- (Version *)I.CurrentVer() == State.CandidateVer)
- continue;
-
- // Set the state to upgrade
- State.iFlags = 0;
- State.Mode = ModeInstall;
- State.InstallVer = State.CandidateVer;
- if (State.CandidateVer == (Version *)I.CurrentVer())
- State.Mode = ModeKeep;
-
- // Do not upgrade things that have the hold flag set.
- if (I->SelectedState == State::Hold)
- {
- State.InstallVer = I.CurrentVer();
- State.Mode = ModeKeep;
- }
- State.Update(I,*this);
- }
+ pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
+ StateCache &P = PkgState[Pkg->ID];
- Update();
-
- /* Initialize the touchd array. Bit 0 is the old install state bit 1
- is the touch value */
- unsigned char *Touch = new unsigned char[Head().PackageCount];
- for (unsigned int I = 0; I != Head().PackageCount; I++)
- {
- if ((PkgState[I].DepState & DepNowMin) == DepNowMin)
- Touch[I] = (1 << 0) | (1 << 1);
- else
- Touch[I] = 1 << 1;
- }
+ RemoveSizes(Pkg);
+ RemoveStates(Pkg);
- // Now downgrade everything that is broken
- ResolveConflicts(Touch);
- delete [] Touch;
+ if (P.CandidateVer == P.InstallVer)
+ P.InstallVer = (Version *)TargetVer;
+ P.CandidateVer = (Version *)TargetVer;
+ P.Update(Pkg,*this);
+
+ AddStates(Pkg);
+ Update(Pkg);
+ AddSizes(Pkg);
}
/*}}}*/
-#endif
-
// StateCache::Update - Compute the various static display things /*{{{*/
// ---------------------------------------------------------------------
/* This is called whenever the Candidate version changes. */
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();
+}
+ /*}}}*/