1 // -*- mode: cpp; mode: fold -*-
3 // $Id: algorithms.cc,v 1.44 2002/11/28 18:49:16 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 /*{{{*/
17 #include <apt-pkg/algorithms.h>
18 #include <apt-pkg/error.h>
19 #include <apt-pkg/configuration.h>
20 #include <apt-pkg/version.h>
21 #include <apt-pkg/sptr.h>
22 #include <apt-pkg/acquire-item.h>
25 #include <sys/types.h>
32 pkgProblemResolver
*pkgProblemResolver::This
= 0;
34 // Simulate::Simulate - Constructor /*{{{*/
35 // ---------------------------------------------------------------------
36 /* The legacy translations here of input Pkg iterators is obsolete,
37 this is not necessary since the pkgCaches are fully shared now. */
38 pkgSimulate::pkgSimulate(pkgDepCache
*Cache
) : pkgPackageManager(Cache
),
40 Sim(&Cache
->GetCache(),&iPolicy
),
44 Flags
= new unsigned char[Cache
->Head().PackageCount
];
45 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
47 // Fake a filename so as not to activate the media swapping
48 string Jnk
= "SIMULATE";
49 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
53 // Simulate::Describe - Describe a package /*{{{*/
54 // ---------------------------------------------------------------------
55 /* Parameter Current == true displays the current package version,
56 Parameter Candidate == true displays the candidate package version */
57 void pkgSimulate::Describe(PkgIterator Pkg
,ostream
&out
,bool Current
,bool Candidate
)
61 out
<< Pkg
.FullName(true);
65 Ver
= Pkg
.CurrentVer();
66 if (Ver
.end() == false)
67 out
<< " [" << Ver
.VerStr() << ']';
70 if (Candidate
== true)
72 Ver
= Sim
[Pkg
].CandidateVerIter(Sim
);
73 if (Ver
.end() == true)
76 out
<< " (" << Ver
.VerStr() << ' ' << Ver
.RelStr() << ')';
80 // Simulate::Install - Simulate unpacking of a package /*{{{*/
81 // ---------------------------------------------------------------------
83 bool pkgSimulate::Install(PkgIterator iPkg
,string
/*File*/)
86 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
90 Describe(Pkg
,cout
,true,true);
91 Sim
.MarkInstall(Pkg
,false);
93 // Look for broken conflicts+predepends.
94 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; I
++)
96 if (Sim
[I
].InstallVer
== 0)
99 for (DepIterator D
= Sim
[I
].InstVerIter(Sim
).DependsList(); D
.end() == false;)
104 if (Start
->Type
== pkgCache::Dep::Conflicts
||
105 Start
->Type
== pkgCache::Dep::DpkgBreaks
||
106 Start
->Type
== pkgCache::Dep::Obsoletes
||
107 End
->Type
== pkgCache::Dep::PreDepends
)
109 if ((Sim
[End
] & pkgDepCache::DepGInstall
) == 0)
111 cout
<< " [" << I
.FullName(false) << " on " << Start
.TargetPkg().FullName(false) << ']';
112 if (Start
->Type
== pkgCache::Dep::Conflicts
)
113 _error
->Error("Fatal, conflicts violated %s",I
.FullName(false).c_str());
119 if (Sim
.BrokenCount() != 0)
126 // Simulate::Configure - Simulate configuration of a Package /*{{{*/
127 // ---------------------------------------------------------------------
128 /* This is not an acurate simulation of relatity, we should really not
129 install the package.. For some investigations it may be necessary
131 bool pkgSimulate::Configure(PkgIterator iPkg
)
133 // Adapt the iterator
134 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
138 if (Sim
[Pkg
].InstBroken() == true)
140 cout
<< "Conf " << Pkg
.FullName(false) << " broken" << endl
;
144 // Print out each package and the failed dependencies
145 for (pkgCache::DepIterator D
= Sim
[Pkg
].InstVerIter(Sim
).DependsList(); D
.end() == false; D
++)
147 if (Sim
.IsImportantDep(D
) == false ||
148 (Sim
[D
] & pkgDepCache::DepInstall
) != 0)
151 if (D
->Type
== pkgCache::Dep::Obsoletes
)
152 cout
<< " Obsoletes:" << D
.TargetPkg().FullName(false);
153 else if (D
->Type
== pkgCache::Dep::Conflicts
)
154 cout
<< " Conflicts:" << D
.TargetPkg().FullName(false);
155 else if (D
->Type
== pkgCache::Dep::DpkgBreaks
)
156 cout
<< " Breaks:" << D
.TargetPkg().FullName(false);
158 cout
<< " Depends:" << D
.TargetPkg().FullName(false);
162 _error
->Error("Conf Broken %s",Pkg
.FullName(false).c_str());
167 Describe(Pkg
,cout
,false,true);
170 if (Sim
.BrokenCount() != 0)
178 // Simulate::Remove - Simulate the removal of a package /*{{{*/
179 // ---------------------------------------------------------------------
181 bool pkgSimulate::Remove(PkgIterator iPkg
,bool Purge
)
183 // Adapt the iterator
184 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
193 Describe(Pkg
,cout
,true,false);
195 if (Sim
.BrokenCount() != 0)
203 // Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
204 // ---------------------------------------------------------------------
206 void pkgSimulate::ShortBreaks()
209 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; I
++)
211 if (Sim
[I
].InstBroken() == true)
213 if (Flags
[I
->ID
] == 0)
214 cout
<< I
.FullName(false) << ' ';
216 cout << I.Name() << "! ";*/
222 // ApplyStatus - Adjust for non-ok packages /*{{{*/
223 // ---------------------------------------------------------------------
224 /* We attempt to change the state of the all packages that have failed
225 installation toward their real state. The ordering code will perform
226 the necessary calculations to deal with the problems. */
227 bool pkgApplyStatus(pkgDepCache
&Cache
)
229 pkgDepCache::ActionGroup
group(Cache
);
231 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
233 if (I
->VersionList
== 0)
236 // Only choice for a ReInstReq package is to reinstall
237 if (I
->InstState
== pkgCache::State::ReInstReq
||
238 I
->InstState
== pkgCache::State::HoldReInstReq
)
240 if (I
->CurrentVer
!= 0 && I
.CurrentVer().Downloadable() == true)
241 Cache
.MarkKeep(I
, false, false);
244 // Is this right? Will dpkg choke on an upgrade?
245 if (Cache
[I
].CandidateVer
!= 0 &&
246 Cache
[I
].CandidateVerIter(Cache
).Downloadable() == true)
247 Cache
.MarkInstall(I
, false, 0, false);
249 return _error
->Error(_("The package %s needs to be reinstalled, "
250 "but I can't find an archive for it."),I
.FullName(true).c_str());
256 switch (I
->CurrentState
)
258 /* This means installation failed somehow - it does not need to be
259 re-unpacked (probably) */
260 case pkgCache::State::UnPacked
:
261 case pkgCache::State::HalfConfigured
:
262 case pkgCache::State::TriggersAwaited
:
263 case pkgCache::State::TriggersPending
:
264 if ((I
->CurrentVer
!= 0 && I
.CurrentVer().Downloadable() == true) ||
265 I
.State() != pkgCache::PkgIterator::NeedsUnpack
)
266 Cache
.MarkKeep(I
, false, false);
269 if (Cache
[I
].CandidateVer
!= 0 &&
270 Cache
[I
].CandidateVerIter(Cache
).Downloadable() == true)
271 Cache
.MarkInstall(I
, true, 0, false);
277 // This means removal failed
278 case pkgCache::State::HalfInstalled
:
283 if (I
->InstState
!= pkgCache::State::Ok
)
284 return _error
->Error("The package %s is not ok and I "
285 "don't know how to fix it!",I
.FullName(false).c_str());
291 // FixBroken - Fix broken packages /*{{{*/
292 // ---------------------------------------------------------------------
293 /* This autoinstalls every broken package and then runs the problem resolver
295 bool pkgFixBroken(pkgDepCache
&Cache
)
297 pkgDepCache::ActionGroup
group(Cache
);
299 // Auto upgrade all broken packages
300 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
301 if (Cache
[I
].NowBroken() == true)
302 Cache
.MarkInstall(I
, true, 0, false);
304 /* Fix packages that are in a NeedArchive state but don't have a
305 downloadable install version */
306 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
308 if (I
.State() != pkgCache::PkgIterator::NeedsUnpack
||
309 Cache
[I
].Delete() == true)
312 if (Cache
[I
].InstVerIter(Cache
).Downloadable() == false)
315 Cache
.MarkInstall(I
, true, 0, false);
318 pkgProblemResolver
Fix(&Cache
);
319 return Fix
.Resolve(true);
322 // DistUpgrade - Distribution upgrade /*{{{*/
323 // ---------------------------------------------------------------------
324 /* This autoinstalls every package and then force installs every
325 pre-existing package. This creates the initial set of conditions which
326 most likely contain problems because too many things were installed.
328 The problem resolver is used to resolve the problems.
330 bool pkgDistUpgrade(pkgDepCache
&Cache
)
332 pkgDepCache::ActionGroup
group(Cache
);
334 /* Upgrade all installed packages first without autoinst to help the resolver
335 in versioned or-groups to upgrade the old solver instead of installing
336 a new one (if the old solver is not the first one [anymore]) */
337 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
338 if (I
->CurrentVer
!= 0)
339 Cache
.MarkInstall(I
, false, 0, false);
341 /* Auto upgrade all installed packages, this provides the basis
342 for the installation */
343 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
344 if (I
->CurrentVer
!= 0)
345 Cache
.MarkInstall(I
, true, 0, false);
347 /* Now, auto upgrade all essential packages - this ensures that
348 the essential packages are present and working */
349 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
350 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
351 Cache
.MarkInstall(I
, true, 0, false);
353 /* We do it again over all previously installed packages to force
354 conflict resolution on them all. */
355 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
356 if (I
->CurrentVer
!= 0)
357 Cache
.MarkInstall(I
, false, 0, false);
359 pkgProblemResolver
Fix(&Cache
);
361 // Hold back held packages.
362 if (_config
->FindB("APT::Ignore-Hold",false) == false)
364 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
366 if (I
->SelectedState
== pkgCache::State::Hold
)
369 Cache
.MarkKeep(I
, false, false);
374 return Fix
.Resolve();
377 // AllUpgrade - Upgrade as many packages as possible /*{{{*/
378 // ---------------------------------------------------------------------
379 /* Right now the system must be consistent before this can be called.
380 It also will not change packages marked for install, it only tries
381 to install packages not marked for install */
382 bool pkgAllUpgrade(pkgDepCache
&Cache
)
384 pkgDepCache::ActionGroup
group(Cache
);
386 pkgProblemResolver
Fix(&Cache
);
388 if (Cache
.BrokenCount() != 0)
391 // Upgrade all installed packages
392 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
394 if (Cache
[I
].Install() == true)
397 if (_config
->FindB("APT::Ignore-Hold",false) == false)
398 if (I
->SelectedState
== pkgCache::State::Hold
)
401 if (I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0)
402 Cache
.MarkInstall(I
, false, 0, false);
405 return Fix
.ResolveByKeep();
408 // MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/
409 // ---------------------------------------------------------------------
410 /* This simply goes over the entire set of packages and tries to keep
411 each package marked for upgrade. If a conflict is generated then
412 the package is restored. */
413 bool pkgMinimizeUpgrade(pkgDepCache
&Cache
)
415 pkgDepCache::ActionGroup
group(Cache
);
417 if (Cache
.BrokenCount() != 0)
420 // We loop for 10 tries to get the minimal set size.
422 unsigned int Count
= 0;
426 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
429 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
432 // Keep it and see if that is OK
433 Cache
.MarkKeep(I
, false, false);
434 if (Cache
.BrokenCount() != 0)
435 Cache
.MarkInstall(I
, false, 0, false);
438 // If keep didnt actually do anything then there was no change..
439 if (Cache
[I
].Upgrade() == false)
445 while (Change
== true && Count
< 10);
447 if (Cache
.BrokenCount() != 0)
448 return _error
->Error("Internal Error in pkgMinimizeUpgrade");
453 // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
454 // ---------------------------------------------------------------------
456 pkgProblemResolver::pkgProblemResolver(pkgDepCache
*pCache
) : Cache(*pCache
)
459 unsigned long Size
= Cache
.Head().PackageCount
;
460 Scores
= new signed short[Size
];
461 Flags
= new unsigned char[Size
];
462 memset(Flags
,0,sizeof(*Flags
)*Size
);
464 // Set debug to true to see its decision logic
465 Debug
= _config
->FindB("Debug::pkgProblemResolver",false);
468 // ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
469 // ---------------------------------------------------------------------
471 pkgProblemResolver::~pkgProblemResolver()
477 // ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
478 // ---------------------------------------------------------------------
480 int pkgProblemResolver::ScoreSort(const void *a
,const void *b
)
482 Package
const **A
= (Package
const **)a
;
483 Package
const **B
= (Package
const **)b
;
484 if (This
->Scores
[(*A
)->ID
] > This
->Scores
[(*B
)->ID
])
486 if (This
->Scores
[(*A
)->ID
] < This
->Scores
[(*B
)->ID
])
491 // ProblemResolver::MakeScores - Make the score table /*{{{*/
492 // ---------------------------------------------------------------------
494 void pkgProblemResolver::MakeScores()
496 unsigned long Size
= Cache
.Head().PackageCount
;
497 memset(Scores
,0,sizeof(*Scores
)*Size
);
499 // Important Required Standard Optional Extra
500 signed short PrioMap
[] = {
502 (signed short) _config
->FindI("pkgProblemResolver::Scores::Important",3),
503 (signed short) _config
->FindI("pkgProblemResolver::Scores::Required",2),
504 (signed short) _config
->FindI("pkgProblemResolver::Scores::Standard",1),
505 (signed short) _config
->FindI("pkgProblemResolver::Scores::Optional",-1),
506 (signed short) _config
->FindI("pkgProblemResolver::Scores::Extra",-2)
508 signed short PrioEssentials
= _config
->FindI("pkgProblemResolver::Scores::Essentials",100);
509 signed short PrioInstalledAndNotObsolete
= _config
->FindI("pkgProblemResolver::Scores::NotObsolete",1);
510 signed short PrioDepends
= _config
->FindI("pkgProblemResolver::Scores::Depends",1);
511 signed short PrioRecommends
= _config
->FindI("pkgProblemResolver::Scores::Recommends",1);
512 signed short AddProtected
= _config
->FindI("pkgProblemResolver::Scores::AddProtected",10000);
513 signed short AddEssential
= _config
->FindI("pkgProblemResolver::Scores::AddEssential",5000);
515 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
516 clog
<< "Settings used to calculate pkgProblemResolver::Scores::" << endl
517 << " Important => " << PrioMap
[1] << endl
518 << " Required => " << PrioMap
[2] << endl
519 << " Standard => " << PrioMap
[3] << endl
520 << " Optional => " << PrioMap
[4] << endl
521 << " Extra => " << PrioMap
[5] << endl
522 << " Essentials => " << PrioEssentials
<< endl
523 << " InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete
<< endl
524 << " Depends => " << PrioDepends
<< endl
525 << " Recommends => " << PrioRecommends
<< endl
526 << " AddProtected => " << AddProtected
<< endl
527 << " AddEssential => " << AddEssential
<< endl
;
529 // Generate the base scores for a package based on its properties
530 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
532 if (Cache
[I
].InstallVer
== 0)
535 signed short &Score
= Scores
[I
->ID
];
537 /* This is arbitrary, it should be high enough to elevate an
538 essantial package above most other packages but low enough
539 to allow an obsolete essential packages to be removed by
540 a conflicts on a powerfull normal package (ie libc6) */
541 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
542 Score
+= PrioEssentials
;
544 // We transform the priority
545 if (Cache
[I
].InstVerIter(Cache
)->Priority
<= 5)
546 Score
+= PrioMap
[Cache
[I
].InstVerIter(Cache
)->Priority
];
548 /* This helps to fix oddball problems with conflicting packages
549 on the same level. We enhance the score of installed packages
550 if those are not obsolete
552 if (I
->CurrentVer
!= 0 && Cache
[I
].CandidateVer
!= 0 && Cache
[I
].CandidateVerIter(Cache
).Downloadable())
553 Score
+= PrioInstalledAndNotObsolete
;
556 // Now that we have the base scores we go and propogate dependencies
557 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
559 if (Cache
[I
].InstallVer
== 0)
562 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false; D
++)
564 if (D
->Type
== pkgCache::Dep::Depends
||
565 D
->Type
== pkgCache::Dep::PreDepends
)
566 Scores
[D
.TargetPkg()->ID
] += PrioDepends
;
567 else if (D
->Type
== pkgCache::Dep::Recommends
)
568 Scores
[D
.TargetPkg()->ID
] += PrioRecommends
;
572 // Copy the scores to advoid additive looping
573 SPtrArray
<signed short> OldScores
= new signed short[Size
];
574 memcpy(OldScores
,Scores
,sizeof(*Scores
)*Size
);
576 /* Now we cause 1 level of dependency inheritance, that is we add the
577 score of the packages that depend on the target Package. This
578 fortifies high scoring packages */
579 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
581 if (Cache
[I
].InstallVer
== 0)
584 for (pkgCache::DepIterator D
= I
.RevDependsList(); D
.end() == false; D
++)
586 // Only do it for the install version
587 if ((pkgCache::Version
*)D
.ParentVer() != Cache
[D
.ParentPkg()].InstallVer
||
588 (D
->Type
!= pkgCache::Dep::Depends
&&
589 D
->Type
!= pkgCache::Dep::PreDepends
&&
590 D
->Type
!= pkgCache::Dep::Recommends
))
593 Scores
[I
->ID
] += abs(OldScores
[D
.ParentPkg()->ID
]);
597 /* Now we propogate along provides. This makes the packages that
598 provide important packages extremely important */
599 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
601 for (pkgCache::PrvIterator P
= I
.ProvidesList(); P
.end() == false; P
++)
603 // Only do it once per package
604 if ((pkgCache::Version
*)P
.OwnerVer() != Cache
[P
.OwnerPkg()].InstallVer
)
606 Scores
[P
.OwnerPkg()->ID
] += abs(Scores
[I
->ID
] - OldScores
[I
->ID
]);
610 /* Protected things are pushed really high up. This number should put them
611 ahead of everything */
612 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
614 if ((Flags
[I
->ID
] & Protected
) != 0)
615 Scores
[I
->ID
] += AddProtected
;
616 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
617 Scores
[I
->ID
] += AddEssential
;
621 // ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
622 // ---------------------------------------------------------------------
623 /* This goes through and tries to reinstall packages to make this package
625 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg
)
627 pkgDepCache::ActionGroup
group(Cache
);
629 if ((Flags
[Pkg
->ID
] & Upgradable
) == 0 || Cache
[Pkg
].Upgradable() == false)
631 if ((Flags
[Pkg
->ID
] & Protected
) == Protected
)
634 Flags
[Pkg
->ID
] &= ~Upgradable
;
636 bool WasKept
= Cache
[Pkg
].Keep();
637 Cache
.MarkInstall(Pkg
, false, 0, false);
639 // This must be a virtual package or something like that.
640 if (Cache
[Pkg
].InstVerIter(Cache
).end() == true)
643 // Isolate the problem dependency
645 for (pkgCache::DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
647 // Compute a single dependency element (glob or)
648 pkgCache::DepIterator Start
= D
;
649 pkgCache::DepIterator End
= D
;
650 for (bool LastOR
= true; D
.end() == false && LastOR
== true;)
652 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
658 // We only worry about critical deps.
659 if (End
.IsCritical() != true)
662 // Iterate over all the members in the or group
666 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
669 // Do not change protected packages
670 PkgIterator P
= Start
.SmartTargetPkg();
671 if ((Flags
[P
->ID
] & Protected
) == Protected
)
674 clog
<< " Reinst Failed because of protected " << P
.FullName(false) << endl
;
679 // Upgrade the package if the candidate version will fix the problem.
680 if ((Cache
[Start
] & pkgDepCache::DepCVer
) == pkgDepCache::DepCVer
)
682 if (DoUpgrade(P
) == false)
685 clog
<< " Reinst Failed because of " << P
.FullName(false) << endl
;
696 /* We let the algorithm deal with conflicts on its next iteration,
697 it is much smarter than us */
698 if (Start
->Type
== pkgCache::Dep::Conflicts
||
699 Start
->Type
== pkgCache::Dep::DpkgBreaks
||
700 Start
->Type
== pkgCache::Dep::Obsoletes
)
704 clog
<< " Reinst Failed early because of " << Start
.TargetPkg().FullName(false) << endl
;
717 // Undo our operations - it might be smart to undo everything this did..
721 Cache
.MarkKeep(Pkg
, false, false);
723 Cache
.MarkDelete(Pkg
);
728 clog
<< " Re-Instated " << Pkg
.FullName(false) << endl
;
732 // ProblemResolver::Resolve - Run the resolution pass /*{{{*/
733 // ---------------------------------------------------------------------
734 /* This routines works by calculating a score for each package. The score
735 is derived by considering the package's priority and all reverse
736 dependents giving an integer that reflects the amount of breakage that
737 adjusting the package will inflict.
739 It goes from highest score to lowest and corrects all of the breaks by
740 keeping or removing the dependant packages. If that fails then it removes
741 the package itself and goes on. The routine should be able to intelligently
742 go from any broken state to a fixed state.
744 The BrokenFix flag enables a mode where the algorithm tries to
745 upgrade packages to advoid problems. */
746 bool pkgProblemResolver::Resolve(bool BrokenFix
)
748 pkgDepCache::ActionGroup
group(Cache
);
750 unsigned long Size
= Cache
.Head().PackageCount
;
752 // Record which packages are marked for install
757 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
759 if (Cache
[I
].Install() == true)
760 Flags
[I
->ID
] |= PreInstalled
;
763 if (Cache
[I
].InstBroken() == true && BrokenFix
== true)
765 Cache
.MarkInstall(I
, false, 0, false);
766 if (Cache
[I
].Install() == true)
770 Flags
[I
->ID
] &= ~PreInstalled
;
772 Flags
[I
->ID
] |= Upgradable
;
775 while (Again
== true);
778 clog
<< "Starting" << endl
;
782 /* We have to order the packages so that the broken fixing pass
783 operates from highest score to lowest. This prevents problems when
784 high score packages cause the removal of lower score packages that
785 would cause the removal of even lower score packages. */
786 SPtrArray
<pkgCache::Package
*> PList
= new pkgCache::Package
*[Size
];
787 pkgCache::Package
**PEnd
= PList
;
788 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
791 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
793 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
795 clog
<< "Show Scores" << endl
;
796 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
797 if (Scores
[(*K
)->ID
] != 0)
799 pkgCache::PkgIterator
Pkg(Cache
,*K
);
800 clog
<< Scores
[(*K
)->ID
] << ' ' << Pkg
<< std::endl
;
805 clog
<< "Starting 2" << endl
;
807 /* Now consider all broken packages. For each broken package we either
808 remove the package or fix it's problem. We do this once, it should
809 not be possible for a loop to form (that is a < b < c and fixing b by
810 changing a breaks c) */
812 bool const TryFixByInstall
= _config
->FindB("pkgProblemResolver::FixByInstall", true);
813 for (int Counter
= 0; Counter
!= 10 && Change
== true; Counter
++)
816 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
818 pkgCache::PkgIterator
I(Cache
,*K
);
820 /* We attempt to install this and see if any breaks result,
821 this takes care of some strange cases */
822 if (Cache
[I
].CandidateVer
!= Cache
[I
].InstallVer
&&
823 I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0 &&
824 (Flags
[I
->ID
] & PreInstalled
) != 0 &&
825 (Flags
[I
->ID
] & Protected
) == 0 &&
826 (Flags
[I
->ID
] & ReInstateTried
) == 0)
829 clog
<< " Try to Re-Instate (" << Counter
<< ") " << I
.FullName(false) << endl
;
830 unsigned long OldBreaks
= Cache
.BrokenCount();
831 pkgCache::Version
*OldVer
= Cache
[I
].InstallVer
;
832 Flags
[I
->ID
] &= ReInstateTried
;
834 Cache
.MarkInstall(I
, false, 0, false);
835 if (Cache
[I
].InstBroken() == true ||
836 OldBreaks
< Cache
.BrokenCount())
841 Cache
.MarkKeep(I
, false, false);
845 clog
<< "Re-Instated " << I
.FullName(false) << " (" << OldBreaks
<< " vs " << Cache
.BrokenCount() << ')' << endl
;
848 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
852 clog
<< "Investigating (" << Counter
<< ") " << I
<< endl
;
854 // Isolate the problem dependency
855 PackageKill KillList
[100];
856 PackageKill
*LEnd
= KillList
;
858 pkgCache::DepIterator Start
;
859 pkgCache::DepIterator End
;
860 PackageKill
*OldEnd
= LEnd
;
862 enum {OrRemove
,OrKeep
} OrOp
= OrRemove
;
863 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList();
864 D
.end() == false || InOr
== true;)
866 // Compute a single dependency element (glob or)
870 if (InOr
== true && OldEnd
== LEnd
)
872 if (OrOp
== OrRemove
)
874 if ((Flags
[I
->ID
] & Protected
) != Protected
)
877 clog
<< " Or group remove for " << I
.FullName(false) << endl
;
882 else if (OrOp
== OrKeep
)
885 clog
<< " Or group keep for " << I
.FullName(false) << endl
;
886 Cache
.MarkKeep(I
, false, false);
891 /* We do an extra loop (as above) to finalize the or group
896 if (Start
.end() == true)
899 // We only worry about critical deps.
900 if (End
.IsCritical() != true)
909 // We only worry about critical deps.
910 if (Start
.IsCritical() != true)
915 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
922 clog
<< "Broken " << Start
<< endl
;
924 /* Look across the version list. If there are no possible
925 targets then we keep the package and bail. This is necessary
926 if a package has a dep on another package that cant be found */
927 SPtrArray
<pkgCache::Version
*> VList
= Start
.AllTargets();
928 if (*VList
== 0 && (Flags
[I
->ID
] & Protected
) != Protected
&&
929 Start
->Type
!= pkgCache::Dep::Conflicts
&&
930 Start
->Type
!= pkgCache::Dep::DpkgBreaks
&&
931 Start
->Type
!= pkgCache::Dep::Obsoletes
&&
932 Cache
[I
].NowBroken() == false)
936 /* No keep choice because the keep being OK could be the
937 result of another element in the OR group! */
942 Cache
.MarkKeep(I
, false, false);
947 for (pkgCache::Version
**V
= VList
; *V
!= 0; V
++)
949 pkgCache::VerIterator
Ver(Cache
,*V
);
950 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
952 /* This is a conflicts, and the version we are looking
953 at is not the currently selected version of the
954 package, which means it is not necessary to
956 if (Cache
[Pkg
].InstallVer
!= Ver
&&
957 (Start
->Type
== pkgCache::Dep::Conflicts
||
958 Start
->Type
== pkgCache::Dep::DpkgBreaks
||
959 Start
->Type
== pkgCache::Dep::Obsoletes
))
962 clog
<< " Conflicts//Breaks against version "
963 << Ver
.VerStr() << " for " << Pkg
.Name()
964 << " but that is not InstVer, ignoring"
970 clog
<< " Considering " << Pkg
.FullName(false) << ' ' << (int)Scores
[Pkg
->ID
] <<
971 " as a solution to " << I
.FullName(false) << ' ' << (int)Scores
[I
->ID
] << endl
;
973 /* Try to fix the package under consideration rather than
974 fiddle with the VList package */
975 if (Scores
[I
->ID
] <= Scores
[Pkg
->ID
] ||
976 ((Cache
[Start
] & pkgDepCache::DepNow
) == 0 &&
977 End
->Type
!= pkgCache::Dep::Conflicts
&&
978 End
->Type
!= pkgCache::Dep::DpkgBreaks
&&
979 End
->Type
!= pkgCache::Dep::Obsoletes
))
981 // Try a little harder to fix protected packages..
982 if ((Flags
[I
->ID
] & Protected
) == Protected
)
984 if (DoUpgrade(Pkg
) == true)
986 if (Scores
[Pkg
->ID
] > Scores
[I
->ID
])
987 Scores
[Pkg
->ID
] = Scores
[I
->ID
];
994 /* See if a keep will do, unless the package is protected,
995 then installing it will be necessary */
996 bool Installed
= Cache
[I
].Install();
997 Cache
.MarkKeep(I
, false, false);
998 if (Cache
[I
].InstBroken() == false)
1000 // Unwind operation will be keep now
1001 if (OrOp
== OrRemove
)
1005 if (InOr
== true && Installed
== true)
1006 Cache
.MarkInstall(I
, false, 0, false);
1009 clog
<< " Holding Back " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
1013 if (BrokenFix
== false || DoUpgrade(I
) == false)
1015 // Consider other options
1019 clog
<< " Removing " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
1020 Cache
.MarkDelete(I
);
1021 if (Counter
> 1 && Scores
[Pkg
->ID
] > Scores
[I
->ID
])
1022 Scores
[I
->ID
] = Scores
[Pkg
->ID
];
1024 else if (TryFixByInstall
== true &&
1025 Start
.TargetPkg()->CurrentVer
== 0 &&
1026 Cache
[Start
.TargetPkg()].Delete() == false &&
1027 (Flags
[Start
.TargetPkg()->ID
] & ToRemove
) != ToRemove
&&
1028 Cache
.GetCandidateVer(Start
.TargetPkg()).end() == false)
1030 /* Before removing or keeping the package with the broken dependency
1031 try instead to install the first not previously installed package
1032 solving this dependency. This helps every time a previous solver
1033 is removed by the resolver because of a conflict or alike but it is
1034 dangerous as it could trigger new breaks/conflicts… */
1036 clog
<< " Try Installing " << Start
.TargetPkg() << " before changing " << I
.FullName(false) << std::endl
;
1037 unsigned long const OldBroken
= Cache
.BrokenCount();
1038 Cache
.MarkInstall(Start
.TargetPkg(), true, 1, false);
1039 // FIXME: we should undo the complete MarkInstall process here
1040 if (Cache
[Start
.TargetPkg()].InstBroken() == true || Cache
.BrokenCount() > OldBroken
)
1041 Cache
.MarkDelete(Start
.TargetPkg(), false, 1, false);
1052 if (Start
->Type
== pkgCache::Dep::DpkgBreaks
)
1054 // first, try upgradring the package, if that
1055 // does not help, the breaks goes onto the
1058 // FIXME: use DoUpgrade(Pkg) instead?
1059 if (Cache
[End
] & pkgDepCache::DepGCVer
)
1062 clog
<< " Upgrading " << Pkg
.FullName(false) << " due to Breaks field in " << I
.FullName(false) << endl
;
1063 Cache
.MarkInstall(Pkg
, false, 0, false);
1068 // Skip adding to the kill list if it is protected
1069 if ((Flags
[Pkg
->ID
] & Protected
) != 0)
1073 clog
<< " Added " << Pkg
.FullName(false) << " to the remove list" << endl
;
1079 if (Start
->Type
!= pkgCache::Dep::Conflicts
&&
1080 Start
->Type
!= pkgCache::Dep::Obsoletes
)
1085 // Hm, nothing can possibly satisify this dep. Nuke it.
1086 if (VList
[0] == 0 &&
1087 Start
->Type
!= pkgCache::Dep::Conflicts
&&
1088 Start
->Type
!= pkgCache::Dep::DpkgBreaks
&&
1089 Start
->Type
!= pkgCache::Dep::Obsoletes
&&
1090 (Flags
[I
->ID
] & Protected
) != Protected
)
1092 bool Installed
= Cache
[I
].Install();
1094 if (Cache
[I
].InstBroken() == false)
1096 // Unwind operation will be keep now
1097 if (OrOp
== OrRemove
)
1101 if (InOr
== true && Installed
== true)
1102 Cache
.MarkInstall(I
, false, 0, false);
1105 clog
<< " Holding Back " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1110 clog
<< " Removing " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1112 Cache
.MarkDelete(I
);
1127 // Apply the kill list now
1128 if (Cache
[I
].InstallVer
!= 0)
1130 for (PackageKill
*J
= KillList
; J
!= LEnd
; J
++)
1133 if ((Cache
[J
->Dep
] & pkgDepCache::DepGNow
) == 0)
1135 if (J
->Dep
->Type
== pkgCache::Dep::Conflicts
||
1136 J
->Dep
->Type
== pkgCache::Dep::DpkgBreaks
||
1137 J
->Dep
->Type
== pkgCache::Dep::Obsoletes
)
1140 clog
<< " Fixing " << I
.FullName(false) << " via remove of " << J
->Pkg
.FullName(false) << endl
;
1141 Cache
.MarkDelete(J
->Pkg
);
1147 clog
<< " Fixing " << I
.FullName(false) << " via keep of " << J
->Pkg
.FullName(false) << endl
;
1148 Cache
.MarkKeep(J
->Pkg
, false, false);
1153 if (Scores
[I
->ID
] > Scores
[J
->Pkg
->ID
])
1154 Scores
[J
->Pkg
->ID
] = Scores
[I
->ID
];
1162 clog
<< "Done" << endl
;
1164 if (Cache
.BrokenCount() != 0)
1166 // See if this is the result of a hold
1167 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1168 for (;I
.end() != true; I
++)
1170 if (Cache
[I
].InstBroken() == false)
1172 if ((Flags
[I
->ID
] & Protected
) != Protected
)
1173 return _error
->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
1175 return _error
->Error(_("Unable to correct problems, you have held broken packages."));
1178 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
1179 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1180 for (;I
.end() != true; I
++) {
1181 if (Cache
[I
].NewInstall() && !(Flags
[I
->ID
] & PreInstalled
)) {
1182 if(_config
->FindI("Debug::pkgAutoRemove",false)) {
1183 std::clog
<< "Resolve installed new pkg: " << I
.FullName(false)
1184 << " (now marking it as auto)" << std::endl
;
1186 Cache
[I
].Flags
|= pkgCache::Flag::Auto
;
1194 // ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1195 // ---------------------------------------------------------------------
1196 /* This is the work horse of the soft upgrade routine. It is very gental
1197 in that it does not install or remove any packages. It is assumed that the
1198 system was non-broken previously. */
1199 bool pkgProblemResolver::ResolveByKeep()
1201 pkgDepCache::ActionGroup
group(Cache
);
1203 unsigned long Size
= Cache
.Head().PackageCount
;
1207 /* We have to order the packages so that the broken fixing pass
1208 operates from highest score to lowest. This prevents problems when
1209 high score packages cause the removal of lower score packages that
1210 would cause the removal of even lower score packages. */
1211 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
1212 pkgCache::Package
**PEnd
= PList
;
1213 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
1216 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
1218 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1220 clog
<< "Show Scores" << endl
;
1221 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1222 if (Scores
[(*K
)->ID
] != 0)
1224 pkgCache::PkgIterator
Pkg(Cache
,*K
);
1225 clog
<< Scores
[(*K
)->ID
] << ' ' << Pkg
<< std::endl
;
1230 clog
<< "Entering ResolveByKeep" << endl
;
1232 // Consider each broken package
1233 pkgCache::Package
**LastStop
= 0;
1234 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1236 pkgCache::PkgIterator
I(Cache
,*K
);
1238 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
1241 /* Keep the package. If this works then great, otherwise we have
1242 to be significantly more agressive and manipulate its dependencies */
1243 if ((Flags
[I
->ID
] & Protected
) == 0)
1246 clog
<< "Keeping package " << I
.FullName(false) << endl
;
1247 Cache
.MarkKeep(I
, false, false);
1248 if (Cache
[I
].InstBroken() == false)
1255 // Isolate the problem dependencies
1256 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
1260 D
.GlobOr(Start
,End
);
1262 // We only worry about critical deps.
1263 if (End
.IsCritical() != true)
1267 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
1270 /* Hm, the group is broken.. I suppose the best thing to do is to
1271 is to try every combination of keep/not-keep for the set, but thats
1272 slow, and this never happens, just be conservative and assume the
1273 list of ors is in preference and keep till it starts to work. */
1277 clog
<< "Package " << I
.FullName(false) << " " << Start
<< endl
;
1279 // Look at all the possible provides on this package
1280 SPtrArray
<pkgCache::Version
*> VList
= Start
.AllTargets();
1281 for (pkgCache::Version
**V
= VList
; *V
!= 0; V
++)
1283 pkgCache::VerIterator
Ver(Cache
,*V
);
1284 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
1286 // It is not keepable
1287 if (Cache
[Pkg
].InstallVer
== 0 ||
1288 Pkg
->CurrentVer
== 0)
1291 if ((Flags
[I
->ID
] & Protected
) == 0)
1294 clog
<< " Keeping Package " << Pkg
.FullName(false) << " due to " << Start
.DepType() << endl
;
1295 Cache
.MarkKeep(Pkg
, false, false);
1298 if (Cache
[I
].InstBroken() == false)
1302 if (Cache
[I
].InstBroken() == false)
1310 if (Cache
[I
].InstBroken() == false)
1314 if (Cache
[I
].InstBroken() == true)
1319 return _error
->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I
.FullName(false).c_str());
1327 // ProblemResolver::InstallProtect - Install all protected packages /*{{{*/
1328 // ---------------------------------------------------------------------
1329 /* This is used to make sure protected packages are installed */
1330 void pkgProblemResolver::InstallProtect()
1332 pkgDepCache::ActionGroup
group(Cache
);
1334 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
1336 if ((Flags
[I
->ID
] & Protected
) == Protected
)
1338 if ((Flags
[I
->ID
] & ToRemove
) == ToRemove
)
1339 Cache
.MarkDelete(I
);
1342 // preserve the information whether the package was auto
1343 // or manually installed
1344 bool autoInst
= (Cache
[I
].Flags
& pkgCache::Flag::Auto
);
1345 Cache
.MarkInstall(I
, false, 0, !autoInst
);
1351 // PrioSortList - Sort a list of versions by priority /*{{{*/
1352 // ---------------------------------------------------------------------
1353 /* This is ment to be used in conjunction with AllTargets to get a list
1354 of versions ordered by preference. */
1355 static pkgCache
*PrioCache
;
1356 static int PrioComp(const void *A
,const void *B
)
1358 pkgCache::VerIterator
L(*PrioCache
,*(pkgCache::Version
**)A
);
1359 pkgCache::VerIterator
R(*PrioCache
,*(pkgCache::Version
**)B
);
1361 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
&&
1362 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
)
1364 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
1365 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
1368 if (L
->Priority
!= R
->Priority
)
1369 return R
->Priority
- L
->Priority
;
1370 return strcmp(L
.ParentPkg().Name(),R
.ParentPkg().Name());
1372 void pkgPrioSortList(pkgCache
&Cache
,pkgCache::Version
**List
)
1374 unsigned long Count
= 0;
1376 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
1378 qsort(List
,Count
,sizeof(*List
),PrioComp
);
1381 // CacheFile::ListUpdate - update the cache files /*{{{*/
1382 // ---------------------------------------------------------------------
1383 /* This is a simple wrapper to update the cache. it will fetch stuff
1384 * from the network (or any other sources defined in sources.list)
1386 bool ListUpdate(pkgAcquireStatus
&Stat
,
1387 pkgSourceList
&List
,
1390 pkgAcquire::RunResult res
;
1392 if (Fetcher
.Setup(&Stat
, _config
->FindDir("Dir::State::Lists")) == false)
1395 // Populate it with the source selection
1396 if (List
.GetIndexes(&Fetcher
) == false)
1400 RunScripts("APT::Update::Pre-Invoke");
1404 res
= Fetcher
.Run(PulseInterval
);
1406 res
= Fetcher
.Run();
1408 if (res
== pkgAcquire::Failed
)
1411 bool Failed
= false;
1412 bool TransientNetworkFailure
= false;
1413 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin();
1414 I
!= Fetcher
.ItemsEnd(); I
++)
1416 if ((*I
)->Status
== pkgAcquire::Item::StatDone
)
1421 ::URI
uri((*I
)->DescURI());
1423 uri
.Password
.clear();
1424 string descUri
= string(uri
);
1425 _error
->Warning(_("Failed to fetch %s %s\n"), descUri
.c_str(),
1426 (*I
)->ErrorText
.c_str());
1428 if ((*I
)->Status
== pkgAcquire::Item::StatTransientNetworkError
)
1430 TransientNetworkFailure
= true;
1437 // Clean out any old list files
1438 // Keep "APT::Get::List-Cleanup" name for compatibility, but
1439 // this is really a global option for the APT library now
1440 if (!TransientNetworkFailure
&& !Failed
&&
1441 (_config
->FindB("APT::Get::List-Cleanup",true) == true &&
1442 _config
->FindB("APT::List-Cleanup",true) == true))
1444 if (Fetcher
.Clean(_config
->FindDir("Dir::State::lists")) == false ||
1445 Fetcher
.Clean(_config
->FindDir("Dir::State::lists") + "partial/") == false)
1446 // something went wrong with the clean
1450 if (TransientNetworkFailure
== true)
1451 _error
->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead."));
1452 else if (Failed
== true)
1453 return _error
->Error(_("Some index files failed to download. They have been ignored, or old ones used instead."));
1456 // Run the success scripts if all was fine
1457 if(!TransientNetworkFailure
&& !Failed
)
1458 RunScripts("APT::Update::Post-Invoke-Success");
1460 // Run the other scripts
1461 RunScripts("APT::Update::Post-Invoke");