do not write state file in simulate mode (closes: #433007)
[ntk/apt.git] / apt-pkg / depcache.cc
CommitLineData
6c139d6e
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
e7b470ee 3// $Id: depcache.cc,v 1.25 2001/05/27 05:36:04 jgg Exp $
6c139d6e
AL
4/* ######################################################################
5
6 Dependency Cache - Caches Dependency information.
7
8 ##################################################################### */
9 /*}}}*/
10// Include Files /*{{{*/
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
8a3a2e99
MV
26#include <sys/stat.h>
27
b2e465d6 28#include <apti18n.h>
74a05226 29
cb1933df
MV
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
af29ffb4
MV
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}
cb1933df 57
74a05226
MV
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}
6c139d6e
AL
86
87// DepCache::pkgDepCache - Constructors /*{{{*/
88// ---------------------------------------------------------------------
89/* */
b2e465d6 90pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
74a05226 91 group_level(0), Cache(pCache), PkgState(0), DepState(0)
6c139d6e 92{
af29ffb4
MV
93 DebugMarker = _config->FindB("Debug::pkgDepCache::Marker", false);
94 DebugAutoInstall = _config->FindB("Debug::pkgDepCache::AutoInstall", false);
b2e465d6
AL
95 delLocalPolicy = 0;
96 LocalPolicy = Plcy;
97 if (LocalPolicy == 0)
98 delLocalPolicy = LocalPolicy = new Policy;
6c139d6e
AL
99}
100 /*}}}*/
101// DepCache::~pkgDepCache - Destructor /*{{{*/
102// ---------------------------------------------------------------------
103/* */
104pkgDepCache::~pkgDepCache()
105{
106 delete [] PkgState;
107 delete [] DepState;
b2e465d6 108 delete delLocalPolicy;
6c139d6e
AL
109}
110 /*}}}*/
6c139d6e
AL
111// DepCache::Init - Generate the initial extra structures. /*{{{*/
112// ---------------------------------------------------------------------
113/* This allocats the extension buffers and initializes them. */
a246f2dc 114bool pkgDepCache::Init(OpProgress *Prog)
6c139d6e 115{
74a05226
MV
116 // Suppress mark updates during this operation (just in case) and
117 // run a mark operation when Init terminates.
118 ActionGroup actions(*this);
119
6c139d6e
AL
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);
b2e465d6 126
a246f2dc
AL
127 if (Prog != 0)
128 {
129 Prog->OverallProgress(0,2*Head().PackageCount,Head().PackageCount,
db0db9fe
CP
130 _("Building dependency tree"));
131 Prog->SubProgress(Head().PackageCount,_("Candidate versions"));
a246f2dc
AL
132 }
133
6c139d6e
AL
134 /* Set the current state of everything. In this state all of the
135 packages are kept exactly as is. See AllUpgrade */
a246f2dc
AL
136 int Done = 0;
137 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
6c139d6e 138 {
a246f2dc
AL
139 if (Prog != 0)
140 Prog->Progress(Done);
141
6c139d6e
AL
142 // Find the proper cache slot
143 StateCache &State = PkgState[I->ID];
144 State.iFlags = 0;
afb1e2e3 145
6c139d6e
AL
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
a246f2dc
AL
154 if (Prog != 0)
155 {
156
157 Prog->OverallProgress(Head().PackageCount,2*Head().PackageCount,
158 Head().PackageCount,
db0db9fe
CP
159 _("Building dependency tree"));
160 Prog->SubProgress(Head().PackageCount,_("Dependency generation"));
a246f2dc
AL
161 }
162
163 Update(Prog);
e004867d
MV
164
165 if(Prog != 0)
166 Prog->Done();
74a05226 167
6c139d6e
AL
168 return true;
169}
170 /*}}}*/
6c139d6e 171
a83d884d
MV
172bool pkgDepCache::readStateFile(OpProgress *Prog)
173{
174 FileFd state_file;
aac2e510 175 string state = _config->FindDir("Dir::State") + "extended_states";
a83d884d
MV
176 if(FileExists(state)) {
177 state_file.Open(state, FileFd::ReadOnly);
178 int file_size = state_file.Size();
bc80031f
MV
179 if(Prog != NULL)
180 Prog->OverallProgress(0, file_size, 1,
181 _("Reading state information"));
a83d884d
MV
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()) {
fc5aece9 192 short reason = section.FindI("Auto-Installed", 0);
e23e6733 193 if(reason > 0)
f8ac1720 194 PkgState[pkg->ID].Flags |= Flag::Auto;
0a57c0f0 195 if(_config->FindB("Debug::pkgAutoRemove",false))
fc5aece9 196 std::cout << "Auto-Installed : " << pkgname << std::endl;
a83d884d 197 amt+=section.size();
bc80031f
MV
198 if(Prog != NULL)
199 Prog->OverallProgress(amt, file_size, 1,
200 _("Reading state information"));
a83d884d 201 }
bc80031f
MV
202 if(Prog != NULL)
203 Prog->OverallProgress(file_size, file_size, 1,
204 _("Reading state information"));
a83d884d
MV
205 }
206 }
207
208 return true;
209}
210
686d0fad 211bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
a83d884d 212{
e23e6733
MV
213 if(_config->FindB("Debug::pkgAutoRemove",false))
214 std::clog << "pkgDepCache::writeStateFile()" << std::endl;
215
b1a8717a
MV
216 FileFd StateFile;
217 string state = _config->FindDir("Dir::State") + "extended_states";
9a9665f9
MV
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
b1a8717a
MV
227 if(!StateFile.Open(state, FileFd::ReadOnly))
228 return _error->Error(_("Failed to open StateFile %s"),
a83d884d
MV
229 state.c_str());
230
b1a8717a
MV
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());
80fa0d8a 236
b1a8717a
MV
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;
b1a8717a
MV
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++) {
f8ac1720 266 if(PkgState[pkg->ID].Flags & Flag::Auto) {
b1a8717a
MV
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 }
468126e3
MV
272 // skip not installed ones if requested
273 if(InstalledOnly && pkg->CurrentVer == 0)
274 continue;
e23e6733 275 if(_config->FindB("Debug::pkgAutoRemove",false))
b1a8717a
MV
276 std::clog << "Writing new AutoInstall: "
277 << pkg.Name() << std::endl;
a83d884d 278 ostr.str(string(""));
0a57c0f0 279 ostr << "Package: " << pkg.Name()
fc5aece9 280 << "\nAuto-Installed: 1\n\n";
3c8cda8b 281 fprintf(OutFile,"%s",ostr.str().c_str());
b1a8717a 282 fprintf(OutFile,"\n");
a83d884d
MV
283 }
284 }
a4decc40 285 fclose(OutFile);
b1a8717a 286
8a3a2e99 287 // move the outfile over the real file and set permissions
b1a8717a 288 rename(outfile.c_str(), state.c_str());
8a3a2e99 289 chmod(state.c_str(), 0644);
b1a8717a 290
a83d884d
MV
291 return true;
292}
293
6c139d6e
AL
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 */
b2e465d6 307 if (Dep.TargetPkg() != Dep.ParentPkg() ||
308c7d30 308 (Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
6c139d6e
AL
309 {
310 PkgIterator Pkg = Dep.TargetPkg();
311 // Check the base package
312 if (Type == NowVersion && Pkg->CurrentVer != 0)
b2e465d6
AL
313 if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep->CompareOp,
314 Dep.TargetVer()) == true)
6c139d6e
AL
315 return true;
316
317 if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
b2e465d6
AL
318 if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
319 Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
320 return true;
321
322 if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
b2e465d6
AL
323 if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
324 Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
325 return true;
326 }
327
b2e465d6
AL
328 if (Dep->Type == Dep::Obsoletes)
329 return false;
330
6c139d6e
AL
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. */
308c7d30
IJ
338 if (P.OwnerPkg() == Pkg &&
339 (Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks))
6c139d6e
AL
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.
b2e465d6 364 if (VS().CheckDep(P.ProvideVersion(),Dep->CompareOp,Dep.TargetVer()) == true)
6c139d6e
AL
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 */
b2e465d6 377void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
6c139d6e
AL
378{
379 StateCache &P = PkgState[Pkg->ID];
380
e7b470ee
AL
381 if (Pkg->VersionList == 0)
382 return;
383
e5a1f2ff
AL
384 if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
385 P.Keep() == true)
2cca3bd9 386 return;
2cca3bd9 387
6c139d6e
AL
388 // Compute the size data
389 if (P.NewInstall() == true)
390 {
b2e465d6
AL
391 iUsrSize += (signed)(Mult*P.InstVerIter(*this)->InstalledSize);
392 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d 393 return;
6c139d6e
AL
394 }
395
396 // Upgrading
d0c59649
AL
397 if (Pkg->CurrentVer != 0 &&
398 (P.InstallVer != (Version *)Pkg.CurrentVer() ||
399 (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
6c139d6e 400 {
b2e465d6
AL
401 iUsrSize += (signed)(Mult*((signed)P.InstVerIter(*this)->InstalledSize -
402 (signed)Pkg.CurrentVer()->InstalledSize));
403 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d
AL
404 return;
405 }
406
407 // Reinstall
2cca3bd9
AL
408 if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
409 P.Delete() == false)
d38b7b3d 410 {
b2e465d6 411 iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
d38b7b3d 412 return;
6c139d6e
AL
413 }
414
415 // Removing
416 if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
d38b7b3d 417 {
b2e465d6 418 iUsrSize -= (signed)(Mult*Pkg.CurrentVer()->InstalledSize);
d38b7b3d
AL
419 return;
420 }
6c139d6e
AL
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
4ef9a929 435 // The Package is broken (either minimal dep or policy dep)
6c139d6e
AL
436 if ((State.DepState & DepInstMin) != DepInstMin)
437 iBrokenCount += Add;
4ef9a929
MV
438 if ((State.DepState & DepInstPolicy) != DepInstPolicy)
439 iPolicyBrokenCount += Add;
6c139d6e
AL
440
441 // Bad state
442 if (Pkg.State() != PkgIterator::NeedsNothing)
443 iBadCount += Add;
444
445 // Not installed
446 if (Pkg->CurrentVer == 0)
447 {
d556d1a1
AL
448 if (State.Mode == ModeDelete &&
449 (State.iFlags | Purge) == Purge && Pkg.Purge() == false)
450 iDelCount += Add;
451
6c139d6e
AL
452 if (State.Mode == ModeInstall)
453 iInstCount += Add;
454 return;
455 }
456
457 // Installed, no upgrade
6321777b 458 if (State.Status == 0)
d0c59649 459 {
6c139d6e
AL
460 if (State.Mode == ModeDelete)
461 iDelCount += Add;
d0c59649
AL
462 else
463 if ((State.iFlags & ReInstall) == ReInstall)
464 iInstCount += Add;
465
6c139d6e
AL
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 */
308c7d30
IJ
493 if (D->Type == Dep::Conflicts ||
494 D->Type == Dep::DpkgBreaks ||
495 D->Type == Dep::Obsoletes)
6c139d6e
AL
496 State = ~State;
497
498 // Add to the group if we are within an or..
d2685fd6 499 State &= 0x7;
6c139d6e
AL
500 Group |= State;
501 State |= Group << 3;
502 if ((D->CompareOp & Dep::Or) != Dep::Or)
503 Group = 0;
504
505 // Invert for Conflicts
308c7d30
IJ
506 if (D->Type == Dep::Conflicts ||
507 D->Type == Dep::DpkgBreaks ||
508 D->Type == Dep::Obsoletes)
6c139d6e
AL
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. */
a246f2dc 608void pkgDepCache::Update(OpProgress *Prog)
6c139d6e
AL
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
a246f2dc
AL
619 int Done = 0;
620 for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
6c139d6e 621 {
a246f2dc
AL
622 if (Prog != 0 && Done%20 == 0)
623 Prog->Progress(Done);
6c139d6e
AL
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];
b2e465d6 632 State = DependencyState(D);
6c139d6e
AL
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
308c7d30
IJ
641 if (D->Type == Dep::Conflicts ||
642 D->Type == Dep::DpkgBreaks ||
643 D->Type == Dep::Obsoletes)
6c139d6e
AL
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 }
a246f2dc
AL
653
654 if (Prog != 0)
655 Prog->Progress(Done);
74a05226
MV
656
657 readStateFile(Prog);
6c139d6e
AL
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.
74a05226 663 It is mainly meant to scan reverse dependencies. */
6c139d6e
AL
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
308c7d30
IJ
673 if (D->Type == Dep::Conflicts ||
674 D->Type == Dep::DpkgBreaks ||
675 D->Type == Dep::Obsoletes)
6c139d6e 676 State = ~State;
b2e465d6 677
6c139d6e
AL
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)
b2e465d6 690{
6c139d6e
AL
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
9972233d
AL
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());
6c139d6e
AL
710}
711
712 /*}}}*/
713
714// DepCache::MarkKeep - Put the package in the keep state /*{{{*/
715// ---------------------------------------------------------------------
716/* */
af29ffb4
MV
717void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser,
718 unsigned long Depth)
6c139d6e
AL
719{
720 // Simplifies other routines.
721 if (Pkg.end() == true)
722 return;
813c8eea
AL
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;
6c139d6e 729
74a05226
MV
730 /** \todo Can this be moved later in the method? */
731 ActionGroup group(*this);
732
6c139d6e
AL
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;
32085498
MV
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
74a05226
MV
755 if(FromUser && !P.Marked)
756 P.Flags &= ~Flag::Auto;
32085498
MV
757#endif
758
af29ffb4
MV
759 if (DebugMarker == true)
760 std::clog << OutputInDepth(Depth) << "MarkKeep " << Pkg << std::endl;
761
6c139d6e
AL
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/* */
af29ffb4
MV
781void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge,
782 unsigned long Depth)
6c139d6e
AL
783{
784 // Simplifies other routines.
785 if (Pkg.end() == true)
786 return;
787
74a05226
MV
788 ActionGroup group(*this);
789
6c139d6e
AL
790 // Check that it is not already marked for delete
791 StateCache &P = PkgState[Pkg->ID];
d556d1a1
AL
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))
6c139d6e 798 return;
d556d1a1 799
6c139d6e
AL
800 // We dont even try to delete virtual packages..
801 if (Pkg->VersionList == 0)
802 return;
803
af29ffb4
MV
804 if (DebugMarker == true)
805 std::clog << OutputInDepth(Depth) << "MarkDelete " << Pkg << std::endl;
806
6c139d6e
AL
807 RemoveSizes(Pkg);
808 RemoveStates(Pkg);
809
d556d1a1 810 if (Pkg->CurrentVer == 0 && (Pkg.Purge() == true || rPurge == false))
3d615484
AL
811 P.Mode = ModeKeep;
812 else
813 P.Mode = ModeDelete;
6c139d6e 814 P.InstallVer = 0;
6c139d6e
AL
815
816 AddStates(Pkg);
817 Update(Pkg);
818 AddSizes(Pkg);
819}
820 /*}}}*/
821// DepCache::MarkInstall - Put the package in the install state /*{{{*/
822// ---------------------------------------------------------------------
823/* */
b2e465d6 824void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
7610bb3d
MV
825 unsigned long Depth, bool FromUser,
826 bool ForceImportantDeps)
b2e465d6
AL
827{
828 if (Depth > 100)
829 return;
830
6c139d6e
AL
831 // Simplifies other routines.
832 if (Pkg.end() == true)
833 return;
834
74a05226
MV
835 ActionGroup group(*this);
836
6c139d6e
AL
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;
60681f93
MV
841 if ((P.InstPolicyBroken() == false && P.InstBroken() == false) &&
842 (P.Mode == ModeInstall ||
6c139d6e
AL
843 P.CandidateVer == (Version *)Pkg.CurrentVer()))
844 {
845 if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
af29ffb4 846 MarkKeep(Pkg, false, FromUser, Depth+1);
6c139d6e
AL
847 return;
848 }
b2e465d6
AL
849
850 // See if there is even any possible instalation candidate
851 if (P.CandidateVer == 0)
852 return;
6c139d6e
AL
853 // We dont even try to install virtual packages..
854 if (Pkg->VersionList == 0)
855 return;
6c139d6e
AL
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;
74a05226
MV
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 }
6c139d6e
AL
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
af29ffb4
MV
888 if (DebugMarker == true)
889 std::clog << OutputInDepth(Depth) << "MarkInstall " << Pkg << std::endl;
890
6c139d6e
AL
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;
b2e465d6
AL
897 unsigned Ors = 0;
898 for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++,Ors++)
6c139d6e
AL
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
4ef9a929
MV
912 it will be installed. Otherwise we only check for important
913 deps that have changed from the installed version
914 */
6c139d6e
AL
915 if (IsImportantDep(Start) == false)
916 continue;
4ef9a929 917
0526822a
DB
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)
1b1c2224
MV
924 */
925 bool isNewImportantDep = false;
0526822a 926 bool isPreviouslySatisfiedImportantDep = false;
4ef9a929 927 if(!ForceImportantDeps && !Start.IsCritical())
1b1c2224
MV
928 {
929 bool found=false;
930 VerIterator instVer = Pkg.CurrentVer();
6ea08680 931 if(!instVer.end())
1d722933 932 {
0526822a
DB
933 for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
934 {
6ea08680
MV
935 //FIXME: deal better with or-groups(?)
936 DepIterator LocalStart = D;
4faff53f
MV
937
938 if(IsImportantDep(D) && !D.IsCritical() &&
939 Start.TargetPkg() == D.TargetPkg())
0526822a
DB
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 }
1d722933
MV
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 }
1b1c2224
MV
958 }
959 if(isNewImportantDep)
af29ffb4
MV
960 if(DebugAutoInstall == true)
961 std::clog << OutputInDepth(Depth) << "new important dependency: "
1b1c2224 962 << Start.TargetPkg().Name() << std::endl;
0526822a 963 if(isPreviouslySatisfiedImportantDep)
af29ffb4
MV
964 if(DebugAutoInstall == true)
965 std::clog << OutputInDepth(Depth) << "previously satisfied important dependency on "
0526822a 966 << Start.TargetPkg().Name() << std::endl;
1b1c2224 967
4ef9a929
MV
968 // skip important deps if the package is already installed
969 if (Pkg->CurrentVer != 0 && Start.IsCritical() == false
0526822a
DB
970 && !isNewImportantDep && !isPreviouslySatisfiedImportantDep
971 && !ForceImportantDeps)
6c139d6e 972 continue;
b2e465d6
AL
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++;
2ed9b455 978
b2e465d6
AL
979 /* This bit is for processing the possibilty of an install/upgrade
980 fixing the problem */
981 SPtrArray<Version *> List = Start.AllTargets();
308c7d30
IJ
982 if (Start->Type != Dep::DpkgBreaks &&
983 (DepState[Start->ID] & DepCVer) == DepCVer)
6c139d6e 984 {
b2e465d6
AL
985 // Right, find the best version to install..
986 Version **Cur = List;
987 PkgIterator P = Start.TargetPkg();
988 PkgIterator InstPkg(*Cache,0);
6c139d6e 989
b2e465d6
AL
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
2ed9b455 1001 if (InstPkg.end() == true)
b2e465d6
AL
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
a23dcda4 1014 if (InstPkg.end() == false)
b2e465d6 1015 {
af29ffb4
MV
1016 if(DebugAutoInstall == true)
1017 std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name()
1018 << " as " << Start.DepType() << " of " << Pkg.Name()
d4c5f11f 1019 << std::endl;
92b9551f 1020 // now check if we should consider it a automatic dependency or not
cb1933df 1021 if(Pkg.Section() && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
92b9551f 1022 {
af29ffb4
MV
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;
92b9551f
MV
1026 MarkInstall(InstPkg,true,Depth + 1, true);
1027 }
1028 else
1029 {
1030 // mark automatic dependency
b51ff02a 1031 MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps);
92b9551f
MV
1032 // Set the autoflag, after MarkInstall because MarkInstall unsets it
1033 if (P->CurrentVer == 0)
1034 PkgState[InstPkg->ID].Flags |= Flag::Auto;
1035 }
b2e465d6 1036 }
6c139d6e
AL
1037 continue;
1038 }
308c7d30 1039
b2e465d6 1040 /* For conflicts we just de-install the package and mark as auto,
308c7d30
IJ
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)
6c139d6e 1045 {
6c139d6e
AL
1046 for (Version **I = List; *I != 0; I++)
1047 {
1048 VerIterator Ver(*this,*I);
1049 PkgIterator Pkg = Ver.ParentPkg();
308c7d30
IJ
1050
1051 if (Start->Type != Dep::DpkgBreaks)
af29ffb4 1052 MarkDelete(Pkg,false,Depth + 1);
308c7d30
IJ
1053 else
1054 if (PkgState[Pkg->ID].CandidateVer != *I)
1055 MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
6c139d6e 1056 }
6c139d6e
AL
1057 continue;
1058 }
1059 }
1060}
1061 /*}}}*/
d0c59649
AL
1062// DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
1063// ---------------------------------------------------------------------
1064/* */
1065void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
1066{
74a05226
MV
1067 ActionGroup group(*this);
1068
d0c59649
AL
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 /*}}}*/
b2e465d6
AL
1082// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
1083// ---------------------------------------------------------------------
1084/* */
1085void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
1086{
74a05226
MV
1087 ActionGroup group(*this);
1088
b2e465d6
AL
1089 pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
1090 StateCache &P = PkgState[Pkg->ID];
74a05226 1091
b2e465d6
AL
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}
74a05226
MV
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}
b2e465d6 1116 /*}}}*/
6c139d6e
AL
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 /*}}}*/
b2e465d6
AL
1161
1162// Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/
6321777b 1163// ---------------------------------------------------------------------
b2e465d6
AL
1164/* The default just returns the highest available version that is not
1165 a source and automatic. */
1166pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
6321777b 1167{
b2e465d6
AL
1168 /* Not source/not automatic versions cannot be a candidate version
1169 unless they are already installed */
1170 VerIterator Last(*(pkgCache *)this,0);
6321777b 1171
b2e465d6
AL
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 }
6321777b 1194
b2e465d6
AL
1195 return Last;
1196}
1197 /*}}}*/
cb1933df 1198
b2e465d6
AL
1199// Policy::IsImportantDep - True if the dependency is important /*{{{*/
1200// ---------------------------------------------------------------------
1201/* */
1202bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
1203{
60681f93
MV
1204 if(Dep.IsCritical())
1205 return true;
1d722933
MV
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
cb1933df
MV
1214 const char *sec = Dep.ParentVer().Section();
1215 if (sec && ConfigValueInSubTree("APT::Install-Recommends-Sections", sec))
1216 return true;
1d722933 1217 }
60681f93
MV
1218 else if(Dep->Type == pkgCache::Dep::Suggests)
1219 return _config->FindB("APT::Install-Suggests", false);
1220
1221 return false;
6321777b
AL
1222}
1223 /*}}}*/
74a05226
MV
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())
83860e37 1330 MarkPackage(p, p.CurrentVer(),
74a05226
MV
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];
36baa77a 1349 VerIterator currver = pkg.CurrentVer();
74a05226
MV
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
36baa77a
MV
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()))
74a05226
MV
1375 return;
1376
1377 // if we are marked already we are done
1378 if(state.Marked)
1379 return;
1380
83860e37
DB
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
74a05226
MV
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 {
83860e37
DB
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 }
74a05226
MV
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 {
83860e37
DB
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
74a05226
MV
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
c9b320e8
MV
1469 // skip required packages
1470 if (!p.CurrentVer().end() &&
1471 (p.CurrentVer()->Priority == pkgCache::State::Required))
1472 continue;
1473
74a05226 1474 // if it is not marked and it is installed, it's garbage
32085498 1475 if(!state.Marked && (!p.CurrentVer().end() || state.Install()))
74a05226
MV
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}