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