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