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/version.h>
23 #include <apt-pkg/sptr.h>
24 #include <apt-pkg/acquire-item.h>
25 #include <apt-pkg/edsp.h>
26 #include <apt-pkg/sourcelist.h>
27 #include <apt-pkg/fileutl.h>
28 #include <apt-pkg/progress.h>
30 #include <sys/types.h>
40 pkgProblemResolver
*pkgProblemResolver::This
= 0;
42 // Simulate::Simulate - Constructor /*{{{*/
43 // ---------------------------------------------------------------------
44 /* The legacy translations here of input Pkg iterators is obsolete,
45 this is not necessary since the pkgCaches are fully shared now. */
46 pkgSimulate::pkgSimulate(pkgDepCache
*Cache
) : pkgPackageManager(Cache
),
48 Sim(&Cache
->GetCache(),&iPolicy
),
52 Flags
= new unsigned char[Cache
->Head().PackageCount
];
53 memset(Flags
,0,sizeof(*Flags
)*Cache
->Head().PackageCount
);
55 // Fake a filename so as not to activate the media swapping
56 string Jnk
= "SIMULATE";
57 for (unsigned int I
= 0; I
!= Cache
->Head().PackageCount
; I
++)
61 // Simulate::~Simulate - Destructor /*{{{*/
62 pkgSimulate::~pkgSimulate()
67 // Simulate::Describe - Describe a package /*{{{*/
68 // ---------------------------------------------------------------------
69 /* Parameter Current == true displays the current package version,
70 Parameter Candidate == true displays the candidate package version */
71 void pkgSimulate::Describe(PkgIterator Pkg
,ostream
&out
,bool Current
,bool Candidate
)
75 out
<< Pkg
.FullName(true);
79 Ver
= Pkg
.CurrentVer();
80 if (Ver
.end() == false)
81 out
<< " [" << Ver
.VerStr() << ']';
84 if (Candidate
== true)
86 Ver
= Sim
[Pkg
].CandidateVerIter(Sim
);
87 if (Ver
.end() == true)
90 out
<< " (" << Ver
.VerStr() << ' ' << Ver
.RelStr() << ')';
94 // Simulate::Install - Simulate unpacking of a package /*{{{*/
95 // ---------------------------------------------------------------------
97 bool pkgSimulate::Install(PkgIterator iPkg
,string
/*File*/)
100 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
104 Describe(Pkg
,cout
,true,true);
105 Sim
.MarkInstall(Pkg
,false);
107 // Look for broken conflicts+predepends.
108 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; ++I
)
110 if (Sim
[I
].InstallVer
== 0)
113 for (DepIterator D
= Sim
[I
].InstVerIter(Sim
).DependsList(); D
.end() == false;)
118 if (Start
.IsNegative() == true ||
119 End
->Type
== pkgCache::Dep::PreDepends
)
121 if ((Sim
[End
] & pkgDepCache::DepGInstall
) == 0)
123 cout
<< " [" << I
.FullName(false) << " on " << Start
.TargetPkg().FullName(false) << ']';
124 if (Start
->Type
== pkgCache::Dep::Conflicts
)
125 _error
->Error("Fatal, conflicts violated %s",I
.FullName(false).c_str());
131 if (Sim
.BrokenCount() != 0)
138 // Simulate::Configure - Simulate configuration of a Package /*{{{*/
139 // ---------------------------------------------------------------------
140 /* This is not an acurate simulation of relatity, we should really not
141 install the package.. For some investigations it may be necessary
143 bool pkgSimulate::Configure(PkgIterator iPkg
)
145 // Adapt the iterator
146 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
150 if (Sim
[Pkg
].InstBroken() == true)
152 cout
<< "Conf " << Pkg
.FullName(false) << " broken" << endl
;
156 // Print out each package and the failed dependencies
157 for (pkgCache::DepIterator D
= Sim
[Pkg
].InstVerIter(Sim
).DependsList(); D
.end() == false; ++D
)
159 if (Sim
.IsImportantDep(D
) == false ||
160 (Sim
[D
] & pkgDepCache::DepInstall
) != 0)
163 if (D
->Type
== pkgCache::Dep::Obsoletes
)
164 cout
<< " Obsoletes:" << D
.TargetPkg().FullName(false);
165 else if (D
->Type
== pkgCache::Dep::Conflicts
)
166 cout
<< " Conflicts:" << D
.TargetPkg().FullName(false);
167 else if (D
->Type
== pkgCache::Dep::DpkgBreaks
)
168 cout
<< " Breaks:" << D
.TargetPkg().FullName(false);
170 cout
<< " Depends:" << D
.TargetPkg().FullName(false);
174 _error
->Error("Conf Broken %s",Pkg
.FullName(false).c_str());
179 Describe(Pkg
,cout
,false,true);
182 if (Sim
.BrokenCount() != 0)
190 // Simulate::Remove - Simulate the removal of a package /*{{{*/
191 // ---------------------------------------------------------------------
193 bool pkgSimulate::Remove(PkgIterator iPkg
,bool Purge
)
195 // Adapt the iterator
196 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name(), iPkg
.Arch());
197 if (Pkg
.end() == true)
199 std::cerr
<< (Purge
? "Purg" : "Remv") << " invalid package " << iPkg
.FullName() << std::endl
;
210 Describe(Pkg
,cout
,true,false);
212 if (Sim
.BrokenCount() != 0)
220 // Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
221 // ---------------------------------------------------------------------
223 void pkgSimulate::ShortBreaks()
226 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; ++I
)
228 if (Sim
[I
].InstBroken() == true)
230 if (Flags
[I
->ID
] == 0)
231 cout
<< I
.FullName(false) << ' ';
233 cout << I.Name() << "! ";*/
239 // ApplyStatus - Adjust for non-ok packages /*{{{*/
240 // ---------------------------------------------------------------------
241 /* We attempt to change the state of the all packages that have failed
242 installation toward their real state. The ordering code will perform
243 the necessary calculations to deal with the problems. */
244 bool pkgApplyStatus(pkgDepCache
&Cache
)
246 pkgDepCache::ActionGroup
group(Cache
);
248 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
250 if (I
->VersionList
== 0)
253 // Only choice for a ReInstReq package is to reinstall
254 if (I
->InstState
== pkgCache::State::ReInstReq
||
255 I
->InstState
== pkgCache::State::HoldReInstReq
)
257 if (I
->CurrentVer
!= 0 && I
.CurrentVer().Downloadable() == true)
258 Cache
.MarkKeep(I
, false, false);
261 // Is this right? Will dpkg choke on an upgrade?
262 if (Cache
[I
].CandidateVer
!= 0 &&
263 Cache
[I
].CandidateVerIter(Cache
).Downloadable() == true)
264 Cache
.MarkInstall(I
, false, 0, false);
266 return _error
->Error(_("The package %s needs to be reinstalled, "
267 "but I can't find an archive for it."),I
.FullName(true).c_str());
273 switch (I
->CurrentState
)
275 /* This means installation failed somehow - it does not need to be
276 re-unpacked (probably) */
277 case pkgCache::State::UnPacked
:
278 case pkgCache::State::HalfConfigured
:
279 case pkgCache::State::TriggersAwaited
:
280 case pkgCache::State::TriggersPending
:
281 if ((I
->CurrentVer
!= 0 && I
.CurrentVer().Downloadable() == true) ||
282 I
.State() != pkgCache::PkgIterator::NeedsUnpack
)
283 Cache
.MarkKeep(I
, false, false);
286 if (Cache
[I
].CandidateVer
!= 0 &&
287 Cache
[I
].CandidateVerIter(Cache
).Downloadable() == true)
288 Cache
.MarkInstall(I
, true, 0, false);
290 Cache
.MarkDelete(I
, false, 0, false);
294 // This means removal failed
295 case pkgCache::State::HalfInstalled
:
296 Cache
.MarkDelete(I
, false, 0, false);
300 if (I
->InstState
!= pkgCache::State::Ok
)
301 return _error
->Error("The package %s is not ok and I "
302 "don't know how to fix it!",I
.FullName(false).c_str());
308 // FixBroken - Fix broken packages /*{{{*/
309 // ---------------------------------------------------------------------
310 /* This autoinstalls every broken package and then runs the problem resolver
312 bool pkgFixBroken(pkgDepCache
&Cache
)
314 pkgDepCache::ActionGroup
group(Cache
);
316 // Auto upgrade all broken packages
317 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
318 if (Cache
[I
].NowBroken() == true)
319 Cache
.MarkInstall(I
, true, 0, false);
321 /* Fix packages that are in a NeedArchive state but don't have a
322 downloadable install version */
323 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
325 if (I
.State() != pkgCache::PkgIterator::NeedsUnpack
||
326 Cache
[I
].Delete() == true)
329 if (Cache
[I
].InstVerIter(Cache
).Downloadable() == false)
332 Cache
.MarkInstall(I
, true, 0, false);
335 pkgProblemResolver
Fix(&Cache
);
336 return Fix
.Resolve(true);
339 // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
340 // ---------------------------------------------------------------------
342 pkgProblemResolver::pkgProblemResolver(pkgDepCache
*pCache
) : d(NULL
), Cache(*pCache
)
345 unsigned long Size
= Cache
.Head().PackageCount
;
346 Scores
= new int[Size
];
347 Flags
= new unsigned char[Size
];
348 memset(Flags
,0,sizeof(*Flags
)*Size
);
350 // Set debug to true to see its decision logic
351 Debug
= _config
->FindB("Debug::pkgProblemResolver",false);
354 // ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
355 // ---------------------------------------------------------------------
357 pkgProblemResolver::~pkgProblemResolver()
363 // ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
364 // ---------------------------------------------------------------------
366 int pkgProblemResolver::ScoreSort(const void *a
,const void *b
)
368 Package
const **A
= (Package
const **)a
;
369 Package
const **B
= (Package
const **)b
;
370 if (This
->Scores
[(*A
)->ID
] > This
->Scores
[(*B
)->ID
])
372 if (This
->Scores
[(*A
)->ID
] < This
->Scores
[(*B
)->ID
])
377 // ProblemResolver::MakeScores - Make the score table /*{{{*/
378 // ---------------------------------------------------------------------
380 void pkgProblemResolver::MakeScores()
382 unsigned long Size
= Cache
.Head().PackageCount
;
383 memset(Scores
,0,sizeof(*Scores
)*Size
);
385 // maps to pkgCache::State::VerPriority:
386 // Required Important Standard Optional Extra
389 _config
->FindI("pkgProblemResolver::Scores::Required",3),
390 _config
->FindI("pkgProblemResolver::Scores::Important",2),
391 _config
->FindI("pkgProblemResolver::Scores::Standard",1),
392 _config
->FindI("pkgProblemResolver::Scores::Optional",-1),
393 _config
->FindI("pkgProblemResolver::Scores::Extra",-2)
395 int PrioEssentials
= _config
->FindI("pkgProblemResolver::Scores::Essentials",100);
396 int PrioInstalledAndNotObsolete
= _config
->FindI("pkgProblemResolver::Scores::NotObsolete",1);
397 int PrioDepends
= _config
->FindI("pkgProblemResolver::Scores::Depends",1);
398 int PrioRecommends
= _config
->FindI("pkgProblemResolver::Scores::Recommends",1);
399 int AddProtected
= _config
->FindI("pkgProblemResolver::Scores::AddProtected",10000);
400 int AddEssential
= _config
->FindI("pkgProblemResolver::Scores::AddEssential",5000);
402 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
403 clog
<< "Settings used to calculate pkgProblemResolver::Scores::" << endl
404 << " Required => " << PrioMap
[pkgCache::State::Required
] << endl
405 << " Important => " << PrioMap
[pkgCache::State::Important
] << endl
406 << " Standard => " << PrioMap
[pkgCache::State::Standard
] << endl
407 << " Optional => " << PrioMap
[pkgCache::State::Optional
] << endl
408 << " Extra => " << PrioMap
[pkgCache::State::Extra
] << endl
409 << " Essentials => " << PrioEssentials
<< endl
410 << " InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete
<< endl
411 << " Depends => " << PrioDepends
<< endl
412 << " Recommends => " << PrioRecommends
<< endl
413 << " AddProtected => " << AddProtected
<< endl
414 << " AddEssential => " << AddEssential
<< endl
;
416 // Generate the base scores for a package based on its properties
417 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
419 if (Cache
[I
].InstallVer
== 0)
422 int &Score
= Scores
[I
->ID
];
424 /* This is arbitrary, it should be high enough to elevate an
425 essantial package above most other packages but low enough
426 to allow an obsolete essential packages to be removed by
427 a conflicts on a powerfull normal package (ie libc6) */
428 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
429 || (I
->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
430 Score
+= PrioEssentials
;
432 // We transform the priority
433 if (Cache
[I
].InstVerIter(Cache
)->Priority
<= 5)
434 Score
+= PrioMap
[Cache
[I
].InstVerIter(Cache
)->Priority
];
436 /* This helps to fix oddball problems with conflicting packages
437 on the same level. We enhance the score of installed packages
438 if those are not obsolete
440 if (I
->CurrentVer
!= 0 && Cache
[I
].CandidateVer
!= 0 && Cache
[I
].CandidateVerIter(Cache
).Downloadable())
441 Score
+= PrioInstalledAndNotObsolete
;
444 // Now that we have the base scores we go and propogate dependencies
445 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
447 if (Cache
[I
].InstallVer
== 0)
450 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false; ++D
)
452 if (D
->Type
== pkgCache::Dep::Depends
||
453 D
->Type
== pkgCache::Dep::PreDepends
)
454 Scores
[D
.TargetPkg()->ID
] += PrioDepends
;
455 else if (D
->Type
== pkgCache::Dep::Recommends
)
456 Scores
[D
.TargetPkg()->ID
] += PrioRecommends
;
460 // Copy the scores to advoid additive looping
461 SPtrArray
<int> OldScores
= new int[Size
];
462 memcpy(OldScores
,Scores
,sizeof(*Scores
)*Size
);
464 /* Now we cause 1 level of dependency inheritance, that is we add the
465 score of the packages that depend on the target Package. This
466 fortifies high scoring packages */
467 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
469 if (Cache
[I
].InstallVer
== 0)
472 for (pkgCache::DepIterator D
= I
.RevDependsList(); D
.end() == false; ++D
)
474 // Only do it for the install version
475 if ((pkgCache::Version
*)D
.ParentVer() != Cache
[D
.ParentPkg()].InstallVer
||
476 (D
->Type
!= pkgCache::Dep::Depends
&&
477 D
->Type
!= pkgCache::Dep::PreDepends
&&
478 D
->Type
!= pkgCache::Dep::Recommends
))
481 // Do not propagate negative scores otherwise
482 // an extra (-2) package might score better than an optional (-1)
483 if (OldScores
[D
.ParentPkg()->ID
] > 0)
484 Scores
[I
->ID
] += OldScores
[D
.ParentPkg()->ID
];
488 /* Now we propogate along provides. This makes the packages that
489 provide important packages extremely important */
490 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
492 for (pkgCache::PrvIterator P
= I
.ProvidesList(); P
.end() == false; ++P
)
494 // Only do it once per package
495 if ((pkgCache::Version
*)P
.OwnerVer() != Cache
[P
.OwnerPkg()].InstallVer
)
497 Scores
[P
.OwnerPkg()->ID
] += abs(Scores
[I
->ID
] - OldScores
[I
->ID
]);
501 /* Protected things are pushed really high up. This number should put them
502 ahead of everything */
503 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
505 if ((Flags
[I
->ID
] & Protected
) != 0)
506 Scores
[I
->ID
] += AddProtected
;
507 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
||
508 (I
->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
509 Scores
[I
->ID
] += AddEssential
;
513 // ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
514 // ---------------------------------------------------------------------
515 /* This goes through and tries to reinstall packages to make this package
517 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg
)
519 pkgDepCache::ActionGroup
group(Cache
);
521 if ((Flags
[Pkg
->ID
] & Upgradable
) == 0 || Cache
[Pkg
].Upgradable() == false)
523 if ((Flags
[Pkg
->ID
] & Protected
) == Protected
)
526 Flags
[Pkg
->ID
] &= ~Upgradable
;
528 bool WasKept
= Cache
[Pkg
].Keep();
529 Cache
.MarkInstall(Pkg
, false, 0, false);
531 // This must be a virtual package or something like that.
532 if (Cache
[Pkg
].InstVerIter(Cache
).end() == true)
535 // Isolate the problem dependency
537 for (pkgCache::DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
539 // Compute a single dependency element (glob or)
540 pkgCache::DepIterator Start
= D
;
541 pkgCache::DepIterator End
= D
;
542 for (bool LastOR
= true; D
.end() == false && LastOR
== true;)
544 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
550 // We only worry about critical deps.
551 if (End
.IsCritical() != true)
554 // Iterate over all the members in the or group
558 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
561 // Do not change protected packages
562 PkgIterator P
= Start
.SmartTargetPkg();
563 if ((Flags
[P
->ID
] & Protected
) == Protected
)
566 clog
<< " Reinst Failed because of protected " << P
.FullName(false) << endl
;
571 // Upgrade the package if the candidate version will fix the problem.
572 if ((Cache
[Start
] & pkgDepCache::DepCVer
) == pkgDepCache::DepCVer
)
574 if (DoUpgrade(P
) == false)
577 clog
<< " Reinst Failed because of " << P
.FullName(false) << endl
;
588 /* We let the algorithm deal with conflicts on its next iteration,
589 it is much smarter than us */
590 if (Start
.IsNegative() == true)
594 clog
<< " Reinst Failed early because of " << Start
.TargetPkg().FullName(false) << endl
;
607 // Undo our operations - it might be smart to undo everything this did..
611 Cache
.MarkKeep(Pkg
, false, false);
613 Cache
.MarkDelete(Pkg
, false, 0, false);
618 clog
<< " Re-Instated " << Pkg
.FullName(false) << endl
;
622 // ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/
623 // ---------------------------------------------------------------------
625 bool pkgProblemResolver::Resolve(bool BrokenFix
)
627 std::string
const solver
= _config
->Find("APT::Solver", "internal");
628 if (solver
!= "internal") {
629 OpTextProgress
Prog(*_config
);
630 return EDSP::ResolveExternal(solver
.c_str(), Cache
, false, false, false, &Prog
);
632 return ResolveInternal(BrokenFix
);
635 // ProblemResolver::ResolveInternal - Run the resolution pass /*{{{*/
636 // ---------------------------------------------------------------------
637 /* This routines works by calculating a score for each package. The score
638 is derived by considering the package's priority and all reverse
639 dependents giving an integer that reflects the amount of breakage that
640 adjusting the package will inflict.
642 It goes from highest score to lowest and corrects all of the breaks by
643 keeping or removing the dependant packages. If that fails then it removes
644 the package itself and goes on. The routine should be able to intelligently
645 go from any broken state to a fixed state.
647 The BrokenFix flag enables a mode where the algorithm tries to
648 upgrade packages to advoid problems. */
649 bool pkgProblemResolver::ResolveInternal(bool const BrokenFix
)
651 pkgDepCache::ActionGroup
group(Cache
);
653 // Record which packages are marked for install
658 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
660 if (Cache
[I
].Install() == true)
661 Flags
[I
->ID
] |= PreInstalled
;
664 if (Cache
[I
].InstBroken() == true && BrokenFix
== true)
666 Cache
.MarkInstall(I
, false, 0, false);
667 if (Cache
[I
].Install() == true)
671 Flags
[I
->ID
] &= ~PreInstalled
;
673 Flags
[I
->ID
] |= Upgradable
;
676 while (Again
== true);
679 clog
<< "Starting pkgProblemResolver with broken count: "
680 << Cache
.BrokenCount() << endl
;
685 unsigned long const Size
= Cache
.Head().PackageCount
;
687 /* We have to order the packages so that the broken fixing pass
688 operates from highest score to lowest. This prevents problems when
689 high score packages cause the removal of lower score packages that
690 would cause the removal of even lower score packages. */
691 SPtrArray
<pkgCache::Package
*> PList
= new pkgCache::Package
*[Size
];
692 pkgCache::Package
**PEnd
= PList
;
693 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
696 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
698 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
700 clog
<< "Show Scores" << endl
;
701 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
702 if (Scores
[(*K
)->ID
] != 0)
704 pkgCache::PkgIterator
Pkg(Cache
,*K
);
705 clog
<< Scores
[(*K
)->ID
] << ' ' << Pkg
<< std::endl
;
710 clog
<< "Starting 2 pkgProblemResolver with broken count: "
711 << Cache
.BrokenCount() << endl
;
714 /* Now consider all broken packages. For each broken package we either
715 remove the package or fix it's problem. We do this once, it should
716 not be possible for a loop to form (that is a < b < c and fixing b by
717 changing a breaks c) */
719 bool const TryFixByInstall
= _config
->FindB("pkgProblemResolver::FixByInstall", true);
720 for (int Counter
= 0; Counter
!= 10 && Change
== true; Counter
++)
723 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
725 pkgCache::PkgIterator
I(Cache
,*K
);
727 /* We attempt to install this and see if any breaks result,
728 this takes care of some strange cases */
729 if (Cache
[I
].CandidateVer
!= Cache
[I
].InstallVer
&&
730 I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0 &&
731 (Flags
[I
->ID
] & PreInstalled
) != 0 &&
732 (Flags
[I
->ID
] & Protected
) == 0 &&
733 (Flags
[I
->ID
] & ReInstateTried
) == 0)
736 clog
<< " Try to Re-Instate (" << Counter
<< ") " << I
.FullName(false) << endl
;
737 unsigned long OldBreaks
= Cache
.BrokenCount();
738 pkgCache::Version
*OldVer
= Cache
[I
].InstallVer
;
739 Flags
[I
->ID
] &= ReInstateTried
;
741 Cache
.MarkInstall(I
, false, 0, false);
742 if (Cache
[I
].InstBroken() == true ||
743 OldBreaks
< Cache
.BrokenCount())
746 Cache
.MarkDelete(I
, false, 0, false);
748 Cache
.MarkKeep(I
, false, false);
752 clog
<< "Re-Instated " << I
.FullName(false) << " (" << OldBreaks
<< " vs " << Cache
.BrokenCount() << ')' << endl
;
755 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
759 clog
<< "Investigating (" << Counter
<< ") " << I
<< endl
;
761 // Isolate the problem dependency
762 PackageKill KillList
[100];
763 PackageKill
*LEnd
= KillList
;
765 pkgCache::DepIterator Start
;
766 pkgCache::DepIterator End
;
767 PackageKill
*OldEnd
= LEnd
;
769 enum {OrRemove
,OrKeep
} OrOp
= OrRemove
;
770 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList();
771 D
.end() == false || InOr
== true;)
773 // Compute a single dependency element (glob or)
777 if (InOr
== true && OldEnd
== LEnd
)
779 if (OrOp
== OrRemove
)
781 if ((Flags
[I
->ID
] & Protected
) != Protected
)
784 clog
<< " Or group remove for " << I
.FullName(false) << endl
;
785 Cache
.MarkDelete(I
, false, 0, false);
789 else if (OrOp
== OrKeep
)
792 clog
<< " Or group keep for " << I
.FullName(false) << endl
;
793 Cache
.MarkKeep(I
, false, false);
798 /* We do an extra loop (as above) to finalize the or group
803 if (Start
.end() == true)
806 // We only worry about critical deps.
807 if (End
.IsCritical() != true)
816 // We only worry about critical deps.
817 if (Start
.IsCritical() != true)
822 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
829 clog
<< "Broken " << Start
<< endl
;
831 /* Look across the version list. If there are no possible
832 targets then we keep the package and bail. This is necessary
833 if a package has a dep on another package that cant be found */
834 SPtrArray
<pkgCache::Version
*> VList
= Start
.AllTargets();
835 if (*VList
== 0 && (Flags
[I
->ID
] & Protected
) != Protected
&&
836 Start
.IsNegative() == false &&
837 Cache
[I
].NowBroken() == false)
841 /* No keep choice because the keep being OK could be the
842 result of another element in the OR group! */
847 Cache
.MarkKeep(I
, false, false);
852 for (pkgCache::Version
**V
= VList
; *V
!= 0; V
++)
854 pkgCache::VerIterator
Ver(Cache
,*V
);
855 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
857 /* This is a conflicts, and the version we are looking
858 at is not the currently selected version of the
859 package, which means it is not necessary to
861 if (Cache
[Pkg
].InstallVer
!= Ver
&& Start
.IsNegative() == true)
864 clog
<< " Conflicts//Breaks against version "
865 << Ver
.VerStr() << " for " << Pkg
.Name()
866 << " but that is not InstVer, ignoring"
872 clog
<< " Considering " << Pkg
.FullName(false) << ' ' << (int)Scores
[Pkg
->ID
] <<
873 " as a solution to " << I
.FullName(false) << ' ' << (int)Scores
[I
->ID
] << endl
;
875 /* Try to fix the package under consideration rather than
876 fiddle with the VList package */
877 if (Scores
[I
->ID
] <= Scores
[Pkg
->ID
] ||
878 ((Cache
[Start
] & pkgDepCache::DepNow
) == 0 &&
879 End
.IsNegative() == false))
881 // Try a little harder to fix protected packages..
882 if ((Flags
[I
->ID
] & Protected
) == Protected
)
884 if (DoUpgrade(Pkg
) == true)
886 if (Scores
[Pkg
->ID
] > Scores
[I
->ID
])
887 Scores
[Pkg
->ID
] = Scores
[I
->ID
];
894 /* See if a keep will do, unless the package is protected,
895 then installing it will be necessary */
896 bool Installed
= Cache
[I
].Install();
897 Cache
.MarkKeep(I
, false, false);
898 if (Cache
[I
].InstBroken() == false)
900 // Unwind operation will be keep now
901 if (OrOp
== OrRemove
)
905 if (InOr
== true && Installed
== true)
906 Cache
.MarkInstall(I
, false, 0, false);
909 clog
<< " Holding Back " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
913 if (BrokenFix
== false || DoUpgrade(I
) == false)
915 // Consider other options
916 if (InOr
== false || Cache
[I
].Garbage
== true)
919 clog
<< " Removing " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
920 Cache
.MarkDelete(I
, false, 0, false);
921 if (Counter
> 1 && Scores
[Pkg
->ID
] > Scores
[I
->ID
])
922 Scores
[I
->ID
] = Scores
[Pkg
->ID
];
924 else if (TryFixByInstall
== true &&
925 Start
.TargetPkg()->CurrentVer
== 0 &&
926 Cache
[Start
.TargetPkg()].Delete() == false &&
927 (Flags
[Start
.TargetPkg()->ID
] & ToRemove
) != ToRemove
&&
928 Cache
.GetCandidateVer(Start
.TargetPkg()).end() == false)
930 /* Before removing or keeping the package with the broken dependency
931 try instead to install the first not previously installed package
932 solving this dependency. This helps every time a previous solver
933 is removed by the resolver because of a conflict or alike but it is
934 dangerous as it could trigger new breaks/conflicts… */
936 clog
<< " Try Installing " << Start
.TargetPkg() << " before changing " << I
.FullName(false) << std::endl
;
937 unsigned long const OldBroken
= Cache
.BrokenCount();
938 Cache
.MarkInstall(Start
.TargetPkg(), true, 1, false);
939 // FIXME: we should undo the complete MarkInstall process here
940 if (Cache
[Start
.TargetPkg()].InstBroken() == true || Cache
.BrokenCount() > OldBroken
)
941 Cache
.MarkDelete(Start
.TargetPkg(), false, 1, false);
952 if (Start
->Type
== pkgCache::Dep::DpkgBreaks
)
954 // first, try upgradring the package, if that
955 // does not help, the breaks goes onto the
958 // FIXME: use DoUpgrade(Pkg) instead?
959 if (Cache
[End
] & pkgDepCache::DepGCVer
)
962 clog
<< " Upgrading " << Pkg
.FullName(false) << " due to Breaks field in " << I
.FullName(false) << endl
;
963 Cache
.MarkInstall(Pkg
, false, 0, false);
968 // Skip adding to the kill list if it is protected
969 if ((Flags
[Pkg
->ID
] & Protected
) != 0)
973 clog
<< " Added " << Pkg
.FullName(false) << " to the remove list" << endl
;
979 if (Start
.IsNegative() == false)
984 // Hm, nothing can possibly satisify this dep. Nuke it.
986 Start
.IsNegative() == false &&
987 (Flags
[I
->ID
] & Protected
) != Protected
)
989 bool Installed
= Cache
[I
].Install();
991 if (Cache
[I
].InstBroken() == false)
993 // Unwind operation will be keep now
994 if (OrOp
== OrRemove
)
998 if (InOr
== true && Installed
== true)
999 Cache
.MarkInstall(I
, false, 0, false);
1002 clog
<< " Holding Back " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1007 clog
<< " Removing " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1009 Cache
.MarkDelete(I
, false, 0, false);
1024 // Apply the kill list now
1025 if (Cache
[I
].InstallVer
!= 0)
1027 for (PackageKill
*J
= KillList
; J
!= LEnd
; J
++)
1030 if ((Cache
[J
->Dep
] & pkgDepCache::DepGNow
) == 0)
1032 if (J
->Dep
.IsNegative() == true)
1035 clog
<< " Fixing " << I
.FullName(false) << " via remove of " << J
->Pkg
.FullName(false) << endl
;
1036 Cache
.MarkDelete(J
->Pkg
, false, 0, false);
1042 clog
<< " Fixing " << I
.FullName(false) << " via keep of " << J
->Pkg
.FullName(false) << endl
;
1043 Cache
.MarkKeep(J
->Pkg
, false, false);
1048 if (Scores
[I
->ID
] > Scores
[J
->Pkg
->ID
])
1049 Scores
[J
->Pkg
->ID
] = Scores
[I
->ID
];
1057 clog
<< "Done" << endl
;
1059 if (Cache
.BrokenCount() != 0)
1061 // See if this is the result of a hold
1062 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1063 for (;I
.end() != true; ++I
)
1065 if (Cache
[I
].InstBroken() == false)
1067 if ((Flags
[I
->ID
] & Protected
) != Protected
)
1068 return _error
->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
1070 return _error
->Error(_("Unable to correct problems, you have held broken packages."));
1073 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
1074 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1075 for (;I
.end() != true; ++I
) {
1076 if (Cache
[I
].NewInstall() && !(Flags
[I
->ID
] & PreInstalled
)) {
1077 if(_config
->FindI("Debug::pkgAutoRemove",false)) {
1078 std::clog
<< "Resolve installed new pkg: " << I
.FullName(false)
1079 << " (now marking it as auto)" << std::endl
;
1081 Cache
[I
].Flags
|= pkgCache::Flag::Auto
;
1089 // ProblemResolver::BreaksInstOrPolicy - Check if the given pkg is broken/*{{{*/
1090 // ---------------------------------------------------------------------
1091 /* This checks if the given package is broken either by a hard dependency
1092 (InstBroken()) or by introducing a new policy breakage e.g. new
1093 unsatisfied recommends for a package that was in "policy-good" state
1095 Note that this is not perfect as it will ignore further breakage
1096 for already broken policy (recommends)
1098 bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I
)
1100 // a broken install is always a problem
1101 if (Cache
[I
].InstBroken() == true)
1104 std::clog
<< " Dependencies are not satisfied for " << I
<< std::endl
;
1108 // a newly broken policy (recommends/suggests) is a problem
1109 if (Cache
[I
].NowPolicyBroken() == false &&
1110 Cache
[I
].InstPolicyBroken() == true)
1113 std::clog
<< " Policy breaks with upgrade of " << I
<< std::endl
;
1120 // ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1121 // ---------------------------------------------------------------------
1122 /* This is the work horse of the soft upgrade routine. It is very gental
1123 in that it does not install or remove any packages. It is assumed that the
1124 system was non-broken previously. */
1125 bool pkgProblemResolver::ResolveByKeep()
1127 std::string
const solver
= _config
->Find("APT::Solver", "internal");
1128 if (solver
!= "internal") {
1129 OpTextProgress
Prog(*_config
);
1130 return EDSP::ResolveExternal(solver
.c_str(), Cache
, true, false, false, &Prog
);
1132 return ResolveByKeepInternal();
1135 // ProblemResolver::ResolveByKeepInternal - Resolve problems using keep /*{{{*/
1136 // ---------------------------------------------------------------------
1137 /* This is the work horse of the soft upgrade routine. It is very gental
1138 in that it does not install or remove any packages. It is assumed that the
1139 system was non-broken previously. */
1140 bool pkgProblemResolver::ResolveByKeepInternal()
1142 pkgDepCache::ActionGroup
group(Cache
);
1144 unsigned long Size
= Cache
.Head().PackageCount
;
1148 /* We have to order the packages so that the broken fixing pass
1149 operates from highest score to lowest. This prevents problems when
1150 high score packages cause the removal of lower score packages that
1151 would cause the removal of even lower score packages. */
1152 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
1153 pkgCache::Package
**PEnd
= PList
;
1154 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1157 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
1159 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1161 clog
<< "Show Scores" << endl
;
1162 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1163 if (Scores
[(*K
)->ID
] != 0)
1165 pkgCache::PkgIterator
Pkg(Cache
,*K
);
1166 clog
<< Scores
[(*K
)->ID
] << ' ' << Pkg
<< std::endl
;
1171 clog
<< "Entering ResolveByKeep" << endl
;
1173 // Consider each broken package
1174 pkgCache::Package
**LastStop
= 0;
1175 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1177 pkgCache::PkgIterator
I(Cache
,*K
);
1179 if (Cache
[I
].InstallVer
== 0)
1182 if (InstOrNewPolicyBroken(I
) == false)
1185 /* Keep the package. If this works then great, otherwise we have
1186 to be significantly more agressive and manipulate its dependencies */
1187 if ((Flags
[I
->ID
] & Protected
) == 0)
1190 clog
<< "Keeping package " << I
.FullName(false) << endl
;
1191 Cache
.MarkKeep(I
, false, false);
1192 if (InstOrNewPolicyBroken(I
) == false)
1199 // Isolate the problem dependencies
1200 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
1204 D
.GlobOr(Start
,End
);
1206 // We only worry about critical deps.
1207 if (End
.IsCritical() != true)
1211 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
1214 /* Hm, the group is broken.. I suppose the best thing to do is to
1215 is to try every combination of keep/not-keep for the set, but thats
1216 slow, and this never happens, just be conservative and assume the
1217 list of ors is in preference and keep till it starts to work. */
1221 clog
<< "Package " << I
.FullName(false) << " " << Start
<< endl
;
1223 // Look at all the possible provides on this package
1224 SPtrArray
<pkgCache::Version
*> VList
= Start
.AllTargets();
1225 for (pkgCache::Version
**V
= VList
; *V
!= 0; V
++)
1227 pkgCache::VerIterator
Ver(Cache
,*V
);
1228 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
1230 // It is not keepable
1231 if (Cache
[Pkg
].InstallVer
== 0 ||
1232 Pkg
->CurrentVer
== 0)
1235 if ((Flags
[I
->ID
] & Protected
) == 0)
1238 clog
<< " Keeping Package " << Pkg
.FullName(false) << " due to " << Start
.DepType() << endl
;
1239 Cache
.MarkKeep(Pkg
, false, false);
1242 if (InstOrNewPolicyBroken(I
) == false)
1246 if (InstOrNewPolicyBroken(I
) == false)
1254 if (InstOrNewPolicyBroken(I
) == false)
1258 if (InstOrNewPolicyBroken(I
) == true)
1262 if (K
== LastStop
) {
1263 // I is an iterator based off our temporary package list,
1264 // so copy the name we need before deleting the temporary list
1265 std::string
const LoopingPackage
= I
.FullName(false);
1267 return _error
->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.", LoopingPackage
.c_str());
1277 // ProblemResolver::InstallProtect - deprecated cpu-eating no-op /*{{{*/
1278 // ---------------------------------------------------------------------
1279 /* Actions issued with FromUser bit set are protected from further
1280 modification (expect by other calls with FromUser set) nowadays , so we
1281 don't need to reissue actions here, they are already set in stone. */
1282 void pkgProblemResolver::InstallProtect()
1284 pkgDepCache::ActionGroup
group(Cache
);
1286 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1288 if ((Flags
[I
->ID
] & Protected
) == Protected
)
1290 if ((Flags
[I
->ID
] & ToRemove
) == ToRemove
)
1291 Cache
.MarkDelete(I
);
1294 // preserve the information whether the package was auto
1295 // or manually installed
1296 bool autoInst
= (Cache
[I
].Flags
& pkgCache::Flag::Auto
);
1297 Cache
.MarkInstall(I
, false, 0, !autoInst
);
1303 // PrioSortList - Sort a list of versions by priority /*{{{*/
1304 // ---------------------------------------------------------------------
1305 /* This is ment to be used in conjunction with AllTargets to get a list
1306 of versions ordered by preference. */
1307 static pkgCache
*PrioCache
;
1308 static int PrioComp(const void *A
,const void *B
)
1310 pkgCache::VerIterator
L(*PrioCache
,*(pkgCache::Version
**)A
);
1311 pkgCache::VerIterator
R(*PrioCache
,*(pkgCache::Version
**)B
);
1313 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
&&
1314 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
)
1316 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
1317 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
1320 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
&&
1321 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
1323 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
&&
1324 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
1327 if (L
->Priority
!= R
->Priority
)
1328 return R
->Priority
- L
->Priority
;
1329 return strcmp(L
.ParentPkg().Name(),R
.ParentPkg().Name());
1331 void pkgPrioSortList(pkgCache
&Cache
,pkgCache::Version
**List
)
1333 unsigned long Count
= 0;
1335 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
1337 qsort(List
,Count
,sizeof(*List
),PrioComp
);
1340 // ListUpdate - construct Fetcher and update the cache files /*{{{*/
1341 // ---------------------------------------------------------------------
1342 /* This is a simple wrapper to update the cache. it will fetch stuff
1343 * from the network (or any other sources defined in sources.list)
1345 bool ListUpdate(pkgAcquireStatus
&Stat
,
1346 pkgSourceList
&List
,
1350 if (Fetcher
.Setup(&Stat
, _config
->FindDir("Dir::State::Lists")) == false)
1353 // Populate it with the source selection
1354 if (List
.GetIndexes(&Fetcher
) == false)
1357 return AcquireUpdate(Fetcher
, PulseInterval
, true);
1360 // AcquireUpdate - take Fetcher and update the cache files /*{{{*/
1361 // ---------------------------------------------------------------------
1362 /* This is a simple wrapper to update the cache with a provided acquire
1363 * If you only need control over Status and the used SourcesList use
1364 * ListUpdate method instead.
1366 bool AcquireUpdate(pkgAcquire
&Fetcher
, int const PulseInterval
,
1367 bool const RunUpdateScripts
, bool const ListCleanup
)
1370 if (RunUpdateScripts
== true)
1371 RunScripts("APT::Update::Pre-Invoke");
1373 pkgAcquire::RunResult res
;
1374 if(PulseInterval
> 0)
1375 res
= Fetcher
.Run(PulseInterval
);
1377 res
= Fetcher
.Run();
1379 if (res
== pkgAcquire::Failed
)
1382 bool Failed
= false;
1383 bool TransientNetworkFailure
= false;
1384 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin();
1385 I
!= Fetcher
.ItemsEnd(); ++I
)
1387 if ((*I
)->Status
== pkgAcquire::Item::StatDone
)
1392 ::URI
uri((*I
)->DescURI());
1394 uri
.Password
.clear();
1395 string descUri
= string(uri
);
1396 _error
->Warning(_("Failed to fetch %s %s\n"), descUri
.c_str(),
1397 (*I
)->ErrorText
.c_str());
1399 if ((*I
)->Status
== pkgAcquire::Item::StatTransientNetworkError
)
1401 TransientNetworkFailure
= true;
1408 // Clean out any old list files
1409 // Keep "APT::Get::List-Cleanup" name for compatibility, but
1410 // this is really a global option for the APT library now
1411 if (!TransientNetworkFailure
&& !Failed
&& ListCleanup
== true &&
1412 (_config
->FindB("APT::Get::List-Cleanup",true) == true &&
1413 _config
->FindB("APT::List-Cleanup",true) == true))
1415 if (Fetcher
.Clean(_config
->FindDir("Dir::State::lists")) == false ||
1416 Fetcher
.Clean(_config
->FindDir("Dir::State::lists") + "partial/") == false)
1417 // something went wrong with the clean
1421 if (TransientNetworkFailure
== true)
1422 _error
->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead."));
1423 else if (Failed
== true)
1424 return _error
->Error(_("Some index files failed to download. They have been ignored, or old ones used instead."));
1427 // Run the success scripts if all was fine
1428 if (RunUpdateScripts
== true)
1430 if(!TransientNetworkFailure
&& !Failed
)
1431 RunScripts("APT::Update::Post-Invoke-Success");
1433 // Run the other scripts
1434 RunScripts("APT::Update::Post-Invoke");