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