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