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