|
|
@ -1,6 +1,6 @@ |
|
|
|
// -*- mode: cpp; mode: fold -*-
|
|
|
|
// Description /*{{{*/
|
|
|
|
// $Id: depcache.cc,v 1.3 1998/09/07 05:28:32 jgg Exp $
|
|
|
|
// $Id: depcache.cc,v 1.4 1998/10/24 04:58:05 jgg Exp $
|
|
|
|
/* ######################################################################
|
|
|
|
|
|
|
|
Dependency Cache - Caches Dependency information. |
|
|
@ -673,203 +673,6 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst) |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
|
|
|
|
|
#if 0 |
|
|
|
// DepCache::ResolveConflicts - Figure the auto upgrades /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* 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() |
|
|
|
{ |
|
|
|
/* 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; |
|
|
|
} |
|
|
|
|
|
|
|
Update(); |
|
|
|
ResolveConflicts(Touch); |
|
|
|
|
|
|
|
delete [] Touch; |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
|
// DepCache::AllUpgrade - Try to upgrade everything /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* */ |
|
|
|
void pkgDepCache::AllUpgrade() |
|
|
|
{ |
|
|
|
// 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); |
|
|
|
} |
|
|
|
|
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
// Now downgrade everything that is broken
|
|
|
|
ResolveConflicts(Touch); |
|
|
|
delete [] Touch; |
|
|
|
} |
|
|
|
/*}}}*/ |
|
|
|
#endif |
|
|
|
|
|
|
|
// StateCache::Update - Compute the various static display things /*{{{*/
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
/* This is called whenever the Candidate version changes. */ |
|
|
|