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 /*{{{*/
19 #include <apt-pkg/algorithms.h>
20 #include <apt-pkg/error.h>
21 #include <apt-pkg/configuration.h>
22 #include <apt-pkg/edsp.h>
23 #include <apt-pkg/depcache.h>
24 #include <apt-pkg/packagemanager.h>
25 #include <apt-pkg/pkgcache.h>
26 #include <apt-pkg/cacheiterators.h>
27 #include <apt-pkg/prettyprinters.h>
28 #include <apt-pkg/dpkgpm.h>
40 class APT_HIDDEN pkgSimulatePrivate
43 std::vector
<pkgDPkgPM::Item
> List
;
45 // Simulate::Simulate - Constructor /*{{{*/
46 // ---------------------------------------------------------------------
47 /* The legacy translations here of input Pkg iterators is obsolete,
48 this is not necessary since the pkgCaches are fully shared now. */
49 pkgSimulate::pkgSimulate(pkgDepCache
*Cache
) : pkgPackageManager(Cache
),
50 d(new pkgSimulatePrivate()), iPolicy(Cache
),
51 Sim(&Cache
->GetCache(),&iPolicy
),
55 Flags
= new unsigned char[Cache
->Head().PackageCount
];
56 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
58 // Fake a filename so as not to activate the media swapping
59 string Jnk
= "SIMULATE";
60 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
64 // Simulate::~Simulate - Destructor /*{{{*/
65 pkgSimulate::~pkgSimulate()
71 // Simulate::Describe - Describe a package /*{{{*/
72 // ---------------------------------------------------------------------
73 /* Parameter Current == true displays the current package version,
74 Parameter Candidate == true displays the candidate package version */
75 void pkgSimulate::Describe(PkgIterator Pkg
,ostream
&out
,bool Current
,bool Candidate
)
79 out
<< Pkg
.FullName(true);
83 Ver
= Pkg
.CurrentVer();
84 if (Ver
.end() == false)
85 out
<< " [" << Ver
.VerStr() << ']';
88 if (Candidate
== true)
90 Ver
= Sim
[Pkg
].CandidateVerIter(Sim
);
91 if (Ver
.end() == true)
94 out
<< " (" << Ver
.VerStr() << ' ' << Ver
.RelStr() << ')';
98 // Simulate::Install - Simulate unpacking of a package /*{{{*/
99 // ---------------------------------------------------------------------
101 bool pkgSimulate::Install(PkgIterator iPkg
,string File
)
103 if (iPkg
.end() || File
.empty())
105 d
->List
.emplace_back(pkgDPkgPM::Item::Install
, iPkg
, File
);
108 bool pkgSimulate::RealInstall(PkgIterator iPkg
,string
/*File*/)
110 // Adapt the iterator
111 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
115 Describe(Pkg
,cout
,true,true);
116 Sim
.MarkInstall(Pkg
,false);
118 // Look for broken conflicts+predepends.
119 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; ++I
)
121 if (Sim
[I
].InstallVer
== 0)
124 for (DepIterator D
= Sim
[I
].InstVerIter(Sim
).DependsList(); D
.end() == false;)
129 if (Start
.IsNegative() == true ||
130 End
->Type
== pkgCache::Dep::PreDepends
)
132 if ((Sim
[End
] & pkgDepCache::DepGInstall
) == 0)
134 cout
<< " [" << I
.FullName(false) << " on " << Start
.TargetPkg().FullName(false) << ']';
135 if (Start
->Type
== pkgCache::Dep::Conflicts
)
136 _error
->Error("Fatal, conflicts violated %s",I
.FullName(false).c_str());
142 if (Sim
.BrokenCount() != 0)
149 // Simulate::Configure - Simulate configuration of a Package /*{{{*/
150 // ---------------------------------------------------------------------
151 /* This is not an acurate simulation of relatity, we should really not
152 install the package.. For some investigations it may be necessary
154 bool pkgSimulate::Configure(PkgIterator iPkg
)
158 d
->List
.emplace_back(pkgDPkgPM::Item::Configure
, iPkg
);
161 bool pkgSimulate::RealConfigure(PkgIterator iPkg
)
163 // Adapt the iterator
164 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
168 if (Sim
[Pkg
].InstBroken() == true)
170 cout
<< "Conf " << Pkg
.FullName(false) << " broken" << endl
;
174 // Print out each package and the failed dependencies
175 for (pkgCache::DepIterator D
= Sim
[Pkg
].InstVerIter(Sim
).DependsList(); D
.end() == false; ++D
)
177 if (Sim
.IsImportantDep(D
) == false ||
178 (Sim
[D
] & pkgDepCache::DepInstall
) != 0)
181 if (D
->Type
== pkgCache::Dep::Obsoletes
)
182 cout
<< " Obsoletes:" << D
.TargetPkg().FullName(false);
183 else if (D
->Type
== pkgCache::Dep::Conflicts
)
184 cout
<< " Conflicts:" << D
.TargetPkg().FullName(false);
185 else if (D
->Type
== pkgCache::Dep::DpkgBreaks
)
186 cout
<< " Breaks:" << D
.TargetPkg().FullName(false);
188 cout
<< " Depends:" << D
.TargetPkg().FullName(false);
192 _error
->Error("Conf Broken %s",Pkg
.FullName(false).c_str());
197 Describe(Pkg
,cout
,false,true);
200 if (Sim
.BrokenCount() != 0)
208 // Simulate::Remove - Simulate the removal of a package /*{{{*/
209 // ---------------------------------------------------------------------
211 bool pkgSimulate::Remove(PkgIterator iPkg
,bool Purge
)
215 d
->List
.emplace_back(Purge
? pkgDPkgPM::Item::Purge
: pkgDPkgPM::Item::Remove
, iPkg
);
218 bool pkgSimulate::RealRemove(PkgIterator iPkg
,bool Purge
)
220 // Adapt the iterator
221 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
222 if (Pkg
.end() == true)
224 std::cerr
<< (Purge
? "Purg" : "Remv") << " invalid package " << iPkg
.FullName() << std::endl
;
235 Describe(Pkg
,cout
,true,false);
237 if (Sim
.BrokenCount() != 0)
245 // Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
246 // ---------------------------------------------------------------------
248 void pkgSimulate::ShortBreaks()
251 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; ++I
)
253 if (Sim
[I
].InstBroken() == true)
255 if (Flags
[I
->ID
] == 0)
256 cout
<< I
.FullName(false) << ' ';
258 cout << I.Name() << "! ";*/
264 bool pkgSimulate::Go2(APT::Progress::PackageManager
*) /*{{{*/
266 if (pkgDPkgPM::ExpandPendingCalls(d
->List
, Cache
) == false)
268 for (auto && I
: d
->List
)
271 case pkgDPkgPM::Item::Install
:
272 if (RealInstall(I
.Pkg
, I
.File
) == false)
275 case pkgDPkgPM::Item::Configure
:
276 if (RealConfigure(I
.Pkg
) == false)
279 case pkgDPkgPM::Item::Remove
:
280 if (RealRemove(I
.Pkg
, false) == false)
283 case pkgDPkgPM::Item::Purge
:
284 if (RealRemove(I
.Pkg
, true) == false)
287 case pkgDPkgPM::Item::ConfigurePending
:
288 case pkgDPkgPM::Item::TriggersPending
:
289 case pkgDPkgPM::Item::RemovePending
:
290 case pkgDPkgPM::Item::PurgePending
:
291 return _error
->Error("Internal error, simulation encountered unexpected pending item");
296 // ApplyStatus - Adjust for non-ok packages /*{{{*/
297 // ---------------------------------------------------------------------
298 /* We attempt to change the state of the all packages that have failed
299 installation toward their real state. The ordering code will perform
300 the necessary calculations to deal with the problems. */
301 bool pkgApplyStatus(pkgDepCache
&Cache
)
303 pkgDepCache::ActionGroup
group(Cache
);
305 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
307 if (I
->VersionList
== 0)
310 // Only choice for a ReInstReq package is to reinstall
311 if (I
->InstState
== pkgCache::State::ReInstReq
||
312 I
->InstState
== pkgCache::State::HoldReInstReq
)
314 if (I
->CurrentVer
!= 0 && I
.CurrentVer().Downloadable() == true)
315 Cache
.MarkKeep(I
, false, false);
318 // Is this right? Will dpkg choke on an upgrade?
319 if (Cache
[I
].CandidateVer
!= 0 &&
320 Cache
[I
].CandidateVerIter(Cache
).Downloadable() == true)
321 Cache
.MarkInstall(I
, false, 0, false);
323 return _error
->Error(_("The package %s needs to be reinstalled, "
324 "but I can't find an archive for it."),I
.FullName(true).c_str());
330 switch (I
->CurrentState
)
332 /* This means installation failed somehow - it does not need to be
333 re-unpacked (probably) */
334 case pkgCache::State::UnPacked
:
335 case pkgCache::State::HalfConfigured
:
336 case pkgCache::State::TriggersAwaited
:
337 case pkgCache::State::TriggersPending
:
338 if ((I
->CurrentVer
!= 0 && I
.CurrentVer().Downloadable() == true) ||
339 I
.State() != pkgCache::PkgIterator::NeedsUnpack
)
340 Cache
.MarkKeep(I
, false, false);
343 if (Cache
[I
].CandidateVer
!= 0 &&
344 Cache
[I
].CandidateVerIter(Cache
).Downloadable() == true)
345 Cache
.MarkInstall(I
, true, 0, false);
347 Cache
.MarkDelete(I
, false, 0, false);
351 // This means removal failed
352 case pkgCache::State::HalfInstalled
:
353 Cache
.MarkDelete(I
, false, 0, false);
357 if (I
->InstState
!= pkgCache::State::Ok
)
358 return _error
->Error("The package %s is not ok and I "
359 "don't know how to fix it!",I
.FullName(false).c_str());
365 // FixBroken - Fix broken packages /*{{{*/
366 // ---------------------------------------------------------------------
367 /* This autoinstalls every broken package and then runs the problem resolver
369 bool pkgFixBroken(pkgDepCache
&Cache
)
371 pkgDepCache::ActionGroup
group(Cache
);
373 // Auto upgrade all broken packages
374 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
375 if (Cache
[I
].NowBroken() == true)
376 Cache
.MarkInstall(I
, true, 0, false);
378 /* Fix packages that are in a NeedArchive state but don't have a
379 downloadable install version */
380 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
382 if (I
.State() != pkgCache::PkgIterator::NeedsUnpack
||
383 Cache
[I
].Delete() == true)
386 if (Cache
[I
].InstVerIter(Cache
).Downloadable() == false)
389 Cache
.MarkInstall(I
, true, 0, false);
392 pkgProblemResolver
Fix(&Cache
);
393 return Fix
.Resolve(true);
396 // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
397 // ---------------------------------------------------------------------
399 pkgProblemResolver::pkgProblemResolver(pkgDepCache
*pCache
) : d(NULL
), Cache(*pCache
)
402 unsigned long Size
= Cache
.Head().PackageCount
;
403 Scores
= new int[Size
];
404 Flags
= new unsigned char[Size
];
405 memset(Flags
,0,sizeof(*Flags
)*Size
);
407 // Set debug to true to see its decision logic
408 Debug
= _config
->FindB("Debug::pkgProblemResolver",false);
411 // ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
412 // ---------------------------------------------------------------------
414 pkgProblemResolver::~pkgProblemResolver()
420 // ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
421 // ---------------------------------------------------------------------
423 int pkgProblemResolver::ScoreSort(Package
const *A
,Package
const *B
)
425 if (Scores
[A
->ID
] > Scores
[B
->ID
])
427 if (Scores
[A
->ID
] < Scores
[B
->ID
])
432 // ProblemResolver::MakeScores - Make the score table /*{{{*/
433 // ---------------------------------------------------------------------
435 void pkgProblemResolver::MakeScores()
437 unsigned long Size
= Cache
.Head().PackageCount
;
438 memset(Scores
,0,sizeof(*Scores
)*Size
);
440 // maps to pkgCache::State::VerPriority:
441 // Required Important Standard Optional Extra
444 _config
->FindI("pkgProblemResolver::Scores::Required",3),
445 _config
->FindI("pkgProblemResolver::Scores::Important",2),
446 _config
->FindI("pkgProblemResolver::Scores::Standard",1),
447 _config
->FindI("pkgProblemResolver::Scores::Optional",-1),
448 _config
->FindI("pkgProblemResolver::Scores::Extra",-2)
450 int PrioEssentials
= _config
->FindI("pkgProblemResolver::Scores::Essentials",100);
451 int PrioInstalledAndNotObsolete
= _config
->FindI("pkgProblemResolver::Scores::NotObsolete",1);
454 _config
->FindI("pkgProblemResolver::Scores::Depends",1),
455 _config
->FindI("pkgProblemResolver::Scores::PreDepends",1),
456 _config
->FindI("pkgProblemResolver::Scores::Suggests",0),
457 _config
->FindI("pkgProblemResolver::Scores::Recommends",1),
458 _config
->FindI("pkgProblemResolver::Scores::Conflicts",-1),
459 _config
->FindI("pkgProblemResolver::Scores::Replaces",0),
460 _config
->FindI("pkgProblemResolver::Scores::Obsoletes",0),
461 _config
->FindI("pkgProblemResolver::Scores::Breaks",-1),
462 _config
->FindI("pkgProblemResolver::Scores::Enhances",0)
464 int AddProtected
= _config
->FindI("pkgProblemResolver::Scores::AddProtected",10000);
465 int AddEssential
= _config
->FindI("pkgProblemResolver::Scores::AddEssential",5000);
467 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
468 clog
<< "Settings used to calculate pkgProblemResolver::Scores::" << endl
469 << " Required => " << PrioMap
[pkgCache::State::Required
] << endl
470 << " Important => " << PrioMap
[pkgCache::State::Important
] << endl
471 << " Standard => " << PrioMap
[pkgCache::State::Standard
] << endl
472 << " Optional => " << PrioMap
[pkgCache::State::Optional
] << endl
473 << " Extra => " << PrioMap
[pkgCache::State::Extra
] << endl
474 << " Essentials => " << PrioEssentials
<< endl
475 << " InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete
<< endl
476 << " Pre-Depends => " << DepMap
[pkgCache::Dep::PreDepends
] << endl
477 << " Depends => " << DepMap
[pkgCache::Dep::Depends
] << endl
478 << " Recommends => " << DepMap
[pkgCache::Dep::Recommends
] << endl
479 << " Suggests => " << DepMap
[pkgCache::Dep::Suggests
] << endl
480 << " Conflicts => " << DepMap
[pkgCache::Dep::Conflicts
] << endl
481 << " Breaks => " << DepMap
[pkgCache::Dep::DpkgBreaks
] << endl
482 << " Replaces => " << DepMap
[pkgCache::Dep::Replaces
] << endl
483 << " Obsoletes => " << DepMap
[pkgCache::Dep::Obsoletes
] << endl
484 << " Enhances => " << DepMap
[pkgCache::Dep::Enhances
] << endl
485 << " AddProtected => " << AddProtected
<< endl
486 << " AddEssential => " << AddEssential
<< endl
;
488 // Generate the base scores for a package based on its properties
489 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
491 if (Cache
[I
].InstallVer
== 0)
494 int &Score
= Scores
[I
->ID
];
496 /* This is arbitrary, it should be high enough to elevate an
497 essantial package above most other packages but low enough
498 to allow an obsolete essential packages to be removed by
499 a conflicts on a powerful normal package (ie libc6) */
500 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
501 || (I
->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
502 Score
+= PrioEssentials
;
504 pkgCache::VerIterator
const InstVer
= Cache
[I
].InstVerIter(Cache
);
505 // We apply priorities only to downloadable packages, all others are prio:extra
506 // as an obsolete prio:standard package can't be that standard anymore…
507 if (InstVer
->Priority
<= pkgCache::State::Extra
&& InstVer
.Downloadable() == true)
508 Score
+= PrioMap
[InstVer
->Priority
];
510 Score
+= PrioMap
[pkgCache::State::Extra
];
512 /* This helps to fix oddball problems with conflicting packages
513 on the same level. We enhance the score of installed packages
514 if those are not obsolete */
515 if (I
->CurrentVer
!= 0 && Cache
[I
].CandidateVer
!= 0 && Cache
[I
].CandidateVerIter(Cache
).Downloadable())
516 Score
+= PrioInstalledAndNotObsolete
;
518 // propagate score points along dependencies
519 for (pkgCache::DepIterator D
= InstVer
.DependsList(); D
.end() == false; ++D
)
521 if (DepMap
[D
->Type
] == 0)
523 pkgCache::PkgIterator
const T
= D
.TargetPkg();
526 pkgCache::VerIterator
const IV
= Cache
[T
].InstVerIter(Cache
);
527 if (IV
.end() == true || D
.IsSatisfied(IV
) == false)
530 Scores
[T
->ID
] += DepMap
[D
->Type
];
534 // Copy the scores to advoid additive looping
535 std::unique_ptr
<int[]> OldScores(new int[Size
]);
536 memcpy(OldScores
.get(),Scores
,sizeof(*Scores
)*Size
);
538 /* Now we cause 1 level of dependency inheritance, that is we add the
539 score of the packages that depend on the target Package. This
540 fortifies high scoring packages */
541 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
543 if (Cache
[I
].InstallVer
== 0)
546 for (pkgCache::DepIterator D
= I
.RevDependsList(); D
.end() == false; ++D
)
548 // Only do it for the install version
549 if ((pkgCache::Version
*)D
.ParentVer() != Cache
[D
.ParentPkg()].InstallVer
||
550 (D
->Type
!= pkgCache::Dep::Depends
&&
551 D
->Type
!= pkgCache::Dep::PreDepends
&&
552 D
->Type
!= pkgCache::Dep::Recommends
))
555 // Do not propagate negative scores otherwise
556 // an extra (-2) package might score better than an optional (-1)
557 if (OldScores
[D
.ParentPkg()->ID
] > 0)
558 Scores
[I
->ID
] += OldScores
[D
.ParentPkg()->ID
];
562 /* Now we propagate along provides. This makes the packages that
563 provide important packages extremely important */
564 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
566 for (pkgCache::PrvIterator P
= I
.ProvidesList(); P
.end() == false; ++P
)
568 // Only do it once per package
569 if ((pkgCache::Version
*)P
.OwnerVer() != Cache
[P
.OwnerPkg()].InstallVer
)
571 Scores
[P
.OwnerPkg()->ID
] += abs(Scores
[I
->ID
] - OldScores
[I
->ID
]);
575 /* Protected things are pushed really high up. This number should put them
576 ahead of everything */
577 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
579 if ((Flags
[I
->ID
] & Protected
) != 0)
580 Scores
[I
->ID
] += AddProtected
;
581 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
||
582 (I
->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
583 Scores
[I
->ID
] += AddEssential
;
587 // ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
588 // ---------------------------------------------------------------------
589 /* This goes through and tries to reinstall packages to make this package
591 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg
)
593 pkgDepCache::ActionGroup
group(Cache
);
595 if ((Flags
[Pkg
->ID
] & Upgradable
) == 0 || Cache
[Pkg
].Upgradable() == false)
597 if ((Flags
[Pkg
->ID
] & Protected
) == Protected
)
600 Flags
[Pkg
->ID
] &= ~Upgradable
;
602 bool WasKept
= Cache
[Pkg
].Keep();
603 Cache
.MarkInstall(Pkg
, false, 0, false);
605 // This must be a virtual package or something like that.
606 if (Cache
[Pkg
].InstVerIter(Cache
).end() == true)
609 // Isolate the problem dependency
611 for (pkgCache::DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
613 // Compute a single dependency element (glob or)
614 pkgCache::DepIterator Start
= D
;
615 pkgCache::DepIterator End
= D
;
616 for (bool LastOR
= true; D
.end() == false && LastOR
== true;)
618 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
624 // We only worry about critical deps.
625 if (End
.IsCritical() != true)
628 // Iterate over all the members in the or group
632 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
635 // Do not change protected packages
636 PkgIterator P
= Start
.SmartTargetPkg();
637 if ((Flags
[P
->ID
] & Protected
) == Protected
)
640 clog
<< " Reinst Failed because of protected " << P
.FullName(false) << endl
;
645 // Upgrade the package if the candidate version will fix the problem.
646 if ((Cache
[Start
] & pkgDepCache::DepCVer
) == pkgDepCache::DepCVer
)
648 if (DoUpgrade(P
) == false)
651 clog
<< " Reinst Failed because of " << P
.FullName(false) << endl
;
662 /* We let the algorithm deal with conflicts on its next iteration,
663 it is much smarter than us */
664 if (Start
.IsNegative() == true)
668 clog
<< " Reinst Failed early because of " << Start
.TargetPkg().FullName(false) << endl
;
681 // Undo our operations - it might be smart to undo everything this did..
685 Cache
.MarkKeep(Pkg
, false, false);
687 Cache
.MarkDelete(Pkg
, false, 0, false);
692 clog
<< " Re-Instated " << Pkg
.FullName(false) << endl
;
696 // ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/
697 bool pkgProblemResolver::Resolve(bool BrokenFix
, OpProgress
* const Progress
)
699 std::string
const solver
= _config
->Find("APT::Solver", "internal");
700 auto const ret
= EDSP::ResolveExternal(solver
.c_str(), Cache
, 0, Progress
);
701 if (solver
!= "internal")
703 return ResolveInternal(BrokenFix
);
706 // ProblemResolver::ResolveInternal - Run the resolution pass /*{{{*/
707 // ---------------------------------------------------------------------
708 /* This routines works by calculating a score for each package. The score
709 is derived by considering the package's priority and all reverse
710 dependents giving an integer that reflects the amount of breakage that
711 adjusting the package will inflict.
713 It goes from highest score to lowest and corrects all of the breaks by
714 keeping or removing the dependent packages. If that fails then it removes
715 the package itself and goes on. The routine should be able to intelligently
716 go from any broken state to a fixed state.
718 The BrokenFix flag enables a mode where the algorithm tries to
719 upgrade packages to advoid problems. */
720 bool pkgProblemResolver::ResolveInternal(bool const BrokenFix
)
722 pkgDepCache::ActionGroup
group(Cache
);
724 // Record which packages are marked for install
729 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
731 if (Cache
[I
].Install() == true)
732 Flags
[I
->ID
] |= PreInstalled
;
735 if (Cache
[I
].InstBroken() == true && BrokenFix
== true)
737 Cache
.MarkInstall(I
, false, 0, false);
738 if (Cache
[I
].Install() == true)
742 Flags
[I
->ID
] &= ~PreInstalled
;
744 Flags
[I
->ID
] |= Upgradable
;
747 while (Again
== true);
750 clog
<< "Starting pkgProblemResolver with broken count: "
751 << Cache
.BrokenCount() << endl
;
756 unsigned long const Size
= Cache
.Head().PackageCount
;
758 /* We have to order the packages so that the broken fixing pass
759 operates from highest score to lowest. This prevents problems when
760 high score packages cause the removal of lower score packages that
761 would cause the removal of even lower score packages. */
762 std::unique_ptr
<pkgCache::Package
*[]> PList(new pkgCache::Package
*[Size
]);
763 pkgCache::Package
**PEnd
= PList
.get();
764 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
767 std::sort(PList
.get(), PEnd
, [this](Package
*a
, Package
*b
) { return ScoreSort(a
, b
) < 0; });
769 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
771 clog
<< "Show Scores" << endl
;
772 for (pkgCache::Package
**K
= PList
.get(); K
!= PEnd
; K
++)
773 if (Scores
[(*K
)->ID
] != 0)
775 pkgCache::PkgIterator
Pkg(Cache
,*K
);
776 clog
<< Scores
[(*K
)->ID
] << ' ' << APT::PrettyPkg(&Cache
, Pkg
) << std::endl
;
781 clog
<< "Starting 2 pkgProblemResolver with broken count: "
782 << Cache
.BrokenCount() << endl
;
785 /* Now consider all broken packages. For each broken package we either
786 remove the package or fix it's problem. We do this once, it should
787 not be possible for a loop to form (that is a < b < c and fixing b by
788 changing a breaks c) */
790 bool const TryFixByInstall
= _config
->FindB("pkgProblemResolver::FixByInstall", true);
791 std::vector
<PackageKill
> KillList
;
792 for (int Counter
= 0; Counter
!= 10 && Change
== true; Counter
++)
795 for (pkgCache::Package
**K
= PList
.get(); K
!= PEnd
; K
++)
797 pkgCache::PkgIterator
I(Cache
,*K
);
799 /* We attempt to install this and see if any breaks result,
800 this takes care of some strange cases */
801 if (Cache
[I
].CandidateVer
!= Cache
[I
].InstallVer
&&
802 I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0 &&
803 (Flags
[I
->ID
] & PreInstalled
) != 0 &&
804 (Flags
[I
->ID
] & Protected
) == 0 &&
805 (Flags
[I
->ID
] & ReInstateTried
) == 0)
808 clog
<< " Try to Re-Instate (" << Counter
<< ") " << I
.FullName(false) << endl
;
809 unsigned long OldBreaks
= Cache
.BrokenCount();
810 pkgCache::Version
*OldVer
= Cache
[I
].InstallVer
;
811 Flags
[I
->ID
] &= ReInstateTried
;
813 Cache
.MarkInstall(I
, false, 0, false);
814 if (Cache
[I
].InstBroken() == true ||
815 OldBreaks
< Cache
.BrokenCount())
818 Cache
.MarkDelete(I
, false, 0, false);
820 Cache
.MarkKeep(I
, false, false);
824 clog
<< "Re-Instated " << I
.FullName(false) << " (" << OldBreaks
<< " vs " << Cache
.BrokenCount() << ')' << endl
;
827 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
831 clog
<< "Investigating (" << Counter
<< ") " << APT::PrettyPkg(&Cache
, I
) << endl
;
833 // Isolate the problem dependency
835 pkgCache::DepIterator Start
;
836 pkgCache::DepIterator End
;
841 enum {OrRemove
,OrKeep
} OrOp
= OrRemove
;
842 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList();
843 D
.end() == false || InOr
== true;)
845 // Compute a single dependency element (glob or)
849 if (InOr
== true && OldSize
== KillList
.size())
851 if (OrOp
== OrRemove
)
853 if ((Flags
[I
->ID
] & Protected
) != Protected
)
856 clog
<< " Or group remove for " << I
.FullName(false) << endl
;
857 Cache
.MarkDelete(I
, false, 0, false);
861 else if (OrOp
== OrKeep
)
864 clog
<< " Or group keep for " << I
.FullName(false) << endl
;
865 Cache
.MarkKeep(I
, false, false);
870 /* We do an extra loop (as above) to finalize the or group
875 if (Start
.end() == true)
878 // We only worry about critical deps.
879 if (End
.IsCritical() != true)
883 OldSize
= KillList
.size();
888 // We only worry about critical deps.
889 if (Start
.IsCritical() != true)
894 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
901 clog
<< "Broken " << APT::PrettyDep(&Cache
, Start
) << endl
;
903 /* Look across the version list. If there are no possible
904 targets then we keep the package and bail. This is necessary
905 if a package has a dep on another package that can't be found */
906 std::unique_ptr
<pkgCache::Version
*[]> VList(Start
.AllTargets());
907 if (VList
[0] == 0 && (Flags
[I
->ID
] & Protected
) != Protected
&&
908 Start
.IsNegative() == false &&
909 Cache
[I
].NowBroken() == false)
913 /* No keep choice because the keep being OK could be the
914 result of another element in the OR group! */
919 Cache
.MarkKeep(I
, false, false);
924 for (pkgCache::Version
**V
= VList
.get(); *V
!= 0; V
++)
926 pkgCache::VerIterator
Ver(Cache
,*V
);
927 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
929 /* This is a conflicts, and the version we are looking
930 at is not the currently selected version of the
931 package, which means it is not necessary to
933 if (Cache
[Pkg
].InstallVer
!= Ver
&& Start
.IsNegative() == true)
936 clog
<< " Conflicts//Breaks against version "
937 << Ver
.VerStr() << " for " << Pkg
.Name()
938 << " but that is not InstVer, ignoring"
944 clog
<< " Considering " << Pkg
.FullName(false) << ' ' << Scores
[Pkg
->ID
] <<
945 " as a solution to " << I
.FullName(false) << ' ' << Scores
[I
->ID
] << endl
;
947 /* Try to fix the package under consideration rather than
948 fiddle with the VList package */
949 if (Scores
[I
->ID
] <= Scores
[Pkg
->ID
] ||
950 ((Cache
[Start
] & pkgDepCache::DepNow
) == 0 &&
951 End
.IsNegative() == false))
953 // Try a little harder to fix protected packages..
954 if ((Flags
[I
->ID
] & Protected
) == Protected
)
956 if (DoUpgrade(Pkg
) == true)
958 if (Scores
[Pkg
->ID
] > Scores
[I
->ID
])
959 Scores
[Pkg
->ID
] = Scores
[I
->ID
];
966 /* See if a keep will do, unless the package is protected,
967 then installing it will be necessary */
968 bool Installed
= Cache
[I
].Install();
969 Cache
.MarkKeep(I
, false, false);
970 if (Cache
[I
].InstBroken() == false)
972 // Unwind operation will be keep now
973 if (OrOp
== OrRemove
)
977 if (InOr
== true && Installed
== true)
978 Cache
.MarkInstall(I
, false, 0, false);
981 clog
<< " Holding Back " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
985 if (BrokenFix
== false || DoUpgrade(I
) == false)
987 // Consider other options
988 if (InOr
== false || Cache
[I
].Garbage
== true)
991 clog
<< " Removing " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
992 Cache
.MarkDelete(I
, false, 0, false);
993 if (Counter
> 1 && Scores
[Pkg
->ID
] > Scores
[I
->ID
])
994 Scores
[I
->ID
] = Scores
[Pkg
->ID
];
996 else if (TryFixByInstall
== true &&
997 Start
.TargetPkg()->CurrentVer
== 0 &&
998 Cache
[Start
.TargetPkg()].Delete() == false &&
999 (Flags
[Start
.TargetPkg()->ID
] & ToRemove
) != ToRemove
&&
1000 Cache
.GetCandidateVersion(Start
.TargetPkg()).end() == false)
1002 /* Before removing or keeping the package with the broken dependency
1003 try instead to install the first not previously installed package
1004 solving this dependency. This helps every time a previous solver
1005 is removed by the resolver because of a conflict or alike but it is
1006 dangerous as it could trigger new breaks/conflicts… */
1008 clog
<< " Try Installing " << APT::PrettyPkg(&Cache
, Start
.TargetPkg()) << " before changing " << I
.FullName(false) << std::endl
;
1009 unsigned long const OldBroken
= Cache
.BrokenCount();
1010 Cache
.MarkInstall(Start
.TargetPkg(), true, 1, false);
1011 // FIXME: we should undo the complete MarkInstall process here
1012 if (Cache
[Start
.TargetPkg()].InstBroken() == true || Cache
.BrokenCount() > OldBroken
)
1013 Cache
.MarkDelete(Start
.TargetPkg(), false, 1, false);
1024 if (Start
->Type
== pkgCache::Dep::DpkgBreaks
)
1026 // first, try upgradring the package, if that
1027 // does not help, the breaks goes onto the
1030 // FIXME: use DoUpgrade(Pkg) instead?
1031 if (Cache
[End
] & pkgDepCache::DepGCVer
)
1034 clog
<< " Upgrading " << Pkg
.FullName(false) << " due to Breaks field in " << I
.FullName(false) << endl
;
1035 Cache
.MarkInstall(Pkg
, false, 0, false);
1040 // Skip adding to the kill list if it is protected
1041 if ((Flags
[Pkg
->ID
] & Protected
) != 0)
1045 clog
<< " Added " << Pkg
.FullName(false) << " to the remove list" << endl
;
1047 KillList
.push_back({Pkg
, End
});
1049 if (Start
.IsNegative() == false)
1054 // Hm, nothing can possibly satisify this dep. Nuke it.
1055 if (VList
[0] == 0 &&
1056 Start
.IsNegative() == false &&
1057 (Flags
[I
->ID
] & Protected
) != Protected
)
1059 bool Installed
= Cache
[I
].Install();
1061 if (Cache
[I
].InstBroken() == false)
1063 // Unwind operation will be keep now
1064 if (OrOp
== OrRemove
)
1068 if (InOr
== true && Installed
== true)
1069 Cache
.MarkInstall(I
, false, 0, false);
1072 clog
<< " Holding Back " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1077 clog
<< " Removing " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1079 Cache
.MarkDelete(I
, false, 0, false);
1094 // Apply the kill list now
1095 if (Cache
[I
].InstallVer
!= 0)
1097 for (auto J
= KillList
.begin(); J
!= KillList
.end(); J
++)
1100 if ((Cache
[J
->Dep
] & pkgDepCache::DepGNow
) == 0)
1102 if (J
->Dep
.IsNegative() == true)
1105 clog
<< " Fixing " << I
.FullName(false) << " via remove of " << J
->Pkg
.FullName(false) << endl
;
1106 Cache
.MarkDelete(J
->Pkg
, false, 0, false);
1112 clog
<< " Fixing " << I
.FullName(false) << " via keep of " << J
->Pkg
.FullName(false) << endl
;
1113 Cache
.MarkKeep(J
->Pkg
, false, false);
1118 if (Scores
[I
->ID
] > Scores
[J
->Pkg
->ID
])
1119 Scores
[J
->Pkg
->ID
] = Scores
[I
->ID
];
1127 clog
<< "Done" << endl
;
1129 if (Cache
.BrokenCount() != 0)
1131 // See if this is the result of a hold
1132 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1133 for (;I
.end() != true; ++I
)
1135 if (Cache
[I
].InstBroken() == false)
1137 if ((Flags
[I
->ID
] & Protected
) != Protected
)
1138 return _error
->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
1140 return _error
->Error(_("Unable to correct problems, you have held broken packages."));
1143 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
1144 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1145 for (;I
.end() != true; ++I
) {
1146 if (Cache
[I
].NewInstall() && !(Flags
[I
->ID
] & PreInstalled
)) {
1147 if(_config
->FindI("Debug::pkgAutoRemove",false)) {
1148 std::clog
<< "Resolve installed new pkg: " << I
.FullName(false)
1149 << " (now marking it as auto)" << std::endl
;
1151 Cache
[I
].Flags
|= pkgCache::Flag::Auto
;
1159 // ProblemResolver::BreaksInstOrPolicy - Check if the given pkg is broken/*{{{*/
1160 // ---------------------------------------------------------------------
1161 /* This checks if the given package is broken either by a hard dependency
1162 (InstBroken()) or by introducing a new policy breakage e.g. new
1163 unsatisfied recommends for a package that was in "policy-good" state
1165 Note that this is not perfect as it will ignore further breakage
1166 for already broken policy (recommends)
1168 bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I
)
1170 // a broken install is always a problem
1171 if (Cache
[I
].InstBroken() == true)
1174 std::clog
<< " Dependencies are not satisfied for " << APT::PrettyPkg(&Cache
, I
) << std::endl
;
1178 // a newly broken policy (recommends/suggests) is a problem
1179 if (Cache
[I
].NowPolicyBroken() == false &&
1180 Cache
[I
].InstPolicyBroken() == true)
1183 std::clog
<< " Policy breaks with upgrade of " << APT::PrettyPkg(&Cache
, I
) << std::endl
;
1190 // ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1191 // ---------------------------------------------------------------------
1192 /* This is the work horse of the soft upgrade routine. It is very gental
1193 in that it does not install or remove any packages. It is assumed that the
1194 system was non-broken previously. */
1195 bool pkgProblemResolver::ResolveByKeep(OpProgress
* const Progress
)
1197 std::string
const solver
= _config
->Find("APT::Solver", "internal");
1198 constexpr auto flags
= EDSP::Request::UPGRADE_ALL
| EDSP::Request::FORBID_NEW_INSTALL
| EDSP::Request::FORBID_REMOVE
;
1199 auto const ret
= EDSP::ResolveExternal(solver
.c_str(), Cache
, flags
, Progress
);
1200 if (solver
!= "internal")
1202 return ResolveByKeepInternal();
1205 // ProblemResolver::ResolveByKeepInternal - Resolve problems using keep /*{{{*/
1206 // ---------------------------------------------------------------------
1207 /* This is the work horse of the soft upgrade routine. It is very gental
1208 in that it does not install or remove any packages. It is assumed that the
1209 system was non-broken previously. */
1210 bool pkgProblemResolver::ResolveByKeepInternal()
1212 pkgDepCache::ActionGroup
group(Cache
);
1214 unsigned long Size
= Cache
.Head().PackageCount
;
1218 /* We have to order the packages so that the broken fixing pass
1219 operates from highest score to lowest. This prevents problems when
1220 high score packages cause the removal of lower score packages that
1221 would cause the removal of even lower score packages. */
1222 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
1223 pkgCache::Package
**PEnd
= PList
;
1224 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1227 std::sort(PList
,PEnd
,[this](Package
*a
, Package
*b
) { return ScoreSort(a
, b
) < 0; });
1230 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1232 clog
<< "Show Scores" << endl
;
1233 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1234 if (Scores
[(*K
)->ID
] != 0)
1236 pkgCache::PkgIterator
Pkg(Cache
,*K
);
1237 clog
<< Scores
[(*K
)->ID
] << ' ' << APT::PrettyPkg(&Cache
, Pkg
) << std::endl
;
1242 clog
<< "Entering ResolveByKeep" << endl
;
1244 // Consider each broken package
1245 pkgCache::Package
**LastStop
= 0;
1246 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1248 pkgCache::PkgIterator
I(Cache
,*K
);
1250 if (Cache
[I
].InstallVer
== 0)
1253 if (InstOrNewPolicyBroken(I
) == false)
1256 /* Keep the package. If this works then great, otherwise we have
1257 to be significantly more aggressive and manipulate its dependencies */
1258 if ((Flags
[I
->ID
] & Protected
) == 0)
1261 clog
<< "Keeping package " << I
.FullName(false) << endl
;
1262 Cache
.MarkKeep(I
, false, false);
1263 if (InstOrNewPolicyBroken(I
) == false)
1270 // Isolate the problem dependencies
1271 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
1275 D
.GlobOr(Start
,End
);
1277 // We only worry about critical deps.
1278 if (End
.IsCritical() != true)
1282 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
1285 /* Hm, the group is broken.. I suppose the best thing to do is to
1286 is to try every combination of keep/not-keep for the set, but thats
1287 slow, and this never happens, just be conservative and assume the
1288 list of ors is in preference and keep till it starts to work. */
1292 clog
<< "Package " << I
.FullName(false) << " " << APT::PrettyDep(&Cache
, Start
) << endl
;
1294 // Look at all the possible provides on this package
1295 std::unique_ptr
<pkgCache::Version
*[]> VList(Start
.AllTargets());
1296 for (pkgCache::Version
**V
= VList
.get(); *V
!= 0; V
++)
1298 pkgCache::VerIterator
Ver(Cache
,*V
);
1299 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
1301 // It is not keepable
1302 if (Cache
[Pkg
].InstallVer
== 0 ||
1303 Pkg
->CurrentVer
== 0)
1306 if ((Flags
[I
->ID
] & Protected
) == 0)
1309 clog
<< " Keeping Package " << Pkg
.FullName(false) << " due to " << Start
.DepType() << endl
;
1310 Cache
.MarkKeep(Pkg
, false, false);
1313 if (InstOrNewPolicyBroken(I
) == false)
1317 if (InstOrNewPolicyBroken(I
) == false)
1325 if (InstOrNewPolicyBroken(I
) == false)
1329 if (InstOrNewPolicyBroken(I
) == true)
1333 if (K
== LastStop
) {
1334 // I is an iterator based off our temporary package list,
1335 // so copy the name we need before deleting the temporary list
1336 std::string
const LoopingPackage
= I
.FullName(false);
1338 return _error
->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.", LoopingPackage
.c_str());
1348 // ProblemResolver::InstallProtect - deprecated cpu-eating no-op /*{{{*/
1349 // ---------------------------------------------------------------------
1350 /* Actions issued with FromUser bit set are protected from further
1351 modification (expect by other calls with FromUser set) nowadays , so we
1352 don't need to reissue actions here, they are already set in stone. */
1353 void pkgProblemResolver::InstallProtect()
1355 pkgDepCache::ActionGroup
group(Cache
);
1357 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1359 if ((Flags
[I
->ID
] & Protected
) == Protected
)
1361 if ((Flags
[I
->ID
] & ToRemove
) == ToRemove
)
1362 Cache
.MarkDelete(I
);
1365 // preserve the information whether the package was auto
1366 // or manually installed
1367 bool autoInst
= (Cache
[I
].Flags
& pkgCache::Flag::Auto
);
1368 Cache
.MarkInstall(I
, false, 0, !autoInst
);
1374 // PrioSortList - Sort a list of versions by priority /*{{{*/
1375 // ---------------------------------------------------------------------
1376 /* This is ment to be used in conjunction with AllTargets to get a list
1377 of versions ordered by preference. */
1380 pkgCache
&PrioCache
;
1382 explicit PrioComp(pkgCache
&PrioCache
) : PrioCache(PrioCache
) {
1385 bool operator() (pkgCache::Version
* const &A
, pkgCache::Version
* const &B
) {
1386 return compare(A
, B
) < 0;
1389 int compare(pkgCache::Version
* const &A
, pkgCache::Version
* const &B
) {
1390 pkgCache::VerIterator
L(PrioCache
,A
);
1391 pkgCache::VerIterator
R(PrioCache
,B
);
1393 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
&&
1394 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
)
1396 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
1397 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
1400 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
&&
1401 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
1403 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
&&
1404 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
1407 if (L
->Priority
!= R
->Priority
)
1408 return R
->Priority
- L
->Priority
;
1409 return strcmp(L
.ParentPkg().Name(),R
.ParentPkg().Name());
1413 void pkgPrioSortList(pkgCache
&Cache
,pkgCache::Version
**List
)
1415 unsigned long Count
= 0;
1416 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
1418 std::sort(List
,List
+Count
,PrioComp(Cache
));