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