// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: algorithms.cc,v 1.9 1998/11/13 07:08:57 jgg Exp $
+// $Id: algorithms.cc,v 1.23 1999/07/30 02:54:25 jgg Exp $
/* ######################################################################
Algorithms - A set of misc algorithms
// ---------------------------------------------------------------------
/* */
pkgSimulate::pkgSimulate(pkgDepCache &Cache) : pkgPackageManager(Cache),
- Sim(Cache)
+ Sim(Cache.GetMap())
{
Flags = new unsigned char[Cache.HeaderP->PackageCount];
memset(Flags,0,sizeof(*Flags)*Cache.HeaderP->PackageCount);
+
+ // Fake a filename so as not to activate the media swapping
+ string Jnk = "SIMULATE";
+ for (unsigned int I = 0; I != Cache.Head().PackageCount; I++)
+ FileNames[I] = Jnk;
}
/*}}}*/
// Simulate::Install - Simulate unpacking of a package /*{{{*/
PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
Flags[Pkg->ID] = 1;
- clog << "Inst " << Pkg.Name();
+ cout << "Inst " << Pkg.Name();
Sim.MarkInstall(Pkg,false);
// Look for broken conflicts+predepends.
{
if ((Sim[D] & pkgDepCache::DepInstall) == 0)
{
- clog << " [" << I.Name() << " on " << D.TargetPkg().Name() << ']';
+ cout << " [" << I.Name() << " on " << D.TargetPkg().Name() << ']';
if (D->Type == pkgCache::Dep::Conflicts)
_error->Error("Fatal, conflicts violated %s",I.Name());
}
if (Sim.BrokenCount() != 0)
ShortBreaks();
else
- clog << endl;
+ cout << endl;
return true;
}
/*}}}*/
// Sim.MarkInstall(Pkg,false);
if (Sim[Pkg].InstBroken() == true)
{
- clog << "Conf " << Pkg.Name() << " broken" << endl;
+ cout << "Conf " << Pkg.Name() << " broken" << endl;
Sim.Update();
continue;
if (D->Type == pkgCache::Dep::Conflicts)
- clog << " Conflicts:" << D.TargetPkg().Name();
+ cout << " Conflicts:" << D.TargetPkg().Name();
else
- clog << " Depends:" << D.TargetPkg().Name();
+ cout << " Depends:" << D.TargetPkg().Name();
}
- clog << endl;
+ cout << endl;
_error->Error("Conf Broken %s",Pkg.Name());
}
else
- clog << "Conf " << Pkg.Name();
+ cout << "Conf " << Pkg.Name();
if (Sim.BrokenCount() != 0)
ShortBreaks();
else
- clog << endl;
+ cout << endl;
return true;
}
// Simulate::Remove - Simulate the removal of a package /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool pkgSimulate::Remove(PkgIterator iPkg)
+bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
{
// Adapt the iterator
PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
Flags[Pkg->ID] = 3;
Sim.MarkDelete(Pkg);
- clog << "Remv " << Pkg.Name();
+ if (Purge == true)
+ cout << "Purg " << Pkg.Name();
+ else
+ cout << "Remv " << Pkg.Name();
if (Sim.BrokenCount() != 0)
ShortBreaks();
else
- clog << endl;
+ cout << endl;
return true;
}
/* */
void pkgSimulate::ShortBreaks()
{
- clog << " [";
+ cout << " [";
for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
{
if (Sim[I].InstBroken() == true)
{
if (Flags[I->ID] == 0)
- clog << I.Name() << ' ';
+ cout << I.Name() << ' ';
/* else
- clog << I.Name() << "! ";*/
+ cout << I.Name() << "! ";*/
}
}
- clog << ']' << endl;
+ cout << ']' << endl;
}
/*}}}*/
// ApplyStatus - Adjust for non-ok packages /*{{{*/
{
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
+ // Only choice for a ReInstReq package is to reinstall
+ if (I->InstState == pkgCache::State::ReInstReq ||
+ I->InstState == pkgCache::State::HoldReInstReq)
+ {
+ if (I.CurrentVer().Downloadable() == true)
+ Cache.MarkKeep(I);
+ else
+ {
+ // Is this right? Will dpkg choke on an upgrade?
+ if (Cache[I].CandidateVerIter(Cache).Downloadable() == true)
+ Cache.MarkInstall(I);
+ else
+ return _error->Error("The package %s needs to be reinstalled, "
+ "but I can't find an archive for it.",I.Name());
+ }
+
+ continue;
+ }
+
switch (I->CurrentState)
{
- // This means installation failed somehow
+ /* This means installation failed somehow - it does not need to be
+ re-unpacked (probably) */
case pkgCache::State::UnPacked:
case pkgCache::State::HalfConfigured:
- Cache.MarkKeep(I);
+ if (I.CurrentVer().Downloadable() == true ||
+ I.State() != pkgCache::PkgIterator::NeedsUnpack)
+ Cache.MarkKeep(I);
+ else
+ {
+ if (Cache[I].CandidateVerIter(Cache).Downloadable() == true)
+ Cache.MarkInstall(I);
+ else
+ Cache.MarkDelete(I);
+ }
break;
// This means removal failed
// We loop indefinately to get the minimal set size.
bool Change = false;
+ unsigned int Count = 0;
do
{
Change = false;
// Not interesting
if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
continue;
-
+
// Keep it and see if that is OK
Cache.MarkKeep(I);
if (Cache.BrokenCount() != 0)
Cache.MarkInstall(I,false);
else
- Change = true;
+ {
+ // If keep didnt actually do anything then there was no change..
+ if (Cache[I].Upgrade() == false)
+ Change = true;
+ }
}
+ Count++;
}
- while (Change == true);
+ while (Change == true && Count < 10);
if (Cache.BrokenCount() != 0)
return _error->Error("Internal Error in pkgMinimizeUpgrade");
/* Protected things are pushed really high up. This number should put them
ahead of everything */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+ {
if ((Flags[I->ID] & Protected) != 0)
Scores[I->ID] += 10000;
+ if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
+ Scores[I->ID] += 5000;
+ }
delete [] OldScores;
}
for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
{
// Compute a single dependency element (glob or)
- pkgCache::DepIterator Start = D;
- pkgCache::DepIterator End = D;
- unsigned char State = 0;
- for (bool LastOR = true; D.end() == false && LastOR == true; D++)
- {
- State |= Cache[D];
- LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
- if (LastOR == true)
- End = D;
- }
+ pkgCache::DepIterator Start;
+ pkgCache::DepIterator End;
+ D.GlobOr(Start,End);
// We only worry about critical deps.
if (End.IsCritical() != true)
// Hm, the group is broken.. I have no idea how to handle this
if (Start != End)
{
- clog << "Note, a broken or group was found in " << I.Name() << "." << endl;
- Cache.MarkDelete(I);
+ if (Debug == true)
+ clog << "Note, a broken or group was found in " << I.Name() << "." << endl;
+ if ((Flags[I->ID] & Protected) != Protected)
+ Cache.MarkDelete(I);
break;
}
if (Debug == true)
clog << "Package " << I.Name() << " has broken dep on " << End.TargetPkg().Name() << endl;
-
- /* Conflicts is simple, decide if we should remove this package
- or the conflicted one */
+
+ /* Look across the version list. If there are no possible
+ targets then we keep the package and bail. This is necessary
+ if a package has a dep on another package that cant be found */
pkgCache::Version **VList = End.AllTargets();
+ if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
+ End->Type != pkgCache::Dep::Conflicts &&
+ Cache[I].NowBroken() == false)
+ {
+ Change = true;
+ Cache.MarkKeep(I);
+ break;
+ }
+
bool Done = false;
for (pkgCache::Version **V = VList; *V != 0; V++)
{
((Cache[End] & pkgDepCache::DepGNow) == 0 &&
End->Type != pkgCache::Dep::Conflicts))
{
+ // Try a little harder to fix protected packages..
if ((Flags[I->ID] & Protected) == Protected)
+ {
+ if (DoUpgrade(Pkg) == true)
+ Scores[Pkg->ID] = Scores[I->ID];
continue;
-
- // See if a keep will do
+ }
+
+ /* See if a keep will do, unless the package is protected,
+ then installing it will be necessary */
Cache.MarkKeep(I);
if (Cache[I].InstBroken() == false)
{
Scores[I->ID] = Scores[Pkg->ID];
}
}
-
+
Change = true;
Done = true;
break;
delete [] PList;
if (Cache.BrokenCount() != 0)
- return _error->Error("Internal error, pkgProblemResolver::Resolve generated breaks.");
-
+ {
+ // See if this is the result of a hold
+ pkgCache::PkgIterator I = Cache.PkgBegin();
+ for (;I.end() != true; I++)
+ {
+ if (Cache[I].InstBroken() == false)
+ continue;
+ if ((Flags[I->ID] & Protected) != Protected)
+ return _error->Error("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.");
+ }
+ return _error->Error("Unable to correct problems, you have held broken packages.");
+ }
+
return true;
}
/*}}}*/