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