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 pkgProblemResolver
*pkgProblemResolver::This
= 0;
39 // Simulate::Simulate - Constructor /*{{{*/
40 // ---------------------------------------------------------------------
41 /* The legacy translations here of input Pkg iterators is obsolete,
42 this is not necessary since the pkgCaches are fully shared now. */
43 pkgSimulate::pkgSimulate(pkgDepCache
*Cache
) : pkgPackageManager(Cache
),
44 d(NULL
), iPolicy(Cache
),
45 Sim(&Cache
->GetCache(),&iPolicy
),
49 Flags
= new unsigned char[Cache
->Head().PackageCount
];
50 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
52 // Fake a filename so as not to activate the media swapping
53 string Jnk
= "SIMULATE";
54 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
58 // Simulate::~Simulate - Destructor /*{{{*/
59 pkgSimulate::~pkgSimulate()
64 // Simulate::Describe - Describe a package /*{{{*/
65 // ---------------------------------------------------------------------
66 /* Parameter Current == true displays the current package version,
67 Parameter Candidate == true displays the candidate package version */
68 void pkgSimulate::Describe(PkgIterator Pkg
,ostream
&out
,bool Current
,bool Candidate
)
72 out
<< Pkg
.FullName(true);
76 Ver
= Pkg
.CurrentVer();
77 if (Ver
.end() == false)
78 out
<< " [" << Ver
.VerStr() << ']';
81 if (Candidate
== true)
83 Ver
= Sim
[Pkg
].CandidateVerIter(Sim
);
84 if (Ver
.end() == true)
87 out
<< " (" << Ver
.VerStr() << ' ' << Ver
.RelStr() << ')';
91 // Simulate::Install - Simulate unpacking of a package /*{{{*/
92 // ---------------------------------------------------------------------
94 bool pkgSimulate::Install(PkgIterator iPkg
,string
/*File*/)
97 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
101 Describe(Pkg
,cout
,true,true);
102 Sim
.MarkInstall(Pkg
,false);
104 // Look for broken conflicts+predepends.
105 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; ++I
)
107 if (Sim
[I
].InstallVer
== 0)
110 for (DepIterator D
= Sim
[I
].InstVerIter(Sim
).DependsList(); D
.end() == false;)
115 if (Start
.IsNegative() == true ||
116 End
->Type
== pkgCache::Dep::PreDepends
)
118 if ((Sim
[End
] & pkgDepCache::DepGInstall
) == 0)
120 cout
<< " [" << I
.FullName(false) << " on " << Start
.TargetPkg().FullName(false) << ']';
121 if (Start
->Type
== pkgCache::Dep::Conflicts
)
122 _error
->Error("Fatal, conflicts violated %s",I
.FullName(false).c_str());
128 if (Sim
.BrokenCount() != 0)
135 // Simulate::Configure - Simulate configuration of a Package /*{{{*/
136 // ---------------------------------------------------------------------
137 /* This is not an acurate simulation of relatity, we should really not
138 install the package.. For some investigations it may be necessary
140 bool pkgSimulate::Configure(PkgIterator iPkg
)
142 // Adapt the iterator
143 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
147 if (Sim
[Pkg
].InstBroken() == true)
149 cout
<< "Conf " << Pkg
.FullName(false) << " broken" << endl
;
153 // Print out each package and the failed dependencies
154 for (pkgCache::DepIterator D
= Sim
[Pkg
].InstVerIter(Sim
).DependsList(); D
.end() == false; ++D
)
156 if (Sim
.IsImportantDep(D
) == false ||
157 (Sim
[D
] & pkgDepCache::DepInstall
) != 0)
160 if (D
->Type
== pkgCache::Dep::Obsoletes
)
161 cout
<< " Obsoletes:" << D
.TargetPkg().FullName(false);
162 else if (D
->Type
== pkgCache::Dep::Conflicts
)
163 cout
<< " Conflicts:" << D
.TargetPkg().FullName(false);
164 else if (D
->Type
== pkgCache::Dep::DpkgBreaks
)
165 cout
<< " Breaks:" << D
.TargetPkg().FullName(false);
167 cout
<< " Depends:" << D
.TargetPkg().FullName(false);
171 _error
->Error("Conf Broken %s",Pkg
.FullName(false).c_str());
176 Describe(Pkg
,cout
,false,true);
179 if (Sim
.BrokenCount() != 0)
187 // Simulate::Remove - Simulate the removal of a package /*{{{*/
188 // ---------------------------------------------------------------------
190 bool pkgSimulate::Remove(PkgIterator iPkg
,bool Purge
)
192 // Adapt the iterator
193 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
194 if (Pkg
.end() == true)
196 std::cerr
<< (Purge
? "Purg" : "Remv") << " invalid package " << iPkg
.FullName() << std::endl
;
207 Describe(Pkg
,cout
,true,false);
209 if (Sim
.BrokenCount() != 0)
217 // Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
218 // ---------------------------------------------------------------------
220 void pkgSimulate::ShortBreaks()
223 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; ++I
)
225 if (Sim
[I
].InstBroken() == true)
227 if (Flags
[I
->ID
] == 0)
228 cout
<< I
.FullName(false) << ' ';
230 cout << I.Name() << "! ";*/
236 // ApplyStatus - Adjust for non-ok packages /*{{{*/
237 // ---------------------------------------------------------------------
238 /* We attempt to change the state of the all packages that have failed
239 installation toward their real state. The ordering code will perform
240 the necessary calculations to deal with the problems. */
241 bool pkgApplyStatus(pkgDepCache
&Cache
)
243 pkgDepCache::ActionGroup
group(Cache
);
245 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
247 if (I
->VersionList
== 0)
250 // Only choice for a ReInstReq package is to reinstall
251 if (I
->InstState
== pkgCache::State::ReInstReq
||
252 I
->InstState
== pkgCache::State::HoldReInstReq
)
254 if (I
->CurrentVer
!= 0 && I
.CurrentVer().Downloadable() == true)
255 Cache
.MarkKeep(I
, false, false);
258 // Is this right? Will dpkg choke on an upgrade?
259 if (Cache
[I
].CandidateVer
!= 0 &&
260 Cache
[I
].CandidateVerIter(Cache
).Downloadable() == true)
261 Cache
.MarkInstall(I
, false, 0, false);
263 return _error
->Error(_("The package %s needs to be reinstalled, "
264 "but I can't find an archive for it."),I
.FullName(true).c_str());
270 switch (I
->CurrentState
)
272 /* This means installation failed somehow - it does not need to be
273 re-unpacked (probably) */
274 case pkgCache::State::UnPacked
:
275 case pkgCache::State::HalfConfigured
:
276 case pkgCache::State::TriggersAwaited
:
277 case pkgCache::State::TriggersPending
:
278 if ((I
->CurrentVer
!= 0 && I
.CurrentVer().Downloadable() == true) ||
279 I
.State() != pkgCache::PkgIterator::NeedsUnpack
)
280 Cache
.MarkKeep(I
, false, false);
283 if (Cache
[I
].CandidateVer
!= 0 &&
284 Cache
[I
].CandidateVerIter(Cache
).Downloadable() == true)
285 Cache
.MarkInstall(I
, true, 0, false);
287 Cache
.MarkDelete(I
, false, 0, false);
291 // This means removal failed
292 case pkgCache::State::HalfInstalled
:
293 Cache
.MarkDelete(I
, false, 0, false);
297 if (I
->InstState
!= pkgCache::State::Ok
)
298 return _error
->Error("The package %s is not ok and I "
299 "don't know how to fix it!",I
.FullName(false).c_str());
305 // FixBroken - Fix broken packages /*{{{*/
306 // ---------------------------------------------------------------------
307 /* This autoinstalls every broken package and then runs the problem resolver
309 bool pkgFixBroken(pkgDepCache
&Cache
)
311 pkgDepCache::ActionGroup
group(Cache
);
313 // Auto upgrade all broken packages
314 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
315 if (Cache
[I
].NowBroken() == true)
316 Cache
.MarkInstall(I
, true, 0, false);
318 /* Fix packages that are in a NeedArchive state but don't have a
319 downloadable install version */
320 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
322 if (I
.State() != pkgCache::PkgIterator::NeedsUnpack
||
323 Cache
[I
].Delete() == true)
326 if (Cache
[I
].InstVerIter(Cache
).Downloadable() == false)
329 Cache
.MarkInstall(I
, true, 0, false);
332 pkgProblemResolver
Fix(&Cache
);
333 return Fix
.Resolve(true);
336 // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
337 // ---------------------------------------------------------------------
339 pkgProblemResolver::pkgProblemResolver(pkgDepCache
*pCache
) : d(NULL
), Cache(*pCache
)
342 unsigned long Size
= Cache
.Head().PackageCount
;
343 Scores
= new int[Size
];
344 Flags
= new unsigned char[Size
];
345 memset(Flags
,0,sizeof(*Flags
)*Size
);
347 // Set debug to true to see its decision logic
348 Debug
= _config
->FindB("Debug::pkgProblemResolver",false);
351 // ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
352 // ---------------------------------------------------------------------
354 pkgProblemResolver::~pkgProblemResolver()
360 // ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
361 // ---------------------------------------------------------------------
363 int pkgProblemResolver::ScoreSort(const void *a
,const void *b
)
365 Package
const **A
= (Package
const **)a
;
366 Package
const **B
= (Package
const **)b
;
367 if (This
->Scores
[(*A
)->ID
] > This
->Scores
[(*B
)->ID
])
369 if (This
->Scores
[(*A
)->ID
] < This
->Scores
[(*B
)->ID
])
374 // ProblemResolver::MakeScores - Make the score table /*{{{*/
375 // ---------------------------------------------------------------------
377 void pkgProblemResolver::MakeScores()
379 unsigned long Size
= Cache
.Head().PackageCount
;
380 memset(Scores
,0,sizeof(*Scores
)*Size
);
382 // maps to pkgCache::State::VerPriority:
383 // Required Important Standard Optional Extra
386 _config
->FindI("pkgProblemResolver::Scores::Required",3),
387 _config
->FindI("pkgProblemResolver::Scores::Important",2),
388 _config
->FindI("pkgProblemResolver::Scores::Standard",1),
389 _config
->FindI("pkgProblemResolver::Scores::Optional",-1),
390 _config
->FindI("pkgProblemResolver::Scores::Extra",-2)
392 int PrioEssentials
= _config
->FindI("pkgProblemResolver::Scores::Essentials",100);
393 int PrioInstalledAndNotObsolete
= _config
->FindI("pkgProblemResolver::Scores::NotObsolete",1);
396 _config
->FindI("pkgProblemResolver::Scores::Depends",1),
397 _config
->FindI("pkgProblemResolver::Scores::PreDepends",1),
398 _config
->FindI("pkgProblemResolver::Scores::Suggests",0),
399 _config
->FindI("pkgProblemResolver::Scores::Recommends",1),
400 _config
->FindI("pkgProblemResolver::Scores::Conflicts",-1),
401 _config
->FindI("pkgProblemResolver::Scores::Replaces",0),
402 _config
->FindI("pkgProblemResolver::Scores::Obsoletes",0),
403 _config
->FindI("pkgProblemResolver::Scores::Breaks",-1),
404 _config
->FindI("pkgProblemResolver::Scores::Enhances",0)
406 int AddProtected
= _config
->FindI("pkgProblemResolver::Scores::AddProtected",10000);
407 int AddEssential
= _config
->FindI("pkgProblemResolver::Scores::AddEssential",5000);
409 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
410 clog
<< "Settings used to calculate pkgProblemResolver::Scores::" << endl
411 << " Required => " << PrioMap
[pkgCache::State::Required
] << endl
412 << " Important => " << PrioMap
[pkgCache::State::Important
] << endl
413 << " Standard => " << PrioMap
[pkgCache::State::Standard
] << endl
414 << " Optional => " << PrioMap
[pkgCache::State::Optional
] << endl
415 << " Extra => " << PrioMap
[pkgCache::State::Extra
] << endl
416 << " Essentials => " << PrioEssentials
<< endl
417 << " InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete
<< endl
418 << " Pre-Depends => " << DepMap
[pkgCache::Dep::PreDepends
] << endl
419 << " Depends => " << DepMap
[pkgCache::Dep::Depends
] << endl
420 << " Recommends => " << DepMap
[pkgCache::Dep::Recommends
] << endl
421 << " Suggests => " << DepMap
[pkgCache::Dep::Suggests
] << endl
422 << " Conflicts => " << DepMap
[pkgCache::Dep::Conflicts
] << endl
423 << " Breaks => " << DepMap
[pkgCache::Dep::DpkgBreaks
] << endl
424 << " Replaces => " << DepMap
[pkgCache::Dep::Replaces
] << endl
425 << " Obsoletes => " << DepMap
[pkgCache::Dep::Obsoletes
] << endl
426 << " Enhances => " << DepMap
[pkgCache::Dep::Enhances
] << endl
427 << " AddProtected => " << AddProtected
<< endl
428 << " AddEssential => " << AddEssential
<< endl
;
430 // Generate the base scores for a package based on its properties
431 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
433 if (Cache
[I
].InstallVer
== 0)
436 int &Score
= Scores
[I
->ID
];
438 /* This is arbitrary, it should be high enough to elevate an
439 essantial package above most other packages but low enough
440 to allow an obsolete essential packages to be removed by
441 a conflicts on a powerful normal package (ie libc6) */
442 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
443 || (I
->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
444 Score
+= PrioEssentials
;
446 pkgCache::VerIterator
const InstVer
= Cache
[I
].InstVerIter(Cache
);
447 // We apply priorities only to downloadable packages, all others are prio:extra
448 // as an obsolete prio:standard package can't be that standard anymore…
449 if (InstVer
->Priority
<= pkgCache::State::Extra
&& InstVer
.Downloadable() == true)
450 Score
+= PrioMap
[InstVer
->Priority
];
452 Score
+= PrioMap
[pkgCache::State::Extra
];
454 /* This helps to fix oddball problems with conflicting packages
455 on the same level. We enhance the score of installed packages
456 if those are not obsolete */
457 if (I
->CurrentVer
!= 0 && Cache
[I
].CandidateVer
!= 0 && Cache
[I
].CandidateVerIter(Cache
).Downloadable())
458 Score
+= PrioInstalledAndNotObsolete
;
460 // propagate score points along dependencies
461 for (pkgCache::DepIterator D
= InstVer
.DependsList(); D
.end() == false; ++D
)
463 if (DepMap
[D
->Type
] == 0)
465 pkgCache::PkgIterator
const T
= D
.TargetPkg();
468 pkgCache::VerIterator
const IV
= Cache
[T
].InstVerIter(Cache
);
469 if (IV
.end() == true || D
.IsSatisfied(IV
) == false)
472 Scores
[T
->ID
] += DepMap
[D
->Type
];
476 // Copy the scores to advoid additive looping
477 std::unique_ptr
<int[]> OldScores(new int[Size
]);
478 memcpy(OldScores
.get(),Scores
,sizeof(*Scores
)*Size
);
480 /* Now we cause 1 level of dependency inheritance, that is we add the
481 score of the packages that depend on the target Package. This
482 fortifies high scoring packages */
483 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
485 if (Cache
[I
].InstallVer
== 0)
488 for (pkgCache::DepIterator D
= I
.RevDependsList(); D
.end() == false; ++D
)
490 // Only do it for the install version
491 if ((pkgCache::Version
*)D
.ParentVer() != Cache
[D
.ParentPkg()].InstallVer
||
492 (D
->Type
!= pkgCache::Dep::Depends
&&
493 D
->Type
!= pkgCache::Dep::PreDepends
&&
494 D
->Type
!= pkgCache::Dep::Recommends
))
497 // Do not propagate negative scores otherwise
498 // an extra (-2) package might score better than an optional (-1)
499 if (OldScores
[D
.ParentPkg()->ID
] > 0)
500 Scores
[I
->ID
] += OldScores
[D
.ParentPkg()->ID
];
504 /* Now we propagate along provides. This makes the packages that
505 provide important packages extremely important */
506 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
508 for (pkgCache::PrvIterator P
= I
.ProvidesList(); P
.end() == false; ++P
)
510 // Only do it once per package
511 if ((pkgCache::Version
*)P
.OwnerVer() != Cache
[P
.OwnerPkg()].InstallVer
)
513 Scores
[P
.OwnerPkg()->ID
] += abs(Scores
[I
->ID
] - OldScores
[I
->ID
]);
517 /* Protected things are pushed really high up. This number should put them
518 ahead of everything */
519 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
521 if ((Flags
[I
->ID
] & Protected
) != 0)
522 Scores
[I
->ID
] += AddProtected
;
523 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
||
524 (I
->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
525 Scores
[I
->ID
] += AddEssential
;
529 // ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
530 // ---------------------------------------------------------------------
531 /* This goes through and tries to reinstall packages to make this package
533 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg
)
535 pkgDepCache::ActionGroup
group(Cache
);
537 if ((Flags
[Pkg
->ID
] & Upgradable
) == 0 || Cache
[Pkg
].Upgradable() == false)
539 if ((Flags
[Pkg
->ID
] & Protected
) == Protected
)
542 Flags
[Pkg
->ID
] &= ~Upgradable
;
544 bool WasKept
= Cache
[Pkg
].Keep();
545 Cache
.MarkInstall(Pkg
, false, 0, false);
547 // This must be a virtual package or something like that.
548 if (Cache
[Pkg
].InstVerIter(Cache
).end() == true)
551 // Isolate the problem dependency
553 for (pkgCache::DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
555 // Compute a single dependency element (glob or)
556 pkgCache::DepIterator Start
= D
;
557 pkgCache::DepIterator End
= D
;
558 for (bool LastOR
= true; D
.end() == false && LastOR
== true;)
560 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
566 // We only worry about critical deps.
567 if (End
.IsCritical() != true)
570 // Iterate over all the members in the or group
574 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
577 // Do not change protected packages
578 PkgIterator P
= Start
.SmartTargetPkg();
579 if ((Flags
[P
->ID
] & Protected
) == Protected
)
582 clog
<< " Reinst Failed because of protected " << P
.FullName(false) << endl
;
587 // Upgrade the package if the candidate version will fix the problem.
588 if ((Cache
[Start
] & pkgDepCache::DepCVer
) == pkgDepCache::DepCVer
)
590 if (DoUpgrade(P
) == false)
593 clog
<< " Reinst Failed because of " << P
.FullName(false) << endl
;
604 /* We let the algorithm deal with conflicts on its next iteration,
605 it is much smarter than us */
606 if (Start
.IsNegative() == true)
610 clog
<< " Reinst Failed early because of " << Start
.TargetPkg().FullName(false) << endl
;
623 // Undo our operations - it might be smart to undo everything this did..
627 Cache
.MarkKeep(Pkg
, false, false);
629 Cache
.MarkDelete(Pkg
, false, 0, false);
634 clog
<< " Re-Instated " << Pkg
.FullName(false) << endl
;
638 // ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/
639 bool pkgProblemResolver::Resolve(bool BrokenFix
, OpProgress
* const Progress
)
641 std::string
const solver
= _config
->Find("APT::Solver", "internal");
642 if (solver
!= "internal")
643 return EDSP::ResolveExternal(solver
.c_str(), Cache
, false, false, false, Progress
);
644 return ResolveInternal(BrokenFix
);
647 // ProblemResolver::ResolveInternal - Run the resolution pass /*{{{*/
648 // ---------------------------------------------------------------------
649 /* This routines works by calculating a score for each package. The score
650 is derived by considering the package's priority and all reverse
651 dependents giving an integer that reflects the amount of breakage that
652 adjusting the package will inflict.
654 It goes from highest score to lowest and corrects all of the breaks by
655 keeping or removing the dependent packages. If that fails then it removes
656 the package itself and goes on. The routine should be able to intelligently
657 go from any broken state to a fixed state.
659 The BrokenFix flag enables a mode where the algorithm tries to
660 upgrade packages to advoid problems. */
661 bool pkgProblemResolver::ResolveInternal(bool const BrokenFix
)
663 pkgDepCache::ActionGroup
group(Cache
);
665 // Record which packages are marked for install
670 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
672 if (Cache
[I
].Install() == true)
673 Flags
[I
->ID
] |= PreInstalled
;
676 if (Cache
[I
].InstBroken() == true && BrokenFix
== true)
678 Cache
.MarkInstall(I
, false, 0, false);
679 if (Cache
[I
].Install() == true)
683 Flags
[I
->ID
] &= ~PreInstalled
;
685 Flags
[I
->ID
] |= Upgradable
;
688 while (Again
== true);
691 clog
<< "Starting pkgProblemResolver with broken count: "
692 << Cache
.BrokenCount() << endl
;
697 unsigned long const Size
= Cache
.Head().PackageCount
;
699 /* We have to order the packages so that the broken fixing pass
700 operates from highest score to lowest. This prevents problems when
701 high score packages cause the removal of lower score packages that
702 would cause the removal of even lower score packages. */
703 std::unique_ptr
<pkgCache::Package
*[]> PList(new pkgCache::Package
*[Size
]);
704 pkgCache::Package
**PEnd
= PList
.get();
705 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
708 qsort(PList
.get(),PEnd
- PList
.get(),sizeof(PList
[0]),&ScoreSort
);
710 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
712 clog
<< "Show Scores" << endl
;
713 for (pkgCache::Package
**K
= PList
.get(); K
!= PEnd
; K
++)
714 if (Scores
[(*K
)->ID
] != 0)
716 pkgCache::PkgIterator
Pkg(Cache
,*K
);
717 clog
<< Scores
[(*K
)->ID
] << ' ' << Pkg
<< std::endl
;
722 clog
<< "Starting 2 pkgProblemResolver with broken count: "
723 << Cache
.BrokenCount() << endl
;
726 /* Now consider all broken packages. For each broken package we either
727 remove the package or fix it's problem. We do this once, it should
728 not be possible for a loop to form (that is a < b < c and fixing b by
729 changing a breaks c) */
731 bool const TryFixByInstall
= _config
->FindB("pkgProblemResolver::FixByInstall", true);
732 for (int Counter
= 0; Counter
!= 10 && Change
== true; Counter
++)
735 for (pkgCache::Package
**K
= PList
.get(); K
!= PEnd
; K
++)
737 pkgCache::PkgIterator
I(Cache
,*K
);
739 /* We attempt to install this and see if any breaks result,
740 this takes care of some strange cases */
741 if (Cache
[I
].CandidateVer
!= Cache
[I
].InstallVer
&&
742 I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0 &&
743 (Flags
[I
->ID
] & PreInstalled
) != 0 &&
744 (Flags
[I
->ID
] & Protected
) == 0 &&
745 (Flags
[I
->ID
] & ReInstateTried
) == 0)
748 clog
<< " Try to Re-Instate (" << Counter
<< ") " << I
.FullName(false) << endl
;
749 unsigned long OldBreaks
= Cache
.BrokenCount();
750 pkgCache::Version
*OldVer
= Cache
[I
].InstallVer
;
751 Flags
[I
->ID
] &= ReInstateTried
;
753 Cache
.MarkInstall(I
, false, 0, false);
754 if (Cache
[I
].InstBroken() == true ||
755 OldBreaks
< Cache
.BrokenCount())
758 Cache
.MarkDelete(I
, false, 0, false);
760 Cache
.MarkKeep(I
, false, false);
764 clog
<< "Re-Instated " << I
.FullName(false) << " (" << OldBreaks
<< " vs " << Cache
.BrokenCount() << ')' << endl
;
767 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
771 clog
<< "Investigating (" << Counter
<< ") " << I
<< endl
;
773 // Isolate the problem dependency
774 PackageKill KillList
[100];
775 PackageKill
*LEnd
= KillList
;
777 pkgCache::DepIterator Start
;
778 pkgCache::DepIterator End
;
779 PackageKill
*OldEnd
= LEnd
;
781 enum {OrRemove
,OrKeep
} OrOp
= OrRemove
;
782 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList();
783 D
.end() == false || InOr
== true;)
785 // Compute a single dependency element (glob or)
789 if (InOr
== true && OldEnd
== LEnd
)
791 if (OrOp
== OrRemove
)
793 if ((Flags
[I
->ID
] & Protected
) != Protected
)
796 clog
<< " Or group remove for " << I
.FullName(false) << endl
;
797 Cache
.MarkDelete(I
, false, 0, false);
801 else if (OrOp
== OrKeep
)
804 clog
<< " Or group keep for " << I
.FullName(false) << endl
;
805 Cache
.MarkKeep(I
, false, false);
810 /* We do an extra loop (as above) to finalize the or group
815 if (Start
.end() == true)
818 // We only worry about critical deps.
819 if (End
.IsCritical() != true)
828 // We only worry about critical deps.
829 if (Start
.IsCritical() != true)
834 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
841 clog
<< "Broken " << Start
<< endl
;
843 /* Look across the version list. If there are no possible
844 targets then we keep the package and bail. This is necessary
845 if a package has a dep on another package that can't be found */
846 std::unique_ptr
<pkgCache::Version
*[]> VList(Start
.AllTargets());
847 if (VList
[0] == 0 && (Flags
[I
->ID
] & Protected
) != Protected
&&
848 Start
.IsNegative() == false &&
849 Cache
[I
].NowBroken() == false)
853 /* No keep choice because the keep being OK could be the
854 result of another element in the OR group! */
859 Cache
.MarkKeep(I
, false, false);
864 for (pkgCache::Version
**V
= VList
.get(); *V
!= 0; V
++)
866 pkgCache::VerIterator
Ver(Cache
,*V
);
867 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
869 /* This is a conflicts, and the version we are looking
870 at is not the currently selected version of the
871 package, which means it is not necessary to
873 if (Cache
[Pkg
].InstallVer
!= Ver
&& Start
.IsNegative() == true)
876 clog
<< " Conflicts//Breaks against version "
877 << Ver
.VerStr() << " for " << Pkg
.Name()
878 << " but that is not InstVer, ignoring"
884 clog
<< " Considering " << Pkg
.FullName(false) << ' ' << Scores
[Pkg
->ID
] <<
885 " as a solution to " << I
.FullName(false) << ' ' << Scores
[I
->ID
] << endl
;
887 /* Try to fix the package under consideration rather than
888 fiddle with the VList package */
889 if (Scores
[I
->ID
] <= Scores
[Pkg
->ID
] ||
890 ((Cache
[Start
] & pkgDepCache::DepNow
) == 0 &&
891 End
.IsNegative() == false))
893 // Try a little harder to fix protected packages..
894 if ((Flags
[I
->ID
] & Protected
) == Protected
)
896 if (DoUpgrade(Pkg
) == true)
898 if (Scores
[Pkg
->ID
] > Scores
[I
->ID
])
899 Scores
[Pkg
->ID
] = Scores
[I
->ID
];
906 /* See if a keep will do, unless the package is protected,
907 then installing it will be necessary */
908 bool Installed
= Cache
[I
].Install();
909 Cache
.MarkKeep(I
, false, false);
910 if (Cache
[I
].InstBroken() == false)
912 // Unwind operation will be keep now
913 if (OrOp
== OrRemove
)
917 if (InOr
== true && Installed
== true)
918 Cache
.MarkInstall(I
, false, 0, false);
921 clog
<< " Holding Back " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
925 if (BrokenFix
== false || DoUpgrade(I
) == false)
927 // Consider other options
928 if (InOr
== false || Cache
[I
].Garbage
== true)
931 clog
<< " Removing " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
932 Cache
.MarkDelete(I
, false, 0, false);
933 if (Counter
> 1 && Scores
[Pkg
->ID
] > Scores
[I
->ID
])
934 Scores
[I
->ID
] = Scores
[Pkg
->ID
];
936 else if (TryFixByInstall
== true &&
937 Start
.TargetPkg()->CurrentVer
== 0 &&
938 Cache
[Start
.TargetPkg()].Delete() == false &&
939 (Flags
[Start
.TargetPkg()->ID
] & ToRemove
) != ToRemove
&&
940 Cache
.GetCandidateVer(Start
.TargetPkg()).end() == false)
942 /* Before removing or keeping the package with the broken dependency
943 try instead to install the first not previously installed package
944 solving this dependency. This helps every time a previous solver
945 is removed by the resolver because of a conflict or alike but it is
946 dangerous as it could trigger new breaks/conflicts… */
948 clog
<< " Try Installing " << Start
.TargetPkg() << " before changing " << I
.FullName(false) << std::endl
;
949 unsigned long const OldBroken
= Cache
.BrokenCount();
950 Cache
.MarkInstall(Start
.TargetPkg(), true, 1, false);
951 // FIXME: we should undo the complete MarkInstall process here
952 if (Cache
[Start
.TargetPkg()].InstBroken() == true || Cache
.BrokenCount() > OldBroken
)
953 Cache
.MarkDelete(Start
.TargetPkg(), false, 1, false);
964 if (Start
->Type
== pkgCache::Dep::DpkgBreaks
)
966 // first, try upgradring the package, if that
967 // does not help, the breaks goes onto the
970 // FIXME: use DoUpgrade(Pkg) instead?
971 if (Cache
[End
] & pkgDepCache::DepGCVer
)
974 clog
<< " Upgrading " << Pkg
.FullName(false) << " due to Breaks field in " << I
.FullName(false) << endl
;
975 Cache
.MarkInstall(Pkg
, false, 0, false);
980 // Skip adding to the kill list if it is protected
981 if ((Flags
[Pkg
->ID
] & Protected
) != 0)
985 clog
<< " Added " << Pkg
.FullName(false) << " to the remove list" << endl
;
991 if (Start
.IsNegative() == false)
996 // Hm, nothing can possibly satisify this dep. Nuke it.
998 Start
.IsNegative() == false &&
999 (Flags
[I
->ID
] & Protected
) != Protected
)
1001 bool Installed
= Cache
[I
].Install();
1003 if (Cache
[I
].InstBroken() == false)
1005 // Unwind operation will be keep now
1006 if (OrOp
== OrRemove
)
1010 if (InOr
== true && Installed
== true)
1011 Cache
.MarkInstall(I
, false, 0, false);
1014 clog
<< " Holding Back " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1019 clog
<< " Removing " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1021 Cache
.MarkDelete(I
, false, 0, false);
1036 // Apply the kill list now
1037 if (Cache
[I
].InstallVer
!= 0)
1039 for (PackageKill
*J
= KillList
; J
!= LEnd
; J
++)
1042 if ((Cache
[J
->Dep
] & pkgDepCache::DepGNow
) == 0)
1044 if (J
->Dep
.IsNegative() == true)
1047 clog
<< " Fixing " << I
.FullName(false) << " via remove of " << J
->Pkg
.FullName(false) << endl
;
1048 Cache
.MarkDelete(J
->Pkg
, false, 0, false);
1054 clog
<< " Fixing " << I
.FullName(false) << " via keep of " << J
->Pkg
.FullName(false) << endl
;
1055 Cache
.MarkKeep(J
->Pkg
, false, false);
1060 if (Scores
[I
->ID
] > Scores
[J
->Pkg
->ID
])
1061 Scores
[J
->Pkg
->ID
] = Scores
[I
->ID
];
1069 clog
<< "Done" << endl
;
1071 if (Cache
.BrokenCount() != 0)
1073 // See if this is the result of a hold
1074 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1075 for (;I
.end() != true; ++I
)
1077 if (Cache
[I
].InstBroken() == false)
1079 if ((Flags
[I
->ID
] & Protected
) != Protected
)
1080 return _error
->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
1082 return _error
->Error(_("Unable to correct problems, you have held broken packages."));
1085 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
1086 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1087 for (;I
.end() != true; ++I
) {
1088 if (Cache
[I
].NewInstall() && !(Flags
[I
->ID
] & PreInstalled
)) {
1089 if(_config
->FindI("Debug::pkgAutoRemove",false)) {
1090 std::clog
<< "Resolve installed new pkg: " << I
.FullName(false)
1091 << " (now marking it as auto)" << std::endl
;
1093 Cache
[I
].Flags
|= pkgCache::Flag::Auto
;
1101 // ProblemResolver::BreaksInstOrPolicy - Check if the given pkg is broken/*{{{*/
1102 // ---------------------------------------------------------------------
1103 /* This checks if the given package is broken either by a hard dependency
1104 (InstBroken()) or by introducing a new policy breakage e.g. new
1105 unsatisfied recommends for a package that was in "policy-good" state
1107 Note that this is not perfect as it will ignore further breakage
1108 for already broken policy (recommends)
1110 bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I
)
1112 // a broken install is always a problem
1113 if (Cache
[I
].InstBroken() == true)
1116 std::clog
<< " Dependencies are not satisfied for " << I
<< std::endl
;
1120 // a newly broken policy (recommends/suggests) is a problem
1121 if (Cache
[I
].NowPolicyBroken() == false &&
1122 Cache
[I
].InstPolicyBroken() == true)
1125 std::clog
<< " Policy breaks with upgrade of " << I
<< std::endl
;
1132 // ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1133 // ---------------------------------------------------------------------
1134 /* This is the work horse of the soft upgrade routine. It is very gental
1135 in that it does not install or remove any packages. It is assumed that the
1136 system was non-broken previously. */
1137 bool pkgProblemResolver::ResolveByKeep(OpProgress
* const Progress
)
1139 std::string
const solver
= _config
->Find("APT::Solver", "internal");
1140 if (solver
!= "internal")
1141 return EDSP::ResolveExternal(solver
.c_str(), Cache
, true, false, false, Progress
);
1142 return ResolveByKeepInternal();
1145 // ProblemResolver::ResolveByKeepInternal - Resolve problems using keep /*{{{*/
1146 // ---------------------------------------------------------------------
1147 /* This is the work horse of the soft upgrade routine. It is very gental
1148 in that it does not install or remove any packages. It is assumed that the
1149 system was non-broken previously. */
1150 bool pkgProblemResolver::ResolveByKeepInternal()
1152 pkgDepCache::ActionGroup
group(Cache
);
1154 unsigned long Size
= Cache
.Head().PackageCount
;
1158 /* We have to order the packages so that the broken fixing pass
1159 operates from highest score to lowest. This prevents problems when
1160 high score packages cause the removal of lower score packages that
1161 would cause the removal of even lower score packages. */
1162 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
1163 pkgCache::Package
**PEnd
= PList
;
1164 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1167 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
1169 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1171 clog
<< "Show Scores" << endl
;
1172 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1173 if (Scores
[(*K
)->ID
] != 0)
1175 pkgCache::PkgIterator
Pkg(Cache
,*K
);
1176 clog
<< Scores
[(*K
)->ID
] << ' ' << Pkg
<< std::endl
;
1181 clog
<< "Entering ResolveByKeep" << endl
;
1183 // Consider each broken package
1184 pkgCache::Package
**LastStop
= 0;
1185 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1187 pkgCache::PkgIterator
I(Cache
,*K
);
1189 if (Cache
[I
].InstallVer
== 0)
1192 if (InstOrNewPolicyBroken(I
) == false)
1195 /* Keep the package. If this works then great, otherwise we have
1196 to be significantly more aggressive and manipulate its dependencies */
1197 if ((Flags
[I
->ID
] & Protected
) == 0)
1200 clog
<< "Keeping package " << I
.FullName(false) << endl
;
1201 Cache
.MarkKeep(I
, false, false);
1202 if (InstOrNewPolicyBroken(I
) == false)
1209 // Isolate the problem dependencies
1210 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
1214 D
.GlobOr(Start
,End
);
1216 // We only worry about critical deps.
1217 if (End
.IsCritical() != true)
1221 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
1224 /* Hm, the group is broken.. I suppose the best thing to do is to
1225 is to try every combination of keep/not-keep for the set, but thats
1226 slow, and this never happens, just be conservative and assume the
1227 list of ors is in preference and keep till it starts to work. */
1231 clog
<< "Package " << I
.FullName(false) << " " << Start
<< endl
;
1233 // Look at all the possible provides on this package
1234 std::unique_ptr
<pkgCache::Version
*[]> VList(Start
.AllTargets());
1235 for (pkgCache::Version
**V
= VList
.get(); *V
!= 0; V
++)
1237 pkgCache::VerIterator
Ver(Cache
,*V
);
1238 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
1240 // It is not keepable
1241 if (Cache
[Pkg
].InstallVer
== 0 ||
1242 Pkg
->CurrentVer
== 0)
1245 if ((Flags
[I
->ID
] & Protected
) == 0)
1248 clog
<< " Keeping Package " << Pkg
.FullName(false) << " due to " << Start
.DepType() << endl
;
1249 Cache
.MarkKeep(Pkg
, false, false);
1252 if (InstOrNewPolicyBroken(I
) == false)
1256 if (InstOrNewPolicyBroken(I
) == false)
1264 if (InstOrNewPolicyBroken(I
) == false)
1268 if (InstOrNewPolicyBroken(I
) == true)
1272 if (K
== LastStop
) {
1273 // I is an iterator based off our temporary package list,
1274 // so copy the name we need before deleting the temporary list
1275 std::string
const LoopingPackage
= I
.FullName(false);
1277 return _error
->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.", LoopingPackage
.c_str());
1287 // ProblemResolver::InstallProtect - deprecated cpu-eating no-op /*{{{*/
1288 // ---------------------------------------------------------------------
1289 /* Actions issued with FromUser bit set are protected from further
1290 modification (expect by other calls with FromUser set) nowadays , so we
1291 don't need to reissue actions here, they are already set in stone. */
1292 void pkgProblemResolver::InstallProtect()
1294 pkgDepCache::ActionGroup
group(Cache
);
1296 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1298 if ((Flags
[I
->ID
] & Protected
) == Protected
)
1300 if ((Flags
[I
->ID
] & ToRemove
) == ToRemove
)
1301 Cache
.MarkDelete(I
);
1304 // preserve the information whether the package was auto
1305 // or manually installed
1306 bool autoInst
= (Cache
[I
].Flags
& pkgCache::Flag::Auto
);
1307 Cache
.MarkInstall(I
, false, 0, !autoInst
);
1313 // PrioSortList - Sort a list of versions by priority /*{{{*/
1314 // ---------------------------------------------------------------------
1315 /* This is ment to be used in conjunction with AllTargets to get a list
1316 of versions ordered by preference. */
1317 static pkgCache
*PrioCache
;
1318 static int PrioComp(const void *A
,const void *B
)
1320 pkgCache::VerIterator
L(*PrioCache
,*(pkgCache::Version
**)A
);
1321 pkgCache::VerIterator
R(*PrioCache
,*(pkgCache::Version
**)B
);
1323 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
&&
1324 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
)
1326 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
1327 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
1330 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
&&
1331 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
1333 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
&&
1334 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
1337 if (L
->Priority
!= R
->Priority
)
1338 return R
->Priority
- L
->Priority
;
1339 return strcmp(L
.ParentPkg().Name(),R
.ParentPkg().Name());
1341 void pkgPrioSortList(pkgCache
&Cache
,pkgCache::Version
**List
)
1343 unsigned long Count
= 0;
1345 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
1347 qsort(List
,Count
,sizeof(*List
),PrioComp
);