]> git.saurik.com Git - apt.git/blame - apt-pkg/algorithms.cc
* apt-pkg/depcache.cc:
[apt.git] / apt-pkg / algorithms.cc
CommitLineData
6c139d6e
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
b8c0f9b7 3// $Id: algorithms.cc,v 1.44 2002/11/28 18:49:16 jgg Exp $
6c139d6e
AL
4/* ######################################################################
5
6 Algorithms - A set of misc algorithms
7
0a8e3465
AL
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.
13
6c139d6e
AL
14 ##################################################################### */
15 /*}}}*/
16// Include Files /*{{{*/
094a497d
AL
17#include <apt-pkg/algorithms.h>
18#include <apt-pkg/error.h>
0a8e3465 19#include <apt-pkg/configuration.h>
0a57c0f0 20#include <apt-pkg/version.h>
b2e465d6 21#include <apt-pkg/sptr.h>
760d4968 22#include <apt-pkg/acquire-item.h>
c3b85126 23#include <apt-pkg/edsp.h>
6d38011b 24
b2e465d6 25#include <apti18n.h>
22dcc318 26#include <sys/types.h>
152ab79e
MV
27#include <cstdlib>
28#include <algorithm>
90f057fd 29#include <iostream>
6d38011b
DK
30
31#include <stdio.h>
6c139d6e 32 /*}}}*/
584e4558 33using namespace std;
6c139d6e
AL
34
35pkgProblemResolver *pkgProblemResolver::This = 0;
36
37// Simulate::Simulate - Constructor /*{{{*/
38// ---------------------------------------------------------------------
b2e465d6
AL
39/* The legacy translations here of input Pkg iterators is obsolete,
40 this is not necessary since the pkgCaches are fully shared now. */
41pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache),
42 iPolicy(Cache),
496d5c70
MV
43 Sim(&Cache->GetCache(),&iPolicy),
44 group(Sim)
6c139d6e 45{
b2e465d6
AL
46 Sim.Init(0);
47 Flags = new unsigned char[Cache->Head().PackageCount];
48 memset(Flags,0,sizeof(*Flags)*Cache->Head().PackageCount);
281daf46
AL
49
50 // Fake a filename so as not to activate the media swapping
51 string Jnk = "SIMULATE";
b2e465d6 52 for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
281daf46 53 FileNames[I] = Jnk;
6c139d6e
AL
54}
55 /*}}}*/
b2e465d6
AL
56// Simulate::Describe - Describe a package /*{{{*/
57// ---------------------------------------------------------------------
3826564e
MZ
58/* Parameter Current == true displays the current package version,
59 Parameter Candidate == true displays the candidate package version */
60void pkgSimulate::Describe(PkgIterator Pkg,ostream &out,bool Current,bool Candidate)
b2e465d6
AL
61{
62 VerIterator Ver(Sim);
e59458f7 63
47f6d1b7 64 out << Pkg.FullName(true);
e59458f7 65
3826564e 66 if (Current == true)
e59458f7 67 {
b2e465d6 68 Ver = Pkg.CurrentVer();
e59458f7
AL
69 if (Ver.end() == false)
70 out << " [" << Ver.VerStr() << ']';
71 }
b2e465d6 72
3826564e
MZ
73 if (Candidate == true)
74 {
75 Ver = Sim[Pkg].CandidateVerIter(Sim);
76 if (Ver.end() == true)
77 return;
b2e465d6 78
3826564e
MZ
79 out << " (" << Ver.VerStr() << ' ' << Ver.RelStr() << ')';
80 }
b2e465d6
AL
81}
82 /*}}}*/
6c139d6e
AL
83// Simulate::Install - Simulate unpacking of a package /*{{{*/
84// ---------------------------------------------------------------------
85/* */
86bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
87{
88 // Adapt the iterator
803ea2a8 89 PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
6c139d6e
AL
90 Flags[Pkg->ID] = 1;
91
b2e465d6 92 cout << "Inst ";
3826564e 93 Describe(Pkg,cout,true,true);
6c139d6e 94 Sim.MarkInstall(Pkg,false);
803ea2a8 95
6c139d6e
AL
96 // Look for broken conflicts+predepends.
97 for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
98 {
99 if (Sim[I].InstallVer == 0)
100 continue;
101
b2e465d6
AL
102 for (DepIterator D = Sim[I].InstVerIter(Sim).DependsList(); D.end() == false;)
103 {
104 DepIterator Start;
105 DepIterator End;
106 D.GlobOr(Start,End);
359e46db 107 if (Start.IsNegative() == true ||
b2e465d6 108 End->Type == pkgCache::Dep::PreDepends)
6c139d6e 109 {
b2e465d6 110 if ((Sim[End] & pkgDepCache::DepGInstall) == 0)
6c139d6e 111 {
47f6d1b7 112 cout << " [" << I.FullName(false) << " on " << Start.TargetPkg().FullName(false) << ']';
b2e465d6 113 if (Start->Type == pkgCache::Dep::Conflicts)
47f6d1b7 114 _error->Error("Fatal, conflicts violated %s",I.FullName(false).c_str());
6c139d6e 115 }
b2e465d6
AL
116 }
117 }
6c139d6e
AL
118 }
119
120 if (Sim.BrokenCount() != 0)
121 ShortBreaks();
122 else
04aa15a8 123 cout << endl;
6c139d6e
AL
124 return true;
125}
126 /*}}}*/
127// Simulate::Configure - Simulate configuration of a Package /*{{{*/
128// ---------------------------------------------------------------------
129/* This is not an acurate simulation of relatity, we should really not
130 install the package.. For some investigations it may be necessary
131 however. */
132bool pkgSimulate::Configure(PkgIterator iPkg)
133{
134 // Adapt the iterator
803ea2a8 135 PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
6c139d6e
AL
136
137 Flags[Pkg->ID] = 2;
803ea2a8 138
6c139d6e
AL
139 if (Sim[Pkg].InstBroken() == true)
140 {
47f6d1b7 141 cout << "Conf " << Pkg.FullName(false) << " broken" << endl;
6c139d6e
AL
142
143 Sim.Update();
144
145 // Print out each package and the failed dependencies
146 for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; D++)
147 {
148 if (Sim.IsImportantDep(D) == false ||
149 (Sim[D] & pkgDepCache::DepInstall) != 0)
150 continue;
151
b2e465d6 152 if (D->Type == pkgCache::Dep::Obsoletes)
47f6d1b7 153 cout << " Obsoletes:" << D.TargetPkg().FullName(false);
b2e465d6 154 else if (D->Type == pkgCache::Dep::Conflicts)
47f6d1b7 155 cout << " Conflicts:" << D.TargetPkg().FullName(false);
308c7d30 156 else if (D->Type == pkgCache::Dep::DpkgBreaks)
47f6d1b7 157 cout << " Breaks:" << D.TargetPkg().FullName(false);
6c139d6e 158 else
47f6d1b7 159 cout << " Depends:" << D.TargetPkg().FullName(false);
6c139d6e 160 }
04aa15a8 161 cout << endl;
6c139d6e 162
09a10f9c 163 _error->Error("Conf Broken %s",Pkg.FullName(false).c_str());
6c139d6e
AL
164 }
165 else
b2e465d6
AL
166 {
167 cout << "Conf ";
3826564e 168 Describe(Pkg,cout,false,true);
b2e465d6 169 }
6c139d6e
AL
170
171 if (Sim.BrokenCount() != 0)
172 ShortBreaks();
173 else
04aa15a8 174 cout << endl;
6c139d6e
AL
175
176 return true;
177}
178 /*}}}*/
179// Simulate::Remove - Simulate the removal of a package /*{{{*/
180// ---------------------------------------------------------------------
181/* */
fc4b5c9f 182bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
6c139d6e
AL
183{
184 // Adapt the iterator
803ea2a8 185 PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
6c139d6e
AL
186
187 Flags[Pkg->ID] = 3;
188 Sim.MarkDelete(Pkg);
803ea2a8 189
fc4b5c9f 190 if (Purge == true)
b2e465d6 191 cout << "Purg ";
fc4b5c9f 192 else
b2e465d6 193 cout << "Remv ";
3826564e 194 Describe(Pkg,cout,true,false);
6c139d6e
AL
195
196 if (Sim.BrokenCount() != 0)
197 ShortBreaks();
198 else
04aa15a8 199 cout << endl;
6c139d6e
AL
200
201 return true;
202}
203 /*}}}*/
204// Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
205// ---------------------------------------------------------------------
206/* */
207void pkgSimulate::ShortBreaks()
208{
04aa15a8 209 cout << " [";
6c139d6e
AL
210 for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
211 {
212 if (Sim[I].InstBroken() == true)
213 {
214 if (Flags[I->ID] == 0)
47f6d1b7 215 cout << I.FullName(false) << ' ';
6c139d6e 216/* else
04aa15a8 217 cout << I.Name() << "! ";*/
6c139d6e
AL
218 }
219 }
04aa15a8 220 cout << ']' << endl;
6c139d6e
AL
221}
222 /*}}}*/
223// ApplyStatus - Adjust for non-ok packages /*{{{*/
224// ---------------------------------------------------------------------
225/* We attempt to change the state of the all packages that have failed
226 installation toward their real state. The ordering code will perform
227 the necessary calculations to deal with the problems. */
228bool pkgApplyStatus(pkgDepCache &Cache)
229{
74a05226
MV
230 pkgDepCache::ActionGroup group(Cache);
231
6c139d6e
AL
232 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
233 {
e481d5b0
AL
234 if (I->VersionList == 0)
235 continue;
236
d38b7b3d
AL
237 // Only choice for a ReInstReq package is to reinstall
238 if (I->InstState == pkgCache::State::ReInstReq ||
239 I->InstState == pkgCache::State::HoldReInstReq)
240 {
5871718b 241 if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
74a05226 242 Cache.MarkKeep(I, false, false);
813c8eea
AL
243 else
244 {
245 // Is this right? Will dpkg choke on an upgrade?
2a3f3893
AL
246 if (Cache[I].CandidateVer != 0 &&
247 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
74a05226 248 Cache.MarkInstall(I, false, 0, false);
813c8eea 249 else
b2e465d6 250 return _error->Error(_("The package %s needs to be reinstalled, "
09a10f9c 251 "but I can't find an archive for it."),I.FullName(true).c_str());
813c8eea
AL
252 }
253
d38b7b3d
AL
254 continue;
255 }
256
6c139d6e
AL
257 switch (I->CurrentState)
258 {
813c8eea
AL
259 /* This means installation failed somehow - it does not need to be
260 re-unpacked (probably) */
b518cca6
AL
261 case pkgCache::State::UnPacked:
262 case pkgCache::State::HalfConfigured:
9d06bc80
MV
263 case pkgCache::State::TriggersAwaited:
264 case pkgCache::State::TriggersPending:
5871718b 265 if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) ||
813c8eea 266 I.State() != pkgCache::PkgIterator::NeedsUnpack)
74a05226 267 Cache.MarkKeep(I, false, false);
813c8eea
AL
268 else
269 {
2a3f3893
AL
270 if (Cache[I].CandidateVer != 0 &&
271 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
74a05226 272 Cache.MarkInstall(I, true, 0, false);
813c8eea
AL
273 else
274 Cache.MarkDelete(I);
275 }
6c139d6e
AL
276 break;
277
278 // This means removal failed
b518cca6 279 case pkgCache::State::HalfInstalled:
6c139d6e
AL
280 Cache.MarkDelete(I);
281 break;
282
283 default:
b518cca6 284 if (I->InstState != pkgCache::State::Ok)
6c139d6e 285 return _error->Error("The package %s is not ok and I "
09a10f9c 286 "don't know how to fix it!",I.FullName(false).c_str());
6c139d6e
AL
287 }
288 }
289 return true;
290}
291 /*}}}*/
292// FixBroken - Fix broken packages /*{{{*/
293// ---------------------------------------------------------------------
0a8e3465
AL
294/* This autoinstalls every broken package and then runs the problem resolver
295 on the result. */
6c139d6e
AL
296bool pkgFixBroken(pkgDepCache &Cache)
297{
74a05226
MV
298 pkgDepCache::ActionGroup group(Cache);
299
6c139d6e
AL
300 // Auto upgrade all broken packages
301 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
302 if (Cache[I].NowBroken() == true)
74a05226 303 Cache.MarkInstall(I, true, 0, false);
7e798dd7 304
6c139d6e
AL
305 /* Fix packages that are in a NeedArchive state but don't have a
306 downloadable install version */
307 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
308 {
309 if (I.State() != pkgCache::PkgIterator::NeedsUnpack ||
310 Cache[I].Delete() == true)
311 continue;
312
b518cca6 313 if (Cache[I].InstVerIter(Cache).Downloadable() == false)
6c139d6e
AL
314 continue;
315
74a05226 316 Cache.MarkInstall(I, true, 0, false);
6c139d6e
AL
317 }
318
b2e465d6 319 pkgProblemResolver Fix(&Cache);
6c139d6e
AL
320 return Fix.Resolve(true);
321}
322 /*}}}*/
323// DistUpgrade - Distribution upgrade /*{{{*/
324// ---------------------------------------------------------------------
325/* This autoinstalls every package and then force installs every
326 pre-existing package. This creates the initial set of conditions which
327 most likely contain problems because too many things were installed.
328
0a8e3465 329 The problem resolver is used to resolve the problems.
6c139d6e
AL
330 */
331bool pkgDistUpgrade(pkgDepCache &Cache)
332{
98278a81 333 std::string const solver = _config->Find("APT::Solver", "internal");
b57c0e35
DK
334 if (solver != "internal") {
335 OpTextProgress Prog(*_config);
336 return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, &Prog);
337 }
741b7da9 338
74a05226
MV
339 pkgDepCache::ActionGroup group(Cache);
340
c427b1e2
DK
341 /* Upgrade all installed packages first without autoinst to help the resolver
342 in versioned or-groups to upgrade the old solver instead of installing
343 a new one (if the old solver is not the first one [anymore]) */
344 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
345 if (I->CurrentVer != 0)
346 Cache.MarkInstall(I, false, 0, false);
347
6c139d6e
AL
348 /* Auto upgrade all installed packages, this provides the basis
349 for the installation */
350 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
351 if (I->CurrentVer != 0)
74a05226 352 Cache.MarkInstall(I, true, 0, false);
6c139d6e
AL
353
354 /* Now, auto upgrade all essential packages - this ensures that
355 the essential packages are present and working */
356 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
b518cca6 357 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
74a05226 358 Cache.MarkInstall(I, true, 0, false);
6c139d6e
AL
359
360 /* We do it again over all previously installed packages to force
361 conflict resolution on them all. */
362 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
363 if (I->CurrentVer != 0)
74a05226 364 Cache.MarkInstall(I, false, 0, false);
6c139d6e 365
b2e465d6 366 pkgProblemResolver Fix(&Cache);
c88edf1d 367
6c139d6e 368 // Hold back held packages.
4490f2de 369 if (_config->FindB("APT::Ignore-Hold",false) == false)
6c139d6e 370 {
c88edf1d 371 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
6c139d6e 372 {
c88edf1d
AL
373 if (I->SelectedState == pkgCache::State::Hold)
374 {
375 Fix.Protect(I);
74a05226 376 Cache.MarkKeep(I, false, false);
c88edf1d 377 }
6c139d6e
AL
378 }
379 }
380
381 return Fix.Resolve();
382}
383 /*}}}*/
0a8e3465
AL
384// AllUpgrade - Upgrade as many packages as possible /*{{{*/
385// ---------------------------------------------------------------------
386/* Right now the system must be consistent before this can be called.
387 It also will not change packages marked for install, it only tries
388 to install packages not marked for install */
389bool pkgAllUpgrade(pkgDepCache &Cache)
390{
98278a81 391 std::string const solver = _config->Find("APT::Solver", "internal");
b57c0e35
DK
392 if (solver != "internal") {
393 OpTextProgress Prog(*_config);
394 return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog);
395 }
741b7da9 396
74a05226
MV
397 pkgDepCache::ActionGroup group(Cache);
398
b2e465d6 399 pkgProblemResolver Fix(&Cache);
0a8e3465
AL
400
401 if (Cache.BrokenCount() != 0)
402 return false;
403
404 // Upgrade all installed packages
405 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
406 {
407 if (Cache[I].Install() == true)
408 Fix.Protect(I);
409
b2e465d6 410 if (_config->FindB("APT::Ignore-Hold",false) == false)
c88edf1d
AL
411 if (I->SelectedState == pkgCache::State::Hold)
412 continue;
0a8e3465
AL
413
414 if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
74a05226 415 Cache.MarkInstall(I, false, 0, false);
0a8e3465
AL
416 }
417
418 return Fix.ResolveByKeep();
419}
420 /*}}}*/
7e798dd7
AL
421// MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/
422// ---------------------------------------------------------------------
423/* This simply goes over the entire set of packages and tries to keep
424 each package marked for upgrade. If a conflict is generated then
425 the package is restored. */
426bool pkgMinimizeUpgrade(pkgDepCache &Cache)
427{
74a05226
MV
428 pkgDepCache::ActionGroup group(Cache);
429
7e798dd7
AL
430 if (Cache.BrokenCount() != 0)
431 return false;
432
abc8419e 433 // We loop for 10 tries to get the minimal set size.
7e798dd7 434 bool Change = false;
a005475e 435 unsigned int Count = 0;
7e798dd7
AL
436 do
437 {
438 Change = false;
439 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
440 {
441 // Not interesting
442 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
443 continue;
a005475e 444
7e798dd7 445 // Keep it and see if that is OK
74a05226 446 Cache.MarkKeep(I, false, false);
7e798dd7 447 if (Cache.BrokenCount() != 0)
74a05226 448 Cache.MarkInstall(I, false, 0, false);
7e798dd7 449 else
a005475e
AL
450 {
451 // If keep didnt actually do anything then there was no change..
452 if (Cache[I].Upgrade() == false)
453 Change = true;
454 }
7e798dd7 455 }
a005475e 456 Count++;
7e798dd7 457 }
a005475e 458 while (Change == true && Count < 10);
7e798dd7
AL
459
460 if (Cache.BrokenCount() != 0)
461 return _error->Error("Internal Error in pkgMinimizeUpgrade");
462
463 return true;
464}
465 /*}}}*/
6c139d6e
AL
466// ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
467// ---------------------------------------------------------------------
468/* */
b2e465d6 469pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : Cache(*pCache)
6c139d6e
AL
470{
471 // Allocate memory
b2e465d6 472 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
473 Scores = new signed short[Size];
474 Flags = new unsigned char[Size];
475 memset(Flags,0,sizeof(*Flags)*Size);
476
477 // Set debug to true to see its decision logic
0a8e3465 478 Debug = _config->FindB("Debug::pkgProblemResolver",false);
6c139d6e
AL
479}
480 /*}}}*/
b2e465d6
AL
481// ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
482// ---------------------------------------------------------------------
483/* */
484pkgProblemResolver::~pkgProblemResolver()
485{
486 delete [] Scores;
487 delete [] Flags;
488}
489 /*}}}*/
6c139d6e
AL
490// ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
491// ---------------------------------------------------------------------
492/* */
493int pkgProblemResolver::ScoreSort(const void *a,const void *b)
494{
495 Package const **A = (Package const **)a;
496 Package const **B = (Package const **)b;
497 if (This->Scores[(*A)->ID] > This->Scores[(*B)->ID])
498 return -1;
499 if (This->Scores[(*A)->ID] < This->Scores[(*B)->ID])
500 return 1;
501 return 0;
502}
503 /*}}}*/
504// ProblemResolver::MakeScores - Make the score table /*{{{*/
505// ---------------------------------------------------------------------
506/* */
507void pkgProblemResolver::MakeScores()
508{
b2e465d6 509 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
510 memset(Scores,0,sizeof(*Scores)*Size);
511
8b4894fe
MV
512 // Important Required Standard Optional Extra
513 signed short PrioMap[] = {
514 0,
5e5d2064
DK
515 (signed short) _config->FindI("pkgProblemResolver::Scores::Important",3),
516 (signed short) _config->FindI("pkgProblemResolver::Scores::Required",2),
517 (signed short) _config->FindI("pkgProblemResolver::Scores::Standard",1),
518 (signed short) _config->FindI("pkgProblemResolver::Scores::Optional",-1),
519 (signed short) _config->FindI("pkgProblemResolver::Scores::Extra",-2)
8b4894fe
MV
520 };
521 signed short PrioEssentials = _config->FindI("pkgProblemResolver::Scores::Essentials",100);
522 signed short PrioInstalledAndNotObsolete = _config->FindI("pkgProblemResolver::Scores::NotObsolete",1);
523 signed short PrioDepends = _config->FindI("pkgProblemResolver::Scores::Depends",1);
53391d0f 524 signed short PrioRecommends = _config->FindI("pkgProblemResolver::Scores::Recommends",1);
8b4894fe
MV
525 signed short AddProtected = _config->FindI("pkgProblemResolver::Scores::AddProtected",10000);
526 signed short AddEssential = _config->FindI("pkgProblemResolver::Scores::AddEssential",5000);
527
528 if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
529 clog << "Settings used to calculate pkgProblemResolver::Scores::" << endl
530 << " Important => " << PrioMap[1] << endl
531 << " Required => " << PrioMap[2] << endl
532 << " Standard => " << PrioMap[3] << endl
533 << " Optional => " << PrioMap[4] << endl
534 << " Extra => " << PrioMap[5] << endl
535 << " Essentials => " << PrioEssentials << endl
536 << " InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete << endl
537 << " Depends => " << PrioDepends << endl
53391d0f 538 << " Recommends => " << PrioRecommends << endl
8b4894fe
MV
539 << " AddProtected => " << AddProtected << endl
540 << " AddEssential => " << AddEssential << endl;
541
6c139d6e
AL
542 // Generate the base scores for a package based on its properties
543 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
544 {
545 if (Cache[I].InstallVer == 0)
546 continue;
547
548 signed short &Score = Scores[I->ID];
549
7365ff46 550 /* This is arbitrary, it should be high enough to elevate an
6c139d6e
AL
551 essantial package above most other packages but low enough
552 to allow an obsolete essential packages to be removed by
553 a conflicts on a powerfull normal package (ie libc6) */
b518cca6 554 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
8b4894fe 555 Score += PrioEssentials;
6c139d6e
AL
556
557 // We transform the priority
6c139d6e
AL
558 if (Cache[I].InstVerIter(Cache)->Priority <= 5)
559 Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
560
561 /* This helps to fix oddball problems with conflicting packages
4172c784
MV
562 on the same level. We enhance the score of installed packages
563 if those are not obsolete
564 */
020daa7b 565 if (I->CurrentVer != 0 && Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable())
8b4894fe 566 Score += PrioInstalledAndNotObsolete;
6c139d6e
AL
567 }
568
569 // Now that we have the base scores we go and propogate dependencies
570 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
571 {
572 if (Cache[I].InstallVer == 0)
573 continue;
574
575 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
576 {
3a998f6a 577 if (D->Type == pkgCache::Dep::Depends ||
53391d0f
MV
578 D->Type == pkgCache::Dep::PreDepends)
579 Scores[D.TargetPkg()->ID] += PrioDepends;
580 else if (D->Type == pkgCache::Dep::Recommends)
581 Scores[D.TargetPkg()->ID] += PrioRecommends;
6c139d6e
AL
582 }
583 }
584
585 // Copy the scores to advoid additive looping
b2e465d6 586 SPtrArray<signed short> OldScores = new signed short[Size];
6c139d6e
AL
587 memcpy(OldScores,Scores,sizeof(*Scores)*Size);
588
589 /* Now we cause 1 level of dependency inheritance, that is we add the
590 score of the packages that depend on the target Package. This
591 fortifies high scoring packages */
592 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
593 {
594 if (Cache[I].InstallVer == 0)
595 continue;
596
597 for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; D++)
598 {
599 // Only do it for the install version
600 if ((pkgCache::Version *)D.ParentVer() != Cache[D.ParentPkg()].InstallVer ||
3a998f6a
MV
601 (D->Type != pkgCache::Dep::Depends &&
602 D->Type != pkgCache::Dep::PreDepends &&
603 D->Type != pkgCache::Dep::Recommends))
6c139d6e
AL
604 continue;
605
606 Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]);
607 }
608 }
609
610 /* Now we propogate along provides. This makes the packages that
611 provide important packages extremely important */
612 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
613 {
614 for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; P++)
615 {
616 // Only do it once per package
617 if ((pkgCache::Version *)P.OwnerVer() != Cache[P.OwnerPkg()].InstallVer)
618 continue;
619 Scores[P.OwnerPkg()->ID] += abs(Scores[I->ID] - OldScores[I->ID]);
620 }
621 }
622
623 /* Protected things are pushed really high up. This number should put them
624 ahead of everything */
625 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
d2685fd6 626 {
6c139d6e 627 if ((Flags[I->ID] & Protected) != 0)
8b4894fe 628 Scores[I->ID] += AddProtected;
d2685fd6 629 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
8b4894fe
MV
630 Scores[I->ID] += AddEssential;
631 }
6c139d6e
AL
632}
633 /*}}}*/
634// ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
635// ---------------------------------------------------------------------
636/* This goes through and tries to reinstall packages to make this package
637 installable */
638bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
639{
74a05226
MV
640 pkgDepCache::ActionGroup group(Cache);
641
6c139d6e
AL
642 if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
643 return false;
3a486305
AL
644 if ((Flags[Pkg->ID] & Protected) == Protected)
645 return false;
0a8e3465 646
6c139d6e
AL
647 Flags[Pkg->ID] &= ~Upgradable;
648
649 bool WasKept = Cache[Pkg].Keep();
74a05226 650 Cache.MarkInstall(Pkg, false, 0, false);
6c139d6e 651
0a8e3465
AL
652 // This must be a virtual package or something like that.
653 if (Cache[Pkg].InstVerIter(Cache).end() == true)
654 return false;
655
6c139d6e
AL
656 // Isolate the problem dependency
657 bool Fail = false;
658 for (pkgCache::DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false;)
659 {
660 // Compute a single dependency element (glob or)
661 pkgCache::DepIterator Start = D;
662 pkgCache::DepIterator End = D;
4b1b89c5 663 for (bool LastOR = true; D.end() == false && LastOR == true;)
6c139d6e 664 {
b518cca6 665 LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
0284eee4 666 ++D;
6c139d6e
AL
667 if (LastOR == true)
668 End = D;
669 }
670
671 // We only worry about critical deps.
672 if (End.IsCritical() != true)
673 continue;
4b1b89c5
AL
674
675 // Iterate over all the members in the or group
676 while (1)
0a8e3465 677 {
4b1b89c5
AL
678 // Dep is ok now
679 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
680 break;
681
682 // Do not change protected packages
683 PkgIterator P = Start.SmartTargetPkg();
684 if ((Flags[P->ID] & Protected) == Protected)
685 {
686 if (Debug == true)
47f6d1b7 687 clog << " Reinst Failed because of protected " << P.FullName(false) << endl;
4b1b89c5 688 Fail = true;
4b1b89c5 689 }
648e3cb4 690 else
6c139d6e 691 {
648e3cb4
AL
692 // Upgrade the package if the candidate version will fix the problem.
693 if ((Cache[Start] & pkgDepCache::DepCVer) == pkgDepCache::DepCVer)
694 {
695 if (DoUpgrade(P) == false)
696 {
697 if (Debug == true)
47f6d1b7 698 clog << " Reinst Failed because of " << P.FullName(false) << endl;
648e3cb4
AL
699 Fail = true;
700 }
701 else
702 {
703 Fail = false;
704 break;
705 }
706 }
707 else
4b1b89c5 708 {
648e3cb4
AL
709 /* We let the algorithm deal with conflicts on its next iteration,
710 it is much smarter than us */
359e46db 711 if (Start.IsNegative() == true)
b2e465d6 712 break;
648e3cb4 713
4b1b89c5 714 if (Debug == true)
47f6d1b7 715 clog << " Reinst Failed early because of " << Start.TargetPkg().FullName(false) << endl;
4b1b89c5 716 Fail = true;
648e3cb4 717 }
4b1b89c5 718 }
6c139d6e 719
4b1b89c5
AL
720 if (Start == End)
721 break;
722 Start++;
723 }
724 if (Fail == true)
6c139d6e 725 break;
6c139d6e
AL
726 }
727
728 // Undo our operations - it might be smart to undo everything this did..
729 if (Fail == true)
730 {
731 if (WasKept == true)
74a05226 732 Cache.MarkKeep(Pkg, false, false);
6c139d6e
AL
733 else
734 Cache.MarkDelete(Pkg);
735 return false;
736 }
737
738 if (Debug == true)
47f6d1b7 739 clog << " Re-Instated " << Pkg.FullName(false) << endl;
6c139d6e
AL
740 return true;
741}
742 /*}}}*/
6d38011b
DK
743// ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/
744// ---------------------------------------------------------------------
745/* */
746bool pkgProblemResolver::Resolve(bool BrokenFix)
747{
98278a81 748 std::string const solver = _config->Find("APT::Solver", "internal");
b57c0e35
DK
749 if (solver != "internal") {
750 OpTextProgress Prog(*_config);
751 return EDSP::ResolveExternal(solver.c_str(), Cache, false, false, false, &Prog);
752 }
6d38011b
DK
753 return ResolveInternal(BrokenFix);
754}
755 /*}}}*/
756// ProblemResolver::ResolveInternal - Run the resolution pass /*{{{*/
6c139d6e
AL
757// ---------------------------------------------------------------------
758/* This routines works by calculating a score for each package. The score
759 is derived by considering the package's priority and all reverse
760 dependents giving an integer that reflects the amount of breakage that
761 adjusting the package will inflict.
762
763 It goes from highest score to lowest and corrects all of the breaks by
764 keeping or removing the dependant packages. If that fails then it removes
765 the package itself and goes on. The routine should be able to intelligently
766 go from any broken state to a fixed state.
767
768 The BrokenFix flag enables a mode where the algorithm tries to
769 upgrade packages to advoid problems. */
6d38011b 770bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
6c139d6e 771{
74a05226
MV
772 pkgDepCache::ActionGroup group(Cache);
773
6c139d6e
AL
774 // Record which packages are marked for install
775 bool Again = false;
776 do
777 {
778 Again = false;
779 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
780 {
781 if (Cache[I].Install() == true)
782 Flags[I->ID] |= PreInstalled;
783 else
784 {
785 if (Cache[I].InstBroken() == true && BrokenFix == true)
786 {
74a05226 787 Cache.MarkInstall(I, false, 0, false);
6c139d6e
AL
788 if (Cache[I].Install() == true)
789 Again = true;
790 }
791
792 Flags[I->ID] &= ~PreInstalled;
793 }
794 Flags[I->ID] |= Upgradable;
795 }
796 }
797 while (Again == true);
798
799 if (Debug == true)
0a8e3465 800 clog << "Starting" << endl;
6c139d6e
AL
801
802 MakeScores();
6d38011b
DK
803
804 unsigned long const Size = Cache.Head().PackageCount;
805
6c139d6e
AL
806 /* We have to order the packages so that the broken fixing pass
807 operates from highest score to lowest. This prevents problems when
808 high score packages cause the removal of lower score packages that
809 would cause the removal of even lower score packages. */
b2e465d6 810 SPtrArray<pkgCache::Package *> PList = new pkgCache::Package *[Size];
6c139d6e
AL
811 pkgCache::Package **PEnd = PList;
812 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
813 *PEnd++ = I;
814 This = this;
815 qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
8b4894fe
MV
816
817 if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
818 {
819 clog << "Show Scores" << endl;
820 for (pkgCache::Package **K = PList; K != PEnd; K++)
821 if (Scores[(*K)->ID] != 0)
822 {
823 pkgCache::PkgIterator Pkg(Cache,*K);
824 clog << Scores[(*K)->ID] << ' ' << Pkg << std::endl;
825 }
826 }
6c139d6e
AL
827
828 if (Debug == true)
0a8e3465 829 clog << "Starting 2" << endl;
8b4894fe 830
6c139d6e
AL
831 /* Now consider all broken packages. For each broken package we either
832 remove the package or fix it's problem. We do this once, it should
833 not be possible for a loop to form (that is a < b < c and fixing b by
834 changing a breaks c) */
835 bool Change = true;
09a10f9c 836 bool const TryFixByInstall = _config->FindB("pkgProblemResolver::FixByInstall", true);
6c139d6e
AL
837 for (int Counter = 0; Counter != 10 && Change == true; Counter++)
838 {
839 Change = false;
840 for (pkgCache::Package **K = PList; K != PEnd; K++)
841 {
842 pkgCache::PkgIterator I(Cache,*K);
843
844 /* We attempt to install this and see if any breaks result,
845 this takes care of some strange cases */
846 if (Cache[I].CandidateVer != Cache[I].InstallVer &&
847 I->CurrentVer != 0 && Cache[I].InstallVer != 0 &&
848 (Flags[I->ID] & PreInstalled) != 0 &&
0a8e3465
AL
849 (Flags[I->ID] & Protected) == 0 &&
850 (Flags[I->ID] & ReInstateTried) == 0)
6c139d6e
AL
851 {
852 if (Debug == true)
09a10f9c 853 clog << " Try to Re-Instate (" << Counter << ") " << I.FullName(false) << endl;
a6568219 854 unsigned long OldBreaks = Cache.BrokenCount();
6c139d6e 855 pkgCache::Version *OldVer = Cache[I].InstallVer;
0a8e3465
AL
856 Flags[I->ID] &= ReInstateTried;
857
74a05226 858 Cache.MarkInstall(I, false, 0, false);
6c139d6e
AL
859 if (Cache[I].InstBroken() == true ||
860 OldBreaks < Cache.BrokenCount())
861 {
862 if (OldVer == 0)
863 Cache.MarkDelete(I);
864 else
74a05226 865 Cache.MarkKeep(I, false, false);
6c139d6e
AL
866 }
867 else
868 if (Debug == true)
47f6d1b7 869 clog << "Re-Instated " << I.FullName(false) << " (" << OldBreaks << " vs " << Cache.BrokenCount() << ')' << endl;
6c139d6e
AL
870 }
871
872 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
873 continue;
874
00b47c98 875 if (Debug == true)
09a10f9c 876 clog << "Investigating (" << Counter << ") " << I << endl;
00b47c98 877
6c139d6e
AL
878 // Isolate the problem dependency
879 PackageKill KillList[100];
880 PackageKill *LEnd = KillList;
421c8d10
AL
881 bool InOr = false;
882 pkgCache::DepIterator Start;
883 pkgCache::DepIterator End;
b2e465d6 884 PackageKill *OldEnd = LEnd;
648e3cb4
AL
885
886 enum {OrRemove,OrKeep} OrOp = OrRemove;
421c8d10
AL
887 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
888 D.end() == false || InOr == true;)
6c139d6e
AL
889 {
890 // Compute a single dependency element (glob or)
648e3cb4
AL
891 if (Start == End)
892 {
893 // Decide what to do
09a10f9c 894 if (InOr == true && OldEnd == LEnd)
648e3cb4 895 {
09a10f9c 896 if (OrOp == OrRemove)
70777d4b
AL
897 {
898 if ((Flags[I->ID] & Protected) != Protected)
00b47c98
AL
899 {
900 if (Debug == true)
47f6d1b7 901 clog << " Or group remove for " << I.FullName(false) << endl;
70777d4b 902 Cache.MarkDelete(I);
cd14eaf2 903 Change = true;
09a10f9c
DK
904 }
905 }
906 else if (OrOp == OrKeep)
00b47c98
AL
907 {
908 if (Debug == true)
47f6d1b7 909 clog << " Or group keep for " << I.FullName(false) << endl;
74a05226 910 Cache.MarkKeep(I, false, false);
cd14eaf2 911 Change = true;
b2e465d6 912 }
648e3cb4
AL
913 }
914
b2e465d6
AL
915 /* We do an extra loop (as above) to finalize the or group
916 processing */
917 InOr = false;
648e3cb4 918 OrOp = OrRemove;
421c8d10 919 D.GlobOr(Start,End);
b2e465d6
AL
920 if (Start.end() == true)
921 break;
cd14eaf2 922
b2e465d6
AL
923 // We only worry about critical deps.
924 if (End.IsCritical() != true)
925 continue;
cd14eaf2 926
648e3cb4
AL
927 InOr = Start != End;
928 OldEnd = LEnd;
cd14eaf2 929 }
421c8d10 930 else
4cc152f9 931 {
421c8d10 932 Start++;
4cc152f9
MV
933 // We only worry about critical deps.
934 if (Start.IsCritical() != true)
935 continue;
936 }
cd14eaf2 937
6c139d6e
AL
938 // Dep is ok
939 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
cd14eaf2
AL
940 {
941 InOr = false;
6c139d6e 942 continue;
cd14eaf2
AL
943 }
944
6c139d6e 945 if (Debug == true)
47f6d1b7 946 clog << "Broken " << Start << endl;
fcf85120
AL
947
948 /* Look across the version list. If there are no possible
949 targets then we keep the package and bail. This is necessary
950 if a package has a dep on another package that cant be found */
b2e465d6 951 SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
fcf85120 952 if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
359e46db 953 Start.IsNegative() == false &&
fcf85120 954 Cache[I].NowBroken() == false)
648e3cb4
AL
955 {
956 if (InOr == true)
957 {
958 /* No keep choice because the keep being OK could be the
959 result of another element in the OR group! */
960 continue;
961 }
962
fcf85120 963 Change = true;
74a05226 964 Cache.MarkKeep(I, false, false);
fcf85120
AL
965 break;
966 }
967
6c139d6e
AL
968 bool Done = false;
969 for (pkgCache::Version **V = VList; *V != 0; V++)
970 {
971 pkgCache::VerIterator Ver(Cache,*V);
972 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
a6bfe583 973
2ba99db8
MV
974 /* This is a conflicts, and the version we are looking
975 at is not the currently selected version of the
976 package, which means it is not necessary to
977 remove/keep */
359e46db 978 if (Cache[Pkg].InstallVer != Ver && Start.IsNegative() == true)
4429616b 979 {
2ba99db8
MV
980 if (Debug)
981 clog << " Conflicts//Breaks against version "
982 << Ver.VerStr() << " for " << Pkg.Name()
983 << " but that is not InstVer, ignoring"
24e93662 984 << endl;
2ba99db8 985 continue;
4429616b
MV
986 }
987
6c139d6e 988 if (Debug == true)
47f6d1b7
DK
989 clog << " Considering " << Pkg.FullName(false) << ' ' << (int)Scores[Pkg->ID] <<
990 " as a solution to " << I.FullName(false) << ' ' << (int)Scores[I->ID] << endl;
a6bfe583
AL
991
992 /* Try to fix the package under consideration rather than
993 fiddle with the VList package */
6c139d6e 994 if (Scores[I->ID] <= Scores[Pkg->ID] ||
421c8d10 995 ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
359e46db 996 End.IsNegative() == false))
6c139d6e 997 {
200f8c52 998 // Try a little harder to fix protected packages..
3b5421b4 999 if ((Flags[I->ID] & Protected) == Protected)
200f8c52
AL
1000 {
1001 if (DoUpgrade(Pkg) == true)
0296c633 1002 {
b2e465d6
AL
1003 if (Scores[Pkg->ID] > Scores[I->ID])
1004 Scores[Pkg->ID] = Scores[I->ID];
0296c633
AL
1005 break;
1006 }
1007
6c139d6e 1008 continue;
200f8c52
AL
1009 }
1010
1011 /* See if a keep will do, unless the package is protected,
648e3cb4
AL
1012 then installing it will be necessary */
1013 bool Installed = Cache[I].Install();
74a05226 1014 Cache.MarkKeep(I, false, false);
6c139d6e
AL
1015 if (Cache[I].InstBroken() == false)
1016 {
648e3cb4
AL
1017 // Unwind operation will be keep now
1018 if (OrOp == OrRemove)
1019 OrOp = OrKeep;
1020
1021 // Restore
1022 if (InOr == true && Installed == true)
74a05226 1023 Cache.MarkInstall(I, false, 0, false);
648e3cb4 1024
6c139d6e 1025 if (Debug == true)
47f6d1b7 1026 clog << " Holding Back " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
6c139d6e
AL
1027 }
1028 else
421c8d10 1029 {
6c139d6e
AL
1030 if (BrokenFix == false || DoUpgrade(I) == false)
1031 {
421c8d10
AL
1032 // Consider other options
1033 if (InOr == false)
1034 {
6910a2ac 1035 if (Debug == true)
47f6d1b7 1036 clog << " Removing " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
6910a2ac
DK
1037 Cache.MarkDelete(I);
1038 if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID])
1039 Scores[I->ID] = Scores[Pkg->ID];
d6ebeb21 1040 }
09a10f9c
DK
1041 else if (TryFixByInstall == true &&
1042 Start.TargetPkg()->CurrentVer == 0 &&
1043 Cache[Start.TargetPkg()].Delete() == false &&
a3f1a6cc 1044 (Flags[Start.TargetPkg()->ID] & ToRemove) != ToRemove &&
09a10f9c
DK
1045 Cache.GetCandidateVer(Start.TargetPkg()).end() == false)
1046 {
1047 /* Before removing or keeping the package with the broken dependency
1048 try instead to install the first not previously installed package
1049 solving this dependency. This helps every time a previous solver
1050 is removed by the resolver because of a conflict or alike but it is
1051 dangerous as it could trigger new breaks/conflicts… */
443266ef
DK
1052 if (Debug == true)
1053 clog << " Try Installing " << Start.TargetPkg() << " before changing " << I.FullName(false) << std::endl;
09a10f9c
DK
1054 unsigned long const OldBroken = Cache.BrokenCount();
1055 Cache.MarkInstall(Start.TargetPkg(), true, 1, false);
1056 // FIXME: we should undo the complete MarkInstall process here
1057 if (Cache[Start.TargetPkg()].InstBroken() == true || Cache.BrokenCount() > OldBroken)
1058 Cache.MarkDelete(Start.TargetPkg(), false, 1, false);
1059 }
0a8e3465 1060 }
6c139d6e 1061 }
b5dc9785 1062
6c139d6e
AL
1063 Change = true;
1064 Done = true;
1065 break;
1066 }
1067 else
1068 {
308c7d30
IJ
1069 if (Start->Type == pkgCache::Dep::DpkgBreaks)
1070 {
76264cb7
MV
1071 // first, try upgradring the package, if that
1072 // does not help, the breaks goes onto the
1073 // kill list
2ba99db8 1074 //
76264cb7 1075 // FIXME: use DoUpgrade(Pkg) instead?
2ba99db8 1076 if (Cache[End] & pkgDepCache::DepGCVer)
76264cb7 1077 {
308c7d30 1078 if (Debug)
47f6d1b7 1079 clog << " Upgrading " << Pkg.FullName(false) << " due to Breaks field in " << I.FullName(false) << endl;
308c7d30
IJ
1080 Cache.MarkInstall(Pkg, false, 0, false);
1081 continue;
1082 }
308c7d30
IJ
1083 }
1084
648e3cb4 1085 // Skip adding to the kill list if it is protected
6c139d6e
AL
1086 if ((Flags[Pkg->ID] & Protected) != 0)
1087 continue;
a6bfe583
AL
1088
1089 if (Debug == true)
47f6d1b7 1090 clog << " Added " << Pkg.FullName(false) << " to the remove list" << endl;
6c139d6e
AL
1091
1092 LEnd->Pkg = Pkg;
1093 LEnd->Dep = End;
1094 LEnd++;
0a8e3465 1095
b2e465d6
AL
1096 if (Start->Type != pkgCache::Dep::Conflicts &&
1097 Start->Type != pkgCache::Dep::Obsoletes)
6c139d6e
AL
1098 break;
1099 }
1100 }
1101
1102 // Hm, nothing can possibly satisify this dep. Nuke it.
359e46db
DK
1103 if (VList[0] == 0 &&
1104 Start.IsNegative() == false &&
648e3cb4 1105 (Flags[I->ID] & Protected) != Protected)
6c139d6e 1106 {
648e3cb4 1107 bool Installed = Cache[I].Install();
6c139d6e
AL
1108 Cache.MarkKeep(I);
1109 if (Cache[I].InstBroken() == false)
1110 {
648e3cb4
AL
1111 // Unwind operation will be keep now
1112 if (OrOp == OrRemove)
1113 OrOp = OrKeep;
1114
1115 // Restore
1116 if (InOr == true && Installed == true)
74a05226 1117 Cache.MarkInstall(I, false, 0, false);
648e3cb4 1118
6c139d6e 1119 if (Debug == true)
47f6d1b7 1120 clog << " Holding Back " << I.FullName(false) << " because I can't find " << Start.TargetPkg().FullName(false) << endl;
6c139d6e
AL
1121 }
1122 else
1123 {
1124 if (Debug == true)
47f6d1b7 1125 clog << " Removing " << I.FullName(false) << " because I can't find " << Start.TargetPkg().FullName(false) << endl;
648e3cb4
AL
1126 if (InOr == false)
1127 Cache.MarkDelete(I);
6c139d6e
AL
1128 }
1129
1130 Change = true;
1131 Done = true;
1132 }
1133
421c8d10
AL
1134 // Try some more
1135 if (InOr == true)
1136 continue;
1137
6c139d6e
AL
1138 if (Done == true)
1139 break;
1140 }
1141
1142 // Apply the kill list now
1143 if (Cache[I].InstallVer != 0)
648e3cb4 1144 {
6c139d6e 1145 for (PackageKill *J = KillList; J != LEnd; J++)
6c139d6e 1146 {
648e3cb4
AL
1147 Change = true;
1148 if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
1149 {
359e46db 1150 if (J->Dep.IsNegative() == true)
648e3cb4
AL
1151 {
1152 if (Debug == true)
47f6d1b7 1153 clog << " Fixing " << I.FullName(false) << " via remove of " << J->Pkg.FullName(false) << endl;
648e3cb4
AL
1154 Cache.MarkDelete(J->Pkg);
1155 }
1156 }
1157 else
6c139d6e
AL
1158 {
1159 if (Debug == true)
47f6d1b7 1160 clog << " Fixing " << I.FullName(false) << " via keep of " << J->Pkg.FullName(false) << endl;
74a05226 1161 Cache.MarkKeep(J->Pkg, false, false);
6c139d6e 1162 }
b2e465d6 1163
648e3cb4 1164 if (Counter > 1)
b2e465d6
AL
1165 {
1166 if (Scores[I->ID] > Scores[J->Pkg->ID])
1167 Scores[J->Pkg->ID] = Scores[I->ID];
1168 }
648e3cb4
AL
1169 }
1170 }
1171 }
6c139d6e
AL
1172 }
1173
1174 if (Debug == true)
0a8e3465 1175 clog << "Done" << endl;
b2e465d6 1176
6c139d6e 1177 if (Cache.BrokenCount() != 0)
b5dc9785
AL
1178 {
1179 // See if this is the result of a hold
1180 pkgCache::PkgIterator I = Cache.PkgBegin();
1181 for (;I.end() != true; I++)
1182 {
1183 if (Cache[I].InstBroken() == false)
1184 continue;
1185 if ((Flags[I->ID] & Protected) != Protected)
b2e465d6 1186 return _error->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
b5dc9785 1187 }
b2e465d6 1188 return _error->Error(_("Unable to correct problems, you have held broken packages."));
b5dc9785
AL
1189 }
1190
fce72602 1191 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
80fa0d8a
MV
1192 pkgCache::PkgIterator I = Cache.PkgBegin();
1193 for (;I.end() != true; I++) {
1194 if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
120365ce 1195 if(_config->FindI("Debug::pkgAutoRemove",false)) {
47f6d1b7 1196 std::clog << "Resolve installed new pkg: " << I.FullName(false)
120365ce
MV
1197 << " (now marking it as auto)" << std::endl;
1198 }
80fa0d8a
MV
1199 Cache[I].Flags |= pkgCache::Flag::Auto;
1200 }
1201 }
1202
1203
0a8e3465
AL
1204 return true;
1205}
1206 /*}}}*/
1207// ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1208// ---------------------------------------------------------------------
1209/* This is the work horse of the soft upgrade routine. It is very gental
1210 in that it does not install or remove any packages. It is assumed that the
1211 system was non-broken previously. */
1212bool pkgProblemResolver::ResolveByKeep()
741b7da9 1213{
98278a81 1214 std::string const solver = _config->Find("APT::Solver", "internal");
b57c0e35
DK
1215 if (solver != "internal") {
1216 OpTextProgress Prog(*_config);
1217 return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog);
1218 }
741b7da9
DK
1219 return ResolveByKeepInternal();
1220}
1221 /*}}}*/
1222// ProblemResolver::ResolveByKeepInternal - Resolve problems using keep /*{{{*/
1223// ---------------------------------------------------------------------
1224/* This is the work horse of the soft upgrade routine. It is very gental
1225 in that it does not install or remove any packages. It is assumed that the
1226 system was non-broken previously. */
1227bool pkgProblemResolver::ResolveByKeepInternal()
0a8e3465 1228{
74a05226
MV
1229 pkgDepCache::ActionGroup group(Cache);
1230
b2e465d6 1231 unsigned long Size = Cache.Head().PackageCount;
0a8e3465 1232
0a8e3465
AL
1233 MakeScores();
1234
1235 /* We have to order the packages so that the broken fixing pass
1236 operates from highest score to lowest. This prevents problems when
1237 high score packages cause the removal of lower score packages that
1238 would cause the removal of even lower score packages. */
1239 pkgCache::Package **PList = new pkgCache::Package *[Size];
1240 pkgCache::Package **PEnd = PList;
1241 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
1242 *PEnd++ = I;
1243 This = this;
1244 qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
8b4894fe
MV
1245
1246 if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1247 {
1248 clog << "Show Scores" << endl;
1249 for (pkgCache::Package **K = PList; K != PEnd; K++)
1250 if (Scores[(*K)->ID] != 0)
1251 {
1252 pkgCache::PkgIterator Pkg(Cache,*K);
1253 clog << Scores[(*K)->ID] << ' ' << Pkg << std::endl;
1254 }
1255 }
1256
1257 if (Debug == true)
1258 clog << "Entering ResolveByKeep" << endl;
1259
0a8e3465
AL
1260 // Consider each broken package
1261 pkgCache::Package **LastStop = 0;
1262 for (pkgCache::Package **K = PList; K != PEnd; K++)
1263 {
1264 pkgCache::PkgIterator I(Cache,*K);
1265
1266 if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
1267 continue;
1268
1269 /* Keep the package. If this works then great, otherwise we have
b2e465d6 1270 to be significantly more agressive and manipulate its dependencies */
0a8e3465
AL
1271 if ((Flags[I->ID] & Protected) == 0)
1272 {
1273 if (Debug == true)
47f6d1b7 1274 clog << "Keeping package " << I.FullName(false) << endl;
74a05226 1275 Cache.MarkKeep(I, false, false);
0a8e3465
AL
1276 if (Cache[I].InstBroken() == false)
1277 {
b2e465d6 1278 K = PList - 1;
0a8e3465
AL
1279 continue;
1280 }
1281 }
1282
1283 // Isolate the problem dependencies
1284 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
1285 {
c5532863
AL
1286 DepIterator Start;
1287 DepIterator End;
1288 D.GlobOr(Start,End);
1289
0a8e3465
AL
1290 // We only worry about critical deps.
1291 if (End.IsCritical() != true)
1292 continue;
1293
1294 // Dep is ok
1295 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
1296 continue;
c5532863
AL
1297
1298 /* Hm, the group is broken.. I suppose the best thing to do is to
1299 is to try every combination of keep/not-keep for the set, but thats
1300 slow, and this never happens, just be conservative and assume the
1301 list of ors is in preference and keep till it starts to work. */
1302 while (true)
0a8e3465 1303 {
c5532863 1304 if (Debug == true)
47f6d1b7 1305 clog << "Package " << I.FullName(false) << " " << Start << endl;
8b4894fe 1306
c5532863
AL
1307 // Look at all the possible provides on this package
1308 SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
1309 for (pkgCache::Version **V = VList; *V != 0; V++)
0a8e3465 1310 {
c5532863
AL
1311 pkgCache::VerIterator Ver(Cache,*V);
1312 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
1313
1314 // It is not keepable
1315 if (Cache[Pkg].InstallVer == 0 ||
1316 Pkg->CurrentVer == 0)
1317 continue;
1318
1319 if ((Flags[I->ID] & Protected) == 0)
1320 {
1321 if (Debug == true)
47f6d1b7 1322 clog << " Keeping Package " << Pkg.FullName(false) << " due to " << Start.DepType() << endl;
74a05226 1323 Cache.MarkKeep(Pkg, false, false);
c5532863
AL
1324 }
1325
1326 if (Cache[I].InstBroken() == false)
1327 break;
0a8e3465
AL
1328 }
1329
1330 if (Cache[I].InstBroken() == false)
1331 break;
0a8e3465 1332
c5532863
AL
1333 if (Start == End)
1334 break;
1335 Start++;
1336 }
1337
0a8e3465
AL
1338 if (Cache[I].InstBroken() == false)
1339 break;
1340 }
1341
1342 if (Cache[I].InstBroken() == true)
1343 continue;
1344
1345 // Restart again.
1346 if (K == LastStop)
09a10f9c 1347 return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.FullName(false).c_str());
0a8e3465 1348 LastStop = K;
b2e465d6 1349 K = PList - 1;
0a8e3465 1350 }
6c139d6e
AL
1351
1352 return true;
1353}
1354 /*}}}*/
3b5421b4
AL
1355// ProblemResolver::InstallProtect - Install all protected packages /*{{{*/
1356// ---------------------------------------------------------------------
1357/* This is used to make sure protected packages are installed */
1358void pkgProblemResolver::InstallProtect()
1359{
74a05226
MV
1360 pkgDepCache::ActionGroup group(Cache);
1361
3b5421b4
AL
1362 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
1363 {
1364 if ((Flags[I->ID] & Protected) == Protected)
1365 {
1366 if ((Flags[I->ID] & ToRemove) == ToRemove)
1367 Cache.MarkDelete(I);
c15f5690
MV
1368 else
1369 {
da543ed8
OS
1370 // preserve the information whether the package was auto
1371 // or manually installed
c15f5690
MV
1372 bool autoInst = (Cache[I].Flags & pkgCache::Flag::Auto);
1373 Cache.MarkInstall(I, false, 0, !autoInst);
1374 }
3b5421b4
AL
1375 }
1376 }
1377}
1378 /*}}}*/
b2e465d6
AL
1379// PrioSortList - Sort a list of versions by priority /*{{{*/
1380// ---------------------------------------------------------------------
1381/* This is ment to be used in conjunction with AllTargets to get a list
1382 of versions ordered by preference. */
1383static pkgCache *PrioCache;
1384static int PrioComp(const void *A,const void *B)
1385{
1386 pkgCache::VerIterator L(*PrioCache,*(pkgCache::Version **)A);
1387 pkgCache::VerIterator R(*PrioCache,*(pkgCache::Version **)B);
1388
1389 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential &&
b8c0f9b7
AL
1390 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
1391 return 1;
b2e465d6 1392 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
b8c0f9b7
AL
1393 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
1394 return -1;
b2e465d6
AL
1395
1396 if (L->Priority != R->Priority)
b8c0f9b7 1397 return R->Priority - L->Priority;
b2e465d6
AL
1398 return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
1399}
1400void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
1401{
1402 unsigned long Count = 0;
1403 PrioCache = &Cache;
1404 for (pkgCache::Version **I = List; *I != 0; I++)
1405 Count++;
1406 qsort(List,Count,sizeof(*List),PrioComp);
1407}
1408 /*}}}*/
760d4968
MV
1409// CacheFile::ListUpdate - update the cache files /*{{{*/
1410// ---------------------------------------------------------------------
1411/* This is a simple wrapper to update the cache. it will fetch stuff
1412 * from the network (or any other sources defined in sources.list)
1413 */
1414bool ListUpdate(pkgAcquireStatus &Stat,
1415 pkgSourceList &List,
1416 int PulseInterval)
1417{
1418 pkgAcquire::RunResult res;
1cd1c398
DK
1419 pkgAcquire Fetcher;
1420 if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false)
1421 return false;
760d4968
MV
1422
1423 // Populate it with the source selection
1424 if (List.GetIndexes(&Fetcher) == false)
1425 return false;
1426
1427 // Run scripts
1428 RunScripts("APT::Update::Pre-Invoke");
1429
1430 // check arguments
1431 if(PulseInterval>0)
1432 res = Fetcher.Run(PulseInterval);
1433 else
1434 res = Fetcher.Run();
1435
1436 if (res == pkgAcquire::Failed)
1437 return false;
1438
1439 bool Failed = false;
1440 bool TransientNetworkFailure = false;
1441 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin();
1442 I != Fetcher.ItemsEnd(); I++)
1443 {
1444 if ((*I)->Status == pkgAcquire::Item::StatDone)
1445 continue;
1446
1447 (*I)->Finished();
1448
70b3d263
MV
1449 ::URI uri((*I)->DescURI());
1450 uri.User.clear();
1451 uri.Password.clear();
1452 string descUri = string(uri);
4805f1cf 1453 _error->Warning(_("Failed to fetch %s %s\n"), descUri.c_str(),
760d4968
MV
1454 (*I)->ErrorText.c_str());
1455
1456 if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError)
1457 {
1458 TransientNetworkFailure = true;
1459 continue;
1460 }
1461
1462 Failed = true;
1463 }
1464
1465 // Clean out any old list files
1466 // Keep "APT::Get::List-Cleanup" name for compatibility, but
1467 // this is really a global option for the APT library now
1468 if (!TransientNetworkFailure && !Failed &&
b7c5ca8c 1469 (_config->FindB("APT::Get::List-Cleanup",true) == true &&
760d4968
MV
1470 _config->FindB("APT::List-Cleanup",true) == true))
1471 {
1472 if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
1473 Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
1474 // something went wrong with the clean
1475 return false;
1476 }
1477
1478 if (TransientNetworkFailure == true)
196c511c 1479 _error->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead."));
760d4968 1480 else if (Failed == true)
196c511c 1481 return _error->Error(_("Some index files failed to download. They have been ignored, or old ones used instead."));
760d4968
MV
1482
1483
e06c72cd
MV
1484 // Run the success scripts if all was fine
1485 if(!TransientNetworkFailure && !Failed)
1486 RunScripts("APT::Update::Post-Invoke-Success");
1487
1488 // Run the other scripts
760d4968
MV
1489 RunScripts("APT::Update::Post-Invoke");
1490 return true;
1491}
1492 /*}}}*/