// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: algorithms.cc,v 1.39 2002/04/02 05:55:24 jgg Exp $
+// $Id: algorithms.cc,v 1.44 2002/11/28 18:49:16 jgg Exp $
/* ######################################################################
Algorithms - A set of misc algorithms
#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();
{
if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
return false;
+ if ((Flags[Pkg->ID] & Protected) == Protected)
+ return false;
Flags[Pkg->ID] &= ~Upgradable;
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++;
-
+
// 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;
return _error->Error(_("Unable to correct problems, you have held broken packages."));
}
+ // set the auto-flags (mvo: I'm not sure if we _really_ need this, but
+ // I didn't managed
+ pkgCache::PkgIterator I = Cache.PkgBegin();
+ for (;I.end() != true; I++) {
+ if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
+ std::cout << "Resolve installed new pkg: " << I.Name() << " (now marking it as auto)" << std::endl;
+ Cache[I].Flags |= pkgCache::Flag::Auto;
+ }
+ }
+
+
return true;
}
/*}}}*/
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)
qsort(List,Count,sizeof(*List),PrioComp);
}
/*}}}*/
+
+
+// pkgMarkPkgUsed - Mark used packages as dirty /*{{{*/
+// ---------------------------------------------------------------------
+/* Mark all reachable packages as dirty. */
+void pkgMarkPkgUsed(pkgDepCache &Cache, pkgCache::PkgIterator Pkg,
+ pkgCache::State::PkgRemoveState DirtLevel)
+{
+ // If it is not installed, and we are in manual mode, ignore it
+ if ((Pkg->CurrentVer == 0 && Cache[Pkg].Install() == false || Cache[Pkg].Delete() == true) &&
+ DirtLevel == pkgCache::State::RemoveManual)
+ {
+// fprintf(stdout,"This one is not installed/virtual %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+ return;
+ }
+
+ // If it is not installed, and it is not virtual, ignore it
+ if ((Pkg->CurrentVer == 0 && Cache[Pkg].Install() == false || Cache[Pkg].Delete() == true) &&
+ Pkg->VersionList != 0)
+ {
+// fprintf(stdout,"This one is not installed %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+ return;
+ }
+
+ // If it is similar or more dirty than we are ;-), because we've been here already, don't mark it
+ // This is necessary because virtual packages just relay the current level,
+ // so it may be possible e.g. that this was already seen with ::RemoveSuggested, but
+ // we are ::RemoveRequired
+ if (Cache[Pkg].Dirty() >= DirtLevel)
+ {
+ //fprintf(stdout,"Seen already %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+ return;
+ }
+
+ // If it is less important than the current DirtLevel, don't mark it
+ if (Cache[Pkg].AutomaticRemove != pkgCache::State::RemoveManual &&
+ Cache[Pkg].AutomaticRemove > DirtLevel)
+ {
+// fprintf(stdout,"We don't need %s %d %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel, Cache[Pkg].Dirty());
+ return;
+ }
+
+ // Mark it as used
+ Cache.SetDirty(Pkg, DirtLevel);
+
+ //fprintf(stdout,"We keep %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+
+ // We are a virtual package
+ if (Pkg->VersionList == 0)
+ {
+// fprintf(stdout,"We are virtual %s %d %d\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+ for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); ! Prv.end(); ++Prv)
+ pkgMarkPkgUsed (Cache, Prv.OwnerPkg(), DirtLevel);
+ return;
+ }
+
+ // Depending on the type of dependency, follow it
+ for (pkgCache::DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); ! D.end(); ++D)
+ {
+// fprintf(stdout,"We depend on %s %s\n", D.TargetPkg().Name(), D.DepType());
+
+ switch(D->Type)
+ {
+ case pkgCache::Dep::Depends:
+ case pkgCache::Dep::PreDepends:
+ pkgMarkPkgUsed (Cache, D.TargetPkg(), pkgCache::State::RemoveRequired);
+ break;
+ case pkgCache::Dep::Recommends:
+ pkgMarkPkgUsed (Cache, D.TargetPkg(), pkgCache::State::RemoveRecommended);
+ break;
+ case pkgCache::Dep::Suggests:
+ pkgMarkPkgUsed (Cache, D.TargetPkg(), pkgCache::State::RemoveSuggested);
+ break;
+ case pkgCache::Dep::Conflicts:
+ case pkgCache::Dep::Replaces:
+ case pkgCache::Dep::Obsoletes:
+ // We don't handle these here
+ break;
+ }
+ }
+// fprintf(stdout,"We keep %s %d %d <END>\n", Pkg.Name(), Pkg->AutomaticRemove, DirtLevel);
+}
+ /*}}}*/
+
+bool pkgMarkUsed(pkgDepCache &Cache)
+{
+ // debug only
+ for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); ! Pkg.end(); ++Pkg)
+ if(!Cache[Pkg].Dirty() && Cache[Pkg].AutomaticRemove > 0)
+ std::cout << "has auto-remove information: " << Pkg.Name()
+ << " " << (int)Cache[Pkg].AutomaticRemove
+ << std::endl;
+
+ // init with defaults
+ for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); ! Pkg.end(); ++Pkg)
+ Cache.SetDirty(Pkg, pkgCache::State::RemoveUnknown);
+
+ // go recursive over the cache
+ for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); ! Pkg.end(); ++Pkg)
+ pkgMarkPkgUsed (Cache, Pkg, pkgCache::State::RemoveManual);
+
+
+ return true;
+}