]> git.saurik.com Git - apt.git/blob - apt-pkg/depcache.cc
* add --dsc-only option, thanks to K. Richard Pixley
[apt.git] / apt-pkg / depcache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: depcache.cc,v 1.25 2001/05/27 05:36:04 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 #include <apt-pkg/version.h>
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/sptr.h>
18 #include <apt-pkg/algorithms.h>
19 #include <apt-pkg/configuration.h>
20
21 #include <apti18n.h>
22 /*}}}*/
23
24 // DepCache::pkgDepCache - Constructors /*{{{*/
25 // ---------------------------------------------------------------------
26 /* */
27 pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
28 Cache(pCache), PkgState(0), DepState(0)
29 {
30 delLocalPolicy = 0;
31 LocalPolicy = Plcy;
32 if (LocalPolicy == 0)
33 delLocalPolicy = LocalPolicy = new Policy;
34 }
35 /*}}}*/
36 // DepCache::~pkgDepCache - Destructor /*{{{*/
37 // ---------------------------------------------------------------------
38 /* */
39 pkgDepCache::~pkgDepCache()
40 {
41 delete [] PkgState;
42 delete [] DepState;
43 delete delLocalPolicy;
44 }
45 /*}}}*/
46 // DepCache::Init - Generate the initial extra structures. /*{{{*/
47 // ---------------------------------------------------------------------
48 /* This allocats the extension buffers and initializes them. */
49 bool pkgDepCache::Init(OpProgress *Prog)
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);
57
58 if (Prog != 0)
59 {
60 Prog->OverallProgress(0,2*Head().PackageCount,Head().PackageCount,
61 _("Building dependency tree"));
62 Prog->SubProgress(Head().PackageCount,_("Candidate versions"));
63 }
64
65 /* Set the current state of everything. In this state all of the
66 packages are kept exactly as is. See AllUpgrade */
67 int Done = 0;
68 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
69 {
70 if (Prog != 0)
71 Prog->Progress(Done);
72
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
85 if (Prog != 0)
86 {
87
88 Prog->OverallProgress(Head().PackageCount,2*Head().PackageCount,
89 Head().PackageCount,
90 _("Building dependency tree"));
91 Prog->SubProgress(Head().PackageCount,_("Dependency generation"));
92 }
93
94 Update(Prog);
95
96 if(Prog != 0)
97 Prog->Done();
98
99 return true;
100 }
101 /*}}}*/
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. */
109 bool 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 */
116 if (Dep.TargetPkg() != Dep.ParentPkg() ||
117 (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes))
118 {
119 PkgIterator Pkg = Dep.TargetPkg();
120 // Check the base package
121 if (Type == NowVersion && Pkg->CurrentVer != 0)
122 if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep->CompareOp,
123 Dep.TargetVer()) == true)
124 return true;
125
126 if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
127 if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
128 Dep->CompareOp,Dep.TargetVer()) == true)
129 return true;
130
131 if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
132 if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
133 Dep->CompareOp,Dep.TargetVer()) == true)
134 return true;
135 }
136
137 if (Dep->Type == Dep::Obsoletes)
138 return false;
139
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.
172 if (VS().CheckDep(P.ProvideVersion(),Dep->CompareOp,Dep.TargetVer()) == true)
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 */
185 void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
186 {
187 StateCache &P = PkgState[Pkg->ID];
188
189 if (Pkg->VersionList == 0)
190 return;
191
192 if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
193 P.Keep() == true)
194 return;
195
196 // Compute the size data
197 if (P.NewInstall() == true)
198 {
199 iUsrSize += (signed)(Mult*P.InstVerIter(*this)->InstalledSize);
200 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
201 return;
202 }
203
204 // Upgrading
205 if (Pkg->CurrentVer != 0 &&
206 (P.InstallVer != (Version *)Pkg.CurrentVer() ||
207 (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
208 {
209 iUsrSize += (signed)(Mult*((signed)P.InstVerIter(*this)->InstalledSize -
210 (signed)Pkg.CurrentVer()->InstalledSize));
211 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
212 return;
213 }
214
215 // Reinstall
216 if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
217 P.Delete() == false)
218 {
219 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
220 return;
221 }
222
223 // Removing
224 if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
225 {
226 iUsrSize -= (signed)(Mult*Pkg.CurrentVer()->InstalledSize);
227 return;
228 }
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 */
239 void 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 {
254 if (State.Mode == ModeDelete &&
255 (State.iFlags | Purge) == Purge && Pkg.Purge() == false)
256 iDelCount += Add;
257
258 if (State.Mode == ModeInstall)
259 iInstCount += Add;
260 return;
261 }
262
263 // Installed, no upgrade
264 if (State.Status == 0)
265 {
266 if (State.Mode == ModeDelete)
267 iDelCount += Add;
268 else
269 if ((State.iFlags & ReInstall) == ReInstall)
270 iInstCount += Add;
271
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. */
288 void 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 */
299 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
300 State = ~State;
301
302 // Add to the group if we are within an or..
303 State &= 0x7;
304 Group |= State;
305 State |= Group << 3;
306 if ((D->CompareOp & Dep::Or) != Dep::Or)
307 Group = 0;
308
309 // Invert for Conflicts
310 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
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. */
321 unsigned 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. */
357 unsigned 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. */
376 void 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. */
410 void pkgDepCache::Update(OpProgress *Prog)
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
421 int Done = 0;
422 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
423 {
424 if (Prog != 0 && Done%20 == 0)
425 Prog->Progress(Done);
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];
434 State = DependencyState(D);
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
443 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
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 }
453
454 if (Prog != 0)
455 Prog->Progress(Done);
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. */
462 void 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
471 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
472 State = ~State;
473
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. */
485 void pkgDepCache::Update(PkgIterator const &Pkg)
486 {
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
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());
506 }
507
508 /*}}}*/
509
510 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
511 // ---------------------------------------------------------------------
512 /* */
513 void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
514 {
515 // Simplifies other routines.
516 if (Pkg.end() == true)
517 return;
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;
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 /* */
561 void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
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];
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))
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 && (Pkg.Purge() == true || rPurge == false))
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 unsigned long Depth)
601 {
602 if (Depth > 100)
603 return;
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 // See if there is even any possible instalation candidate
622 if (P.CandidateVer == 0)
623 return;
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;
654 unsigned Ors = 0;
655 for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++,Ors++)
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;
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++;
679
680 /* This bit is for processing the possibilty of an install/upgrade
681 fixing the problem */
682 SPtrArray<Version *> List = Start.AllTargets();
683 if ((DepState[Start->ID] & DepCVer) == DepCVer)
684 {
685 // Right, find the best version to install..
686 Version **Cur = List;
687 PkgIterator P = Start.TargetPkg();
688 PkgIterator InstPkg(*Cache,0);
689
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
701 if (InstPkg.end() == true)
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 {
716 if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
717 std::clog << "Installing " << InstPkg.Name()
718 << " as dep of " << Pkg.Name()
719 << std::endl;
720 MarkInstall(InstPkg,true,Depth + 1);
721
722 // Set the autoflag, after MarkInstall because MarkInstall unsets it
723 if (P->CurrentVer == 0)
724 PkgState[InstPkg->ID].Flags |= Flag::Auto;
725 }
726
727 continue;
728 }
729
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)
733 {
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 }
742 continue;
743 }
744 }
745 }
746 /*}}}*/
747 // DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
748 // ---------------------------------------------------------------------
749 /* */
750 void 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 /*}}}*/
765 // DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
766 // ---------------------------------------------------------------------
767 /* */
768 void 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 /*}}}*/
786 // StateCache::Update - Compute the various static display things /*{{{*/
787 // ---------------------------------------------------------------------
788 /* This is called whenever the Candidate version changes. */
789 void 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 /* */
818 const 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 /*}}}*/
830
831 // Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/
832 // ---------------------------------------------------------------------
833 /* The default just returns the highest available version that is not
834 a source and automatic. */
835 pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
836 {
837 /* Not source/not automatic versions cannot be a candidate version
838 unless they are already installed */
839 VerIterator Last(*(pkgCache *)this,0);
840
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 }
863
864 return Last;
865 }
866 /*}}}*/
867 // Policy::IsImportantDep - True if the dependency is important /*{{{*/
868 // ---------------------------------------------------------------------
869 /* */
870 bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
871 {
872 return Dep.IsCritical();
873 }
874 /*}}}*/