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