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