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