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