#include <apt-pkg/version.h>
#include <apt-pkg/sptr.h>
#include <apt-pkg/acquire-item.h>
-
+#include <apt-pkg/edspwriter.h>
+
#include <apti18n.h>
#include <sys/types.h>
#include <cstdlib>
#include <algorithm>
#include <iostream>
+
+#include <stdio.h>
/*}}}*/
using namespace std;
Describe(Pkg,cout,true,true);
Sim.MarkInstall(Pkg,false);
- if (strcmp(Pkg.Arch(),"all") == 0)
- {
- pkgCache::GrpIterator G = Pkg.Group();
- pkgCache::GrpIterator iG = iPkg.Group();
- for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P))
- {
- if (strcmp(P.Arch(), "all") == 0)
- continue;
- if (iG.FindPkg(P.Arch())->CurrentVer == 0)
- continue;
- Flags[P->ID] = 1;
- Sim.MarkInstall(P, false);
- }
- }
-
// Look for broken conflicts+predepends.
for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
{
Flags[Pkg->ID] = 2;
- if (strcmp(Pkg.Arch(),"all") == 0)
- {
- pkgCache::GrpIterator G = Pkg.Group();
- for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P))
- {
- if (strcmp(P.Arch(), "all") == 0)
- continue;
- if (Flags[P->ID] == 1)
- Flags[P->ID] = 2;
- }
- }
-
-// Sim.MarkInstall(Pkg,false);
if (Sim[Pkg].InstBroken() == true)
{
cout << "Conf " << Pkg.FullName(false) << " broken" << endl;
}
cout << endl;
- _error->Error("Conf Broken %s",Pkg.FullName(false));
+ _error->Error("Conf Broken %s",Pkg.FullName(false).c_str());
}
else
{
Flags[Pkg->ID] = 3;
Sim.MarkDelete(Pkg);
- if (strcmp(Pkg.Arch(),"all") == 0)
- {
- pkgCache::GrpIterator G = Pkg.Group();
- pkgCache::GrpIterator iG = iPkg.Group();
- for (pkgCache::PkgIterator P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P))
- {
- if (strcmp(P.Arch(), "all") == 0)
- continue;
- if (iG.FindPkg(P.Arch())->CurrentVer == 0)
- continue;
- Flags[P->ID] = 3;
- Sim.MarkDelete(P);
- }
- }
-
if (Purge == true)
cout << "Purg ";
else
Cache.MarkInstall(I, false, 0, false);
else
return _error->Error(_("The package %s needs to be reinstalled, "
- "but I can't find an archive for it."),I.FullName(true));
+ "but I can't find an archive for it."),I.FullName(true).c_str());
}
continue;
default:
if (I->InstState != pkgCache::State::Ok)
return _error->Error("The package %s is not ok and I "
- "don't know how to fix it!",I.FullName(false));
+ "don't know how to fix it!",I.FullName(false).c_str());
}
}
return true;
{
pkgDepCache::ActionGroup group(Cache);
+ /* Upgrade all installed packages first without autoinst to help the resolver
+ in versioned or-groups to upgrade the old solver instead of installing
+ a new one (if the old solver is not the first one [anymore]) */
+ for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+ if (I->CurrentVer != 0)
+ Cache.MarkInstall(I, false, 0, false);
+
/* Auto upgrade all installed packages, this provides the basis
for the installation */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
return true;
}
/*}}}*/
-// ProblemResolver::Resolve - Run the resolution pass /*{{{*/
+// ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgProblemResolver::Resolve(bool BrokenFix)
+{
+ std::string const solver = _config->Find("APT::Solver::Name", "internal");
+ if (solver != "internal")
+ {
+ FILE* output = fopen("/tmp/scenario.log", "w");
+ edspWriter::WriteScenario(Cache, output);
+ fclose(output);
+ output = fopen("/tmp/request.log", "w");
+ edspWriter::WriteRequest(Cache, output);
+ fclose(output);
+ if (ResolveInternal(BrokenFix) == false)
+ return false;
+ output = fopen("/tmp/solution.log", "w");
+ edspWriter::WriteSolution(Cache, output);
+ fclose(output);
+ return true;
+ }
+ return ResolveInternal(BrokenFix);
+}
+ /*}}}*/
+// ProblemResolver::ResolveInternal - Run the resolution pass /*{{{*/
// ---------------------------------------------------------------------
/* This routines works by calculating a score for each package. The score
is derived by considering the package's priority and all reverse
The BrokenFix flag enables a mode where the algorithm tries to
upgrade packages to advoid problems. */
-bool pkgProblemResolver::Resolve(bool BrokenFix)
+bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
{
pkgDepCache::ActionGroup group(Cache);
- unsigned long Size = Cache.Head().PackageCount;
-
// Record which packages are marked for install
bool Again = false;
do
clog << "Starting" << endl;
MakeScores();
-
+
+ unsigned long const Size = Cache.Head().PackageCount;
+
/* We have to order the packages so that the broken fixing pass
operates from highest score to lowest. This prevents problems when
high score packages cause the removal of lower score packages that
not be possible for a loop to form (that is a < b < c and fixing b by
changing a breaks c) */
bool Change = true;
+ bool const TryFixByInstall = _config->FindB("pkgProblemResolver::FixByInstall", true);
for (int Counter = 0; Counter != 10 && Change == true; Counter++)
{
Change = false;
(Flags[I->ID] & ReInstateTried) == 0)
{
if (Debug == true)
- clog << " Try to Re-Instate " << I.FullName(false) << endl;
+ clog << " Try to Re-Instate (" << Counter << ") " << I.FullName(false) << endl;
unsigned long OldBreaks = Cache.BrokenCount();
pkgCache::Version *OldVer = Cache[I].InstallVer;
Flags[I->ID] &= ReInstateTried;
continue;
if (Debug == true)
- clog << "Investigating " << I << endl;
+ clog << "Investigating (" << Counter << ") " << I << endl;
// Isolate the problem dependency
PackageKill KillList[100];
if (Start == End)
{
// Decide what to do
- if (InOr == true)
+ if (InOr == true && OldEnd == LEnd)
{
- if (OldEnd == LEnd && OrOp == OrRemove)
+ if (OrOp == OrRemove)
{
if ((Flags[I->ID] & Protected) != Protected)
{
clog << " Or group remove for " << I.FullName(false) << endl;
Cache.MarkDelete(I);
Change = true;
- }
- }
- if (OldEnd == LEnd && OrOp == OrKeep)
+ }
+ }
+ else if (OrOp == OrKeep)
{
if (Debug == true)
clog << " Or group keep for " << I.FullName(false) << endl;
pkgCache::VerIterator Ver(Cache,*V);
pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+ /* This is a conflicts, and the version we are looking
+ at is not the currently selected version of the
+ package, which means it is not necessary to
+ remove/keep */
+ if (Cache[Pkg].InstallVer != Ver &&
+ (Start->Type == pkgCache::Dep::Conflicts ||
+ Start->Type == pkgCache::Dep::DpkgBreaks ||
+ Start->Type == pkgCache::Dep::Obsoletes))
+ {
+ if (Debug)
+ clog << " Conflicts//Breaks against version "
+ << Ver.VerStr() << " for " << Pkg.Name()
+ << " but that is not InstVer, ignoring"
+ << endl;
+ continue;
+ }
+
if (Debug == true)
clog << " Considering " << Pkg.FullName(false) << ' ' << (int)Scores[Pkg->ID] <<
" as a solution to " << I.FullName(false) << ' ' << (int)Scores[I->ID] << endl;
if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID])
Scores[I->ID] = Scores[Pkg->ID];
}
+ else if (TryFixByInstall == true &&
+ Start.TargetPkg()->CurrentVer == 0 &&
+ Cache[Start.TargetPkg()].Delete() == false &&
+ (Flags[Start.TargetPkg()->ID] & ToRemove) != ToRemove &&
+ Cache.GetCandidateVer(Start.TargetPkg()).end() == false)
+ {
+ /* Before removing or keeping the package with the broken dependency
+ try instead to install the first not previously installed package
+ solving this dependency. This helps every time a previous solver
+ is removed by the resolver because of a conflict or alike but it is
+ dangerous as it could trigger new breaks/conflicts… */
+ if (Debug == true)
+ clog << " Try Installing " << Start.TargetPkg() << " before changing " << I.FullName(false) << std::endl;
+ unsigned long const OldBroken = Cache.BrokenCount();
+ Cache.MarkInstall(Start.TargetPkg(), true, 1, false);
+ // FIXME: we should undo the complete MarkInstall process here
+ if (Cache[Start.TargetPkg()].InstBroken() == true || Cache.BrokenCount() > OldBroken)
+ Cache.MarkDelete(Start.TargetPkg(), false, 1, false);
+ }
}
}
}
else
{
- /* This is a conflicts, and the version we are looking
- at is not the currently selected version of the
- package, which means it is not necessary to
- remove/keep */
- if (Cache[Pkg].InstallVer != Ver &&
- (Start->Type == pkgCache::Dep::Conflicts ||
- Start->Type == pkgCache::Dep::Obsoletes))
- continue;
-
if (Start->Type == pkgCache::Dep::DpkgBreaks)
{
// first, try upgradring the package, if that
// does not help, the breaks goes onto the
// kill list
+ //
// FIXME: use DoUpgrade(Pkg) instead?
- if (Cache[End] & pkgDepCache::DepGCVer)
+ if (Cache[End] & pkgDepCache::DepGCVer)
{
if (Debug)
clog << " Upgrading " << Pkg.FullName(false) << " due to Breaks field in " << I.FullName(false) << endl;
// Restart again.
if (K == LastStop)
- return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.FullName(false));
+ return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.FullName(false).c_str());
LastStop = K;
K = PList - 1;
}
}
if (TransientNetworkFailure == true)
- _error->Warning(_("Some index files failed to download, they have been ignored, or old ones used instead."));
+ _error->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead."));
else if (Failed == true)
- return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead."));
+ return _error->Error(_("Some index files failed to download. They have been ignored, or old ones used instead."));
// Run the success scripts if all was fine