]>
git.saurik.com Git - apt.git/blob - apt-pkg/algorithms.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: algorithms.cc,v 1.7 1998/10/20 04:33:13 jgg Exp $
4 /* ######################################################################
6 Algorithms - A set of misc algorithms
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.
14 ##################################################################### */
16 // Include Files /*{{{*/
18 #pragma implementation "apt-pkg/algorithms.h"
20 #include <apt-pkg/algorithms.h>
21 #include <apt-pkg/error.h>
22 #include <apt-pkg/configuration.h>
26 pkgProblemResolver
*pkgProblemResolver::This
= 0;
28 // Simulate::Simulate - Constructor /*{{{*/
29 // ---------------------------------------------------------------------
31 pkgSimulate::pkgSimulate(pkgDepCache
&Cache
) : pkgPackageManager(Cache
),
34 Flags
= new unsigned char[Cache
.HeaderP
->PackageCount
];
35 memset(Flags
,0,sizeof(*Flags
)*Cache
.HeaderP
->PackageCount
);
38 // Simulate::Install - Simulate unpacking of a package /*{{{*/
39 // ---------------------------------------------------------------------
41 bool pkgSimulate::Install(PkgIterator iPkg
,string
/*File*/)
44 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name());
47 clog
<< "Inst " << Pkg
.Name();
48 Sim
.MarkInstall(Pkg
,false);
50 // Look for broken conflicts+predepends.
51 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; I
++)
53 if (Sim
[I
].InstallVer
== 0)
56 for (DepIterator D
= Sim
[I
].InstVerIter(Sim
).DependsList(); D
.end() == false; D
++)
57 if (D
->Type
== pkgCache::Dep::Conflicts
|| D
->Type
== pkgCache::Dep::PreDepends
)
59 if ((Sim
[D
] & pkgDepCache::DepInstall
) == 0)
61 clog
<< " [" << I
.Name() << " on " << D
.TargetPkg().Name() << ']';
62 if (D
->Type
== pkgCache::Dep::Conflicts
)
63 _error
->Error("Fatal, conflicts violated %s",I
.Name());
68 if (Sim
.BrokenCount() != 0)
75 // Simulate::Configure - Simulate configuration of a Package /*{{{*/
76 // ---------------------------------------------------------------------
77 /* This is not an acurate simulation of relatity, we should really not
78 install the package.. For some investigations it may be necessary
80 bool pkgSimulate::Configure(PkgIterator iPkg
)
83 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name());
86 // Sim.MarkInstall(Pkg,false);
87 if (Sim
[Pkg
].InstBroken() == true)
89 clog
<< "Conf " << Pkg
.Name() << " broken" << endl
;
93 // Print out each package and the failed dependencies
94 for (pkgCache::DepIterator D
= Sim
[Pkg
].InstVerIter(Sim
).DependsList(); D
.end() == false; D
++)
96 if (Sim
.IsImportantDep(D
) == false ||
97 (Sim
[D
] & pkgDepCache::DepInstall
) != 0)
100 if (D
->Type
== pkgCache::Dep::Conflicts
)
101 clog
<< " Conflicts:" << D
.TargetPkg().Name();
103 clog
<< " Depends:" << D
.TargetPkg().Name();
107 _error
->Error("Conf Broken %s",Pkg
.Name());
110 clog
<< "Conf " << Pkg
.Name();
112 if (Sim
.BrokenCount() != 0)
120 // Simulate::Remove - Simulate the removal of a package /*{{{*/
121 // ---------------------------------------------------------------------
123 bool pkgSimulate::Remove(PkgIterator iPkg
)
125 // Adapt the iterator
126 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name());
130 clog
<< "Remv " << Pkg
.Name();
132 if (Sim
.BrokenCount() != 0)
140 // Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
141 // ---------------------------------------------------------------------
143 void pkgSimulate::ShortBreaks()
146 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; I
++)
148 if (Sim
[I
].InstBroken() == true)
150 if (Flags
[I
->ID
] == 0)
151 clog
<< I
.Name() << ' ';
153 clog << I.Name() << "! ";*/
159 // ApplyStatus - Adjust for non-ok packages /*{{{*/
160 // ---------------------------------------------------------------------
161 /* We attempt to change the state of the all packages that have failed
162 installation toward their real state. The ordering code will perform
163 the necessary calculations to deal with the problems. */
164 bool pkgApplyStatus(pkgDepCache
&Cache
)
166 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
168 switch (I
->CurrentState
)
170 // This means installation failed somehow
171 case pkgCache::State::UnPacked
:
172 case pkgCache::State::HalfConfigured
:
176 // This means removal failed
177 case pkgCache::State::HalfInstalled
:
182 if (I
->InstState
!= pkgCache::State::Ok
)
183 return _error
->Error("The package %s is not ok and I "
184 "don't know how to fix it!",I
.Name());
190 // FixBroken - Fix broken packages /*{{{*/
191 // ---------------------------------------------------------------------
192 /* This autoinstalls every broken package and then runs the problem resolver
194 bool pkgFixBroken(pkgDepCache
&Cache
)
196 // Auto upgrade all broken packages
197 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
198 if (Cache
[I
].NowBroken() == true)
199 Cache
.MarkInstall(I
,true);
201 /* Fix packages that are in a NeedArchive state but don't have a
202 downloadable install version */
203 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
205 if (I
.State() != pkgCache::PkgIterator::NeedsUnpack
||
206 Cache
[I
].Delete() == true)
209 if (Cache
[I
].InstVerIter(Cache
).Downloadable() == false)
212 Cache
.MarkInstall(I
,true);
215 pkgProblemResolver
Fix(Cache
);
216 return Fix
.Resolve(true);
219 // DistUpgrade - Distribution upgrade /*{{{*/
220 // ---------------------------------------------------------------------
221 /* This autoinstalls every package and then force installs every
222 pre-existing package. This creates the initial set of conditions which
223 most likely contain problems because too many things were installed.
225 The problem resolver is used to resolve the problems.
227 bool pkgDistUpgrade(pkgDepCache
&Cache
)
229 /* Auto upgrade all installed packages, this provides the basis
230 for the installation */
231 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
232 if (I
->CurrentVer
!= 0)
233 Cache
.MarkInstall(I
,true);
235 /* Now, auto upgrade all essential packages - this ensures that
236 the essential packages are present and working */
237 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
238 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
239 Cache
.MarkInstall(I
,true);
241 /* We do it again over all previously installed packages to force
242 conflict resolution on them all. */
243 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
244 if (I
->CurrentVer
!= 0)
245 Cache
.MarkInstall(I
,false);
247 pkgProblemResolver
Fix(Cache
);
249 // Hold back held packages.
250 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
252 if (I
->SelectedState
== pkgCache::State::Hold
)
259 return Fix
.Resolve();
262 // AllUpgrade - Upgrade as many packages as possible /*{{{*/
263 // ---------------------------------------------------------------------
264 /* Right now the system must be consistent before this can be called.
265 It also will not change packages marked for install, it only tries
266 to install packages not marked for install */
267 bool pkgAllUpgrade(pkgDepCache
&Cache
)
269 pkgProblemResolver
Fix(Cache
);
271 if (Cache
.BrokenCount() != 0)
274 // Upgrade all installed packages
275 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
277 if (Cache
[I
].Install() == true)
280 if (I
->SelectedState
== pkgCache::State::Hold
)
283 if (I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0)
284 Cache
.MarkInstall(I
,false);
287 return Fix
.ResolveByKeep();
290 // MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/
291 // ---------------------------------------------------------------------
292 /* This simply goes over the entire set of packages and tries to keep
293 each package marked for upgrade. If a conflict is generated then
294 the package is restored. */
295 bool pkgMinimizeUpgrade(pkgDepCache
&Cache
)
297 if (Cache
.BrokenCount() != 0)
300 // We loop indefinately to get the minimal set size.
305 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
308 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
311 // Keep it and see if that is OK
313 if (Cache
.BrokenCount() != 0)
314 Cache
.MarkInstall(I
,false);
319 while (Change
== true);
321 if (Cache
.BrokenCount() != 0)
322 return _error
->Error("Internal Error in pkgMinimizeUpgrade");
328 // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
329 // ---------------------------------------------------------------------
331 pkgProblemResolver::pkgProblemResolver(pkgDepCache
&Cache
) : Cache(Cache
)
334 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
335 Scores
= new signed short[Size
];
336 Flags
= new unsigned char[Size
];
337 memset(Flags
,0,sizeof(*Flags
)*Size
);
339 // Set debug to true to see its decision logic
340 Debug
= _config
->FindB("Debug::pkgProblemResolver",false);
343 // ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
344 // ---------------------------------------------------------------------
346 int pkgProblemResolver::ScoreSort(const void *a
,const void *b
)
348 Package
const **A
= (Package
const **)a
;
349 Package
const **B
= (Package
const **)b
;
350 if (This
->Scores
[(*A
)->ID
] > This
->Scores
[(*B
)->ID
])
352 if (This
->Scores
[(*A
)->ID
] < This
->Scores
[(*B
)->ID
])
357 // ProblemResolver::MakeScores - Make the score table /*{{{*/
358 // ---------------------------------------------------------------------
360 void pkgProblemResolver::MakeScores()
362 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
363 memset(Scores
,0,sizeof(*Scores
)*Size
);
365 // Generate the base scores for a package based on its properties
366 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
368 if (Cache
[I
].InstallVer
== 0)
371 signed short &Score
= Scores
[I
->ID
];
373 /* This is arbitary, it should be high enough to elevate an
374 essantial package above most other packages but low enough
375 to allow an obsolete essential packages to be removed by
376 a conflicts on a powerfull normal package (ie libc6) */
377 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
380 // We transform the priority
381 // Important Required Standard Optional Extra
382 signed short PrioMap
[] = {0,3,2,1,-1,-2};
383 if (Cache
[I
].InstVerIter(Cache
)->Priority
<= 5)
384 Score
+= PrioMap
[Cache
[I
].InstVerIter(Cache
)->Priority
];
386 /* This helps to fix oddball problems with conflicting packages
387 on the same level. We enhance the score of installed packages */
388 if (I
->CurrentVer
!= 0)
392 // Now that we have the base scores we go and propogate dependencies
393 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
395 if (Cache
[I
].InstallVer
== 0)
398 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false; D
++)
400 if (D
->Type
== pkgCache::Dep::Depends
|| D
->Type
== pkgCache::Dep::PreDepends
)
401 Scores
[D
.TargetPkg()->ID
]++;
405 // Copy the scores to advoid additive looping
406 signed short *OldScores
= new signed short[Size
];
407 memcpy(OldScores
,Scores
,sizeof(*Scores
)*Size
);
409 /* Now we cause 1 level of dependency inheritance, that is we add the
410 score of the packages that depend on the target Package. This
411 fortifies high scoring packages */
412 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
414 if (Cache
[I
].InstallVer
== 0)
417 for (pkgCache::DepIterator D
= I
.RevDependsList(); D
.end() == false; D
++)
419 // Only do it for the install version
420 if ((pkgCache::Version
*)D
.ParentVer() != Cache
[D
.ParentPkg()].InstallVer
||
421 (D
->Type
!= pkgCache::Dep::Depends
&& D
->Type
!= pkgCache::Dep::PreDepends
))
424 Scores
[I
->ID
] += abs(OldScores
[D
.ParentPkg()->ID
]);
428 /* Now we propogate along provides. This makes the packages that
429 provide important packages extremely important */
430 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
432 for (pkgCache::PrvIterator P
= I
.ProvidesList(); P
.end() == false; P
++)
434 // Only do it once per package
435 if ((pkgCache::Version
*)P
.OwnerVer() != Cache
[P
.OwnerPkg()].InstallVer
)
437 Scores
[P
.OwnerPkg()->ID
] += abs(Scores
[I
->ID
] - OldScores
[I
->ID
]);
441 /* Protected things are pushed really high up. This number should put them
442 ahead of everything */
443 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
444 if ((Flags
[I
->ID
] & Protected
) != 0)
445 Scores
[I
->ID
] += 10000;
450 // ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
451 // ---------------------------------------------------------------------
452 /* This goes through and tries to reinstall packages to make this package
454 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg
)
456 if ((Flags
[Pkg
->ID
] & Upgradable
) == 0 || Cache
[Pkg
].Upgradable() == false)
459 Flags
[Pkg
->ID
] &= ~Upgradable
;
461 bool WasKept
= Cache
[Pkg
].Keep();
462 Cache
.MarkInstall(Pkg
,false);
464 // This must be a virtual package or something like that.
465 if (Cache
[Pkg
].InstVerIter(Cache
).end() == true)
468 // Isolate the problem dependency
470 for (pkgCache::DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
472 // Compute a single dependency element (glob or)
473 pkgCache::DepIterator Start
= D
;
474 pkgCache::DepIterator End
= D
;
475 unsigned char State
= 0;
476 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
479 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
484 // We only worry about critical deps.
485 if (End
.IsCritical() != true)
489 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
492 // Hm, the group is broken.. I have no idea how to handle this
495 clog
<< "Note, a broken or group was found in " << Pkg
.Name() << "." << endl
;
500 // Do not change protected packages
501 PkgIterator P
= Start
.SmartTargetPkg();
502 if ((Flags
[P
->ID
] & Protected
) == Protected
)
505 clog
<< " Reinet Failed because of protected " << P
.Name() << endl
;
510 // Upgrade the package if the candidate version will fix the problem.
511 if ((Cache
[Start
] & pkgDepCache::DepCVer
) == pkgDepCache::DepCVer
)
513 if (DoUpgrade(P
) == false)
516 clog
<< " Reinst Failed because of " << P
.Name() << endl
;
523 /* We let the algorithm deal with conflicts on its next iteration,
524 it is much smarter than us */
525 if (End
->Type
== pkgCache::Dep::Conflicts
)
529 clog
<< " Reinst Failed early because of " << Start
.TargetPkg().Name() << endl
;
535 // Undo our operations - it might be smart to undo everything this did..
541 Cache
.MarkDelete(Pkg
);
546 clog
<< " Re-Instated " << Pkg
.Name() << endl
;
550 // ProblemResolver::Resolve - Run the resolution pass /*{{{*/
551 // ---------------------------------------------------------------------
552 /* This routines works by calculating a score for each package. The score
553 is derived by considering the package's priority and all reverse
554 dependents giving an integer that reflects the amount of breakage that
555 adjusting the package will inflict.
557 It goes from highest score to lowest and corrects all of the breaks by
558 keeping or removing the dependant packages. If that fails then it removes
559 the package itself and goes on. The routine should be able to intelligently
560 go from any broken state to a fixed state.
562 The BrokenFix flag enables a mode where the algorithm tries to
563 upgrade packages to advoid problems. */
564 bool pkgProblemResolver::Resolve(bool BrokenFix
)
566 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
568 // Record which packages are marked for install
573 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
575 if (Cache
[I
].Install() == true)
576 Flags
[I
->ID
] |= PreInstalled
;
579 if (Cache
[I
].InstBroken() == true && BrokenFix
== true)
581 Cache
.MarkInstall(I
,false);
582 if (Cache
[I
].Install() == true)
586 Flags
[I
->ID
] &= ~PreInstalled
;
588 Flags
[I
->ID
] |= Upgradable
;
591 while (Again
== true);
594 clog
<< "Starting" << endl
;
598 /* We have to order the packages so that the broken fixing pass
599 operates from highest score to lowest. This prevents problems when
600 high score packages cause the removal of lower score packages that
601 would cause the removal of even lower score packages. */
602 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
603 pkgCache::Package
**PEnd
= PList
;
604 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
607 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
609 /* for (pkgCache::Package **K = PList; K != PEnd; K++)
610 if (Scores[(*K)->ID] != 0)
612 pkgCache::PkgIterator Pkg(Cache,*K);
613 clog << Scores[(*K)->ID] << ' ' << Pkg.Name() <<
614 ' ' << (pkgCache::Version *)Pkg.CurrentVer() << ' ' <<
615 Cache[Pkg].InstallVer << ' ' << Cache[Pkg].CandidateVer << endl;
619 clog
<< "Starting 2" << endl
;
621 /* Now consider all broken packages. For each broken package we either
622 remove the package or fix it's problem. We do this once, it should
623 not be possible for a loop to form (that is a < b < c and fixing b by
624 changing a breaks c) */
626 for (int Counter
= 0; Counter
!= 10 && Change
== true; Counter
++)
629 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
631 pkgCache::PkgIterator
I(Cache
,*K
);
633 /* We attempt to install this and see if any breaks result,
634 this takes care of some strange cases */
635 if (Cache
[I
].CandidateVer
!= Cache
[I
].InstallVer
&&
636 I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0 &&
637 (Flags
[I
->ID
] & PreInstalled
) != 0 &&
638 (Flags
[I
->ID
] & Protected
) == 0 &&
639 (Flags
[I
->ID
] & ReInstateTried
) == 0)
642 clog
<< " Try to Re-Instate " << I
.Name() << endl
;
643 int OldBreaks
= Cache
.BrokenCount();
644 pkgCache::Version
*OldVer
= Cache
[I
].InstallVer
;
645 Flags
[I
->ID
] &= ReInstateTried
;
647 Cache
.MarkInstall(I
,false);
648 if (Cache
[I
].InstBroken() == true ||
649 OldBreaks
< Cache
.BrokenCount())
658 clog
<< "Re-Instated " << I
.Name() << " (" << OldBreaks
<< " vs " << Cache
.BrokenCount() << ')' << endl
;
661 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
664 // Isolate the problem dependency
665 PackageKill KillList
[100];
666 PackageKill
*LEnd
= KillList
;
667 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
669 // Compute a single dependency element (glob or)
670 pkgCache::DepIterator Start
= D
;
671 pkgCache::DepIterator End
= D
;
672 unsigned char State
= 0;
673 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
676 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
681 // We only worry about critical deps.
682 if (End
.IsCritical() != true)
686 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
689 // Hm, the group is broken.. I have no idea how to handle this
692 clog
<< "Note, a broken or group was found in " << I
.Name() << "." << endl
;
698 clog
<< "Package " << I
.Name() << " has broken dep on " << End
.TargetPkg().Name() << endl
;
700 /* Conflicts is simple, decide if we should remove this package
701 or the conflicted one */
702 pkgCache::Version
**VList
= End
.AllTargets();
704 for (pkgCache::Version
**V
= VList
; *V
!= 0; V
++)
706 pkgCache::VerIterator
Ver(Cache
,*V
);
707 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
710 clog
<< " Considering " << Pkg
.Name() << ' ' << (int)Scores
[Pkg
->ID
] <<
711 " as a solution to " << I
.Name() << ' ' << (int)Scores
[I
->ID
] << endl
;
712 if (Scores
[I
->ID
] <= Scores
[Pkg
->ID
] ||
713 ((Cache
[End
] & pkgDepCache::DepGNow
) == 0 &&
714 End
->Type
!= pkgCache::Dep::Conflicts
))
716 if ((Flags
[I
->ID
] & Protected
) == Protected
)
719 // See if a keep will do
721 if (Cache
[I
].InstBroken() == false)
724 clog
<< " Holding Back " << I
.Name() << " rather than change " << End
.TargetPkg().Name() << endl
;
728 if (BrokenFix
== false || DoUpgrade(I
) == false)
731 clog
<< " Removing " << I
.Name() << " rather than change " << End
.TargetPkg().Name() << endl
;
734 Scores
[I
->ID
] = Scores
[Pkg
->ID
];
744 // Skip this if it is protected
745 if ((Flags
[Pkg
->ID
] & Protected
) != 0)
752 if (End
->Type
!= pkgCache::Dep::Conflicts
)
757 // Hm, nothing can possibly satisify this dep. Nuke it.
758 if (VList
[0] == 0 && End
->Type
!= pkgCache::Dep::Conflicts
&&
759 (Flags
[I
->ID
] & Protected
) != Protected
)
762 if (Cache
[I
].InstBroken() == false)
765 clog
<< " Holding Back " << I
.Name() << " because I can't find " << End
.TargetPkg().Name() << endl
;
770 clog
<< " Removing " << I
.Name() << " because I can't find " << End
.TargetPkg().Name() << endl
;
783 // Apply the kill list now
784 if (Cache
[I
].InstallVer
!= 0)
785 for (PackageKill
*J
= KillList
; J
!= LEnd
; J
++)
788 if ((Cache
[J
->Dep
] & pkgDepCache::DepGNow
) == 0)
790 if (J
->Dep
->Type
== pkgCache::Dep::Conflicts
)
793 clog
<< " Fixing " << I
.Name() << " via remove of " << J
->Pkg
.Name() << endl
;
794 Cache
.MarkDelete(J
->Pkg
);
800 clog
<< " Fixing " << I
.Name() << " via keep of " << J
->Pkg
.Name() << endl
;
801 Cache
.MarkKeep(J
->Pkg
);
805 Scores
[J
->Pkg
->ID
] = Scores
[I
->ID
];
811 clog
<< "Done" << endl
;
816 if (Cache
.BrokenCount() != 0)
817 return _error
->Error("Internal error, pkgProblemResolver::Resolve generated breaks.");
822 // ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
823 // ---------------------------------------------------------------------
824 /* This is the work horse of the soft upgrade routine. It is very gental
825 in that it does not install or remove any packages. It is assumed that the
826 system was non-broken previously. */
827 bool pkgProblemResolver::ResolveByKeep()
829 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
832 clog
<< "Entering ResolveByKeep" << endl
;
836 /* We have to order the packages so that the broken fixing pass
837 operates from highest score to lowest. This prevents problems when
838 high score packages cause the removal of lower score packages that
839 would cause the removal of even lower score packages. */
840 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
841 pkgCache::Package
**PEnd
= PList
;
842 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
845 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
847 // Consider each broken package
848 pkgCache::Package
**LastStop
= 0;
849 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
851 pkgCache::PkgIterator
I(Cache
,*K
);
853 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
856 /* Keep the package. If this works then great, otherwise we have
857 to be significantly more agressive and manipulate its dependencies */
858 if ((Flags
[I
->ID
] & Protected
) == 0)
861 clog
<< "Keeping package " << I
.Name() << endl
;
863 if (Cache
[I
].InstBroken() == false)
870 // Isolate the problem dependencies
871 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
873 // Compute a single dependency element (glob or)
874 pkgCache::DepIterator Start
= D
;
875 pkgCache::DepIterator End
= D
;
876 unsigned char State
= 0;
877 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
880 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
885 // We only worry about critical deps.
886 if (End
.IsCritical() != true)
890 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
893 // Hm, the group is broken.. I have no idea how to handle this
896 clog
<< "Note, a broken or group was found in " << I
.Name() << "." << endl
;
897 if ((Flags
[I
->ID
] & Protected
) == 0)
903 clog
<< "Package " << I
.Name() << " has broken dep on " << End
.TargetPkg().Name() << endl
;
905 // Look at all the possible provides on this package
906 pkgCache::Version
**VList
= End
.AllTargets();
907 for (pkgCache::Version
**V
= VList
; *V
!= 0; V
++)
909 pkgCache::VerIterator
Ver(Cache
,*V
);
910 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
912 // It is not keepable
913 if (Cache
[Pkg
].InstallVer
== 0 ||
914 Pkg
->CurrentVer
== 0)
917 if ((Flags
[I
->ID
] & Protected
) == 0)
920 clog
<< " Keeping Package " << Pkg
.Name() << " due to dep" << endl
;
924 if (Cache
[I
].InstBroken() == false)
928 if (Cache
[I
].InstBroken() == false)
932 if (Cache
[I
].InstBroken() == true)
937 return _error
->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I
.Name());
945 // ProblemResolver::InstallProtect - Install all protected packages /*{{{*/
946 // ---------------------------------------------------------------------
947 /* This is used to make sure protected packages are installed */
948 void pkgProblemResolver::InstallProtect()
950 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
952 if ((Flags
[I
->ID
] & Protected
) == Protected
)
954 if ((Flags
[I
->ID
] & ToRemove
) == ToRemove
)
957 Cache
.MarkInstall(I
,false);