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