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