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