]> git.saurik.com Git - apt.git/blame - apt-pkg/depcache.cc
Sync with apt@packages.debian.org/apt--main--0--patch-75
[apt.git] / apt-pkg / depcache.cc
CommitLineData
6c139d6e
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
e7b470ee 3// $Id: depcache.cc,v 1.25 2001/05/27 05:36:04 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>
094a497d
AL
15#include <apt-pkg/version.h>
16#include <apt-pkg/error.h>
b2e465d6
AL
17#include <apt-pkg/sptr.h>
18#include <apt-pkg/algorithms.h>
19
20#include <apti18n.h>
6c139d6e
AL
21 /*}}}*/
22
23// DepCache::pkgDepCache - Constructors /*{{{*/
24// ---------------------------------------------------------------------
25/* */
b2e465d6
AL
26pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
27 Cache(pCache), PkgState(0), DepState(0)
6c139d6e 28{
b2e465d6
AL
29 delLocalPolicy = 0;
30 LocalPolicy = Plcy;
31 if (LocalPolicy == 0)
32 delLocalPolicy = LocalPolicy = new Policy;
6c139d6e
AL
33}
34 /*}}}*/
35// DepCache::~pkgDepCache - Destructor /*{{{*/
36// ---------------------------------------------------------------------
37/* */
38pkgDepCache::~pkgDepCache()
39{
40 delete [] PkgState;
41 delete [] DepState;
b2e465d6 42 delete delLocalPolicy;
6c139d6e
AL
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);
b2e465d6 56
a246f2dc
AL
57 if (Prog != 0)
58 {
59 Prog->OverallProgress(0,2*Head().PackageCount,Head().PackageCount,
db0db9fe
CP
60 _("Building dependency tree"));
61 Prog->SubProgress(Head().PackageCount,_("Candidate versions"));
a246f2dc
AL
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,
db0db9fe
CP
89 _("Building dependency tree"));
90 Prog->SubProgress(Head().PackageCount,_("Dependency generation"));
a246f2dc
AL
91 }
92
93 Update(Prog);
6c139d6e
AL
94
95 return true;
96}
97 /*}}}*/
6c139d6e
AL
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. */
105bool 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 */
b2e465d6
AL
112 if (Dep.TargetPkg() != Dep.ParentPkg() ||
113 (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes))
6c139d6e
AL
114 {
115 PkgIterator Pkg = Dep.TargetPkg();
116 // Check the base package
117 if (Type == NowVersion && Pkg->CurrentVer != 0)
b2e465d6
AL
118 if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep->CompareOp,
119 Dep.TargetVer()) == true)
6c139d6e
AL
120 return true;
121
122 if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
b2e465d6
AL
123 if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
124 Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
125 return true;
126
127 if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
b2e465d6
AL
128 if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
129 Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
130 return true;
131 }
132
b2e465d6
AL
133 if (Dep->Type == Dep::Obsoletes)
134 return false;
135
6c139d6e
AL
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.
b2e465d6 168 if (VS().CheckDep(P.ProvideVersion(),Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
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 */
b2e465d6 181void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
6c139d6e
AL
182{
183 StateCache &P = PkgState[Pkg->ID];
184
e7b470ee
AL
185 if (Pkg->VersionList == 0)
186 return;
187
e5a1f2ff
AL
188 if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
189 P.Keep() == true)
2cca3bd9 190 return;
2cca3bd9 191
6c139d6e
AL
192 // Compute the size data
193 if (P.NewInstall() == true)
194 {
b2e465d6
AL
195 iUsrSize += (signed)(Mult*P.InstVerIter(*this)->InstalledSize);
196 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d 197 return;
6c139d6e
AL
198 }
199
200 // Upgrading
d0c59649
AL
201 if (Pkg->CurrentVer != 0 &&
202 (P.InstallVer != (Version *)Pkg.CurrentVer() ||
203 (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
6c139d6e 204 {
b2e465d6
AL
205 iUsrSize += (signed)(Mult*((signed)P.InstVerIter(*this)->InstalledSize -
206 (signed)Pkg.CurrentVer()->InstalledSize));
207 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d
AL
208 return;
209 }
210
211 // Reinstall
2cca3bd9
AL
212 if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
213 P.Delete() == false)
d38b7b3d 214 {
b2e465d6 215 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d 216 return;
6c139d6e
AL
217 }
218
219 // Removing
220 if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
d38b7b3d 221 {
b2e465d6 222 iUsrSize -= (signed)(Mult*Pkg.CurrentVer()->InstalledSize);
d38b7b3d
AL
223 return;
224 }
6c139d6e
AL
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 */
235void 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 {
d556d1a1
AL
250 if (State.Mode == ModeDelete &&
251 (State.iFlags | Purge) == Purge && Pkg.Purge() == false)
252 iDelCount += Add;
253
6c139d6e
AL
254 if (State.Mode == ModeInstall)
255 iInstCount += Add;
256 return;
257 }
258
259 // Installed, no upgrade
6321777b 260 if (State.Status == 0)
d0c59649 261 {
6c139d6e
AL
262 if (State.Mode == ModeDelete)
263 iDelCount += Add;
d0c59649
AL
264 else
265 if ((State.iFlags & ReInstall) == ReInstall)
266 iInstCount += Add;
267
6c139d6e
AL
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. */
284void 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 */
b2e465d6 295 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e
AL
296 State = ~State;
297
298 // Add to the group if we are within an or..
d2685fd6 299 State &= 0x7;
6c139d6e
AL
300 Group |= State;
301 State |= Group << 3;
302 if ((D->CompareOp & Dep::Or) != Dep::Or)
303 Group = 0;
304
305 // Invert for Conflicts
b2e465d6 306 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e
AL
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. */
317unsigned 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. */
353unsigned 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. */
372void 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. */
a246f2dc 406void pkgDepCache::Update(OpProgress *Prog)
6c139d6e
AL
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
a246f2dc
AL
417 int Done = 0;
418 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
6c139d6e 419 {
a246f2dc
AL
420 if (Prog != 0 && Done%20 == 0)
421 Prog->Progress(Done);
6c139d6e
AL
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];
b2e465d6 430 State = DependencyState(D);
6c139d6e
AL
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
b2e465d6 439 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e
AL
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 }
a246f2dc
AL
449
450 if (Prog != 0)
451 Prog->Progress(Done);
6c139d6e
AL
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. */
458void 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
b2e465d6 467 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e 468 State = ~State;
b2e465d6 469
6c139d6e
AL
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. */
481void pkgDepCache::Update(PkgIterator const &Pkg)
b2e465d6 482{
6c139d6e
AL
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
9972233d
AL
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());
6c139d6e
AL
502}
503
504 /*}}}*/
505
506// DepCache::MarkKeep - Put the package in the keep state /*{{{*/
507// ---------------------------------------------------------------------
508/* */
509void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
510{
511 // Simplifies other routines.
512 if (Pkg.end() == true)
513 return;
813c8eea
AL
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;
6c139d6e
AL
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/* */
d556d1a1 557void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
6c139d6e
AL
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];
d556d1a1
AL
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))
6c139d6e 571 return;
d556d1a1 572
6c139d6e
AL
573 // We dont even try to delete virtual packages..
574 if (Pkg->VersionList == 0)
575 return;
576
577 RemoveSizes(Pkg);
578 RemoveStates(Pkg);
579
d556d1a1 580 if (Pkg->CurrentVer == 0 && (Pkg.Purge() == true || rPurge == false))
3d615484
AL
581 P.Mode = ModeKeep;
582 else
583 P.Mode = ModeDelete;
6c139d6e
AL
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/* */
b2e465d6
AL
595void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
596 unsigned long Depth)
597{
598 if (Depth > 100)
599 return;
600
6c139d6e
AL
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 }
b2e465d6
AL
616
617 // See if there is even any possible instalation candidate
618 if (P.CandidateVer == 0)
619 return;
6c139d6e
AL
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;
b2e465d6
AL
650 unsigned Ors = 0;
651 for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++,Ors++)
6c139d6e
AL
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;
b2e465d6
AL
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++;
2ed9b455 675
b2e465d6
AL
676 /* This bit is for processing the possibilty of an install/upgrade
677 fixing the problem */
678 SPtrArray<Version *> List = Start.AllTargets();
6c139d6e
AL
679 if ((DepState[Start->ID] & DepCVer) == DepCVer)
680 {
b2e465d6
AL
681 // Right, find the best version to install..
682 Version **Cur = List;
683 PkgIterator P = Start.TargetPkg();
684 PkgIterator InstPkg(*Cache,0);
6c139d6e 685
b2e465d6
AL
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
2ed9b455 697 if (InstPkg.end() == true)
b2e465d6
AL
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);
6c139d6e 713
b2e465d6
AL
714 // Set the autoflag, after MarkInstall because MarkInstall unsets it
715 if (P->CurrentVer == 0)
716 PkgState[InstPkg->ID].Flags |= Flag::Auto;
717 }
718
6c139d6e
AL
719 continue;
720 }
721
b2e465d6
AL
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)
6c139d6e 725 {
6c139d6e
AL
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 }
6c139d6e
AL
734 continue;
735 }
736 }
737}
738 /*}}}*/
d0c59649
AL
739// DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
740// ---------------------------------------------------------------------
741/* */
742void 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 /*}}}*/
b2e465d6
AL
757// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
758// ---------------------------------------------------------------------
759/* */
760void 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 /*}}}*/
6c139d6e
AL
778// StateCache::Update - Compute the various static display things /*{{{*/
779// ---------------------------------------------------------------------
780/* This is called whenever the Candidate version changes. */
781void 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/* */
810const 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 /*}}}*/
b2e465d6
AL
822
823// Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/
6321777b 824// ---------------------------------------------------------------------
b2e465d6
AL
825/* The default just returns the highest available version that is not
826 a source and automatic. */
827pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
6321777b 828{
b2e465d6
AL
829 /* Not source/not automatic versions cannot be a candidate version
830 unless they are already installed */
831 VerIterator Last(*(pkgCache *)this,0);
6321777b 832
b2e465d6
AL
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 }
6321777b 855
b2e465d6
AL
856 return Last;
857}
858 /*}}}*/
859// Policy::IsImportantDep - True if the dependency is important /*{{{*/
860// ---------------------------------------------------------------------
861/* */
862bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
863{
864 return Dep.IsCritical();
6321777b
AL
865}
866 /*}}}*/