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