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 for (int Counter
= 0; Counter
!= 10 && Change
== true; Counter
++)
731 for (pkgCache::Package
**K
= PList
.get(); K
!= PEnd
; K
++)
733 pkgCache::PkgIterator
I(Cache
,*K
);
735 /* We attempt to install this and see if any breaks result,
736 this takes care of some strange cases */
737 if (Cache
[I
].CandidateVer
!= Cache
[I
].InstallVer
&&
738 I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0 &&
739 (Flags
[I
->ID
] & PreInstalled
) != 0 &&
740 (Flags
[I
->ID
] & Protected
) == 0 &&
741 (Flags
[I
->ID
] & ReInstateTried
) == 0)
744 clog
<< " Try to Re-Instate (" << Counter
<< ") " << I
.FullName(false) << endl
;
745 unsigned long OldBreaks
= Cache
.BrokenCount();
746 pkgCache::Version
*OldVer
= Cache
[I
].InstallVer
;
747 Flags
[I
->ID
] &= ReInstateTried
;
749 Cache
.MarkInstall(I
, false, 0, false);
750 if (Cache
[I
].InstBroken() == true ||
751 OldBreaks
< Cache
.BrokenCount())
754 Cache
.MarkDelete(I
, false, 0, false);
756 Cache
.MarkKeep(I
, false, false);
760 clog
<< "Re-Instated " << I
.FullName(false) << " (" << OldBreaks
<< " vs " << Cache
.BrokenCount() << ')' << endl
;
763 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
767 clog
<< "Investigating (" << Counter
<< ") " << I
<< endl
;
769 // Isolate the problem dependency
770 PackageKill KillList
[100];
771 PackageKill
*LEnd
= KillList
;
773 pkgCache::DepIterator Start
;
774 pkgCache::DepIterator End
;
775 PackageKill
*OldEnd
= LEnd
;
777 enum {OrRemove
,OrKeep
} OrOp
= OrRemove
;
778 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList();
779 D
.end() == false || InOr
== true;)
781 // Compute a single dependency element (glob or)
785 if (InOr
== true && OldEnd
== LEnd
)
787 if (OrOp
== OrRemove
)
789 if ((Flags
[I
->ID
] & Protected
) != Protected
)
792 clog
<< " Or group remove for " << I
.FullName(false) << endl
;
793 Cache
.MarkDelete(I
, false, 0, false);
797 else if (OrOp
== OrKeep
)
800 clog
<< " Or group keep for " << I
.FullName(false) << endl
;
801 Cache
.MarkKeep(I
, false, false);
806 /* We do an extra loop (as above) to finalize the or group
811 if (Start
.end() == true)
814 // We only worry about critical deps.
815 if (End
.IsCritical() != true)
824 // We only worry about critical deps.
825 if (Start
.IsCritical() != true)
830 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
837 clog
<< "Broken " << Start
<< endl
;
839 /* Look across the version list. If there are no possible
840 targets then we keep the package and bail. This is necessary
841 if a package has a dep on another package that can't be found */
842 std::unique_ptr
<pkgCache::Version
*[]> VList(Start
.AllTargets());
843 if (VList
[0] == 0 && (Flags
[I
->ID
] & Protected
) != Protected
&&
844 Start
.IsNegative() == false &&
845 Cache
[I
].NowBroken() == false)
849 /* No keep choice because the keep being OK could be the
850 result of another element in the OR group! */
855 Cache
.MarkKeep(I
, false, false);
860 for (pkgCache::Version
**V
= VList
.get(); *V
!= 0; V
++)
862 pkgCache::VerIterator
Ver(Cache
,*V
);
863 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
865 /* This is a conflicts, and the version we are looking
866 at is not the currently selected version of the
867 package, which means it is not necessary to
869 if (Cache
[Pkg
].InstallVer
!= Ver
&& Start
.IsNegative() == true)
872 clog
<< " Conflicts//Breaks against version "
873 << Ver
.VerStr() << " for " << Pkg
.Name()
874 << " but that is not InstVer, ignoring"
880 clog
<< " Considering " << Pkg
.FullName(false) << ' ' << Scores
[Pkg
->ID
] <<
881 " as a solution to " << I
.FullName(false) << ' ' << Scores
[I
->ID
] << endl
;
883 /* Try to fix the package under consideration rather than
884 fiddle with the VList package */
885 if (Scores
[I
->ID
] <= Scores
[Pkg
->ID
] ||
886 ((Cache
[Start
] & pkgDepCache::DepNow
) == 0 &&
887 End
.IsNegative() == false))
889 // Try a little harder to fix protected packages..
890 if ((Flags
[I
->ID
] & Protected
) == Protected
)
892 if (DoUpgrade(Pkg
) == true)
894 if (Scores
[Pkg
->ID
] > Scores
[I
->ID
])
895 Scores
[Pkg
->ID
] = Scores
[I
->ID
];
902 /* See if a keep will do, unless the package is protected,
903 then installing it will be necessary */
904 bool Installed
= Cache
[I
].Install();
905 Cache
.MarkKeep(I
, false, false);
906 if (Cache
[I
].InstBroken() == false)
908 // Unwind operation will be keep now
909 if (OrOp
== OrRemove
)
913 if (InOr
== true && Installed
== true)
914 Cache
.MarkInstall(I
, false, 0, false);
917 clog
<< " Holding Back " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
921 if (BrokenFix
== false || DoUpgrade(I
) == false)
923 // Consider other options
924 if (InOr
== false || Cache
[I
].Garbage
== true)
927 clog
<< " Removing " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
928 Cache
.MarkDelete(I
, false, 0, false);
929 if (Counter
> 1 && Scores
[Pkg
->ID
] > Scores
[I
->ID
])
930 Scores
[I
->ID
] = Scores
[Pkg
->ID
];
932 else if (TryFixByInstall
== true &&
933 Start
.TargetPkg()->CurrentVer
== 0 &&
934 Cache
[Start
.TargetPkg()].Delete() == false &&
935 (Flags
[Start
.TargetPkg()->ID
] & ToRemove
) != ToRemove
&&
936 Cache
.GetCandidateVer(Start
.TargetPkg()).end() == false)
938 /* Before removing or keeping the package with the broken dependency
939 try instead to install the first not previously installed package
940 solving this dependency. This helps every time a previous solver
941 is removed by the resolver because of a conflict or alike but it is
942 dangerous as it could trigger new breaks/conflicts… */
944 clog
<< " Try Installing " << Start
.TargetPkg() << " before changing " << I
.FullName(false) << std::endl
;
945 unsigned long const OldBroken
= Cache
.BrokenCount();
946 Cache
.MarkInstall(Start
.TargetPkg(), true, 1, false);
947 // FIXME: we should undo the complete MarkInstall process here
948 if (Cache
[Start
.TargetPkg()].InstBroken() == true || Cache
.BrokenCount() > OldBroken
)
949 Cache
.MarkDelete(Start
.TargetPkg(), false, 1, false);
960 if (Start
->Type
== pkgCache::Dep::DpkgBreaks
)
962 // first, try upgradring the package, if that
963 // does not help, the breaks goes onto the
966 // FIXME: use DoUpgrade(Pkg) instead?
967 if (Cache
[End
] & pkgDepCache::DepGCVer
)
970 clog
<< " Upgrading " << Pkg
.FullName(false) << " due to Breaks field in " << I
.FullName(false) << endl
;
971 Cache
.MarkInstall(Pkg
, false, 0, false);
976 // Skip adding to the kill list if it is protected
977 if ((Flags
[Pkg
->ID
] & Protected
) != 0)
981 clog
<< " Added " << Pkg
.FullName(false) << " to the remove list" << endl
;
987 if (Start
.IsNegative() == false)
992 // Hm, nothing can possibly satisify this dep. Nuke it.
994 Start
.IsNegative() == false &&
995 (Flags
[I
->ID
] & Protected
) != Protected
)
997 bool Installed
= Cache
[I
].Install();
999 if (Cache
[I
].InstBroken() == false)
1001 // Unwind operation will be keep now
1002 if (OrOp
== OrRemove
)
1006 if (InOr
== true && Installed
== true)
1007 Cache
.MarkInstall(I
, false, 0, false);
1010 clog
<< " Holding Back " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1015 clog
<< " Removing " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1017 Cache
.MarkDelete(I
, false, 0, false);
1032 // Apply the kill list now
1033 if (Cache
[I
].InstallVer
!= 0)
1035 for (PackageKill
*J
= KillList
; J
!= LEnd
; J
++)
1038 if ((Cache
[J
->Dep
] & pkgDepCache::DepGNow
) == 0)
1040 if (J
->Dep
.IsNegative() == true)
1043 clog
<< " Fixing " << I
.FullName(false) << " via remove of " << J
->Pkg
.FullName(false) << endl
;
1044 Cache
.MarkDelete(J
->Pkg
, false, 0, false);
1050 clog
<< " Fixing " << I
.FullName(false) << " via keep of " << J
->Pkg
.FullName(false) << endl
;
1051 Cache
.MarkKeep(J
->Pkg
, false, false);
1056 if (Scores
[I
->ID
] > Scores
[J
->Pkg
->ID
])
1057 Scores
[J
->Pkg
->ID
] = Scores
[I
->ID
];
1065 clog
<< "Done" << endl
;
1067 if (Cache
.BrokenCount() != 0)
1069 // See if this is the result of a hold
1070 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1071 for (;I
.end() != true; ++I
)
1073 if (Cache
[I
].InstBroken() == false)
1075 if ((Flags
[I
->ID
] & Protected
) != Protected
)
1076 return _error
->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
1078 return _error
->Error(_("Unable to correct problems, you have held broken packages."));
1081 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
1082 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1083 for (;I
.end() != true; ++I
) {
1084 if (Cache
[I
].NewInstall() && !(Flags
[I
->ID
] & PreInstalled
)) {
1085 if(_config
->FindI("Debug::pkgAutoRemove",false)) {
1086 std::clog
<< "Resolve installed new pkg: " << I
.FullName(false)
1087 << " (now marking it as auto)" << std::endl
;
1089 Cache
[I
].Flags
|= pkgCache::Flag::Auto
;
1097 // ProblemResolver::BreaksInstOrPolicy - Check if the given pkg is broken/*{{{*/
1098 // ---------------------------------------------------------------------
1099 /* This checks if the given package is broken either by a hard dependency
1100 (InstBroken()) or by introducing a new policy breakage e.g. new
1101 unsatisfied recommends for a package that was in "policy-good" state
1103 Note that this is not perfect as it will ignore further breakage
1104 for already broken policy (recommends)
1106 bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I
)
1108 // a broken install is always a problem
1109 if (Cache
[I
].InstBroken() == true)
1112 std::clog
<< " Dependencies are not satisfied for " << I
<< std::endl
;
1116 // a newly broken policy (recommends/suggests) is a problem
1117 if (Cache
[I
].NowPolicyBroken() == false &&
1118 Cache
[I
].InstPolicyBroken() == true)
1121 std::clog
<< " Policy breaks with upgrade of " << I
<< std::endl
;
1128 // ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1129 // ---------------------------------------------------------------------
1130 /* This is the work horse of the soft upgrade routine. It is very gental
1131 in that it does not install or remove any packages. It is assumed that the
1132 system was non-broken previously. */
1133 bool pkgProblemResolver::ResolveByKeep(OpProgress
* const Progress
)
1135 std::string
const solver
= _config
->Find("APT::Solver", "internal");
1136 if (solver
!= "internal")
1137 return EDSP::ResolveExternal(solver
.c_str(), Cache
, true, false, false, Progress
);
1138 return ResolveByKeepInternal();
1141 // ProblemResolver::ResolveByKeepInternal - Resolve problems using keep /*{{{*/
1142 // ---------------------------------------------------------------------
1143 /* This is the work horse of the soft upgrade routine. It is very gental
1144 in that it does not install or remove any packages. It is assumed that the
1145 system was non-broken previously. */
1146 bool pkgProblemResolver::ResolveByKeepInternal()
1148 pkgDepCache::ActionGroup
group(Cache
);
1150 unsigned long Size
= Cache
.Head().PackageCount
;
1154 /* We have to order the packages so that the broken fixing pass
1155 operates from highest score to lowest. This prevents problems when
1156 high score packages cause the removal of lower score packages that
1157 would cause the removal of even lower score packages. */
1158 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
1159 pkgCache::Package
**PEnd
= PList
;
1160 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1163 std::sort(PList
,PEnd
,[this](Package
*a
, Package
*b
) { return ScoreSort(a
, b
) < 0; });
1166 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1168 clog
<< "Show Scores" << endl
;
1169 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1170 if (Scores
[(*K
)->ID
] != 0)
1172 pkgCache::PkgIterator
Pkg(Cache
,*K
);
1173 clog
<< Scores
[(*K
)->ID
] << ' ' << Pkg
<< std::endl
;
1178 clog
<< "Entering ResolveByKeep" << endl
;
1180 // Consider each broken package
1181 pkgCache::Package
**LastStop
= 0;
1182 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1184 pkgCache::PkgIterator
I(Cache
,*K
);
1186 if (Cache
[I
].InstallVer
== 0)
1189 if (InstOrNewPolicyBroken(I
) == false)
1192 /* Keep the package. If this works then great, otherwise we have
1193 to be significantly more aggressive and manipulate its dependencies */
1194 if ((Flags
[I
->ID
] & Protected
) == 0)
1197 clog
<< "Keeping package " << I
.FullName(false) << endl
;
1198 Cache
.MarkKeep(I
, false, false);
1199 if (InstOrNewPolicyBroken(I
) == false)
1206 // Isolate the problem dependencies
1207 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
1211 D
.GlobOr(Start
,End
);
1213 // We only worry about critical deps.
1214 if (End
.IsCritical() != true)
1218 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
1221 /* Hm, the group is broken.. I suppose the best thing to do is to
1222 is to try every combination of keep/not-keep for the set, but thats
1223 slow, and this never happens, just be conservative and assume the
1224 list of ors is in preference and keep till it starts to work. */
1228 clog
<< "Package " << I
.FullName(false) << " " << Start
<< endl
;
1230 // Look at all the possible provides on this package
1231 std::unique_ptr
<pkgCache::Version
*[]> VList(Start
.AllTargets());
1232 for (pkgCache::Version
**V
= VList
.get(); *V
!= 0; V
++)
1234 pkgCache::VerIterator
Ver(Cache
,*V
);
1235 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
1237 // It is not keepable
1238 if (Cache
[Pkg
].InstallVer
== 0 ||
1239 Pkg
->CurrentVer
== 0)
1242 if ((Flags
[I
->ID
] & Protected
) == 0)
1245 clog
<< " Keeping Package " << Pkg
.FullName(false) << " due to " << Start
.DepType() << endl
;
1246 Cache
.MarkKeep(Pkg
, false, false);
1249 if (InstOrNewPolicyBroken(I
) == false)
1253 if (InstOrNewPolicyBroken(I
) == false)
1261 if (InstOrNewPolicyBroken(I
) == false)
1265 if (InstOrNewPolicyBroken(I
) == true)
1269 if (K
== LastStop
) {
1270 // I is an iterator based off our temporary package list,
1271 // so copy the name we need before deleting the temporary list
1272 std::string
const LoopingPackage
= I
.FullName(false);
1274 return _error
->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.", LoopingPackage
.c_str());
1284 // ProblemResolver::InstallProtect - deprecated cpu-eating no-op /*{{{*/
1285 // ---------------------------------------------------------------------
1286 /* Actions issued with FromUser bit set are protected from further
1287 modification (expect by other calls with FromUser set) nowadays , so we
1288 don't need to reissue actions here, they are already set in stone. */
1289 void pkgProblemResolver::InstallProtect()
1291 pkgDepCache::ActionGroup
group(Cache
);
1293 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1295 if ((Flags
[I
->ID
] & Protected
) == Protected
)
1297 if ((Flags
[I
->ID
] & ToRemove
) == ToRemove
)
1298 Cache
.MarkDelete(I
);
1301 // preserve the information whether the package was auto
1302 // or manually installed
1303 bool autoInst
= (Cache
[I
].Flags
& pkgCache::Flag::Auto
);
1304 Cache
.MarkInstall(I
, false, 0, !autoInst
);
1310 // PrioSortList - Sort a list of versions by priority /*{{{*/
1311 // ---------------------------------------------------------------------
1312 /* This is ment to be used in conjunction with AllTargets to get a list
1313 of versions ordered by preference. */
1316 pkgCache
&PrioCache
;
1318 PrioComp(pkgCache
&PrioCache
) : PrioCache(PrioCache
) {
1321 bool operator() (pkgCache::Version
* const &A
, pkgCache::Version
* const &B
) {
1322 return compare(A
, B
) < 0;
1325 int compare(pkgCache::Version
* const &A
, pkgCache::Version
* const &B
) {
1326 pkgCache::VerIterator
L(PrioCache
,A
);
1327 pkgCache::VerIterator
R(PrioCache
,B
);
1329 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
&&
1330 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
)
1332 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
1333 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
1336 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
&&
1337 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
1339 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
&&
1340 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
1343 if (L
->Priority
!= R
->Priority
)
1344 return R
->Priority
- L
->Priority
;
1345 return strcmp(L
.ParentPkg().Name(),R
.ParentPkg().Name());
1349 void pkgPrioSortList(pkgCache
&Cache
,pkgCache::Version
**List
)
1351 unsigned long Count
= 0;
1352 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
1354 std::sort(List
,List
+Count
,PrioComp(Cache
));