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