add hook for auto-install (closes: #470035)
[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;
2d403b92
MV
856
857 /* if the user doesn't request directly the install we have to check
858 if this install will conflict with any rule a application
859 like apt-get or aptitude might has set (for the user)
860 e.g. forbidden versions, holds or other magic stuff */
861 if(FromUser == false && !IsAutoInstallOk(Pkg, Depth))
862 {
863 MarkKeep(Pkg, false, FromUser, Depth);
864 return;
865 }
866
6c139d6e
AL
867 /* Target the candidate version and remove the autoflag. We reset the
868 autoflag below if this was called recursively. Otherwise the user
869 should have the ability to de-auto a package by changing its state */
870 RemoveSizes(Pkg);
871 RemoveStates(Pkg);
872
873 P.Mode = ModeInstall;
874 P.InstallVer = P.CandidateVer;
74a05226
MV
875
876 if(FromUser)
877 {
878 // Set it to manual if it's a new install or cancelling the
879 // removal of a garbage package.
880 if(P.Status == 2 || (!Pkg.CurrentVer().end() && !P.Marked))
881 P.Flags &= ~Flag::Auto;
882 }
883 else
884 {
885 // Set it to auto if this is a new install.
886 if(P.Status == 2)
887 P.Flags |= Flag::Auto;
888 }
6c139d6e
AL
889 if (P.CandidateVer == (Version *)Pkg.CurrentVer())
890 P.Mode = ModeKeep;
891
892 AddStates(Pkg);
893 Update(Pkg);
894 AddSizes(Pkg);
895
896 if (AutoInst == false)
897 return;
898
af29ffb4
MV
899 if (DebugMarker == true)
900 std::clog << OutputInDepth(Depth) << "MarkInstall " << Pkg << std::endl;
901
6c139d6e
AL
902 DepIterator Dep = P.InstVerIter(*this).DependsList();
903 for (; Dep.end() != true;)
904 {
905 // Grok or groups
906 DepIterator Start = Dep;
907 bool Result = true;
b2e465d6
AL
908 unsigned Ors = 0;
909 for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++,Ors++)
6c139d6e
AL
910 {
911 LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or;
912
913 if ((DepState[Dep->ID] & DepInstall) == DepInstall)
914 Result = false;
915 }
916
917 // Dep is satisfied okay.
918 if (Result == false)
919 continue;
920
921 /* Check if this dep should be consider for install. If it is a user
922 defined important dep and we are installed a new package then
4ef9a929
MV
923 it will be installed. Otherwise we only check for important
924 deps that have changed from the installed version
925 */
6c139d6e
AL
926 if (IsImportantDep(Start) == false)
927 continue;
4ef9a929 928
0526822a
DB
929 /* Check if any ImportantDep() (but not Critical) were added
930 * since we installed the package. Also check for deps that
931 * were satisfied in the past: for instance, if a version
932 * restriction in a Recommends was tightened, upgrading the
933 * package should follow that Recommends rather than causing the
934 * dependency to be removed. (bug #470115)
1b1c2224
MV
935 */
936 bool isNewImportantDep = false;
0526822a 937 bool isPreviouslySatisfiedImportantDep = false;
4ef9a929 938 if(!ForceImportantDeps && !Start.IsCritical())
1b1c2224
MV
939 {
940 bool found=false;
941 VerIterator instVer = Pkg.CurrentVer();
6ea08680 942 if(!instVer.end())
1d722933 943 {
0526822a
DB
944 for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
945 {
6ea08680
MV
946 //FIXME: deal better with or-groups(?)
947 DepIterator LocalStart = D;
4faff53f
MV
948
949 if(IsImportantDep(D) && !D.IsCritical() &&
950 Start.TargetPkg() == D.TargetPkg())
0526822a
DB
951 {
952 if(!isPreviouslySatisfiedImportantDep)
953 {
954 DepIterator D2 = D;
955 while((D2->CompareOp & Dep::Or) != 0)
956 ++D2;
957
958 isPreviouslySatisfiedImportantDep =
959 (((*this)[D2] & DepGNow) != 0);
960 }
961
962 found=true;
963 }
964 }
1d722933
MV
965 // this is a new dep if it was not found to be already
966 // a important dep of the installed pacakge
967 isNewImportantDep = !found;
968 }
1b1c2224
MV
969 }
970 if(isNewImportantDep)
af29ffb4
MV
971 if(DebugAutoInstall == true)
972 std::clog << OutputInDepth(Depth) << "new important dependency: "
1b1c2224 973 << Start.TargetPkg().Name() << std::endl;
0526822a 974 if(isPreviouslySatisfiedImportantDep)
af29ffb4
MV
975 if(DebugAutoInstall == true)
976 std::clog << OutputInDepth(Depth) << "previously satisfied important dependency on "
0526822a 977 << Start.TargetPkg().Name() << std::endl;
1b1c2224 978
4ef9a929
MV
979 // skip important deps if the package is already installed
980 if (Pkg->CurrentVer != 0 && Start.IsCritical() == false
0526822a
DB
981 && !isNewImportantDep && !isPreviouslySatisfiedImportantDep
982 && !ForceImportantDeps)
6c139d6e 983 continue;
b2e465d6
AL
984
985 /* If we are in an or group locate the first or that can
986 succeed. We have already cached this.. */
987 for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; Ors--)
988 Start++;
2ed9b455 989
b2e465d6
AL
990 /* This bit is for processing the possibilty of an install/upgrade
991 fixing the problem */
992 SPtrArray<Version *> List = Start.AllTargets();
308c7d30
IJ
993 if (Start->Type != Dep::DpkgBreaks &&
994 (DepState[Start->ID] & DepCVer) == DepCVer)
6c139d6e 995 {
b2e465d6
AL
996 // Right, find the best version to install..
997 Version **Cur = List;
998 PkgIterator P = Start.TargetPkg();
999 PkgIterator InstPkg(*Cache,0);
6c139d6e 1000
b2e465d6
AL
1001 // See if there are direct matches (at the start of the list)
1002 for (; *Cur != 0 && (*Cur)->ParentPkg == P.Index(); Cur++)
1003 {
1004 PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
1005 if (PkgState[Pkg->ID].CandidateVer != *Cur)
1006 continue;
1007 InstPkg = Pkg;
1008 break;
1009 }
1010
1011 // Select the highest priority providing package
2ed9b455 1012 if (InstPkg.end() == true)
b2e465d6
AL
1013 {
1014 pkgPrioSortList(*Cache,Cur);
1015 for (; *Cur != 0; Cur++)
1016 {
1017 PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
1018 if (PkgState[Pkg->ID].CandidateVer != *Cur)
1019 continue;
1020 InstPkg = Pkg;
1021 break;
1022 }
1023 }
1024
a23dcda4 1025 if (InstPkg.end() == false)
b2e465d6 1026 {
af29ffb4
MV
1027 if(DebugAutoInstall == true)
1028 std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name()
1029 << " as " << Start.DepType() << " of " << Pkg.Name()
d4c5f11f 1030 << std::endl;
92b9551f 1031 // now check if we should consider it a automatic dependency or not
cb1933df 1032 if(Pkg.Section() && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
92b9551f 1033 {
af29ffb4
MV
1034 if(DebugAutoInstall == true)
1035 std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct "
1036 << Start.DepType() << " of pkg in APT::Never-MarkAuto-Sections)" << std::endl;
92b9551f
MV
1037 MarkInstall(InstPkg,true,Depth + 1, true);
1038 }
1039 else
1040 {
1041 // mark automatic dependency
b51ff02a 1042 MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps);
92b9551f
MV
1043 // Set the autoflag, after MarkInstall because MarkInstall unsets it
1044 if (P->CurrentVer == 0)
1045 PkgState[InstPkg->ID].Flags |= Flag::Auto;
1046 }
b2e465d6 1047 }
6c139d6e
AL
1048 continue;
1049 }
308c7d30 1050
b2e465d6 1051 /* For conflicts we just de-install the package and mark as auto,
308c7d30
IJ
1052 Conflicts may not have or groups. For dpkg's Breaks we try to
1053 upgrade the package. */
1054 if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes ||
1055 Start->Type == Dep::DpkgBreaks)
6c139d6e 1056 {
6c139d6e
AL
1057 for (Version **I = List; *I != 0; I++)
1058 {
1059 VerIterator Ver(*this,*I);
1060 PkgIterator Pkg = Ver.ParentPkg();
308c7d30
IJ
1061
1062 if (Start->Type != Dep::DpkgBreaks)
af29ffb4 1063 MarkDelete(Pkg,false,Depth + 1);
308c7d30
IJ
1064 else
1065 if (PkgState[Pkg->ID].CandidateVer != *I)
1066 MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
6c139d6e 1067 }
6c139d6e
AL
1068 continue;
1069 }
1070 }
1071}
1072 /*}}}*/
2d403b92
MV
1073// DepCache::IsAutoInstallOk - check if it is to install this package /*{{{*/
1074// ---------------------------------------------------------------------
1075/* The default implementation is useless, but an application using this
1076 library can override this method to control the MarkInstall behaviour */
1077bool pkgDepCache::IsAutoInstallOk(const PkgIterator &Pkg, unsigned long Depth)
1078{
1079 return true;
1080}
1081 /*}}}*/
d0c59649
AL
1082// DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
1083// ---------------------------------------------------------------------
1084/* */
1085void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
1086{
74a05226
MV
1087 ActionGroup group(*this);
1088
d0c59649
AL
1089 RemoveSizes(Pkg);
1090 RemoveStates(Pkg);
1091
1092 StateCache &P = PkgState[Pkg->ID];
1093 if (To == true)
1094 P.iFlags |= ReInstall;
1095 else
1096 P.iFlags &= ~ReInstall;
1097
1098 AddStates(Pkg);
1099 AddSizes(Pkg);
1100}
1101 /*}}}*/
b2e465d6
AL
1102// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
1103// ---------------------------------------------------------------------
1104/* */
1105void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
1106{
74a05226
MV
1107 ActionGroup group(*this);
1108
b2e465d6
AL
1109 pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
1110 StateCache &P = PkgState[Pkg->ID];
74a05226 1111
b2e465d6
AL
1112 RemoveSizes(Pkg);
1113 RemoveStates(Pkg);
1114
1115 if (P.CandidateVer == P.InstallVer)
1116 P.InstallVer = (Version *)TargetVer;
1117 P.CandidateVer = (Version *)TargetVer;
1118 P.Update(Pkg,*this);
1119
1120 AddStates(Pkg);
1121 Update(Pkg);
1122 AddSizes(Pkg);
1123}
74a05226
MV
1124
1125void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
1126{
1127 StateCache &state = PkgState[Pkg->ID];
1128
1129 ActionGroup group(*this);
1130
1131 if(Auto)
1132 state.Flags |= Flag::Auto;
1133 else
1134 state.Flags &= ~Flag::Auto;
1135}
b2e465d6 1136 /*}}}*/
6c139d6e
AL
1137// StateCache::Update - Compute the various static display things /*{{{*/
1138// ---------------------------------------------------------------------
1139/* This is called whenever the Candidate version changes. */
1140void pkgDepCache::StateCache::Update(PkgIterator Pkg,pkgCache &Cache)
1141{
1142 // Some info
1143 VerIterator Ver = CandidateVerIter(Cache);
1144
1145 // Use a null string or the version string
1146 if (Ver.end() == true)
1147 CandVersion = "";
1148 else
1149 CandVersion = Ver.VerStr();
1150
1151 // Find the current version
1152 CurVersion = "";
1153 if (Pkg->CurrentVer != 0)
1154 CurVersion = Pkg.CurrentVer().VerStr();
1155
1156 // Strip off the epochs for display
1157 CurVersion = StripEpoch(CurVersion);
1158 CandVersion = StripEpoch(CandVersion);
1159
1160 // Figure out if its up or down or equal
1161 Status = Ver.CompareVer(Pkg.CurrentVer());
1162 if (Pkg->CurrentVer == 0 || Pkg->VersionList == 0 || CandidateVer == 0)
1163 Status = 2;
1164}
1165 /*}}}*/
1166// StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
1167// ---------------------------------------------------------------------
1168/* */
1169const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
1170{
1171 if (Ver == 0)
1172 return 0;
1173
1174 // Strip any epoch
1175 for (const char *I = Ver; *I != 0; I++)
1176 if (*I == ':')
1177 return I + 1;
1178 return Ver;
1179}
1180 /*}}}*/
b2e465d6
AL
1181
1182// Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/
6321777b 1183// ---------------------------------------------------------------------
b2e465d6
AL
1184/* The default just returns the highest available version that is not
1185 a source and automatic. */
1186pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
6321777b 1187{
b2e465d6
AL
1188 /* Not source/not automatic versions cannot be a candidate version
1189 unless they are already installed */
1190 VerIterator Last(*(pkgCache *)this,0);
6321777b 1191
b2e465d6
AL
1192 for (VerIterator I = Pkg.VersionList(); I.end() == false; I++)
1193 {
1194 if (Pkg.CurrentVer() == I)
1195 return I;
1196
1197 for (VerFileIterator J = I.FileList(); J.end() == false; J++)
1198 {
1199 if ((J.File()->Flags & Flag::NotSource) != 0)
1200 continue;
1201
1202 /* Stash the highest version of a not-automatic source, we use it
1203 if there is nothing better */
1204 if ((J.File()->Flags & Flag::NotAutomatic) != 0)
1205 {
1206 if (Last.end() == true)
1207 Last = I;
1208 continue;
1209 }
1210
1211 return I;
1212 }
1213 }
6321777b 1214
b2e465d6
AL
1215 return Last;
1216}
1217 /*}}}*/
cb1933df 1218
b2e465d6
AL
1219// Policy::IsImportantDep - True if the dependency is important /*{{{*/
1220// ---------------------------------------------------------------------
1221/* */
1222bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
1223{
60681f93
MV
1224 if(Dep.IsCritical())
1225 return true;
1d722933
MV
1226 else if(Dep->Type == pkgCache::Dep::Recommends)
1227 {
1228 if ( _config->FindB("APT::Install-Recommends", false))
1229 return true;
1230 // we suport a special mode to only install-recommends for certain
1231 // sections
1232 // FIXME: this is a meant as a temporarly solution until the
1233 // recommends are cleaned up
cb1933df
MV
1234 const char *sec = Dep.ParentVer().Section();
1235 if (sec && ConfigValueInSubTree("APT::Install-Recommends-Sections", sec))
1236 return true;
1d722933 1237 }
60681f93
MV
1238 else if(Dep->Type == pkgCache::Dep::Suggests)
1239 return _config->FindB("APT::Install-Suggests", false);
1240
1241 return false;
6321777b
AL
1242}
1243 /*}}}*/
74a05226
MV
1244
1245pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
1246 : constructedSuccessfully(false)
1247{
1248 Configuration::Item const *Opts;
1249 Opts = _config->Tree("APT::NeverAutoRemove");
1250 if (Opts != 0 && Opts->Child != 0)
1251 {
1252 Opts = Opts->Child;
1253 for (; Opts != 0; Opts = Opts->Next)
1254 {
1255 if (Opts->Value.empty() == true)
1256 continue;
1257
1258 regex_t *p = new regex_t;
1259 if(regcomp(p,Opts->Value.c_str(),
1260 REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
1261 {
1262 regfree(p);
1263 delete p;
1264 _error->Error("Regex compilation error for APT::NeverAutoRemove");
1265 return;
1266 }
1267
1268 rootSetRegexp.push_back(p);
1269 }
1270 }
1271
1272 constructedSuccessfully = true;
1273}
1274
1275pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
1276{
1277 for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
1278 {
1279 regfree(rootSetRegexp[i]);
1280 delete rootSetRegexp[i];
1281 }
1282}
1283
1284
1285bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg)
1286{
1287 for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
1288 if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
1289 return true;
1290
1291 return false;
1292}
1293
1294pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
1295{
1296 DefaultRootSetFunc *f = new DefaultRootSetFunc;
1297 if(f->wasConstructedSuccessfully())
1298 return f;
1299 else
1300 {
1301 delete f;
1302 return NULL;
1303 }
1304}
1305
1306bool pkgDepCache::MarkFollowsRecommends()
1307{
1308 return _config->FindB("APT::AutoRemove::RecommendsImportant", true);
1309}
1310
1311bool pkgDepCache::MarkFollowsSuggests()
1312{
1313 return _config->FindB("APT::AutoRemove::SuggestsImportant", false);
1314}
1315
1316// the main mark algorithm
1317bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
1318{
1319 bool follow_recommends;
1320 bool follow_suggests;
1321
1322 // init the states
1323 for(PkgIterator p = PkgBegin(); !p.end(); ++p)
1324 {
1325 PkgState[p->ID].Marked = false;
1326 PkgState[p->ID].Garbage = false;
1327
1328 // debug output
1329 if(_config->FindB("Debug::pkgAutoRemove",false)
1330 && PkgState[p->ID].Flags & Flag::Auto)
1331 std::clog << "AutoDep: " << p.Name() << std::endl;
1332 }
1333
1334 // init vars
1335 follow_recommends = MarkFollowsRecommends();
1336 follow_suggests = MarkFollowsSuggests();
1337
1338
1339
1340 // do the mark part, this is the core bit of the algorithm
1341 for(PkgIterator p = PkgBegin(); !p.end(); ++p)
1342 {
1343 if(!(PkgState[p->ID].Flags & Flag::Auto) ||
1344 (p->Flags & Flag::Essential) ||
1345 userFunc.InRootSet(p))
1346
1347 {
1348 // the package is installed (and set to keep)
1349 if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
83860e37 1350 MarkPackage(p, p.CurrentVer(),
74a05226
MV
1351 follow_recommends, follow_suggests);
1352 // the package is to be installed
1353 else if(PkgState[p->ID].Install())
1354 MarkPackage(p, PkgState[p->ID].InstVerIter(*this),
1355 follow_recommends, follow_suggests);
1356 }
1357 }
1358
1359 return true;
1360}
1361
1362// mark a single package in Mark-and-Sweep
1363void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
1364 const pkgCache::VerIterator &ver,
1365 bool follow_recommends,
1366 bool follow_suggests)
1367{
1368 pkgDepCache::StateCache &state = PkgState[pkg->ID];
36baa77a 1369 VerIterator currver = pkg.CurrentVer();
74a05226
MV
1370 VerIterator candver = state.CandidateVerIter(*this);
1371 VerIterator instver = state.InstVerIter(*this);
1372
1373#if 0
1374 // If a package was garbage-collected but is now being marked, we
1375 // should re-select it
1376 // For cases when a pkg is set to upgrade and this trigger the
1377 // removal of a no-longer used dependency. if the pkg is set to
1378 // keep again later it will result in broken deps
1379 if(state.Delete() && state.RemoveReason = Unused)
1380 {
1381 if(ver==candver)
1382 mark_install(pkg, false, false, NULL);
1383 else if(ver==pkg.CurrentVer())
1384 MarkKeep(pkg, false, false);
1385
1386 instver=state.InstVerIter(*this);
1387 }
1388#endif
1389
36baa77a
MV
1390 // For packages that are not going to be removed, ignore versions
1391 // other than the InstVer. For packages that are going to be
1392 // removed, ignore versions other than the current version.
1393 if(!(ver == instver && !instver.end()) &&
1394 !(ver == currver && instver.end() && !ver.end()))
74a05226
MV
1395 return;
1396
1397 // if we are marked already we are done
1398 if(state.Marked)
1399 return;
1400
83860e37
DB
1401 if(_config->FindB("Debug::pkgAutoRemove",false))
1402 {
1403 std::clog << "Marking: " << pkg.Name();
1404 if(!ver.end())
1405 std::clog << " " << ver.VerStr();
1406 if(!currver.end())
1407 std::clog << ", Curr=" << currver.VerStr();
1408 if(!instver.end())
1409 std::clog << ", Inst=" << instver.VerStr();
1410 std::clog << std::endl;
1411 }
1412
74a05226
MV
1413 state.Marked=true;
1414
1415 if(!ver.end())
1416 {
1417 for(DepIterator d = ver.DependsList(); !d.end(); ++d)
1418 {
1419 if(d->Type == Dep::Depends ||
1420 d->Type == Dep::PreDepends ||
1421 (follow_recommends &&
1422 d->Type == Dep::Recommends) ||
1423 (follow_suggests &&
1424 d->Type == Dep::Suggests))
1425 {
1426 // Try all versions of this package.
1427 for(VerIterator V = d.TargetPkg().VersionList();
1428 !V.end(); ++V)
1429 {
1430 if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
1431 {
83860e37
DB
1432 if(_config->FindB("Debug::pkgAutoRemove",false))
1433 {
1434 std::clog << "Following dep: " << d.ParentPkg().Name()
1435 << " " << d.ParentVer().VerStr() << " "
1436 << d.DepType() << " "
1437 << d.TargetPkg().Name();
1438 if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
1439 {
1440 std::clog << " (" << d.CompType() << " "
1441 << d.TargetVer() << ")";
1442 }
1443 std::clog << std::endl;
1444 }
74a05226
MV
1445 MarkPackage(V.ParentPkg(), V,
1446 follow_recommends, follow_suggests);
1447 }
1448 }
1449 // Now try virtual packages
1450 for(PrvIterator prv=d.TargetPkg().ProvidesList();
1451 !prv.end(); ++prv)
1452 {
1453 if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp,
1454 d.TargetVer()))
1455 {
83860e37
DB
1456 if(_config->FindB("Debug::pkgAutoRemove",false))
1457 {
1458 std::clog << "Following dep: " << d.ParentPkg().Name()
1459 << " " << d.ParentVer().VerStr() << " "
1460 << d.DepType() << " "
1461 << d.TargetPkg().Name();
1462 if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
1463 {
1464 std::clog << " (" << d.CompType() << " "
1465 << d.TargetVer() << ")";
1466 }
1467 std::clog << ", provided by "
1468 << prv.OwnerPkg().Name() << " "
1469 << prv.OwnerVer().VerStr()
1470 << std::endl;
1471 }
1472
74a05226
MV
1473 MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
1474 follow_recommends, follow_suggests);
1475 }
1476 }
1477 }
1478 }
1479 }
1480}
1481
1482bool pkgDepCache::Sweep()
1483{
1484 // do the sweep
1485 for(PkgIterator p=PkgBegin(); !p.end(); ++p)
1486 {
1487 StateCache &state=PkgState[p->ID];
1488
c9b320e8
MV
1489 // skip required packages
1490 if (!p.CurrentVer().end() &&
1491 (p.CurrentVer()->Priority == pkgCache::State::Required))
1492 continue;
1493
74a05226 1494 // if it is not marked and it is installed, it's garbage
32085498 1495 if(!state.Marked && (!p.CurrentVer().end() || state.Install()))
74a05226
MV
1496 {
1497 state.Garbage=true;
1498 if(_config->FindB("Debug::pkgAutoRemove",false))
1499 std::cout << "Garbage: " << p.Name() << std::endl;
1500 }
1501 }
1502
1503 return true;
1504}