]> git.saurik.com Git - apt.git/blame - apt-pkg/depcache.cc
* apt-pkg/acquire-item.cc:
[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>
74a05226 22#include <apt-pkg/pkgsystem.h>
afb1e2e3 23#include <apt-pkg/tagfile.h>
120365ce
MV
24
25#include <iostream>
a83d884d 26#include <sstream>
b1a8717a 27#include <set>
d4c5f11f 28
5f3e0a63
MV
29#include <sys/stat.h>
30
b2e465d6 31#include <apti18n.h>
74a05226
MV
32
33pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :
34 cache(cache), released(false)
35{
36 ++cache.group_level;
37}
38
39void pkgDepCache::ActionGroup::release()
40{
41 if(!released)
42 {
43 if(cache.group_level == 0)
44 std::cerr << "W: Unbalanced action groups, expect badness" << std::endl;
45 else
46 {
47 --cache.group_level;
48
49 if(cache.group_level == 0)
50 cache.MarkAndSweep();
51 }
52
53 released = false;
54 }
55}
56
57pkgDepCache::ActionGroup::~ActionGroup()
58{
59 release();
60}
6c139d6e
AL
61
62// DepCache::pkgDepCache - Constructors /*{{{*/
63// ---------------------------------------------------------------------
64/* */
b2e465d6 65pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
74a05226 66 group_level(0), Cache(pCache), PkgState(0), DepState(0)
6c139d6e 67{
b2e465d6
AL
68 delLocalPolicy = 0;
69 LocalPolicy = Plcy;
70 if (LocalPolicy == 0)
71 delLocalPolicy = LocalPolicy = new Policy;
6c139d6e
AL
72}
73 /*}}}*/
74// DepCache::~pkgDepCache - Destructor /*{{{*/
75// ---------------------------------------------------------------------
76/* */
77pkgDepCache::~pkgDepCache()
78{
79 delete [] PkgState;
80 delete [] DepState;
b2e465d6 81 delete delLocalPolicy;
6c139d6e
AL
82}
83 /*}}}*/
6c139d6e
AL
84// DepCache::Init - Generate the initial extra structures. /*{{{*/
85// ---------------------------------------------------------------------
86/* This allocats the extension buffers and initializes them. */
a246f2dc 87bool pkgDepCache::Init(OpProgress *Prog)
6c139d6e 88{
74a05226
MV
89 // Suppress mark updates during this operation (just in case) and
90 // run a mark operation when Init terminates.
91 ActionGroup actions(*this);
92
6c139d6e
AL
93 delete [] PkgState;
94 delete [] DepState;
95 PkgState = new StateCache[Head().PackageCount];
96 DepState = new unsigned char[Head().DependsCount];
97 memset(PkgState,0,sizeof(*PkgState)*Head().PackageCount);
98 memset(DepState,0,sizeof(*DepState)*Head().DependsCount);
b2e465d6 99
a246f2dc
AL
100 if (Prog != 0)
101 {
102 Prog->OverallProgress(0,2*Head().PackageCount,Head().PackageCount,
db0db9fe
CP
103 _("Building dependency tree"));
104 Prog->SubProgress(Head().PackageCount,_("Candidate versions"));
a246f2dc
AL
105 }
106
6c139d6e
AL
107 /* Set the current state of everything. In this state all of the
108 packages are kept exactly as is. See AllUpgrade */
a246f2dc
AL
109 int Done = 0;
110 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
6c139d6e 111 {
a246f2dc
AL
112 if (Prog != 0)
113 Prog->Progress(Done);
114
6c139d6e
AL
115 // Find the proper cache slot
116 StateCache &State = PkgState[I->ID];
117 State.iFlags = 0;
afb1e2e3 118
6c139d6e
AL
119 // Figure out the install version
120 State.CandidateVer = GetCandidateVer(I);
121 State.InstallVer = I.CurrentVer();
122 State.Mode = ModeKeep;
123
124 State.Update(I,*this);
125 }
126
a246f2dc
AL
127 if (Prog != 0)
128 {
129
130 Prog->OverallProgress(Head().PackageCount,2*Head().PackageCount,
131 Head().PackageCount,
db0db9fe
CP
132 _("Building dependency tree"));
133 Prog->SubProgress(Head().PackageCount,_("Dependency generation"));
a246f2dc
AL
134 }
135
136 Update(Prog);
e004867d
MV
137
138 if(Prog != 0)
139 Prog->Done();
74a05226 140
6c139d6e
AL
141 return true;
142}
143 /*}}}*/
6c139d6e 144
a83d884d
MV
145bool pkgDepCache::readStateFile(OpProgress *Prog)
146{
147 FileFd state_file;
aac2e510 148 string state = _config->FindDir("Dir::State") + "extended_states";
a83d884d
MV
149 if(FileExists(state)) {
150 state_file.Open(state, FileFd::ReadOnly);
151 int file_size = state_file.Size();
bc80031f
MV
152 if(Prog != NULL)
153 Prog->OverallProgress(0, file_size, 1,
154 _("Reading state information"));
a83d884d
MV
155
156 pkgTagFile tagfile(&state_file);
157 pkgTagSection section;
158 int amt=0;
159 while(tagfile.Step(section)) {
160 string pkgname = section.FindS("Package");
161 pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
162 // Silently ignore unknown packages and packages with no actual
163 // version.
164 if(!pkg.end() && !pkg.VersionList().end()) {
fc5aece9 165 short reason = section.FindI("Auto-Installed", 0);
e23e6733 166 if(reason > 0)
f8ac1720 167 PkgState[pkg->ID].Flags |= Flag::Auto;
0a57c0f0 168 if(_config->FindB("Debug::pkgAutoRemove",false))
fc5aece9 169 std::cout << "Auto-Installed : " << pkgname << std::endl;
a83d884d 170 amt+=section.size();
bc80031f
MV
171 if(Prog != NULL)
172 Prog->OverallProgress(amt, file_size, 1,
173 _("Reading state information"));
a83d884d 174 }
bc80031f
MV
175 if(Prog != NULL)
176 Prog->OverallProgress(file_size, file_size, 1,
177 _("Reading state information"));
a83d884d
MV
178 }
179 }
180
181 return true;
182}
183
95689ede 184bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
a83d884d 185{
e23e6733
MV
186 if(_config->FindB("Debug::pkgAutoRemove",false))
187 std::clog << "pkgDepCache::writeStateFile()" << std::endl;
188
b1a8717a
MV
189 FileFd StateFile;
190 string state = _config->FindDir("Dir::State") + "extended_states";
9a9665f9
MV
191
192 // if it does not exist, create a empty one
193 if(!FileExists(state))
194 {
195 StateFile.Open(state, FileFd::WriteEmpty);
196 StateFile.Close();
197 }
198
199 // open it
b1a8717a
MV
200 if(!StateFile.Open(state, FileFd::ReadOnly))
201 return _error->Error(_("Failed to open StateFile %s"),
a83d884d
MV
202 state.c_str());
203
b1a8717a
MV
204 FILE *OutFile;
205 string outfile = state + ".tmp";
206 if((OutFile = fopen(outfile.c_str(),"w")) == NULL)
207 return _error->Error(_("Failed to write temporary StateFile %s"),
208 outfile.c_str());
80fa0d8a 209
b1a8717a
MV
210 // first merge with the existing sections
211 pkgTagFile tagfile(&StateFile);
212 pkgTagSection section;
213 std::set<string> pkgs_seen;
214 const char *nullreorderlist[] = {0};
215 while(tagfile.Step(section)) {
216 string pkgname = section.FindS("Package");
217 // Silently ignore unknown packages and packages with no actual
218 // version.
219 pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
220 if(pkg.end() || pkg.VersionList().end())
221 continue;
222 bool oldAuto = section.FindI("Auto-Installed");
223 bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
224 if(_config->FindB("Debug::pkgAutoRemove",false))
225 std::clog << "Update exisiting AutoInstall info: "
226 << pkg.Name() << std::endl;
227 TFRewriteData rewrite[2];
228 rewrite[0].Tag = "Auto-Installed";
229 rewrite[0].Rewrite = newAuto ? "1" : "0";
230 rewrite[0].NewTag = 0;
231 rewrite[1].Tag = 0;
232 TFRewrite(OutFile, section, nullreorderlist, rewrite);
233 fprintf(OutFile,"\n");
234 pkgs_seen.insert(pkgname);
235 }
236
237 // then write the ones we have not seen yet
238 std::ostringstream ostr;
239 for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) {
f8ac1720 240 if(PkgState[pkg->ID].Flags & Flag::Auto) {
b1a8717a
MV
241 if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) {
242 if(_config->FindB("Debug::pkgAutoRemove",false))
243 std::clog << "Skipping already written " << pkg.Name() << std::endl;
244 continue;
245 }
95689ede
MV
246 // skip not installed ones if requested
247 if(InstalledOnly && pkg->CurrentVer == 0)
248 continue;
e23e6733 249 if(_config->FindB("Debug::pkgAutoRemove",false))
b1a8717a
MV
250 std::clog << "Writing new AutoInstall: "
251 << pkg.Name() << std::endl;
a83d884d 252 ostr.str(string(""));
0a57c0f0 253 ostr << "Package: " << pkg.Name()
fc5aece9 254 << "\nAuto-Installed: 1\n\n";
b1a8717a
MV
255 fprintf(OutFile,ostr.str().c_str());
256 fprintf(OutFile,"\n");
a83d884d
MV
257 }
258 }
8953292e 259 fclose(OutFile);
b1a8717a 260
5f3e0a63 261 // move the outfile over the real file and set permissions
b1a8717a 262 rename(outfile.c_str(), state.c_str());
5f3e0a63 263 chmod(state.c_str(), 0644);
b1a8717a 264
a83d884d
MV
265 return true;
266}
267
6c139d6e
AL
268// DepCache::CheckDep - Checks a single dependency /*{{{*/
269// ---------------------------------------------------------------------
270/* This first checks the dependency against the main target package and
271 then walks along the package provides list and checks if each provides
272 will be installed then checks the provides against the dep. Res will be
273 set to the package which was used to satisfy the dep. */
274bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
275{
276 Res = Dep.TargetPkg();
277
278 /* Check simple depends. A depends -should- never self match but
279 we allow it anyhow because dpkg does. Technically it is a packaging
280 bug. Conflicts may never self match */
b2e465d6 281 if (Dep.TargetPkg() != Dep.ParentPkg() ||
308c7d30 282 (Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
6c139d6e
AL
283 {
284 PkgIterator Pkg = Dep.TargetPkg();
285 // Check the base package
286 if (Type == NowVersion && Pkg->CurrentVer != 0)
b2e465d6
AL
287 if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep->CompareOp,
288 Dep.TargetVer()) == true)
6c139d6e
AL
289 return true;
290
291 if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
b2e465d6
AL
292 if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
293 Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
294 return true;
295
296 if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
b2e465d6
AL
297 if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
298 Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
299 return true;
300 }
301
b2e465d6
AL
302 if (Dep->Type == Dep::Obsoletes)
303 return false;
304
6c139d6e
AL
305 // Check the providing packages
306 PrvIterator P = Dep.TargetPkg().ProvidesList();
307 PkgIterator Pkg = Dep.ParentPkg();
308 for (; P.end() != true; P++)
309 {
310 /* Provides may never be applied against the same package if it is
311 a conflicts. See the comment above. */
308c7d30
IJ
312 if (P.OwnerPkg() == Pkg &&
313 (Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks))
6c139d6e
AL
314 continue;
315
316 // Check if the provides is a hit
317 if (Type == NowVersion)
318 {
319 if (P.OwnerPkg().CurrentVer() != P.OwnerVer())
320 continue;
321 }
322
323 if (Type == InstallVersion)
324 {
325 StateCache &State = PkgState[P.OwnerPkg()->ID];
326 if (State.InstallVer != (Version *)P.OwnerVer())
327 continue;
328 }
329
330 if (Type == CandidateVersion)
331 {
332 StateCache &State = PkgState[P.OwnerPkg()->ID];
333 if (State.CandidateVer != (Version *)P.OwnerVer())
334 continue;
335 }
336
337 // Compare the versions.
b2e465d6 338 if (VS().CheckDep(P.ProvideVersion(),Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
339 {
340 Res = P.OwnerPkg();
341 return true;
342 }
343 }
344
345 return false;
346}
347 /*}}}*/
348// DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
349// ---------------------------------------------------------------------
350/* Call with Mult = -1 to preform the inverse opration */
b2e465d6 351void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
6c139d6e
AL
352{
353 StateCache &P = PkgState[Pkg->ID];
354
e7b470ee
AL
355 if (Pkg->VersionList == 0)
356 return;
357
e5a1f2ff
AL
358 if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
359 P.Keep() == true)
2cca3bd9 360 return;
2cca3bd9 361
6c139d6e
AL
362 // Compute the size data
363 if (P.NewInstall() == true)
364 {
b2e465d6
AL
365 iUsrSize += (signed)(Mult*P.InstVerIter(*this)->InstalledSize);
366 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d 367 return;
6c139d6e
AL
368 }
369
370 // Upgrading
d0c59649
AL
371 if (Pkg->CurrentVer != 0 &&
372 (P.InstallVer != (Version *)Pkg.CurrentVer() ||
373 (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
6c139d6e 374 {
b2e465d6
AL
375 iUsrSize += (signed)(Mult*((signed)P.InstVerIter(*this)->InstalledSize -
376 (signed)Pkg.CurrentVer()->InstalledSize));
377 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d
AL
378 return;
379 }
380
381 // Reinstall
2cca3bd9
AL
382 if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
383 P.Delete() == false)
d38b7b3d 384 {
b2e465d6 385 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d 386 return;
6c139d6e
AL
387 }
388
389 // Removing
390 if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
d38b7b3d 391 {
b2e465d6 392 iUsrSize -= (signed)(Mult*Pkg.CurrentVer()->InstalledSize);
d38b7b3d
AL
393 return;
394 }
6c139d6e
AL
395}
396 /*}}}*/
397// DepCache::AddStates - Add the package to the state counter /*{{{*/
398// ---------------------------------------------------------------------
399/* This routine is tricky to use, you must make sure that it is never
400 called twice for the same package. This means the Remove/Add section
401 should be as short as possible and not encompass any code that will
402 calld Remove/Add itself. Remember, dependencies can be circular so
403 while processing a dep for Pkg it is possible that Add/Remove
404 will be called on Pkg */
405void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add)
406{
407 StateCache &State = PkgState[Pkg->ID];
408
4ef9a929 409 // The Package is broken (either minimal dep or policy dep)
6c139d6e
AL
410 if ((State.DepState & DepInstMin) != DepInstMin)
411 iBrokenCount += Add;
4ef9a929
MV
412 if ((State.DepState & DepInstPolicy) != DepInstPolicy)
413 iPolicyBrokenCount += Add;
6c139d6e
AL
414
415 // Bad state
416 if (Pkg.State() != PkgIterator::NeedsNothing)
417 iBadCount += Add;
418
419 // Not installed
420 if (Pkg->CurrentVer == 0)
421 {
d556d1a1
AL
422 if (State.Mode == ModeDelete &&
423 (State.iFlags | Purge) == Purge && Pkg.Purge() == false)
424 iDelCount += Add;
425
6c139d6e
AL
426 if (State.Mode == ModeInstall)
427 iInstCount += Add;
428 return;
429 }
430
431 // Installed, no upgrade
6321777b 432 if (State.Status == 0)
d0c59649 433 {
6c139d6e
AL
434 if (State.Mode == ModeDelete)
435 iDelCount += Add;
d0c59649
AL
436 else
437 if ((State.iFlags & ReInstall) == ReInstall)
438 iInstCount += Add;
439
6c139d6e
AL
440 return;
441 }
442
443 // Alll 3 are possible
444 if (State.Mode == ModeDelete)
445 iDelCount += Add;
446 if (State.Mode == ModeKeep)
447 iKeepCount += Add;
448 if (State.Mode == ModeInstall)
449 iInstCount += Add;
450}
451 /*}}}*/
452// DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
453// ---------------------------------------------------------------------
454/* The or group results are stored in the last item of the or group. This
455 allows easy detection of the state of a whole or'd group. */
456void pkgDepCache::BuildGroupOrs(VerIterator const &V)
457{
458 unsigned char Group = 0;
459
460 for (DepIterator D = V.DependsList(); D.end() != true; D++)
461 {
462 // Build the dependency state.
463 unsigned char &State = DepState[D->ID];
464
465 /* Invert for Conflicts. We have to do this twice to get the
466 right sense for a conflicts group */
308c7d30
IJ
467 if (D->Type == Dep::Conflicts ||
468 D->Type == Dep::DpkgBreaks ||
469 D->Type == Dep::Obsoletes)
6c139d6e
AL
470 State = ~State;
471
472 // Add to the group if we are within an or..
d2685fd6 473 State &= 0x7;
6c139d6e
AL
474 Group |= State;
475 State |= Group << 3;
476 if ((D->CompareOp & Dep::Or) != Dep::Or)
477 Group = 0;
478
479 // Invert for Conflicts
308c7d30
IJ
480 if (D->Type == Dep::Conflicts ||
481 D->Type == Dep::DpkgBreaks ||
482 D->Type == Dep::Obsoletes)
6c139d6e
AL
483 State = ~State;
484 }
485}
486 /*}}}*/
487// DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
488// ---------------------------------------------------------------------
489/* This is used to run over a dependency list and determine the dep
490 state of the list, filtering it through both a Min check and a Policy
491 check. The return result will have SetMin/SetPolicy low if a check
492 fails. It uses the DepState cache for it's computations. */
493unsigned char pkgDepCache::VersionState(DepIterator D,unsigned char Check,
494 unsigned char SetMin,
495 unsigned char SetPolicy)
496{
497 unsigned char Dep = 0xFF;
498
499 while (D.end() != true)
500 {
501 // Compute a single dependency element (glob or)
502 DepIterator Start = D;
503 unsigned char State = 0;
504 for (bool LastOR = true; D.end() == false && LastOR == true; D++)
505 {
506 State |= DepState[D->ID];
507 LastOR = (D->CompareOp & Dep::Or) == Dep::Or;
508 }
509
510 // Minimum deps that must be satisfied to have a working package
511 if (Start.IsCritical() == true)
512 if ((State & Check) != Check)
513 Dep &= ~SetMin;
514
515 // Policy deps that must be satisfied to install the package
516 if (IsImportantDep(Start) == true &&
517 (State & Check) != Check)
518 Dep &= ~SetPolicy;
519 }
520
521 return Dep;
522}
523 /*}}}*/
524// DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
525// ---------------------------------------------------------------------
526/* This is the main dependency computation bit. It computes the 3 main
527 results for a dependencys, Now, Install and Candidate. Callers must
528 invert the result if dealing with conflicts. */
529unsigned char pkgDepCache::DependencyState(DepIterator &D)
530{
531 unsigned char State = 0;
532
533 if (CheckDep(D,NowVersion) == true)
534 State |= DepNow;
535 if (CheckDep(D,InstallVersion) == true)
536 State |= DepInstall;
537 if (CheckDep(D,CandidateVersion) == true)
538 State |= DepCVer;
539
540 return State;
541}
542 /*}}}*/
543// DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
544// ---------------------------------------------------------------------
545/* This determines the combined dependency representation of a package
546 for its two states now and install. This is done by using the pre-generated
547 dependency information. */
548void pkgDepCache::UpdateVerState(PkgIterator Pkg)
549{
550 // Empty deps are always true
551 StateCache &State = PkgState[Pkg->ID];
552 State.DepState = 0xFF;
553
554 // Check the Current state
555 if (Pkg->CurrentVer != 0)
556 {
557 DepIterator D = Pkg.CurrentVer().DependsList();
558 State.DepState &= VersionState(D,DepNow,DepNowMin,DepNowPolicy);
559 }
560
561 /* Check the candidate state. We do not compare against the whole as
562 a candidate state but check the candidate version against the
563 install states */
564 if (State.CandidateVer != 0)
565 {
566 DepIterator D = State.CandidateVerIter(*this).DependsList();
567 State.DepState &= VersionState(D,DepInstall,DepCandMin,DepCandPolicy);
568 }
569
570 // Check target state which can only be current or installed
571 if (State.InstallVer != 0)
572 {
573 DepIterator D = State.InstVerIter(*this).DependsList();
574 State.DepState &= VersionState(D,DepInstall,DepInstMin,DepInstPolicy);
575 }
576}
577 /*}}}*/
578// DepCache::Update - Figure out all the state information /*{{{*/
579// ---------------------------------------------------------------------
580/* This will figure out the state of all the packages and all the
581 dependencies based on the current policy. */
a246f2dc 582void pkgDepCache::Update(OpProgress *Prog)
6c139d6e
AL
583{
584 iUsrSize = 0;
585 iDownloadSize = 0;
586 iDelCount = 0;
587 iInstCount = 0;
588 iKeepCount = 0;
589 iBrokenCount = 0;
590 iBadCount = 0;
591
592 // Perform the depends pass
a246f2dc
AL
593 int Done = 0;
594 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
6c139d6e 595 {
a246f2dc
AL
596 if (Prog != 0 && Done%20 == 0)
597 Prog->Progress(Done);
6c139d6e
AL
598 for (VerIterator V = I.VersionList(); V.end() != true; V++)
599 {
600 unsigned char Group = 0;
601
602 for (DepIterator D = V.DependsList(); D.end() != true; D++)
603 {
604 // Build the dependency state.
605 unsigned char &State = DepState[D->ID];
b2e465d6 606 State = DependencyState(D);
6c139d6e
AL
607
608 // Add to the group if we are within an or..
609 Group |= State;
610 State |= Group << 3;
611 if ((D->CompareOp & Dep::Or) != Dep::Or)
612 Group = 0;
613
614 // Invert for Conflicts
308c7d30
IJ
615 if (D->Type == Dep::Conflicts ||
616 D->Type == Dep::DpkgBreaks ||
617 D->Type == Dep::Obsoletes)
6c139d6e
AL
618 State = ~State;
619 }
620 }
621
622 // Compute the pacakge dependency state and size additions
623 AddSizes(I);
624 UpdateVerState(I);
625 AddStates(I);
626 }
a246f2dc
AL
627
628 if (Prog != 0)
629 Prog->Progress(Done);
74a05226
MV
630
631 readStateFile(Prog);
6c139d6e
AL
632}
633 /*}}}*/
634// DepCache::Update - Update the deps list of a package /*{{{*/
635// ---------------------------------------------------------------------
636/* This is a helper for update that only does the dep portion of the scan.
74a05226 637 It is mainly meant to scan reverse dependencies. */
6c139d6e
AL
638void pkgDepCache::Update(DepIterator D)
639{
640 // Update the reverse deps
641 for (;D.end() != true; D++)
642 {
643 unsigned char &State = DepState[D->ID];
644 State = DependencyState(D);
645
646 // Invert for Conflicts
308c7d30
IJ
647 if (D->Type == Dep::Conflicts ||
648 D->Type == Dep::DpkgBreaks ||
649 D->Type == Dep::Obsoletes)
6c139d6e 650 State = ~State;
b2e465d6 651
6c139d6e
AL
652 RemoveStates(D.ParentPkg());
653 BuildGroupOrs(D.ParentVer());
654 UpdateVerState(D.ParentPkg());
655 AddStates(D.ParentPkg());
656 }
657}
658 /*}}}*/
659// DepCache::Update - Update the related deps of a package /*{{{*/
660// ---------------------------------------------------------------------
661/* This is called whenever the state of a package changes. It updates
662 all cached dependencies related to this package. */
663void pkgDepCache::Update(PkgIterator const &Pkg)
b2e465d6 664{
6c139d6e
AL
665 // Recompute the dep of the package
666 RemoveStates(Pkg);
667 UpdateVerState(Pkg);
668 AddStates(Pkg);
669
670 // Update the reverse deps
671 Update(Pkg.RevDependsList());
672
673 // Update the provides map for the current ver
674 if (Pkg->CurrentVer != 0)
675 for (PrvIterator P = Pkg.CurrentVer().ProvidesList();
676 P.end() != true; P++)
677 Update(P.ParentPkg().RevDependsList());
678
679 // Update the provides map for the candidate ver
9972233d
AL
680 if (PkgState[Pkg->ID].CandidateVer != 0)
681 for (PrvIterator P = PkgState[Pkg->ID].CandidateVerIter(*this).ProvidesList();
682 P.end() != true; P++)
683 Update(P.ParentPkg().RevDependsList());
6c139d6e
AL
684}
685
686 /*}}}*/
687
688// DepCache::MarkKeep - Put the package in the keep state /*{{{*/
689// ---------------------------------------------------------------------
690/* */
74a05226 691void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
6c139d6e
AL
692{
693 // Simplifies other routines.
694 if (Pkg.end() == true)
695 return;
813c8eea
AL
696
697 /* Reject an attempt to keep a non-source broken installed package, those
698 must be upgraded */
699 if (Pkg.State() == PkgIterator::NeedsUnpack &&
700 Pkg.CurrentVer().Downloadable() == false)
701 return;
6c139d6e 702
74a05226
MV
703 /** \todo Can this be moved later in the method? */
704 ActionGroup group(*this);
705
6c139d6e
AL
706 /* We changed the soft state all the time so the UI is a bit nicer
707 to use */
708 StateCache &P = PkgState[Pkg->ID];
709 if (Soft == true)
710 P.iFlags |= AutoKept;
711 else
712 P.iFlags &= ~AutoKept;
713
714 // Check that it is not already kept
715 if (P.Mode == ModeKeep)
716 return;
717
718 // We dont even try to keep virtual packages..
719 if (Pkg->VersionList == 0)
720 return;
32085498
MV
721
722#if 0 // reseting the autoflag here means we lose the
723 // auto-mark information if a user selects a package for removal
724 // but changes his mind then and sets it for keep again
725 // - this makes sense as default when all Garbage dependencies
726 // are automatically marked for removal (as aptitude does).
727 // setting a package for keep then makes it no longer autoinstalled
728 // for all other use-case this action is rather suprising
74a05226
MV
729 if(FromUser && !P.Marked)
730 P.Flags &= ~Flag::Auto;
32085498
MV
731#endif
732
6c139d6e
AL
733 RemoveSizes(Pkg);
734 RemoveStates(Pkg);
735
736 P.Mode = ModeKeep;
737 if (Pkg->CurrentVer == 0)
738 P.InstallVer = 0;
739 else
740 P.InstallVer = Pkg.CurrentVer();
741
742 AddStates(Pkg);
743
744 Update(Pkg);
745
746 AddSizes(Pkg);
747}
748 /*}}}*/
749// DepCache::MarkDelete - Put the package in the delete state /*{{{*/
750// ---------------------------------------------------------------------
751/* */
d556d1a1 752void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
6c139d6e
AL
753{
754 // Simplifies other routines.
755 if (Pkg.end() == true)
756 return;
757
74a05226
MV
758 ActionGroup group(*this);
759
6c139d6e
AL
760 // Check that it is not already marked for delete
761 StateCache &P = PkgState[Pkg->ID];
d556d1a1
AL
762 P.iFlags &= ~(AutoKept | Purge);
763 if (rPurge == true)
764 P.iFlags |= Purge;
765
766 if ((P.Mode == ModeDelete || P.InstallVer == 0) &&
767 (Pkg.Purge() == true || rPurge == false))
6c139d6e 768 return;
d556d1a1 769
6c139d6e
AL
770 // We dont even try to delete virtual packages..
771 if (Pkg->VersionList == 0)
772 return;
773
774 RemoveSizes(Pkg);
775 RemoveStates(Pkg);
776
d556d1a1 777 if (Pkg->CurrentVer == 0 && (Pkg.Purge() == true || rPurge == false))
3d615484
AL
778 P.Mode = ModeKeep;
779 else
780 P.Mode = ModeDelete;
6c139d6e 781 P.InstallVer = 0;
6c139d6e
AL
782
783 AddStates(Pkg);
784 Update(Pkg);
785 AddSizes(Pkg);
786}
787 /*}}}*/
788// DepCache::MarkInstall - Put the package in the install state /*{{{*/
789// ---------------------------------------------------------------------
790/* */
b2e465d6 791void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
2ae2e04d
MV
792 unsigned long Depth, bool FromUser,
793 bool ForceImportantDeps)
b2e465d6
AL
794{
795 if (Depth > 100)
796 return;
797
6c139d6e
AL
798 // Simplifies other routines.
799 if (Pkg.end() == true)
800 return;
801
74a05226
MV
802 ActionGroup group(*this);
803
6c139d6e
AL
804 /* Check that it is not already marked for install and that it can be
805 installed */
806 StateCache &P = PkgState[Pkg->ID];
807 P.iFlags &= ~AutoKept;
60681f93
MV
808 if ((P.InstPolicyBroken() == false && P.InstBroken() == false) &&
809 (P.Mode == ModeInstall ||
6c139d6e
AL
810 P.CandidateVer == (Version *)Pkg.CurrentVer()))
811 {
812 if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
74a05226 813 MarkKeep(Pkg, false, FromUser);
6c139d6e
AL
814 return;
815 }
b2e465d6
AL
816
817 // See if there is even any possible instalation candidate
818 if (P.CandidateVer == 0)
819 return;
6c139d6e
AL
820 // We dont even try to install virtual packages..
821 if (Pkg->VersionList == 0)
822 return;
6c139d6e
AL
823 /* Target the candidate version and remove the autoflag. We reset the
824 autoflag below if this was called recursively. Otherwise the user
825 should have the ability to de-auto a package by changing its state */
826 RemoveSizes(Pkg);
827 RemoveStates(Pkg);
828
829 P.Mode = ModeInstall;
830 P.InstallVer = P.CandidateVer;
74a05226
MV
831
832 if(FromUser)
833 {
834 // Set it to manual if it's a new install or cancelling the
835 // removal of a garbage package.
836 if(P.Status == 2 || (!Pkg.CurrentVer().end() && !P.Marked))
837 P.Flags &= ~Flag::Auto;
838 }
839 else
840 {
841 // Set it to auto if this is a new install.
842 if(P.Status == 2)
843 P.Flags |= Flag::Auto;
844 }
6c139d6e
AL
845 if (P.CandidateVer == (Version *)Pkg.CurrentVer())
846 P.Mode = ModeKeep;
847
848 AddStates(Pkg);
849 Update(Pkg);
850 AddSizes(Pkg);
851
852 if (AutoInst == false)
853 return;
854
855 DepIterator Dep = P.InstVerIter(*this).DependsList();
856 for (; Dep.end() != true;)
857 {
858 // Grok or groups
859 DepIterator Start = Dep;
860 bool Result = true;
b2e465d6
AL
861 unsigned Ors = 0;
862 for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++,Ors++)
6c139d6e
AL
863 {
864 LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or;
865
866 if ((DepState[Dep->ID] & DepInstall) == DepInstall)
867 Result = false;
868 }
869
870 // Dep is satisfied okay.
871 if (Result == false)
872 continue;
873
874 /* Check if this dep should be consider for install. If it is a user
875 defined important dep and we are installed a new package then
4ef9a929
MV
876 it will be installed. Otherwise we only check for important
877 deps that have changed from the installed version
878 */
6c139d6e
AL
879 if (IsImportantDep(Start) == false)
880 continue;
4ef9a929 881
1b1c2224 882 /* check if any ImportantDep() (but not Critial) where added
4ef9a929 883 * since we installed the package
1b1c2224
MV
884 */
885 bool isNewImportantDep = false;
4ef9a929 886 if(!ForceImportantDeps && !Start.IsCritical())
1b1c2224
MV
887 {
888 bool found=false;
889 VerIterator instVer = Pkg.CurrentVer();
6ea08680 890 if(!instVer.end())
1d722933 891 {
6ea08680
MV
892 for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
893 {
894 //FIXME: deal better with or-groups(?)
895 DepIterator LocalStart = D;
896
897 if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg())
898 found=true;
899 }
1d722933
MV
900 // this is a new dep if it was not found to be already
901 // a important dep of the installed pacakge
902 isNewImportantDep = !found;
903 }
1b1c2224
MV
904 }
905 if(isNewImportantDep)
906 if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
907 std::clog << "new important dependency: "
908 << Start.TargetPkg().Name() << std::endl;
909
4ef9a929
MV
910 // skip important deps if the package is already installed
911 if (Pkg->CurrentVer != 0 && Start.IsCritical() == false
912 && !isNewImportantDep && !ForceImportantDeps)
6c139d6e 913 continue;
b2e465d6
AL
914
915 /* If we are in an or group locate the first or that can
916 succeed. We have already cached this.. */
917 for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; Ors--)
918 Start++;
2ed9b455 919
b2e465d6
AL
920 /* This bit is for processing the possibilty of an install/upgrade
921 fixing the problem */
922 SPtrArray<Version *> List = Start.AllTargets();
308c7d30
IJ
923 if (Start->Type != Dep::DpkgBreaks &&
924 (DepState[Start->ID] & DepCVer) == DepCVer)
6c139d6e 925 {
b2e465d6
AL
926 // Right, find the best version to install..
927 Version **Cur = List;
928 PkgIterator P = Start.TargetPkg();
929 PkgIterator InstPkg(*Cache,0);
6c139d6e 930
b2e465d6
AL
931 // See if there are direct matches (at the start of the list)
932 for (; *Cur != 0 && (*Cur)->ParentPkg == P.Index(); Cur++)
933 {
934 PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
935 if (PkgState[Pkg->ID].CandidateVer != *Cur)
936 continue;
937 InstPkg = Pkg;
938 break;
939 }
940
941 // Select the highest priority providing package
2ed9b455 942 if (InstPkg.end() == true)
b2e465d6
AL
943 {
944 pkgPrioSortList(*Cache,Cur);
945 for (; *Cur != 0; Cur++)
946 {
947 PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
948 if (PkgState[Pkg->ID].CandidateVer != *Cur)
949 continue;
950 InstPkg = Pkg;
951 break;
952 }
953 }
954
a23dcda4 955 if (InstPkg.end() == false)
b2e465d6 956 {
d4c5f11f
MV
957 if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
958 std::clog << "Installing " << InstPkg.Name()
959 << " as dep of " << Pkg.Name()
960 << std::endl;
6c139d6e 961
e6065cfc
MV
962 // now check if we should consider it a automatic dependency or not
963 string sec = _config->Find("APT::Never-MarkAuto-Section","");
964 if(Pkg.Section() && (string(Pkg.Section()) == sec))
965 {
966 if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
967 std::clog << "Setting NOT as auto-installed because its a direct dep of a package in section " << sec << std::endl;
968 MarkInstall(InstPkg,true,Depth + 1, true, ForceImportantDeps);
969 }
970 else
971 {
972 // mark automatic dependency
973 MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps);
974 // Set the autoflag, after MarkInstall because MarkInstall unsets it
975 if (P->CurrentVer == 0)
976 PkgState[InstPkg->ID].Flags |= Flag::Auto;
977 }
b2e465d6 978 }
6c139d6e
AL
979 continue;
980 }
308c7d30 981
b2e465d6 982 /* For conflicts we just de-install the package and mark as auto,
308c7d30
IJ
983 Conflicts may not have or groups. For dpkg's Breaks we try to
984 upgrade the package. */
985 if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes ||
986 Start->Type == Dep::DpkgBreaks)
6c139d6e 987 {
6c139d6e
AL
988 for (Version **I = List; *I != 0; I++)
989 {
990 VerIterator Ver(*this,*I);
991 PkgIterator Pkg = Ver.ParentPkg();
308c7d30
IJ
992
993 if (Start->Type != Dep::DpkgBreaks)
994 MarkDelete(Pkg);
995 else
996 if (PkgState[Pkg->ID].CandidateVer != *I)
997 MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
6c139d6e 998 }
6c139d6e
AL
999 continue;
1000 }
1001 }
1002}
1003 /*}}}*/
d0c59649
AL
1004// DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
1005// ---------------------------------------------------------------------
1006/* */
1007void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
1008{
74a05226
MV
1009 ActionGroup group(*this);
1010
d0c59649
AL
1011 RemoveSizes(Pkg);
1012 RemoveStates(Pkg);
1013
1014 StateCache &P = PkgState[Pkg->ID];
1015 if (To == true)
1016 P.iFlags |= ReInstall;
1017 else
1018 P.iFlags &= ~ReInstall;
1019
1020 AddStates(Pkg);
1021 AddSizes(Pkg);
1022}
1023 /*}}}*/
b2e465d6
AL
1024// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
1025// ---------------------------------------------------------------------
1026/* */
1027void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
1028{
74a05226
MV
1029 ActionGroup group(*this);
1030
b2e465d6
AL
1031 pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
1032 StateCache &P = PkgState[Pkg->ID];
74a05226 1033
b2e465d6
AL
1034 RemoveSizes(Pkg);
1035 RemoveStates(Pkg);
1036
1037 if (P.CandidateVer == P.InstallVer)
1038 P.InstallVer = (Version *)TargetVer;
1039 P.CandidateVer = (Version *)TargetVer;
1040 P.Update(Pkg,*this);
1041
1042 AddStates(Pkg);
1043 Update(Pkg);
1044 AddSizes(Pkg);
1045}
74a05226
MV
1046
1047void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
1048{
1049 StateCache &state = PkgState[Pkg->ID];
1050
1051 ActionGroup group(*this);
1052
1053 if(Auto)
1054 state.Flags |= Flag::Auto;
1055 else
1056 state.Flags &= ~Flag::Auto;
1057}
b2e465d6 1058 /*}}}*/
6c139d6e
AL
1059// StateCache::Update - Compute the various static display things /*{{{*/
1060// ---------------------------------------------------------------------
1061/* This is called whenever the Candidate version changes. */
1062void pkgDepCache::StateCache::Update(PkgIterator Pkg,pkgCache &Cache)
1063{
1064 // Some info
1065 VerIterator Ver = CandidateVerIter(Cache);
1066
1067 // Use a null string or the version string
1068 if (Ver.end() == true)
1069 CandVersion = "";
1070 else
1071 CandVersion = Ver.VerStr();
1072
1073 // Find the current version
1074 CurVersion = "";
1075 if (Pkg->CurrentVer != 0)
1076 CurVersion = Pkg.CurrentVer().VerStr();
1077
1078 // Strip off the epochs for display
1079 CurVersion = StripEpoch(CurVersion);
1080 CandVersion = StripEpoch(CandVersion);
1081
1082 // Figure out if its up or down or equal
1083 Status = Ver.CompareVer(Pkg.CurrentVer());
1084 if (Pkg->CurrentVer == 0 || Pkg->VersionList == 0 || CandidateVer == 0)
1085 Status = 2;
1086}
1087 /*}}}*/
1088// StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
1089// ---------------------------------------------------------------------
1090/* */
1091const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
1092{
1093 if (Ver == 0)
1094 return 0;
1095
1096 // Strip any epoch
1097 for (const char *I = Ver; *I != 0; I++)
1098 if (*I == ':')
1099 return I + 1;
1100 return Ver;
1101}
1102 /*}}}*/
b2e465d6
AL
1103
1104// Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/
6321777b 1105// ---------------------------------------------------------------------
b2e465d6
AL
1106/* The default just returns the highest available version that is not
1107 a source and automatic. */
1108pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
6321777b 1109{
b2e465d6
AL
1110 /* Not source/not automatic versions cannot be a candidate version
1111 unless they are already installed */
1112 VerIterator Last(*(pkgCache *)this,0);
6321777b 1113
b2e465d6
AL
1114 for (VerIterator I = Pkg.VersionList(); I.end() == false; I++)
1115 {
1116 if (Pkg.CurrentVer() == I)
1117 return I;
1118
1119 for (VerFileIterator J = I.FileList(); J.end() == false; J++)
1120 {
1121 if ((J.File()->Flags & Flag::NotSource) != 0)
1122 continue;
1123
1124 /* Stash the highest version of a not-automatic source, we use it
1125 if there is nothing better */
1126 if ((J.File()->Flags & Flag::NotAutomatic) != 0)
1127 {
1128 if (Last.end() == true)
1129 Last = I;
1130 continue;
1131 }
1132
1133 return I;
1134 }
1135 }
6321777b 1136
b2e465d6
AL
1137 return Last;
1138}
1139 /*}}}*/
6321777b 1140 /*}}}*/
74a05226
MV
1141
1142pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
1143 : constructedSuccessfully(false)
1144{
1145 Configuration::Item const *Opts;
1146 Opts = _config->Tree("APT::NeverAutoRemove");
1147 if (Opts != 0 && Opts->Child != 0)
1148 {
1149 Opts = Opts->Child;
1150 for (; Opts != 0; Opts = Opts->Next)
1151 {
1152 if (Opts->Value.empty() == true)
1153 continue;
1154
1155 regex_t *p = new regex_t;
1156 if(regcomp(p,Opts->Value.c_str(),
1157 REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
1158 {
1159 regfree(p);
1160 delete p;
1161 _error->Error("Regex compilation error for APT::NeverAutoRemove");
1162 return;
1163 }
1164
1165 rootSetRegexp.push_back(p);
1166 }
1167 }
1168
1169 constructedSuccessfully = true;
1170}
1171
1172pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
1173{
1174 for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
1175 {
1176 regfree(rootSetRegexp[i]);
1177 delete rootSetRegexp[i];
1178 }
1179}
1180
1181
1182bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg)
1183{
1184 for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
1185 if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
1186 return true;
1187
1188 return false;
1189}
1190
1191pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
1192{
1193 DefaultRootSetFunc *f = new DefaultRootSetFunc;
1194 if(f->wasConstructedSuccessfully())
1195 return f;
1196 else
1197 {
1198 delete f;
1199 return NULL;
1200 }
1201}
1202
1203bool pkgDepCache::MarkFollowsRecommends()
1204{
1205 return _config->FindB("APT::AutoRemove::RecommendsImportant", true);
1206}
1207
1208bool pkgDepCache::MarkFollowsSuggests()
1209{
1210 return _config->FindB("APT::AutoRemove::SuggestsImportant", false);
1211}
1212
1213// the main mark algorithm
1214bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
1215{
1216 bool follow_recommends;
1217 bool follow_suggests;
1218
1219 // init the states
1220 for(PkgIterator p = PkgBegin(); !p.end(); ++p)
1221 {
1222 PkgState[p->ID].Marked = false;
1223 PkgState[p->ID].Garbage = false;
1224
1225 // debug output
1226 if(_config->FindB("Debug::pkgAutoRemove",false)
1227 && PkgState[p->ID].Flags & Flag::Auto)
1228 std::clog << "AutoDep: " << p.Name() << std::endl;
1229 }
1230
1231 // init vars
1232 follow_recommends = MarkFollowsRecommends();
1233 follow_suggests = MarkFollowsSuggests();
1234
1235
1236
1237 // do the mark part, this is the core bit of the algorithm
1238 for(PkgIterator p = PkgBegin(); !p.end(); ++p)
1239 {
1240 if(!(PkgState[p->ID].Flags & Flag::Auto) ||
1241 (p->Flags & Flag::Essential) ||
1242 userFunc.InRootSet(p))
1243
1244 {
1245 // the package is installed (and set to keep)
1246 if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
1247 MarkPackage(p, p.CurrentVer(),
1248 follow_recommends, follow_suggests);
1249 // the package is to be installed
1250 else if(PkgState[p->ID].Install())
1251 MarkPackage(p, PkgState[p->ID].InstVerIter(*this),
1252 follow_recommends, follow_suggests);
1253 }
1254 }
1255
1256 return true;
1257}
1258
1259// mark a single package in Mark-and-Sweep
1260void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
1261 const pkgCache::VerIterator &ver,
1262 bool follow_recommends,
1263 bool follow_suggests)
1264{
1265 pkgDepCache::StateCache &state = PkgState[pkg->ID];
1266 VerIterator candver = state.CandidateVerIter(*this);
1267 VerIterator instver = state.InstVerIter(*this);
1268
1269#if 0
1270 // If a package was garbage-collected but is now being marked, we
1271 // should re-select it
1272 // For cases when a pkg is set to upgrade and this trigger the
1273 // removal of a no-longer used dependency. if the pkg is set to
1274 // keep again later it will result in broken deps
1275 if(state.Delete() && state.RemoveReason = Unused)
1276 {
1277 if(ver==candver)
1278 mark_install(pkg, false, false, NULL);
1279 else if(ver==pkg.CurrentVer())
1280 MarkKeep(pkg, false, false);
1281
1282 instver=state.InstVerIter(*this);
1283 }
1284#endif
1285
1286 // Ignore versions other than the InstVer, and ignore packages
1287 // that are already going to be removed or just left uninstalled.
1288 if(!(ver == instver && !instver.end()))
1289 return;
1290
1291 // if we are marked already we are done
1292 if(state.Marked)
1293 return;
1294
1295 //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
1296 state.Marked=true;
1297
1298 if(!ver.end())
1299 {
1300 for(DepIterator d = ver.DependsList(); !d.end(); ++d)
1301 {
1302 if(d->Type == Dep::Depends ||
1303 d->Type == Dep::PreDepends ||
1304 (follow_recommends &&
1305 d->Type == Dep::Recommends) ||
1306 (follow_suggests &&
1307 d->Type == Dep::Suggests))
1308 {
1309 // Try all versions of this package.
1310 for(VerIterator V = d.TargetPkg().VersionList();
1311 !V.end(); ++V)
1312 {
1313 if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
1314 {
1315 MarkPackage(V.ParentPkg(), V,
1316 follow_recommends, follow_suggests);
1317 }
1318 }
1319 // Now try virtual packages
1320 for(PrvIterator prv=d.TargetPkg().ProvidesList();
1321 !prv.end(); ++prv)
1322 {
1323 if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp,
1324 d.TargetVer()))
1325 {
1326 MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
1327 follow_recommends, follow_suggests);
1328 }
1329 }
1330 }
1331 }
1332 }
1333}
1334
1335bool pkgDepCache::Sweep()
1336{
1337 // do the sweep
1338 for(PkgIterator p=PkgBegin(); !p.end(); ++p)
1339 {
1340 StateCache &state=PkgState[p->ID];
1341
c9b320e8
MV
1342 // skip required packages
1343 if (!p.CurrentVer().end() &&
1344 (p.CurrentVer()->Priority == pkgCache::State::Required))
1345 continue;
1346
74a05226 1347 // if it is not marked and it is installed, it's garbage
32085498 1348 if(!state.Marked && (!p.CurrentVer().end() || state.Install()))
74a05226
MV
1349 {
1350 state.Garbage=true;
1351 if(_config->FindB("Debug::pkgAutoRemove",false))
1352 std::cout << "Garbage: " << p.Name() << std::endl;
1353 }
1354 }
1355
1356 return true;
1357}
be615841 1358
b2e465d6
AL
1359// Policy::IsImportantDep - True if the dependency is important /*{{{*/
1360// ---------------------------------------------------------------------
1361/* */
1362bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
1363{
60681f93
MV
1364 if(Dep.IsCritical())
1365 return true;
1d722933
MV
1366 else if(Dep->Type == pkgCache::Dep::Recommends)
1367 {
1368 if ( _config->FindB("APT::Install-Recommends", false))
1369 return true;
1370 // we suport a special mode to only install-recommends for certain
1371 // sections
1372 // FIXME: this is a meant as a temporarly solution until the
1373 // recommends are cleaned up
1374 string s = _config->Find("APT::Install-Recommends-Section","");
1375 if(s.size() > 0)
1376 {
98a27a21 1377 const char *sec = Dep.ParentVer().Section();
1d722933
MV
1378 if (sec && strcmp(sec, s.c_str()) == 0)
1379 return true;
1380 }
1381 }
60681f93
MV
1382 else if(Dep->Type == pkgCache::Dep::Suggests)
1383 return _config->FindB("APT::Install-Suggests", false);
1384
1385 return false;
6321777b
AL
1386}
1387 /*}}}*/