]> git.saurik.com Git - apt.git/blame - apt-pkg/algorithms.cc
implement operator* for cacheset iterators
[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);
6c139d6e
AL
728 for (int Counter = 0; Counter != 10 && Change == true; Counter++)
729 {
730 Change = false;
98cc7fd2 731 for (pkgCache::Package **K = PList.get(); K != PEnd; K++)
6c139d6e
AL
732 {
733 pkgCache::PkgIterator I(Cache,*K);
734
735 /* We attempt to install this and see if any breaks result,
736 this takes care of some strange cases */
737 if (Cache[I].CandidateVer != Cache[I].InstallVer &&
738 I->CurrentVer != 0 && Cache[I].InstallVer != 0 &&
739 (Flags[I->ID] & PreInstalled) != 0 &&
0a8e3465
AL
740 (Flags[I->ID] & Protected) == 0 &&
741 (Flags[I->ID] & ReInstateTried) == 0)
6c139d6e
AL
742 {
743 if (Debug == true)
09a10f9c 744 clog << " Try to Re-Instate (" << Counter << ") " << I.FullName(false) << endl;
a6568219 745 unsigned long OldBreaks = Cache.BrokenCount();
6c139d6e 746 pkgCache::Version *OldVer = Cache[I].InstallVer;
0a8e3465
AL
747 Flags[I->ID] &= ReInstateTried;
748
74a05226 749 Cache.MarkInstall(I, false, 0, false);
6c139d6e
AL
750 if (Cache[I].InstBroken() == true ||
751 OldBreaks < Cache.BrokenCount())
752 {
753 if (OldVer == 0)
b83cad32 754 Cache.MarkDelete(I, false, 0, false);
6c139d6e 755 else
74a05226 756 Cache.MarkKeep(I, false, false);
6c139d6e
AL
757 }
758 else
759 if (Debug == true)
47f6d1b7 760 clog << "Re-Instated " << I.FullName(false) << " (" << OldBreaks << " vs " << Cache.BrokenCount() << ')' << endl;
6c139d6e
AL
761 }
762
763 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
764 continue;
765
00b47c98 766 if (Debug == true)
09a10f9c 767 clog << "Investigating (" << Counter << ") " << I << endl;
00b47c98 768
6c139d6e
AL
769 // Isolate the problem dependency
770 PackageKill KillList[100];
771 PackageKill *LEnd = KillList;
421c8d10
AL
772 bool InOr = false;
773 pkgCache::DepIterator Start;
774 pkgCache::DepIterator End;
b2e465d6 775 PackageKill *OldEnd = LEnd;
648e3cb4
AL
776
777 enum {OrRemove,OrKeep} OrOp = OrRemove;
421c8d10
AL
778 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
779 D.end() == false || InOr == true;)
6c139d6e
AL
780 {
781 // Compute a single dependency element (glob or)
648e3cb4
AL
782 if (Start == End)
783 {
784 // Decide what to do
09a10f9c 785 if (InOr == true && OldEnd == LEnd)
648e3cb4 786 {
09a10f9c 787 if (OrOp == OrRemove)
70777d4b
AL
788 {
789 if ((Flags[I->ID] & Protected) != Protected)
00b47c98
AL
790 {
791 if (Debug == true)
47f6d1b7 792 clog << " Or group remove for " << I.FullName(false) << endl;
b83cad32 793 Cache.MarkDelete(I, false, 0, false);
cd14eaf2 794 Change = true;
09a10f9c
DK
795 }
796 }
797 else if (OrOp == OrKeep)
00b47c98
AL
798 {
799 if (Debug == true)
47f6d1b7 800 clog << " Or group keep for " << I.FullName(false) << endl;
74a05226 801 Cache.MarkKeep(I, false, false);
cd14eaf2 802 Change = true;
b2e465d6 803 }
648e3cb4
AL
804 }
805
b2e465d6
AL
806 /* We do an extra loop (as above) to finalize the or group
807 processing */
808 InOr = false;
648e3cb4 809 OrOp = OrRemove;
421c8d10 810 D.GlobOr(Start,End);
b2e465d6
AL
811 if (Start.end() == true)
812 break;
cd14eaf2 813
b2e465d6
AL
814 // We only worry about critical deps.
815 if (End.IsCritical() != true)
816 continue;
cd14eaf2 817
648e3cb4
AL
818 InOr = Start != End;
819 OldEnd = LEnd;
cd14eaf2 820 }
421c8d10 821 else
4cc152f9 822 {
f7f0d6c7 823 ++Start;
4cc152f9
MV
824 // We only worry about critical deps.
825 if (Start.IsCritical() != true)
826 continue;
827 }
cd14eaf2 828
6c139d6e
AL
829 // Dep is ok
830 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
cd14eaf2
AL
831 {
832 InOr = false;
6c139d6e 833 continue;
cd14eaf2
AL
834 }
835
6c139d6e 836 if (Debug == true)
47f6d1b7 837 clog << "Broken " << Start << endl;
fcf85120
AL
838
839 /* Look across the version list. If there are no possible
840 targets then we keep the package and bail. This is necessary
1e3f4083 841 if a package has a dep on another package that can't be found */
98cc7fd2
JAK
842 std::unique_ptr<pkgCache::Version *[]> VList(Start.AllTargets());
843 if (VList[0] == 0 && (Flags[I->ID] & Protected) != Protected &&
359e46db 844 Start.IsNegative() == false &&
fcf85120 845 Cache[I].NowBroken() == false)
648e3cb4
AL
846 {
847 if (InOr == true)
848 {
849 /* No keep choice because the keep being OK could be the
850 result of another element in the OR group! */
851 continue;
852 }
853
fcf85120 854 Change = true;
74a05226 855 Cache.MarkKeep(I, false, false);
fcf85120
AL
856 break;
857 }
858
6c139d6e 859 bool Done = false;
98cc7fd2 860 for (pkgCache::Version **V = VList.get(); *V != 0; V++)
6c139d6e
AL
861 {
862 pkgCache::VerIterator Ver(Cache,*V);
863 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
a6bfe583 864
2ba99db8
MV
865 /* This is a conflicts, and the version we are looking
866 at is not the currently selected version of the
867 package, which means it is not necessary to
868 remove/keep */
359e46db 869 if (Cache[Pkg].InstallVer != Ver && Start.IsNegative() == true)
4429616b 870 {
2ba99db8
MV
871 if (Debug)
872 clog << " Conflicts//Breaks against version "
873 << Ver.VerStr() << " for " << Pkg.Name()
874 << " but that is not InstVer, ignoring"
24e93662 875 << endl;
2ba99db8 876 continue;
4429616b
MV
877 }
878
6c139d6e 879 if (Debug == true)
e788a834
DK
880 clog << " Considering " << Pkg.FullName(false) << ' ' << Scores[Pkg->ID] <<
881 " as a solution to " << I.FullName(false) << ' ' << Scores[I->ID] << endl;
a6bfe583
AL
882
883 /* Try to fix the package under consideration rather than
884 fiddle with the VList package */
6c139d6e 885 if (Scores[I->ID] <= Scores[Pkg->ID] ||
421c8d10 886 ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
359e46db 887 End.IsNegative() == false))
6c139d6e 888 {
200f8c52 889 // Try a little harder to fix protected packages..
3b5421b4 890 if ((Flags[I->ID] & Protected) == Protected)
200f8c52
AL
891 {
892 if (DoUpgrade(Pkg) == true)
0296c633 893 {
b2e465d6
AL
894 if (Scores[Pkg->ID] > Scores[I->ID])
895 Scores[Pkg->ID] = Scores[I->ID];
0296c633
AL
896 break;
897 }
898
6c139d6e 899 continue;
200f8c52
AL
900 }
901
902 /* See if a keep will do, unless the package is protected,
648e3cb4
AL
903 then installing it will be necessary */
904 bool Installed = Cache[I].Install();
74a05226 905 Cache.MarkKeep(I, false, false);
6c139d6e
AL
906 if (Cache[I].InstBroken() == false)
907 {
648e3cb4
AL
908 // Unwind operation will be keep now
909 if (OrOp == OrRemove)
910 OrOp = OrKeep;
911
912 // Restore
913 if (InOr == true && Installed == true)
74a05226 914 Cache.MarkInstall(I, false, 0, false);
648e3cb4 915
6c139d6e 916 if (Debug == true)
47f6d1b7 917 clog << " Holding Back " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
6c139d6e
AL
918 }
919 else
421c8d10 920 {
6c139d6e
AL
921 if (BrokenFix == false || DoUpgrade(I) == false)
922 {
421c8d10 923 // Consider other options
87da7451 924 if (InOr == false || Cache[I].Garbage == true)
421c8d10 925 {
6910a2ac 926 if (Debug == true)
47f6d1b7 927 clog << " Removing " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
b83cad32 928 Cache.MarkDelete(I, false, 0, false);
6910a2ac
DK
929 if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID])
930 Scores[I->ID] = Scores[Pkg->ID];
d6ebeb21 931 }
09a10f9c
DK
932 else if (TryFixByInstall == true &&
933 Start.TargetPkg()->CurrentVer == 0 &&
934 Cache[Start.TargetPkg()].Delete() == false &&
a3f1a6cc 935 (Flags[Start.TargetPkg()->ID] & ToRemove) != ToRemove &&
09a10f9c
DK
936 Cache.GetCandidateVer(Start.TargetPkg()).end() == false)
937 {
938 /* Before removing or keeping the package with the broken dependency
939 try instead to install the first not previously installed package
940 solving this dependency. This helps every time a previous solver
941 is removed by the resolver because of a conflict or alike but it is
942 dangerous as it could trigger new breaks/conflicts… */
443266ef
DK
943 if (Debug == true)
944 clog << " Try Installing " << Start.TargetPkg() << " before changing " << I.FullName(false) << std::endl;
09a10f9c
DK
945 unsigned long const OldBroken = Cache.BrokenCount();
946 Cache.MarkInstall(Start.TargetPkg(), true, 1, false);
947 // FIXME: we should undo the complete MarkInstall process here
948 if (Cache[Start.TargetPkg()].InstBroken() == true || Cache.BrokenCount() > OldBroken)
949 Cache.MarkDelete(Start.TargetPkg(), false, 1, false);
950 }
0a8e3465 951 }
6c139d6e 952 }
b5dc9785 953
6c139d6e
AL
954 Change = true;
955 Done = true;
956 break;
957 }
958 else
959 {
308c7d30
IJ
960 if (Start->Type == pkgCache::Dep::DpkgBreaks)
961 {
76264cb7
MV
962 // first, try upgradring the package, if that
963 // does not help, the breaks goes onto the
964 // kill list
2ba99db8 965 //
76264cb7 966 // FIXME: use DoUpgrade(Pkg) instead?
2ba99db8 967 if (Cache[End] & pkgDepCache::DepGCVer)
76264cb7 968 {
308c7d30 969 if (Debug)
47f6d1b7 970 clog << " Upgrading " << Pkg.FullName(false) << " due to Breaks field in " << I.FullName(false) << endl;
308c7d30
IJ
971 Cache.MarkInstall(Pkg, false, 0, false);
972 continue;
973 }
308c7d30
IJ
974 }
975
648e3cb4 976 // Skip adding to the kill list if it is protected
6c139d6e
AL
977 if ((Flags[Pkg->ID] & Protected) != 0)
978 continue;
a6bfe583
AL
979
980 if (Debug == true)
47f6d1b7 981 clog << " Added " << Pkg.FullName(false) << " to the remove list" << endl;
6c139d6e
AL
982
983 LEnd->Pkg = Pkg;
984 LEnd->Dep = End;
985 LEnd++;
0a8e3465 986
b47053bd 987 if (Start.IsNegative() == false)
6c139d6e
AL
988 break;
989 }
990 }
991
992 // Hm, nothing can possibly satisify this dep. Nuke it.
359e46db
DK
993 if (VList[0] == 0 &&
994 Start.IsNegative() == false &&
648e3cb4 995 (Flags[I->ID] & Protected) != Protected)
6c139d6e 996 {
648e3cb4 997 bool Installed = Cache[I].Install();
6c139d6e
AL
998 Cache.MarkKeep(I);
999 if (Cache[I].InstBroken() == false)
1000 {
648e3cb4
AL
1001 // Unwind operation will be keep now
1002 if (OrOp == OrRemove)
1003 OrOp = OrKeep;
1004
1005 // Restore
1006 if (InOr == true && Installed == true)
74a05226 1007 Cache.MarkInstall(I, false, 0, false);
648e3cb4 1008
6c139d6e 1009 if (Debug == true)
47f6d1b7 1010 clog << " Holding Back " << I.FullName(false) << " because I can't find " << Start.TargetPkg().FullName(false) << endl;
6c139d6e
AL
1011 }
1012 else
1013 {
1014 if (Debug == true)
47f6d1b7 1015 clog << " Removing " << I.FullName(false) << " because I can't find " << Start.TargetPkg().FullName(false) << endl;
648e3cb4 1016 if (InOr == false)
b83cad32 1017 Cache.MarkDelete(I, false, 0, false);
6c139d6e
AL
1018 }
1019
1020 Change = true;
1021 Done = true;
1022 }
1023
421c8d10
AL
1024 // Try some more
1025 if (InOr == true)
1026 continue;
1027
6c139d6e
AL
1028 if (Done == true)
1029 break;
1030 }
1031
1032 // Apply the kill list now
1033 if (Cache[I].InstallVer != 0)
648e3cb4 1034 {
6c139d6e 1035 for (PackageKill *J = KillList; J != LEnd; J++)
6c139d6e 1036 {
648e3cb4
AL
1037 Change = true;
1038 if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
1039 {
359e46db 1040 if (J->Dep.IsNegative() == true)
648e3cb4
AL
1041 {
1042 if (Debug == true)
47f6d1b7 1043 clog << " Fixing " << I.FullName(false) << " via remove of " << J->Pkg.FullName(false) << endl;
b83cad32 1044 Cache.MarkDelete(J->Pkg, false, 0, false);
648e3cb4
AL
1045 }
1046 }
1047 else
6c139d6e
AL
1048 {
1049 if (Debug == true)
47f6d1b7 1050 clog << " Fixing " << I.FullName(false) << " via keep of " << J->Pkg.FullName(false) << endl;
74a05226 1051 Cache.MarkKeep(J->Pkg, false, false);
6c139d6e 1052 }
b2e465d6 1053
648e3cb4 1054 if (Counter > 1)
b2e465d6
AL
1055 {
1056 if (Scores[I->ID] > Scores[J->Pkg->ID])
1057 Scores[J->Pkg->ID] = Scores[I->ID];
1058 }
648e3cb4
AL
1059 }
1060 }
1061 }
6c139d6e
AL
1062 }
1063
1064 if (Debug == true)
0a8e3465 1065 clog << "Done" << endl;
b2e465d6 1066
6c139d6e 1067 if (Cache.BrokenCount() != 0)
b5dc9785
AL
1068 {
1069 // See if this is the result of a hold
1070 pkgCache::PkgIterator I = Cache.PkgBegin();
f7f0d6c7 1071 for (;I.end() != true; ++I)
b5dc9785
AL
1072 {
1073 if (Cache[I].InstBroken() == false)
1074 continue;
1075 if ((Flags[I->ID] & Protected) != Protected)
b2e465d6 1076 return _error->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
b5dc9785 1077 }
b2e465d6 1078 return _error->Error(_("Unable to correct problems, you have held broken packages."));
b5dc9785
AL
1079 }
1080
fce72602 1081 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
80fa0d8a 1082 pkgCache::PkgIterator I = Cache.PkgBegin();
f7f0d6c7 1083 for (;I.end() != true; ++I) {
80fa0d8a 1084 if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
120365ce 1085 if(_config->FindI("Debug::pkgAutoRemove",false)) {
47f6d1b7 1086 std::clog << "Resolve installed new pkg: " << I.FullName(false)
120365ce
MV
1087 << " (now marking it as auto)" << std::endl;
1088 }
80fa0d8a
MV
1089 Cache[I].Flags |= pkgCache::Flag::Auto;
1090 }
1091 }
1092
1093
0a8e3465
AL
1094 return true;
1095}
1096 /*}}}*/
953b348c
MV
1097// ProblemResolver::BreaksInstOrPolicy - Check if the given pkg is broken/*{{{*/
1098// ---------------------------------------------------------------------
1099/* This checks if the given package is broken either by a hard dependency
1100 (InstBroken()) or by introducing a new policy breakage e.g. new
1101 unsatisfied recommends for a package that was in "policy-good" state
1102
1103 Note that this is not perfect as it will ignore further breakage
1104 for already broken policy (recommends)
1105*/
1106bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I)
1107{
953b348c
MV
1108 // a broken install is always a problem
1109 if (Cache[I].InstBroken() == true)
deec6474
DK
1110 {
1111 if (Debug == true)
1112 std::clog << " Dependencies are not satisfied for " << I << std::endl;
953b348c 1113 return true;
deec6474 1114 }
953b348c
MV
1115
1116 // a newly broken policy (recommends/suggests) is a problem
1117 if (Cache[I].NowPolicyBroken() == false &&
1118 Cache[I].InstPolicyBroken() == true)
deec6474
DK
1119 {
1120 if (Debug == true)
1121 std::clog << " Policy breaks with upgrade of " << I << std::endl;
953b348c 1122 return true;
deec6474
DK
1123 }
1124
953b348c
MV
1125 return false;
1126}
36a171e1 1127 /*}}}*/
0a8e3465
AL
1128// ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1129// ---------------------------------------------------------------------
1130/* This is the work horse of the soft upgrade routine. It is very gental
1131 in that it does not install or remove any packages. It is assumed that the
1132 system was non-broken previously. */
2a884c61 1133bool pkgProblemResolver::ResolveByKeep(OpProgress * const Progress)
741b7da9 1134{
98278a81 1135 std::string const solver = _config->Find("APT::Solver", "internal");
2a884c61
DK
1136 if (solver != "internal")
1137 return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, Progress);
741b7da9
DK
1138 return ResolveByKeepInternal();
1139}
1140 /*}}}*/
1141// ProblemResolver::ResolveByKeepInternal - Resolve problems using keep /*{{{*/
1142// ---------------------------------------------------------------------
1143/* This is the work horse of the soft upgrade routine. It is very gental
1144 in that it does not install or remove any packages. It is assumed that the
1145 system was non-broken previously. */
1146bool pkgProblemResolver::ResolveByKeepInternal()
0a8e3465 1147{
74a05226
MV
1148 pkgDepCache::ActionGroup group(Cache);
1149
b2e465d6 1150 unsigned long Size = Cache.Head().PackageCount;
0a8e3465 1151
0a8e3465
AL
1152 MakeScores();
1153
1154 /* We have to order the packages so that the broken fixing pass
1155 operates from highest score to lowest. This prevents problems when
1156 high score packages cause the removal of lower score packages that
1157 would cause the removal of even lower score packages. */
1158 pkgCache::Package **PList = new pkgCache::Package *[Size];
1159 pkgCache::Package **PEnd = PList;
f7f0d6c7 1160 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
0a8e3465 1161 *PEnd++ = I;
f1f9f9bf
JAK
1162
1163 std::sort(PList,PEnd,[this](Package *a, Package *b) { return ScoreSort(a, b) < 0; });
1164
8b4894fe
MV
1165
1166 if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1167 {
1168 clog << "Show Scores" << endl;
1169 for (pkgCache::Package **K = PList; K != PEnd; K++)
1170 if (Scores[(*K)->ID] != 0)
1171 {
1172 pkgCache::PkgIterator Pkg(Cache,*K);
1173 clog << Scores[(*K)->ID] << ' ' << Pkg << std::endl;
1174 }
1175 }
1176
1177 if (Debug == true)
1178 clog << "Entering ResolveByKeep" << endl;
1179
0a8e3465
AL
1180 // Consider each broken package
1181 pkgCache::Package **LastStop = 0;
1182 for (pkgCache::Package **K = PList; K != PEnd; K++)
1183 {
1184 pkgCache::PkgIterator I(Cache,*K);
1185
953b348c 1186 if (Cache[I].InstallVer == 0)
0a8e3465
AL
1187 continue;
1188
953b348c
MV
1189 if (InstOrNewPolicyBroken(I) == false)
1190 continue;
1191
0a8e3465 1192 /* Keep the package. If this works then great, otherwise we have
1e3f4083 1193 to be significantly more aggressive and manipulate its dependencies */
0a8e3465
AL
1194 if ((Flags[I->ID] & Protected) == 0)
1195 {
1196 if (Debug == true)
47f6d1b7 1197 clog << "Keeping package " << I.FullName(false) << endl;
74a05226 1198 Cache.MarkKeep(I, false, false);
953b348c 1199 if (InstOrNewPolicyBroken(I) == false)
0a8e3465 1200 {
b2e465d6 1201 K = PList - 1;
0a8e3465
AL
1202 continue;
1203 }
1204 }
1205
1206 // Isolate the problem dependencies
1207 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
1208 {
c5532863
AL
1209 DepIterator Start;
1210 DepIterator End;
1211 D.GlobOr(Start,End);
1212
0a8e3465
AL
1213 // We only worry about critical deps.
1214 if (End.IsCritical() != true)
1215 continue;
1216
1217 // Dep is ok
1218 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
1219 continue;
c5532863
AL
1220
1221 /* Hm, the group is broken.. I suppose the best thing to do is to
1222 is to try every combination of keep/not-keep for the set, but thats
1223 slow, and this never happens, just be conservative and assume the
1224 list of ors is in preference and keep till it starts to work. */
1225 while (true)
0a8e3465 1226 {
c5532863 1227 if (Debug == true)
47f6d1b7 1228 clog << "Package " << I.FullName(false) << " " << Start << endl;
8b4894fe 1229
c5532863 1230 // Look at all the possible provides on this package
98cc7fd2
JAK
1231 std::unique_ptr<pkgCache::Version *[]> VList(Start.AllTargets());
1232 for (pkgCache::Version **V = VList.get(); *V != 0; V++)
0a8e3465 1233 {
c5532863
AL
1234 pkgCache::VerIterator Ver(Cache,*V);
1235 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
1236
1237 // It is not keepable
1238 if (Cache[Pkg].InstallVer == 0 ||
1239 Pkg->CurrentVer == 0)
1240 continue;
1241
1242 if ((Flags[I->ID] & Protected) == 0)
1243 {
1244 if (Debug == true)
47f6d1b7 1245 clog << " Keeping Package " << Pkg.FullName(false) << " due to " << Start.DepType() << endl;
74a05226 1246 Cache.MarkKeep(Pkg, false, false);
c5532863
AL
1247 }
1248
953b348c 1249 if (InstOrNewPolicyBroken(I) == false)
c5532863 1250 break;
0a8e3465
AL
1251 }
1252
953b348c 1253 if (InstOrNewPolicyBroken(I) == false)
0a8e3465 1254 break;
0a8e3465 1255
c5532863
AL
1256 if (Start == End)
1257 break;
f7f0d6c7 1258 ++Start;
c5532863
AL
1259 }
1260
953b348c 1261 if (InstOrNewPolicyBroken(I) == false)
0a8e3465
AL
1262 break;
1263 }
1264
953b348c 1265 if (InstOrNewPolicyBroken(I) == true)
0a8e3465
AL
1266 continue;
1267
1268 // Restart again.
0291f645
JT
1269 if (K == LastStop) {
1270 // I is an iterator based off our temporary package list,
1271 // so copy the name we need before deleting the temporary list
1272 std::string const LoopingPackage = I.FullName(false);
1273 delete[] PList;
1274 return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.", LoopingPackage.c_str());
1275 }
0a8e3465 1276 LastStop = K;
b2e465d6 1277 K = PList - 1;
0291f645 1278 }
6c139d6e 1279
0291f645 1280 delete[] PList;
6c139d6e
AL
1281 return true;
1282}
1283 /*}}}*/
f3c736f9 1284// ProblemResolver::InstallProtect - deprecated cpu-eating no-op /*{{{*/
3b5421b4 1285// ---------------------------------------------------------------------
f3c736f9
DK
1286/* Actions issued with FromUser bit set are protected from further
1287 modification (expect by other calls with FromUser set) nowadays , so we
1288 don't need to reissue actions here, they are already set in stone. */
3b5421b4
AL
1289void pkgProblemResolver::InstallProtect()
1290{
74a05226
MV
1291 pkgDepCache::ActionGroup group(Cache);
1292
f7f0d6c7 1293 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
3b5421b4
AL
1294 {
1295 if ((Flags[I->ID] & Protected) == Protected)
1296 {
1297 if ((Flags[I->ID] & ToRemove) == ToRemove)
1298 Cache.MarkDelete(I);
c15f5690
MV
1299 else
1300 {
da543ed8
OS
1301 // preserve the information whether the package was auto
1302 // or manually installed
c15f5690
MV
1303 bool autoInst = (Cache[I].Flags & pkgCache::Flag::Auto);
1304 Cache.MarkInstall(I, false, 0, !autoInst);
1305 }
3b5421b4
AL
1306 }
1307 }
1308}
1309 /*}}}*/
b2e465d6
AL
1310// PrioSortList - Sort a list of versions by priority /*{{{*/
1311// ---------------------------------------------------------------------
1312/* This is ment to be used in conjunction with AllTargets to get a list
1313 of versions ordered by preference. */
f1f9f9bf
JAK
1314
1315struct PrioComp {
1316 pkgCache &PrioCache;
1317
1318 PrioComp(pkgCache &PrioCache) : PrioCache(PrioCache) {
1319 }
1320
1321 bool operator() (pkgCache::Version * const &A, pkgCache::Version * const &B) {
1322 return compare(A, B) < 0;
1323 }
1324
1325 int compare(pkgCache::Version * const &A, pkgCache::Version * const &B) {
1326 pkgCache::VerIterator L(PrioCache,A);
1327 pkgCache::VerIterator R(PrioCache,B);
1328
1329 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential &&
1330 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
1331 return 1;
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
1336 if ((L.ParentPkg()->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important &&
1337 (R.ParentPkg()->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
1338 return 1;
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
1343 if (L->Priority != R->Priority)
1344 return R->Priority - L->Priority;
1345 return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
1346 }
1347};
1348
b2e465d6
AL
1349void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
1350{
1351 unsigned long Count = 0;
b2e465d6
AL
1352 for (pkgCache::Version **I = List; *I != 0; I++)
1353 Count++;
f1f9f9bf 1354 std::sort(List,List+Count,PrioComp(Cache));
b2e465d6
AL
1355}
1356 /*}}}*/