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