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