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