// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: algorithms.cc,v 1.36 2001/05/27 03:46:10 jgg Exp $
+// $Id: algorithms.cc,v 1.44 2002/11/28 18:49:16 jgg Exp $
/* ######################################################################
Algorithms - A set of misc algorithms
#include <apti18n.h>
-#include <iostream.h>
+#include <iostream>
/*}}}*/
+using namespace std;
pkgProblemResolver *pkgProblemResolver::This = 0;
/*}}}*/
// Simulate::Describe - Describe a package /*{{{*/
// ---------------------------------------------------------------------
-/* */
-void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Now)
+/* Parameter Current == true displays the current package version,
+ Parameter Candidate == true displays the candidate package version */
+void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candidate)
{
VerIterator Ver(Sim);
- if (Now == true)
+
+ out << Pkg.Name();
+
+ if (Current == true)
+ {
Ver = Pkg.CurrentVer();
- else
- Ver = Sim[Pkg].CandidateVerIter(Sim);
+ if (Ver.end() == false)
+ out << " [" << Ver.VerStr() << ']';
+ }
- out << Pkg.Name();
-
- if (Ver.end() == true)
- return;
+ if (Candidate == true)
+ {
+ Ver = Sim[Pkg].CandidateVerIter(Sim);
+ if (Ver.end() == true)
+ return;
- out << " (" << Ver.VerStr() << ' ' << Ver.RelStr() << ')';
+ out << " (" << Ver.VerStr() << ' ' << Ver.RelStr() << ')';
+ }
}
/*}}}*/
// Simulate::Install - Simulate unpacking of a package /*{{{*/
Flags[Pkg->ID] = 1;
cout << "Inst ";
- Describe(Pkg,cout,false);
+ Describe(Pkg,cout,true,true);
Sim.MarkInstall(Pkg,false);
// Look for broken conflicts+predepends.
else
{
cout << "Conf ";
- Describe(Pkg,cout,false);
+ Describe(Pkg,cout,false,true);
}
if (Sim.BrokenCount() != 0)
cout << "Purg ";
else
cout << "Remv ";
- Describe(Pkg,cout,false);
+ Describe(Pkg,cout,true,false);
if (Sim.BrokenCount() != 0)
ShortBreaks();
else
{
// Is this right? Will dpkg choke on an upgrade?
- if (Cache[I].CandidateVerIter(Cache).Downloadable() == true)
+ if (Cache[I].CandidateVer != 0 &&
+ Cache[I].CandidateVerIter(Cache).Downloadable() == true)
Cache.MarkInstall(I);
else
return _error->Error(_("The package %s needs to be reinstalled, "
Cache.MarkKeep(I);
else
{
- if (Cache[I].CandidateVerIter(Cache).Downloadable() == true)
+ if (Cache[I].CandidateVer != 0 &&
+ Cache[I].CandidateVerIter(Cache).Downloadable() == true)
Cache.MarkInstall(I);
else
Cache.MarkDelete(I);
Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
/* This helps to fix oddball problems with conflicting packages
- on the same level. We enhance the score of installed packages */
- if (I->CurrentVer != 0)
+ on the same level. We enhance the score of installed packages
+ if those are not obsolete
+ */
+ if (I->CurrentVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable())
Score += 1;
}
{
if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
return false;
+ if ((Flags[Pkg->ID] & Protected) == Protected)
+ return false;
Flags[Pkg->ID] &= ~Upgradable;
continue;
if (Debug == true)
- cout << "Investigating " << I.Name() << endl;
+ clog << "Investigating " << I.Name() << endl;
// Isolate the problem dependency
PackageKill KillList[100];
if (Debug == true)
clog << " Or group remove for " << I.Name() << endl;
Cache.MarkDelete(I);
+ Change = true;
}
}
if (OldEnd == LEnd && OrOp == OrKeep)
if (Debug == true)
clog << " Or group keep for " << I.Name() << endl;
Cache.MarkKeep(I);
+ Change = true;
}
}
D.GlobOr(Start,End);
if (Start.end() == true)
break;
-
+
// We only worry about critical deps.
if (End.IsCritical() != true)
continue;
-
+
InOr = Start != End;
OldEnd = LEnd;
- }
+ }
else
+ {
Start++;
-
+ // We only worry about critical deps.
+ if (Start.IsCritical() != true)
+ continue;
+ }
+
// Dep is ok
if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
+ {
+ InOr = false;
continue;
-
+ }
+
if (Debug == true)
clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl;
// Isolate the problem dependencies
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;
- }
-
+ DepIterator Start;
+ DepIterator End;
+ D.GlobOr(Start,End);
+
// We only worry about critical deps.
if (End.IsCritical() != true)
continue;
// Dep is ok
if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
continue;
-
- // 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;
- if ((Flags[I->ID] & Protected) == 0)
- Cache.MarkKeep(I);
- break;
- }
-
- if (Debug == true)
- clog << "Package " << I.Name() << " has broken dep on " << End.TargetPkg().Name() << endl;
-
- // Look at all the possible provides on this package
- SPtrArray<pkgCache::Version *> VList = End.AllTargets();
- for (pkgCache::Version **V = VList; *V != 0; V++)
+
+ /* Hm, the group is broken.. I suppose the best thing to do is to
+ is to try every combination of keep/not-keep for the set, but thats
+ slow, and this never happens, just be conservative and assume the
+ list of ors is in preference and keep till it starts to work. */
+ while (true)
{
- pkgCache::VerIterator Ver(Cache,*V);
- pkgCache::PkgIterator Pkg = Ver.ParentPkg();
-
- // It is not keepable
- if (Cache[Pkg].InstallVer == 0 ||
- Pkg->CurrentVer == 0)
- continue;
+ if (Debug == true)
+ clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl;
- if ((Flags[I->ID] & Protected) == 0)
+ // Look at all the possible provides on this package
+ SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
+ for (pkgCache::Version **V = VList; *V != 0; V++)
{
- if (Debug == true)
- clog << " Keeping Package " << Pkg.Name() << " due to dep" << endl;
- Cache.MarkKeep(Pkg);
+ pkgCache::VerIterator Ver(Cache,*V);
+ pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+
+ // It is not keepable
+ if (Cache[Pkg].InstallVer == 0 ||
+ Pkg->CurrentVer == 0)
+ continue;
+
+ if ((Flags[I->ID] & Protected) == 0)
+ {
+ if (Debug == true)
+ clog << " Keeping Package " << Pkg.Name() << " due to dep" << endl;
+ Cache.MarkKeep(Pkg);
+ }
+
+ if (Cache[I].InstBroken() == false)
+ break;
}
if (Cache[I].InstBroken() == false)
break;
- }
+ if (Start == End)
+ break;
+ Start++;
+ }
+
if (Cache[I].InstBroken() == false)
break;
}
pkgCache::VerIterator R(*PrioCache,*(pkgCache::Version **)B);
if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential &&
- (L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
- return 1;
+ (R.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
+ return 1;
if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
- (L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
- return -1;
+ (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
+ return -1;
if (L->Priority != R->Priority)
- return L->Priority - R->Priority;
+ return R->Priority - L->Priority;
return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
}
void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)