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