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