]> git.saurik.com Git - apt.git/blob - apt-pkg/algorithms.cc
* test/versions.lst:
[apt.git] / apt-pkg / algorithms.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: algorithms.cc,v 1.44 2002/11/28 18:49:16 jgg Exp $
4 /* ######################################################################
5
6 Algorithms - A set of misc algorithms
7
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
14 ##################################################################### */
15 /*}}}*/
16 // Include Files /*{{{*/
17 #include <apt-pkg/algorithms.h>
18 #include <apt-pkg/error.h>
19 #include <apt-pkg/configuration.h>
20 #include <apt-pkg/version.h>
21 #include <apt-pkg/sptr.h>
22 #include <apt-pkg/acquire-item.h>
23
24 #include <apti18n.h>
25 #include <sys/types.h>
26 #include <cstdlib>
27 #include <algorithm>
28 #include <iostream>
29 /*}}}*/
30 using namespace std;
31
32 pkgProblemResolver *pkgProblemResolver::This = 0;
33
34 // Simulate::Simulate - Constructor /*{{{*/
35 // ---------------------------------------------------------------------
36 /* The legacy translations here of input Pkg iterators is obsolete,
37 this is not necessary since the pkgCaches are fully shared now. */
38 pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache),
39 iPolicy(Cache),
40 Sim(&Cache->GetCache(),&iPolicy),
41 group(Sim)
42 {
43 Sim.Init(0);
44 Flags = new unsigned char[Cache->Head().PackageCount];
45 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
46
47 // Fake a filename so as not to activate the media swapping
48 string Jnk = "SIMULATE";
49 for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
50 FileNames[I] = Jnk;
51 }
52 /*}}}*/
53 // Simulate::Describe - Describe a package /*{{{*/
54 // ---------------------------------------------------------------------
55 /* Parameter Current == true displays the current package version,
56 Parameter Candidate == true displays the candidate package version */
57 void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candidate)
58 {
59 VerIterator Ver(Sim);
60
61 out << Pkg.FullName(true);
62
63 if (Current == true)
64 {
65 Ver = Pkg.CurrentVer();
66 if (Ver.end() == false)
67 out << " [" << Ver.VerStr() << ']';
68 }
69
70 if (Candidate == true)
71 {
72 Ver = Sim[Pkg].CandidateVerIter(Sim);
73 if (Ver.end() == true)
74 return;
75
76 out << " (" << Ver.VerStr() << ' ' << Ver.RelStr() << ')';
77 }
78 }
79 /*}}}*/
80 // Simulate::Install - Simulate unpacking of a package /*{{{*/
81 // ---------------------------------------------------------------------
82 /* */
83 bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
84 {
85 // Adapt the iterator
86 PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
87 Flags[Pkg->ID] = 1;
88
89 cout << "Inst ";
90 Describe(Pkg,cout,true,true);
91 Sim.MarkInstall(Pkg,false);
92
93 // Look for broken conflicts+predepends.
94 for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
95 {
96 if (Sim[I].InstallVer == 0)
97 continue;
98
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 ||
105 Start->Type == pkgCache::Dep::DpkgBreaks ||
106 Start->Type == pkgCache::Dep::Obsoletes ||
107 End->Type == pkgCache::Dep::PreDepends)
108 {
109 if ((Sim[End] & pkgDepCache::DepGInstall) == 0)
110 {
111 cout << " [" << I.FullName(false) << " on " << Start.TargetPkg().FullName(false) << ']';
112 if (Start->Type == pkgCache::Dep::Conflicts)
113 _error->Error("Fatal, conflicts violated %s",I.FullName(false).c_str());
114 }
115 }
116 }
117 }
118
119 if (Sim.BrokenCount() != 0)
120 ShortBreaks();
121 else
122 cout << endl;
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. */
131 bool pkgSimulate::Configure(PkgIterator iPkg)
132 {
133 // Adapt the iterator
134 PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
135
136 Flags[Pkg->ID] = 2;
137
138 if (Sim[Pkg].InstBroken() == true)
139 {
140 cout << "Conf " << Pkg.FullName(false) << " broken" << endl;
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
151 if (D->Type == pkgCache::Dep::Obsoletes)
152 cout << " Obsoletes:" << D.TargetPkg().FullName(false);
153 else if (D->Type == pkgCache::Dep::Conflicts)
154 cout << " Conflicts:" << D.TargetPkg().FullName(false);
155 else if (D->Type == pkgCache::Dep::DpkgBreaks)
156 cout << " Breaks:" << D.TargetPkg().FullName(false);
157 else
158 cout << " Depends:" << D.TargetPkg().FullName(false);
159 }
160 cout << endl;
161
162 _error->Error("Conf Broken %s",Pkg.FullName(false).c_str());
163 }
164 else
165 {
166 cout << "Conf ";
167 Describe(Pkg,cout,false,true);
168 }
169
170 if (Sim.BrokenCount() != 0)
171 ShortBreaks();
172 else
173 cout << endl;
174
175 return true;
176 }
177 /*}}}*/
178 // Simulate::Remove - Simulate the removal of a package /*{{{*/
179 // ---------------------------------------------------------------------
180 /* */
181 bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
182 {
183 // Adapt the iterator
184 PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
185
186 Flags[Pkg->ID] = 3;
187 Sim.MarkDelete(Pkg);
188
189 if (Purge == true)
190 cout << "Purg ";
191 else
192 cout << "Remv ";
193 Describe(Pkg,cout,true,false);
194
195 if (Sim.BrokenCount() != 0)
196 ShortBreaks();
197 else
198 cout << endl;
199
200 return true;
201 }
202 /*}}}*/
203 // Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
204 // ---------------------------------------------------------------------
205 /* */
206 void pkgSimulate::ShortBreaks()
207 {
208 cout << " [";
209 for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
210 {
211 if (Sim[I].InstBroken() == true)
212 {
213 if (Flags[I->ID] == 0)
214 cout << I.FullName(false) << ' ';
215 /* else
216 cout << I.Name() << "! ";*/
217 }
218 }
219 cout << ']' << endl;
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. */
227 bool pkgApplyStatus(pkgDepCache &Cache)
228 {
229 pkgDepCache::ActionGroup group(Cache);
230
231 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
232 {
233 if (I->VersionList == 0)
234 continue;
235
236 // Only choice for a ReInstReq package is to reinstall
237 if (I->InstState == pkgCache::State::ReInstReq ||
238 I->InstState == pkgCache::State::HoldReInstReq)
239 {
240 if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
241 Cache.MarkKeep(I, false, false);
242 else
243 {
244 // Is this right? Will dpkg choke on an upgrade?
245 if (Cache[I].CandidateVer != 0 &&
246 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
247 Cache.MarkInstall(I, false, 0, false);
248 else
249 return _error->Error(_("The package %s needs to be reinstalled, "
250 "but I can't find an archive for it."),I.FullName(true).c_str());
251 }
252
253 continue;
254 }
255
256 switch (I->CurrentState)
257 {
258 /* This means installation failed somehow - it does not need to be
259 re-unpacked (probably) */
260 case pkgCache::State::UnPacked:
261 case pkgCache::State::HalfConfigured:
262 case pkgCache::State::TriggersAwaited:
263 case pkgCache::State::TriggersPending:
264 if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) ||
265 I.State() != pkgCache::PkgIterator::NeedsUnpack)
266 Cache.MarkKeep(I, false, false);
267 else
268 {
269 if (Cache[I].CandidateVer != 0 &&
270 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
271 Cache.MarkInstall(I, true, 0, false);
272 else
273 Cache.MarkDelete(I);
274 }
275 break;
276
277 // This means removal failed
278 case pkgCache::State::HalfInstalled:
279 Cache.MarkDelete(I);
280 break;
281
282 default:
283 if (I->InstState != pkgCache::State::Ok)
284 return _error->Error("The package %s is not ok and I "
285 "don't know how to fix it!",I.FullName(false).c_str());
286 }
287 }
288 return true;
289 }
290 /*}}}*/
291 // FixBroken - Fix broken packages /*{{{*/
292 // ---------------------------------------------------------------------
293 /* This autoinstalls every broken package and then runs the problem resolver
294 on the result. */
295 bool pkgFixBroken(pkgDepCache &Cache)
296 {
297 pkgDepCache::ActionGroup group(Cache);
298
299 // Auto upgrade all broken packages
300 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
301 if (Cache[I].NowBroken() == true)
302 Cache.MarkInstall(I, true, 0, false);
303
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
312 if (Cache[I].InstVerIter(Cache).Downloadable() == false)
313 continue;
314
315 Cache.MarkInstall(I, true, 0, false);
316 }
317
318 pkgProblemResolver Fix(&Cache);
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
328 The problem resolver is used to resolve the problems.
329 */
330 bool pkgDistUpgrade(pkgDepCache &Cache)
331 {
332 pkgDepCache::ActionGroup group(Cache);
333
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
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)
345 Cache.MarkInstall(I, true, 0, false);
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++)
350 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
351 Cache.MarkInstall(I, true, 0, false);
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)
357 Cache.MarkInstall(I, false, 0, false);
358
359 pkgProblemResolver Fix(&Cache);
360
361 // Hold back held packages.
362 if (_config->FindB("APT::Ignore-Hold",false) == false)
363 {
364 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
365 {
366 if (I->SelectedState == pkgCache::State::Hold)
367 {
368 Fix.Protect(I);
369 Cache.MarkKeep(I, false, false);
370 }
371 }
372 }
373
374 return Fix.Resolve();
375 }
376 /*}}}*/
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 */
382 bool pkgAllUpgrade(pkgDepCache &Cache)
383 {
384 pkgDepCache::ActionGroup group(Cache);
385
386 pkgProblemResolver Fix(&Cache);
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
397 if (_config->FindB("APT::Ignore-Hold",false) == false)
398 if (I->SelectedState == pkgCache::State::Hold)
399 continue;
400
401 if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
402 Cache.MarkInstall(I, false, 0, false);
403 }
404
405 return Fix.ResolveByKeep();
406 }
407 /*}}}*/
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. */
413 bool pkgMinimizeUpgrade(pkgDepCache &Cache)
414 {
415 pkgDepCache::ActionGroup group(Cache);
416
417 if (Cache.BrokenCount() != 0)
418 return false;
419
420 // We loop for 10 tries to get the minimal set size.
421 bool Change = false;
422 unsigned int Count = 0;
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;
431
432 // Keep it and see if that is OK
433 Cache.MarkKeep(I, false, false);
434 if (Cache.BrokenCount() != 0)
435 Cache.MarkInstall(I, false, 0, false);
436 else
437 {
438 // If keep didnt actually do anything then there was no change..
439 if (Cache[I].Upgrade() == false)
440 Change = true;
441 }
442 }
443 Count++;
444 }
445 while (Change == true && Count < 10);
446
447 if (Cache.BrokenCount() != 0)
448 return _error->Error("Internal Error in pkgMinimizeUpgrade");
449
450 return true;
451 }
452 /*}}}*/
453 // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
454 // ---------------------------------------------------------------------
455 /* */
456 pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : Cache(*pCache)
457 {
458 // Allocate memory
459 unsigned long Size = Cache.Head().PackageCount;
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
465 Debug = _config->FindB("Debug::pkgProblemResolver",false);
466 }
467 /*}}}*/
468 // ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
469 // ---------------------------------------------------------------------
470 /* */
471 pkgProblemResolver::~pkgProblemResolver()
472 {
473 delete [] Scores;
474 delete [] Flags;
475 }
476 /*}}}*/
477 // ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
478 // ---------------------------------------------------------------------
479 /* */
480 int 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 /* */
494 void pkgProblemResolver::MakeScores()
495 {
496 unsigned long Size = Cache.Head().PackageCount;
497 memset(Scores,0,sizeof(*Scores)*Size);
498
499 // Important Required Standard Optional Extra
500 signed short PrioMap[] = {
501 0,
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)
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);
511 signed short PrioRecommends = _config->FindI("pkgProblemResolver::Scores::Recommends",1);
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
525 << " Recommends => " << PrioRecommends << endl
526 << " AddProtected => " << AddProtected << endl
527 << " AddEssential => " << AddEssential << endl;
528
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
537 /* This is arbitrary, it should be high enough to elevate an
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) */
541 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
542 Score += PrioEssentials;
543
544 // We transform the priority
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
549 on the same level. We enhance the score of installed packages
550 if those are not obsolete
551 */
552 if (I->CurrentVer != 0 && Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable())
553 Score += PrioInstalledAndNotObsolete;
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 {
564 if (D->Type == pkgCache::Dep::Depends ||
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;
569 }
570 }
571
572 // Copy the scores to advoid additive looping
573 SPtrArray<signed short> OldScores = new signed short[Size];
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 ||
588 (D->Type != pkgCache::Dep::Depends &&
589 D->Type != pkgCache::Dep::PreDepends &&
590 D->Type != pkgCache::Dep::Recommends))
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++)
613 {
614 if ((Flags[I->ID] & Protected) != 0)
615 Scores[I->ID] += AddProtected;
616 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
617 Scores[I->ID] += AddEssential;
618 }
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 */
625 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
626 {
627 pkgDepCache::ActionGroup group(Cache);
628
629 if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
630 return false;
631 if ((Flags[Pkg->ID] & Protected) == Protected)
632 return false;
633
634 Flags[Pkg->ID] &= ~Upgradable;
635
636 bool WasKept = Cache[Pkg].Keep();
637 Cache.MarkInstall(Pkg, false, 0, false);
638
639 // This must be a virtual package or something like that.
640 if (Cache[Pkg].InstVerIter(Cache).end() == true)
641 return false;
642
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;
650 for (bool LastOR = true; D.end() == false && LastOR == true;)
651 {
652 LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
653 ++D;
654 if (LastOR == true)
655 End = D;
656 }
657
658 // We only worry about critical deps.
659 if (End.IsCritical() != true)
660 continue;
661
662 // Iterate over all the members in the or group
663 while (1)
664 {
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)
674 clog << " Reinst Failed because of protected " << P.FullName(false) << endl;
675 Fail = true;
676 }
677 else
678 {
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)
685 clog << " Reinst Failed because of " << P.FullName(false) << endl;
686 Fail = true;
687 }
688 else
689 {
690 Fail = false;
691 break;
692 }
693 }
694 else
695 {
696 /* We let the algorithm deal with conflicts on its next iteration,
697 it is much smarter than us */
698 if (Start->Type == pkgCache::Dep::Conflicts ||
699 Start->Type == pkgCache::Dep::DpkgBreaks ||
700 Start->Type == pkgCache::Dep::Obsoletes)
701 break;
702
703 if (Debug == true)
704 clog << " Reinst Failed early because of " << Start.TargetPkg().FullName(false) << endl;
705 Fail = true;
706 }
707 }
708
709 if (Start == End)
710 break;
711 Start++;
712 }
713 if (Fail == true)
714 break;
715 }
716
717 // Undo our operations - it might be smart to undo everything this did..
718 if (Fail == true)
719 {
720 if (WasKept == true)
721 Cache.MarkKeep(Pkg, false, false);
722 else
723 Cache.MarkDelete(Pkg);
724 return false;
725 }
726
727 if (Debug == true)
728 clog << " Re-Instated " << Pkg.FullName(false) << endl;
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. */
746 bool pkgProblemResolver::Resolve(bool BrokenFix)
747 {
748 pkgDepCache::ActionGroup group(Cache);
749
750 unsigned long Size = Cache.Head().PackageCount;
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 {
765 Cache.MarkInstall(I, false, 0, false);
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)
778 clog << "Starting" << endl;
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. */
786 SPtrArray<pkgCache::Package *> PList = new pkgCache::Package *[Size];
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);
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 }
803
804 if (Debug == true)
805 clog << "Starting 2" << endl;
806
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;
812 bool const TryFixByInstall = _config->FindB("pkgProblemResolver::FixByInstall", true);
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 &&
825 (Flags[I->ID] & Protected) == 0 &&
826 (Flags[I->ID] & ReInstateTried) == 0)
827 {
828 if (Debug == true)
829 clog << " Try to Re-Instate (" << Counter << ") " << I.FullName(false) << endl;
830 unsigned long OldBreaks = Cache.BrokenCount();
831 pkgCache::Version *OldVer = Cache[I].InstallVer;
832 Flags[I->ID] &= ReInstateTried;
833
834 Cache.MarkInstall(I, false, 0, false);
835 if (Cache[I].InstBroken() == true ||
836 OldBreaks < Cache.BrokenCount())
837 {
838 if (OldVer == 0)
839 Cache.MarkDelete(I);
840 else
841 Cache.MarkKeep(I, false, false);
842 }
843 else
844 if (Debug == true)
845 clog << "Re-Instated " << I.FullName(false) << " (" << OldBreaks << " vs " << Cache.BrokenCount() << ')' << endl;
846 }
847
848 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
849 continue;
850
851 if (Debug == true)
852 clog << "Investigating (" << Counter << ") " << I << endl;
853
854 // Isolate the problem dependency
855 PackageKill KillList[100];
856 PackageKill *LEnd = KillList;
857 bool InOr = false;
858 pkgCache::DepIterator Start;
859 pkgCache::DepIterator End;
860 PackageKill *OldEnd = LEnd;
861
862 enum {OrRemove,OrKeep} OrOp = OrRemove;
863 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
864 D.end() == false || InOr == true;)
865 {
866 // Compute a single dependency element (glob or)
867 if (Start == End)
868 {
869 // Decide what to do
870 if (InOr == true && OldEnd == LEnd)
871 {
872 if (OrOp == OrRemove)
873 {
874 if ((Flags[I->ID] & Protected) != Protected)
875 {
876 if (Debug == true)
877 clog << " Or group remove for " << I.FullName(false) << endl;
878 Cache.MarkDelete(I);
879 Change = true;
880 }
881 }
882 else if (OrOp == OrKeep)
883 {
884 if (Debug == true)
885 clog << " Or group keep for " << I.FullName(false) << endl;
886 Cache.MarkKeep(I, false, false);
887 Change = true;
888 }
889 }
890
891 /* We do an extra loop (as above) to finalize the or group
892 processing */
893 InOr = false;
894 OrOp = OrRemove;
895 D.GlobOr(Start,End);
896 if (Start.end() == true)
897 break;
898
899 // We only worry about critical deps.
900 if (End.IsCritical() != true)
901 continue;
902
903 InOr = Start != End;
904 OldEnd = LEnd;
905 }
906 else
907 {
908 Start++;
909 // We only worry about critical deps.
910 if (Start.IsCritical() != true)
911 continue;
912 }
913
914 // Dep is ok
915 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
916 {
917 InOr = false;
918 continue;
919 }
920
921 if (Debug == true)
922 clog << "Broken " << Start << endl;
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 */
927 SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
928 if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
929 Start->Type != pkgCache::Dep::Conflicts &&
930 Start->Type != pkgCache::Dep::DpkgBreaks &&
931 Start->Type != pkgCache::Dep::Obsoletes &&
932 Cache[I].NowBroken() == false)
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
941 Change = true;
942 Cache.MarkKeep(I, false, false);
943 break;
944 }
945
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();
951
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))
960 {
961 if (Debug)
962 clog << " Conflicts//Breaks against version "
963 << Ver.VerStr() << " for " << Pkg.Name()
964 << " but that is not InstVer, ignoring"
965 << endl;
966 continue;
967 }
968
969 if (Debug == true)
970 clog << " Considering " << Pkg.FullName(false) << ' ' << (int)Scores[Pkg->ID] <<
971 " as a solution to " << I.FullName(false) << ' ' << (int)Scores[I->ID] << endl;
972
973 /* Try to fix the package under consideration rather than
974 fiddle with the VList package */
975 if (Scores[I->ID] <= Scores[Pkg->ID] ||
976 ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
977 End->Type != pkgCache::Dep::Conflicts &&
978 End->Type != pkgCache::Dep::DpkgBreaks &&
979 End->Type != pkgCache::Dep::Obsoletes))
980 {
981 // Try a little harder to fix protected packages..
982 if ((Flags[I->ID] & Protected) == Protected)
983 {
984 if (DoUpgrade(Pkg) == true)
985 {
986 if (Scores[Pkg->ID] > Scores[I->ID])
987 Scores[Pkg->ID] = Scores[I->ID];
988 break;
989 }
990
991 continue;
992 }
993
994 /* See if a keep will do, unless the package is protected,
995 then installing it will be necessary */
996 bool Installed = Cache[I].Install();
997 Cache.MarkKeep(I, false, false);
998 if (Cache[I].InstBroken() == false)
999 {
1000 // Unwind operation will be keep now
1001 if (OrOp == OrRemove)
1002 OrOp = OrKeep;
1003
1004 // Restore
1005 if (InOr == true && Installed == true)
1006 Cache.MarkInstall(I, false, 0, false);
1007
1008 if (Debug == true)
1009 clog << " Holding Back " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
1010 }
1011 else
1012 {
1013 if (BrokenFix == false || DoUpgrade(I) == false)
1014 {
1015 // Consider other options
1016 if (InOr == false)
1017 {
1018 if (Debug == true)
1019 clog << " Removing " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
1020 Cache.MarkDelete(I);
1021 if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID])
1022 Scores[I->ID] = Scores[Pkg->ID];
1023 }
1024 else if (TryFixByInstall == true &&
1025 Start.TargetPkg()->CurrentVer == 0 &&
1026 Cache[Start.TargetPkg()].Delete() == false &&
1027 (Flags[Start.TargetPkg()->ID] & ToRemove) != ToRemove &&
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… */
1035 if (Debug == true)
1036 clog << " Try Installing " << Start.TargetPkg() << " before changing " << I.FullName(false) << std::endl;
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 }
1043 }
1044 }
1045
1046 Change = true;
1047 Done = true;
1048 break;
1049 }
1050 else
1051 {
1052 if (Start->Type == pkgCache::Dep::DpkgBreaks)
1053 {
1054 // first, try upgradring the package, if that
1055 // does not help, the breaks goes onto the
1056 // kill list
1057 //
1058 // FIXME: use DoUpgrade(Pkg) instead?
1059 if (Cache[End] & pkgDepCache::DepGCVer)
1060 {
1061 if (Debug)
1062 clog << " Upgrading " << Pkg.FullName(false) << " due to Breaks field in " << I.FullName(false) << endl;
1063 Cache.MarkInstall(Pkg, false, 0, false);
1064 continue;
1065 }
1066 }
1067
1068 // Skip adding to the kill list if it is protected
1069 if ((Flags[Pkg->ID] & Protected) != 0)
1070 continue;
1071
1072 if (Debug == true)
1073 clog << " Added " << Pkg.FullName(false) << " to the remove list" << endl;
1074
1075 LEnd->Pkg = Pkg;
1076 LEnd->Dep = End;
1077 LEnd++;
1078
1079 if (Start->Type != pkgCache::Dep::Conflicts &&
1080 Start->Type != pkgCache::Dep::Obsoletes)
1081 break;
1082 }
1083 }
1084
1085 // Hm, nothing can possibly satisify this dep. Nuke it.
1086 if (VList[0] == 0 &&
1087 Start->Type != pkgCache::Dep::Conflicts &&
1088 Start->Type != pkgCache::Dep::DpkgBreaks &&
1089 Start->Type != pkgCache::Dep::Obsoletes &&
1090 (Flags[I->ID] & Protected) != Protected)
1091 {
1092 bool Installed = Cache[I].Install();
1093 Cache.MarkKeep(I);
1094 if (Cache[I].InstBroken() == false)
1095 {
1096 // Unwind operation will be keep now
1097 if (OrOp == OrRemove)
1098 OrOp = OrKeep;
1099
1100 // Restore
1101 if (InOr == true && Installed == true)
1102 Cache.MarkInstall(I, false, 0, false);
1103
1104 if (Debug == true)
1105 clog << " Holding Back " << I.FullName(false) << " because I can't find " << Start.TargetPkg().FullName(false) << endl;
1106 }
1107 else
1108 {
1109 if (Debug == true)
1110 clog << " Removing " << I.FullName(false) << " because I can't find " << Start.TargetPkg().FullName(false) << endl;
1111 if (InOr == false)
1112 Cache.MarkDelete(I);
1113 }
1114
1115 Change = true;
1116 Done = true;
1117 }
1118
1119 // Try some more
1120 if (InOr == true)
1121 continue;
1122
1123 if (Done == true)
1124 break;
1125 }
1126
1127 // Apply the kill list now
1128 if (Cache[I].InstallVer != 0)
1129 {
1130 for (PackageKill *J = KillList; J != LEnd; J++)
1131 {
1132 Change = true;
1133 if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
1134 {
1135 if (J->Dep->Type == pkgCache::Dep::Conflicts ||
1136 J->Dep->Type == pkgCache::Dep::DpkgBreaks ||
1137 J->Dep->Type == pkgCache::Dep::Obsoletes)
1138 {
1139 if (Debug == true)
1140 clog << " Fixing " << I.FullName(false) << " via remove of " << J->Pkg.FullName(false) << endl;
1141 Cache.MarkDelete(J->Pkg);
1142 }
1143 }
1144 else
1145 {
1146 if (Debug == true)
1147 clog << " Fixing " << I.FullName(false) << " via keep of " << J->Pkg.FullName(false) << endl;
1148 Cache.MarkKeep(J->Pkg, false, false);
1149 }
1150
1151 if (Counter > 1)
1152 {
1153 if (Scores[I->ID] > Scores[J->Pkg->ID])
1154 Scores[J->Pkg->ID] = Scores[I->ID];
1155 }
1156 }
1157 }
1158 }
1159 }
1160
1161 if (Debug == true)
1162 clog << "Done" << endl;
1163
1164 if (Cache.BrokenCount() != 0)
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)
1173 return _error->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
1174 }
1175 return _error->Error(_("Unable to correct problems, you have held broken packages."));
1176 }
1177
1178 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
1179 pkgCache::PkgIterator I = Cache.PkgBegin();
1180 for (;I.end() != true; I++) {
1181 if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
1182 if(_config->FindI("Debug::pkgAutoRemove",false)) {
1183 std::clog << "Resolve installed new pkg: " << I.FullName(false)
1184 << " (now marking it as auto)" << std::endl;
1185 }
1186 Cache[I].Flags |= pkgCache::Flag::Auto;
1187 }
1188 }
1189
1190
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. */
1199 bool pkgProblemResolver::ResolveByKeep()
1200 {
1201 pkgDepCache::ActionGroup group(Cache);
1202
1203 unsigned long Size = Cache.Head().PackageCount;
1204
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);
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
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
1242 to be significantly more agressive and manipulate its dependencies */
1243 if ((Flags[I->ID] & Protected) == 0)
1244 {
1245 if (Debug == true)
1246 clog << "Keeping package " << I.FullName(false) << endl;
1247 Cache.MarkKeep(I, false, false);
1248 if (Cache[I].InstBroken() == false)
1249 {
1250 K = PList - 1;
1251 continue;
1252 }
1253 }
1254
1255 // Isolate the problem dependencies
1256 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
1257 {
1258 DepIterator Start;
1259 DepIterator End;
1260 D.GlobOr(Start,End);
1261
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;
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)
1275 {
1276 if (Debug == true)
1277 clog << "Package " << I.FullName(false) << " " << Start << endl;
1278
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++)
1282 {
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)
1294 clog << " Keeping Package " << Pkg.FullName(false) << " due to " << Start.DepType() << endl;
1295 Cache.MarkKeep(Pkg, false, false);
1296 }
1297
1298 if (Cache[I].InstBroken() == false)
1299 break;
1300 }
1301
1302 if (Cache[I].InstBroken() == false)
1303 break;
1304
1305 if (Start == End)
1306 break;
1307 Start++;
1308 }
1309
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)
1319 return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.FullName(false).c_str());
1320 LastStop = K;
1321 K = PList - 1;
1322 }
1323
1324 return true;
1325 }
1326 /*}}}*/
1327 // ProblemResolver::InstallProtect - Install all protected packages /*{{{*/
1328 // ---------------------------------------------------------------------
1329 /* This is used to make sure protected packages are installed */
1330 void pkgProblemResolver::InstallProtect()
1331 {
1332 pkgDepCache::ActionGroup group(Cache);
1333
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);
1340 else
1341 {
1342 // preserve the information whether the package was auto
1343 // or manually installed
1344 bool autoInst = (Cache[I].Flags & pkgCache::Flag::Auto);
1345 Cache.MarkInstall(I, false, 0, !autoInst);
1346 }
1347 }
1348 }
1349 }
1350 /*}}}*/
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. */
1355 static pkgCache *PrioCache;
1356 static 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 &&
1362 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
1363 return 1;
1364 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
1365 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
1366 return -1;
1367
1368 if (L->Priority != R->Priority)
1369 return R->Priority - L->Priority;
1370 return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
1371 }
1372 void 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 /*}}}*/
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 */
1386 bool ListUpdate(pkgAcquireStatus &Stat,
1387 pkgSourceList &List,
1388 int PulseInterval)
1389 {
1390 pkgAcquire::RunResult res;
1391 pkgAcquire Fetcher;
1392 if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false)
1393 return false;
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
1421 ::URI uri((*I)->DescURI());
1422 uri.User.clear();
1423 uri.Password.clear();
1424 string descUri = string(uri);
1425 _error->Warning(_("Failed to fetch %s %s\n"), descUri.c_str(),
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 &&
1441 (_config->FindB("APT::Get::List-Cleanup",true) == true &&
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)
1451 _error->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead."));
1452 else if (Failed == true)
1453 return _error->Error(_("Some index files failed to download. They have been ignored, or old ones used instead."));
1454
1455
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
1461 RunScripts("APT::Update::Post-Invoke");
1462 return true;
1463 }
1464 /*}}}*/