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