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