]> git.saurik.com Git - apt.git/blob - apt-pkg/depcache.cc
c6bf3185ae2b09bb4e093c6d91a02bf53f544b15
[apt.git] / apt-pkg / depcache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: depcache.cc,v 1.25 2001/05/27 05:36:04 jgg Exp $
4 /* ######################################################################
5
6 Dependency Cache - Caches Dependency information.
7
8 ##################################################################### */
9 /*}}}*/
10 // Include Files /*{{{*/
11 #ifdef __GNUG__
12 #pragma implementation "apt-pkg/depcache.h"
13 #endif
14 #include <apt-pkg/depcache.h>
15 #include <apt-pkg/version.h>
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/sptr.h>
18 #include <apt-pkg/algorithms.h>
19
20 #include <apti18n.h>
21 /*}}}*/
22
23 // DepCache::pkgDepCache - Constructors /*{{{*/
24 // ---------------------------------------------------------------------
25 /* */
26 pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
27 Cache(pCache), PkgState(0), DepState(0)
28 {
29 delLocalPolicy = 0;
30 LocalPolicy = Plcy;
31 if (LocalPolicy == 0)
32 delLocalPolicy = LocalPolicy = new Policy;
33 }
34 /*}}}*/
35 // DepCache::~pkgDepCache - Destructor /*{{{*/
36 // ---------------------------------------------------------------------
37 /* */
38 pkgDepCache::~pkgDepCache()
39 {
40 delete [] PkgState;
41 delete [] DepState;
42 delete delLocalPolicy;
43 }
44 /*}}}*/
45 // DepCache::Init - Generate the initial extra structures. /*{{{*/
46 // ---------------------------------------------------------------------
47 /* This allocats the extension buffers and initializes them. */
48 bool pkgDepCache::Init(OpProgress *Prog)
49 {
50 delete [] PkgState;
51 delete [] DepState;
52 PkgState = new StateCache[Head().PackageCount];
53 DepState = new unsigned char[Head().DependsCount];
54 memset(PkgState,0,sizeof(*PkgState)*Head().PackageCount);
55 memset(DepState,0,sizeof(*DepState)*Head().DependsCount);
56
57 if (Prog != 0)
58 {
59 Prog->OverallProgress(0,2*Head().PackageCount,Head().PackageCount,
60 _("Building dependency tree"));
61 Prog->SubProgress(Head().PackageCount,_("Candidate versions"));
62 }
63
64 /* Set the current state of everything. In this state all of the
65 packages are kept exactly as is. See AllUpgrade */
66 int Done = 0;
67 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
68 {
69 if (Prog != 0)
70 Prog->Progress(Done);
71
72 // Find the proper cache slot
73 StateCache &State = PkgState[I->ID];
74 State.iFlags = 0;
75
76 // Figure out the install version
77 State.CandidateVer = GetCandidateVer(I);
78 State.InstallVer = I.CurrentVer();
79 State.Mode = ModeKeep;
80
81 State.Update(I,*this);
82 }
83
84 if (Prog != 0)
85 {
86
87 Prog->OverallProgress(Head().PackageCount,2*Head().PackageCount,
88 Head().PackageCount,
89 _("Building dependency tree"));
90 Prog->SubProgress(Head().PackageCount,_("Dependency generation"));
91 }
92
93 Update(Prog);
94
95 return true;
96 }
97 /*}}}*/
98
99 // DepCache::CheckDep - Checks a single dependency /*{{{*/
100 // ---------------------------------------------------------------------
101 /* This first checks the dependency against the main target package and
102 then walks along the package provides list and checks if each provides
103 will be installed then checks the provides against the dep. Res will be
104 set to the package which was used to satisfy the dep. */
105 bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
106 {
107 Res = Dep.TargetPkg();
108
109 /* Check simple depends. A depends -should- never self match but
110 we allow it anyhow because dpkg does. Technically it is a packaging
111 bug. Conflicts may never self match */
112 if (Dep.TargetPkg() != Dep.ParentPkg() ||
113 (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes))
114 {
115 PkgIterator Pkg = Dep.TargetPkg();
116 // Check the base package
117 if (Type == NowVersion && Pkg->CurrentVer != 0)
118 if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep->CompareOp,
119 Dep.TargetVer()) == true)
120 return true;
121
122 if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
123 if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
124 Dep->CompareOp,Dep.TargetVer()) == true)
125 return true;
126
127 if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
128 if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
129 Dep->CompareOp,Dep.TargetVer()) == true)
130 return true;
131 }
132
133 if (Dep->Type == Dep::Obsoletes)
134 return false;
135
136 // Check the providing packages
137 PrvIterator P = Dep.TargetPkg().ProvidesList();
138 PkgIterator Pkg = Dep.ParentPkg();
139 for (; P.end() != true; P++)
140 {
141 /* Provides may never be applied against the same package if it is
142 a conflicts. See the comment above. */
143 if (P.OwnerPkg() == Pkg && Dep->Type == Dep::Conflicts)
144 continue;
145
146 // Check if the provides is a hit
147 if (Type == NowVersion)
148 {
149 if (P.OwnerPkg().CurrentVer() != P.OwnerVer())
150 continue;
151 }
152
153 if (Type == InstallVersion)
154 {
155 StateCache &State = PkgState[P.OwnerPkg()->ID];
156 if (State.InstallVer != (Version *)P.OwnerVer())
157 continue;
158 }
159
160 if (Type == CandidateVersion)
161 {
162 StateCache &State = PkgState[P.OwnerPkg()->ID];
163 if (State.CandidateVer != (Version *)P.OwnerVer())
164 continue;
165 }
166
167 // Compare the versions.
168 if (VS().CheckDep(P.ProvideVersion(),Dep->CompareOp,Dep.TargetVer()) == true)
169 {
170 Res = P.OwnerPkg();
171 return true;
172 }
173 }
174
175 return false;
176 }
177 /*}}}*/
178 // DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
179 // ---------------------------------------------------------------------
180 /* Call with Mult = -1 to preform the inverse opration */
181 void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
182 {
183 StateCache &P = PkgState[Pkg->ID];
184
185 if (Pkg->VersionList == 0)
186 return;
187
188 if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
189 P.Keep() == true)
190 return;
191
192 // Compute the size data
193 if (P.NewInstall() == true)
194 {
195 iUsrSize += (signed)(Mult*P.InstVerIter(*this)->InstalledSize);
196 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
197 return;
198 }
199
200 // Upgrading
201 if (Pkg->CurrentVer != 0 &&
202 (P.InstallVer != (Version *)Pkg.CurrentVer() ||
203 (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
204 {
205 iUsrSize += (signed)(Mult*((signed)P.InstVerIter(*this)->InstalledSize -
206 (signed)Pkg.CurrentVer()->InstalledSize));
207 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
208 return;
209 }
210
211 // Reinstall
212 if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
213 P.Delete() == false)
214 {
215 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
216 return;
217 }
218
219 // Removing
220 if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
221 {
222 iUsrSize -= (signed)(Mult*Pkg.CurrentVer()->InstalledSize);
223 return;
224 }
225 }
226 /*}}}*/
227 // DepCache::AddStates - Add the package to the state counter /*{{{*/
228 // ---------------------------------------------------------------------
229 /* This routine is tricky to use, you must make sure that it is never
230 called twice for the same package. This means the Remove/Add section
231 should be as short as possible and not encompass any code that will
232 calld Remove/Add itself. Remember, dependencies can be circular so
233 while processing a dep for Pkg it is possible that Add/Remove
234 will be called on Pkg */
235 void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add)
236 {
237 StateCache &State = PkgState[Pkg->ID];
238
239 // The Package is broken
240 if ((State.DepState & DepInstMin) != DepInstMin)
241 iBrokenCount += Add;
242
243 // Bad state
244 if (Pkg.State() != PkgIterator::NeedsNothing)
245 iBadCount += Add;
246
247 // Not installed
248 if (Pkg->CurrentVer == 0)
249 {
250 if (State.Mode == ModeDelete &&
251 (State.iFlags | Purge) == Purge && Pkg.Purge() == false)
252 iDelCount += Add;
253
254 if (State.Mode == ModeInstall)
255 iInstCount += Add;
256 return;
257 }
258
259 // Installed, no upgrade
260 if (State.Status == 0)
261 {
262 if (State.Mode == ModeDelete)
263 iDelCount += Add;
264 else
265 if ((State.iFlags & ReInstall) == ReInstall)
266 iInstCount += Add;
267
268 return;
269 }
270
271 // Alll 3 are possible
272 if (State.Mode == ModeDelete)
273 iDelCount += Add;
274 if (State.Mode == ModeKeep)
275 iKeepCount += Add;
276 if (State.Mode == ModeInstall)
277 iInstCount += Add;
278 }
279 /*}}}*/
280 // DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
281 // ---------------------------------------------------------------------
282 /* The or group results are stored in the last item of the or group. This
283 allows easy detection of the state of a whole or'd group. */
284 void pkgDepCache::BuildGroupOrs(VerIterator const &V)
285 {
286 unsigned char Group = 0;
287
288 for (DepIterator D = V.DependsList(); D.end() != true; D++)
289 {
290 // Build the dependency state.
291 unsigned char &State = DepState[D->ID];
292
293 /* Invert for Conflicts. We have to do this twice to get the
294 right sense for a conflicts group */
295 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
296 State = ~State;
297
298 // Add to the group if we are within an or..
299 State &= 0x7;
300 Group |= State;
301 State |= Group << 3;
302 if ((D->CompareOp & Dep::Or) != Dep::Or)
303 Group = 0;
304
305 // Invert for Conflicts
306 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
307 State = ~State;
308 }
309 }
310 /*}}}*/
311 // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
312 // ---------------------------------------------------------------------
313 /* This is used to run over a dependency list and determine the dep
314 state of the list, filtering it through both a Min check and a Policy
315 check. The return result will have SetMin/SetPolicy low if a check
316 fails. It uses the DepState cache for it's computations. */
317 unsigned char pkgDepCache::VersionState(DepIterator D,unsigned char Check,
318 unsigned char SetMin,
319 unsigned char SetPolicy)
320 {
321 unsigned char Dep = 0xFF;
322
323 while (D.end() != true)
324 {
325 // Compute a single dependency element (glob or)
326 DepIterator Start = D;
327 unsigned char State = 0;
328 for (bool LastOR = true; D.end() == false && LastOR == true; D++)
329 {
330 State |= DepState[D->ID];
331 LastOR = (D->CompareOp & Dep::Or) == Dep::Or;
332 }
333
334 // Minimum deps that must be satisfied to have a working package
335 if (Start.IsCritical() == true)
336 if ((State & Check) != Check)
337 Dep &= ~SetMin;
338
339 // Policy deps that must be satisfied to install the package
340 if (IsImportantDep(Start) == true &&
341 (State & Check) != Check)
342 Dep &= ~SetPolicy;
343 }
344
345 return Dep;
346 }
347 /*}}}*/
348 // DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
349 // ---------------------------------------------------------------------
350 /* This is the main dependency computation bit. It computes the 3 main
351 results for a dependencys, Now, Install and Candidate. Callers must
352 invert the result if dealing with conflicts. */
353 unsigned char pkgDepCache::DependencyState(DepIterator &D)
354 {
355 unsigned char State = 0;
356
357 if (CheckDep(D,NowVersion) == true)
358 State |= DepNow;
359 if (CheckDep(D,InstallVersion) == true)
360 State |= DepInstall;
361 if (CheckDep(D,CandidateVersion) == true)
362 State |= DepCVer;
363
364 return State;
365 }
366 /*}}}*/
367 // DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
368 // ---------------------------------------------------------------------
369 /* This determines the combined dependency representation of a package
370 for its two states now and install. This is done by using the pre-generated
371 dependency information. */
372 void pkgDepCache::UpdateVerState(PkgIterator Pkg)
373 {
374 // Empty deps are always true
375 StateCache &State = PkgState[Pkg->ID];
376 State.DepState = 0xFF;
377
378 // Check the Current state
379 if (Pkg->CurrentVer != 0)
380 {
381 DepIterator D = Pkg.CurrentVer().DependsList();
382 State.DepState &= VersionState(D,DepNow,DepNowMin,DepNowPolicy);
383 }
384
385 /* Check the candidate state. We do not compare against the whole as
386 a candidate state but check the candidate version against the
387 install states */
388 if (State.CandidateVer != 0)
389 {
390 DepIterator D = State.CandidateVerIter(*this).DependsList();
391 State.DepState &= VersionState(D,DepInstall,DepCandMin,DepCandPolicy);
392 }
393
394 // Check target state which can only be current or installed
395 if (State.InstallVer != 0)
396 {
397 DepIterator D = State.InstVerIter(*this).DependsList();
398 State.DepState &= VersionState(D,DepInstall,DepInstMin,DepInstPolicy);
399 }
400 }
401 /*}}}*/
402 // DepCache::Update - Figure out all the state information /*{{{*/
403 // ---------------------------------------------------------------------
404 /* This will figure out the state of all the packages and all the
405 dependencies based on the current policy. */
406 void pkgDepCache::Update(OpProgress *Prog)
407 {
408 iUsrSize = 0;
409 iDownloadSize = 0;
410 iDelCount = 0;
411 iInstCount = 0;
412 iKeepCount = 0;
413 iBrokenCount = 0;
414 iBadCount = 0;
415
416 // Perform the depends pass
417 int Done = 0;
418 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
419 {
420 if (Prog != 0 && Done%20 == 0)
421 Prog->Progress(Done);
422 for (VerIterator V = I.VersionList(); V.end() != true; V++)
423 {
424 unsigned char Group = 0;
425
426 for (DepIterator D = V.DependsList(); D.end() != true; D++)
427 {
428 // Build the dependency state.
429 unsigned char &State = DepState[D->ID];
430 State = DependencyState(D);
431
432 // Add to the group if we are within an or..
433 Group |= State;
434 State |= Group << 3;
435 if ((D->CompareOp & Dep::Or) != Dep::Or)
436 Group = 0;
437
438 // Invert for Conflicts
439 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
440 State = ~State;
441 }
442 }
443
444 // Compute the pacakge dependency state and size additions
445 AddSizes(I);
446 UpdateVerState(I);
447 AddStates(I);
448 }
449
450 if (Prog != 0)
451 Prog->Progress(Done);
452 }
453 /*}}}*/
454 // DepCache::Update - Update the deps list of a package /*{{{*/
455 // ---------------------------------------------------------------------
456 /* This is a helper for update that only does the dep portion of the scan.
457 It is mainly ment to scan reverse dependencies. */
458 void pkgDepCache::Update(DepIterator D)
459 {
460 // Update the reverse deps
461 for (;D.end() != true; D++)
462 {
463 unsigned char &State = DepState[D->ID];
464 State = DependencyState(D);
465
466 // Invert for Conflicts
467 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
468 State = ~State;
469
470 RemoveStates(D.ParentPkg());
471 BuildGroupOrs(D.ParentVer());
472 UpdateVerState(D.ParentPkg());
473 AddStates(D.ParentPkg());
474 }
475 }
476 /*}}}*/
477 // DepCache::Update - Update the related deps of a package /*{{{*/
478 // ---------------------------------------------------------------------
479 /* This is called whenever the state of a package changes. It updates
480 all cached dependencies related to this package. */
481 void pkgDepCache::Update(PkgIterator const &Pkg)
482 {
483 // Recompute the dep of the package
484 RemoveStates(Pkg);
485 UpdateVerState(Pkg);
486 AddStates(Pkg);
487
488 // Update the reverse deps
489 Update(Pkg.RevDependsList());
490
491 // Update the provides map for the current ver
492 if (Pkg->CurrentVer != 0)
493 for (PrvIterator P = Pkg.CurrentVer().ProvidesList();
494 P.end() != true; P++)
495 Update(P.ParentPkg().RevDependsList());
496
497 // Update the provides map for the candidate ver
498 if (PkgState[Pkg->ID].CandidateVer != 0)
499 for (PrvIterator P = PkgState[Pkg->ID].CandidateVerIter(*this).ProvidesList();
500 P.end() != true; P++)
501 Update(P.ParentPkg().RevDependsList());
502 }
503
504 /*}}}*/
505
506 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
507 // ---------------------------------------------------------------------
508 /* */
509 void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
510 {
511 // Simplifies other routines.
512 if (Pkg.end() == true)
513 return;
514
515 /* Reject an attempt to keep a non-source broken installed package, those
516 must be upgraded */
517 if (Pkg.State() == PkgIterator::NeedsUnpack &&
518 Pkg.CurrentVer().Downloadable() == false)
519 return;
520
521 /* We changed the soft state all the time so the UI is a bit nicer
522 to use */
523 StateCache &P = PkgState[Pkg->ID];
524 if (Soft == true)
525 P.iFlags |= AutoKept;
526 else
527 P.iFlags &= ~AutoKept;
528
529 // Check that it is not already kept
530 if (P.Mode == ModeKeep)
531 return;
532
533 // We dont even try to keep virtual packages..
534 if (Pkg->VersionList == 0)
535 return;
536
537 P.Flags &= ~Flag::Auto;
538 RemoveSizes(Pkg);
539 RemoveStates(Pkg);
540
541 P.Mode = ModeKeep;
542 if (Pkg->CurrentVer == 0)
543 P.InstallVer = 0;
544 else
545 P.InstallVer = Pkg.CurrentVer();
546
547 AddStates(Pkg);
548
549 Update(Pkg);
550
551 AddSizes(Pkg);
552 }
553 /*}}}*/
554 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
555 // ---------------------------------------------------------------------
556 /* */
557 void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
558 {
559 // Simplifies other routines.
560 if (Pkg.end() == true)
561 return;
562
563 // Check that it is not already marked for delete
564 StateCache &P = PkgState[Pkg->ID];
565 P.iFlags &= ~(AutoKept | Purge);
566 if (rPurge == true)
567 P.iFlags |= Purge;
568
569 if ((P.Mode == ModeDelete || P.InstallVer == 0) &&
570 (Pkg.Purge() == true || rPurge == false))
571 return;
572
573 // We dont even try to delete virtual packages..
574 if (Pkg->VersionList == 0)
575 return;
576
577 RemoveSizes(Pkg);
578 RemoveStates(Pkg);
579
580 if (Pkg->CurrentVer == 0 && (Pkg.Purge() == true || rPurge == false))
581 P.Mode = ModeKeep;
582 else
583 P.Mode = ModeDelete;
584 P.InstallVer = 0;
585 P.Flags &= Flag::Auto;
586
587 AddStates(Pkg);
588 Update(Pkg);
589 AddSizes(Pkg);
590 }
591 /*}}}*/
592 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
593 // ---------------------------------------------------------------------
594 /* */
595 void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
596 unsigned long Depth)
597 {
598 if (Depth > 100)
599 return;
600
601 // Simplifies other routines.
602 if (Pkg.end() == true)
603 return;
604
605 /* Check that it is not already marked for install and that it can be
606 installed */
607 StateCache &P = PkgState[Pkg->ID];
608 P.iFlags &= ~AutoKept;
609 if (P.InstBroken() == false && (P.Mode == ModeInstall ||
610 P.CandidateVer == (Version *)Pkg.CurrentVer()))
611 {
612 if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
613 MarkKeep(Pkg);
614 return;
615 }
616
617 // See if there is even any possible instalation candidate
618 if (P.CandidateVer == 0)
619 return;
620
621 // We dont even try to install virtual packages..
622 if (Pkg->VersionList == 0)
623 return;
624
625 /* Target the candidate version and remove the autoflag. We reset the
626 autoflag below if this was called recursively. Otherwise the user
627 should have the ability to de-auto a package by changing its state */
628 RemoveSizes(Pkg);
629 RemoveStates(Pkg);
630
631 P.Mode = ModeInstall;
632 P.InstallVer = P.CandidateVer;
633 P.Flags &= ~Flag::Auto;
634 if (P.CandidateVer == (Version *)Pkg.CurrentVer())
635 P.Mode = ModeKeep;
636
637 AddStates(Pkg);
638 Update(Pkg);
639 AddSizes(Pkg);
640
641 if (AutoInst == false)
642 return;
643
644 DepIterator Dep = P.InstVerIter(*this).DependsList();
645 for (; Dep.end() != true;)
646 {
647 // Grok or groups
648 DepIterator Start = Dep;
649 bool Result = true;
650 unsigned Ors = 0;
651 for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++,Ors++)
652 {
653 LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or;
654
655 if ((DepState[Dep->ID] & DepInstall) == DepInstall)
656 Result = false;
657 }
658
659 // Dep is satisfied okay.
660 if (Result == false)
661 continue;
662
663 /* Check if this dep should be consider for install. If it is a user
664 defined important dep and we are installed a new package then
665 it will be installed. Otherwise we only worry about critical deps */
666 if (IsImportantDep(Start) == false)
667 continue;
668 if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
669 continue;
670
671 /* If we are in an or group locate the first or that can
672 succeed. We have already cached this.. */
673 for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; Ors--)
674 Start++;
675
676 /* This bit is for processing the possibilty of an install/upgrade
677 fixing the problem */
678 SPtrArray<Version *> List = Start.AllTargets();
679 if ((DepState[Start->ID] & DepCVer) == DepCVer)
680 {
681 // Right, find the best version to install..
682 Version **Cur = List;
683 PkgIterator P = Start.TargetPkg();
684 PkgIterator InstPkg(*Cache,0);
685
686 // See if there are direct matches (at the start of the list)
687 for (; *Cur != 0 && (*Cur)->ParentPkg == P.Index(); Cur++)
688 {
689 PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
690 if (PkgState[Pkg->ID].CandidateVer != *Cur)
691 continue;
692 InstPkg = Pkg;
693 break;
694 }
695
696 // Select the highest priority providing package
697 if (InstPkg.end() == true)
698 {
699 pkgPrioSortList(*Cache,Cur);
700 for (; *Cur != 0; Cur++)
701 {
702 PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
703 if (PkgState[Pkg->ID].CandidateVer != *Cur)
704 continue;
705 InstPkg = Pkg;
706 break;
707 }
708 }
709
710 if (InstPkg.end() == false)
711 {
712 MarkInstall(InstPkg,true,Depth + 1);
713
714 // Set the autoflag, after MarkInstall because MarkInstall unsets it
715 if (P->CurrentVer == 0)
716 PkgState[InstPkg->ID].Flags |= Flag::Auto;
717 }
718
719 continue;
720 }
721
722 /* For conflicts we just de-install the package and mark as auto,
723 Conflicts may not have or groups */
724 if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes)
725 {
726 for (Version **I = List; *I != 0; I++)
727 {
728 VerIterator Ver(*this,*I);
729 PkgIterator Pkg = Ver.ParentPkg();
730
731 MarkDelete(Pkg);
732 PkgState[Pkg->ID].Flags |= Flag::Auto;
733 }
734 continue;
735 }
736 }
737 }
738 /*}}}*/
739 // DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
740 // ---------------------------------------------------------------------
741 /* */
742 void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
743 {
744 RemoveSizes(Pkg);
745 RemoveStates(Pkg);
746
747 StateCache &P = PkgState[Pkg->ID];
748 if (To == true)
749 P.iFlags |= ReInstall;
750 else
751 P.iFlags &= ~ReInstall;
752
753 AddStates(Pkg);
754 AddSizes(Pkg);
755 }
756 /*}}}*/
757 // DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
758 // ---------------------------------------------------------------------
759 /* */
760 void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
761 {
762 pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
763 StateCache &P = PkgState[Pkg->ID];
764
765 RemoveSizes(Pkg);
766 RemoveStates(Pkg);
767
768 if (P.CandidateVer == P.InstallVer)
769 P.InstallVer = (Version *)TargetVer;
770 P.CandidateVer = (Version *)TargetVer;
771 P.Update(Pkg,*this);
772
773 AddStates(Pkg);
774 Update(Pkg);
775 AddSizes(Pkg);
776 }
777 /*}}}*/
778 // StateCache::Update - Compute the various static display things /*{{{*/
779 // ---------------------------------------------------------------------
780 /* This is called whenever the Candidate version changes. */
781 void pkgDepCache::StateCache::Update(PkgIterator Pkg,pkgCache &Cache)
782 {
783 // Some info
784 VerIterator Ver = CandidateVerIter(Cache);
785
786 // Use a null string or the version string
787 if (Ver.end() == true)
788 CandVersion = "";
789 else
790 CandVersion = Ver.VerStr();
791
792 // Find the current version
793 CurVersion = "";
794 if (Pkg->CurrentVer != 0)
795 CurVersion = Pkg.CurrentVer().VerStr();
796
797 // Strip off the epochs for display
798 CurVersion = StripEpoch(CurVersion);
799 CandVersion = StripEpoch(CandVersion);
800
801 // Figure out if its up or down or equal
802 Status = Ver.CompareVer(Pkg.CurrentVer());
803 if (Pkg->CurrentVer == 0 || Pkg->VersionList == 0 || CandidateVer == 0)
804 Status = 2;
805 }
806 /*}}}*/
807 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
808 // ---------------------------------------------------------------------
809 /* */
810 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
811 {
812 if (Ver == 0)
813 return 0;
814
815 // Strip any epoch
816 for (const char *I = Ver; *I != 0; I++)
817 if (*I == ':')
818 return I + 1;
819 return Ver;
820 }
821 /*}}}*/
822
823 // Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/
824 // ---------------------------------------------------------------------
825 /* The default just returns the highest available version that is not
826 a source and automatic. */
827 pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
828 {
829 /* Not source/not automatic versions cannot be a candidate version
830 unless they are already installed */
831 VerIterator Last(*(pkgCache *)this,0);
832
833 for (VerIterator I = Pkg.VersionList(); I.end() == false; I++)
834 {
835 if (Pkg.CurrentVer() == I)
836 return I;
837
838 for (VerFileIterator J = I.FileList(); J.end() == false; J++)
839 {
840 if ((J.File()->Flags & Flag::NotSource) != 0)
841 continue;
842
843 /* Stash the highest version of a not-automatic source, we use it
844 if there is nothing better */
845 if ((J.File()->Flags & Flag::NotAutomatic) != 0)
846 {
847 if (Last.end() == true)
848 Last = I;
849 continue;
850 }
851
852 return I;
853 }
854 }
855
856 return Last;
857 }
858 /*}}}*/
859 // Policy::IsImportantDep - True if the dependency is important /*{{{*/
860 // ---------------------------------------------------------------------
861 /* */
862 bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
863 {
864 return Dep.IsCritical();
865 }
866 /*}}}*/