Debug code
[ntk/apt.git] / apt-pkg / depcache.cc
CommitLineData
6c139d6e
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
d2685fd6 3// $Id: depcache.cc,v 1.8 1998/12/06 03:41:26 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
211 // Compute the size data
212 if (P.NewInstall() == true)
213 {
214 iUsrSize += Mult*P.InstVerIter(*this)->InstalledSize;
215 iDownloadSize += Mult*P.InstVerIter(*this)->Size;
d38b7b3d 216 return;
6c139d6e
AL
217 }
218
219 // Upgrading
220 if (Pkg->CurrentVer != 0 && P.InstallVer != (Version *)Pkg.CurrentVer() &&
221 P.InstallVer != 0)
222 {
7a658e66
AL
223 iUsrSize += Mult*((signed)P.InstVerIter(*this)->InstalledSize -
224 (signed)Pkg.CurrentVer()->InstalledSize);
6c139d6e 225 iDownloadSize += Mult*P.InstVerIter(*this)->Size;
d38b7b3d
AL
226 return;
227 }
228
229 // Reinstall
230 if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack)
231 {
232 iDownloadSize += Mult*P.InstVerIter(*this)->Size;
233 return;
6c139d6e
AL
234 }
235
236 // Removing
237 if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
d38b7b3d 238 {
6c139d6e 239 iUsrSize -= Mult*Pkg.CurrentVer()->InstalledSize;
d38b7b3d
AL
240 return;
241 }
6c139d6e
AL
242}
243 /*}}}*/
244// DepCache::AddStates - Add the package to the state counter /*{{{*/
245// ---------------------------------------------------------------------
246/* This routine is tricky to use, you must make sure that it is never
247 called twice for the same package. This means the Remove/Add section
248 should be as short as possible and not encompass any code that will
249 calld Remove/Add itself. Remember, dependencies can be circular so
250 while processing a dep for Pkg it is possible that Add/Remove
251 will be called on Pkg */
252void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add)
253{
254 StateCache &State = PkgState[Pkg->ID];
255
256 // The Package is broken
257 if ((State.DepState & DepInstMin) != DepInstMin)
258 iBrokenCount += Add;
259
260 // Bad state
261 if (Pkg.State() != PkgIterator::NeedsNothing)
262 iBadCount += Add;
263
264 // Not installed
265 if (Pkg->CurrentVer == 0)
266 {
267 if (State.Mode == ModeInstall)
268 iInstCount += Add;
269 return;
270 }
271
272 // Installed, no upgrade
273 if (State.Upgradable() == false)
274 {
275 if (State.Mode == ModeDelete)
276 iDelCount += Add;
277 return;
278 }
279
280 // Alll 3 are possible
281 if (State.Mode == ModeDelete)
282 iDelCount += Add;
283 if (State.Mode == ModeKeep)
284 iKeepCount += Add;
285 if (State.Mode == ModeInstall)
286 iInstCount += Add;
287}
288 /*}}}*/
289// DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
290// ---------------------------------------------------------------------
291/* The or group results are stored in the last item of the or group. This
292 allows easy detection of the state of a whole or'd group. */
293void pkgDepCache::BuildGroupOrs(VerIterator const &V)
294{
295 unsigned char Group = 0;
296
297 for (DepIterator D = V.DependsList(); D.end() != true; D++)
298 {
299 // Build the dependency state.
300 unsigned char &State = DepState[D->ID];
301
302 /* Invert for Conflicts. We have to do this twice to get the
303 right sense for a conflicts group */
304 if (D->Type == Dep::Conflicts)
305 State = ~State;
306
307 // Add to the group if we are within an or..
d2685fd6 308 State &= 0x7;
6c139d6e
AL
309 Group |= State;
310 State |= Group << 3;
311 if ((D->CompareOp & Dep::Or) != Dep::Or)
312 Group = 0;
313
314 // Invert for Conflicts
315 if (D->Type == Dep::Conflicts)
316 State = ~State;
317 }
318}
319 /*}}}*/
320// DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
321// ---------------------------------------------------------------------
322/* This is used to run over a dependency list and determine the dep
323 state of the list, filtering it through both a Min check and a Policy
324 check. The return result will have SetMin/SetPolicy low if a check
325 fails. It uses the DepState cache for it's computations. */
326unsigned char pkgDepCache::VersionState(DepIterator D,unsigned char Check,
327 unsigned char SetMin,
328 unsigned char SetPolicy)
329{
330 unsigned char Dep = 0xFF;
331
332 while (D.end() != true)
333 {
334 // Compute a single dependency element (glob or)
335 DepIterator Start = D;
336 unsigned char State = 0;
337 for (bool LastOR = true; D.end() == false && LastOR == true; D++)
338 {
339 State |= DepState[D->ID];
340 LastOR = (D->CompareOp & Dep::Or) == Dep::Or;
341 }
342
343 // Minimum deps that must be satisfied to have a working package
344 if (Start.IsCritical() == true)
345 if ((State & Check) != Check)
346 Dep &= ~SetMin;
347
348 // Policy deps that must be satisfied to install the package
349 if (IsImportantDep(Start) == true &&
350 (State & Check) != Check)
351 Dep &= ~SetPolicy;
352 }
353
354 return Dep;
355}
356 /*}}}*/
357// DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
358// ---------------------------------------------------------------------
359/* This is the main dependency computation bit. It computes the 3 main
360 results for a dependencys, Now, Install and Candidate. Callers must
361 invert the result if dealing with conflicts. */
362unsigned char pkgDepCache::DependencyState(DepIterator &D)
363{
364 unsigned char State = 0;
365
366 if (CheckDep(D,NowVersion) == true)
367 State |= DepNow;
368 if (CheckDep(D,InstallVersion) == true)
369 State |= DepInstall;
370 if (CheckDep(D,CandidateVersion) == true)
371 State |= DepCVer;
372
373 return State;
374}
375 /*}}}*/
376// DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
377// ---------------------------------------------------------------------
378/* This determines the combined dependency representation of a package
379 for its two states now and install. This is done by using the pre-generated
380 dependency information. */
381void pkgDepCache::UpdateVerState(PkgIterator Pkg)
382{
383 // Empty deps are always true
384 StateCache &State = PkgState[Pkg->ID];
385 State.DepState = 0xFF;
386
387 // Check the Current state
388 if (Pkg->CurrentVer != 0)
389 {
390 DepIterator D = Pkg.CurrentVer().DependsList();
391 State.DepState &= VersionState(D,DepNow,DepNowMin,DepNowPolicy);
392 }
393
394 /* Check the candidate state. We do not compare against the whole as
395 a candidate state but check the candidate version against the
396 install states */
397 if (State.CandidateVer != 0)
398 {
399 DepIterator D = State.CandidateVerIter(*this).DependsList();
400 State.DepState &= VersionState(D,DepInstall,DepCandMin,DepCandPolicy);
401 }
402
403 // Check target state which can only be current or installed
404 if (State.InstallVer != 0)
405 {
406 DepIterator D = State.InstVerIter(*this).DependsList();
407 State.DepState &= VersionState(D,DepInstall,DepInstMin,DepInstPolicy);
408 }
409}
410 /*}}}*/
411// DepCache::Update - Figure out all the state information /*{{{*/
412// ---------------------------------------------------------------------
413/* This will figure out the state of all the packages and all the
414 dependencies based on the current policy. */
a246f2dc 415void pkgDepCache::Update(OpProgress *Prog)
6c139d6e
AL
416{
417 iUsrSize = 0;
418 iDownloadSize = 0;
419 iDelCount = 0;
420 iInstCount = 0;
421 iKeepCount = 0;
422 iBrokenCount = 0;
423 iBadCount = 0;
424
425 // Perform the depends pass
a246f2dc
AL
426 int Done = 0;
427 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
6c139d6e 428 {
a246f2dc
AL
429 if (Prog != 0 && Done%20 == 0)
430 Prog->Progress(Done);
6c139d6e
AL
431 for (VerIterator V = I.VersionList(); V.end() != true; V++)
432 {
433 unsigned char Group = 0;
434
435 for (DepIterator D = V.DependsList(); D.end() != true; D++)
436 {
437 // Build the dependency state.
438 unsigned char &State = DepState[D->ID];
439 State = DependencyState(D);;
440
441 // Add to the group if we are within an or..
442 Group |= State;
443 State |= Group << 3;
444 if ((D->CompareOp & Dep::Or) != Dep::Or)
445 Group = 0;
446
447 // Invert for Conflicts
448 if (D->Type == Dep::Conflicts)
449 State = ~State;
450 }
451 }
452
453 // Compute the pacakge dependency state and size additions
454 AddSizes(I);
455 UpdateVerState(I);
456 AddStates(I);
457 }
a246f2dc
AL
458
459 if (Prog != 0)
460 Prog->Progress(Done);
6c139d6e
AL
461}
462 /*}}}*/
463// DepCache::Update - Update the deps list of a package /*{{{*/
464// ---------------------------------------------------------------------
465/* This is a helper for update that only does the dep portion of the scan.
466 It is mainly ment to scan reverse dependencies. */
467void pkgDepCache::Update(DepIterator D)
468{
469 // Update the reverse deps
470 for (;D.end() != true; D++)
471 {
472 unsigned char &State = DepState[D->ID];
473 State = DependencyState(D);
474
475 // Invert for Conflicts
476 if (D->Type == Dep::Conflicts)
477 State = ~State;
478
479 RemoveStates(D.ParentPkg());
480 BuildGroupOrs(D.ParentVer());
481 UpdateVerState(D.ParentPkg());
482 AddStates(D.ParentPkg());
483 }
484}
485 /*}}}*/
486// DepCache::Update - Update the related deps of a package /*{{{*/
487// ---------------------------------------------------------------------
488/* This is called whenever the state of a package changes. It updates
489 all cached dependencies related to this package. */
490void pkgDepCache::Update(PkgIterator const &Pkg)
491{
492 // Recompute the dep of the package
493 RemoveStates(Pkg);
494 UpdateVerState(Pkg);
495 AddStates(Pkg);
496
497 // Update the reverse deps
498 Update(Pkg.RevDependsList());
499
500 // Update the provides map for the current ver
501 if (Pkg->CurrentVer != 0)
502 for (PrvIterator P = Pkg.CurrentVer().ProvidesList();
503 P.end() != true; P++)
504 Update(P.ParentPkg().RevDependsList());
505
506 // Update the provides map for the candidate ver
507 for (PrvIterator P = PkgState[Pkg->ID].CandidateVerIter(*this).ProvidesList();
508 P.end() != true; P++)
509 Update(P.ParentPkg().RevDependsList());
510}
511
512 /*}}}*/
513
514// DepCache::MarkKeep - Put the package in the keep state /*{{{*/
515// ---------------------------------------------------------------------
516/* */
517void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
518{
519 // Simplifies other routines.
520 if (Pkg.end() == true)
521 return;
522
523 /* We changed the soft state all the time so the UI is a bit nicer
524 to use */
525 StateCache &P = PkgState[Pkg->ID];
526 if (Soft == true)
527 P.iFlags |= AutoKept;
528 else
529 P.iFlags &= ~AutoKept;
530
531 // Check that it is not already kept
532 if (P.Mode == ModeKeep)
533 return;
534
535 // We dont even try to keep virtual packages..
536 if (Pkg->VersionList == 0)
537 return;
538
539 P.Flags &= ~Flag::Auto;
540 RemoveSizes(Pkg);
541 RemoveStates(Pkg);
542
543 P.Mode = ModeKeep;
544 if (Pkg->CurrentVer == 0)
545 P.InstallVer = 0;
546 else
547 P.InstallVer = Pkg.CurrentVer();
548
549 AddStates(Pkg);
550
551 Update(Pkg);
552
553 AddSizes(Pkg);
554}
555 /*}}}*/
556// DepCache::MarkDelete - Put the package in the delete state /*{{{*/
557// ---------------------------------------------------------------------
558/* */
559void pkgDepCache::MarkDelete(PkgIterator const &Pkg)
560{
561 // Simplifies other routines.
562 if (Pkg.end() == true)
563 return;
564
565 // Check that it is not already marked for delete
566 StateCache &P = PkgState[Pkg->ID];
567 P.iFlags &= ~AutoKept;
568 if (P.Mode == ModeDelete || P.InstallVer == 0)
569 return;
570
571 // We dont even try to delete virtual packages..
572 if (Pkg->VersionList == 0)
573 return;
574
575 RemoveSizes(Pkg);
576 RemoveStates(Pkg);
577
578 P.Mode = ModeDelete;
579 P.InstallVer = 0;
580 P.Flags &= Flag::Auto;
581
582 AddStates(Pkg);
583 Update(Pkg);
584 AddSizes(Pkg);
585}
586 /*}}}*/
587// DepCache::MarkInstall - Put the package in the install state /*{{{*/
588// ---------------------------------------------------------------------
589/* */
590void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst)
591{
592 // Simplifies other routines.
593 if (Pkg.end() == true)
594 return;
595
596 /* Check that it is not already marked for install and that it can be
597 installed */
598 StateCache &P = PkgState[Pkg->ID];
599 P.iFlags &= ~AutoKept;
600 if (P.InstBroken() == false && (P.Mode == ModeInstall ||
601 P.CandidateVer == (Version *)Pkg.CurrentVer()))
602 {
603 if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
604 MarkKeep(Pkg);
605 return;
606 }
607
608 // We dont even try to install virtual packages..
609 if (Pkg->VersionList == 0)
610 return;
611
612 /* Target the candidate version and remove the autoflag. We reset the
613 autoflag below if this was called recursively. Otherwise the user
614 should have the ability to de-auto a package by changing its state */
615 RemoveSizes(Pkg);
616 RemoveStates(Pkg);
617
618 P.Mode = ModeInstall;
619 P.InstallVer = P.CandidateVer;
620 P.Flags &= ~Flag::Auto;
621 if (P.CandidateVer == (Version *)Pkg.CurrentVer())
622 P.Mode = ModeKeep;
623
624 AddStates(Pkg);
625 Update(Pkg);
626 AddSizes(Pkg);
627
628 if (AutoInst == false)
629 return;
630
631 DepIterator Dep = P.InstVerIter(*this).DependsList();
632 for (; Dep.end() != true;)
633 {
634 // Grok or groups
635 DepIterator Start = Dep;
636 bool Result = true;
637 for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++)
638 {
639 LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or;
640
641 if ((DepState[Dep->ID] & DepInstall) == DepInstall)
642 Result = false;
643 }
644
645 // Dep is satisfied okay.
646 if (Result == false)
647 continue;
648
649 /* Check if this dep should be consider for install. If it is a user
650 defined important dep and we are installed a new package then
651 it will be installed. Otherwise we only worry about critical deps */
652 if (IsImportantDep(Start) == false)
653 continue;
654 if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
655 continue;
656
657 // Now we have to take action...
658 PkgIterator P = Start.SmartTargetPkg();
659 if ((DepState[Start->ID] & DepCVer) == DepCVer)
660 {
661 MarkInstall(P,true);
662
663 // Set the autoflag, after MarkInstall because MarkInstall unsets it
664 if (P->CurrentVer == 0)
665 PkgState[P->ID].Flags |= Flag::Auto;
666
667 continue;
668 }
669
670 // For conflicts we just de-install the package and mark as auto
671 if (Start->Type == Dep::Conflicts)
672 {
673 Version **List = Start.AllTargets();
674 for (Version **I = List; *I != 0; I++)
675 {
676 VerIterator Ver(*this,*I);
677 PkgIterator Pkg = Ver.ParentPkg();
678
679 MarkDelete(Pkg);
680 PkgState[Pkg->ID].Flags |= Flag::Auto;
681 }
682 delete [] List;
683 continue;
684 }
685 }
686}
687 /*}}}*/
688
6c139d6e
AL
689// StateCache::Update - Compute the various static display things /*{{{*/
690// ---------------------------------------------------------------------
691/* This is called whenever the Candidate version changes. */
692void pkgDepCache::StateCache::Update(PkgIterator Pkg,pkgCache &Cache)
693{
694 // Some info
695 VerIterator Ver = CandidateVerIter(Cache);
696
697 // Use a null string or the version string
698 if (Ver.end() == true)
699 CandVersion = "";
700 else
701 CandVersion = Ver.VerStr();
702
703 // Find the current version
704 CurVersion = "";
705 if (Pkg->CurrentVer != 0)
706 CurVersion = Pkg.CurrentVer().VerStr();
707
708 // Strip off the epochs for display
709 CurVersion = StripEpoch(CurVersion);
710 CandVersion = StripEpoch(CandVersion);
711
712 // Figure out if its up or down or equal
713 Status = Ver.CompareVer(Pkg.CurrentVer());
714 if (Pkg->CurrentVer == 0 || Pkg->VersionList == 0 || CandidateVer == 0)
715 Status = 2;
716}
717 /*}}}*/
718// StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
719// ---------------------------------------------------------------------
720/* */
721const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
722{
723 if (Ver == 0)
724 return 0;
725
726 // Strip any epoch
727 for (const char *I = Ver; *I != 0; I++)
728 if (*I == ':')
729 return I + 1;
730 return Ver;
731}
732 /*}}}*/