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