]> git.saurik.com Git - apt.git/blame - apt-pkg/algorithms.cc
eipp: let apt make a plan, not make stuff plane
[apt.git] / apt-pkg / algorithms.cc
CommitLineData
6c139d6e
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
b8c0f9b7 3// $Id: algorithms.cc,v 1.44 2002/11/28 18:49:16 jgg Exp $
6c139d6e
AL
4/* ######################################################################
5
6 Algorithms - A set of misc algorithms
7
0a8e3465
AL
8 The pkgProblemResolver class has become insanely complex and
9 very sophisticated, it handles every test case I have thrown at it
10 to my satisfaction. Understanding exactly why all the steps the class
11 does are required is difficult and changing though not very risky
12 may result in other cases not working.
13
6c139d6e
AL
14 ##################################################################### */
15 /*}}}*/
16// Include Files /*{{{*/
ea542140
DK
17#include <config.h>
18
094a497d
AL
19#include <apt-pkg/algorithms.h>
20#include <apt-pkg/error.h>
0a8e3465 21#include <apt-pkg/configuration.h>
c3b85126 22#include <apt-pkg/edsp.h>
453b82a3
DK
23#include <apt-pkg/depcache.h>
24#include <apt-pkg/packagemanager.h>
25#include <apt-pkg/pkgcache.h>
26#include <apt-pkg/cacheiterators.h>
84573326 27#include <apt-pkg/prettyprinters.h>
6d38011b 28
453b82a3
DK
29#include <string.h>
30#include <string>
152ab79e 31#include <cstdlib>
90f057fd 32#include <iostream>
ea542140
DK
33
34#include <apti18n.h>
6c139d6e 35 /*}}}*/
584e4558 36using namespace std;
6c139d6e 37
6c139d6e
AL
38// Simulate::Simulate - Constructor /*{{{*/
39// ---------------------------------------------------------------------
b2e465d6
AL
40/* The legacy translations here of input Pkg iterators is obsolete,
41 this is not necessary since the pkgCaches are fully shared now. */
42pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache),
6c55f07a 43 d(NULL), iPolicy(Cache),
496d5c70
MV
44 Sim(&Cache->GetCache(),&iPolicy),
45 group(Sim)
6c139d6e 46{
b2e465d6
AL
47 Sim.Init(0);
48 Flags = new unsigned char[Cache->Head().PackageCount];
49 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
281daf46
AL
50
51 // Fake a filename so as not to activate the media swapping
52 string Jnk = "SIMULATE";
b2e465d6 53 for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
281daf46 54 FileNames[I] = Jnk;
6c139d6e
AL
55}
56 /*}}}*/
b270388b
MV
57// Simulate::~Simulate - Destructor /*{{{*/
58pkgSimulate::~pkgSimulate()
59{
60 delete[] Flags;
61}
62 /*}}}*/
b2e465d6
AL
63// Simulate::Describe - Describe a package /*{{{*/
64// ---------------------------------------------------------------------
3826564e
MZ
65/* Parameter Current == true displays the current package version,
66 Parameter Candidate == true displays the candidate package version */
67void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candidate)
b2e465d6
AL
68{
69 VerIterator Ver(Sim);
e59458f7 70
47f6d1b7 71 out << Pkg.FullName(true);
e59458f7 72
3826564e 73 if (Current == true)
e59458f7 74 {
b2e465d6 75 Ver = Pkg.CurrentVer();
e59458f7
AL
76 if (Ver.end() == false)
77 out << " [" << Ver.VerStr() << ']';
78 }
b2e465d6 79
3826564e
MZ
80 if (Candidate == true)
81 {
82 Ver = Sim[Pkg].CandidateVerIter(Sim);
83 if (Ver.end() == true)
84 return;
b2e465d6 85
3826564e
MZ
86 out << " (" << Ver.VerStr() << ' ' << Ver.RelStr() << ')';
87 }
b2e465d6
AL
88}
89 /*}}}*/
6c139d6e
AL
90// Simulate::Install - Simulate unpacking of a package /*{{{*/
91// ---------------------------------------------------------------------
92/* */
93bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
94{
95 // Adapt the iterator
803ea2a8 96 PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
6c139d6e
AL
97 Flags[Pkg->ID] = 1;
98
b2e465d6 99 cout << "Inst ";
3826564e 100 Describe(Pkg,cout,true,true);
6c139d6e 101 Sim.MarkInstall(Pkg,false);
803ea2a8 102
6c139d6e 103 // Look for broken conflicts+predepends.
f7f0d6c7 104 for (PkgIterator I = Sim.PkgBegin(); I.end() == false; ++I)
6c139d6e
AL
105 {
106 if (Sim[I].InstallVer == 0)
107 continue;
108
b2e465d6
AL
109 for (DepIterator D = Sim[I].InstVerIter(Sim).DependsList(); D.end() == false;)
110 {
111 DepIterator Start;
112 DepIterator End;
113 D.GlobOr(Start,End);
359e46db 114 if (Start.IsNegative() == true ||
b2e465d6 115 End->Type == pkgCache::Dep::PreDepends)
6c139d6e 116 {
b2e465d6 117 if ((Sim[End] & pkgDepCache::DepGInstall) == 0)
6c139d6e 118 {
47f6d1b7 119 cout << " [" << I.FullName(false) << " on " << Start.TargetPkg().FullName(false) << ']';
b2e465d6 120 if (Start->Type == pkgCache::Dep::Conflicts)
47f6d1b7 121 _error->Error("Fatal, conflicts violated %s",I.FullName(false).c_str());
6c139d6e 122 }
b2e465d6
AL
123 }
124 }
6c139d6e
AL
125 }
126
127 if (Sim.BrokenCount() != 0)
128 ShortBreaks();
129 else
04aa15a8 130 cout << endl;
6c139d6e
AL
131 return true;
132}
133 /*}}}*/
134// Simulate::Configure - Simulate configuration of a Package /*{{{*/
135// ---------------------------------------------------------------------
136/* This is not an acurate simulation of relatity, we should really not
137 install the package.. For some investigations it may be necessary
138 however. */
139bool pkgSimulate::Configure(PkgIterator iPkg)
140{
141 // Adapt the iterator
803ea2a8 142 PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
6c139d6e
AL
143
144 Flags[Pkg->ID] = 2;
803ea2a8 145
6c139d6e
AL
146 if (Sim[Pkg].InstBroken() == true)
147 {
47f6d1b7 148 cout << "Conf " << Pkg.FullName(false) << " broken" << endl;
6c139d6e
AL
149
150 Sim.Update();
151
152 // Print out each package and the failed dependencies
f7f0d6c7 153 for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; ++D)
6c139d6e
AL
154 {
155 if (Sim.IsImportantDep(D) == false ||
156 (Sim[D] & pkgDepCache::DepInstall) != 0)
157 continue;
158
b2e465d6 159 if (D->Type == pkgCache::Dep::Obsoletes)
47f6d1b7 160 cout << " Obsoletes:" << D.TargetPkg().FullName(false);
b2e465d6 161 else if (D->Type == pkgCache::Dep::Conflicts)
47f6d1b7 162 cout << " Conflicts:" << D.TargetPkg().FullName(false);
308c7d30 163 else if (D->Type == pkgCache::Dep::DpkgBreaks)
47f6d1b7 164 cout << " Breaks:" << D.TargetPkg().FullName(false);
6c139d6e 165 else
47f6d1b7 166 cout << " Depends:" << D.TargetPkg().FullName(false);
6c139d6e 167 }
04aa15a8 168 cout << endl;
6c139d6e 169
09a10f9c 170 _error->Error("Conf Broken %s",Pkg.FullName(false).c_str());
6c139d6e
AL
171 }
172 else
b2e465d6
AL
173 {
174 cout << "Conf ";
3826564e 175 Describe(Pkg,cout,false,true);
b2e465d6 176 }
6c139d6e
AL
177
178 if (Sim.BrokenCount() != 0)
179 ShortBreaks();
180 else
04aa15a8 181 cout << endl;
6c139d6e
AL
182
183 return true;
184}
185 /*}}}*/
186// Simulate::Remove - Simulate the removal of a package /*{{{*/
187// ---------------------------------------------------------------------
188/* */
fc4b5c9f 189bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
6c139d6e
AL
190{
191 // Adapt the iterator
803ea2a8 192 PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
c919ad6e
DK
193 if (Pkg.end() == true)
194 {
195 std::cerr << (Purge ? "Purg" : "Remv") << " invalid package " << iPkg.FullName() << std::endl;
196 return false;
197 }
6c139d6e
AL
198
199 Flags[Pkg->ID] = 3;
200 Sim.MarkDelete(Pkg);
803ea2a8 201
fc4b5c9f 202 if (Purge == true)
b2e465d6 203 cout << "Purg ";
fc4b5c9f 204 else
b2e465d6 205 cout << "Remv ";
3826564e 206 Describe(Pkg,cout,true,false);
6c139d6e
AL
207
208 if (Sim.BrokenCount() != 0)
209 ShortBreaks();
210 else
04aa15a8 211 cout << endl;
6c139d6e
AL
212
213 return true;
214}
215 /*}}}*/
216// Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
217// ---------------------------------------------------------------------
218/* */
219void pkgSimulate::ShortBreaks()
220{
04aa15a8 221 cout << " [";
f7f0d6c7 222 for (PkgIterator I = Sim.PkgBegin(); I.end() == false; ++I)
6c139d6e
AL
223 {
224 if (Sim[I].InstBroken() == true)
225 {
226 if (Flags[I->ID] == 0)
47f6d1b7 227 cout << I.FullName(false) << ' ';
6c139d6e 228/* else
04aa15a8 229 cout << I.Name() << "! ";*/
6c139d6e
AL
230 }
231 }
04aa15a8 232 cout << ']' << endl;
6c139d6e
AL
233}
234 /*}}}*/
235// ApplyStatus - Adjust for non-ok packages /*{{{*/
236// ---------------------------------------------------------------------
237/* We attempt to change the state of the all packages that have failed
238 installation toward their real state. The ordering code will perform
239 the necessary calculations to deal with the problems. */
240bool pkgApplyStatus(pkgDepCache &Cache)
241{
74a05226
MV
242 pkgDepCache::ActionGroup group(Cache);
243
f7f0d6c7 244 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
6c139d6e 245 {
e481d5b0
AL
246 if (I->VersionList == 0)
247 continue;
248
d38b7b3d
AL
249 // Only choice for a ReInstReq package is to reinstall
250 if (I->InstState == pkgCache::State::ReInstReq ||
251 I->InstState == pkgCache::State::HoldReInstReq)
252 {
5871718b 253 if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
74a05226 254 Cache.MarkKeep(I, false, false);
813c8eea
AL
255 else
256 {
257 // Is this right? Will dpkg choke on an upgrade?
2a3f3893
AL
258 if (Cache[I].CandidateVer != 0 &&
259 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
74a05226 260 Cache.MarkInstall(I, false, 0, false);
813c8eea 261 else
b2e465d6 262 return _error->Error(_("The package %s needs to be reinstalled, "
09a10f9c 263 "but I can't find an archive for it."),I.FullName(true).c_str());
813c8eea
AL
264 }
265
d38b7b3d
AL
266 continue;
267 }
268
6c139d6e
AL
269 switch (I->CurrentState)
270 {
813c8eea
AL
271 /* This means installation failed somehow - it does not need to be
272 re-unpacked (probably) */
b518cca6
AL
273 case pkgCache::State::UnPacked:
274 case pkgCache::State::HalfConfigured:
9d06bc80
MV
275 case pkgCache::State::TriggersAwaited:
276 case pkgCache::State::TriggersPending:
5871718b 277 if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) ||
813c8eea 278 I.State() != pkgCache::PkgIterator::NeedsUnpack)
74a05226 279 Cache.MarkKeep(I, false, false);
813c8eea
AL
280 else
281 {
2a3f3893
AL
282 if (Cache[I].CandidateVer != 0 &&
283 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
74a05226 284 Cache.MarkInstall(I, true, 0, false);
813c8eea 285 else
b83cad32 286 Cache.MarkDelete(I, false, 0, false);
813c8eea 287 }
6c139d6e
AL
288 break;
289
290 // This means removal failed
b518cca6 291 case pkgCache::State::HalfInstalled:
b83cad32 292 Cache.MarkDelete(I, false, 0, false);
6c139d6e
AL
293 break;
294
295 default:
b518cca6 296 if (I->InstState != pkgCache::State::Ok)
6c139d6e 297 return _error->Error("The package %s is not ok and I "
09a10f9c 298 "don't know how to fix it!",I.FullName(false).c_str());
6c139d6e
AL
299 }
300 }
301 return true;
302}
303 /*}}}*/
304// FixBroken - Fix broken packages /*{{{*/
305// ---------------------------------------------------------------------
0a8e3465
AL
306/* This autoinstalls every broken package and then runs the problem resolver
307 on the result. */
6c139d6e
AL
308bool pkgFixBroken(pkgDepCache &Cache)
309{
74a05226
MV
310 pkgDepCache::ActionGroup group(Cache);
311
6c139d6e 312 // Auto upgrade all broken packages
f7f0d6c7 313 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
6c139d6e 314 if (Cache[I].NowBroken() == true)
74a05226 315 Cache.MarkInstall(I, true, 0, false);
7e798dd7 316
6c139d6e
AL
317 /* Fix packages that are in a NeedArchive state but don't have a
318 downloadable install version */
f7f0d6c7 319 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
6c139d6e
AL
320 {
321 if (I.State() != pkgCache::PkgIterator::NeedsUnpack ||
322 Cache[I].Delete() == true)
323 continue;
324
b518cca6 325 if (Cache[I].InstVerIter(Cache).Downloadable() == false)
6c139d6e
AL
326 continue;
327
74a05226 328 Cache.MarkInstall(I, true, 0, false);
6c139d6e
AL
329 }
330
b2e465d6 331 pkgProblemResolver Fix(&Cache);
6c139d6e
AL
332 return Fix.Resolve(true);
333}
334 /*}}}*/
6c139d6e
AL
335// ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
336// ---------------------------------------------------------------------
337/* */
dcaa1185 338pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : d(NULL), Cache(*pCache)
6c139d6e
AL
339{
340 // Allocate memory
b2e465d6 341 unsigned long Size = Cache.Head().PackageCount;
d0f2c87c 342 Scores = new int[Size];
6c139d6e
AL
343 Flags = new unsigned char[Size];
344 memset(Flags,0,sizeof(*Flags)*Size);
345
346 // Set debug to true to see its decision logic
0a8e3465 347 Debug = _config->FindB("Debug::pkgProblemResolver",false);
6c139d6e
AL
348}
349 /*}}}*/
b2e465d6
AL
350// ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
351// ---------------------------------------------------------------------
352/* */
353pkgProblemResolver::~pkgProblemResolver()
354{
355 delete [] Scores;
356 delete [] Flags;
357}
358 /*}}}*/
6c139d6e
AL
359// ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
360// ---------------------------------------------------------------------
361/* */
f1f9f9bf 362int pkgProblemResolver::ScoreSort(Package const *A,Package const *B)
6c139d6e 363{
f1f9f9bf 364 if (Scores[A->ID] > Scores[B->ID])
6c139d6e 365 return -1;
f1f9f9bf 366 if (Scores[A->ID] < Scores[B->ID])
6c139d6e
AL
367 return 1;
368 return 0;
369}
370 /*}}}*/
371// ProblemResolver::MakeScores - Make the score table /*{{{*/
372// ---------------------------------------------------------------------
373/* */
374void pkgProblemResolver::MakeScores()
375{
b2e465d6 376 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
377 memset(Scores,0,sizeof(*Scores)*Size);
378
b9179170
MV
379 // maps to pkgCache::State::VerPriority:
380 // Required Important Standard Optional Extra
d0f2c87c 381 int PrioMap[] = {
8b4894fe 382 0,
84de0cea 383 _config->FindI("pkgProblemResolver::Scores::Required",3),
b9179170 384 _config->FindI("pkgProblemResolver::Scores::Important",2),
d0f2c87c
CW
385 _config->FindI("pkgProblemResolver::Scores::Standard",1),
386 _config->FindI("pkgProblemResolver::Scores::Optional",-1),
387 _config->FindI("pkgProblemResolver::Scores::Extra",-2)
8b4894fe 388 };
d0f2c87c
CW
389 int PrioEssentials = _config->FindI("pkgProblemResolver::Scores::Essentials",100);
390 int PrioInstalledAndNotObsolete = _config->FindI("pkgProblemResolver::Scores::NotObsolete",1);
8daf68e3
DK
391 int DepMap[] = {
392 0,
393 _config->FindI("pkgProblemResolver::Scores::Depends",1),
394 _config->FindI("pkgProblemResolver::Scores::PreDepends",1),
395 _config->FindI("pkgProblemResolver::Scores::Suggests",0),
396 _config->FindI("pkgProblemResolver::Scores::Recommends",1),
397 _config->FindI("pkgProblemResolver::Scores::Conflicts",-1),
398 _config->FindI("pkgProblemResolver::Scores::Replaces",0),
399 _config->FindI("pkgProblemResolver::Scores::Obsoletes",0),
400 _config->FindI("pkgProblemResolver::Scores::Breaks",-1),
401 _config->FindI("pkgProblemResolver::Scores::Enhances",0)
402 };
d0f2c87c
CW
403 int AddProtected = _config->FindI("pkgProblemResolver::Scores::AddProtected",10000);
404 int AddEssential = _config->FindI("pkgProblemResolver::Scores::AddEssential",5000);
8b4894fe
MV
405
406 if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
407 clog << "Settings used to calculate pkgProblemResolver::Scores::" << endl
84de0cea
MV
408 << " Required => " << PrioMap[pkgCache::State::Required] << endl
409 << " Important => " << PrioMap[pkgCache::State::Important] << endl
410 << " Standard => " << PrioMap[pkgCache::State::Standard] << endl
411 << " Optional => " << PrioMap[pkgCache::State::Optional] << endl
412 << " Extra => " << PrioMap[pkgCache::State::Extra] << endl
8b4894fe
MV
413 << " Essentials => " << PrioEssentials << endl
414 << " InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete << endl
8daf68e3
DK
415 << " Pre-Depends => " << DepMap[pkgCache::Dep::PreDepends] << endl
416 << " Depends => " << DepMap[pkgCache::Dep::Depends] << endl
417 << " Recommends => " << DepMap[pkgCache::Dep::Recommends] << endl
418 << " Suggests => " << DepMap[pkgCache::Dep::Suggests] << endl
419 << " Conflicts => " << DepMap[pkgCache::Dep::Conflicts] << endl
420 << " Breaks => " << DepMap[pkgCache::Dep::DpkgBreaks] << endl
421 << " Replaces => " << DepMap[pkgCache::Dep::Replaces] << endl
422 << " Obsoletes => " << DepMap[pkgCache::Dep::Obsoletes] << endl
423 << " Enhances => " << DepMap[pkgCache::Dep::Enhances] << endl
8b4894fe
MV
424 << " AddProtected => " << AddProtected << endl
425 << " AddEssential => " << AddEssential << endl;
426
6c139d6e 427 // Generate the base scores for a package based on its properties
f7f0d6c7 428 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
6c139d6e
AL
429 {
430 if (Cache[I].InstallVer == 0)
431 continue;
432
d0f2c87c 433 int &Score = Scores[I->ID];
6c139d6e 434
7365ff46 435 /* This is arbitrary, it should be high enough to elevate an
6c139d6e
AL
436 essantial package above most other packages but low enough
437 to allow an obsolete essential packages to be removed by
1e3f4083 438 a conflicts on a powerful normal package (ie libc6) */
c5200869
JAK
439 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential
440 || (I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
8b4894fe 441 Score += PrioEssentials;
6c139d6e 442
4cd4a2e7
DK
443 pkgCache::VerIterator const InstVer = Cache[I].InstVerIter(Cache);
444 // We apply priorities only to downloadable packages, all others are prio:extra
445 // as an obsolete prio:standard package can't be that standard anymore…
446 if (InstVer->Priority <= pkgCache::State::Extra && InstVer.Downloadable() == true)
447 Score += PrioMap[InstVer->Priority];
448 else
449 Score += PrioMap[pkgCache::State::Extra];
450
6c139d6e 451 /* This helps to fix oddball problems with conflicting packages
4cd4a2e7
DK
452 on the same level. We enhance the score of installed packages
453 if those are not obsolete */
020daa7b 454 if (I->CurrentVer != 0 && Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable())
8b4894fe 455 Score += PrioInstalledAndNotObsolete;
8daf68e3 456
cb4b85b0 457 // propagate score points along dependencies
4cd4a2e7 458 for (pkgCache::DepIterator D = InstVer.DependsList(); D.end() == false; ++D)
9ec748ff
DK
459 {
460 if (DepMap[D->Type] == 0)
461 continue;
462 pkgCache::PkgIterator const T = D.TargetPkg();
463 if (D->Version != 0)
464 {
465 pkgCache::VerIterator const IV = Cache[T].InstVerIter(Cache);
77b6f202 466 if (IV.end() == true || D.IsSatisfied(IV) == false)
9ec748ff
DK
467 continue;
468 }
469 Scores[T->ID] += DepMap[D->Type];
470 }
8daf68e3
DK
471 }
472
6c139d6e 473 // Copy the scores to advoid additive looping
98cc7fd2
JAK
474 std::unique_ptr<int[]> OldScores(new int[Size]);
475 memcpy(OldScores.get(),Scores,sizeof(*Scores)*Size);
6c139d6e
AL
476
477 /* Now we cause 1 level of dependency inheritance, that is we add the
478 score of the packages that depend on the target Package. This
479 fortifies high scoring packages */
f7f0d6c7 480 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
6c139d6e
AL
481 {
482 if (Cache[I].InstallVer == 0)
483 continue;
484
f7f0d6c7 485 for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; ++D)
6c139d6e
AL
486 {
487 // Only do it for the install version
488 if ((pkgCache::Version *)D.ParentVer() != Cache[D.ParentPkg()].InstallVer ||
3a998f6a
MV
489 (D->Type != pkgCache::Dep::Depends &&
490 D->Type != pkgCache::Dep::PreDepends &&
491 D->Type != pkgCache::Dep::Recommends))
6c139d6e
AL
492 continue;
493
dec5b117
MV
494 // Do not propagate negative scores otherwise
495 // an extra (-2) package might score better than an optional (-1)
496 if (OldScores[D.ParentPkg()->ID] > 0)
497 Scores[I->ID] += OldScores[D.ParentPkg()->ID];
6c139d6e
AL
498 }
499 }
500
1e3f4083 501 /* Now we propagate along provides. This makes the packages that
6c139d6e 502 provide important packages extremely important */
f7f0d6c7 503 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
6c139d6e 504 {
f7f0d6c7 505 for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; ++P)
6c139d6e
AL
506 {
507 // Only do it once per package
508 if ((pkgCache::Version *)P.OwnerVer() != Cache[P.OwnerPkg()].InstallVer)
509 continue;
510 Scores[P.OwnerPkg()->ID] += abs(Scores[I->ID] - OldScores[I->ID]);
511 }
512 }
513
514 /* Protected things are pushed really high up. This number should put them
515 ahead of everything */
f7f0d6c7 516 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
d2685fd6 517 {
6c139d6e 518 if ((Flags[I->ID] & Protected) != 0)
8b4894fe 519 Scores[I->ID] += AddProtected;
c5200869
JAK
520 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential ||
521 (I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
8b4894fe
MV
522 Scores[I->ID] += AddEssential;
523 }
6c139d6e
AL
524}
525 /*}}}*/
526// ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
527// ---------------------------------------------------------------------
528/* This goes through and tries to reinstall packages to make this package
529 installable */
530bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
531{
74a05226
MV
532 pkgDepCache::ActionGroup group(Cache);
533
6c139d6e
AL
534 if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
535 return false;
3a486305
AL
536 if ((Flags[Pkg->ID] & Protected) == Protected)
537 return false;
0a8e3465 538
6c139d6e
AL
539 Flags[Pkg->ID] &= ~Upgradable;
540
541 bool WasKept = Cache[Pkg].Keep();
74a05226 542 Cache.MarkInstall(Pkg, false, 0, false);
6c139d6e 543
0a8e3465
AL
544 // This must be a virtual package or something like that.
545 if (Cache[Pkg].InstVerIter(Cache).end() == true)
546 return false;
547
6c139d6e
AL
548 // Isolate the problem dependency
549 bool Fail = false;
550 for (pkgCache::DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false;)
551 {
552 // Compute a single dependency element (glob or)
553 pkgCache::DepIterator Start = D;
554 pkgCache::DepIterator End = D;
4b1b89c5 555 for (bool LastOR = true; D.end() == false && LastOR == true;)
6c139d6e 556 {
b518cca6 557 LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
0284eee4 558 ++D;
6c139d6e
AL
559 if (LastOR == true)
560 End = D;
561 }
562
563 // We only worry about critical deps.
564 if (End.IsCritical() != true)
565 continue;
4b1b89c5
AL
566
567 // Iterate over all the members in the or group
568 while (1)
0a8e3465 569 {
4b1b89c5
AL
570 // Dep is ok now
571 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
572 break;
573
574 // Do not change protected packages
575 PkgIterator P = Start.SmartTargetPkg();
576 if ((Flags[P->ID] & Protected) == Protected)
577 {
578 if (Debug == true)
47f6d1b7 579 clog << " Reinst Failed because of protected " << P.FullName(false) << endl;
4b1b89c5 580 Fail = true;
4b1b89c5 581 }
648e3cb4 582 else
6c139d6e 583 {
648e3cb4
AL
584 // Upgrade the package if the candidate version will fix the problem.
585 if ((Cache[Start] & pkgDepCache::DepCVer) == pkgDepCache::DepCVer)
586 {
587 if (DoUpgrade(P) == false)
588 {
589 if (Debug == true)
47f6d1b7 590 clog << " Reinst Failed because of " << P.FullName(false) << endl;
648e3cb4
AL
591 Fail = true;
592 }
593 else
594 {
595 Fail = false;
596 break;
597 }
598 }
599 else
4b1b89c5 600 {
648e3cb4
AL
601 /* We let the algorithm deal with conflicts on its next iteration,
602 it is much smarter than us */
359e46db 603 if (Start.IsNegative() == true)
b2e465d6 604 break;
648e3cb4 605
4b1b89c5 606 if (Debug == true)
47f6d1b7 607 clog << " Reinst Failed early because of " << Start.TargetPkg().FullName(false) << endl;
4b1b89c5 608 Fail = true;
648e3cb4 609 }
4b1b89c5 610 }
6c139d6e 611
4b1b89c5
AL
612 if (Start == End)
613 break;
f7f0d6c7 614 ++Start;
4b1b89c5
AL
615 }
616 if (Fail == true)
6c139d6e 617 break;
6c139d6e
AL
618 }
619
620 // Undo our operations - it might be smart to undo everything this did..
621 if (Fail == true)
622 {
623 if (WasKept == true)
74a05226 624 Cache.MarkKeep(Pkg, false, false);
6c139d6e 625 else
b83cad32 626 Cache.MarkDelete(Pkg, false, 0, false);
6c139d6e
AL
627 return false;
628 }
629
630 if (Debug == true)
47f6d1b7 631 clog << " Re-Instated " << Pkg.FullName(false) << endl;
6c139d6e
AL
632 return true;
633}
634 /*}}}*/
6d38011b 635// ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/
2a884c61 636bool pkgProblemResolver::Resolve(bool BrokenFix, OpProgress * const Progress)
6d38011b 637{
98278a81 638 std::string const solver = _config->Find("APT::Solver", "internal");
3a487cc0 639 auto const ret = EDSP::ResolveExternal(solver.c_str(), Cache, 0, Progress);
2a884c61 640 if (solver != "internal")
3a487cc0 641 return ret;
6d38011b
DK
642 return ResolveInternal(BrokenFix);
643}
644 /*}}}*/
645// ProblemResolver::ResolveInternal - Run the resolution pass /*{{{*/
6c139d6e
AL
646// ---------------------------------------------------------------------
647/* This routines works by calculating a score for each package. The score
648 is derived by considering the package's priority and all reverse
649 dependents giving an integer that reflects the amount of breakage that
650 adjusting the package will inflict.
651
652 It goes from highest score to lowest and corrects all of the breaks by
1e3f4083 653 keeping or removing the dependent packages. If that fails then it removes
6c139d6e
AL
654 the package itself and goes on. The routine should be able to intelligently
655 go from any broken state to a fixed state.
656
657 The BrokenFix flag enables a mode where the algorithm tries to
658 upgrade packages to advoid problems. */
6d38011b 659bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
6c139d6e 660{
74a05226
MV
661 pkgDepCache::ActionGroup group(Cache);
662
6c139d6e
AL
663 // Record which packages are marked for install
664 bool Again = false;
665 do
666 {
667 Again = false;
f7f0d6c7 668 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
6c139d6e
AL
669 {
670 if (Cache[I].Install() == true)
671 Flags[I->ID] |= PreInstalled;
672 else
673 {
674 if (Cache[I].InstBroken() == true && BrokenFix == true)
675 {
74a05226 676 Cache.MarkInstall(I, false, 0, false);
6c139d6e
AL
677 if (Cache[I].Install() == true)
678 Again = true;
679 }
680
681 Flags[I->ID] &= ~PreInstalled;
682 }
683 Flags[I->ID] |= Upgradable;
684 }
685 }
686 while (Again == true);
687
32b5dd08 688 if (Debug == true) {
49b49018
MV
689 clog << "Starting pkgProblemResolver with broken count: "
690 << Cache.BrokenCount() << endl;
32b5dd08 691 }
6c139d6e
AL
692
693 MakeScores();
6d38011b
DK
694
695 unsigned long const Size = Cache.Head().PackageCount;
696
6c139d6e
AL
697 /* We have to order the packages so that the broken fixing pass
698 operates from highest score to lowest. This prevents problems when
699 high score packages cause the removal of lower score packages that
700 would cause the removal of even lower score packages. */
98cc7fd2
JAK
701 std::unique_ptr<pkgCache::Package *[]> PList(new pkgCache::Package *[Size]);
702 pkgCache::Package **PEnd = PList.get();
f7f0d6c7 703 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
6c139d6e 704 *PEnd++ = I;
f1f9f9bf
JAK
705
706 std::sort(PList.get(), PEnd, [this](Package *a, Package *b) { return ScoreSort(a, b) < 0; });
8b4894fe
MV
707
708 if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
709 {
710 clog << "Show Scores" << endl;
98cc7fd2 711 for (pkgCache::Package **K = PList.get(); K != PEnd; K++)
8b4894fe
MV
712 if (Scores[(*K)->ID] != 0)
713 {
714 pkgCache::PkgIterator Pkg(Cache,*K);
84573326 715 clog << Scores[(*K)->ID] << ' ' << APT::PrettyPkg(&Cache, Pkg) << std::endl;
8b4894fe
MV
716 }
717 }
6c139d6e 718
32b5dd08 719 if (Debug == true) {
49b49018
MV
720 clog << "Starting 2 pkgProblemResolver with broken count: "
721 << Cache.BrokenCount() << endl;
32b5dd08 722 }
8b4894fe 723
6c139d6e
AL
724 /* Now consider all broken packages. For each broken package we either
725 remove the package or fix it's problem. We do this once, it should
726 not be possible for a loop to form (that is a < b < c and fixing b by
727 changing a breaks c) */
728 bool Change = true;
09a10f9c 729 bool const TryFixByInstall = _config->FindB("pkgProblemResolver::FixByInstall", true);
f99b0621 730 std::vector<PackageKill> KillList;
6c139d6e
AL
731 for (int Counter = 0; Counter != 10 && Change == true; Counter++)
732 {
733 Change = false;
98cc7fd2 734 for (pkgCache::Package **K = PList.get(); K != PEnd; K++)
6c139d6e
AL
735 {
736 pkgCache::PkgIterator I(Cache,*K);
737
738 /* We attempt to install this and see if any breaks result,
739 this takes care of some strange cases */
740 if (Cache[I].CandidateVer != Cache[I].InstallVer &&
741 I->CurrentVer != 0 && Cache[I].InstallVer != 0 &&
742 (Flags[I->ID] & PreInstalled) != 0 &&
0a8e3465
AL
743 (Flags[I->ID] & Protected) == 0 &&
744 (Flags[I->ID] & ReInstateTried) == 0)
6c139d6e
AL
745 {
746 if (Debug == true)
09a10f9c 747 clog << " Try to Re-Instate (" << Counter << ") " << I.FullName(false) << endl;
a6568219 748 unsigned long OldBreaks = Cache.BrokenCount();
6c139d6e 749 pkgCache::Version *OldVer = Cache[I].InstallVer;
0a8e3465
AL
750 Flags[I->ID] &= ReInstateTried;
751
74a05226 752 Cache.MarkInstall(I, false, 0, false);
6c139d6e
AL
753 if (Cache[I].InstBroken() == true ||
754 OldBreaks < Cache.BrokenCount())
755 {
756 if (OldVer == 0)
b83cad32 757 Cache.MarkDelete(I, false, 0, false);
6c139d6e 758 else
74a05226 759 Cache.MarkKeep(I, false, false);
6c139d6e
AL
760 }
761 else
762 if (Debug == true)
47f6d1b7 763 clog << "Re-Instated " << I.FullName(false) << " (" << OldBreaks << " vs " << Cache.BrokenCount() << ')' << endl;
6c139d6e
AL
764 }
765
766 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
767 continue;
768
00b47c98 769 if (Debug == true)
84573326 770 clog << "Investigating (" << Counter << ") " << APT::PrettyPkg(&Cache, I) << endl;
00b47c98 771
6c139d6e 772 // Isolate the problem dependency
421c8d10
AL
773 bool InOr = false;
774 pkgCache::DepIterator Start;
775 pkgCache::DepIterator End;
f99b0621
JAK
776 size_t OldSize = 0;
777
778 KillList.resize(0);
648e3cb4
AL
779
780 enum {OrRemove,OrKeep} OrOp = OrRemove;
421c8d10
AL
781 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
782 D.end() == false || InOr == true;)
6c139d6e
AL
783 {
784 // Compute a single dependency element (glob or)
648e3cb4
AL
785 if (Start == End)
786 {
787 // Decide what to do
f99b0621 788 if (InOr == true && OldSize == KillList.size())
648e3cb4 789 {
09a10f9c 790 if (OrOp == OrRemove)
70777d4b
AL
791 {
792 if ((Flags[I->ID] & Protected) != Protected)
00b47c98
AL
793 {
794 if (Debug == true)
47f6d1b7 795 clog << " Or group remove for " << I.FullName(false) << endl;
b83cad32 796 Cache.MarkDelete(I, false, 0, false);
cd14eaf2 797 Change = true;
09a10f9c
DK
798 }
799 }
800 else if (OrOp == OrKeep)
00b47c98
AL
801 {
802 if (Debug == true)
47f6d1b7 803 clog << " Or group keep for " << I.FullName(false) << endl;
74a05226 804 Cache.MarkKeep(I, false, false);
cd14eaf2 805 Change = true;
b2e465d6 806 }
648e3cb4
AL
807 }
808
b2e465d6
AL
809 /* We do an extra loop (as above) to finalize the or group
810 processing */
811 InOr = false;
648e3cb4 812 OrOp = OrRemove;
421c8d10 813 D.GlobOr(Start,End);
b2e465d6
AL
814 if (Start.end() == true)
815 break;
cd14eaf2 816
b2e465d6
AL
817 // We only worry about critical deps.
818 if (End.IsCritical() != true)
819 continue;
cd14eaf2 820
648e3cb4 821 InOr = Start != End;
f99b0621 822 OldSize = KillList.size();
cd14eaf2 823 }
421c8d10 824 else
4cc152f9 825 {
f7f0d6c7 826 ++Start;
4cc152f9
MV
827 // We only worry about critical deps.
828 if (Start.IsCritical() != true)
829 continue;
830 }
cd14eaf2 831
6c139d6e
AL
832 // Dep is ok
833 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
cd14eaf2
AL
834 {
835 InOr = false;
6c139d6e 836 continue;
cd14eaf2
AL
837 }
838
6c139d6e 839 if (Debug == true)
84573326 840 clog << "Broken " << APT::PrettyDep(&Cache, Start) << endl;
fcf85120
AL
841
842 /* Look across the version list. If there are no possible
843 targets then we keep the package and bail. This is necessary
1e3f4083 844 if a package has a dep on another package that can't be found */
98cc7fd2
JAK
845 std::unique_ptr<pkgCache::Version *[]> VList(Start.AllTargets());
846 if (VList[0] == 0 && (Flags[I->ID] & Protected) != Protected &&
359e46db 847 Start.IsNegative() == false &&
fcf85120 848 Cache[I].NowBroken() == false)
648e3cb4
AL
849 {
850 if (InOr == true)
851 {
852 /* No keep choice because the keep being OK could be the
853 result of another element in the OR group! */
854 continue;
855 }
856
fcf85120 857 Change = true;
74a05226 858 Cache.MarkKeep(I, false, false);
fcf85120
AL
859 break;
860 }
861
6c139d6e 862 bool Done = false;
98cc7fd2 863 for (pkgCache::Version **V = VList.get(); *V != 0; V++)
6c139d6e
AL
864 {
865 pkgCache::VerIterator Ver(Cache,*V);
866 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
a6bfe583 867
2ba99db8
MV
868 /* This is a conflicts, and the version we are looking
869 at is not the currently selected version of the
870 package, which means it is not necessary to
871 remove/keep */
359e46db 872 if (Cache[Pkg].InstallVer != Ver && Start.IsNegative() == true)
4429616b 873 {
2ba99db8
MV
874 if (Debug)
875 clog << " Conflicts//Breaks against version "
876 << Ver.VerStr() << " for " << Pkg.Name()
877 << " but that is not InstVer, ignoring"
24e93662 878 << endl;
2ba99db8 879 continue;
4429616b
MV
880 }
881
6c139d6e 882 if (Debug == true)
e788a834
DK
883 clog << " Considering " << Pkg.FullName(false) << ' ' << Scores[Pkg->ID] <<
884 " as a solution to " << I.FullName(false) << ' ' << Scores[I->ID] << endl;
a6bfe583
AL
885
886 /* Try to fix the package under consideration rather than
887 fiddle with the VList package */
6c139d6e 888 if (Scores[I->ID] <= Scores[Pkg->ID] ||
421c8d10 889 ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
359e46db 890 End.IsNegative() == false))
6c139d6e 891 {
200f8c52 892 // Try a little harder to fix protected packages..
3b5421b4 893 if ((Flags[I->ID] & Protected) == Protected)
200f8c52
AL
894 {
895 if (DoUpgrade(Pkg) == true)
0296c633 896 {
b2e465d6
AL
897 if (Scores[Pkg->ID] > Scores[I->ID])
898 Scores[Pkg->ID] = Scores[I->ID];
0296c633
AL
899 break;
900 }
901
6c139d6e 902 continue;
200f8c52
AL
903 }
904
905 /* See if a keep will do, unless the package is protected,
648e3cb4
AL
906 then installing it will be necessary */
907 bool Installed = Cache[I].Install();
74a05226 908 Cache.MarkKeep(I, false, false);
6c139d6e
AL
909 if (Cache[I].InstBroken() == false)
910 {
648e3cb4
AL
911 // Unwind operation will be keep now
912 if (OrOp == OrRemove)
913 OrOp = OrKeep;
914
915 // Restore
916 if (InOr == true && Installed == true)
74a05226 917 Cache.MarkInstall(I, false, 0, false);
648e3cb4 918
6c139d6e 919 if (Debug == true)
47f6d1b7 920 clog << " Holding Back " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
6c139d6e
AL
921 }
922 else
421c8d10 923 {
6c139d6e
AL
924 if (BrokenFix == false || DoUpgrade(I) == false)
925 {
421c8d10 926 // Consider other options
87da7451 927 if (InOr == false || Cache[I].Garbage == true)
421c8d10 928 {
6910a2ac 929 if (Debug == true)
47f6d1b7 930 clog << " Removing " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
b83cad32 931 Cache.MarkDelete(I, false, 0, false);
6910a2ac
DK
932 if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID])
933 Scores[I->ID] = Scores[Pkg->ID];
d6ebeb21 934 }
09a10f9c
DK
935 else if (TryFixByInstall == true &&
936 Start.TargetPkg()->CurrentVer == 0 &&
937 Cache[Start.TargetPkg()].Delete() == false &&
a3f1a6cc 938 (Flags[Start.TargetPkg()->ID] & ToRemove) != ToRemove &&
294a8020 939 Cache.GetCandidateVersion(Start.TargetPkg()).end() == false)
09a10f9c
DK
940 {
941 /* Before removing or keeping the package with the broken dependency
942 try instead to install the first not previously installed package
943 solving this dependency. This helps every time a previous solver
944 is removed by the resolver because of a conflict or alike but it is
945 dangerous as it could trigger new breaks/conflicts… */
443266ef 946 if (Debug == true)
84573326 947 clog << " Try Installing " << APT::PrettyPkg(&Cache, Start.TargetPkg()) << " before changing " << I.FullName(false) << std::endl;
09a10f9c
DK
948 unsigned long const OldBroken = Cache.BrokenCount();
949 Cache.MarkInstall(Start.TargetPkg(), true, 1, false);
950 // FIXME: we should undo the complete MarkInstall process here
951 if (Cache[Start.TargetPkg()].InstBroken() == true || Cache.BrokenCount() > OldBroken)
952 Cache.MarkDelete(Start.TargetPkg(), false, 1, false);
953 }
0a8e3465 954 }
6c139d6e 955 }
b5dc9785 956
6c139d6e
AL
957 Change = true;
958 Done = true;
959 break;
960 }
961 else
962 {
308c7d30
IJ
963 if (Start->Type == pkgCache::Dep::DpkgBreaks)
964 {
76264cb7
MV
965 // first, try upgradring the package, if that
966 // does not help, the breaks goes onto the
967 // kill list
2ba99db8 968 //
76264cb7 969 // FIXME: use DoUpgrade(Pkg) instead?
2ba99db8 970 if (Cache[End] & pkgDepCache::DepGCVer)
76264cb7 971 {
308c7d30 972 if (Debug)
47f6d1b7 973 clog << " Upgrading " << Pkg.FullName(false) << " due to Breaks field in " << I.FullName(false) << endl;
308c7d30
IJ
974 Cache.MarkInstall(Pkg, false, 0, false);
975 continue;
976 }
308c7d30
IJ
977 }
978
648e3cb4 979 // Skip adding to the kill list if it is protected
6c139d6e
AL
980 if ((Flags[Pkg->ID] & Protected) != 0)
981 continue;
a6bfe583
AL
982
983 if (Debug == true)
47f6d1b7 984 clog << " Added " << Pkg.FullName(false) << " to the remove list" << endl;
f99b0621
JAK
985
986 KillList.push_back({Pkg, End});
0a8e3465 987
b47053bd 988 if (Start.IsNegative() == false)
6c139d6e
AL
989 break;
990 }
991 }
992
993 // Hm, nothing can possibly satisify this dep. Nuke it.
359e46db
DK
994 if (VList[0] == 0 &&
995 Start.IsNegative() == false &&
648e3cb4 996 (Flags[I->ID] & Protected) != Protected)
6c139d6e 997 {
648e3cb4 998 bool Installed = Cache[I].Install();
6c139d6e
AL
999 Cache.MarkKeep(I);
1000 if (Cache[I].InstBroken() == false)
1001 {
648e3cb4
AL
1002 // Unwind operation will be keep now
1003 if (OrOp == OrRemove)
1004 OrOp = OrKeep;
1005
1006 // Restore
1007 if (InOr == true && Installed == true)
74a05226 1008 Cache.MarkInstall(I, false, 0, false);
648e3cb4 1009
6c139d6e 1010 if (Debug == true)
47f6d1b7 1011 clog << " Holding Back " << I.FullName(false) << " because I can't find " << Start.TargetPkg().FullName(false) << endl;
6c139d6e
AL
1012 }
1013 else
1014 {
1015 if (Debug == true)
47f6d1b7 1016 clog << " Removing " << I.FullName(false) << " because I can't find " << Start.TargetPkg().FullName(false) << endl;
648e3cb4 1017 if (InOr == false)
b83cad32 1018 Cache.MarkDelete(I, false, 0, false);
6c139d6e
AL
1019 }
1020
1021 Change = true;
1022 Done = true;
1023 }
1024
421c8d10
AL
1025 // Try some more
1026 if (InOr == true)
1027 continue;
1028
6c139d6e
AL
1029 if (Done == true)
1030 break;
1031 }
1032
1033 // Apply the kill list now
1034 if (Cache[I].InstallVer != 0)
648e3cb4 1035 {
f99b0621 1036 for (auto J = KillList.begin(); J != KillList.end(); J++)
6c139d6e 1037 {
648e3cb4
AL
1038 Change = true;
1039 if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
1040 {
359e46db 1041 if (J->Dep.IsNegative() == true)
648e3cb4
AL
1042 {
1043 if (Debug == true)
47f6d1b7 1044 clog << " Fixing " << I.FullName(false) << " via remove of " << J->Pkg.FullName(false) << endl;
b83cad32 1045 Cache.MarkDelete(J->Pkg, false, 0, false);
648e3cb4
AL
1046 }
1047 }
1048 else
6c139d6e
AL
1049 {
1050 if (Debug == true)
47f6d1b7 1051 clog << " Fixing " << I.FullName(false) << " via keep of " << J->Pkg.FullName(false) << endl;
74a05226 1052 Cache.MarkKeep(J->Pkg, false, false);
6c139d6e 1053 }
b2e465d6 1054
648e3cb4 1055 if (Counter > 1)
b2e465d6
AL
1056 {
1057 if (Scores[I->ID] > Scores[J->Pkg->ID])
1058 Scores[J->Pkg->ID] = Scores[I->ID];
1059 }
648e3cb4
AL
1060 }
1061 }
1062 }
6c139d6e
AL
1063 }
1064
1065 if (Debug == true)
0a8e3465 1066 clog << "Done" << endl;
b2e465d6 1067
6c139d6e 1068 if (Cache.BrokenCount() != 0)
b5dc9785
AL
1069 {
1070 // See if this is the result of a hold
1071 pkgCache::PkgIterator I = Cache.PkgBegin();
f7f0d6c7 1072 for (;I.end() != true; ++I)
b5dc9785
AL
1073 {
1074 if (Cache[I].InstBroken() == false)
1075 continue;
1076 if ((Flags[I->ID] & Protected) != Protected)
b2e465d6 1077 return _error->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
b5dc9785 1078 }
b2e465d6 1079 return _error->Error(_("Unable to correct problems, you have held broken packages."));
b5dc9785
AL
1080 }
1081
fce72602 1082 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
80fa0d8a 1083 pkgCache::PkgIterator I = Cache.PkgBegin();
f7f0d6c7 1084 for (;I.end() != true; ++I) {
80fa0d8a 1085 if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
120365ce 1086 if(_config->FindI("Debug::pkgAutoRemove",false)) {
47f6d1b7 1087 std::clog << "Resolve installed new pkg: " << I.FullName(false)
120365ce
MV
1088 << " (now marking it as auto)" << std::endl;
1089 }
80fa0d8a
MV
1090 Cache[I].Flags |= pkgCache::Flag::Auto;
1091 }
1092 }
1093
1094
0a8e3465
AL
1095 return true;
1096}
1097 /*}}}*/
953b348c
MV
1098// ProblemResolver::BreaksInstOrPolicy - Check if the given pkg is broken/*{{{*/
1099// ---------------------------------------------------------------------
1100/* This checks if the given package is broken either by a hard dependency
1101 (InstBroken()) or by introducing a new policy breakage e.g. new
1102 unsatisfied recommends for a package that was in "policy-good" state
1103
1104 Note that this is not perfect as it will ignore further breakage
1105 for already broken policy (recommends)
1106*/
1107bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I)
1108{
953b348c
MV
1109 // a broken install is always a problem
1110 if (Cache[I].InstBroken() == true)
deec6474
DK
1111 {
1112 if (Debug == true)
84573326 1113 std::clog << " Dependencies are not satisfied for " << APT::PrettyPkg(&Cache, I) << std::endl;
953b348c 1114 return true;
deec6474 1115 }
953b348c
MV
1116
1117 // a newly broken policy (recommends/suggests) is a problem
1118 if (Cache[I].NowPolicyBroken() == false &&
1119 Cache[I].InstPolicyBroken() == true)
deec6474
DK
1120 {
1121 if (Debug == true)
84573326 1122 std::clog << " Policy breaks with upgrade of " << APT::PrettyPkg(&Cache, I) << std::endl;
953b348c 1123 return true;
deec6474
DK
1124 }
1125
953b348c
MV
1126 return false;
1127}
36a171e1 1128 /*}}}*/
0a8e3465
AL
1129// ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1130// ---------------------------------------------------------------------
1131/* This is the work horse of the soft upgrade routine. It is very gental
1132 in that it does not install or remove any packages. It is assumed that the
1133 system was non-broken previously. */
2a884c61 1134bool pkgProblemResolver::ResolveByKeep(OpProgress * const Progress)
741b7da9 1135{
98278a81 1136 std::string const solver = _config->Find("APT::Solver", "internal");
3a487cc0
DK
1137 constexpr auto flags = EDSP::Request::UPGRADE_ALL | EDSP::Request::FORBID_NEW_INSTALL | EDSP::Request::FORBID_REMOVE;
1138 auto const ret = EDSP::ResolveExternal(solver.c_str(), Cache, flags, Progress);
2a884c61 1139 if (solver != "internal")
3a487cc0 1140 return ret;
741b7da9
DK
1141 return ResolveByKeepInternal();
1142}
1143 /*}}}*/
1144// ProblemResolver::ResolveByKeepInternal - Resolve problems using keep /*{{{*/
1145// ---------------------------------------------------------------------
1146/* This is the work horse of the soft upgrade routine. It is very gental
1147 in that it does not install or remove any packages. It is assumed that the
1148 system was non-broken previously. */
1149bool pkgProblemResolver::ResolveByKeepInternal()
0a8e3465 1150{
74a05226
MV
1151 pkgDepCache::ActionGroup group(Cache);
1152
b2e465d6 1153 unsigned long Size = Cache.Head().PackageCount;
0a8e3465 1154
0a8e3465
AL
1155 MakeScores();
1156
1157 /* We have to order the packages so that the broken fixing pass
1158 operates from highest score to lowest. This prevents problems when
1159 high score packages cause the removal of lower score packages that
1160 would cause the removal of even lower score packages. */
1161 pkgCache::Package **PList = new pkgCache::Package *[Size];
1162 pkgCache::Package **PEnd = PList;
f7f0d6c7 1163 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
0a8e3465 1164 *PEnd++ = I;
f1f9f9bf
JAK
1165
1166 std::sort(PList,PEnd,[this](Package *a, Package *b) { return ScoreSort(a, b) < 0; });
1167
8b4894fe
MV
1168
1169 if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1170 {
1171 clog << "Show Scores" << endl;
1172 for (pkgCache::Package **K = PList; K != PEnd; K++)
1173 if (Scores[(*K)->ID] != 0)
1174 {
1175 pkgCache::PkgIterator Pkg(Cache,*K);
84573326 1176 clog << Scores[(*K)->ID] << ' ' << APT::PrettyPkg(&Cache, Pkg) << std::endl;
8b4894fe
MV
1177 }
1178 }
1179
1180 if (Debug == true)
1181 clog << "Entering ResolveByKeep" << endl;
1182
0a8e3465
AL
1183 // Consider each broken package
1184 pkgCache::Package **LastStop = 0;
1185 for (pkgCache::Package **K = PList; K != PEnd; K++)
1186 {
1187 pkgCache::PkgIterator I(Cache,*K);
1188
953b348c 1189 if (Cache[I].InstallVer == 0)
0a8e3465
AL
1190 continue;
1191
953b348c
MV
1192 if (InstOrNewPolicyBroken(I) == false)
1193 continue;
1194
0a8e3465 1195 /* Keep the package. If this works then great, otherwise we have
1e3f4083 1196 to be significantly more aggressive and manipulate its dependencies */
0a8e3465
AL
1197 if ((Flags[I->ID] & Protected) == 0)
1198 {
1199 if (Debug == true)
47f6d1b7 1200 clog << "Keeping package " << I.FullName(false) << endl;
74a05226 1201 Cache.MarkKeep(I, false, false);
953b348c 1202 if (InstOrNewPolicyBroken(I) == false)
0a8e3465 1203 {
b2e465d6 1204 K = PList - 1;
0a8e3465
AL
1205 continue;
1206 }
1207 }
1208
1209 // Isolate the problem dependencies
1210 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
1211 {
c5532863
AL
1212 DepIterator Start;
1213 DepIterator End;
1214 D.GlobOr(Start,End);
1215
0a8e3465
AL
1216 // We only worry about critical deps.
1217 if (End.IsCritical() != true)
1218 continue;
1219
1220 // Dep is ok
1221 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
1222 continue;
c5532863
AL
1223
1224 /* Hm, the group is broken.. I suppose the best thing to do is to
1225 is to try every combination of keep/not-keep for the set, but thats
1226 slow, and this never happens, just be conservative and assume the
1227 list of ors is in preference and keep till it starts to work. */
1228 while (true)
0a8e3465 1229 {
c5532863 1230 if (Debug == true)
84573326 1231 clog << "Package " << I.FullName(false) << " " << APT::PrettyDep(&Cache, Start) << endl;
8b4894fe 1232
c5532863 1233 // Look at all the possible provides on this package
98cc7fd2
JAK
1234 std::unique_ptr<pkgCache::Version *[]> VList(Start.AllTargets());
1235 for (pkgCache::Version **V = VList.get(); *V != 0; V++)
0a8e3465 1236 {
c5532863
AL
1237 pkgCache::VerIterator Ver(Cache,*V);
1238 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
1239
1240 // It is not keepable
1241 if (Cache[Pkg].InstallVer == 0 ||
1242 Pkg->CurrentVer == 0)
1243 continue;
1244
1245 if ((Flags[I->ID] & Protected) == 0)
1246 {
1247 if (Debug == true)
47f6d1b7 1248 clog << " Keeping Package " << Pkg.FullName(false) << " due to " << Start.DepType() << endl;
74a05226 1249 Cache.MarkKeep(Pkg, false, false);
c5532863
AL
1250 }
1251
953b348c 1252 if (InstOrNewPolicyBroken(I) == false)
c5532863 1253 break;
0a8e3465
AL
1254 }
1255
953b348c 1256 if (InstOrNewPolicyBroken(I) == false)
0a8e3465 1257 break;
0a8e3465 1258
c5532863
AL
1259 if (Start == End)
1260 break;
f7f0d6c7 1261 ++Start;
c5532863
AL
1262 }
1263
953b348c 1264 if (InstOrNewPolicyBroken(I) == false)
0a8e3465
AL
1265 break;
1266 }
1267
953b348c 1268 if (InstOrNewPolicyBroken(I) == true)
0a8e3465
AL
1269 continue;
1270
1271 // Restart again.
0291f645
JT
1272 if (K == LastStop) {
1273 // I is an iterator based off our temporary package list,
1274 // so copy the name we need before deleting the temporary list
1275 std::string const LoopingPackage = I.FullName(false);
1276 delete[] PList;
1277 return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.", LoopingPackage.c_str());
1278 }
0a8e3465 1279 LastStop = K;
b2e465d6 1280 K = PList - 1;
0291f645 1281 }
6c139d6e 1282
0291f645 1283 delete[] PList;
6c139d6e
AL
1284 return true;
1285}
1286 /*}}}*/
f3c736f9 1287// ProblemResolver::InstallProtect - deprecated cpu-eating no-op /*{{{*/
3b5421b4 1288// ---------------------------------------------------------------------
f3c736f9
DK
1289/* Actions issued with FromUser bit set are protected from further
1290 modification (expect by other calls with FromUser set) nowadays , so we
1291 don't need to reissue actions here, they are already set in stone. */
3b5421b4
AL
1292void pkgProblemResolver::InstallProtect()
1293{
74a05226
MV
1294 pkgDepCache::ActionGroup group(Cache);
1295
f7f0d6c7 1296 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
3b5421b4
AL
1297 {
1298 if ((Flags[I->ID] & Protected) == Protected)
1299 {
1300 if ((Flags[I->ID] & ToRemove) == ToRemove)
1301 Cache.MarkDelete(I);
c15f5690
MV
1302 else
1303 {
da543ed8
OS
1304 // preserve the information whether the package was auto
1305 // or manually installed
c15f5690
MV
1306 bool autoInst = (Cache[I].Flags & pkgCache::Flag::Auto);
1307 Cache.MarkInstall(I, false, 0, !autoInst);
1308 }
3b5421b4
AL
1309 }
1310 }
1311}
1312 /*}}}*/
b2e465d6
AL
1313// PrioSortList - Sort a list of versions by priority /*{{{*/
1314// ---------------------------------------------------------------------
1315/* This is ment to be used in conjunction with AllTargets to get a list
1316 of versions ordered by preference. */
f1f9f9bf
JAK
1317
1318struct PrioComp {
1319 pkgCache &PrioCache;
1320
258b9e51 1321 explicit PrioComp(pkgCache &PrioCache) : PrioCache(PrioCache) {
f1f9f9bf
JAK
1322 }
1323
1324 bool operator() (pkgCache::Version * const &A, pkgCache::Version * const &B) {
1325 return compare(A, B) < 0;
1326 }
1327
1328 int compare(pkgCache::Version * const &A, pkgCache::Version * const &B) {
1329 pkgCache::VerIterator L(PrioCache,A);
1330 pkgCache::VerIterator R(PrioCache,B);
1331
1332 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential &&
1333 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
1334 return 1;
1335 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
1336 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
1337 return -1;
1338
1339 if ((L.ParentPkg()->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important &&
1340 (R.ParentPkg()->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
1341 return 1;
1342 if ((L.ParentPkg()->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important &&
1343 (R.ParentPkg()->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
1344 return -1;
1345
1346 if (L->Priority != R->Priority)
1347 return R->Priority - L->Priority;
1348 return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
1349 }
1350};
1351
b2e465d6
AL
1352void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
1353{
1354 unsigned long Count = 0;
b2e465d6
AL
1355 for (pkgCache::Version **I = List; *I != 0; I++)
1356 Count++;
f1f9f9bf 1357 std::sort(List,List+Count,PrioComp(Cache));
b2e465d6
AL
1358}
1359 /*}}}*/