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