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