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