]>
git.saurik.com Git - apt.git/blob - apt-pkg/depcache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: depcache.cc,v 1.25 2001/05/27 05:36:04 jgg Exp $
4 /* ######################################################################
6 Dependency Cache - Caches Dependency information.
8 ##################################################################### */
10 // Include Files /*{{{*/
11 #include <apt-pkg/depcache.h>
12 #include <apt-pkg/version.h>
13 #include <apt-pkg/error.h>
14 #include <apt-pkg/sptr.h>
15 #include <apt-pkg/algorithms.h>
17 #include <apt-pkg/fileutl.h>
18 #include <apt-pkg/configuration.h>
19 #include <apt-pkg/pkgsystem.h>
20 #include <apt-pkg/tagfile.h>
28 pkgDepCache::ActionGroup::ActionGroup(pkgDepCache
&cache
) :
29 cache(cache
), released(false)
34 void pkgDepCache::ActionGroup::release()
38 if(cache
.group_level
== 0)
39 std::cerr
<< "W: Unbalanced action groups, expect badness" << std::endl
;
44 if(cache
.group_level
== 0)
52 pkgDepCache::ActionGroup::~ActionGroup()
57 // DepCache::pkgDepCache - Constructors /*{{{*/
58 // ---------------------------------------------------------------------
60 pkgDepCache::pkgDepCache(pkgCache
*pCache
,Policy
*Plcy
) :
61 group_level(0), Cache(pCache
), PkgState(0), DepState(0)
66 delLocalPolicy
= LocalPolicy
= new Policy
;
69 // DepCache::~pkgDepCache - Destructor /*{{{*/
70 // ---------------------------------------------------------------------
72 pkgDepCache::~pkgDepCache()
76 delete delLocalPolicy
;
79 // DepCache::Init - Generate the initial extra structures. /*{{{*/
80 // ---------------------------------------------------------------------
81 /* This allocats the extension buffers and initializes them. */
82 bool pkgDepCache::Init(OpProgress
*Prog
)
84 // Suppress mark updates during this operation (just in case) and
85 // run a mark operation when Init terminates.
86 ActionGroup
actions(*this);
90 PkgState
= new StateCache
[Head().PackageCount
];
91 DepState
= new unsigned char[Head().DependsCount
];
92 memset(PkgState
,0,sizeof(*PkgState
)*Head().PackageCount
);
93 memset(DepState
,0,sizeof(*DepState
)*Head().DependsCount
);
97 Prog
->OverallProgress(0,2*Head().PackageCount
,Head().PackageCount
,
98 _("Building dependency tree"));
99 Prog
->SubProgress(Head().PackageCount
,_("Candidate versions"));
102 /* Set the current state of everything. In this state all of the
103 packages are kept exactly as is. See AllUpgrade */
105 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
108 Prog
->Progress(Done
);
110 // Find the proper cache slot
111 StateCache
&State
= PkgState
[I
->ID
];
114 // Figure out the install version
115 State
.CandidateVer
= GetCandidateVer(I
);
116 State
.InstallVer
= I
.CurrentVer();
117 State
.Mode
= ModeKeep
;
119 State
.Update(I
,*this);
125 Prog
->OverallProgress(Head().PackageCount
,2*Head().PackageCount
,
127 _("Building dependency tree"));
128 Prog
->SubProgress(Head().PackageCount
,_("Dependency generation"));
140 bool pkgDepCache::readStateFile(OpProgress
*Prog
)
143 string state
= _config
->FindDir("Dir::State") + "extended_states";
144 if(FileExists(state
)) {
145 state_file
.Open(state
, FileFd::ReadOnly
);
146 int file_size
= state_file
.Size();
148 Prog
->OverallProgress(0, file_size
, 1,
149 _("Reading state information"));
151 pkgTagFile
tagfile(&state_file
);
152 pkgTagSection section
;
154 while(tagfile
.Step(section
)) {
155 string pkgname
= section
.FindS("Package");
156 pkgCache::PkgIterator pkg
=Cache
->FindPkg(pkgname
);
157 // Silently ignore unknown packages and packages with no actual
159 if(!pkg
.end() && !pkg
.VersionList().end()) {
160 short reason
= section
.FindI("Auto-Installed", 0);
162 PkgState
[pkg
->ID
].Flags
|= Flag::Auto
;
163 if(_config
->FindB("Debug::pkgAutoRemove",false))
164 std::cout
<< "Auto-Installed : " << pkgname
<< std::endl
;
167 Prog
->OverallProgress(amt
, file_size
, 1,
168 _("Reading state information"));
171 Prog
->OverallProgress(file_size
, file_size
, 1,
172 _("Reading state information"));
179 bool pkgDepCache::writeStateFile(OpProgress
*prog
)
181 if(_config
->FindB("Debug::pkgAutoRemove",false))
182 std::clog
<< "pkgDepCache::writeStateFile()" << std::endl
;
185 string state
= _config
->FindDir("Dir::State") + "extended_states";
187 // if it does not exist, create a empty one
188 if(!FileExists(state
))
190 StateFile
.Open(state
, FileFd::WriteEmpty
);
195 if(!StateFile
.Open(state
, FileFd::ReadOnly
))
196 return _error
->Error(_("Failed to open StateFile %s"),
200 string outfile
= state
+ ".tmp";
201 if((OutFile
= fopen(outfile
.c_str(),"w")) == NULL
)
202 return _error
->Error(_("Failed to write temporary StateFile %s"),
205 // first merge with the existing sections
206 pkgTagFile
tagfile(&StateFile
);
207 pkgTagSection section
;
208 std::set
<string
> pkgs_seen
;
209 const char *nullreorderlist
[] = {0};
210 while(tagfile
.Step(section
)) {
211 string pkgname
= section
.FindS("Package");
212 // Silently ignore unknown packages and packages with no actual
214 pkgCache::PkgIterator pkg
=Cache
->FindPkg(pkgname
);
215 if(pkg
.end() || pkg
.VersionList().end())
217 bool oldAuto
= section
.FindI("Auto-Installed");
218 bool newAuto
= (PkgState
[pkg
->ID
].Flags
& Flag::Auto
);
219 if(_config
->FindB("Debug::pkgAutoRemove",false))
220 std::clog
<< "Update exisiting AutoInstall info: "
221 << pkg
.Name() << std::endl
;
222 TFRewriteData rewrite
[2];
223 rewrite
[0].Tag
= "Auto-Installed";
224 rewrite
[0].Rewrite
= newAuto
? "1" : "0";
225 rewrite
[0].NewTag
= 0;
227 TFRewrite(OutFile
, section
, nullreorderlist
, rewrite
);
228 fprintf(OutFile
,"\n");
229 pkgs_seen
.insert(pkgname
);
232 // then write the ones we have not seen yet
233 std::ostringstream ostr
;
234 for(pkgCache::PkgIterator pkg
=Cache
->PkgBegin(); !pkg
.end(); pkg
++) {
235 if(PkgState
[pkg
->ID
].Flags
& Flag::Auto
) {
236 if (pkgs_seen
.find(pkg
.Name()) != pkgs_seen
.end()) {
237 if(_config
->FindB("Debug::pkgAutoRemove",false))
238 std::clog
<< "Skipping already written " << pkg
.Name() << std::endl
;
241 if(_config
->FindB("Debug::pkgAutoRemove",false))
242 std::clog
<< "Writing new AutoInstall: "
243 << pkg
.Name() << std::endl
;
244 ostr
.str(string(""));
245 ostr
<< "Package: " << pkg
.Name()
246 << "\nAuto-Installed: 1\n\n";
247 fprintf(OutFile
,ostr
.str().c_str());
248 fprintf(OutFile
,"\n");
253 // move the outfile over the real file
254 rename(outfile
.c_str(), state
.c_str());
259 // DepCache::CheckDep - Checks a single dependency /*{{{*/
260 // ---------------------------------------------------------------------
261 /* This first checks the dependency against the main target package and
262 then walks along the package provides list and checks if each provides
263 will be installed then checks the provides against the dep. Res will be
264 set to the package which was used to satisfy the dep. */
265 bool pkgDepCache::CheckDep(DepIterator Dep
,int Type
,PkgIterator
&Res
)
267 Res
= Dep
.TargetPkg();
269 /* Check simple depends. A depends -should- never self match but
270 we allow it anyhow because dpkg does. Technically it is a packaging
271 bug. Conflicts may never self match */
272 if (Dep
.TargetPkg() != Dep
.ParentPkg() ||
273 (Dep
->Type
!= Dep::Conflicts
&& Dep
->Type
!= Dep::Obsoletes
))
275 PkgIterator Pkg
= Dep
.TargetPkg();
276 // Check the base package
277 if (Type
== NowVersion
&& Pkg
->CurrentVer
!= 0)
278 if (VS().CheckDep(Pkg
.CurrentVer().VerStr(),Dep
->CompareOp
,
279 Dep
.TargetVer()) == true)
282 if (Type
== InstallVersion
&& PkgState
[Pkg
->ID
].InstallVer
!= 0)
283 if (VS().CheckDep(PkgState
[Pkg
->ID
].InstVerIter(*this).VerStr(),
284 Dep
->CompareOp
,Dep
.TargetVer()) == true)
287 if (Type
== CandidateVersion
&& PkgState
[Pkg
->ID
].CandidateVer
!= 0)
288 if (VS().CheckDep(PkgState
[Pkg
->ID
].CandidateVerIter(*this).VerStr(),
289 Dep
->CompareOp
,Dep
.TargetVer()) == true)
293 if (Dep
->Type
== Dep::Obsoletes
)
296 // Check the providing packages
297 PrvIterator P
= Dep
.TargetPkg().ProvidesList();
298 PkgIterator Pkg
= Dep
.ParentPkg();
299 for (; P
.end() != true; P
++)
301 /* Provides may never be applied against the same package if it is
302 a conflicts. See the comment above. */
303 if (P
.OwnerPkg() == Pkg
&& Dep
->Type
== Dep::Conflicts
)
306 // Check if the provides is a hit
307 if (Type
== NowVersion
)
309 if (P
.OwnerPkg().CurrentVer() != P
.OwnerVer())
313 if (Type
== InstallVersion
)
315 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
316 if (State
.InstallVer
!= (Version
*)P
.OwnerVer())
320 if (Type
== CandidateVersion
)
322 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
323 if (State
.CandidateVer
!= (Version
*)P
.OwnerVer())
327 // Compare the versions.
328 if (VS().CheckDep(P
.ProvideVersion(),Dep
->CompareOp
,Dep
.TargetVer()) == true)
338 // DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
339 // ---------------------------------------------------------------------
340 /* Call with Mult = -1 to preform the inverse opration */
341 void pkgDepCache::AddSizes(const PkgIterator
&Pkg
,signed long Mult
)
343 StateCache
&P
= PkgState
[Pkg
->ID
];
345 if (Pkg
->VersionList
== 0)
348 if (Pkg
.State() == pkgCache::PkgIterator::NeedsConfigure
&&
352 // Compute the size data
353 if (P
.NewInstall() == true)
355 iUsrSize
+= (signed)(Mult
*P
.InstVerIter(*this)->InstalledSize
);
356 iDownloadSize
+= (signed)(Mult
*P
.InstVerIter(*this)->Size
);
361 if (Pkg
->CurrentVer
!= 0 &&
362 (P
.InstallVer
!= (Version
*)Pkg
.CurrentVer() ||
363 (P
.iFlags
& ReInstall
) == ReInstall
) && P
.InstallVer
!= 0)
365 iUsrSize
+= (signed)(Mult
*((signed)P
.InstVerIter(*this)->InstalledSize
-
366 (signed)Pkg
.CurrentVer()->InstalledSize
));
367 iDownloadSize
+= (signed)(Mult
*P
.InstVerIter(*this)->Size
);
372 if (Pkg
.State() == pkgCache::PkgIterator::NeedsUnpack
&&
375 iDownloadSize
+= (signed)(Mult
*P
.InstVerIter(*this)->Size
);
380 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
== 0)
382 iUsrSize
-= (signed)(Mult
*Pkg
.CurrentVer()->InstalledSize
);
387 // DepCache::AddStates - Add the package to the state counter /*{{{*/
388 // ---------------------------------------------------------------------
389 /* This routine is tricky to use, you must make sure that it is never
390 called twice for the same package. This means the Remove/Add section
391 should be as short as possible and not encompass any code that will
392 calld Remove/Add itself. Remember, dependencies can be circular so
393 while processing a dep for Pkg it is possible that Add/Remove
394 will be called on Pkg */
395 void pkgDepCache::AddStates(const PkgIterator
&Pkg
,int Add
)
397 StateCache
&State
= PkgState
[Pkg
->ID
];
399 // The Package is broken (either minimal dep or policy dep)
400 if ((State
.DepState
& DepInstMin
) != DepInstMin
)
402 if ((State
.DepState
& DepInstPolicy
) != DepInstPolicy
)
403 iPolicyBrokenCount
+= Add
;
406 if (Pkg
.State() != PkgIterator::NeedsNothing
)
410 if (Pkg
->CurrentVer
== 0)
412 if (State
.Mode
== ModeDelete
&&
413 (State
.iFlags
| Purge
) == Purge
&& Pkg
.Purge() == false)
416 if (State
.Mode
== ModeInstall
)
421 // Installed, no upgrade
422 if (State
.Status
== 0)
424 if (State
.Mode
== ModeDelete
)
427 if ((State
.iFlags
& ReInstall
) == ReInstall
)
433 // Alll 3 are possible
434 if (State
.Mode
== ModeDelete
)
436 if (State
.Mode
== ModeKeep
)
438 if (State
.Mode
== ModeInstall
)
442 // DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
443 // ---------------------------------------------------------------------
444 /* The or group results are stored in the last item of the or group. This
445 allows easy detection of the state of a whole or'd group. */
446 void pkgDepCache::BuildGroupOrs(VerIterator
const &V
)
448 unsigned char Group
= 0;
450 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
452 // Build the dependency state.
453 unsigned char &State
= DepState
[D
->ID
];
455 /* Invert for Conflicts. We have to do this twice to get the
456 right sense for a conflicts group */
457 if (D
->Type
== Dep::Conflicts
|| D
->Type
== Dep::Obsoletes
)
460 // Add to the group if we are within an or..
464 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
467 // Invert for Conflicts
468 if (D
->Type
== Dep::Conflicts
|| D
->Type
== Dep::Obsoletes
)
473 // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
474 // ---------------------------------------------------------------------
475 /* This is used to run over a dependency list and determine the dep
476 state of the list, filtering it through both a Min check and a Policy
477 check. The return result will have SetMin/SetPolicy low if a check
478 fails. It uses the DepState cache for it's computations. */
479 unsigned char pkgDepCache::VersionState(DepIterator D
,unsigned char Check
,
480 unsigned char SetMin
,
481 unsigned char SetPolicy
)
483 unsigned char Dep
= 0xFF;
485 while (D
.end() != true)
487 // Compute a single dependency element (glob or)
488 DepIterator Start
= D
;
489 unsigned char State
= 0;
490 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
492 State
|= DepState
[D
->ID
];
493 LastOR
= (D
->CompareOp
& Dep::Or
) == Dep::Or
;
496 // Minimum deps that must be satisfied to have a working package
497 if (Start
.IsCritical() == true)
498 if ((State
& Check
) != Check
)
501 // Policy deps that must be satisfied to install the package
502 if (IsImportantDep(Start
) == true &&
503 (State
& Check
) != Check
)
510 // DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
511 // ---------------------------------------------------------------------
512 /* This is the main dependency computation bit. It computes the 3 main
513 results for a dependencys, Now, Install and Candidate. Callers must
514 invert the result if dealing with conflicts. */
515 unsigned char pkgDepCache::DependencyState(DepIterator
&D
)
517 unsigned char State
= 0;
519 if (CheckDep(D
,NowVersion
) == true)
521 if (CheckDep(D
,InstallVersion
) == true)
523 if (CheckDep(D
,CandidateVersion
) == true)
529 // DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
530 // ---------------------------------------------------------------------
531 /* This determines the combined dependency representation of a package
532 for its two states now and install. This is done by using the pre-generated
533 dependency information. */
534 void pkgDepCache::UpdateVerState(PkgIterator Pkg
)
536 // Empty deps are always true
537 StateCache
&State
= PkgState
[Pkg
->ID
];
538 State
.DepState
= 0xFF;
540 // Check the Current state
541 if (Pkg
->CurrentVer
!= 0)
543 DepIterator D
= Pkg
.CurrentVer().DependsList();
544 State
.DepState
&= VersionState(D
,DepNow
,DepNowMin
,DepNowPolicy
);
547 /* Check the candidate state. We do not compare against the whole as
548 a candidate state but check the candidate version against the
550 if (State
.CandidateVer
!= 0)
552 DepIterator D
= State
.CandidateVerIter(*this).DependsList();
553 State
.DepState
&= VersionState(D
,DepInstall
,DepCandMin
,DepCandPolicy
);
556 // Check target state which can only be current or installed
557 if (State
.InstallVer
!= 0)
559 DepIterator D
= State
.InstVerIter(*this).DependsList();
560 State
.DepState
&= VersionState(D
,DepInstall
,DepInstMin
,DepInstPolicy
);
564 // DepCache::Update - Figure out all the state information /*{{{*/
565 // ---------------------------------------------------------------------
566 /* This will figure out the state of all the packages and all the
567 dependencies based on the current policy. */
568 void pkgDepCache::Update(OpProgress
*Prog
)
578 // Perform the depends pass
580 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
582 if (Prog
!= 0 && Done%20
== 0)
583 Prog
->Progress(Done
);
584 for (VerIterator V
= I
.VersionList(); V
.end() != true; V
++)
586 unsigned char Group
= 0;
588 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
590 // Build the dependency state.
591 unsigned char &State
= DepState
[D
->ID
];
592 State
= DependencyState(D
);
594 // Add to the group if we are within an or..
597 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
600 // Invert for Conflicts
601 if (D
->Type
== Dep::Conflicts
|| D
->Type
== Dep::Obsoletes
)
606 // Compute the pacakge dependency state and size additions
613 Prog
->Progress(Done
);
618 // DepCache::Update - Update the deps list of a package /*{{{*/
619 // ---------------------------------------------------------------------
620 /* This is a helper for update that only does the dep portion of the scan.
621 It is mainly meant to scan reverse dependencies. */
622 void pkgDepCache::Update(DepIterator D
)
624 // Update the reverse deps
625 for (;D
.end() != true; D
++)
627 unsigned char &State
= DepState
[D
->ID
];
628 State
= DependencyState(D
);
630 // Invert for Conflicts
631 if (D
->Type
== Dep::Conflicts
|| D
->Type
== Dep::Obsoletes
)
634 RemoveStates(D
.ParentPkg());
635 BuildGroupOrs(D
.ParentVer());
636 UpdateVerState(D
.ParentPkg());
637 AddStates(D
.ParentPkg());
641 // DepCache::Update - Update the related deps of a package /*{{{*/
642 // ---------------------------------------------------------------------
643 /* This is called whenever the state of a package changes. It updates
644 all cached dependencies related to this package. */
645 void pkgDepCache::Update(PkgIterator
const &Pkg
)
647 // Recompute the dep of the package
652 // Update the reverse deps
653 Update(Pkg
.RevDependsList());
655 // Update the provides map for the current ver
656 if (Pkg
->CurrentVer
!= 0)
657 for (PrvIterator P
= Pkg
.CurrentVer().ProvidesList();
658 P
.end() != true; P
++)
659 Update(P
.ParentPkg().RevDependsList());
661 // Update the provides map for the candidate ver
662 if (PkgState
[Pkg
->ID
].CandidateVer
!= 0)
663 for (PrvIterator P
= PkgState
[Pkg
->ID
].CandidateVerIter(*this).ProvidesList();
664 P
.end() != true; P
++)
665 Update(P
.ParentPkg().RevDependsList());
670 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
671 // ---------------------------------------------------------------------
673 void pkgDepCache::MarkKeep(PkgIterator
const &Pkg
, bool Soft
, bool FromUser
)
675 // Simplifies other routines.
676 if (Pkg
.end() == true)
679 /* Reject an attempt to keep a non-source broken installed package, those
681 if (Pkg
.State() == PkgIterator::NeedsUnpack
&&
682 Pkg
.CurrentVer().Downloadable() == false)
685 /** \todo Can this be moved later in the method? */
686 ActionGroup
group(*this);
688 /* We changed the soft state all the time so the UI is a bit nicer
690 StateCache
&P
= PkgState
[Pkg
->ID
];
692 P
.iFlags
|= AutoKept
;
694 P
.iFlags
&= ~AutoKept
;
696 // Check that it is not already kept
697 if (P
.Mode
== ModeKeep
)
700 // We dont even try to keep virtual packages..
701 if (Pkg
->VersionList
== 0)
703 #if 0 // reseting the autoflag here means we lose the
704 // auto-mark information if a user selects a package for removal
705 // but changes his mind then and sets it for keep again
706 // - this makes sense as default when all Garbage dependencies
707 // are automatically marked for removal (as aptitude does).
708 // setting a package for keep then makes it no longer autoinstalled
709 // for all other use-case this action is rather suprising
710 if(FromUser
&& !P
.Marked
)
711 P
.Flags
&= ~Flag::Auto
;
718 if (Pkg
->CurrentVer
== 0)
721 P
.InstallVer
= Pkg
.CurrentVer();
730 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
731 // ---------------------------------------------------------------------
733 void pkgDepCache::MarkDelete(PkgIterator
const &Pkg
, bool rPurge
)
735 // Simplifies other routines.
736 if (Pkg
.end() == true)
739 ActionGroup
group(*this);
741 // Check that it is not already marked for delete
742 StateCache
&P
= PkgState
[Pkg
->ID
];
743 P
.iFlags
&= ~(AutoKept
| Purge
);
747 if ((P
.Mode
== ModeDelete
|| P
.InstallVer
== 0) &&
748 (Pkg
.Purge() == true || rPurge
== false))
751 // We dont even try to delete virtual packages..
752 if (Pkg
->VersionList
== 0)
758 if (Pkg
->CurrentVer
== 0 && (Pkg
.Purge() == true || rPurge
== false))
769 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
770 // ---------------------------------------------------------------------
772 void pkgDepCache::MarkInstall(PkgIterator
const &Pkg
,bool AutoInst
,
773 unsigned long Depth
, bool FromUser
,
774 bool ForceImportantDeps
)
779 // Simplifies other routines.
780 if (Pkg
.end() == true)
783 ActionGroup
group(*this);
785 /* Check that it is not already marked for install and that it can be
787 StateCache
&P
= PkgState
[Pkg
->ID
];
788 P
.iFlags
&= ~AutoKept
;
789 if ((P
.InstPolicyBroken() == false && P
.InstBroken() == false) &&
790 (P
.Mode
== ModeInstall
||
791 P
.CandidateVer
== (Version
*)Pkg
.CurrentVer()))
793 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer() && P
.InstallVer
== 0)
794 MarkKeep(Pkg
, false, FromUser
);
798 // See if there is even any possible instalation candidate
799 if (P
.CandidateVer
== 0)
801 // We dont even try to install virtual packages..
802 if (Pkg
->VersionList
== 0)
804 /* Target the candidate version and remove the autoflag. We reset the
805 autoflag below if this was called recursively. Otherwise the user
806 should have the ability to de-auto a package by changing its state */
810 P
.Mode
= ModeInstall
;
811 P
.InstallVer
= P
.CandidateVer
;
815 // Set it to manual if it's a new install or cancelling the
816 // removal of a garbage package.
817 if(P
.Status
== 2 || (!Pkg
.CurrentVer().end() && !P
.Marked
))
818 P
.Flags
&= ~Flag::Auto
;
822 // Set it to auto if this is a new install.
824 P
.Flags
|= Flag::Auto
;
826 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer())
833 if (AutoInst
== false)
836 DepIterator Dep
= P
.InstVerIter(*this).DependsList();
837 for (; Dep
.end() != true;)
840 DepIterator Start
= Dep
;
843 for (bool LastOR
= true; Dep
.end() == false && LastOR
== true; Dep
++,Ors
++)
845 LastOR
= (Dep
->CompareOp
& Dep::Or
) == Dep::Or
;
847 if ((DepState
[Dep
->ID
] & DepInstall
) == DepInstall
)
851 // Dep is satisfied okay.
855 /* Check if this dep should be consider for install. If it is a user
856 defined important dep and we are installed a new package then
857 it will be installed. Otherwise we only check for important
858 deps that have changed from the installed version
860 if (IsImportantDep(Start
) == false)
863 /* check if any ImportantDep() (but not Critial) where added
864 * since we installed the package
866 bool isNewImportantDep
= false;
867 if(!ForceImportantDeps
&& !Start
.IsCritical())
870 VerIterator instVer
= Pkg
.CurrentVer();
873 for (DepIterator D
= instVer
.DependsList(); D
.end() != true; D
++)
875 //FIXME: deal better with or-groups(?)
876 DepIterator LocalStart
= D
;
878 if(IsImportantDep(D
) && Start
.TargetPkg() == D
.TargetPkg())
881 // this is a new dep if it was not found to be already
882 // a important dep of the installed pacakge
883 isNewImportantDep
= !found
;
886 if(isNewImportantDep
)
887 if(_config
->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
888 std::clog
<< "new important dependency: "
889 << Start
.TargetPkg().Name() << std::endl
;
891 // skip important deps if the package is already installed
892 if (Pkg
->CurrentVer
!= 0 && Start
.IsCritical() == false
893 && !isNewImportantDep
&& !ForceImportantDeps
)
896 /* If we are in an or group locate the first or that can
897 succeed. We have already cached this.. */
898 for (; Ors
> 1 && (DepState
[Start
->ID
] & DepCVer
) != DepCVer
; Ors
--)
901 /* This bit is for processing the possibilty of an install/upgrade
902 fixing the problem */
903 SPtrArray
<Version
*> List
= Start
.AllTargets();
904 if ((DepState
[Start
->ID
] & DepCVer
) == DepCVer
)
906 // Right, find the best version to install..
907 Version
**Cur
= List
;
908 PkgIterator P
= Start
.TargetPkg();
909 PkgIterator
InstPkg(*Cache
,0);
911 // See if there are direct matches (at the start of the list)
912 for (; *Cur
!= 0 && (*Cur
)->ParentPkg
== P
.Index(); Cur
++)
914 PkgIterator
Pkg(*Cache
,Cache
->PkgP
+ (*Cur
)->ParentPkg
);
915 if (PkgState
[Pkg
->ID
].CandidateVer
!= *Cur
)
921 // Select the highest priority providing package
922 if (InstPkg
.end() == true)
924 pkgPrioSortList(*Cache
,Cur
);
925 for (; *Cur
!= 0; Cur
++)
927 PkgIterator
Pkg(*Cache
,Cache
->PkgP
+ (*Cur
)->ParentPkg
);
928 if (PkgState
[Pkg
->ID
].CandidateVer
!= *Cur
)
935 if (InstPkg
.end() == false)
937 if(_config
->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
938 std::clog
<< "Installing " << InstPkg
.Name()
939 << " as dep of " << Pkg
.Name()
941 MarkInstall(InstPkg
, true, Depth
+ 1, false, ForceImportantDeps
);
946 /* For conflicts we just de-install the package and mark as auto,
947 Conflicts may not have or groups */
948 if (Start
->Type
== Dep::Conflicts
|| Start
->Type
== Dep::Obsoletes
)
950 for (Version
**I
= List
; *I
!= 0; I
++)
952 VerIterator
Ver(*this,*I
);
953 PkgIterator Pkg
= Ver
.ParentPkg();
962 // DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
963 // ---------------------------------------------------------------------
965 void pkgDepCache::SetReInstall(PkgIterator
const &Pkg
,bool To
)
967 ActionGroup
group(*this);
972 StateCache
&P
= PkgState
[Pkg
->ID
];
974 P
.iFlags
|= ReInstall
;
976 P
.iFlags
&= ~ReInstall
;
982 // DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
983 // ---------------------------------------------------------------------
985 void pkgDepCache::SetCandidateVersion(VerIterator TargetVer
)
987 ActionGroup
group(*this);
989 pkgCache::PkgIterator Pkg
= TargetVer
.ParentPkg();
990 StateCache
&P
= PkgState
[Pkg
->ID
];
995 if (P
.CandidateVer
== P
.InstallVer
)
996 P
.InstallVer
= (Version
*)TargetVer
;
997 P
.CandidateVer
= (Version
*)TargetVer
;
1005 void pkgDepCache::MarkAuto(const PkgIterator
&Pkg
, bool Auto
)
1007 StateCache
&state
= PkgState
[Pkg
->ID
];
1009 ActionGroup
group(*this);
1012 state
.Flags
|= Flag::Auto
;
1014 state
.Flags
&= ~Flag::Auto
;
1017 // StateCache::Update - Compute the various static display things /*{{{*/
1018 // ---------------------------------------------------------------------
1019 /* This is called whenever the Candidate version changes. */
1020 void pkgDepCache::StateCache::Update(PkgIterator Pkg
,pkgCache
&Cache
)
1023 VerIterator Ver
= CandidateVerIter(Cache
);
1025 // Use a null string or the version string
1026 if (Ver
.end() == true)
1029 CandVersion
= Ver
.VerStr();
1031 // Find the current version
1033 if (Pkg
->CurrentVer
!= 0)
1034 CurVersion
= Pkg
.CurrentVer().VerStr();
1036 // Strip off the epochs for display
1037 CurVersion
= StripEpoch(CurVersion
);
1038 CandVersion
= StripEpoch(CandVersion
);
1040 // Figure out if its up or down or equal
1041 Status
= Ver
.CompareVer(Pkg
.CurrentVer());
1042 if (Pkg
->CurrentVer
== 0 || Pkg
->VersionList
== 0 || CandidateVer
== 0)
1046 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
1047 // ---------------------------------------------------------------------
1049 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver
)
1055 for (const char *I
= Ver
; *I
!= 0; I
++)
1062 // Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/
1063 // ---------------------------------------------------------------------
1064 /* The default just returns the highest available version that is not
1065 a source and automatic. */
1066 pkgCache::VerIterator
pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg
)
1068 /* Not source/not automatic versions cannot be a candidate version
1069 unless they are already installed */
1070 VerIterator
Last(*(pkgCache
*)this,0);
1072 for (VerIterator I
= Pkg
.VersionList(); I
.end() == false; I
++)
1074 if (Pkg
.CurrentVer() == I
)
1077 for (VerFileIterator J
= I
.FileList(); J
.end() == false; J
++)
1079 if ((J
.File()->Flags
& Flag::NotSource
) != 0)
1082 /* Stash the highest version of a not-automatic source, we use it
1083 if there is nothing better */
1084 if ((J
.File()->Flags
& Flag::NotAutomatic
) != 0)
1086 if (Last
.end() == true)
1098 // Policy::IsImportantDep - True if the dependency is important /*{{{*/
1099 // ---------------------------------------------------------------------
1101 bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep
)
1103 if(Dep
.IsCritical())
1105 else if(Dep
->Type
== pkgCache::Dep::Recommends
)
1107 if ( _config
->FindB("APT::Install-Recommends", false))
1109 // we suport a special mode to only install-recommends for certain
1111 // FIXME: this is a meant as a temporarly solution until the
1112 // recommends are cleaned up
1113 string s
= _config
->Find("APT::Install-Recommends-Section","");
1116 const char *sec
= Dep
.TargetPkg().Section();
1117 if (sec
&& strcmp(sec
, s
.c_str()) == 0)
1121 else if(Dep
->Type
== pkgCache::Dep::Suggests
)
1122 return _config
->FindB("APT::Install-Suggests", false);
1128 pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
1129 : constructedSuccessfully(false)
1131 Configuration::Item
const *Opts
;
1132 Opts
= _config
->Tree("APT::NeverAutoRemove");
1133 if (Opts
!= 0 && Opts
->Child
!= 0)
1136 for (; Opts
!= 0; Opts
= Opts
->Next
)
1138 if (Opts
->Value
.empty() == true)
1141 regex_t
*p
= new regex_t
;
1142 if(regcomp(p
,Opts
->Value
.c_str(),
1143 REG_EXTENDED
| REG_ICASE
| REG_NOSUB
) != 0)
1147 _error
->Error("Regex compilation error for APT::NeverAutoRemove");
1151 rootSetRegexp
.push_back(p
);
1155 constructedSuccessfully
= true;
1158 pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
1160 for(unsigned int i
= 0; i
< rootSetRegexp
.size(); i
++)
1162 regfree(rootSetRegexp
[i
]);
1163 delete rootSetRegexp
[i
];
1168 bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator
&pkg
)
1170 for(unsigned int i
= 0; i
< rootSetRegexp
.size(); i
++)
1171 if (regexec(rootSetRegexp
[i
], pkg
.Name(), 0, 0, 0) == 0)
1177 pkgDepCache::InRootSetFunc
*pkgDepCache::GetRootSetFunc()
1179 DefaultRootSetFunc
*f
= new DefaultRootSetFunc
;
1180 if(f
->wasConstructedSuccessfully())
1189 bool pkgDepCache::MarkFollowsRecommends()
1191 return _config
->FindB("APT::AutoRemove::RecommendsImportant", true);
1194 bool pkgDepCache::MarkFollowsSuggests()
1196 return _config
->FindB("APT::AutoRemove::SuggestsImportant", false);
1199 // the main mark algorithm
1200 bool pkgDepCache::MarkRequired(InRootSetFunc
&userFunc
)
1202 bool follow_recommends
;
1203 bool follow_suggests
;
1206 for(PkgIterator p
= PkgBegin(); !p
.end(); ++p
)
1208 PkgState
[p
->ID
].Marked
= false;
1209 PkgState
[p
->ID
].Garbage
= false;
1212 if(_config
->FindB("Debug::pkgAutoRemove",false)
1213 && PkgState
[p
->ID
].Flags
& Flag::Auto
)
1214 std::clog
<< "AutoDep: " << p
.Name() << std::endl
;
1218 follow_recommends
= MarkFollowsRecommends();
1219 follow_suggests
= MarkFollowsSuggests();
1223 // do the mark part, this is the core bit of the algorithm
1224 for(PkgIterator p
= PkgBegin(); !p
.end(); ++p
)
1226 if(!(PkgState
[p
->ID
].Flags
& Flag::Auto
) ||
1227 (p
->Flags
& Flag::Essential
) ||
1228 userFunc
.InRootSet(p
))
1231 // the package is installed (and set to keep)
1232 if(PkgState
[p
->ID
].Keep() && !p
.CurrentVer().end())
1233 MarkPackage(p
, p
.CurrentVer(),
1234 follow_recommends
, follow_suggests
);
1235 // the package is to be installed
1236 else if(PkgState
[p
->ID
].Install())
1237 MarkPackage(p
, PkgState
[p
->ID
].InstVerIter(*this),
1238 follow_recommends
, follow_suggests
);
1245 // mark a single package in Mark-and-Sweep
1246 void pkgDepCache::MarkPackage(const pkgCache::PkgIterator
&pkg
,
1247 const pkgCache::VerIterator
&ver
,
1248 bool follow_recommends
,
1249 bool follow_suggests
)
1251 pkgDepCache::StateCache
&state
= PkgState
[pkg
->ID
];
1252 VerIterator candver
= state
.CandidateVerIter(*this);
1253 VerIterator instver
= state
.InstVerIter(*this);
1256 // If a package was garbage-collected but is now being marked, we
1257 // should re-select it
1258 // For cases when a pkg is set to upgrade and this trigger the
1259 // removal of a no-longer used dependency. if the pkg is set to
1260 // keep again later it will result in broken deps
1261 if(state
.Delete() && state
.RemoveReason
= Unused
)
1264 mark_install(pkg
, false, false, NULL
);
1265 else if(ver
==pkg
.CurrentVer())
1266 MarkKeep(pkg
, false, false);
1268 instver
=state
.InstVerIter(*this);
1272 // Ignore versions other than the InstVer, and ignore packages
1273 // that are already going to be removed or just left uninstalled.
1274 if(!(ver
== instver
&& !instver
.end()))
1277 // if we are marked already we are done
1281 //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
1286 for(DepIterator d
= ver
.DependsList(); !d
.end(); ++d
)
1288 if(d
->Type
== Dep::Depends
||
1289 d
->Type
== Dep::PreDepends
||
1290 (follow_recommends
&&
1291 d
->Type
== Dep::Recommends
) ||
1293 d
->Type
== Dep::Suggests
))
1295 // Try all versions of this package.
1296 for(VerIterator V
= d
.TargetPkg().VersionList();
1299 if(_system
->VS
->CheckDep(V
.VerStr(), d
->CompareOp
, d
.TargetVer()))
1301 MarkPackage(V
.ParentPkg(), V
,
1302 follow_recommends
, follow_suggests
);
1305 // Now try virtual packages
1306 for(PrvIterator prv
=d
.TargetPkg().ProvidesList();
1309 if(_system
->VS
->CheckDep(prv
.ProvideVersion(), d
->CompareOp
,
1312 MarkPackage(prv
.OwnerPkg(), prv
.OwnerVer(),
1313 follow_recommends
, follow_suggests
);
1321 bool pkgDepCache::Sweep()
1324 for(PkgIterator p
=PkgBegin(); !p
.end(); ++p
)
1326 StateCache
&state
=PkgState
[p
->ID
];
1328 // if it is not marked and it is installed, it's garbage
1329 if(!state
.Marked
&& (!p
.CurrentVer().end() || state
.Install()))
1332 if(_config
->FindB("Debug::pkgAutoRemove",false))
1333 std::cout
<< "Garbage: " << p
.Name() << std::endl
;