]> git.saurik.com Git - apt.git/blob - apt-pkg/depcache.cc
g++- works
[apt.git] / apt-pkg / depcache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: depcache.cc,v 1.18 1999/04/28 22:48:45 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
16 #include <apt-pkg/version.h>
17 #include <apt-pkg/error.h>
18 /*}}}*/
19
20 // DepCache::pkgDepCache - Constructors /*{{{*/
21 // ---------------------------------------------------------------------
22 /* */
23 pkgDepCache::pkgDepCache(MMap &Map,OpProgress &Prog) :
24 pkgCache(Map), PkgState(0), DepState(0)
25 {
26 if (_error->PendingError() == false)
27 Init(&Prog);
28 }
29 pkgDepCache::pkgDepCache(MMap &Map) :
30 pkgCache(Map), PkgState(0), DepState(0)
31 {
32 if (_error->PendingError() == false)
33 Init(0);
34 }
35 /*}}}*/
36 // DepCache::~pkgDepCache - Destructor /*{{{*/
37 // ---------------------------------------------------------------------
38 /* */
39 pkgDepCache::~pkgDepCache()
40 {
41 delete [] PkgState;
42 delete [] DepState;
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 // DepCache::GetCandidateVer - Returns the Candidate install version /*{{{*/
99 // ---------------------------------------------------------------------
100 /* The default just returns the target version if it exists or the
101 highest version. */
102 pkgDepCache::VerIterator pkgDepCache::GetCandidateVer(PkgIterator Pkg,
103 bool AllowCurrent)
104 {
105 // Try to use an explicit target
106 if (Pkg->TargetVer == 0 ||
107 (AllowCurrent == false && Pkg.TargetVer() == Pkg.CurrentVer()))
108 return pkgCache::GetCandidateVer(Pkg,AllowCurrent);
109 else
110 return Pkg.TargetVer();
111 }
112 /*}}}*/
113 // DepCache::IsImportantDep - True if the dependency is important /*{{{*/
114 // ---------------------------------------------------------------------
115 /* */
116 bool pkgDepCache::IsImportantDep(DepIterator Dep)
117 {
118 return Dep.IsCritical();
119 }
120 /*}}}*/
121
122 // DepCache::CheckDep - Checks a single dependency /*{{{*/
123 // ---------------------------------------------------------------------
124 /* This first checks the dependency against the main target package and
125 then walks along the package provides list and checks if each provides
126 will be installed then checks the provides against the dep. Res will be
127 set to the package which was used to satisfy the dep. */
128 bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
129 {
130 Res = Dep.TargetPkg();
131
132 /* Check simple depends. A depends -should- never self match but
133 we allow it anyhow because dpkg does. Technically it is a packaging
134 bug. Conflicts may never self match */
135 if (Dep.TargetPkg() != Dep.ParentPkg() || Dep->Type != Dep::Conflicts)
136 {
137 PkgIterator Pkg = Dep.TargetPkg();
138 // Check the base package
139 if (Type == NowVersion && Pkg->CurrentVer != 0)
140 if (pkgCheckDep(Dep.TargetVer(),
141 Pkg.CurrentVer().VerStr(),Dep->CompareOp) == true)
142 return true;
143
144 if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
145 if (pkgCheckDep(Dep.TargetVer(),
146 PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
147 Dep->CompareOp) == true)
148 return true;
149
150 if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
151 if (pkgCheckDep(Dep.TargetVer(),
152 PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
153 Dep->CompareOp) == true)
154 return true;
155 }
156
157 // Check the providing packages
158 PrvIterator P = Dep.TargetPkg().ProvidesList();
159 PkgIterator Pkg = Dep.ParentPkg();
160 for (; P.end() != true; P++)
161 {
162 /* Provides may never be applied against the same package if it is
163 a conflicts. See the comment above. */
164 if (P.OwnerPkg() == Pkg && Dep->Type == Dep::Conflicts)
165 continue;
166
167 // Check if the provides is a hit
168 if (Type == NowVersion)
169 {
170 if (P.OwnerPkg().CurrentVer() != P.OwnerVer())
171 continue;
172 }
173
174 if (Type == InstallVersion)
175 {
176 StateCache &State = PkgState[P.OwnerPkg()->ID];
177 if (State.InstallVer != (Version *)P.OwnerVer())
178 continue;
179 }
180
181 if (Type == CandidateVersion)
182 {
183 StateCache &State = PkgState[P.OwnerPkg()->ID];
184 if (State.CandidateVer != (Version *)P.OwnerVer())
185 continue;
186 }
187
188 // Compare the versions.
189 if (pkgCheckDep(Dep.TargetVer(),P.ProvideVersion(),Dep->CompareOp) == true)
190 {
191 Res = P.OwnerPkg();
192 return true;
193 }
194 }
195
196 return false;
197 }
198 /*}}}*/
199 // DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
200 // ---------------------------------------------------------------------
201 /* Call with Mult = -1 to preform the inverse opration */
202 void pkgDepCache::AddSizes(const PkgIterator &Pkg,long Mult)
203 {
204 StateCache &P = PkgState[Pkg->ID];
205
206 if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
207 P.Keep() == true)
208 return;
209
210 // Compute the size data
211 if (P.NewInstall() == true)
212 {
213 iUsrSize += Mult*P.InstVerIter(*this)->InstalledSize;
214 iDownloadSize += Mult*P.InstVerIter(*this)->Size;
215 return;
216 }
217
218 // Upgrading
219 if (Pkg->CurrentVer != 0 && P.InstallVer != (Version *)Pkg.CurrentVer() &&
220 P.InstallVer != 0)
221 {
222 iUsrSize += Mult*((signed)P.InstVerIter(*this)->InstalledSize -
223 (signed)Pkg.CurrentVer()->InstalledSize);
224 iDownloadSize += Mult*P.InstVerIter(*this)->Size;
225 return;
226 }
227
228 // Reinstall
229 if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
230 P.Delete() == false)
231 {
232 iDownloadSize += Mult*P.InstVerIter(*this)->Size;
233 return;
234 }
235
236 // Removing
237 if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
238 {
239 iUsrSize -= Mult*Pkg.CurrentVer()->InstalledSize;
240 return;
241 }
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 */
252 void 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. */
293 void 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..
308 State &= 0x7;
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. */
326 unsigned 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. */
362 unsigned 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. */
381 void 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. */
415 void pkgDepCache::Update(OpProgress *Prog)
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
426 int Done = 0;
427 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
428 {
429 if (Prog != 0 && Done%20 == 0)
430 Prog->Progress(Done);
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 }
458
459 if (Prog != 0)
460 Prog->Progress(Done);
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. */
467 void 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. */
490 void 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 /* */
517 void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
518 {
519 // Simplifies other routines.
520 if (Pkg.end() == true)
521 return;
522
523 /* Reject an attempt to keep a non-source broken installed package, those
524 must be upgraded */
525 if (Pkg.State() == PkgIterator::NeedsUnpack &&
526 Pkg.CurrentVer().Downloadable() == false)
527 return;
528
529 /* We changed the soft state all the time so the UI is a bit nicer
530 to use */
531 StateCache &P = PkgState[Pkg->ID];
532 if (Soft == true)
533 P.iFlags |= AutoKept;
534 else
535 P.iFlags &= ~AutoKept;
536
537 // Check that it is not already kept
538 if (P.Mode == ModeKeep)
539 return;
540
541 // We dont even try to keep virtual packages..
542 if (Pkg->VersionList == 0)
543 return;
544
545 P.Flags &= ~Flag::Auto;
546 RemoveSizes(Pkg);
547 RemoveStates(Pkg);
548
549 P.Mode = ModeKeep;
550 if (Pkg->CurrentVer == 0)
551 P.InstallVer = 0;
552 else
553 P.InstallVer = Pkg.CurrentVer();
554
555 AddStates(Pkg);
556
557 Update(Pkg);
558
559 AddSizes(Pkg);
560 }
561 /*}}}*/
562 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
563 // ---------------------------------------------------------------------
564 /* */
565 void pkgDepCache::MarkDelete(PkgIterator const &Pkg)
566 {
567 // Simplifies other routines.
568 if (Pkg.end() == true)
569 return;
570
571 // Check that it is not already marked for delete
572 StateCache &P = PkgState[Pkg->ID];
573 P.iFlags &= ~AutoKept;
574 if (P.Mode == ModeDelete || P.InstallVer == 0)
575 return;
576
577 // We dont even try to delete virtual packages..
578 if (Pkg->VersionList == 0)
579 return;
580
581 RemoveSizes(Pkg);
582 RemoveStates(Pkg);
583
584 if (Pkg->CurrentVer == 0)
585 P.Mode = ModeKeep;
586 else
587 P.Mode = ModeDelete;
588 P.InstallVer = 0;
589 P.Flags &= Flag::Auto;
590
591 AddStates(Pkg);
592 Update(Pkg);
593 AddSizes(Pkg);
594 }
595 /*}}}*/
596 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
597 // ---------------------------------------------------------------------
598 /* */
599 void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst)
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 // We dont even try to install virtual packages..
618 if (Pkg->VersionList == 0)
619 return;
620
621 /* Target the candidate version and remove the autoflag. We reset the
622 autoflag below if this was called recursively. Otherwise the user
623 should have the ability to de-auto a package by changing its state */
624 RemoveSizes(Pkg);
625 RemoveStates(Pkg);
626
627 P.Mode = ModeInstall;
628 P.InstallVer = P.CandidateVer;
629 P.Flags &= ~Flag::Auto;
630 if (P.CandidateVer == (Version *)Pkg.CurrentVer())
631 P.Mode = ModeKeep;
632
633 AddStates(Pkg);
634 Update(Pkg);
635 AddSizes(Pkg);
636
637 if (AutoInst == false)
638 return;
639
640 DepIterator Dep = P.InstVerIter(*this).DependsList();
641 for (; Dep.end() != true;)
642 {
643 // Grok or groups
644 DepIterator Start = Dep;
645 bool Result = true;
646 for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++)
647 {
648 LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or;
649
650 if ((DepState[Dep->ID] & DepInstall) == DepInstall)
651 Result = false;
652 }
653
654 // Dep is satisfied okay.
655 if (Result == false)
656 continue;
657
658 /* Check if this dep should be consider for install. If it is a user
659 defined important dep and we are installed a new package then
660 it will be installed. Otherwise we only worry about critical deps */
661 if (IsImportantDep(Start) == false)
662 continue;
663 if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
664 continue;
665
666 // Now we have to take action...
667 PkgIterator P = Start.SmartTargetPkg();
668 if ((DepState[Start->ID] & DepCVer) == DepCVer)
669 {
670 MarkInstall(P,true);
671
672 // Set the autoflag, after MarkInstall because MarkInstall unsets it
673 if (P->CurrentVer == 0)
674 PkgState[P->ID].Flags |= Flag::Auto;
675
676 continue;
677 }
678
679 // For conflicts we just de-install the package and mark as auto
680 if (Start->Type == Dep::Conflicts)
681 {
682 Version **List = Start.AllTargets();
683 for (Version **I = List; *I != 0; I++)
684 {
685 VerIterator Ver(*this,*I);
686 PkgIterator Pkg = Ver.ParentPkg();
687
688 MarkDelete(Pkg);
689 PkgState[Pkg->ID].Flags |= Flag::Auto;
690 }
691 delete [] List;
692 continue;
693 }
694 }
695 }
696 /*}}}*/
697
698 // StateCache::Update - Compute the various static display things /*{{{*/
699 // ---------------------------------------------------------------------
700 /* This is called whenever the Candidate version changes. */
701 void pkgDepCache::StateCache::Update(PkgIterator Pkg,pkgCache &Cache)
702 {
703 // Some info
704 VerIterator Ver = CandidateVerIter(Cache);
705
706 // Use a null string or the version string
707 if (Ver.end() == true)
708 CandVersion = "";
709 else
710 CandVersion = Ver.VerStr();
711
712 // Find the current version
713 CurVersion = "";
714 if (Pkg->CurrentVer != 0)
715 CurVersion = Pkg.CurrentVer().VerStr();
716
717 // Strip off the epochs for display
718 CurVersion = StripEpoch(CurVersion);
719 CandVersion = StripEpoch(CandVersion);
720
721 // Figure out if its up or down or equal
722 Status = Ver.CompareVer(Pkg.CurrentVer());
723 if (Pkg->CurrentVer == 0 || Pkg->VersionList == 0 || CandidateVer == 0)
724 Status = 2;
725 }
726 /*}}}*/
727 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
728 // ---------------------------------------------------------------------
729 /* */
730 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
731 {
732 if (Ver == 0)
733 return 0;
734
735 // Strip any epoch
736 for (const char *I = Ver; *I != 0; I++)
737 if (*I == ':')
738 return I + 1;
739 return Ver;
740 }
741 /*}}}*/