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