]> git.saurik.com Git - apt.git/blame - apt-pkg/algorithms.cc
* apt-pkg/acquire-item.{cc,h}:
[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);
359e46db 107 if (Start.IsNegative() == true ||
b2e465d6 108 End->Type == pkgCache::Dep::PreDepends)
6c139d6e 109 {
b2e465d6 110 if ((Sim[End] & pkgDepCache::DepGInstall) == 0)
6c139d6e 111 {
47f6d1b7 112 cout << " [" << I.FullName(false) << " on " << Start.TargetPkg().FullName(false) << ']';
b2e465d6 113 if (Start->Type == pkgCache::Dep::Conflicts)
47f6d1b7 114 _error->Error("Fatal, conflicts violated %s",I.FullName(false).c_str());
6c139d6e 115 }
b2e465d6
AL
116 }
117 }
6c139d6e
AL
118 }
119
120 if (Sim.BrokenCount() != 0)
121 ShortBreaks();
122 else
04aa15a8 123 cout << endl;
6c139d6e
AL
124 return true;
125}
126 /*}}}*/
127// Simulate::Configure - Simulate configuration of a Package /*{{{*/
128// ---------------------------------------------------------------------
129/* This is not an acurate simulation of relatity, we should really not
130 install the package.. For some investigations it may be necessary
131 however. */
132bool pkgSimulate::Configure(PkgIterator iPkg)
133{
134 // Adapt the iterator
803ea2a8 135 PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
6c139d6e
AL
136
137 Flags[Pkg->ID] = 2;
803ea2a8 138
6c139d6e
AL
139 if (Sim[Pkg].InstBroken() == true)
140 {
47f6d1b7 141 cout << "Conf " << Pkg.FullName(false) << " broken" << endl;
6c139d6e
AL
142
143 Sim.Update();
144
145 // Print out each package and the failed dependencies
146 for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; D++)
147 {
148 if (Sim.IsImportantDep(D) == false ||
149 (Sim[D] & pkgDepCache::DepInstall) != 0)
150 continue;
151
b2e465d6 152 if (D->Type == pkgCache::Dep::Obsoletes)
47f6d1b7 153 cout << " Obsoletes:" << D.TargetPkg().FullName(false);
b2e465d6 154 else if (D->Type == pkgCache::Dep::Conflicts)
47f6d1b7 155 cout << " Conflicts:" << D.TargetPkg().FullName(false);
308c7d30 156 else if (D->Type == pkgCache::Dep::DpkgBreaks)
47f6d1b7 157 cout << " Breaks:" << D.TargetPkg().FullName(false);
6c139d6e 158 else
47f6d1b7 159 cout << " Depends:" << D.TargetPkg().FullName(false);
6c139d6e 160 }
04aa15a8 161 cout << endl;
6c139d6e 162
09a10f9c 163 _error->Error("Conf Broken %s",Pkg.FullName(false).c_str());
6c139d6e
AL
164 }
165 else
b2e465d6
AL
166 {
167 cout << "Conf ";
3826564e 168 Describe(Pkg,cout,false,true);
b2e465d6 169 }
6c139d6e
AL
170
171 if (Sim.BrokenCount() != 0)
172 ShortBreaks();
173 else
04aa15a8 174 cout << endl;
6c139d6e
AL
175
176 return true;
177}
178 /*}}}*/
179// Simulate::Remove - Simulate the removal of a package /*{{{*/
180// ---------------------------------------------------------------------
181/* */
fc4b5c9f 182bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
6c139d6e
AL
183{
184 // Adapt the iterator
803ea2a8 185 PkgIterator Pkg = Sim.FindPkg(iPkg.Name(), iPkg.Arch());
6c139d6e
AL
186
187 Flags[Pkg->ID] = 3;
188 Sim.MarkDelete(Pkg);
803ea2a8 189
fc4b5c9f 190 if (Purge == true)
b2e465d6 191 cout << "Purg ";
fc4b5c9f 192 else
b2e465d6 193 cout << "Remv ";
3826564e 194 Describe(Pkg,cout,true,false);
6c139d6e
AL
195
196 if (Sim.BrokenCount() != 0)
197 ShortBreaks();
198 else
04aa15a8 199 cout << endl;
6c139d6e
AL
200
201 return true;
202}
203 /*}}}*/
204// Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
205// ---------------------------------------------------------------------
206/* */
207void pkgSimulate::ShortBreaks()
208{
04aa15a8 209 cout << " [";
6c139d6e
AL
210 for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
211 {
212 if (Sim[I].InstBroken() == true)
213 {
214 if (Flags[I->ID] == 0)
47f6d1b7 215 cout << I.FullName(false) << ' ';
6c139d6e 216/* else
04aa15a8 217 cout << I.Name() << "! ";*/
6c139d6e
AL
218 }
219 }
04aa15a8 220 cout << ']' << endl;
6c139d6e
AL
221}
222 /*}}}*/
223// ApplyStatus - Adjust for non-ok packages /*{{{*/
224// ---------------------------------------------------------------------
225/* We attempt to change the state of the all packages that have failed
226 installation toward their real state. The ordering code will perform
227 the necessary calculations to deal with the problems. */
228bool pkgApplyStatus(pkgDepCache &Cache)
229{
74a05226
MV
230 pkgDepCache::ActionGroup group(Cache);
231
6c139d6e
AL
232 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
233 {
e481d5b0
AL
234 if (I->VersionList == 0)
235 continue;
236
d38b7b3d
AL
237 // Only choice for a ReInstReq package is to reinstall
238 if (I->InstState == pkgCache::State::ReInstReq ||
239 I->InstState == pkgCache::State::HoldReInstReq)
240 {
5871718b 241 if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
74a05226 242 Cache.MarkKeep(I, false, false);
813c8eea
AL
243 else
244 {
245 // Is this right? Will dpkg choke on an upgrade?
2a3f3893
AL
246 if (Cache[I].CandidateVer != 0 &&
247 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
74a05226 248 Cache.MarkInstall(I, false, 0, false);
813c8eea 249 else
b2e465d6 250 return _error->Error(_("The package %s needs to be reinstalled, "
09a10f9c 251 "but I can't find an archive for it."),I.FullName(true).c_str());
813c8eea
AL
252 }
253
d38b7b3d
AL
254 continue;
255 }
256
6c139d6e
AL
257 switch (I->CurrentState)
258 {
813c8eea
AL
259 /* This means installation failed somehow - it does not need to be
260 re-unpacked (probably) */
b518cca6
AL
261 case pkgCache::State::UnPacked:
262 case pkgCache::State::HalfConfigured:
9d06bc80
MV
263 case pkgCache::State::TriggersAwaited:
264 case pkgCache::State::TriggersPending:
5871718b 265 if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) ||
813c8eea 266 I.State() != pkgCache::PkgIterator::NeedsUnpack)
74a05226 267 Cache.MarkKeep(I, false, false);
813c8eea
AL
268 else
269 {
2a3f3893
AL
270 if (Cache[I].CandidateVer != 0 &&
271 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
74a05226 272 Cache.MarkInstall(I, true, 0, false);
813c8eea
AL
273 else
274 Cache.MarkDelete(I);
275 }
6c139d6e
AL
276 break;
277
278 // This means removal failed
b518cca6 279 case pkgCache::State::HalfInstalled:
6c139d6e
AL
280 Cache.MarkDelete(I);
281 break;
282
283 default:
b518cca6 284 if (I->InstState != pkgCache::State::Ok)
6c139d6e 285 return _error->Error("The package %s is not ok and I "
09a10f9c 286 "don't know how to fix it!",I.FullName(false).c_str());
6c139d6e
AL
287 }
288 }
289 return true;
290}
291 /*}}}*/
292// FixBroken - Fix broken packages /*{{{*/
293// ---------------------------------------------------------------------
0a8e3465
AL
294/* This autoinstalls every broken package and then runs the problem resolver
295 on the result. */
6c139d6e
AL
296bool pkgFixBroken(pkgDepCache &Cache)
297{
74a05226
MV
298 pkgDepCache::ActionGroup group(Cache);
299
6c139d6e
AL
300 // Auto upgrade all broken packages
301 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
302 if (Cache[I].NowBroken() == true)
74a05226 303 Cache.MarkInstall(I, true, 0, false);
7e798dd7 304
6c139d6e
AL
305 /* Fix packages that are in a NeedArchive state but don't have a
306 downloadable install version */
307 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
308 {
309 if (I.State() != pkgCache::PkgIterator::NeedsUnpack ||
310 Cache[I].Delete() == true)
311 continue;
312
b518cca6 313 if (Cache[I].InstVerIter(Cache).Downloadable() == false)
6c139d6e
AL
314 continue;
315
74a05226 316 Cache.MarkInstall(I, true, 0, false);
6c139d6e
AL
317 }
318
b2e465d6 319 pkgProblemResolver Fix(&Cache);
6c139d6e
AL
320 return Fix.Resolve(true);
321}
322 /*}}}*/
323// DistUpgrade - Distribution upgrade /*{{{*/
324// ---------------------------------------------------------------------
325/* This autoinstalls every package and then force installs every
326 pre-existing package. This creates the initial set of conditions which
327 most likely contain problems because too many things were installed.
328
0a8e3465 329 The problem resolver is used to resolve the problems.
6c139d6e
AL
330 */
331bool pkgDistUpgrade(pkgDepCache &Cache)
332{
98278a81 333 std::string const solver = _config->Find("APT::Solver", "internal");
b57c0e35
DK
334 if (solver != "internal") {
335 OpTextProgress Prog(*_config);
336 return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, &Prog);
337 }
741b7da9 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{
98278a81 391 std::string const solver = _config->Find("APT::Solver", "internal");
b57c0e35
DK
392 if (solver != "internal") {
393 OpTextProgress Prog(*_config);
394 return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog);
395 }
741b7da9 396
74a05226
MV
397 pkgDepCache::ActionGroup group(Cache);
398
b2e465d6 399 pkgProblemResolver Fix(&Cache);
0a8e3465
AL
400
401 if (Cache.BrokenCount() != 0)
402 return false;
403
404 // Upgrade all installed packages
405 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
406 {
407 if (Cache[I].Install() == true)
408 Fix.Protect(I);
409
b2e465d6 410 if (_config->FindB("APT::Ignore-Hold",false) == false)
c88edf1d
AL
411 if (I->SelectedState == pkgCache::State::Hold)
412 continue;
0a8e3465
AL
413
414 if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
74a05226 415 Cache.MarkInstall(I, false, 0, false);
0a8e3465
AL
416 }
417
418 return Fix.ResolveByKeep();
419}
420 /*}}}*/
7e798dd7
AL
421// MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/
422// ---------------------------------------------------------------------
423/* This simply goes over the entire set of packages and tries to keep
424 each package marked for upgrade. If a conflict is generated then
425 the package is restored. */
426bool pkgMinimizeUpgrade(pkgDepCache &Cache)
427{
74a05226
MV
428 pkgDepCache::ActionGroup group(Cache);
429
7e798dd7
AL
430 if (Cache.BrokenCount() != 0)
431 return false;
432
abc8419e 433 // We loop for 10 tries to get the minimal set size.
7e798dd7 434 bool Change = false;
a005475e 435 unsigned int Count = 0;
7e798dd7
AL
436 do
437 {
438 Change = false;
439 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
440 {
441 // Not interesting
442 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
443 continue;
a005475e 444
7e798dd7 445 // Keep it and see if that is OK
74a05226 446 Cache.MarkKeep(I, false, false);
7e798dd7 447 if (Cache.BrokenCount() != 0)
74a05226 448 Cache.MarkInstall(I, false, 0, false);
7e798dd7 449 else
a005475e
AL
450 {
451 // If keep didnt actually do anything then there was no change..
452 if (Cache[I].Upgrade() == false)
453 Change = true;
454 }
7e798dd7 455 }
a005475e 456 Count++;
7e798dd7 457 }
a005475e 458 while (Change == true && Count < 10);
7e798dd7
AL
459
460 if (Cache.BrokenCount() != 0)
461 return _error->Error("Internal Error in pkgMinimizeUpgrade");
462
463 return true;
464}
465 /*}}}*/
6c139d6e
AL
466// ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
467// ---------------------------------------------------------------------
468/* */
b2e465d6 469pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : Cache(*pCache)
6c139d6e
AL
470{
471 // Allocate memory
b2e465d6 472 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
473 Scores = new signed short[Size];
474 Flags = new unsigned char[Size];
475 memset(Flags,0,sizeof(*Flags)*Size);
476
477 // Set debug to true to see its decision logic
0a8e3465 478 Debug = _config->FindB("Debug::pkgProblemResolver",false);
6c139d6e
AL
479}
480 /*}}}*/
b2e465d6
AL
481// ProblemResolver::~pkgProblemResolver - Destructor /*{{{*/
482// ---------------------------------------------------------------------
483/* */
484pkgProblemResolver::~pkgProblemResolver()
485{
486 delete [] Scores;
487 delete [] Flags;
488}
489 /*}}}*/
6c139d6e
AL
490// ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
491// ---------------------------------------------------------------------
492/* */
493int pkgProblemResolver::ScoreSort(const void *a,const void *b)
494{
495 Package const **A = (Package const **)a;
496 Package const **B = (Package const **)b;
497 if (This->Scores[(*A)->ID] > This->Scores[(*B)->ID])
498 return -1;
499 if (This->Scores[(*A)->ID] < This->Scores[(*B)->ID])
500 return 1;
501 return 0;
502}
503 /*}}}*/
504// ProblemResolver::MakeScores - Make the score table /*{{{*/
505// ---------------------------------------------------------------------
506/* */
507void pkgProblemResolver::MakeScores()
508{
b2e465d6 509 unsigned long Size = Cache.Head().PackageCount;
6c139d6e
AL
510 memset(Scores,0,sizeof(*Scores)*Size);
511
8b4894fe
MV
512 // Important Required Standard Optional Extra
513 signed short PrioMap[] = {
514 0,
5e5d2064
DK
515 (signed short) _config->FindI("pkgProblemResolver::Scores::Important",3),
516 (signed short) _config->FindI("pkgProblemResolver::Scores::Required",2),
517 (signed short) _config->FindI("pkgProblemResolver::Scores::Standard",1),
518 (signed short) _config->FindI("pkgProblemResolver::Scores::Optional",-1),
519 (signed short) _config->FindI("pkgProblemResolver::Scores::Extra",-2)
8b4894fe
MV
520 };
521 signed short PrioEssentials = _config->FindI("pkgProblemResolver::Scores::Essentials",100);
522 signed short PrioInstalledAndNotObsolete = _config->FindI("pkgProblemResolver::Scores::NotObsolete",1);
523 signed short PrioDepends = _config->FindI("pkgProblemResolver::Scores::Depends",1);
53391d0f 524 signed short PrioRecommends = _config->FindI("pkgProblemResolver::Scores::Recommends",1);
8b4894fe
MV
525 signed short AddProtected = _config->FindI("pkgProblemResolver::Scores::AddProtected",10000);
526 signed short AddEssential = _config->FindI("pkgProblemResolver::Scores::AddEssential",5000);
527
528 if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
529 clog << "Settings used to calculate pkgProblemResolver::Scores::" << endl
530 << " Important => " << PrioMap[1] << endl
531 << " Required => " << PrioMap[2] << endl
532 << " Standard => " << PrioMap[3] << endl
533 << " Optional => " << PrioMap[4] << endl
534 << " Extra => " << PrioMap[5] << endl
535 << " Essentials => " << PrioEssentials << endl
536 << " InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete << endl
537 << " Depends => " << PrioDepends << endl
53391d0f 538 << " Recommends => " << PrioRecommends << endl
8b4894fe
MV
539 << " AddProtected => " << AddProtected << endl
540 << " AddEssential => " << AddEssential << endl;
541
6c139d6e
AL
542 // Generate the base scores for a package based on its properties
543 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
544 {
545 if (Cache[I].InstallVer == 0)
546 continue;
547
548 signed short &Score = Scores[I->ID];
549
7365ff46 550 /* This is arbitrary, it should be high enough to elevate an
6c139d6e
AL
551 essantial package above most other packages but low enough
552 to allow an obsolete essential packages to be removed by
553 a conflicts on a powerfull normal package (ie libc6) */
b518cca6 554 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
8b4894fe 555 Score += PrioEssentials;
6c139d6e
AL
556
557 // We transform the priority
6c139d6e
AL
558 if (Cache[I].InstVerIter(Cache)->Priority <= 5)
559 Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
560
561 /* This helps to fix oddball problems with conflicting packages
4172c784
MV
562 on the same level. We enhance the score of installed packages
563 if those are not obsolete
564 */
020daa7b 565 if (I->CurrentVer != 0 && Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable())
8b4894fe 566 Score += PrioInstalledAndNotObsolete;
6c139d6e
AL
567 }
568
569 // Now that we have the base scores we go and propogate dependencies
570 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
571 {
572 if (Cache[I].InstallVer == 0)
573 continue;
574
575 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
576 {
3a998f6a 577 if (D->Type == pkgCache::Dep::Depends ||
53391d0f
MV
578 D->Type == pkgCache::Dep::PreDepends)
579 Scores[D.TargetPkg()->ID] += PrioDepends;
580 else if (D->Type == pkgCache::Dep::Recommends)
581 Scores[D.TargetPkg()->ID] += PrioRecommends;
6c139d6e
AL
582 }
583 }
584
585 // Copy the scores to advoid additive looping
b2e465d6 586 SPtrArray<signed short> OldScores = new signed short[Size];
6c139d6e
AL
587 memcpy(OldScores,Scores,sizeof(*Scores)*Size);
588
589 /* Now we cause 1 level of dependency inheritance, that is we add the
590 score of the packages that depend on the target Package. This
591 fortifies high scoring packages */
592 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
593 {
594 if (Cache[I].InstallVer == 0)
595 continue;
596
597 for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; D++)
598 {
599 // Only do it for the install version
600 if ((pkgCache::Version *)D.ParentVer() != Cache[D.ParentPkg()].InstallVer ||
3a998f6a
MV
601 (D->Type != pkgCache::Dep::Depends &&
602 D->Type != pkgCache::Dep::PreDepends &&
603 D->Type != pkgCache::Dep::Recommends))
6c139d6e
AL
604 continue;
605
606 Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]);
607 }
608 }
609
610 /* Now we propogate along provides. This makes the packages that
611 provide important packages extremely important */
612 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
613 {
614 for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; P++)
615 {
616 // Only do it once per package
617 if ((pkgCache::Version *)P.OwnerVer() != Cache[P.OwnerPkg()].InstallVer)
618 continue;
619 Scores[P.OwnerPkg()->ID] += abs(Scores[I->ID] - OldScores[I->ID]);
620 }
621 }
622
623 /* Protected things are pushed really high up. This number should put them
624 ahead of everything */
625 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
d2685fd6 626 {
6c139d6e 627 if ((Flags[I->ID] & Protected) != 0)
8b4894fe 628 Scores[I->ID] += AddProtected;
d2685fd6 629 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
8b4894fe
MV
630 Scores[I->ID] += AddEssential;
631 }
6c139d6e
AL
632}
633 /*}}}*/
634// ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
635// ---------------------------------------------------------------------
636/* This goes through and tries to reinstall packages to make this package
637 installable */
638bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
639{
74a05226
MV
640 pkgDepCache::ActionGroup group(Cache);
641
6c139d6e
AL
642 if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
643 return false;
3a486305
AL
644 if ((Flags[Pkg->ID] & Protected) == Protected)
645 return false;
0a8e3465 646
6c139d6e
AL
647 Flags[Pkg->ID] &= ~Upgradable;
648
649 bool WasKept = Cache[Pkg].Keep();
74a05226 650 Cache.MarkInstall(Pkg, false, 0, false);
6c139d6e 651
0a8e3465
AL
652 // This must be a virtual package or something like that.
653 if (Cache[Pkg].InstVerIter(Cache).end() == true)
654 return false;
655
6c139d6e
AL
656 // Isolate the problem dependency
657 bool Fail = false;
658 for (pkgCache::DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false;)
659 {
660 // Compute a single dependency element (glob or)
661 pkgCache::DepIterator Start = D;
662 pkgCache::DepIterator End = D;
4b1b89c5 663 for (bool LastOR = true; D.end() == false && LastOR == true;)
6c139d6e 664 {
b518cca6 665 LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
0284eee4 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 */
359e46db 711 if (Start.IsNegative() == true)
b2e465d6 712 break;
648e3cb4 713
4b1b89c5 714 if (Debug == true)
47f6d1b7 715 clog << " Reinst Failed early because of " << Start.TargetPkg().FullName(false) << endl;
4b1b89c5 716 Fail = true;
648e3cb4 717 }
4b1b89c5 718 }
6c139d6e 719
4b1b89c5
AL
720 if (Start == End)
721 break;
722 Start++;
723 }
724 if (Fail == true)
6c139d6e 725 break;
6c139d6e
AL
726 }
727
728 // Undo our operations - it might be smart to undo everything this did..
729 if (Fail == true)
730 {
731 if (WasKept == true)
74a05226 732 Cache.MarkKeep(Pkg, false, false);
6c139d6e
AL
733 else
734 Cache.MarkDelete(Pkg);
735 return false;
736 }
737
738 if (Debug == true)
47f6d1b7 739 clog << " Re-Instated " << Pkg.FullName(false) << endl;
6c139d6e
AL
740 return true;
741}
742 /*}}}*/
6d38011b
DK
743// ProblemResolver::Resolve - calls a resolver to fix the situation /*{{{*/
744// ---------------------------------------------------------------------
745/* */
746bool pkgProblemResolver::Resolve(bool BrokenFix)
747{
98278a81 748 std::string const solver = _config->Find("APT::Solver", "internal");
b57c0e35
DK
749 if (solver != "internal") {
750 OpTextProgress Prog(*_config);
751 return EDSP::ResolveExternal(solver.c_str(), Cache, false, false, false, &Prog);
752 }
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 &&
359e46db 953 Start.IsNegative() == false &&
fcf85120 954 Cache[I].NowBroken() == false)
648e3cb4
AL
955 {
956 if (InOr == true)
957 {
958 /* No keep choice because the keep being OK could be the
959 result of another element in the OR group! */
960 continue;
961 }
962
fcf85120 963 Change = true;
74a05226 964 Cache.MarkKeep(I, false, false);
fcf85120
AL
965 break;
966 }
967
6c139d6e
AL
968 bool Done = false;
969 for (pkgCache::Version **V = VList; *V != 0; V++)
970 {
971 pkgCache::VerIterator Ver(Cache,*V);
972 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
a6bfe583 973
2ba99db8
MV
974 /* This is a conflicts, and the version we are looking
975 at is not the currently selected version of the
976 package, which means it is not necessary to
977 remove/keep */
359e46db 978 if (Cache[Pkg].InstallVer != Ver && Start.IsNegative() == true)
4429616b 979 {
2ba99db8
MV
980 if (Debug)
981 clog << " Conflicts//Breaks against version "
982 << Ver.VerStr() << " for " << Pkg.Name()
983 << " but that is not InstVer, ignoring"
24e93662 984 << endl;
2ba99db8 985 continue;
4429616b
MV
986 }
987
6c139d6e 988 if (Debug == true)
47f6d1b7
DK
989 clog << " Considering " << Pkg.FullName(false) << ' ' << (int)Scores[Pkg->ID] <<
990 " as a solution to " << I.FullName(false) << ' ' << (int)Scores[I->ID] << endl;
a6bfe583
AL
991
992 /* Try to fix the package under consideration rather than
993 fiddle with the VList package */
6c139d6e 994 if (Scores[I->ID] <= Scores[Pkg->ID] ||
421c8d10 995 ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
359e46db 996 End.IsNegative() == false))
6c139d6e 997 {
200f8c52 998 // Try a little harder to fix protected packages..
3b5421b4 999 if ((Flags[I->ID] & Protected) == Protected)
200f8c52
AL
1000 {
1001 if (DoUpgrade(Pkg) == true)
0296c633 1002 {
b2e465d6
AL
1003 if (Scores[Pkg->ID] > Scores[I->ID])
1004 Scores[Pkg->ID] = Scores[I->ID];
0296c633
AL
1005 break;
1006 }
1007
6c139d6e 1008 continue;
200f8c52
AL
1009 }
1010
1011 /* See if a keep will do, unless the package is protected,
648e3cb4
AL
1012 then installing it will be necessary */
1013 bool Installed = Cache[I].Install();
74a05226 1014 Cache.MarkKeep(I, false, false);
6c139d6e
AL
1015 if (Cache[I].InstBroken() == false)
1016 {
648e3cb4
AL
1017 // Unwind operation will be keep now
1018 if (OrOp == OrRemove)
1019 OrOp = OrKeep;
1020
1021 // Restore
1022 if (InOr == true && Installed == true)
74a05226 1023 Cache.MarkInstall(I, false, 0, false);
648e3cb4 1024
6c139d6e 1025 if (Debug == true)
47f6d1b7 1026 clog << " Holding Back " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
6c139d6e
AL
1027 }
1028 else
421c8d10 1029 {
6c139d6e
AL
1030 if (BrokenFix == false || DoUpgrade(I) == false)
1031 {
421c8d10
AL
1032 // Consider other options
1033 if (InOr == false)
1034 {
6910a2ac 1035 if (Debug == true)
47f6d1b7 1036 clog << " Removing " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
6910a2ac
DK
1037 Cache.MarkDelete(I);
1038 if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID])
1039 Scores[I->ID] = Scores[Pkg->ID];
d6ebeb21 1040 }
09a10f9c
DK
1041 else if (TryFixByInstall == true &&
1042 Start.TargetPkg()->CurrentVer == 0 &&
1043 Cache[Start.TargetPkg()].Delete() == false &&
a3f1a6cc 1044 (Flags[Start.TargetPkg()->ID] & ToRemove) != ToRemove &&
09a10f9c
DK
1045 Cache.GetCandidateVer(Start.TargetPkg()).end() == false)
1046 {
1047 /* Before removing or keeping the package with the broken dependency
1048 try instead to install the first not previously installed package
1049 solving this dependency. This helps every time a previous solver
1050 is removed by the resolver because of a conflict or alike but it is
1051 dangerous as it could trigger new breaks/conflicts… */
443266ef
DK
1052 if (Debug == true)
1053 clog << " Try Installing " << Start.TargetPkg() << " before changing " << I.FullName(false) << std::endl;
09a10f9c
DK
1054 unsigned long const OldBroken = Cache.BrokenCount();
1055 Cache.MarkInstall(Start.TargetPkg(), true, 1, false);
1056 // FIXME: we should undo the complete MarkInstall process here
1057 if (Cache[Start.TargetPkg()].InstBroken() == true || Cache.BrokenCount() > OldBroken)
1058 Cache.MarkDelete(Start.TargetPkg(), false, 1, false);
1059 }
0a8e3465 1060 }
6c139d6e 1061 }
b5dc9785 1062
6c139d6e
AL
1063 Change = true;
1064 Done = true;
1065 break;
1066 }
1067 else
1068 {
308c7d30
IJ
1069 if (Start->Type == pkgCache::Dep::DpkgBreaks)
1070 {
76264cb7
MV
1071 // first, try upgradring the package, if that
1072 // does not help, the breaks goes onto the
1073 // kill list
2ba99db8 1074 //
76264cb7 1075 // FIXME: use DoUpgrade(Pkg) instead?
2ba99db8 1076 if (Cache[End] & pkgDepCache::DepGCVer)
76264cb7 1077 {
308c7d30 1078 if (Debug)
47f6d1b7 1079 clog << " Upgrading " << Pkg.FullName(false) << " due to Breaks field in " << I.FullName(false) << endl;
308c7d30
IJ
1080 Cache.MarkInstall(Pkg, false, 0, false);
1081 continue;
1082 }
308c7d30
IJ
1083 }
1084
648e3cb4 1085 // Skip adding to the kill list if it is protected
6c139d6e
AL
1086 if ((Flags[Pkg->ID] & Protected) != 0)
1087 continue;
a6bfe583
AL
1088
1089 if (Debug == true)
47f6d1b7 1090 clog << " Added " << Pkg.FullName(false) << " to the remove list" << endl;
6c139d6e
AL
1091
1092 LEnd->Pkg = Pkg;
1093 LEnd->Dep = End;
1094 LEnd++;
0a8e3465 1095
b2e465d6
AL
1096 if (Start->Type != pkgCache::Dep::Conflicts &&
1097 Start->Type != pkgCache::Dep::Obsoletes)
6c139d6e
AL
1098 break;
1099 }
1100 }
1101
1102 // Hm, nothing can possibly satisify this dep. Nuke it.
359e46db
DK
1103 if (VList[0] == 0 &&
1104 Start.IsNegative() == false &&
648e3cb4 1105 (Flags[I->ID] & Protected) != Protected)
6c139d6e 1106 {
648e3cb4 1107 bool Installed = Cache[I].Install();
6c139d6e
AL
1108 Cache.MarkKeep(I);
1109 if (Cache[I].InstBroken() == false)
1110 {
648e3cb4
AL
1111 // Unwind operation will be keep now
1112 if (OrOp == OrRemove)
1113 OrOp = OrKeep;
1114
1115 // Restore
1116 if (InOr == true && Installed == true)
74a05226 1117 Cache.MarkInstall(I, false, 0, false);
648e3cb4 1118
6c139d6e 1119 if (Debug == true)
47f6d1b7 1120 clog << " Holding Back " << I.FullName(false) << " because I can't find " << Start.TargetPkg().FullName(false) << endl;
6c139d6e
AL
1121 }
1122 else
1123 {
1124 if (Debug == true)
47f6d1b7 1125 clog << " Removing " << I.FullName(false) << " because I can't find " << Start.TargetPkg().FullName(false) << endl;
648e3cb4
AL
1126 if (InOr == false)
1127 Cache.MarkDelete(I);
6c139d6e
AL
1128 }
1129
1130 Change = true;
1131 Done = true;
1132 }
1133
421c8d10
AL
1134 // Try some more
1135 if (InOr == true)
1136 continue;
1137
6c139d6e
AL
1138 if (Done == true)
1139 break;
1140 }
1141
1142 // Apply the kill list now
1143 if (Cache[I].InstallVer != 0)
648e3cb4 1144 {
6c139d6e 1145 for (PackageKill *J = KillList; J != LEnd; J++)
6c139d6e 1146 {
648e3cb4
AL
1147 Change = true;
1148 if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
1149 {
359e46db 1150 if (J->Dep.IsNegative() == true)
648e3cb4
AL
1151 {
1152 if (Debug == true)
47f6d1b7 1153 clog << " Fixing " << I.FullName(false) << " via remove of " << J->Pkg.FullName(false) << endl;
648e3cb4
AL
1154 Cache.MarkDelete(J->Pkg);
1155 }
1156 }
1157 else
6c139d6e
AL
1158 {
1159 if (Debug == true)
47f6d1b7 1160 clog << " Fixing " << I.FullName(false) << " via keep of " << J->Pkg.FullName(false) << endl;
74a05226 1161 Cache.MarkKeep(J->Pkg, false, false);
6c139d6e 1162 }
b2e465d6 1163
648e3cb4 1164 if (Counter > 1)
b2e465d6
AL
1165 {
1166 if (Scores[I->ID] > Scores[J->Pkg->ID])
1167 Scores[J->Pkg->ID] = Scores[I->ID];
1168 }
648e3cb4
AL
1169 }
1170 }
1171 }
6c139d6e
AL
1172 }
1173
1174 if (Debug == true)
0a8e3465 1175 clog << "Done" << endl;
b2e465d6 1176
6c139d6e 1177 if (Cache.BrokenCount() != 0)
b5dc9785
AL
1178 {
1179 // See if this is the result of a hold
1180 pkgCache::PkgIterator I = Cache.PkgBegin();
1181 for (;I.end() != true; I++)
1182 {
1183 if (Cache[I].InstBroken() == false)
1184 continue;
1185 if ((Flags[I->ID] & Protected) != Protected)
b2e465d6 1186 return _error->Error(_("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages."));
b5dc9785 1187 }
b2e465d6 1188 return _error->Error(_("Unable to correct problems, you have held broken packages."));
b5dc9785
AL
1189 }
1190
fce72602 1191 // set the auto-flags (mvo: I'm not sure if we _really_ need this)
80fa0d8a
MV
1192 pkgCache::PkgIterator I = Cache.PkgBegin();
1193 for (;I.end() != true; I++) {
1194 if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
120365ce 1195 if(_config->FindI("Debug::pkgAutoRemove",false)) {
47f6d1b7 1196 std::clog << "Resolve installed new pkg: " << I.FullName(false)
120365ce
MV
1197 << " (now marking it as auto)" << std::endl;
1198 }
80fa0d8a
MV
1199 Cache[I].Flags |= pkgCache::Flag::Auto;
1200 }
1201 }
1202
1203
0a8e3465
AL
1204 return true;
1205}
1206 /*}}}*/
953b348c
MV
1207
1208// ProblemResolver::BreaksInstOrPolicy - Check if the given pkg is broken/*{{{*/
1209// ---------------------------------------------------------------------
1210/* This checks if the given package is broken either by a hard dependency
1211 (InstBroken()) or by introducing a new policy breakage e.g. new
1212 unsatisfied recommends for a package that was in "policy-good" state
1213
1214 Note that this is not perfect as it will ignore further breakage
1215 for already broken policy (recommends)
1216*/
1217bool pkgProblemResolver::InstOrNewPolicyBroken(pkgCache::PkgIterator I)
1218{
1219
1220 // a broken install is always a problem
1221 if (Cache[I].InstBroken() == true)
1222 return true;
1223
1224 // a newly broken policy (recommends/suggests) is a problem
1225 if (Cache[I].NowPolicyBroken() == false &&
1226 Cache[I].InstPolicyBroken() == true)
1227 return true;
1228
1229 return false;
1230}
1231
0a8e3465
AL
1232// ProblemResolver::ResolveByKeep - Resolve problems using keep /*{{{*/
1233// ---------------------------------------------------------------------
1234/* This is the work horse of the soft upgrade routine. It is very gental
1235 in that it does not install or remove any packages. It is assumed that the
1236 system was non-broken previously. */
1237bool pkgProblemResolver::ResolveByKeep()
741b7da9 1238{
98278a81 1239 std::string const solver = _config->Find("APT::Solver", "internal");
b57c0e35
DK
1240 if (solver != "internal") {
1241 OpTextProgress Prog(*_config);
1242 return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog);
1243 }
741b7da9
DK
1244 return ResolveByKeepInternal();
1245}
1246 /*}}}*/
1247// ProblemResolver::ResolveByKeepInternal - Resolve problems using keep /*{{{*/
1248// ---------------------------------------------------------------------
1249/* This is the work horse of the soft upgrade routine. It is very gental
1250 in that it does not install or remove any packages. It is assumed that the
1251 system was non-broken previously. */
1252bool pkgProblemResolver::ResolveByKeepInternal()
0a8e3465 1253{
74a05226
MV
1254 pkgDepCache::ActionGroup group(Cache);
1255
b2e465d6 1256 unsigned long Size = Cache.Head().PackageCount;
0a8e3465 1257
0a8e3465
AL
1258 MakeScores();
1259
1260 /* We have to order the packages so that the broken fixing pass
1261 operates from highest score to lowest. This prevents problems when
1262 high score packages cause the removal of lower score packages that
1263 would cause the removal of even lower score packages. */
1264 pkgCache::Package **PList = new pkgCache::Package *[Size];
1265 pkgCache::Package **PEnd = PList;
1266 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
1267 *PEnd++ = I;
1268 This = this;
1269 qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
8b4894fe
MV
1270
1271 if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
1272 {
1273 clog << "Show Scores" << endl;
1274 for (pkgCache::Package **K = PList; K != PEnd; K++)
1275 if (Scores[(*K)->ID] != 0)
1276 {
1277 pkgCache::PkgIterator Pkg(Cache,*K);
1278 clog << Scores[(*K)->ID] << ' ' << Pkg << std::endl;
1279 }
1280 }
1281
1282 if (Debug == true)
1283 clog << "Entering ResolveByKeep" << endl;
1284
0a8e3465
AL
1285 // Consider each broken package
1286 pkgCache::Package **LastStop = 0;
1287 for (pkgCache::Package **K = PList; K != PEnd; K++)
1288 {
1289 pkgCache::PkgIterator I(Cache,*K);
1290
953b348c 1291 if (Cache[I].InstallVer == 0)
0a8e3465
AL
1292 continue;
1293
953b348c
MV
1294 if (InstOrNewPolicyBroken(I) == false)
1295 continue;
1296
0a8e3465 1297 /* Keep the package. If this works then great, otherwise we have
b2e465d6 1298 to be significantly more agressive and manipulate its dependencies */
0a8e3465
AL
1299 if ((Flags[I->ID] & Protected) == 0)
1300 {
1301 if (Debug == true)
47f6d1b7 1302 clog << "Keeping package " << I.FullName(false) << endl;
74a05226 1303 Cache.MarkKeep(I, false, false);
953b348c 1304 if (InstOrNewPolicyBroken(I) == false)
0a8e3465 1305 {
b2e465d6 1306 K = PList - 1;
0a8e3465
AL
1307 continue;
1308 }
1309 }
1310
1311 // Isolate the problem dependencies
1312 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
1313 {
c5532863
AL
1314 DepIterator Start;
1315 DepIterator End;
1316 D.GlobOr(Start,End);
1317
0a8e3465
AL
1318 // We only worry about critical deps.
1319 if (End.IsCritical() != true)
1320 continue;
1321
1322 // Dep is ok
1323 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
1324 continue;
c5532863
AL
1325
1326 /* Hm, the group is broken.. I suppose the best thing to do is to
1327 is to try every combination of keep/not-keep for the set, but thats
1328 slow, and this never happens, just be conservative and assume the
1329 list of ors is in preference and keep till it starts to work. */
1330 while (true)
0a8e3465 1331 {
c5532863 1332 if (Debug == true)
47f6d1b7 1333 clog << "Package " << I.FullName(false) << " " << Start << endl;
8b4894fe 1334
c5532863
AL
1335 // Look at all the possible provides on this package
1336 SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
1337 for (pkgCache::Version **V = VList; *V != 0; V++)
0a8e3465 1338 {
c5532863
AL
1339 pkgCache::VerIterator Ver(Cache,*V);
1340 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
1341
1342 // It is not keepable
1343 if (Cache[Pkg].InstallVer == 0 ||
1344 Pkg->CurrentVer == 0)
1345 continue;
1346
1347 if ((Flags[I->ID] & Protected) == 0)
1348 {
1349 if (Debug == true)
47f6d1b7 1350 clog << " Keeping Package " << Pkg.FullName(false) << " due to " << Start.DepType() << endl;
74a05226 1351 Cache.MarkKeep(Pkg, false, false);
c5532863
AL
1352 }
1353
953b348c 1354 if (InstOrNewPolicyBroken(I) == false)
c5532863 1355 break;
0a8e3465
AL
1356 }
1357
953b348c 1358 if (InstOrNewPolicyBroken(I) == false)
0a8e3465 1359 break;
0a8e3465 1360
c5532863
AL
1361 if (Start == End)
1362 break;
1363 Start++;
1364 }
1365
953b348c 1366 if (InstOrNewPolicyBroken(I) == false)
0a8e3465
AL
1367 break;
1368 }
1369
953b348c 1370 if (InstOrNewPolicyBroken(I) == true)
0a8e3465
AL
1371 continue;
1372
1373 // Restart again.
1374 if (K == LastStop)
09a10f9c 1375 return _error->Error("Internal Error, pkgProblemResolver::ResolveByKeep is looping on package %s.",I.FullName(false).c_str());
0a8e3465 1376 LastStop = K;
b2e465d6 1377 K = PList - 1;
0a8e3465 1378 }
6c139d6e
AL
1379
1380 return true;
1381}
1382 /*}}}*/
3b5421b4
AL
1383// ProblemResolver::InstallProtect - Install all protected packages /*{{{*/
1384// ---------------------------------------------------------------------
1385/* This is used to make sure protected packages are installed */
1386void pkgProblemResolver::InstallProtect()
1387{
74a05226
MV
1388 pkgDepCache::ActionGroup group(Cache);
1389
3b5421b4
AL
1390 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
1391 {
1392 if ((Flags[I->ID] & Protected) == Protected)
1393 {
1394 if ((Flags[I->ID] & ToRemove) == ToRemove)
1395 Cache.MarkDelete(I);
c15f5690
MV
1396 else
1397 {
da543ed8
OS
1398 // preserve the information whether the package was auto
1399 // or manually installed
c15f5690
MV
1400 bool autoInst = (Cache[I].Flags & pkgCache::Flag::Auto);
1401 Cache.MarkInstall(I, false, 0, !autoInst);
1402 }
3b5421b4
AL
1403 }
1404 }
1405}
1406 /*}}}*/
b2e465d6
AL
1407// PrioSortList - Sort a list of versions by priority /*{{{*/
1408// ---------------------------------------------------------------------
1409/* This is ment to be used in conjunction with AllTargets to get a list
1410 of versions ordered by preference. */
1411static pkgCache *PrioCache;
1412static int PrioComp(const void *A,const void *B)
1413{
1414 pkgCache::VerIterator L(*PrioCache,*(pkgCache::Version **)A);
1415 pkgCache::VerIterator R(*PrioCache,*(pkgCache::Version **)B);
1416
1417 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential &&
b8c0f9b7
AL
1418 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
1419 return 1;
b2e465d6 1420 if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
b8c0f9b7
AL
1421 (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
1422 return -1;
b2e465d6
AL
1423
1424 if (L->Priority != R->Priority)
b8c0f9b7 1425 return R->Priority - L->Priority;
b2e465d6
AL
1426 return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
1427}
1428void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
1429{
1430 unsigned long Count = 0;
1431 PrioCache = &Cache;
1432 for (pkgCache::Version **I = List; *I != 0; I++)
1433 Count++;
1434 qsort(List,Count,sizeof(*List),PrioComp);
1435}
1436 /*}}}*/
760d4968
MV
1437// CacheFile::ListUpdate - update the cache files /*{{{*/
1438// ---------------------------------------------------------------------
1439/* This is a simple wrapper to update the cache. it will fetch stuff
1440 * from the network (or any other sources defined in sources.list)
1441 */
1442bool ListUpdate(pkgAcquireStatus &Stat,
1443 pkgSourceList &List,
1444 int PulseInterval)
1445{
1446 pkgAcquire::RunResult res;
1cd1c398
DK
1447 pkgAcquire Fetcher;
1448 if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false)
1449 return false;
760d4968
MV
1450
1451 // Populate it with the source selection
1452 if (List.GetIndexes(&Fetcher) == false)
1453 return false;
1454
1455 // Run scripts
1456 RunScripts("APT::Update::Pre-Invoke");
1457
1458 // check arguments
1459 if(PulseInterval>0)
1460 res = Fetcher.Run(PulseInterval);
1461 else
1462 res = Fetcher.Run();
1463
1464 if (res == pkgAcquire::Failed)
1465 return false;
1466
1467 bool Failed = false;
1468 bool TransientNetworkFailure = false;
1469 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin();
1470 I != Fetcher.ItemsEnd(); I++)
1471 {
1472 if ((*I)->Status == pkgAcquire::Item::StatDone)
1473 continue;
1474
1475 (*I)->Finished();
1476
70b3d263
MV
1477 ::URI uri((*I)->DescURI());
1478 uri.User.clear();
1479 uri.Password.clear();
1480 string descUri = string(uri);
4805f1cf 1481 _error->Warning(_("Failed to fetch %s %s\n"), descUri.c_str(),
760d4968
MV
1482 (*I)->ErrorText.c_str());
1483
1484 if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError)
1485 {
1486 TransientNetworkFailure = true;
1487 continue;
1488 }
1489
1490 Failed = true;
1491 }
1492
1493 // Clean out any old list files
1494 // Keep "APT::Get::List-Cleanup" name for compatibility, but
1495 // this is really a global option for the APT library now
1496 if (!TransientNetworkFailure && !Failed &&
b7c5ca8c 1497 (_config->FindB("APT::Get::List-Cleanup",true) == true &&
760d4968
MV
1498 _config->FindB("APT::List-Cleanup",true) == true))
1499 {
1500 if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
1501 Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
1502 // something went wrong with the clean
1503 return false;
1504 }
1505
1506 if (TransientNetworkFailure == true)
196c511c 1507 _error->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead."));
760d4968 1508 else if (Failed == true)
196c511c 1509 return _error->Error(_("Some index files failed to download. They have been ignored, or old ones used instead."));
760d4968
MV
1510
1511
e06c72cd
MV
1512 // Run the success scripts if all was fine
1513 if(!TransientNetworkFailure && !Failed)
1514 RunScripts("APT::Update::Post-Invoke-Success");
1515
1516 // Run the other scripts
760d4968
MV
1517 RunScripts("APT::Update::Post-Invoke");
1518 return true;
1519}
1520 /*}}}*/