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 // DistUpgrade - Distribution upgrade /*{{{*/
340 // ---------------------------------------------------------------------
341 /* This autoinstalls every package and then force installs every
342 pre-existing package. This creates the initial set of conditions which
343 most likely contain problems because too many things were installed.
345 The problem resolver is used to resolve the problems.
347 bool pkgDistUpgrade(pkgDepCache
&Cache
)
349 std::string
const solver
= _config
->Find("APT::Solver", "internal");
350 if (solver
!= "internal") {
351 OpTextProgress
Prog(*_config
);
352 return EDSP::ResolveExternal(solver
.c_str(), Cache
, false, true, false, &Prog
);
355 pkgDepCache::ActionGroup
group(Cache
);
357 /* Upgrade all installed packages first without autoinst to help the resolver
358 in versioned or-groups to upgrade the old solver instead of installing
359 a new one (if the old solver is not the first one [anymore]) */
360 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
361 if (I
->CurrentVer
!= 0)
362 Cache
.MarkInstall(I
, false, 0, false);
364 /* Auto upgrade all installed packages, this provides the basis
365 for the installation */
366 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
367 if (I
->CurrentVer
!= 0)
368 Cache
.MarkInstall(I
, true, 0, false);
370 /* Now, install each essential package which is not installed
371 (and not provided by another package in the same name group) */
372 std::string essential
= _config
->Find("pkgCacheGen::Essential", "all");
373 if (essential
== "all")
375 for (pkgCache::GrpIterator G
= Cache
.GrpBegin(); G
.end() == false; ++G
)
377 bool isEssential
= false;
378 bool instEssential
= false;
379 for (pkgCache::PkgIterator P
= G
.PackageList(); P
.end() == false; P
= G
.NextPkg(P
))
381 if ((P
->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
)
384 if (Cache
[P
].Install() == true)
386 instEssential
= true;
390 if (isEssential
== false || instEssential
== true)
392 pkgCache::PkgIterator P
= G
.FindPreferredPkg();
393 Cache
.MarkInstall(P
, true, 0, false);
396 else if (essential
!= "none")
397 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
398 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
399 Cache
.MarkInstall(I
, true, 0, false);
401 /* We do it again over all previously installed packages to force
402 conflict resolution on them all. */
403 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
404 if (I
->CurrentVer
!= 0)
405 Cache
.MarkInstall(I
, false, 0, false);
407 pkgProblemResolver
Fix(&Cache
);
409 // Hold back held packages.
410 if (_config
->FindB("APT::Ignore-Hold",false) == false)
412 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
414 if (I
->SelectedState
== pkgCache::State::Hold
)
417 Cache
.MarkKeep(I
, false, false);
422 return Fix
.Resolve();
425 // AllUpgrade - Upgrade as many packages as possible /*{{{*/
426 // ---------------------------------------------------------------------
427 /* Right now the system must be consistent before this can be called.
428 It also will not change packages marked for install, it only tries
429 to install packages not marked for install */
430 bool pkgAllUpgrade(pkgDepCache
&Cache
)
432 std::string
const solver
= _config
->Find("APT::Solver", "internal");
433 if (solver
!= "internal") {
434 OpTextProgress
Prog(*_config
);
435 return EDSP::ResolveExternal(solver
.c_str(), Cache
, true, false, false, &Prog
);
438 pkgDepCache::ActionGroup
group(Cache
);
440 pkgProblemResolver
Fix(&Cache
);
442 if (Cache
.BrokenCount() != 0)
445 // Upgrade all installed packages
446 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
448 if (Cache
[I
].Install() == true)
451 if (_config
->FindB("APT::Ignore-Hold",false) == false)
452 if (I
->SelectedState
== pkgCache::State::Hold
)
455 if (I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0)
456 Cache
.MarkInstall(I
, false, 0, false);
459 return Fix
.ResolveByKeep();
462 // AllUpgradeNoDelete - Upgrade without removing packages /*{{{*/
463 // ---------------------------------------------------------------------
464 /* Right now the system must be consistent before this can be called.
465 * Upgrade as much as possible without deleting anything (useful for
468 bool pkgAllUpgradeNoDelete(pkgDepCache
&Cache
)
470 pkgDepCache::ActionGroup
group(Cache
);
472 pkgProblemResolver
Fix(&Cache
);
474 if (Cache
.BrokenCount() != 0)
477 // provide the initial set of stuff we want to upgrade by marking
478 // all upgradable packages for upgrade
479 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
481 if (I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0)
483 if (_config
->FindB("APT::Ignore-Hold",false) == false)
484 if (I
->SelectedState
== pkgCache::State::Hold
)
487 Cache
.MarkInstall(I
, false, 0, false);
491 // then let auto-install loose
492 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
493 if (Cache
[I
].Install())
494 Cache
.MarkInstall(I
, true, 0, false);
496 // ... but it may remove stuff, we we need to clean up afterwards again
497 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
498 if (Cache
[I
].Delete() == true)
499 Cache
.MarkKeep(I
, false, false);
501 // resolve remaining issues via keep
502 return Fix
.ResolveByKeep();
505 // MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/
506 // ---------------------------------------------------------------------
507 /* This simply goes over the entire set of packages and tries to keep
508 each package marked for upgrade. If a conflict is generated then
509 the package is restored. */
510 bool pkgMinimizeUpgrade(pkgDepCache
&Cache
)
512 pkgDepCache::ActionGroup
group(Cache
);
514 if (Cache
.BrokenCount() != 0)
517 // We loop for 10 tries to get the minimal set size.
519 unsigned int Count
= 0;
523 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
526 if (Cache
[I
].Upgrade() == false || Cache
[I
].NewInstall() == true)
529 // Keep it and see if that is OK
530 Cache
.MarkKeep(I
, false, false);
531 if (Cache
.BrokenCount() != 0)
532 Cache
.MarkInstall(I
, false, 0, false);
535 // If keep didnt actually do anything then there was no change..
536 if (Cache
[I
].Upgrade() == false)
542 while (Change
== true && Count
< 10);
544 if (Cache
.BrokenCount() != 0)
545 return _error
->Error("Internal Error in pkgMinimizeUpgrade");
550 // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
551 // ---------------------------------------------------------------------
553 pkgProblemResolver::pkgProblemResolver(pkgDepCache
*pCache
) : d(NULL
), Cache(*pCache
)
556 unsigned long Size
= Cache
.Head().PackageCount
;
557 Scores
= new int[Size
];
558 Flags
= new unsigned char[Size
];
559 memset(Flags
,0,sizeof(*Flags
)*Size
);
561 // Set debug to true to see its decision logic
562 Debug
= _config
->FindB("Debug::pkgProblemResolver",false);
565 // ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
566 // ---------------------------------------------------------------------
568 pkgProblemResolver::~pkgProblemResolver()
574 // ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
575 // ---------------------------------------------------------------------
577 int pkgProblemResolver::ScoreSort(const void *a
,const void *b
)
579 Package
const **A
= (Package
const **)a
;
580 Package
const **B
= (Package
const **)b
;
581 if (This
->Scores
[(*A
)->ID
] > This
->Scores
[(*B
)->ID
])
583 if (This
->Scores
[(*A
)->ID
] < This
->Scores
[(*B
)->ID
])
588 // ProblemResolver::MakeScores - Make the score table /*{{{*/
589 // ---------------------------------------------------------------------
591 void pkgProblemResolver::MakeScores()
593 unsigned long Size
= Cache
.Head().PackageCount
;
594 memset(Scores
,0,sizeof(*Scores
)*Size
);
596 // maps to pkgCache::State::VerPriority:
597 // Required Important Standard Optional Extra
600 _config
->FindI("pkgProblemResolver::Scores::Required",3),
601 _config
->FindI("pkgProblemResolver::Scores::Important",2),
602 _config
->FindI("pkgProblemResolver::Scores::Standard",1),
603 _config
->FindI("pkgProblemResolver::Scores::Optional",-1),
604 _config
->FindI("pkgProblemResolver::Scores::Extra",-2)
606 int PrioEssentials
= _config
->FindI("pkgProblemResolver::Scores::Essentials",100);
607 int PrioInstalledAndNotObsolete
= _config
->FindI("pkgProblemResolver::Scores::NotObsolete",1);
608 int PrioDepends
= _config
->FindI("pkgProblemResolver::Scores::Depends",1);
609 int PrioRecommends
= _config
->FindI("pkgProblemResolver::Scores::Recommends",1);
610 int AddProtected
= _config
->FindI("pkgProblemResolver::Scores::AddProtected",10000);
611 int AddEssential
= _config
->FindI("pkgProblemResolver::Scores::AddEssential",5000);
613 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
614 clog
<< "Settings used to calculate pkgProblemResolver::Scores::" << endl
615 << " Required => " << PrioMap
[pkgCache::State::Required
] << endl
616 << " Important => " << PrioMap
[pkgCache::State::Important
] << endl
617 << " Standard => " << PrioMap
[pkgCache::State::Standard
] << endl
618 << " Optional => " << PrioMap
[pkgCache::State::Optional
] << endl
619 << " Extra => " << PrioMap
[pkgCache::State::Extra
] << endl
620 << " Essentials => " << PrioEssentials
<< endl
621 << " InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete
<< endl
622 << " Depends => " << PrioDepends
<< endl
623 << " Recommends => " << PrioRecommends
<< endl
624 << " AddProtected => " << AddProtected
<< endl
625 << " AddEssential => " << AddEssential
<< endl
;
627 // Generate the base scores for a package based on its properties
628 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
630 if (Cache
[I
].InstallVer
== 0)
633 int &Score
= Scores
[I
->ID
];
635 /* This is arbitrary, it should be high enough to elevate an
636 essantial package above most other packages but low enough
637 to allow an obsolete essential packages to be removed by
638 a conflicts on a powerfull normal package (ie libc6) */
639 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
640 || (I
->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
641 Score
+= PrioEssentials
;
643 // We transform the priority
644 if (Cache
[I
].InstVerIter(Cache
)->Priority
<= 5)
645 Score
+= PrioMap
[Cache
[I
].InstVerIter(Cache
)->Priority
];
647 /* This helps to fix oddball problems with conflicting packages
648 on the same level. We enhance the score of installed packages
649 if those are not obsolete
651 if (I
->CurrentVer
!= 0 && Cache
[I
].CandidateVer
!= 0 && Cache
[I
].CandidateVerIter(Cache
).Downloadable())
652 Score
+= PrioInstalledAndNotObsolete
;
655 // Now that we have the base scores we go and propogate dependencies
656 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
658 if (Cache
[I
].InstallVer
== 0)
661 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false; ++D
)
663 if (D
->Type
== pkgCache::Dep::Depends
||
664 D
->Type
== pkgCache::Dep::PreDepends
)
665 Scores
[D
.TargetPkg()->ID
] += PrioDepends
;
666 else if (D
->Type
== pkgCache::Dep::Recommends
)
667 Scores
[D
.TargetPkg()->ID
] += PrioRecommends
;
671 // Copy the scores to advoid additive looping
672 SPtrArray
<int> OldScores
= new int[Size
];
673 memcpy(OldScores
,Scores
,sizeof(*Scores
)*Size
);
675 /* Now we cause 1 level of dependency inheritance, that is we add the
676 score of the packages that depend on the target Package. This
677 fortifies high scoring packages */
678 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
680 if (Cache
[I
].InstallVer
== 0)
683 for (pkgCache::DepIterator D
= I
.RevDependsList(); D
.end() == false; ++D
)
685 // Only do it for the install version
686 if ((pkgCache::Version
*)D
.ParentVer() != Cache
[D
.ParentPkg()].InstallVer
||
687 (D
->Type
!= pkgCache::Dep::Depends
&&
688 D
->Type
!= pkgCache::Dep::PreDepends
&&
689 D
->Type
!= pkgCache::Dep::Recommends
))
692 // Do not propagate negative scores otherwise
693 // an extra (-2) package might score better than an optional (-1)
694 if (OldScores
[D
.ParentPkg()->ID
] > 0)
695 Scores
[I
->ID
] += OldScores
[D
.ParentPkg()->ID
];
699 /* Now we propogate along provides. This makes the packages that
700 provide important packages extremely important */
701 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
703 for (pkgCache::PrvIterator P
= I
.ProvidesList(); P
.end() == false; ++P
)
705 // Only do it once per package
706 if ((pkgCache::Version
*)P
.OwnerVer() != Cache
[P
.OwnerPkg()].InstallVer
)
708 Scores
[P
.OwnerPkg()->ID
] += abs(Scores
[I
->ID
] - OldScores
[I
->ID
]);
712 /* Protected things are pushed really high up. This number should put them
713 ahead of everything */
714 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
716 if ((Flags
[I
->ID
] & Protected
) != 0)
717 Scores
[I
->ID
] += AddProtected
;
718 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
||
719 (I
->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
720 Scores
[I
->ID
] += AddEssential
;
724 // ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
725 // ---------------------------------------------------------------------
726 /* This goes through and tries to reinstall packages to make this package
728 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg
)
730 pkgDepCache::ActionGroup
group(Cache
);
732 if ((Flags
[Pkg
->ID
] & Upgradable
) == 0 || Cache
[Pkg
].Upgradable() == false)
734 if ((Flags
[Pkg
->ID
] & Protected
) == Protected
)
737 Flags
[Pkg
->ID
] &= ~Upgradable
;
739 bool WasKept
= Cache
[Pkg
].Keep();
740 Cache
.MarkInstall(Pkg
, false, 0, false);
742 // This must be a virtual package or something like that.
743 if (Cache
[Pkg
].InstVerIter(Cache
).end() == true)
746 // Isolate the problem dependency
748 for (pkgCache::DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
750 // Compute a single dependency element (glob or)
751 pkgCache::DepIterator Start
= D
;
752 pkgCache::DepIterator End
= D
;
753 for (bool LastOR
= true; D
.end() == false && LastOR
== true;)
755 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
761 // We only worry about critical deps.
762 if (End
.IsCritical() != true)
765 // Iterate over all the members in the or group
769 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
772 // Do not change protected packages
773 PkgIterator P
= Start
.SmartTargetPkg();
774 if ((Flags
[P
->ID
] & Protected
) == Protected
)
777 clog
<< " Reinst Failed because of protected " << P
.FullName(false) << endl
;
782 // Upgrade the package if the candidate version will fix the problem.
783 if ((Cache
[Start
] & pkgDepCache::DepCVer
) == pkgDepCache::DepCVer
)
785 if (DoUpgrade(P
) == false)
788 clog
<< " Reinst Failed because of " << P
.FullName(false) << endl
;
799 /* We let the algorithm deal with conflicts on its next iteration,
800 it is much smarter than us */
801 if (Start
.IsNegative() == true)
805 clog
<< " Reinst Failed early because of " << Start
.TargetPkg().FullName(false) << endl
;
818 // Undo our operations - it might be smart to undo everything this did..
822 Cache
.MarkKeep(Pkg
, false, false);
824 Cache
.MarkDelete(Pkg
, false, 0, false);
829 clog
<< " Re-Instated " << Pkg
.FullName(false) << endl
;
833 // ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/
834 // ---------------------------------------------------------------------
836 bool pkgProblemResolver::Resolve(bool BrokenFix
)
838 std::string
const solver
= _config
->Find("APT::Solver", "internal");
839 if (solver
!= "internal") {
840 OpTextProgress
Prog(*_config
);
841 return EDSP::ResolveExternal(solver
.c_str(), Cache
, false, false, false, &Prog
);
843 return ResolveInternal(BrokenFix
);
846 // ProblemResolver::ResolveInternal - Run the resolution pass /*{{{*/
847 // ---------------------------------------------------------------------
848 /* This routines works by calculating a score for each package. The score
849 is derived by considering the package's priority and all reverse
850 dependents giving an integer that reflects the amount of breakage that
851 adjusting the package will inflict.
853 It goes from highest score to lowest and corrects all of the breaks by
854 keeping or removing the dependant packages. If that fails then it removes
855 the package itself and goes on. The routine should be able to intelligently
856 go from any broken state to a fixed state.
858 The BrokenFix flag enables a mode where the algorithm tries to
859 upgrade packages to advoid problems. */
860 bool pkgProblemResolver::ResolveInternal(bool const BrokenFix
)
862 pkgDepCache::ActionGroup
group(Cache
);
864 // Record which packages are marked for install
869 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
871 if (Cache
[I
].Install() == true)
872 Flags
[I
->ID
] |= PreInstalled
;
875 if (Cache
[I
].InstBroken() == true && BrokenFix
== true)
877 Cache
.MarkInstall(I
, false, 0, false);
878 if (Cache
[I
].Install() == true)
882 Flags
[I
->ID
] &= ~PreInstalled
;
884 Flags
[I
->ID
] |= Upgradable
;
887 while (Again
== true);
890 clog
<< "Starting pkgProblemResolver with broken count: "
891 << Cache
.BrokenCount() << endl
;
896 unsigned long const Size
= Cache
.Head().PackageCount
;
898 /* We have to order the packages so that the broken fixing pass
899 operates from highest score to lowest. This prevents problems when
900 high score packages cause the removal of lower score packages that
901 would cause the removal of even lower score packages. */
902 SPtrArray
<pkgCache::Package
*> PList
= new pkgCache::Package
*[Size
];
903 pkgCache::Package
**PEnd
= PList
;
904 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
907 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
909 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
911 clog
<< "Show Scores" << endl
;
912 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
913 if (Scores
[(*K
)->ID
] != 0)
915 pkgCache::PkgIterator
Pkg(Cache
,*K
);
916 clog
<< Scores
[(*K
)->ID
] << ' ' << Pkg
<< std::endl
;
921 clog
<< "Starting 2 pkgProblemResolver with broken count: "
922 << Cache
.BrokenCount() << endl
;
925 /* Now consider all broken packages. For each broken package we either
926 remove the package or fix it's problem. We do this once, it should
927 not be possible for a loop to form (that is a < b < c and fixing b by
928 changing a breaks c) */
930 bool const TryFixByInstall
= _config
->FindB("pkgProblemResolver::FixByInstall", true);
931 for (int Counter
= 0; Counter
!= 10 && Change
== true; Counter
++)
934 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
936 pkgCache::PkgIterator
I(Cache
,*K
);
938 /* We attempt to install this and see if any breaks result,
939 this takes care of some strange cases */
940 if (Cache
[I
].CandidateVer
!= Cache
[I
].InstallVer
&&
941 I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0 &&
942 (Flags
[I
->ID
] & PreInstalled
) != 0 &&
943 (Flags
[I
->ID
] & Protected
) == 0 &&
944 (Flags
[I
->ID
] & ReInstateTried
) == 0)
947 clog
<< " Try to Re-Instate (" << Counter
<< ") " << I
.FullName(false) << endl
;
948 unsigned long OldBreaks
= Cache
.BrokenCount();
949 pkgCache::Version
*OldVer
= Cache
[I
].InstallVer
;
950 Flags
[I
->ID
] &= ReInstateTried
;
952 Cache
.MarkInstall(I
, false, 0, false);
953 if (Cache
[I
].InstBroken() == true ||
954 OldBreaks
< Cache
.BrokenCount())
957 Cache
.MarkDelete(I
, false, 0, false);
959 Cache
.MarkKeep(I
, false, false);
963 clog
<< "Re-Instated " << I
.FullName(false) << " (" << OldBreaks
<< " vs " << Cache
.BrokenCount() << ')' << endl
;
966 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
970 clog
<< "Investigating (" << Counter
<< ") " << I
<< endl
;
972 // Isolate the problem dependency
973 PackageKill KillList
[100];
974 PackageKill
*LEnd
= KillList
;
976 pkgCache::DepIterator Start
;
977 pkgCache::DepIterator End
;
978 PackageKill
*OldEnd
= LEnd
;
980 enum {OrRemove
,OrKeep
} OrOp
= OrRemove
;
981 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList();
982 D
.end() == false || InOr
== true;)
984 // Compute a single dependency element (glob or)
988 if (InOr
== true && OldEnd
== LEnd
)
990 if (OrOp
== OrRemove
)
992 if ((Flags
[I
->ID
] & Protected
) != Protected
)
995 clog
<< " Or group remove for " << I
.FullName(false) << endl
;
996 Cache
.MarkDelete(I
, false, 0, false);
1000 else if (OrOp
== OrKeep
)
1003 clog
<< " Or group keep for " << I
.FullName(false) << endl
;
1004 Cache
.MarkKeep(I
, false, false);
1009 /* We do an extra loop (as above) to finalize the or group
1013 D
.GlobOr(Start
,End
);
1014 if (Start
.end() == true)
1017 // We only worry about critical deps.
1018 if (End
.IsCritical() != true)
1021 InOr
= Start
!= End
;
1027 // We only worry about critical deps.
1028 if (Start
.IsCritical() != true)
1033 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
1040 clog
<< "Broken " << Start
<< endl
;
1042 /* Look across the version list. If there are no possible
1043 targets then we keep the package and bail. This is necessary
1044 if a package has a dep on another package that cant be found */
1045 SPtrArray
<pkgCache::Version
*> VList
= Start
.AllTargets();
1046 if (*VList
== 0 && (Flags
[I
->ID
] & Protected
) != Protected
&&
1047 Start
.IsNegative() == false &&
1048 Cache
[I
].NowBroken() == false)
1052 /* No keep choice because the keep being OK could be the
1053 result of another element in the OR group! */
1058 Cache
.MarkKeep(I
, false, false);
1063 for (pkgCache::Version
**V
= VList
; *V
!= 0; V
++)
1065 pkgCache::VerIterator
Ver(Cache
,*V
);
1066 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
1068 /* This is a conflicts, and the version we are looking
1069 at is not the currently selected version of the
1070 package, which means it is not necessary to
1072 if (Cache
[Pkg
].InstallVer
!= Ver
&& Start
.IsNegative() == true)
1075 clog
<< " Conflicts//Breaks against version "
1076 << Ver
.VerStr() << " for " << Pkg
.Name()
1077 << " but that is not InstVer, ignoring"
1083 clog
<< " Considering " << Pkg
.FullName(false) << ' ' << (int)Scores
[Pkg
->ID
] <<
1084 " as a solution to " << I
.FullName(false) << ' ' << (int)Scores
[I
->ID
] << endl
;
1086 /* Try to fix the package under consideration rather than
1087 fiddle with the VList package */
1088 if (Scores
[I
->ID
] <= Scores
[Pkg
->ID
] ||
1089 ((Cache
[Start
] & pkgDepCache::DepNow
) == 0 &&
1090 End
.IsNegative() == false))
1092 // Try a little harder to fix protected packages..
1093 if ((Flags
[I
->ID
] & Protected
) == Protected
)
1095 if (DoUpgrade(Pkg
) == true)
1097 if (Scores
[Pkg
->ID
] > Scores
[I
->ID
])
1098 Scores
[Pkg
->ID
] = Scores
[I
->ID
];
1105 /* See if a keep will do, unless the package is protected,
1106 then installing it will be necessary */
1107 bool Installed
= Cache
[I
].Install();
1108 Cache
.MarkKeep(I
, false, false);
1109 if (Cache
[I
].InstBroken() == false)
1111 // Unwind operation will be keep now
1112 if (OrOp
== OrRemove
)
1116 if (InOr
== true && Installed
== true)
1117 Cache
.MarkInstall(I
, false, 0, false);
1120 clog
<< " Holding Back " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
1124 if (BrokenFix
== false || DoUpgrade(I
) == false)
1126 // Consider other options
1127 if (InOr
== false || Cache
[I
].Garbage
== true)
1130 clog
<< " Removing " << I
.FullName(false) << " rather than change " << Start
.TargetPkg().FullName(false) << endl
;
1131 Cache
.MarkDelete(I
, false, 0, false);
1132 if (Counter
> 1 && Scores
[Pkg
->ID
] > Scores
[I
->ID
])
1133 Scores
[I
->ID
] = Scores
[Pkg
->ID
];
1135 else if (TryFixByInstall
== true &&
1136 Start
.TargetPkg()->CurrentVer
== 0 &&
1137 Cache
[Start
.TargetPkg()].Delete() == false &&
1138 (Flags
[Start
.TargetPkg()->ID
] & ToRemove
) != ToRemove
&&
1139 Cache
.GetCandidateVer(Start
.TargetPkg()).end() == false)
1141 /* Before removing or keeping the package with the broken dependency
1142 try instead to install the first not previously installed package
1143 solving this dependency. This helps every time a previous solver
1144 is removed by the resolver because of a conflict or alike but it is
1145 dangerous as it could trigger new breaks/conflicts… */
1147 clog
<< " Try Installing " << Start
.TargetPkg() << " before changing " << I
.FullName(false) << std::endl
;
1148 unsigned long const OldBroken
= Cache
.BrokenCount();
1149 Cache
.MarkInstall(Start
.TargetPkg(), true, 1, false);
1150 // FIXME: we should undo the complete MarkInstall process here
1151 if (Cache
[Start
.TargetPkg()].InstBroken() == true || Cache
.BrokenCount() > OldBroken
)
1152 Cache
.MarkDelete(Start
.TargetPkg(), false, 1, false);
1163 if (Start
->Type
== pkgCache::Dep::DpkgBreaks
)
1165 // first, try upgradring the package, if that
1166 // does not help, the breaks goes onto the
1169 // FIXME: use DoUpgrade(Pkg) instead?
1170 if (Cache
[End
] & pkgDepCache::DepGCVer
)
1173 clog
<< " Upgrading " << Pkg
.FullName(false) << " due to Breaks field in " << I
.FullName(false) << endl
;
1174 Cache
.MarkInstall(Pkg
, false, 0, false);
1179 // Skip adding to the kill list if it is protected
1180 if ((Flags
[Pkg
->ID
] & Protected
) != 0)
1184 clog
<< " Added " << Pkg
.FullName(false) << " to the remove list" << endl
;
1190 if (Start
.IsNegative() == false)
1195 // Hm, nothing can possibly satisify this dep. Nuke it.
1196 if (VList
[0] == 0 &&
1197 Start
.IsNegative() == false &&
1198 (Flags
[I
->ID
] & Protected
) != Protected
)
1200 bool Installed
= Cache
[I
].Install();
1202 if (Cache
[I
].InstBroken() == false)
1204 // Unwind operation will be keep now
1205 if (OrOp
== OrRemove
)
1209 if (InOr
== true && Installed
== true)
1210 Cache
.MarkInstall(I
, false, 0, false);
1213 clog
<< " Holding Back " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1218 clog
<< " Removing " << I
.FullName(false) << " because I can't find " << Start
.TargetPkg().FullName(false) << endl
;
1220 Cache
.MarkDelete(I
, false, 0, false);
1235 // Apply the kill list now
1236 if (Cache
[I
].InstallVer
!= 0)
1238 for (PackageKill
*J
= KillList
; J
!= LEnd
; J
++)
1241 if ((Cache
[J
->Dep
] & pkgDepCache::DepGNow
) == 0)
1243 if (J
->Dep
.IsNegative() == true)
1246 clog
<< " Fixing " << I
.FullName(false) << " via remove of " << J
->Pkg
.FullName(false) << endl
;
1247 Cache
.MarkDelete(J
->Pkg
, false, 0, false);
1253 clog
<< " Fixing " << I
.FullName(false) << " via keep of " << J
->Pkg
.FullName(false) << endl
;
1254 Cache
.MarkKeep(J
->Pkg
, false, false);
1259 if (Scores
[I
->ID
] > Scores
[J
->Pkg
->ID
])
1260 Scores
[J
->Pkg
->ID
] = Scores
[I
->ID
];
1268 clog
<< "Done" << endl
;
1270 if (Cache
.BrokenCount() != 0)
1272 // See if this is the result of a hold
1273 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1274 for (;I
.end() != true; ++I
)
1276 if (Cache
[I
].InstBroken() == false)
1278 if ((Flags
[I
->ID
] & Protected
) != Protected
)
1279 return _error
->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
1281 return _error
->Error(_("Unable to correct problems, you have held broken packages."));
1284 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
1285 pkgCache::PkgIterator I
= Cache
.PkgBegin();
1286 for (;I
.end() != true; ++I
) {
1287 if (Cache
[I
].NewInstall() && !(Flags
[I
->ID
] & PreInstalled
)) {
1288 if(_config
->FindI("Debug::pkgAutoRemove",false)) {
1289 std::clog
<< "Resolve installed new pkg: " << I
.FullName(false)
1290 << " (now marking it as auto)" << std::endl
;
1292 Cache
[I
].Flags
|= pkgCache::Flag::Auto
;
1300 // ProblemResolver::BreaksInstOrPolicy - Check if the given pkg is broken/*{{{*/
1301 // ---------------------------------------------------------------------
1302 /* This checks if the given package is broken either by a hard dependency
1303 (InstBroken()) or by introducing a new policy breakage e.g. new
1304 unsatisfied recommends for a package that was in "policy-good" state
1306 Note that this is not perfect as it will ignore further breakage
1307 for already broken policy (recommends)
1309 bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I
)
1311 // a broken install is always a problem
1312 if (Cache
[I
].InstBroken() == true)
1315 std::clog
<< " Dependencies are not satisfied for " << I
<< std::endl
;
1319 // a newly broken policy (recommends/suggests) is a problem
1320 if (Cache
[I
].NowPolicyBroken() == false &&
1321 Cache
[I
].InstPolicyBroken() == true)
1324 std::clog
<< " Policy breaks with upgrade of " << I
<< std::endl
;
1331 // ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1332 // ---------------------------------------------------------------------
1333 /* This is the work horse of the soft upgrade routine. It is very gental
1334 in that it does not install or remove any packages. It is assumed that the
1335 system was non-broken previously. */
1336 bool pkgProblemResolver::ResolveByKeep()
1338 std::string
const solver
= _config
->Find("APT::Solver", "internal");
1339 if (solver
!= "internal") {
1340 OpTextProgress
Prog(*_config
);
1341 return EDSP::ResolveExternal(solver
.c_str(), Cache
, true, false, false, &Prog
);
1343 return ResolveByKeepInternal();
1346 // ProblemResolver::ResolveByKeepInternal - Resolve problems using keep /*{{{*/
1347 // ---------------------------------------------------------------------
1348 /* This is the work horse of the soft upgrade routine. It is very gental
1349 in that it does not install or remove any packages. It is assumed that the
1350 system was non-broken previously. */
1351 bool pkgProblemResolver::ResolveByKeepInternal()
1353 pkgDepCache::ActionGroup
group(Cache
);
1355 unsigned long Size
= Cache
.Head().PackageCount
;
1359 /* We have to order the packages so that the broken fixing pass
1360 operates from highest score to lowest. This prevents problems when
1361 high score packages cause the removal of lower score packages that
1362 would cause the removal of even lower score packages. */
1363 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
1364 pkgCache::Package
**PEnd
= PList
;
1365 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1368 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
1370 if (_config
->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1372 clog
<< "Show Scores" << endl
;
1373 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1374 if (Scores
[(*K
)->ID
] != 0)
1376 pkgCache::PkgIterator
Pkg(Cache
,*K
);
1377 clog
<< Scores
[(*K
)->ID
] << ' ' << Pkg
<< std::endl
;
1382 clog
<< "Entering ResolveByKeep" << endl
;
1384 // Consider each broken package
1385 pkgCache::Package
**LastStop
= 0;
1386 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
1388 pkgCache::PkgIterator
I(Cache
,*K
);
1390 if (Cache
[I
].InstallVer
== 0)
1393 if (InstOrNewPolicyBroken(I
) == false)
1396 /* Keep the package. If this works then great, otherwise we have
1397 to be significantly more agressive and manipulate its dependencies */
1398 if ((Flags
[I
->ID
] & Protected
) == 0)
1401 clog
<< "Keeping package " << I
.FullName(false) << endl
;
1402 Cache
.MarkKeep(I
, false, false);
1403 if (InstOrNewPolicyBroken(I
) == false)
1410 // Isolate the problem dependencies
1411 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
1415 D
.GlobOr(Start
,End
);
1417 // We only worry about critical deps.
1418 if (End
.IsCritical() != true)
1422 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
1425 /* Hm, the group is broken.. I suppose the best thing to do is to
1426 is to try every combination of keep/not-keep for the set, but thats
1427 slow, and this never happens, just be conservative and assume the
1428 list of ors is in preference and keep till it starts to work. */
1432 clog
<< "Package " << I
.FullName(false) << " " << Start
<< endl
;
1434 // Look at all the possible provides on this package
1435 SPtrArray
<pkgCache::Version
*> VList
= Start
.AllTargets();
1436 for (pkgCache::Version
**V
= VList
; *V
!= 0; V
++)
1438 pkgCache::VerIterator
Ver(Cache
,*V
);
1439 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
1441 // It is not keepable
1442 if (Cache
[Pkg
].InstallVer
== 0 ||
1443 Pkg
->CurrentVer
== 0)
1446 if ((Flags
[I
->ID
] & Protected
) == 0)
1449 clog
<< " Keeping Package " << Pkg
.FullName(false) << " due to " << Start
.DepType() << endl
;
1450 Cache
.MarkKeep(Pkg
, false, false);
1453 if (InstOrNewPolicyBroken(I
) == false)
1457 if (InstOrNewPolicyBroken(I
) == false)
1465 if (InstOrNewPolicyBroken(I
) == false)
1469 if (InstOrNewPolicyBroken(I
) == true)
1473 if (K
== LastStop
) {
1474 // I is an iterator based off our temporary package list,
1475 // so copy the name we need before deleting the temporary list
1476 std::string
const LoopingPackage
= I
.FullName(false);
1478 return _error
->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.", LoopingPackage
.c_str());
1488 // ProblemResolver::InstallProtect - deprecated cpu-eating no-op /*{{{*/
1489 // ---------------------------------------------------------------------
1490 /* Actions issued with FromUser bit set are protected from further
1491 modification (expect by other calls with FromUser set) nowadays , so we
1492 don't need to reissue actions here, they are already set in stone. */
1493 void pkgProblemResolver::InstallProtect()
1495 pkgDepCache::ActionGroup
group(Cache
);
1497 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; ++I
)
1499 if ((Flags
[I
->ID
] & Protected
) == Protected
)
1501 if ((Flags
[I
->ID
] & ToRemove
) == ToRemove
)
1502 Cache
.MarkDelete(I
);
1505 // preserve the information whether the package was auto
1506 // or manually installed
1507 bool autoInst
= (Cache
[I
].Flags
& pkgCache::Flag::Auto
);
1508 Cache
.MarkInstall(I
, false, 0, !autoInst
);
1514 // PrioSortList - Sort a list of versions by priority /*{{{*/
1515 // ---------------------------------------------------------------------
1516 /* This is ment to be used in conjunction with AllTargets to get a list
1517 of versions ordered by preference. */
1518 static pkgCache
*PrioCache
;
1519 static int PrioComp(const void *A
,const void *B
)
1521 pkgCache::VerIterator
L(*PrioCache
,*(pkgCache::Version
**)A
);
1522 pkgCache::VerIterator
R(*PrioCache
,*(pkgCache::Version
**)B
);
1524 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
&&
1525 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
)
1527 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) != pkgCache::Flag::Essential
&&
1528 (R
.ParentPkg()->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
1531 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
&&
1532 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
)
1534 if ((L
.ParentPkg()->Flags
& pkgCache::Flag::Important
) != pkgCache::Flag::Important
&&
1535 (R
.ParentPkg()->Flags
& pkgCache::Flag::Important
) == pkgCache::Flag::Important
)
1538 if (L
->Priority
!= R
->Priority
)
1539 return R
->Priority
- L
->Priority
;
1540 return strcmp(L
.ParentPkg().Name(),R
.ParentPkg().Name());
1542 void pkgPrioSortList(pkgCache
&Cache
,pkgCache::Version
**List
)
1544 unsigned long Count
= 0;
1546 for (pkgCache::Version
**I
= List
; *I
!= 0; I
++)
1548 qsort(List
,Count
,sizeof(*List
),PrioComp
);
1551 // ListUpdate - construct Fetcher and update the cache files /*{{{*/
1552 // ---------------------------------------------------------------------
1553 /* This is a simple wrapper to update the cache. it will fetch stuff
1554 * from the network (or any other sources defined in sources.list)
1556 bool ListUpdate(pkgAcquireStatus
&Stat
,
1557 pkgSourceList
&List
,
1561 if (Fetcher
.Setup(&Stat
, _config
->FindDir("Dir::State::Lists")) == false)
1564 // Populate it with the source selection
1565 if (List
.GetIndexes(&Fetcher
) == false)
1568 return AcquireUpdate(Fetcher
, PulseInterval
, true);
1571 // AcquireUpdate - take Fetcher and update the cache files /*{{{*/
1572 // ---------------------------------------------------------------------
1573 /* This is a simple wrapper to update the cache with a provided acquire
1574 * If you only need control over Status and the used SourcesList use
1575 * ListUpdate method instead.
1577 bool AcquireUpdate(pkgAcquire
&Fetcher
, int const PulseInterval
,
1578 bool const RunUpdateScripts
, bool const ListCleanup
)
1581 if (RunUpdateScripts
== true)
1582 RunScripts("APT::Update::Pre-Invoke");
1584 pkgAcquire::RunResult res
;
1585 if(PulseInterval
> 0)
1586 res
= Fetcher
.Run(PulseInterval
);
1588 res
= Fetcher
.Run();
1590 if (res
== pkgAcquire::Failed
)
1593 bool Failed
= false;
1594 bool TransientNetworkFailure
= false;
1595 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin();
1596 I
!= Fetcher
.ItemsEnd(); ++I
)
1598 if ((*I
)->Status
== pkgAcquire::Item::StatDone
)
1603 ::URI
uri((*I
)->DescURI());
1605 uri
.Password
.clear();
1606 string descUri
= string(uri
);
1607 _error
->Warning(_("Failed to fetch %s %s\n"), descUri
.c_str(),
1608 (*I
)->ErrorText
.c_str());
1610 if ((*I
)->Status
== pkgAcquire::Item::StatTransientNetworkError
)
1612 TransientNetworkFailure
= true;
1619 // Clean out any old list files
1620 // Keep "APT::Get::List-Cleanup" name for compatibility, but
1621 // this is really a global option for the APT library now
1622 if (!TransientNetworkFailure
&& !Failed
&& ListCleanup
== true &&
1623 (_config
->FindB("APT::Get::List-Cleanup",true) == true &&
1624 _config
->FindB("APT::List-Cleanup",true) == true))
1626 if (Fetcher
.Clean(_config
->FindDir("Dir::State::lists")) == false ||
1627 Fetcher
.Clean(_config
->FindDir("Dir::State::lists") + "partial/") == false)
1628 // something went wrong with the clean
1632 if (TransientNetworkFailure
== true)
1633 _error
->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead."));
1634 else if (Failed
== true)
1635 return _error
->Error(_("Some index files failed to download. They have been ignored, or old ones used instead."));
1638 // Run the success scripts if all was fine
1639 if (RunUpdateScripts
== true)
1641 if(!TransientNetworkFailure
&& !Failed
)
1642 RunScripts("APT::Update::Post-Invoke-Success");
1644 // Run the other scripts
1645 RunScripts("APT::Update::Post-Invoke");