]> git.saurik.com Git - apt.git/blame - apt-pkg/depcache.cc
* apt-pkg/policy.cc:
[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>
d4c5f11f
MV
19#include <apt-pkg/configuration.h>
20
b2e465d6 21#include <apti18n.h>
6c139d6e
AL
22 /*}}}*/
23
24// DepCache::pkgDepCache - Constructors /*{{{*/
25// ---------------------------------------------------------------------
26/* */
b2e465d6
AL
27pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
28 Cache(pCache), PkgState(0), DepState(0)
6c139d6e 29{
b2e465d6
AL
30 delLocalPolicy = 0;
31 LocalPolicy = Plcy;
32 if (LocalPolicy == 0)
33 delLocalPolicy = LocalPolicy = new Policy;
6c139d6e
AL
34}
35 /*}}}*/
36// DepCache::~pkgDepCache - Destructor /*{{{*/
37// ---------------------------------------------------------------------
38/* */
39pkgDepCache::~pkgDepCache()
40{
41 delete [] PkgState;
42 delete [] DepState;
b2e465d6 43 delete delLocalPolicy;
6c139d6e
AL
44}
45 /*}}}*/
6c139d6e
AL
46// DepCache::Init - Generate the initial extra structures. /*{{{*/
47// ---------------------------------------------------------------------
48/* This allocats the extension buffers and initializes them. */
a246f2dc 49bool pkgDepCache::Init(OpProgress *Prog)
6c139d6e
AL
50{
51 delete [] PkgState;
52 delete [] DepState;
53 PkgState = new StateCache[Head().PackageCount];
54 DepState = new unsigned char[Head().DependsCount];
55 memset(PkgState,0,sizeof(*PkgState)*Head().PackageCount);
56 memset(DepState,0,sizeof(*DepState)*Head().DependsCount);
b2e465d6 57
a246f2dc
AL
58 if (Prog != 0)
59 {
60 Prog->OverallProgress(0,2*Head().PackageCount,Head().PackageCount,
db0db9fe
CP
61 _("Building dependency tree"));
62 Prog->SubProgress(Head().PackageCount,_("Candidate versions"));
a246f2dc
AL
63 }
64
6c139d6e
AL
65 /* Set the current state of everything. In this state all of the
66 packages are kept exactly as is. See AllUpgrade */
a246f2dc
AL
67 int Done = 0;
68 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
6c139d6e 69 {
a246f2dc
AL
70 if (Prog != 0)
71 Prog->Progress(Done);
72
6c139d6e
AL
73 // Find the proper cache slot
74 StateCache &State = PkgState[I->ID];
75 State.iFlags = 0;
76
77 // Figure out the install version
78 State.CandidateVer = GetCandidateVer(I);
79 State.InstallVer = I.CurrentVer();
80 State.Mode = ModeKeep;
81
82 State.Update(I,*this);
83 }
84
a246f2dc
AL
85 if (Prog != 0)
86 {
87
88 Prog->OverallProgress(Head().PackageCount,2*Head().PackageCount,
89 Head().PackageCount,
db0db9fe
CP
90 _("Building dependency tree"));
91 Prog->SubProgress(Head().PackageCount,_("Dependency generation"));
a246f2dc
AL
92 }
93
94 Update(Prog);
bebfc824
MV
95
96 if(Prog != 0)
97 Prog->Done();
6c139d6e
AL
98
99 return true;
100}
101 /*}}}*/
6c139d6e
AL
102
103// DepCache::CheckDep - Checks a single dependency /*{{{*/
104// ---------------------------------------------------------------------
105/* This first checks the dependency against the main target package and
106 then walks along the package provides list and checks if each provides
107 will be installed then checks the provides against the dep. Res will be
108 set to the package which was used to satisfy the dep. */
109bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
110{
111 Res = Dep.TargetPkg();
112
113 /* Check simple depends. A depends -should- never self match but
114 we allow it anyhow because dpkg does. Technically it is a packaging
115 bug. Conflicts may never self match */
b2e465d6
AL
116 if (Dep.TargetPkg() != Dep.ParentPkg() ||
117 (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes))
6c139d6e
AL
118 {
119 PkgIterator Pkg = Dep.TargetPkg();
120 // Check the base package
121 if (Type == NowVersion && Pkg->CurrentVer != 0)
b2e465d6
AL
122 if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep->CompareOp,
123 Dep.TargetVer()) == true)
6c139d6e
AL
124 return true;
125
126 if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
b2e465d6
AL
127 if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
128 Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
129 return true;
130
131 if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
b2e465d6
AL
132 if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
133 Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
134 return true;
135 }
136
b2e465d6
AL
137 if (Dep->Type == Dep::Obsoletes)
138 return false;
139
6c139d6e
AL
140 // Check the providing packages
141 PrvIterator P = Dep.TargetPkg().ProvidesList();
142 PkgIterator Pkg = Dep.ParentPkg();
143 for (; P.end() != true; P++)
144 {
145 /* Provides may never be applied against the same package if it is
146 a conflicts. See the comment above. */
147 if (P.OwnerPkg() == Pkg && Dep->Type == Dep::Conflicts)
148 continue;
149
150 // Check if the provides is a hit
151 if (Type == NowVersion)
152 {
153 if (P.OwnerPkg().CurrentVer() != P.OwnerVer())
154 continue;
155 }
156
157 if (Type == InstallVersion)
158 {
159 StateCache &State = PkgState[P.OwnerPkg()->ID];
160 if (State.InstallVer != (Version *)P.OwnerVer())
161 continue;
162 }
163
164 if (Type == CandidateVersion)
165 {
166 StateCache &State = PkgState[P.OwnerPkg()->ID];
167 if (State.CandidateVer != (Version *)P.OwnerVer())
168 continue;
169 }
170
171 // Compare the versions.
b2e465d6 172 if (VS().CheckDep(P.ProvideVersion(),Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
173 {
174 Res = P.OwnerPkg();
175 return true;
176 }
177 }
178
179 return false;
180}
181 /*}}}*/
182// DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
183// ---------------------------------------------------------------------
184/* Call with Mult = -1 to preform the inverse opration */
b2e465d6 185void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
6c139d6e
AL
186{
187 StateCache &P = PkgState[Pkg->ID];
188
e7b470ee
AL
189 if (Pkg->VersionList == 0)
190 return;
191
e5a1f2ff
AL
192 if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
193 P.Keep() == true)
2cca3bd9 194 return;
2cca3bd9 195
6c139d6e
AL
196 // Compute the size data
197 if (P.NewInstall() == true)
198 {
b2e465d6
AL
199 iUsrSize += (signed)(Mult*P.InstVerIter(*this)->InstalledSize);
200 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d 201 return;
6c139d6e
AL
202 }
203
204 // Upgrading
d0c59649
AL
205 if (Pkg->CurrentVer != 0 &&
206 (P.InstallVer != (Version *)Pkg.CurrentVer() ||
207 (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
6c139d6e 208 {
b2e465d6
AL
209 iUsrSize += (signed)(Mult*((signed)P.InstVerIter(*this)->InstalledSize -
210 (signed)Pkg.CurrentVer()->InstalledSize));
211 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d
AL
212 return;
213 }
214
215 // Reinstall
2cca3bd9
AL
216 if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
217 P.Delete() == false)
d38b7b3d 218 {
b2e465d6 219 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d 220 return;
6c139d6e
AL
221 }
222
223 // Removing
224 if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
d38b7b3d 225 {
b2e465d6 226 iUsrSize -= (signed)(Mult*Pkg.CurrentVer()->InstalledSize);
d38b7b3d
AL
227 return;
228 }
6c139d6e
AL
229}
230 /*}}}*/
231// DepCache::AddStates - Add the package to the state counter /*{{{*/
232// ---------------------------------------------------------------------
233/* This routine is tricky to use, you must make sure that it is never
234 called twice for the same package. This means the Remove/Add section
235 should be as short as possible and not encompass any code that will
236 calld Remove/Add itself. Remember, dependencies can be circular so
237 while processing a dep for Pkg it is possible that Add/Remove
238 will be called on Pkg */
239void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add)
240{
241 StateCache &State = PkgState[Pkg->ID];
242
243 // The Package is broken
244 if ((State.DepState & DepInstMin) != DepInstMin)
245 iBrokenCount += Add;
246
247 // Bad state
248 if (Pkg.State() != PkgIterator::NeedsNothing)
249 iBadCount += Add;
250
251 // Not installed
252 if (Pkg->CurrentVer == 0)
253 {
d556d1a1
AL
254 if (State.Mode == ModeDelete &&
255 (State.iFlags | Purge) == Purge && Pkg.Purge() == false)
256 iDelCount += Add;
257
6c139d6e
AL
258 if (State.Mode == ModeInstall)
259 iInstCount += Add;
260 return;
261 }
262
263 // Installed, no upgrade
6321777b 264 if (State.Status == 0)
d0c59649 265 {
6c139d6e
AL
266 if (State.Mode == ModeDelete)
267 iDelCount += Add;
d0c59649
AL
268 else
269 if ((State.iFlags & ReInstall) == ReInstall)
270 iInstCount += Add;
271
6c139d6e
AL
272 return;
273 }
274
275 // Alll 3 are possible
276 if (State.Mode == ModeDelete)
277 iDelCount += Add;
278 if (State.Mode == ModeKeep)
279 iKeepCount += Add;
280 if (State.Mode == ModeInstall)
281 iInstCount += Add;
282}
283 /*}}}*/
284// DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
285// ---------------------------------------------------------------------
286/* The or group results are stored in the last item of the or group. This
287 allows easy detection of the state of a whole or'd group. */
288void pkgDepCache::BuildGroupOrs(VerIterator const &V)
289{
290 unsigned char Group = 0;
291
292 for (DepIterator D = V.DependsList(); D.end() != true; D++)
293 {
294 // Build the dependency state.
295 unsigned char &State = DepState[D->ID];
296
297 /* Invert for Conflicts. We have to do this twice to get the
298 right sense for a conflicts group */
b2e465d6 299 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e
AL
300 State = ~State;
301
302 // Add to the group if we are within an or..
d2685fd6 303 State &= 0x7;
6c139d6e
AL
304 Group |= State;
305 State |= Group << 3;
306 if ((D->CompareOp & Dep::Or) != Dep::Or)
307 Group = 0;
308
309 // Invert for Conflicts
b2e465d6 310 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e
AL
311 State = ~State;
312 }
313}
314 /*}}}*/
315// DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
316// ---------------------------------------------------------------------
317/* This is used to run over a dependency list and determine the dep
318 state of the list, filtering it through both a Min check and a Policy
319 check. The return result will have SetMin/SetPolicy low if a check
320 fails. It uses the DepState cache for it's computations. */
321unsigned char pkgDepCache::VersionState(DepIterator D,unsigned char Check,
322 unsigned char SetMin,
323 unsigned char SetPolicy)
324{
325 unsigned char Dep = 0xFF;
326
327 while (D.end() != true)
328 {
329 // Compute a single dependency element (glob or)
330 DepIterator Start = D;
331 unsigned char State = 0;
332 for (bool LastOR = true; D.end() == false && LastOR == true; D++)
333 {
334 State |= DepState[D->ID];
335 LastOR = (D->CompareOp & Dep::Or) == Dep::Or;
336 }
337
338 // Minimum deps that must be satisfied to have a working package
339 if (Start.IsCritical() == true)
340 if ((State & Check) != Check)
341 Dep &= ~SetMin;
342
343 // Policy deps that must be satisfied to install the package
344 if (IsImportantDep(Start) == true &&
345 (State & Check) != Check)
346 Dep &= ~SetPolicy;
347 }
348
349 return Dep;
350}
351 /*}}}*/
352// DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
353// ---------------------------------------------------------------------
354/* This is the main dependency computation bit. It computes the 3 main
355 results for a dependencys, Now, Install and Candidate. Callers must
356 invert the result if dealing with conflicts. */
357unsigned char pkgDepCache::DependencyState(DepIterator &D)
358{
359 unsigned char State = 0;
360
361 if (CheckDep(D,NowVersion) == true)
362 State |= DepNow;
363 if (CheckDep(D,InstallVersion) == true)
364 State |= DepInstall;
365 if (CheckDep(D,CandidateVersion) == true)
366 State |= DepCVer;
367
368 return State;
369}
370 /*}}}*/
371// DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
372// ---------------------------------------------------------------------
373/* This determines the combined dependency representation of a package
374 for its two states now and install. This is done by using the pre-generated
375 dependency information. */
376void pkgDepCache::UpdateVerState(PkgIterator Pkg)
377{
378 // Empty deps are always true
379 StateCache &State = PkgState[Pkg->ID];
380 State.DepState = 0xFF;
381
382 // Check the Current state
383 if (Pkg->CurrentVer != 0)
384 {
385 DepIterator D = Pkg.CurrentVer().DependsList();
386 State.DepState &= VersionState(D,DepNow,DepNowMin,DepNowPolicy);
387 }
388
389 /* Check the candidate state. We do not compare against the whole as
390 a candidate state but check the candidate version against the
391 install states */
392 if (State.CandidateVer != 0)
393 {
394 DepIterator D = State.CandidateVerIter(*this).DependsList();
395 State.DepState &= VersionState(D,DepInstall,DepCandMin,DepCandPolicy);
396 }
397
398 // Check target state which can only be current or installed
399 if (State.InstallVer != 0)
400 {
401 DepIterator D = State.InstVerIter(*this).DependsList();
402 State.DepState &= VersionState(D,DepInstall,DepInstMin,DepInstPolicy);
403 }
404}
405 /*}}}*/
406// DepCache::Update - Figure out all the state information /*{{{*/
407// ---------------------------------------------------------------------
408/* This will figure out the state of all the packages and all the
409 dependencies based on the current policy. */
a246f2dc 410void pkgDepCache::Update(OpProgress *Prog)
6c139d6e
AL
411{
412 iUsrSize = 0;
413 iDownloadSize = 0;
414 iDelCount = 0;
415 iInstCount = 0;
416 iKeepCount = 0;
417 iBrokenCount = 0;
418 iBadCount = 0;
419
420 // Perform the depends pass
a246f2dc
AL
421 int Done = 0;
422 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
6c139d6e 423 {
a246f2dc
AL
424 if (Prog != 0 && Done%20 == 0)
425 Prog->Progress(Done);
6c139d6e
AL
426 for (VerIterator V = I.VersionList(); V.end() != true; V++)
427 {
428 unsigned char Group = 0;
429
430 for (DepIterator D = V.DependsList(); D.end() != true; D++)
431 {
432 // Build the dependency state.
433 unsigned char &State = DepState[D->ID];
b2e465d6 434 State = DependencyState(D);
6c139d6e
AL
435
436 // Add to the group if we are within an or..
437 Group |= State;
438 State |= Group << 3;
439 if ((D->CompareOp & Dep::Or) != Dep::Or)
440 Group = 0;
441
442 // Invert for Conflicts
b2e465d6 443 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e
AL
444 State = ~State;
445 }
446 }
447
448 // Compute the pacakge dependency state and size additions
449 AddSizes(I);
450 UpdateVerState(I);
451 AddStates(I);
452 }
a246f2dc
AL
453
454 if (Prog != 0)
455 Prog->Progress(Done);
6c139d6e
AL
456}
457 /*}}}*/
458// DepCache::Update - Update the deps list of a package /*{{{*/
459// ---------------------------------------------------------------------
460/* This is a helper for update that only does the dep portion of the scan.
461 It is mainly ment to scan reverse dependencies. */
462void pkgDepCache::Update(DepIterator D)
463{
464 // Update the reverse deps
465 for (;D.end() != true; D++)
466 {
467 unsigned char &State = DepState[D->ID];
468 State = DependencyState(D);
469
470 // Invert for Conflicts
b2e465d6 471 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e 472 State = ~State;
b2e465d6 473
6c139d6e
AL
474 RemoveStates(D.ParentPkg());
475 BuildGroupOrs(D.ParentVer());
476 UpdateVerState(D.ParentPkg());
477 AddStates(D.ParentPkg());
478 }
479}
480 /*}}}*/
481// DepCache::Update - Update the related deps of a package /*{{{*/
482// ---------------------------------------------------------------------
483/* This is called whenever the state of a package changes. It updates
484 all cached dependencies related to this package. */
485void pkgDepCache::Update(PkgIterator const &Pkg)
b2e465d6 486{
6c139d6e
AL
487 // Recompute the dep of the package
488 RemoveStates(Pkg);
489 UpdateVerState(Pkg);
490 AddStates(Pkg);
491
492 // Update the reverse deps
493 Update(Pkg.RevDependsList());
494
495 // Update the provides map for the current ver
496 if (Pkg->CurrentVer != 0)
497 for (PrvIterator P = Pkg.CurrentVer().ProvidesList();
498 P.end() != true; P++)
499 Update(P.ParentPkg().RevDependsList());
500
501 // Update the provides map for the candidate ver
9972233d
AL
502 if (PkgState[Pkg->ID].CandidateVer != 0)
503 for (PrvIterator P = PkgState[Pkg->ID].CandidateVerIter(*this).ProvidesList();
504 P.end() != true; P++)
505 Update(P.ParentPkg().RevDependsList());
6c139d6e
AL
506}
507
508 /*}}}*/
509
510// DepCache::MarkKeep - Put the package in the keep state /*{{{*/
511// ---------------------------------------------------------------------
512/* */
513void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
514{
515 // Simplifies other routines.
516 if (Pkg.end() == true)
517 return;
813c8eea
AL
518
519 /* Reject an attempt to keep a non-source broken installed package, those
520 must be upgraded */
521 if (Pkg.State() == PkgIterator::NeedsUnpack &&
522 Pkg.CurrentVer().Downloadable() == false)
523 return;
6c139d6e
AL
524
525 /* We changed the soft state all the time so the UI is a bit nicer
526 to use */
527 StateCache &P = PkgState[Pkg->ID];
528 if (Soft == true)
529 P.iFlags |= AutoKept;
530 else
531 P.iFlags &= ~AutoKept;
532
533 // Check that it is not already kept
534 if (P.Mode == ModeKeep)
535 return;
536
537 // We dont even try to keep virtual packages..
538 if (Pkg->VersionList == 0)
539 return;
540
541 P.Flags &= ~Flag::Auto;
542 RemoveSizes(Pkg);
543 RemoveStates(Pkg);
544
545 P.Mode = ModeKeep;
546 if (Pkg->CurrentVer == 0)
547 P.InstallVer = 0;
548 else
549 P.InstallVer = Pkg.CurrentVer();
550
551 AddStates(Pkg);
552
553 Update(Pkg);
554
555 AddSizes(Pkg);
556}
557 /*}}}*/
558// DepCache::MarkDelete - Put the package in the delete state /*{{{*/
559// ---------------------------------------------------------------------
560/* */
d556d1a1 561void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
6c139d6e
AL
562{
563 // Simplifies other routines.
564 if (Pkg.end() == true)
565 return;
566
567 // Check that it is not already marked for delete
568 StateCache &P = PkgState[Pkg->ID];
d556d1a1
AL
569 P.iFlags &= ~(AutoKept | Purge);
570 if (rPurge == true)
571 P.iFlags |= Purge;
572
573 if ((P.Mode == ModeDelete || P.InstallVer == 0) &&
574 (Pkg.Purge() == true || rPurge == false))
6c139d6e 575 return;
d556d1a1 576
6c139d6e
AL
577 // We dont even try to delete virtual packages..
578 if (Pkg->VersionList == 0)
579 return;
580
581 RemoveSizes(Pkg);
582 RemoveStates(Pkg);
583
d556d1a1 584 if (Pkg->CurrentVer == 0 && (Pkg.Purge() == true || rPurge == false))
3d615484
AL
585 P.Mode = ModeKeep;
586 else
587 P.Mode = ModeDelete;
6c139d6e
AL
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/* */
b2e465d6
AL
599void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
600 unsigned long Depth)
601{
602 if (Depth > 100)
603 return;
604
6c139d6e
AL
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 }
b2e465d6
AL
620
621 // See if there is even any possible instalation candidate
622 if (P.CandidateVer == 0)
623 return;
6c139d6e
AL
624
625 // We dont even try to install virtual packages..
626 if (Pkg->VersionList == 0)
627 return;
628
629 /* Target the candidate version and remove the autoflag. We reset the
630 autoflag below if this was called recursively. Otherwise the user
631 should have the ability to de-auto a package by changing its state */
632 RemoveSizes(Pkg);
633 RemoveStates(Pkg);
634
635 P.Mode = ModeInstall;
636 P.InstallVer = P.CandidateVer;
637 P.Flags &= ~Flag::Auto;
638 if (P.CandidateVer == (Version *)Pkg.CurrentVer())
639 P.Mode = ModeKeep;
640
641 AddStates(Pkg);
642 Update(Pkg);
643 AddSizes(Pkg);
644
645 if (AutoInst == false)
646 return;
647
648 DepIterator Dep = P.InstVerIter(*this).DependsList();
649 for (; Dep.end() != true;)
650 {
651 // Grok or groups
652 DepIterator Start = Dep;
653 bool Result = true;
b2e465d6
AL
654 unsigned Ors = 0;
655 for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++,Ors++)
6c139d6e
AL
656 {
657 LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or;
658
659 if ((DepState[Dep->ID] & DepInstall) == DepInstall)
660 Result = false;
661 }
662
663 // Dep is satisfied okay.
664 if (Result == false)
665 continue;
666
667 /* Check if this dep should be consider for install. If it is a user
668 defined important dep and we are installed a new package then
669 it will be installed. Otherwise we only worry about critical deps */
670 if (IsImportantDep(Start) == false)
671 continue;
672 if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
673 continue;
b2e465d6
AL
674
675 /* If we are in an or group locate the first or that can
676 succeed. We have already cached this.. */
677 for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; Ors--)
678 Start++;
2ed9b455 679
b2e465d6
AL
680 /* This bit is for processing the possibilty of an install/upgrade
681 fixing the problem */
682 SPtrArray<Version *> List = Start.AllTargets();
6c139d6e
AL
683 if ((DepState[Start->ID] & DepCVer) == DepCVer)
684 {
b2e465d6
AL
685 // Right, find the best version to install..
686 Version **Cur = List;
687 PkgIterator P = Start.TargetPkg();
688 PkgIterator InstPkg(*Cache,0);
6c139d6e 689
b2e465d6
AL
690 // See if there are direct matches (at the start of the list)
691 for (; *Cur != 0 && (*Cur)->ParentPkg == P.Index(); Cur++)
692 {
693 PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
694 if (PkgState[Pkg->ID].CandidateVer != *Cur)
695 continue;
696 InstPkg = Pkg;
697 break;
698 }
699
700 // Select the highest priority providing package
2ed9b455 701 if (InstPkg.end() == true)
b2e465d6
AL
702 {
703 pkgPrioSortList(*Cache,Cur);
704 for (; *Cur != 0; Cur++)
705 {
706 PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
707 if (PkgState[Pkg->ID].CandidateVer != *Cur)
708 continue;
709 InstPkg = Pkg;
710 break;
711 }
712 }
713
714 if (InstPkg.end() == false)
715 {
d4c5f11f
MV
716 if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
717 std::clog << "Installing " << InstPkg.Name()
718 << " as dep of " << Pkg.Name()
719 << std::endl;
b2e465d6 720 MarkInstall(InstPkg,true,Depth + 1);
6c139d6e 721
b2e465d6
AL
722 // Set the autoflag, after MarkInstall because MarkInstall unsets it
723 if (P->CurrentVer == 0)
724 PkgState[InstPkg->ID].Flags |= Flag::Auto;
725 }
726
6c139d6e
AL
727 continue;
728 }
729
b2e465d6
AL
730 /* For conflicts we just de-install the package and mark as auto,
731 Conflicts may not have or groups */
732 if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes)
6c139d6e 733 {
6c139d6e
AL
734 for (Version **I = List; *I != 0; I++)
735 {
736 VerIterator Ver(*this,*I);
737 PkgIterator Pkg = Ver.ParentPkg();
738
739 MarkDelete(Pkg);
740 PkgState[Pkg->ID].Flags |= Flag::Auto;
741 }
6c139d6e
AL
742 continue;
743 }
744 }
745}
746 /*}}}*/
d0c59649
AL
747// DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
748// ---------------------------------------------------------------------
749/* */
750void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
751{
752 RemoveSizes(Pkg);
753 RemoveStates(Pkg);
754
755 StateCache &P = PkgState[Pkg->ID];
756 if (To == true)
757 P.iFlags |= ReInstall;
758 else
759 P.iFlags &= ~ReInstall;
760
761 AddStates(Pkg);
762 AddSizes(Pkg);
763}
764 /*}}}*/
b2e465d6
AL
765// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
766// ---------------------------------------------------------------------
767/* */
768void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
769{
770 pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
771 StateCache &P = PkgState[Pkg->ID];
772
773 RemoveSizes(Pkg);
774 RemoveStates(Pkg);
775
776 if (P.CandidateVer == P.InstallVer)
777 P.InstallVer = (Version *)TargetVer;
778 P.CandidateVer = (Version *)TargetVer;
779 P.Update(Pkg,*this);
780
781 AddStates(Pkg);
782 Update(Pkg);
783 AddSizes(Pkg);
784}
785 /*}}}*/
6c139d6e
AL
786// StateCache::Update - Compute the various static display things /*{{{*/
787// ---------------------------------------------------------------------
788/* This is called whenever the Candidate version changes. */
789void pkgDepCache::StateCache::Update(PkgIterator Pkg,pkgCache &Cache)
790{
791 // Some info
792 VerIterator Ver = CandidateVerIter(Cache);
793
794 // Use a null string or the version string
795 if (Ver.end() == true)
796 CandVersion = "";
797 else
798 CandVersion = Ver.VerStr();
799
800 // Find the current version
801 CurVersion = "";
802 if (Pkg->CurrentVer != 0)
803 CurVersion = Pkg.CurrentVer().VerStr();
804
805 // Strip off the epochs for display
806 CurVersion = StripEpoch(CurVersion);
807 CandVersion = StripEpoch(CandVersion);
808
809 // Figure out if its up or down or equal
810 Status = Ver.CompareVer(Pkg.CurrentVer());
811 if (Pkg->CurrentVer == 0 || Pkg->VersionList == 0 || CandidateVer == 0)
812 Status = 2;
813}
814 /*}}}*/
815// StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
816// ---------------------------------------------------------------------
817/* */
818const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
819{
820 if (Ver == 0)
821 return 0;
822
823 // Strip any epoch
824 for (const char *I = Ver; *I != 0; I++)
825 if (*I == ':')
826 return I + 1;
827 return Ver;
828}
829 /*}}}*/
b2e465d6
AL
830
831// Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/
6321777b 832// ---------------------------------------------------------------------
b2e465d6
AL
833/* The default just returns the highest available version that is not
834 a source and automatic. */
835pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
6321777b 836{
b2e465d6
AL
837 /* Not source/not automatic versions cannot be a candidate version
838 unless they are already installed */
839 VerIterator Last(*(pkgCache *)this,0);
6321777b 840
b2e465d6
AL
841 for (VerIterator I = Pkg.VersionList(); I.end() == false; I++)
842 {
843 if (Pkg.CurrentVer() == I)
844 return I;
845
846 for (VerFileIterator J = I.FileList(); J.end() == false; J++)
847 {
848 if ((J.File()->Flags & Flag::NotSource) != 0)
849 continue;
850
851 /* Stash the highest version of a not-automatic source, we use it
852 if there is nothing better */
853 if ((J.File()->Flags & Flag::NotAutomatic) != 0)
854 {
855 if (Last.end() == true)
856 Last = I;
857 continue;
858 }
859
860 return I;
861 }
862 }
6321777b 863
b2e465d6
AL
864 return Last;
865}
866 /*}}}*/
867// Policy::IsImportantDep - True if the dependency is important /*{{{*/
868// ---------------------------------------------------------------------
869/* */
870bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
871{
872 return Dep.IsCritical();
6321777b
AL
873}
874 /*}}}*/