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