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