]> git.saurik.com Git - apt.git/blame - apt-pkg/algorithms.cc
* cmdline/apt-get.cc:
[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// ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
446// ---------------------------------------------------------------------
447/* */
b2e465d6 448pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : Cache(*pCache)
6c139d6e
AL
449{
450 // Allocate memory
b2e465d6 451 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
452 Scores = new signed short[Size];
453 Flags = new unsigned char[Size];
454 memset(Flags,0,sizeof(*Flags)*Size);
455
456 // Set debug to true to see its decision logic
0a8e3465 457 Debug = _config->FindB("Debug::pkgProblemResolver",false);
6c139d6e
AL
458}
459 /*}}}*/
b2e465d6
AL
460// ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
461// ---------------------------------------------------------------------
462/* */
463pkgProblemResolver::~pkgProblemResolver()
464{
465 delete [] Scores;
466 delete [] Flags;
467}
468 /*}}}*/
6c139d6e
AL
469// ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
470// ---------------------------------------------------------------------
471/* */
472int pkgProblemResolver::ScoreSort(const void *a,const void *b)
473{
474 Package const **A = (Package const **)a;
475 Package const **B = (Package const **)b;
476 if (This->Scores[(*A)->ID] > This->Scores[(*B)->ID])
477 return -1;
478 if (This->Scores[(*A)->ID] < This->Scores[(*B)->ID])
479 return 1;
480 return 0;
481}
482 /*}}}*/
483// ProblemResolver::MakeScores - Make the score table /*{{{*/
484// ---------------------------------------------------------------------
485/* */
486void pkgProblemResolver::MakeScores()
487{
b2e465d6 488 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
489 memset(Scores,0,sizeof(*Scores)*Size);
490
8b4894fe
MV
491 // Important Required Standard Optional Extra
492 signed short PrioMap[] = {
493 0,
494 _config->FindI("pkgProblemResolver::Scores::Important",3),
495 _config->FindI("pkgProblemResolver::Scores::Required",2),
496 _config->FindI("pkgProblemResolver::Scores::Standard",1),
497 _config->FindI("pkgProblemResolver::Scores::Optional",-1),
498 _config->FindI("pkgProblemResolver::Scores::Extra",-2)
499 };
500 signed short PrioEssentials = _config->FindI("pkgProblemResolver::Scores::Essentials",100);
501 signed short PrioInstalledAndNotObsolete = _config->FindI("pkgProblemResolver::Scores::NotObsolete",1);
502 signed short PrioDepends = _config->FindI("pkgProblemResolver::Scores::Depends",1);
53391d0f 503 signed short PrioRecommends = _config->FindI("pkgProblemResolver::Scores::Recommends",1);
8b4894fe
MV
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
53391d0f 517 << " Recommends => " << PrioRecommends << endl
8b4894fe
MV
518 << " AddProtected => " << AddProtected << endl
519 << " AddEssential => " << AddEssential << endl;
520
6c139d6e
AL
521 // Generate the base scores for a package based on its properties
522 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
523 {
524 if (Cache[I].InstallVer == 0)
525 continue;
526
527 signed short &Score = Scores[I->ID];
528
7365ff46 529 /* This is arbitrary, it should be high enough to elevate an
6c139d6e
AL
530 essantial package above most other packages but low enough
531 to allow an obsolete essential packages to be removed by
532 a conflicts on a powerfull normal package (ie libc6) */
b518cca6 533 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
8b4894fe 534 Score += PrioEssentials;
6c139d6e
AL
535
536 // We transform the priority
6c139d6e
AL
537 if (Cache[I].InstVerIter(Cache)->Priority <= 5)
538 Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
539
540 /* This helps to fix oddball problems with conflicting packages
4172c784
MV
541 on the same level. We enhance the score of installed packages
542 if those are not obsolete
543 */
020daa7b 544 if (I->CurrentVer != 0 && Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable())
8b4894fe 545 Score += PrioInstalledAndNotObsolete;
6c139d6e
AL
546 }
547
548 // Now that we have the base scores we go and propogate dependencies
549 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
550 {
551 if (Cache[I].InstallVer == 0)
552 continue;
553
554 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
555 {
3a998f6a 556 if (D->Type == pkgCache::Dep::Depends ||
53391d0f
MV
557 D->Type == pkgCache::Dep::PreDepends)
558 Scores[D.TargetPkg()->ID] += PrioDepends;
559 else if (D->Type == pkgCache::Dep::Recommends)
560 Scores[D.TargetPkg()->ID] += PrioRecommends;
6c139d6e
AL
561 }
562 }
563
564 // Copy the scores to advoid additive looping
b2e465d6 565 SPtrArray<signed short> OldScores = new signed short[Size];
6c139d6e
AL
566 memcpy(OldScores,Scores,sizeof(*Scores)*Size);
567
568 /* Now we cause 1 level of dependency inheritance, that is we add the
569 score of the packages that depend on the target Package. This
570 fortifies high scoring packages */
571 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
572 {
573 if (Cache[I].InstallVer == 0)
574 continue;
575
576 for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; D++)
577 {
578 // Only do it for the install version
579 if ((pkgCache::Version *)D.ParentVer() != Cache[D.ParentPkg()].InstallVer ||
3a998f6a
MV
580 (D->Type != pkgCache::Dep::Depends &&
581 D->Type != pkgCache::Dep::PreDepends &&
582 D->Type != pkgCache::Dep::Recommends))
6c139d6e
AL
583 continue;
584
585 Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]);
586 }
587 }
588
589 /* Now we propogate along provides. This makes the packages that
590 provide important packages extremely important */
591 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
592 {
593 for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; P++)
594 {
595 // Only do it once per package
596 if ((pkgCache::Version *)P.OwnerVer() != Cache[P.OwnerPkg()].InstallVer)
597 continue;
598 Scores[P.OwnerPkg()->ID] += abs(Scores[I->ID] - OldScores[I->ID]);
599 }
600 }
601
602 /* Protected things are pushed really high up. This number should put them
603 ahead of everything */
604 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
d2685fd6 605 {
6c139d6e 606 if ((Flags[I->ID] & Protected) != 0)
8b4894fe 607 Scores[I->ID] += AddProtected;
d2685fd6 608 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
8b4894fe
MV
609 Scores[I->ID] += AddEssential;
610 }
6c139d6e
AL
611}
612 /*}}}*/
613// ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
614// ---------------------------------------------------------------------
615/* This goes through and tries to reinstall packages to make this package
616 installable */
617bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
618{
74a05226
MV
619 pkgDepCache::ActionGroup group(Cache);
620
6c139d6e
AL
621 if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
622 return false;
3a486305
AL
623 if ((Flags[Pkg->ID] & Protected) == Protected)
624 return false;
0a8e3465 625
6c139d6e
AL
626 Flags[Pkg->ID] &= ~Upgradable;
627
628 bool WasKept = Cache[Pkg].Keep();
74a05226 629 Cache.MarkInstall(Pkg, false, 0, false);
6c139d6e 630
0a8e3465
AL
631 // This must be a virtual package or something like that.
632 if (Cache[Pkg].InstVerIter(Cache).end() == true)
633 return false;
634
6c139d6e
AL
635 // Isolate the problem dependency
636 bool Fail = false;
637 for (pkgCache::DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false;)
638 {
639 // Compute a single dependency element (glob or)
640 pkgCache::DepIterator Start = D;
641 pkgCache::DepIterator End = D;
642 unsigned char State = 0;
4b1b89c5 643 for (bool LastOR = true; D.end() == false && LastOR == true;)
6c139d6e
AL
644 {
645 State |= Cache[D];
b518cca6 646 LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
4b1b89c5 647 D++;
6c139d6e
AL
648 if (LastOR == true)
649 End = D;
650 }
651
652 // We only worry about critical deps.
653 if (End.IsCritical() != true)
654 continue;
4b1b89c5
AL
655
656 // Iterate over all the members in the or group
657 while (1)
0a8e3465 658 {
4b1b89c5
AL
659 // Dep is ok now
660 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
661 break;
662
663 // Do not change protected packages
664 PkgIterator P = Start.SmartTargetPkg();
665 if ((Flags[P->ID] & Protected) == Protected)
666 {
667 if (Debug == true)
648e3cb4 668 clog << " Reinst Failed because of protected " << P.Name() << endl;
4b1b89c5 669 Fail = true;
4b1b89c5 670 }
648e3cb4 671 else
6c139d6e 672 {
648e3cb4
AL
673 // Upgrade the package if the candidate version will fix the problem.
674 if ((Cache[Start] & pkgDepCache::DepCVer) == pkgDepCache::DepCVer)
675 {
676 if (DoUpgrade(P) == false)
677 {
678 if (Debug == true)
679 clog << " Reinst Failed because of " << P.Name() << endl;
680 Fail = true;
681 }
682 else
683 {
684 Fail = false;
685 break;
686 }
687 }
688 else
4b1b89c5 689 {
648e3cb4
AL
690 /* We let the algorithm deal with conflicts on its next iteration,
691 it is much smarter than us */
b2e465d6 692 if (Start->Type == pkgCache::Dep::Conflicts ||
308c7d30 693 Start->Type == pkgCache::Dep::DpkgBreaks ||
b2e465d6
AL
694 Start->Type == pkgCache::Dep::Obsoletes)
695 break;
648e3cb4 696
4b1b89c5 697 if (Debug == true)
648e3cb4 698 clog << " Reinst Failed early because of " << Start.TargetPkg().Name() << endl;
4b1b89c5 699 Fail = true;
648e3cb4 700 }
4b1b89c5 701 }
6c139d6e 702
4b1b89c5
AL
703 if (Start == End)
704 break;
705 Start++;
706 }
707 if (Fail == true)
6c139d6e 708 break;
6c139d6e
AL
709 }
710
711 // Undo our operations - it might be smart to undo everything this did..
712 if (Fail == true)
713 {
714 if (WasKept == true)
74a05226 715 Cache.MarkKeep(Pkg, false, false);
6c139d6e
AL
716 else
717 Cache.MarkDelete(Pkg);
718 return false;
719 }
720
721 if (Debug == true)
0a8e3465 722 clog << " Re-Instated " << Pkg.Name() << endl;
6c139d6e
AL
723 return true;
724}
725 /*}}}*/
726// ProblemResolver::Resolve - Run the resolution pass /*{{{*/
727// ---------------------------------------------------------------------
728/* This routines works by calculating a score for each package. The score
729 is derived by considering the package's priority and all reverse
730 dependents giving an integer that reflects the amount of breakage that
731 adjusting the package will inflict.
732
733 It goes from highest score to lowest and corrects all of the breaks by
734 keeping or removing the dependant packages. If that fails then it removes
735 the package itself and goes on. The routine should be able to intelligently
736 go from any broken state to a fixed state.
737
738 The BrokenFix flag enables a mode where the algorithm tries to
739 upgrade packages to advoid problems. */
740bool pkgProblemResolver::Resolve(bool BrokenFix)
741{
74a05226
MV
742 pkgDepCache::ActionGroup group(Cache);
743
b2e465d6 744 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
745
746 // Record which packages are marked for install
747 bool Again = false;
748 do
749 {
750 Again = false;
751 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
752 {
753 if (Cache[I].Install() == true)
754 Flags[I->ID] |= PreInstalled;
755 else
756 {
757 if (Cache[I].InstBroken() == true && BrokenFix == true)
758 {
74a05226 759 Cache.MarkInstall(I, false, 0, false);
6c139d6e
AL
760 if (Cache[I].Install() == true)
761 Again = true;
762 }
763
764 Flags[I->ID] &= ~PreInstalled;
765 }
766 Flags[I->ID] |= Upgradable;
767 }
768 }
769 while (Again == true);
770
771 if (Debug == true)
0a8e3465 772 clog << "Starting" << endl;
6c139d6e
AL
773
774 MakeScores();
775
776 /* We have to order the packages so that the broken fixing pass
777 operates from highest score to lowest. This prevents problems when
778 high score packages cause the removal of lower score packages that
779 would cause the removal of even lower score packages. */
b2e465d6 780 SPtrArray<pkgCache::Package *> PList = new pkgCache::Package *[Size];
6c139d6e
AL
781 pkgCache::Package **PEnd = PList;
782 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
783 *PEnd++ = I;
784 This = this;
785 qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
8b4894fe
MV
786
787 if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
788 {
789 clog << "Show Scores" << endl;
790 for (pkgCache::Package **K = PList; K != PEnd; K++)
791 if (Scores[(*K)->ID] != 0)
792 {
793 pkgCache::PkgIterator Pkg(Cache,*K);
794 clog << Scores[(*K)->ID] << ' ' << Pkg << std::endl;
795 }
796 }
6c139d6e
AL
797
798 if (Debug == true)
0a8e3465 799 clog << "Starting 2" << endl;
8b4894fe 800
6c139d6e
AL
801 /* Now consider all broken packages. For each broken package we either
802 remove the package or fix it's problem. We do this once, it should
803 not be possible for a loop to form (that is a < b < c and fixing b by
804 changing a breaks c) */
805 bool Change = true;
806 for (int Counter = 0; Counter != 10 && Change == true; Counter++)
807 {
808 Change = false;
809 for (pkgCache::Package **K = PList; K != PEnd; K++)
810 {
811 pkgCache::PkgIterator I(Cache,*K);
812
813 /* We attempt to install this and see if any breaks result,
814 this takes care of some strange cases */
815 if (Cache[I].CandidateVer != Cache[I].InstallVer &&
816 I->CurrentVer != 0 && Cache[I].InstallVer != 0 &&
817 (Flags[I->ID] & PreInstalled) != 0 &&
0a8e3465
AL
818 (Flags[I->ID] & Protected) == 0 &&
819 (Flags[I->ID] & ReInstateTried) == 0)
6c139d6e
AL
820 {
821 if (Debug == true)
0a8e3465 822 clog << " Try to Re-Instate " << I.Name() << endl;
a6568219 823 unsigned long OldBreaks = Cache.BrokenCount();
6c139d6e 824 pkgCache::Version *OldVer = Cache[I].InstallVer;
0a8e3465
AL
825 Flags[I->ID] &= ReInstateTried;
826
74a05226 827 Cache.MarkInstall(I, false, 0, false);
6c139d6e
AL
828 if (Cache[I].InstBroken() == true ||
829 OldBreaks < Cache.BrokenCount())
830 {
831 if (OldVer == 0)
832 Cache.MarkDelete(I);
833 else
74a05226 834 Cache.MarkKeep(I, false, false);
6c139d6e
AL
835 }
836 else
837 if (Debug == true)
0a8e3465 838 clog << "Re-Instated " << I.Name() << " (" << OldBreaks << " vs " << Cache.BrokenCount() << ')' << endl;
6c139d6e
AL
839 }
840
841 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
842 continue;
843
00b47c98 844 if (Debug == true)
d2de5a76 845 clog << "Investigating " << I.Name() << endl;
00b47c98 846
6c139d6e
AL
847 // Isolate the problem dependency
848 PackageKill KillList[100];
849 PackageKill *LEnd = KillList;
421c8d10
AL
850 bool InOr = false;
851 pkgCache::DepIterator Start;
852 pkgCache::DepIterator End;
b2e465d6 853 PackageKill *OldEnd = LEnd;
648e3cb4
AL
854
855 enum {OrRemove,OrKeep} OrOp = OrRemove;
421c8d10
AL
856 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
857 D.end() == false || InOr == true;)
6c139d6e
AL
858 {
859 // Compute a single dependency element (glob or)
648e3cb4
AL
860 if (Start == End)
861 {
862 // Decide what to do
863 if (InOr == true)
864 {
865 if (OldEnd == LEnd && OrOp == OrRemove)
70777d4b
AL
866 {
867 if ((Flags[I->ID] & Protected) != Protected)
00b47c98
AL
868 {
869 if (Debug == true)
870 clog << " Or group remove for " << I.Name() << endl;
70777d4b 871 Cache.MarkDelete(I);
cd14eaf2 872 Change = true;
00b47c98 873 }
70777d4b 874 }
648e3cb4 875 if (OldEnd == LEnd && OrOp == OrKeep)
00b47c98
AL
876 {
877 if (Debug == true)
878 clog << " Or group keep for " << I.Name() << endl;
74a05226 879 Cache.MarkKeep(I, false, false);
cd14eaf2 880 Change = true;
b2e465d6 881 }
648e3cb4
AL
882 }
883
b2e465d6
AL
884 /* We do an extra loop (as above) to finalize the or group
885 processing */
886 InOr = false;
648e3cb4 887 OrOp = OrRemove;
421c8d10 888 D.GlobOr(Start,End);
b2e465d6
AL
889 if (Start.end() == true)
890 break;
cd14eaf2 891
b2e465d6
AL
892 // We only worry about critical deps.
893 if (End.IsCritical() != true)
894 continue;
cd14eaf2 895
648e3cb4
AL
896 InOr = Start != End;
897 OldEnd = LEnd;
cd14eaf2 898 }
421c8d10 899 else
4cc152f9 900 {
421c8d10 901 Start++;
4cc152f9
MV
902 // We only worry about critical deps.
903 if (Start.IsCritical() != true)
904 continue;
905 }
cd14eaf2 906
6c139d6e
AL
907 // Dep is ok
908 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
cd14eaf2
AL
909 {
910 InOr = false;
6c139d6e 911 continue;
cd14eaf2
AL
912 }
913
6c139d6e 914 if (Debug == true)
8b4894fe 915 clog << "Package " << I.Name() << " has broken " << Start.DepType() << " on " << Start.TargetPkg().Name() << endl;
fcf85120
AL
916
917 /* Look across the version list. If there are no possible
918 targets then we keep the package and bail. This is necessary
919 if a package has a dep on another package that cant be found */
b2e465d6 920 SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
fcf85120 921 if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
648e3cb4 922 Start->Type != pkgCache::Dep::Conflicts &&
308c7d30 923 Start->Type != pkgCache::Dep::DpkgBreaks &&
b2e465d6 924 Start->Type != pkgCache::Dep::Obsoletes &&
fcf85120 925 Cache[I].NowBroken() == false)
648e3cb4
AL
926 {
927 if (InOr == true)
928 {
929 /* No keep choice because the keep being OK could be the
930 result of another element in the OR group! */
931 continue;
932 }
933
fcf85120 934 Change = true;
74a05226 935 Cache.MarkKeep(I, false, false);
fcf85120
AL
936 break;
937 }
938
6c139d6e
AL
939 bool Done = false;
940 for (pkgCache::Version **V = VList; *V != 0; V++)
941 {
942 pkgCache::VerIterator Ver(Cache,*V);
943 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
a6bfe583 944
6c139d6e 945 if (Debug == true)
421c8d10 946 clog << " Considering " << Pkg.Name() << ' ' << (int)Scores[Pkg->ID] <<
6c139d6e 947 " as a solution to " << I.Name() << ' ' << (int)Scores[I->ID] << endl;
a6bfe583
AL
948
949 /* Try to fix the package under consideration rather than
950 fiddle with the VList package */
6c139d6e 951 if (Scores[I->ID] <= Scores[Pkg->ID] ||
421c8d10 952 ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
b2e465d6 953 End->Type != pkgCache::Dep::Conflicts &&
308c7d30 954 End->Type != pkgCache::Dep::DpkgBreaks &&
b2e465d6 955 End->Type != pkgCache::Dep::Obsoletes))
6c139d6e 956 {
200f8c52 957 // Try a little harder to fix protected packages..
3b5421b4 958 if ((Flags[I->ID] & Protected) == Protected)
200f8c52
AL
959 {
960 if (DoUpgrade(Pkg) == true)
0296c633 961 {
b2e465d6
AL
962 if (Scores[Pkg->ID] > Scores[I->ID])
963 Scores[Pkg->ID] = Scores[I->ID];
0296c633
AL
964 break;
965 }
966
6c139d6e 967 continue;
200f8c52
AL
968 }
969
970 /* See if a keep will do, unless the package is protected,
648e3cb4
AL
971 then installing it will be necessary */
972 bool Installed = Cache[I].Install();
74a05226 973 Cache.MarkKeep(I, false, false);
6c139d6e
AL
974 if (Cache[I].InstBroken() == false)
975 {
648e3cb4
AL
976 // Unwind operation will be keep now
977 if (OrOp == OrRemove)
978 OrOp = OrKeep;
979
980 // Restore
981 if (InOr == true && Installed == true)
74a05226 982 Cache.MarkInstall(I, false, 0, false);
648e3cb4 983
6c139d6e 984 if (Debug == true)
421c8d10 985 clog << " Holding Back " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
6c139d6e
AL
986 }
987 else
421c8d10 988 {
6c139d6e
AL
989 if (BrokenFix == false || DoUpgrade(I) == false)
990 {
421c8d10
AL
991 // Consider other options
992 if (InOr == false)
993 {
994 if (Debug == true)
995 clog << " Removing " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
996 Cache.MarkDelete(I);
6910a2ac
DK
997 if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID])
998 Scores[I->ID] = Scores[Pkg->ID];
d6ebeb21 999 }
0a8e3465 1000 }
6c139d6e 1001 }
b5dc9785 1002
6c139d6e
AL
1003 Change = true;
1004 Done = true;
1005 break;
1006 }
1007 else
1008 {
a6bfe583
AL
1009 /* This is a conflicts, and the version we are looking
1010 at is not the currently selected version of the
1011 package, which means it is not necessary to
1012 remove/keep */
1013 if (Cache[Pkg].InstallVer != Ver &&
1014 (Start->Type == pkgCache::Dep::Conflicts ||
1015 Start->Type == pkgCache::Dep::Obsoletes))
1016 continue;
308c7d30
IJ
1017
1018 if (Start->Type == pkgCache::Dep::DpkgBreaks)
1019 {
76264cb7
MV
1020 // first, try upgradring the package, if that
1021 // does not help, the breaks goes onto the
1022 // kill list
1023 // FIXME: use DoUpgrade(Pkg) instead?
1024 if (Cache[End] & pkgDepCache::DepGCVer)
1025 {
308c7d30
IJ
1026 if (Debug)
1027 clog << " Upgrading " << Pkg.Name() << " due to Breaks field in " << I.Name() << endl;
1028 Cache.MarkInstall(Pkg, false, 0, false);
1029 continue;
1030 }
308c7d30
IJ
1031 }
1032
648e3cb4 1033 // Skip adding to the kill list if it is protected
6c139d6e
AL
1034 if ((Flags[Pkg->ID] & Protected) != 0)
1035 continue;
a6bfe583
AL
1036
1037 if (Debug == true)
1038 clog << " Added " << Pkg.Name() << " to the remove list" << endl;
6c139d6e
AL
1039
1040 LEnd->Pkg = Pkg;
1041 LEnd->Dep = End;
1042 LEnd++;
0a8e3465 1043
b2e465d6
AL
1044 if (Start->Type != pkgCache::Dep::Conflicts &&
1045 Start->Type != pkgCache::Dep::Obsoletes)
6c139d6e
AL
1046 break;
1047 }
1048 }
1049
1050 // Hm, nothing can possibly satisify this dep. Nuke it.
b2e465d6
AL
1051 if (VList[0] == 0 &&
1052 Start->Type != pkgCache::Dep::Conflicts &&
308c7d30 1053 Start->Type != pkgCache::Dep::DpkgBreaks &&
b2e465d6 1054 Start->Type != pkgCache::Dep::Obsoletes &&
648e3cb4 1055 (Flags[I->ID] & Protected) != Protected)
6c139d6e 1056 {
648e3cb4 1057 bool Installed = Cache[I].Install();
6c139d6e
AL
1058 Cache.MarkKeep(I);
1059 if (Cache[I].InstBroken() == false)
1060 {
648e3cb4
AL
1061 // Unwind operation will be keep now
1062 if (OrOp == OrRemove)
1063 OrOp = OrKeep;
1064
1065 // Restore
1066 if (InOr == true && Installed == true)
74a05226 1067 Cache.MarkInstall(I, false, 0, false);
648e3cb4 1068
6c139d6e 1069 if (Debug == true)
421c8d10 1070 clog << " Holding Back " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl;
6c139d6e
AL
1071 }
1072 else
1073 {
1074 if (Debug == true)
421c8d10 1075 clog << " Removing " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl;
648e3cb4
AL
1076 if (InOr == false)
1077 Cache.MarkDelete(I);
6c139d6e
AL
1078 }
1079
1080 Change = true;
1081 Done = true;
1082 }
1083
421c8d10
AL
1084 // Try some more
1085 if (InOr == true)
1086 continue;
1087
6c139d6e
AL
1088 if (Done == true)
1089 break;
1090 }
1091
1092 // Apply the kill list now
1093 if (Cache[I].InstallVer != 0)
648e3cb4 1094 {
6c139d6e 1095 for (PackageKill *J = KillList; J != LEnd; J++)
6c139d6e 1096 {
648e3cb4
AL
1097 Change = true;
1098 if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
1099 {
b2e465d6 1100 if (J->Dep->Type == pkgCache::Dep::Conflicts ||
76264cb7 1101 J->Dep->Type == pkgCache::Dep::DpkgBreaks ||
b2e465d6 1102 J->Dep->Type == pkgCache::Dep::Obsoletes)
648e3cb4
AL
1103 {
1104 if (Debug == true)
1105 clog << " Fixing " << I.Name() << " via remove of " << J->Pkg.Name() << endl;
1106 Cache.MarkDelete(J->Pkg);
1107 }
1108 }
1109 else
6c139d6e
AL
1110 {
1111 if (Debug == true)
648e3cb4 1112 clog << " Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl;
74a05226 1113 Cache.MarkKeep(J->Pkg, false, false);
6c139d6e 1114 }
b2e465d6 1115
648e3cb4 1116 if (Counter > 1)
b2e465d6
AL
1117 {
1118 if (Scores[I->ID] > Scores[J->Pkg->ID])
1119 Scores[J->Pkg->ID] = Scores[I->ID];
1120 }
648e3cb4
AL
1121 }
1122 }
1123 }
6c139d6e
AL
1124 }
1125
1126 if (Debug == true)
0a8e3465 1127 clog << "Done" << endl;
b2e465d6 1128
6c139d6e 1129 if (Cache.BrokenCount() != 0)
b5dc9785
AL
1130 {
1131 // See if this is the result of a hold
1132 pkgCache::PkgIterator I = Cache.PkgBegin();
1133 for (;I.end() != true; I++)
1134 {
1135 if (Cache[I].InstBroken() == false)
1136 continue;
1137 if ((Flags[I->ID] & Protected) != Protected)
b2e465d6 1138 return _error->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
b5dc9785 1139 }
b2e465d6 1140 return _error->Error(_("Unable to correct problems, you have held broken packages."));
b5dc9785
AL
1141 }
1142
fce72602 1143 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
80fa0d8a
MV
1144 pkgCache::PkgIterator I = Cache.PkgBegin();
1145 for (;I.end() != true; I++) {
1146 if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
120365ce
MV
1147 if(_config->FindI("Debug::pkgAutoRemove",false)) {
1148 std::clog << "Resolve installed new pkg: " << I.Name()
1149 << " (now marking it as auto)" << std::endl;
1150 }
80fa0d8a
MV
1151 Cache[I].Flags |= pkgCache::Flag::Auto;
1152 }
1153 }
1154
1155
0a8e3465
AL
1156 return true;
1157}
1158 /*}}}*/
1159// ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1160// ---------------------------------------------------------------------
1161/* This is the work horse of the soft upgrade routine. It is very gental
1162 in that it does not install or remove any packages. It is assumed that the
1163 system was non-broken previously. */
1164bool pkgProblemResolver::ResolveByKeep()
1165{
74a05226
MV
1166 pkgDepCache::ActionGroup group(Cache);
1167
b2e465d6 1168 unsigned long Size = Cache.Head().PackageCount;
0a8e3465 1169
0a8e3465
AL
1170 MakeScores();
1171
1172 /* We have to order the packages so that the broken fixing pass
1173 operates from highest score to lowest. This prevents problems when
1174 high score packages cause the removal of lower score packages that
1175 would cause the removal of even lower score packages. */
1176 pkgCache::Package **PList = new pkgCache::Package *[Size];
1177 pkgCache::Package **PEnd = PList;
1178 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
1179 *PEnd++ = I;
1180 This = this;
1181 qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
8b4894fe
MV
1182
1183 if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1184 {
1185 clog << "Show Scores" << endl;
1186 for (pkgCache::Package **K = PList; K != PEnd; K++)
1187 if (Scores[(*K)->ID] != 0)
1188 {
1189 pkgCache::PkgIterator Pkg(Cache,*K);
1190 clog << Scores[(*K)->ID] << ' ' << Pkg << std::endl;
1191 }
1192 }
1193
1194 if (Debug == true)
1195 clog << "Entering ResolveByKeep" << endl;
1196
0a8e3465
AL
1197 // Consider each broken package
1198 pkgCache::Package **LastStop = 0;
1199 for (pkgCache::Package **K = PList; K != PEnd; K++)
1200 {
1201 pkgCache::PkgIterator I(Cache,*K);
1202
1203 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
1204 continue;
1205
1206 /* Keep the package. If this works then great, otherwise we have
b2e465d6 1207 to be significantly more agressive and manipulate its dependencies */
0a8e3465
AL
1208 if ((Flags[I->ID] & Protected) == 0)
1209 {
1210 if (Debug == true)
1211 clog << "Keeping package " << I.Name() << endl;
74a05226 1212 Cache.MarkKeep(I, false, false);
0a8e3465
AL
1213 if (Cache[I].InstBroken() == false)
1214 {
b2e465d6 1215 K = PList - 1;
0a8e3465
AL
1216 continue;
1217 }
1218 }
1219
1220 // Isolate the problem dependencies
1221 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
1222 {
c5532863
AL
1223 DepIterator Start;
1224 DepIterator End;
1225 D.GlobOr(Start,End);
1226
0a8e3465
AL
1227 // We only worry about critical deps.
1228 if (End.IsCritical() != true)
1229 continue;
1230
1231 // Dep is ok
1232 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
1233 continue;
c5532863
AL
1234
1235 /* Hm, the group is broken.. I suppose the best thing to do is to
1236 is to try every combination of keep/not-keep for the set, but thats
1237 slow, and this never happens, just be conservative and assume the
1238 list of ors is in preference and keep till it starts to work. */
1239 while (true)
0a8e3465 1240 {
c5532863 1241 if (Debug == true)
8b4894fe
MV
1242 clog << "Package " << I.Name() << " has broken " << Start.DepType() << " on " << Start.TargetPkg().Name() << endl;
1243
c5532863
AL
1244 // Look at all the possible provides on this package
1245 SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
1246 for (pkgCache::Version **V = VList; *V != 0; V++)
0a8e3465 1247 {
c5532863
AL
1248 pkgCache::VerIterator Ver(Cache,*V);
1249 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
1250
1251 // It is not keepable
1252 if (Cache[Pkg].InstallVer == 0 ||
1253 Pkg->CurrentVer == 0)
1254 continue;
1255
1256 if ((Flags[I->ID] & Protected) == 0)
1257 {
1258 if (Debug == true)
8b4894fe 1259 clog << " Keeping Package " << Pkg.Name() << " due to " << Start.DepType() << endl;
74a05226 1260 Cache.MarkKeep(Pkg, false, false);
c5532863
AL
1261 }
1262
1263 if (Cache[I].InstBroken() == false)
1264 break;
0a8e3465
AL
1265 }
1266
1267 if (Cache[I].InstBroken() == false)
1268 break;
0a8e3465 1269
c5532863
AL
1270 if (Start == End)
1271 break;
1272 Start++;
1273 }
1274
0a8e3465
AL
1275 if (Cache[I].InstBroken() == false)
1276 break;
1277 }
1278
1279 if (Cache[I].InstBroken() == true)
1280 continue;
1281
1282 // Restart again.
1283 if (K == LastStop)
1284 return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.Name());
1285 LastStop = K;
b2e465d6 1286 K = PList - 1;
0a8e3465 1287 }
6c139d6e
AL
1288
1289 return true;
1290}
1291 /*}}}*/
3b5421b4
AL
1292// ProblemResolver::InstallProtect - Install all protected packages /*{{{*/
1293// ---------------------------------------------------------------------
1294/* This is used to make sure protected packages are installed */
1295void pkgProblemResolver::InstallProtect()
1296{
74a05226
MV
1297 pkgDepCache::ActionGroup group(Cache);
1298
3b5421b4
AL
1299 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
1300 {
1301 if ((Flags[I->ID] & Protected) == Protected)
1302 {
1303 if ((Flags[I->ID] & ToRemove) == ToRemove)
1304 Cache.MarkDelete(I);
c15f5690
MV
1305 else
1306 {
da543ed8
OS
1307 // preserve the information whether the package was auto
1308 // or manually installed
c15f5690
MV
1309 bool autoInst = (Cache[I].Flags & pkgCache::Flag::Auto);
1310 Cache.MarkInstall(I, false, 0, !autoInst);
1311 }
3b5421b4
AL
1312 }
1313 }
1314}
1315 /*}}}*/
b2e465d6
AL
1316// PrioSortList - Sort a list of versions by priority /*{{{*/
1317// ---------------------------------------------------------------------
1318/* This is ment to be used in conjunction with AllTargets to get a list
1319 of versions ordered by preference. */
1320static pkgCache *PrioCache;
1321static int PrioComp(const void *A,const void *B)
1322{
1323 pkgCache::VerIterator L(*PrioCache,*(pkgCache::Version **)A);
1324 pkgCache::VerIterator R(*PrioCache,*(pkgCache::Version **)B);
1325
1326 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential &&
b8c0f9b7
AL
1327 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
1328 return 1;
b2e465d6 1329 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
b8c0f9b7
AL
1330 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
1331 return -1;
b2e465d6
AL
1332
1333 if (L->Priority != R->Priority)
b8c0f9b7 1334 return R->Priority - L->Priority;
b2e465d6
AL
1335 return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
1336}
1337void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
1338{
1339 unsigned long Count = 0;
1340 PrioCache = &Cache;
1341 for (pkgCache::Version **I = List; *I != 0; I++)
1342 Count++;
1343 qsort(List,Count,sizeof(*List),PrioComp);
1344}
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 &&
b26daf93 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 /*}}}*/