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>
37 // Simulate::Simulate - Constructor /*{{{*/
38 // ---------------------------------------------------------------------
39 /* The legacy translations here of input Pkg iterators is obsolete,
40 this is not necessary since the pkgCaches are fully shared now. */
41 pkgSimulate::pkgSimulate(pkgDepCache
*Cache
) : pkgPackageManager(Cache
),
42 d(NULL
), iPolicy(Cache
),
43 Sim(&Cache
->GetCache(),&iPolicy
),
47 Flags
= new unsigned char[Cache
->Head().PackageCount
];
48 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
50 // Fake a filename so as not to activate the media swapping
51 string Jnk
= "SIMULATE";
52 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
56 // Simulate::~Simulate - Destructor /*{{{*/
57 pkgSimulate::~pkgSimulate()
62 // Simulate::Describe - Describe a package /*{{{*/
63 // ---------------------------------------------------------------------
64 /* Parameter Current == true displays the current package version,
65 Parameter Candidate == true displays the candidate package version */
66 void pkgSimulate::Describe(PkgIterator Pkg
,ostream
&out
,bool Current
,bool Candidate
)
70 out
<< Pkg
.FullName(true);
74 Ver
= Pkg
.CurrentVer();
75 if (Ver
.end() == false)
76 out
<< " [" << Ver
.VerStr() << ']';
79 if (Candidate
== true)
81 Ver
= Sim
[Pkg
].CandidateVerIter(Sim
);
82 if (Ver
.end() == true)
85 out
<< " (" << Ver
.VerStr() << ' ' << Ver
.RelStr() << ')';
89 // Simulate::Install - Simulate unpacking of a package /*{{{*/
90 // ---------------------------------------------------------------------
92 bool pkgSimulate::Install(PkgIterator iPkg
,string
/*File*/)
95 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
99 Describe(Pkg
,cout
,true,true);
100 Sim
.MarkInstall(Pkg
,false);
102 // Look for broken conflicts+predepends.
103 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; ++I
)
105 if (Sim
[I
].InstallVer
== 0)
108 for (DepIterator D
= Sim
[I
].InstVerIter(Sim
).DependsList(); D
.end() == false;)
113 if (Start
.IsNegative() == true ||
114 End
->Type
== pkgCache::Dep::PreDepends
)
116 if ((Sim
[End
] & pkgDepCache::DepGInstall
) == 0)
118 cout
<< " [" << I
.FullName(false) << " on " << Start
.TargetPkg().FullName(false) << ']';
119 if (Start
->Type
== pkgCache::Dep::Conflicts
)
120 _error
->Error("Fatal, conflicts violated %s",I
.FullName(false).c_str());
126 if (Sim
.BrokenCount() != 0)
133 // Simulate::Configure - Simulate configuration of a Package /*{{{*/
134 // ---------------------------------------------------------------------
135 /* This is not an acurate simulation of relatity, we should really not
136 install the package.. For some investigations it may be necessary
138 bool pkgSimulate::Configure(PkgIterator iPkg
)
140 // Adapt the iterator
141 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
145 if (Sim
[Pkg
].InstBroken() == true)
147 cout
<< "Conf " << Pkg
.FullName(false) << " broken" << endl
;
151 // Print out each package and the failed dependencies
152 for (pkgCache::DepIterator D
= Sim
[Pkg
].InstVerIter(Sim
).DependsList(); D
.end() == false; ++D
)
154 if (Sim
.IsImportantDep(D
) == false ||
155 (Sim
[D
] & pkgDepCache::DepInstall
) != 0)
158 if (D
->Type
== pkgCache::Dep::Obsoletes
)
159 cout
<< " Obsoletes:" << D
.TargetPkg().FullName(false);
160 else if (D
->Type
== pkgCache::Dep::Conflicts
)
161 cout
<< " Conflicts:" << D
.TargetPkg().FullName(false);
162 else if (D
->Type
== pkgCache::Dep::DpkgBreaks
)
163 cout
<< " Breaks:" << D
.TargetPkg().FullName(false);
165 cout
<< " Depends:" << D
.TargetPkg().FullName(false);
169 _error
->Error("Conf Broken %s",Pkg
.FullName(false).c_str());
174 Describe(Pkg
,cout
,false,true);
177 if (Sim
.BrokenCount() != 0)
185 // Simulate::Remove - Simulate the removal of a package /*{{{*/
186 // ---------------------------------------------------------------------
188 bool pkgSimulate::Remove(PkgIterator iPkg
,bool Purge
)
190 // Adapt the iterator
191 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
192 if (Pkg
.end() == true)
194 std::cerr
<< (Purge
? "Purg" : "Remv") << " invalid package " << iPkg
.FullName() << std::endl
;
205 Describe(Pkg
,cout
,true,false);
207 if (Sim
.BrokenCount() != 0)
215 // Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
216 // ---------------------------------------------------------------------
218 void pkgSimulate::ShortBreaks()
221 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; ++I
)
223 if (Sim
[I
].InstBroken() == true)
225 if (Flags
[I
->ID
] == 0)
226 cout
<< I
.FullName(false) << ' ';
228 cout << I.Name() << "! ";*/
234 // ApplyStatus - Adjust for non-ok packages /*{{{*/
235 // ---------------------------------------------------------------------
236 /* We attempt to change the state of the all packages that have failed
237 installation toward their real state. The ordering code will perform
238 the necessary calculations to deal with the problems. */
239 bool pkgApplyStatus(pkgDepCache
&Cache
)
241 pkgDepCache::ActionGroup
group(Cache
);
243 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
245 if (I
->VersionList
== 0)
248 // Only choice for a ReInstReq package is to reinstall
249 if (I
->InstState
== pkgCache::State::ReInstReq
||
250 I
->InstState
== pkgCache::State::HoldReInstReq
)
252 if (I
->CurrentVer
!= 0 && I
.CurrentVer().Downloadable() == true)
253 Cache
.MarkKeep(I
, false, false);
256 // Is this right? Will dpkg choke on an upgrade?
257 if (Cache
[I
].CandidateVer
!= 0 &&
258 Cache
[I
].CandidateVerIter(Cache
).Downloadable() == true)
259 Cache
.MarkInstall(I
, false, 0, false);
261 return _error
->Error(_("The package %s needs to be reinstalled, "
262 "but I can't find an archive for it."),I
.FullName(true).c_str());
268 switch (I
->CurrentState
)
270 /* This means installation failed somehow - it does not need to be
271 re-unpacked (probably) */
272 case pkgCache::State::UnPacked
:
273 case pkgCache::State::HalfConfigured
:
274 case pkgCache::State::TriggersAwaited
:
275 case pkgCache::State::TriggersPending
:
276 if ((I
->CurrentVer
!= 0 && I
.CurrentVer().Downloadable() == true) ||
277 I
.State() != pkgCache::PkgIterator::NeedsUnpack
)
278 Cache
.MarkKeep(I
, false, false);
281 if (Cache
[I
].CandidateVer
!= 0 &&
282 Cache
[I
].CandidateVerIter(Cache
).Downloadable() == true)
283 Cache
.MarkInstall(I
, true, 0, false);
285 Cache
.MarkDelete(I
, false, 0, false);
289 // This means removal failed
290 case pkgCache::State::HalfInstalled
:
291 Cache
.MarkDelete(I
, false, 0, false);
295 if (I
->InstState
!= pkgCache::State::Ok
)
296 return _error
->Error("The package %s is not ok and I "
297 "don't know how to fix it!",I
.FullName(false).c_str());
303 // FixBroken - Fix broken packages /*{{{*/
304 // ---------------------------------------------------------------------
305 /* This autoinstalls every broken package and then runs the problem resolver
307 bool pkgFixBroken(pkgDepCache
&Cache
)
309 pkgDepCache::ActionGroup
group(Cache
);
311 // Auto upgrade all broken packages
312 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
313 if (Cache
[I
].NowBroken() == true)
314 Cache
.MarkInstall(I
, true, 0, false);
316 /* Fix packages that are in a NeedArchive state but don't have a
317 downloadable install version */
318 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
320 if (I
.State() != pkgCache::PkgIterator::NeedsUnpack
||
321 Cache
[I
].Delete() == true)
324 if (Cache
[I
].InstVerIter(Cache
).Downloadable() == false)
327 Cache
.MarkInstall(I
, true, 0, false);
330 pkgProblemResolver
Fix(&Cache
);
331 return Fix
.Resolve(true);
334 // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
335 // ---------------------------------------------------------------------
337 pkgProblemResolver::pkgProblemResolver(pkgDepCache
*pCache
) : d(NULL
), Cache(*pCache
)
340 unsigned long Size
= Cache
.Head().PackageCount
;
341 Scores
= new int[Size
];
342 Flags
= new unsigned char[Size
];
343 memset(Flags
,0,sizeof(*Flags
)*Size
);
345 // Set debug to true to see its decision logic
346 Debug
= _config
->FindB("Debug::pkgProblemResolver",false);
349 // ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
350 // ---------------------------------------------------------------------
352 pkgProblemResolver::~pkgProblemResolver()
358 // ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
359 // ---------------------------------------------------------------------
361 int pkgProblemResolver::ScoreSort(Package
const *A
,Package
const *B
)
363 if (Scores
[A
->ID
] > Scores
[B
->ID
])
365 if (Scores
[A
->ID
] < Scores
[B
->ID
])
370 // ProblemResolver::MakeScores - Make the score table /*{{{*/
371 // ---------------------------------------------------------------------
373 void pkgProblemResolver::MakeScores()
375 unsigned long Size
= Cache
.Head().PackageCount
;
376 memset(Scores
,0,sizeof(*Scores
)*Size
);
378 // maps to pkgCache::State::VerPriority:
379 // Required Important Standard Optional Extra
382 _config
->FindI("pkgProblemResolver::Scores::Required",3),
383 _config
->FindI("pkgProblemResolver::Scores::Important",2),
384 _config
->FindI("pkgProblemResolver::Scores::Standard",1),
385 _config
->FindI("pkgProblemResolver::Scores::Optional",-1),
386 _config
->FindI("pkgProblemResolver::Scores::Extra",-2)
388 int PrioEssentials
= _config
->FindI("pkgProblemResolver::Scores::Essentials",100);
389 int PrioInstalledAndNotObsolete
= _config
->FindI("pkgProblemResolver::Scores::NotObsolete",1);
392 _config
->FindI("pkgProblemResolver::Scores::Depends",1),
393 _config
->FindI("pkgProblemResolver::Scores::PreDepends",1),
394 _config
->FindI("pkgProblemResolver::Scores::Suggests",0),
395 _config
->FindI("pkgProblemResolver::Scores::Recommends",1),
396 _config
->FindI("pkgProblemResolver::Scores::Conflicts",-1),
397 _config
->FindI("pkgProblemResolver::Scores::Replaces",0),
398 _config
->FindI("pkgProblemResolver::Scores::Obsoletes",0),
399 _config
->FindI("pkgProblemResolver::Scores::Breaks",-1),
400 _config
->FindI("pkgProblemResolver::Scores::Enhances",0)
402 int AddProtected
= _config
->FindI("pkgProblemResolver::Scores::AddProtected",10000);
403 int AddEssential
= _config
->FindI("pkgProblemResolver::Scores::AddEssential",5000);
405 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
406 clog
<< "Settings used to calculate pkgProblemResolver::Scores::" << endl
407 << " Required => " << PrioMap
[pkgCache::State::Required
] << endl
408 << " Important => " << PrioMap
[pkgCache::State::Important
] << endl
409 << " Standard => " << PrioMap
[pkgCache::State::Standard
] << endl
410 << " Optional => " << PrioMap
[pkgCache::State::Optional
] << endl
411 << " Extra => " << PrioMap
[pkgCache::State::Extra
] << endl
412 << " Essentials => " << PrioEssentials
<< endl
413 << " InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete
<< endl
414 << " Pre-Depends => " << DepMap
[pkgCache::Dep::PreDepends
] << endl
415 << " Depends => " << DepMap
[pkgCache::Dep::Depends
] << endl
416 << " Recommends => " << DepMap
[pkgCache::Dep::Recommends
] << endl
417 << " Suggests => " << DepMap
[pkgCache::Dep::Suggests
] << endl
418 << " Conflicts => " << DepMap
[pkgCache::Dep::Conflicts
] << endl
419 << " Breaks => " << DepMap
[pkgCache::Dep::DpkgBreaks
] << endl
420 << " Replaces => " << DepMap
[pkgCache::Dep::Replaces
] << endl
421 << " Obsoletes => " << DepMap
[pkgCache::Dep::Obsoletes
] << endl
422 << " Enhances => " << DepMap
[pkgCache::Dep::Enhances
] << endl
423 << " AddProtected => " << AddProtected
<< endl
424 << " AddEssential => " << AddEssential
<< endl
;
426 // Generate the base scores for a package based on its properties
427 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
429 if (Cache
[I
].InstallVer
== 0)
432 int &Score
= Scores
[I
->ID
];
434 /* This is arbitrary, it should be high enough to elevate an
435 essantial package above most other packages but low enough
436 to allow an obsolete essential packages to be removed by
437 a conflicts on a powerful normal package (ie libc6) */
438 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
439 || (I
->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
440 Score
+= PrioEssentials
;
442 pkgCache::VerIterator
const InstVer
= Cache
[I
].InstVerIter(Cache
);
443 // We apply priorities only to downloadable packages, all others are prio:extra
444 // as an obsolete prio:standard package can't be that standard anymore…
445 if (InstVer
->Priority
<= pkgCache::State::Extra
&& InstVer
.Downloadable() == true)
446 Score
+= PrioMap
[InstVer
->Priority
];
448 Score
+= PrioMap
[pkgCache::State::Extra
];
450 /* This helps to fix oddball problems with conflicting packages
451 on the same level. We enhance the score of installed packages
452 if those are not obsolete */
453 if (I
->CurrentVer
!= 0 && Cache
[I
].CandidateVer
!= 0 && Cache
[I
].CandidateVerIter(Cache
).Downloadable())
454 Score
+= PrioInstalledAndNotObsolete
;
456 // propagate score points along dependencies
457 for (pkgCache::DepIterator D
= InstVer
.DependsList(); D
.end() == false; ++D
)
459 if (DepMap
[D
->Type
] == 0)
461 pkgCache::PkgIterator
const T
= D
.TargetPkg();
464 pkgCache::VerIterator
const IV
= Cache
[T
].InstVerIter(Cache
);
465 if (IV
.end() == true || D
.IsSatisfied(IV
) == false)
468 Scores
[T
->ID
] += DepMap
[D
->Type
];
472 // Copy the scores to advoid additive looping
473 std::unique_ptr
<int[]> OldScores(new int[Size
]);
474 memcpy(OldScores
.get(),Scores
,sizeof(*Scores
)*Size
);
476 /* Now we cause 1 level of dependency inheritance, that is we add the
477 score of the packages that depend on the target Package. This
478 fortifies high scoring packages */
479 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
481 if (Cache
[I
].InstallVer
== 0)
484 for (pkgCache::DepIterator D
= I
.RevDependsList(); D
.end() == false; ++D
)
486 // Only do it for the install version
487 if ((pkgCache::Version
*)D
.ParentVer() != Cache
[D
.ParentPkg()].InstallVer
||
488 (D
->Type
!= pkgCache::Dep::Depends
&&
489 D
->Type
!= pkgCache::Dep::PreDepends
&&
490 D
->Type
!= pkgCache::Dep::Recommends
))
493 // Do not propagate negative scores otherwise
494 // an extra (-2) package might score better than an optional (-1)
495 if (OldScores
[D
.ParentPkg()->ID
] > 0)
496 Scores
[I
->ID
] += OldScores
[D
.ParentPkg()->ID
];
500 /* Now we propagate along provides. This makes the packages that
501 provide important packages extremely important */
502 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
504 for (pkgCache::PrvIterator P
= I
.ProvidesList(); P
.end() == false; ++P
)
506 // Only do it once per package
507 if ((pkgCache::Version
*)P
.OwnerVer() != Cache
[P
.OwnerPkg()].InstallVer
)
509 Scores
[P
.OwnerPkg()->ID
] += abs(Scores
[I
->ID
] - OldScores
[I
->ID
]);
513 /* Protected things are pushed really high up. This number should put them
514 ahead of everything */
515 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
517 if ((Flags
[I
->ID
] & Protected
) != 0)
518 Scores
[I
->ID
] += AddProtected
;
519 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
||
520 (I
->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
521 Scores
[I
->ID
] += AddEssential
;
525 // ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
526 // ---------------------------------------------------------------------
527 /* This goes through and tries to reinstall packages to make this package
529 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg
)
531 pkgDepCache::ActionGroup
group(Cache
);
533 if ((Flags
[Pkg
->ID
] & Upgradable
) == 0 || Cache
[Pkg
].Upgradable() == false)
535 if ((Flags
[Pkg
->ID
] & Protected
) == Protected
)
538 Flags
[Pkg
->ID
] &= ~Upgradable
;
540 bool WasKept
= Cache
[Pkg
].Keep();
541 Cache
.MarkInstall(Pkg
, false, 0, false);
543 // This must be a virtual package or something like that.
544 if (Cache
[Pkg
].InstVerIter(Cache
).end() == true)
547 // Isolate the problem dependency
549 for (pkgCache::DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
551 // Compute a single dependency element (glob or)
552 pkgCache::DepIterator Start
= D
;
553 pkgCache::DepIterator End
= D
;
554 for (bool LastOR
= true; D
.end() == false && LastOR
== true;)
556 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
562 // We only worry about critical deps.
563 if (End
.IsCritical() != true)
566 // Iterate over all the members in the or group
570 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
573 // Do not change protected packages
574 PkgIterator P
= Start
.SmartTargetPkg();
575 if ((Flags
[P
->ID
] & Protected
) == Protected
)
578 clog
<< " Reinst Failed because of protected " << P
.FullName(false) << endl
;
583 // Upgrade the package if the candidate version will fix the problem.
584 if ((Cache
[Start
] & pkgDepCache::DepCVer
) == pkgDepCache::DepCVer
)
586 if (DoUpgrade(P
) == false)
589 clog
<< " Reinst Failed because of " << P
.FullName(false) << endl
;
600 /* We let the algorithm deal with conflicts on its next iteration,
601 it is much smarter than us */
602 if (Start
.IsNegative() == true)
606 clog
<< " Reinst Failed early because of " << Start
.TargetPkg().FullName(false) << endl
;
619 // Undo our operations - it might be smart to undo everything this did..
623 Cache
.MarkKeep(Pkg
, false, false);
625 Cache
.MarkDelete(Pkg
, false, 0, false);
630 clog
<< " Re-Instated " << Pkg
.FullName(false) << endl
;
634 // ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/
635 bool pkgProblemResolver::Resolve(bool BrokenFix
, OpProgress
* const Progress
)
637 std::string
const solver
= _config
->Find("APT::Solver", "internal");
638 if (solver
!= "internal")
639 return EDSP::ResolveExternal(solver
.c_str(), Cache
, false, false, false, Progress
);
640 return ResolveInternal(BrokenFix
);
643 // ProblemResolver::ResolveInternal - Run the resolution pass /*{{{*/
644 // ---------------------------------------------------------------------
645 /* This routines works by calculating a score for each package. The score
646 is derived by considering the package's priority and all reverse
647 dependents giving an integer that reflects the amount of breakage that
648 adjusting the package will inflict.
650 It goes from highest score to lowest and corrects all of the breaks by
651 keeping or removing the dependent packages. If that fails then it removes
652 the package itself and goes on. The routine should be able to intelligently
653 go from any broken state to a fixed state.
655 The BrokenFix flag enables a mode where the algorithm tries to
656 upgrade packages to advoid problems. */
657 bool pkgProblemResolver::ResolveInternal(bool const BrokenFix
)
659 pkgDepCache::ActionGroup
group(Cache
);
661 // Record which packages are marked for install
666 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
668 if (Cache
[I
].Install() == true)
669 Flags
[I
->ID
] |= PreInstalled
;
672 if (Cache
[I
].InstBroken() == true && BrokenFix
== true)
674 Cache
.MarkInstall(I
, false, 0, false);
675 if (Cache
[I
].Install() == true)
679 Flags
[I
->ID
] &= ~PreInstalled
;
681 Flags
[I
->ID
] |= Upgradable
;
684 while (Again
== true);
687 clog
<< "Starting pkgProblemResolver with broken count: "
688 << Cache
.BrokenCount() << endl
;
693 unsigned long const Size
= Cache
.Head().PackageCount
;
695 /* We have to order the packages so that the broken fixing pass
696 operates from highest score to lowest. This prevents problems when
697 high score packages cause the removal of lower score packages that
698 would cause the removal of even lower score packages. */
699 std::unique_ptr
<pkgCache::Package
*[]> PList(new pkgCache::Package
*[Size
]);
700 pkgCache::Package
**PEnd
= PList
.get();
701 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
704 std::sort(PList
.get(), PEnd
, [this](Package
*a
, Package
*b
) { return ScoreSort(a
, b
) < 0; });
706 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
708 clog
<< "Show Scores" << endl
;
709 for (pkgCache::Package
**K
= PList
.get(); K
!= PEnd
; K
++)
710 if (Scores
[(*K
)->ID
] != 0)
712 pkgCache::PkgIterator
Pkg(Cache
,*K
);
713 clog
<< Scores
[(*K
)->ID
] << ' ' << Pkg
<< std::endl
;
718 clog
<< "Starting 2 pkgProblemResolver with broken count: "
719 << Cache
.BrokenCount() << endl
;
722 /* Now consider all broken packages. For each broken package we either
723 remove the package or fix it's problem. We do this once, it should
724 not be possible for a loop to form (that is a < b < c and fixing b by
725 changing a breaks c) */
727 bool const TryFixByInstall
= _config
->FindB("pkgProblemResolver::FixByInstall", true);
728 std::vector
<PackageKill
> KillList
;
729 for (int Counter
= 0; Counter
!= 10 && Change
== true; Counter
++)
732 for (pkgCache::Package
**K
= PList
.get(); K
!= PEnd
; K
++)
734 pkgCache::PkgIterator
I(Cache
,*K
);
736 /* We attempt to install this and see if any breaks result,
737 this takes care of some strange cases */
738 if (Cache
[I
].CandidateVer
!= Cache
[I
].InstallVer
&&
739 I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0 &&
740 (Flags
[I
->ID
] & PreInstalled
) != 0 &&
741 (Flags
[I
->ID
] & Protected
) == 0 &&
742 (Flags
[I
->ID
] & ReInstateTried
) == 0)
745 clog
<< " Try to Re-Instate (" << Counter
<< ") " << I
.FullName(false) << endl
;
746 unsigned long OldBreaks
= Cache
.BrokenCount();
747 pkgCache::Version
*OldVer
= Cache
[I
].InstallVer
;
748 Flags
[I
->ID
] &= ReInstateTried
;
750 Cache
.MarkInstall(I
, false, 0, false);
751 if (Cache
[I
].InstBroken() == true ||
752 OldBreaks
< Cache
.BrokenCount())
755 Cache
.MarkDelete(I
, false, 0, false);
757 Cache
.MarkKeep(I
, false, false);
761 clog
<< "Re-Instated " << I
.FullName(false) << " (" << OldBreaks
<< " vs " << Cache
.BrokenCount() << ')' << endl
;
764 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
768 clog
<< "Investigating (" << Counter
<< ") " << I
<< endl
;
770 // Isolate the problem dependency
772 pkgCache::DepIterator Start
;
773 pkgCache::DepIterator End
;
778 enum {OrRemove
,OrKeep
} OrOp
= OrRemove
;
779 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList();
780 D
.end() == false || InOr
== true;)
782 // Compute a single dependency element (glob or)
786 if (InOr
== true && OldSize
== KillList
.size())
788 if (OrOp
== OrRemove
)
790 if ((Flags
[I
->ID
] & Protected
) != Protected
)
793 clog
<< " Or group remove for " << I
.FullName(false) << endl
;
794 Cache
.MarkDelete(I
, false, 0, false);
798 else if (OrOp
== OrKeep
)
801 clog
<< " Or group keep for " << I
.FullName(false) << endl
;
802 Cache
.MarkKeep(I
, false, false);
807 /* We do an extra loop (as above) to finalize the or group
812 if (Start
.end() == true)
815 // We only worry about critical deps.
816 if (End
.IsCritical() != true)
820 OldSize
= KillList
.size();
825 // We only worry about critical deps.
826 if (Start
.IsCritical() != true)
831 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
838 clog
<< "Broken " << Start
<< endl
;
840 /* Look across the version list. If there are no possible
841 targets then we keep the package and bail. This is necessary
842 if a package has a dep on another package that can't be found */
843 std::unique_ptr
<pkgCache::Version
*[]> VList(Start
.AllTargets());
844 if (VList
[0] == 0 && (Flags
[I
->ID
] & Protected
) != Protected
&&
845 Start
.IsNegative() == false &&
846 Cache
[I
].NowBroken() == false)
850 /* No keep choice because the keep being OK could be the
851 result of another element in the OR group! */
856 Cache
.MarkKeep(I
, false, false);
861 for (pkgCache::Version
**V
= VList
.get(); *V
!= 0; V
++)
863 pkgCache::VerIterator
Ver(Cache
,*V
);
864 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
866 /* This is a conflicts, and the version we are looking
867 at is not the currently selected version of the
868 package, which means it is not necessary to
870 if (Cache
[Pkg
].InstallVer
!= Ver
&& Start
.IsNegative() == true)
873 clog
<< " Conflicts//Breaks against version "
874 << Ver
.VerStr() << " for " << Pkg
.Name()
875 << " but that is not InstVer, ignoring"
881 clog
<< " Considering " << Pkg
.FullName(false) << ' ' << Scores
[Pkg
->ID
] <<
882 " as a solution to " << I
.FullName(false) << ' ' << Scores
[I
->ID
] << endl
;
884 /* Try to fix the package under consideration rather than
885 fiddle with the VList package */
886 if (Scores
[I
->ID
] <= Scores
[Pkg
->ID
] ||
887 ((Cache
[Start
] & pkgDepCache::DepNow
) == 0 &&
888 End
.IsNegative() == false))
890 // Try a little harder to fix protected packages..
891 if ((Flags
[I
->ID
] & Protected
) == Protected
)
893 if (DoUpgrade(Pkg
) == true)
895 if (Scores
[Pkg
->ID
] > Scores
[I
->ID
])
896 Scores
[Pkg
->ID
] = Scores
[I
->ID
];
903 /* See if a keep will do, unless the package is protected,
904 then installing it will be necessary */
905 bool Installed
= Cache
[I
].Install();
906 Cache
.MarkKeep(I
, false, false);
907 if (Cache
[I
].InstBroken() == false)
909 // Unwind operation will be keep now
910 if (OrOp
== OrRemove
)
914 if (InOr
== true && Installed
== true)
915 Cache
.MarkInstall(I
, false, 0, false);
918 clog
<< " Holding Back " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
922 if (BrokenFix
== false || DoUpgrade(I
) == false)
924 // Consider other options
925 if (InOr
== false || Cache
[I
].Garbage
== true)
928 clog
<< " Removing " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
929 Cache
.MarkDelete(I
, false, 0, false);
930 if (Counter
> 1 && Scores
[Pkg
->ID
] > Scores
[I
->ID
])
931 Scores
[I
->ID
] = Scores
[Pkg
->ID
];
933 else if (TryFixByInstall
== true &&
934 Start
.TargetPkg()->CurrentVer
== 0 &&
935 Cache
[Start
.TargetPkg()].Delete() == false &&
936 (Flags
[Start
.TargetPkg()->ID
] & ToRemove
) != ToRemove
&&
937 Cache
.GetCandidateVersion(Start
.TargetPkg()).end() == false)
939 /* Before removing or keeping the package with the broken dependency
940 try instead to install the first not previously installed package
941 solving this dependency. This helps every time a previous solver
942 is removed by the resolver because of a conflict or alike but it is
943 dangerous as it could trigger new breaks/conflicts… */
945 clog
<< " Try Installing " << Start
.TargetPkg() << " before changing " << I
.FullName(false) << std::endl
;
946 unsigned long const OldBroken
= Cache
.BrokenCount();
947 Cache
.MarkInstall(Start
.TargetPkg(), true, 1, false);
948 // FIXME: we should undo the complete MarkInstall process here
949 if (Cache
[Start
.TargetPkg()].InstBroken() == true || Cache
.BrokenCount() > OldBroken
)
950 Cache
.MarkDelete(Start
.TargetPkg(), false, 1, false);
961 if (Start
->Type
== pkgCache::Dep::DpkgBreaks
)
963 // first, try upgradring the package, if that
964 // does not help, the breaks goes onto the
967 // FIXME: use DoUpgrade(Pkg) instead?
968 if (Cache
[End
] & pkgDepCache::DepGCVer
)
971 clog
<< " Upgrading " << Pkg
.FullName(false) << " due to Breaks field in " << I
.FullName(false) << endl
;
972 Cache
.MarkInstall(Pkg
, false, 0, false);
977 // Skip adding to the kill list if it is protected
978 if ((Flags
[Pkg
->ID
] & Protected
) != 0)
982 clog
<< " Added " << Pkg
.FullName(false) << " to the remove list" << endl
;
984 KillList
.push_back({Pkg
, End
});
986 if (Start
.IsNegative() == false)
991 // Hm, nothing can possibly satisify this dep. Nuke it.
993 Start
.IsNegative() == false &&
994 (Flags
[I
->ID
] & Protected
) != Protected
)
996 bool Installed
= Cache
[I
].Install();
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) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1014 clog
<< " Removing " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1016 Cache
.MarkDelete(I
, false, 0, false);
1031 // Apply the kill list now
1032 if (Cache
[I
].InstallVer
!= 0)
1034 for (auto J
= KillList
.begin(); J
!= KillList
.end(); J
++)
1037 if ((Cache
[J
->Dep
] & pkgDepCache::DepGNow
) == 0)
1039 if (J
->Dep
.IsNegative() == true)
1042 clog
<< " Fixing " << I
.FullName(false) << " via remove of " << J
->Pkg
.FullName(false) << endl
;
1043 Cache
.MarkDelete(J
->Pkg
, false, 0, false);
1049 clog
<< " Fixing " << I
.FullName(false) << " via keep of " << J
->Pkg
.FullName(false) << endl
;
1050 Cache
.MarkKeep(J
->Pkg
, false, false);
1055 if (Scores
[I
->ID
] > Scores
[J
->Pkg
->ID
])
1056 Scores
[J
->Pkg
->ID
] = Scores
[I
->ID
];
1064 clog
<< "Done" << endl
;
1066 if (Cache
.BrokenCount() != 0)
1068 // See if this is the result of a hold
1069 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1070 for (;I
.end() != true; ++I
)
1072 if (Cache
[I
].InstBroken() == false)
1074 if ((Flags
[I
->ID
] & Protected
) != Protected
)
1075 return _error
->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
1077 return _error
->Error(_("Unable to correct problems, you have held broken packages."));
1080 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
1081 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1082 for (;I
.end() != true; ++I
) {
1083 if (Cache
[I
].NewInstall() && !(Flags
[I
->ID
] & PreInstalled
)) {
1084 if(_config
->FindI("Debug::pkgAutoRemove",false)) {
1085 std::clog
<< "Resolve installed new pkg: " << I
.FullName(false)
1086 << " (now marking it as auto)" << std::endl
;
1088 Cache
[I
].Flags
|= pkgCache::Flag::Auto
;
1096 // ProblemResolver::BreaksInstOrPolicy - Check if the given pkg is broken/*{{{*/
1097 // ---------------------------------------------------------------------
1098 /* This checks if the given package is broken either by a hard dependency
1099 (InstBroken()) or by introducing a new policy breakage e.g. new
1100 unsatisfied recommends for a package that was in "policy-good" state
1102 Note that this is not perfect as it will ignore further breakage
1103 for already broken policy (recommends)
1105 bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I
)
1107 // a broken install is always a problem
1108 if (Cache
[I
].InstBroken() == true)
1111 std::clog
<< " Dependencies are not satisfied for " << I
<< std::endl
;
1115 // a newly broken policy (recommends/suggests) is a problem
1116 if (Cache
[I
].NowPolicyBroken() == false &&
1117 Cache
[I
].InstPolicyBroken() == true)
1120 std::clog
<< " Policy breaks with upgrade of " << I
<< std::endl
;
1127 // ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1128 // ---------------------------------------------------------------------
1129 /* This is the work horse of the soft upgrade routine. It is very gental
1130 in that it does not install or remove any packages. It is assumed that the
1131 system was non-broken previously. */
1132 bool pkgProblemResolver::ResolveByKeep(OpProgress
* const Progress
)
1134 std::string
const solver
= _config
->Find("APT::Solver", "internal");
1135 if (solver
!= "internal")
1136 return EDSP::ResolveExternal(solver
.c_str(), Cache
, true, false, false, Progress
);
1137 return ResolveByKeepInternal();
1140 // ProblemResolver::ResolveByKeepInternal - Resolve problems using keep /*{{{*/
1141 // ---------------------------------------------------------------------
1142 /* This is the work horse of the soft upgrade routine. It is very gental
1143 in that it does not install or remove any packages. It is assumed that the
1144 system was non-broken previously. */
1145 bool pkgProblemResolver::ResolveByKeepInternal()
1147 pkgDepCache::ActionGroup
group(Cache
);
1149 unsigned long Size
= Cache
.Head().PackageCount
;
1153 /* We have to order the packages so that the broken fixing pass
1154 operates from highest score to lowest. This prevents problems when
1155 high score packages cause the removal of lower score packages that
1156 would cause the removal of even lower score packages. */
1157 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
1158 pkgCache::Package
**PEnd
= PList
;
1159 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1162 std::sort(PList
,PEnd
,[this](Package
*a
, Package
*b
) { return ScoreSort(a
, b
) < 0; });
1165 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1167 clog
<< "Show Scores" << endl
;
1168 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1169 if (Scores
[(*K
)->ID
] != 0)
1171 pkgCache::PkgIterator
Pkg(Cache
,*K
);
1172 clog
<< Scores
[(*K
)->ID
] << ' ' << Pkg
<< std::endl
;
1177 clog
<< "Entering ResolveByKeep" << endl
;
1179 // Consider each broken package
1180 pkgCache::Package
**LastStop
= 0;
1181 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1183 pkgCache::PkgIterator
I(Cache
,*K
);
1185 if (Cache
[I
].InstallVer
== 0)
1188 if (InstOrNewPolicyBroken(I
) == false)
1191 /* Keep the package. If this works then great, otherwise we have
1192 to be significantly more aggressive and manipulate its dependencies */
1193 if ((Flags
[I
->ID
] & Protected
) == 0)
1196 clog
<< "Keeping package " << I
.FullName(false) << endl
;
1197 Cache
.MarkKeep(I
, false, false);
1198 if (InstOrNewPolicyBroken(I
) == false)
1205 // Isolate the problem dependencies
1206 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
1210 D
.GlobOr(Start
,End
);
1212 // We only worry about critical deps.
1213 if (End
.IsCritical() != true)
1217 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
1220 /* Hm, the group is broken.. I suppose the best thing to do is to
1221 is to try every combination of keep/not-keep for the set, but thats
1222 slow, and this never happens, just be conservative and assume the
1223 list of ors is in preference and keep till it starts to work. */
1227 clog
<< "Package " << I
.FullName(false) << " " << Start
<< endl
;
1229 // Look at all the possible provides on this package
1230 std::unique_ptr
<pkgCache::Version
*[]> VList(Start
.AllTargets());
1231 for (pkgCache::Version
**V
= VList
.get(); *V
!= 0; V
++)
1233 pkgCache::VerIterator
Ver(Cache
,*V
);
1234 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
1236 // It is not keepable
1237 if (Cache
[Pkg
].InstallVer
== 0 ||
1238 Pkg
->CurrentVer
== 0)
1241 if ((Flags
[I
->ID
] & Protected
) == 0)
1244 clog
<< " Keeping Package " << Pkg
.FullName(false) << " due to " << Start
.DepType() << endl
;
1245 Cache
.MarkKeep(Pkg
, false, false);
1248 if (InstOrNewPolicyBroken(I
) == false)
1252 if (InstOrNewPolicyBroken(I
) == false)
1260 if (InstOrNewPolicyBroken(I
) == false)
1264 if (InstOrNewPolicyBroken(I
) == true)
1268 if (K
== LastStop
) {
1269 // I is an iterator based off our temporary package list,
1270 // so copy the name we need before deleting the temporary list
1271 std::string
const LoopingPackage
= I
.FullName(false);
1273 return _error
->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.", LoopingPackage
.c_str());
1283 // ProblemResolver::InstallProtect - deprecated cpu-eating no-op /*{{{*/
1284 // ---------------------------------------------------------------------
1285 /* Actions issued with FromUser bit set are protected from further
1286 modification (expect by other calls with FromUser set) nowadays , so we
1287 don't need to reissue actions here, they are already set in stone. */
1288 void pkgProblemResolver::InstallProtect()
1290 pkgDepCache::ActionGroup
group(Cache
);
1292 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1294 if ((Flags
[I
->ID
] & Protected
) == Protected
)
1296 if ((Flags
[I
->ID
] & ToRemove
) == ToRemove
)
1297 Cache
.MarkDelete(I
);
1300 // preserve the information whether the package was auto
1301 // or manually installed
1302 bool autoInst
= (Cache
[I
].Flags
& pkgCache::Flag::Auto
);
1303 Cache
.MarkInstall(I
, false, 0, !autoInst
);
1309 // PrioSortList - Sort a list of versions by priority /*{{{*/
1310 // ---------------------------------------------------------------------
1311 /* This is ment to be used in conjunction with AllTargets to get a list
1312 of versions ordered by preference. */
1315 pkgCache
&PrioCache
;
1317 explicit PrioComp(pkgCache
&PrioCache
) : PrioCache(PrioCache
) {
1320 bool operator() (pkgCache::Version
* const &A
, pkgCache::Version
* const &B
) {
1321 return compare(A
, B
) < 0;
1324 int compare(pkgCache::Version
* const &A
, pkgCache::Version
* const &B
) {
1325 pkgCache::VerIterator
L(PrioCache
,A
);
1326 pkgCache::VerIterator
R(PrioCache
,B
);
1328 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
&&
1329 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
)
1331 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
1332 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
1335 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
&&
1336 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
1338 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
&&
1339 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
1342 if (L
->Priority
!= R
->Priority
)
1343 return R
->Priority
- L
->Priority
;
1344 return strcmp(L
.ParentPkg().Name(),R
.ParentPkg().Name());
1348 void pkgPrioSortList(pkgCache
&Cache
,pkgCache::Version
**List
)
1350 unsigned long Count
= 0;
1351 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
1353 std::sort(List
,List
+Count
,PrioComp(Cache
));