]> git.saurik.com Git - apt.git/blame - apt-pkg/depcache.cc
* moved most of the real work into depcache::writeStateFile
[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>
a83d884d 23#include <sstream>
b2e465d6 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 105
a83d884d
MV
106bool 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
141bool 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++) {
80fa0d8a
MV
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
a83d884d
MV
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
6c139d6e
AL
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. */
183bool 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 */
b2e465d6
AL
190 if (Dep.TargetPkg() != Dep.ParentPkg() ||
191 (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes))
6c139d6e
AL
192 {
193 PkgIterator Pkg = Dep.TargetPkg();
194 // Check the base package
195 if (Type == NowVersion && Pkg->CurrentVer != 0)
b2e465d6
AL
196 if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep->CompareOp,
197 Dep.TargetVer()) == true)
6c139d6e
AL
198 return true;
199
200 if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
b2e465d6
AL
201 if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
202 Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
203 return true;
204
205 if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
b2e465d6
AL
206 if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
207 Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
208 return true;
209 }
210
b2e465d6
AL
211 if (Dep->Type == Dep::Obsoletes)
212 return false;
213
6c139d6e
AL
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.
b2e465d6 246 if (VS().CheckDep(P.ProvideVersion(),Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
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 */
b2e465d6 259void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
6c139d6e
AL
260{
261 StateCache &P = PkgState[Pkg->ID];
262
e7b470ee
AL
263 if (Pkg->VersionList == 0)
264 return;
265
e5a1f2ff
AL
266 if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
267 P.Keep() == true)
2cca3bd9 268 return;
2cca3bd9 269
6c139d6e
AL
270 // Compute the size data
271 if (P.NewInstall() == true)
272 {
b2e465d6
AL
273 iUsrSize += (signed)(Mult*P.InstVerIter(*this)->InstalledSize);
274 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d 275 return;
6c139d6e
AL
276 }
277
278 // Upgrading
d0c59649
AL
279 if (Pkg->CurrentVer != 0 &&
280 (P.InstallVer != (Version *)Pkg.CurrentVer() ||
281 (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
6c139d6e 282 {
b2e465d6
AL
283 iUsrSize += (signed)(Mult*((signed)P.InstVerIter(*this)->InstalledSize -
284 (signed)Pkg.CurrentVer()->InstalledSize));
285 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d
AL
286 return;
287 }
288
289 // Reinstall
2cca3bd9
AL
290 if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
291 P.Delete() == false)
d38b7b3d 292 {
b2e465d6 293 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d 294 return;
6c139d6e
AL
295 }
296
297 // Removing
298 if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
d38b7b3d 299 {
b2e465d6 300 iUsrSize -= (signed)(Mult*Pkg.CurrentVer()->InstalledSize);
d38b7b3d
AL
301 return;
302 }
6c139d6e
AL
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 */
313void 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 {
d556d1a1
AL
328 if (State.Mode == ModeDelete &&
329 (State.iFlags | Purge) == Purge && Pkg.Purge() == false)
330 iDelCount += Add;
331
6c139d6e
AL
332 if (State.Mode == ModeInstall)
333 iInstCount += Add;
334 return;
335 }
336
337 // Installed, no upgrade
6321777b 338 if (State.Status == 0)
d0c59649 339 {
6c139d6e
AL
340 if (State.Mode == ModeDelete)
341 iDelCount += Add;
d0c59649
AL
342 else
343 if ((State.iFlags & ReInstall) == ReInstall)
344 iInstCount += Add;
345
6c139d6e
AL
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. */
362void 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 */
b2e465d6 373 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e
AL
374 State = ~State;
375
376 // Add to the group if we are within an or..
d2685fd6 377 State &= 0x7;
6c139d6e
AL
378 Group |= State;
379 State |= Group << 3;
380 if ((D->CompareOp & Dep::Or) != Dep::Or)
381 Group = 0;
382
383 // Invert for Conflicts
b2e465d6 384 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e
AL
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. */
395unsigned 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. */
431unsigned 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. */
450void 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. */
a246f2dc 484void pkgDepCache::Update(OpProgress *Prog)
6c139d6e
AL
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
a246f2dc
AL
495 int Done = 0;
496 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
6c139d6e 497 {
a246f2dc
AL
498 if (Prog != 0 && Done%20 == 0)
499 Prog->Progress(Done);
6c139d6e
AL
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];
b2e465d6 508 State = DependencyState(D);
6c139d6e
AL
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
b2e465d6 517 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e
AL
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 }
a246f2dc 527
a83d884d 528 readStateFile(Prog);
afb1e2e3 529
a246f2dc
AL
530 if (Prog != 0)
531 Prog->Progress(Done);
6c139d6e
AL
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. */
538void 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
b2e465d6 547 if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
6c139d6e 548 State = ~State;
b2e465d6 549
6c139d6e
AL
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. */
561void pkgDepCache::Update(PkgIterator const &Pkg)
b2e465d6 562{
6c139d6e
AL
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
9972233d
AL
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());
6c139d6e
AL
582}
583
584 /*}}}*/
585
586// DepCache::MarkKeep - Put the package in the keep state /*{{{*/
587// ---------------------------------------------------------------------
588/* */
589void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
590{
591 // Simplifies other routines.
592 if (Pkg.end() == true)
593 return;
813c8eea
AL
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;
6c139d6e
AL
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/* */
d556d1a1 637void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
6c139d6e
AL
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];
d556d1a1
AL
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))
6c139d6e 651 return;
d556d1a1 652
6c139d6e
AL
653 // We dont even try to delete virtual packages..
654 if (Pkg->VersionList == 0)
655 return;
656
657 RemoveSizes(Pkg);
658 RemoveStates(Pkg);
659
d556d1a1 660 if (Pkg->CurrentVer == 0 && (Pkg.Purge() == true || rPurge == false))
3d615484
AL
661 P.Mode = ModeKeep;
662 else
663 P.Mode = ModeDelete;
6c139d6e 664 P.InstallVer = 0;
afb1e2e3
MV
665 // This was not inverted before, but I think it should be
666 P.Flags &= ~Flag::Auto;
6c139d6e
AL
667
668 AddStates(Pkg);
669 Update(Pkg);
670 AddSizes(Pkg);
671}
672 /*}}}*/
673// DepCache::MarkInstall - Put the package in the install state /*{{{*/
674// ---------------------------------------------------------------------
675/* */
b2e465d6
AL
676void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
677 unsigned long Depth)
678{
679 if (Depth > 100)
680 return;
681
6c139d6e
AL
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 }
b2e465d6
AL
697
698 // See if there is even any possible instalation candidate
699 if (P.CandidateVer == 0)
700 return;
6c139d6e
AL
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;
b2e465d6
AL
731 unsigned Ors = 0;
732 for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++,Ors++)
6c139d6e
AL
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;
b2e465d6
AL
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++;
2ed9b455 756
b2e465d6
AL
757 /* This bit is for processing the possibilty of an install/upgrade
758 fixing the problem */
759 SPtrArray<Version *> List = Start.AllTargets();
6c139d6e
AL
760 if ((DepState[Start->ID] & DepCVer) == DepCVer)
761 {
b2e465d6
AL
762 // Right, find the best version to install..
763 Version **Cur = List;
764 PkgIterator P = Start.TargetPkg();
765 PkgIterator InstPkg(*Cache,0);
6c139d6e 766
b2e465d6
AL
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
2ed9b455 778 if (InstPkg.end() == true)
b2e465d6
AL
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);
6c139d6e 794
b2e465d6
AL
795 // Set the autoflag, after MarkInstall because MarkInstall unsets it
796 if (P->CurrentVer == 0)
797 PkgState[InstPkg->ID].Flags |= Flag::Auto;
798 }
799
6c139d6e
AL
800 continue;
801 }
802
b2e465d6
AL
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)
6c139d6e 806 {
6c139d6e
AL
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 }
6c139d6e
AL
815 continue;
816 }
817 }
818}
819 /*}}}*/
d0c59649
AL
820// DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
821// ---------------------------------------------------------------------
822/* */
823void 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 /*}}}*/
afb1e2e3
MV
838// DepCache::SetDirty - Switch the package between dirty states /*{{{*/
839// ---------------------------------------------------------------------
840/* */
841void pkgDepCache::SetDirty(PkgIterator const &Pkg, pkgCache::State::PkgRemoveState To)
842{
843 StateCache &P = PkgState[Pkg->ID];
844 P.DirtyState = To;
845}
846 /*}}}*/
b2e465d6
AL
847// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
848// ---------------------------------------------------------------------
849/* */
850void 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 /*}}}*/
6c139d6e
AL
868// StateCache::Update - Compute the various static display things /*{{{*/
869// ---------------------------------------------------------------------
870/* This is called whenever the Candidate version changes. */
871void 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/* */
900const 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 /*}}}*/
b2e465d6
AL
912
913// Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/
6321777b 914// ---------------------------------------------------------------------
b2e465d6
AL
915/* The default just returns the highest available version that is not
916 a source and automatic. */
917pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
6321777b 918{
b2e465d6
AL
919 /* Not source/not automatic versions cannot be a candidate version
920 unless they are already installed */
921 VerIterator Last(*(pkgCache *)this,0);
6321777b 922
b2e465d6
AL
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 }
6321777b 945
b2e465d6
AL
946 return Last;
947}
948 /*}}}*/
949// Policy::IsImportantDep - True if the dependency is important /*{{{*/
950// ---------------------------------------------------------------------
951/* */
952bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
953{
954 return Dep.IsCritical();
6321777b
AL
955}
956 /*}}}*/