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