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