]>
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 /*{{{*/
12 #pragma implementation "apt-pkg/depcache.h"
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>
20 #include <apt-pkg/fileutl.h>
21 #include <apt-pkg/configuration.h>
22 #include <apt-pkg/pkgsystem.h>
23 #include <apt-pkg/tagfile.h>
31 pkgDepCache::ActionGroup::ActionGroup(pkgDepCache
&cache
) :
32 cache(cache
), released(false)
37 void pkgDepCache::ActionGroup::release()
41 if(cache
.group_level
== 0)
42 std::cerr
<< "W: Unbalanced action groups, expect badness" << std::endl
;
47 if(cache
.group_level
== 0)
55 pkgDepCache::ActionGroup::~ActionGroup()
60 // DepCache::pkgDepCache - Constructors /*{{{*/
61 // ---------------------------------------------------------------------
63 pkgDepCache::pkgDepCache(pkgCache
*pCache
,Policy
*Plcy
) :
64 group_level(0), Cache(pCache
), PkgState(0), DepState(0)
69 delLocalPolicy
= LocalPolicy
= new Policy
;
72 // DepCache::~pkgDepCache - Destructor /*{{{*/
73 // ---------------------------------------------------------------------
75 pkgDepCache::~pkgDepCache()
79 delete delLocalPolicy
;
82 // DepCache::Init - Generate the initial extra structures. /*{{{*/
83 // ---------------------------------------------------------------------
84 /* This allocats the extension buffers and initializes them. */
85 bool pkgDepCache::Init(OpProgress
*Prog
)
87 // Suppress mark updates during this operation (just in case) and
88 // run a mark operation when Init terminates.
89 ActionGroup
actions(*this);
93 PkgState
= new StateCache
[Head().PackageCount
];
94 DepState
= new unsigned char[Head().DependsCount
];
95 memset(PkgState
,0,sizeof(*PkgState
)*Head().PackageCount
);
96 memset(DepState
,0,sizeof(*DepState
)*Head().DependsCount
);
100 Prog
->OverallProgress(0,2*Head().PackageCount
,Head().PackageCount
,
101 _("Building dependency tree"));
102 Prog
->SubProgress(Head().PackageCount
,_("Candidate versions"));
105 /* Set the current state of everything. In this state all of the
106 packages are kept exactly as is. See AllUpgrade */
108 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
111 Prog
->Progress(Done
);
113 // Find the proper cache slot
114 StateCache
&State
= PkgState
[I
->ID
];
117 // Figure out the install version
118 State
.CandidateVer
= GetCandidateVer(I
);
119 State
.InstallVer
= I
.CurrentVer();
120 State
.Mode
= ModeKeep
;
122 State
.Update(I
,*this);
128 Prog
->OverallProgress(Head().PackageCount
,2*Head().PackageCount
,
130 _("Building dependency tree"));
131 Prog
->SubProgress(Head().PackageCount
,_("Dependency generation"));
143 bool pkgDepCache::readStateFile(OpProgress
*Prog
)
146 string state
= _config
->FindDir("Dir::State") + "extended_states";
147 if(FileExists(state
)) {
148 state_file
.Open(state
, FileFd::ReadOnly
);
149 int file_size
= state_file
.Size();
151 Prog
->OverallProgress(0, file_size
, 1,
152 _("Reading state information"));
154 pkgTagFile
tagfile(&state_file
);
155 pkgTagSection section
;
157 while(tagfile
.Step(section
)) {
158 string pkgname
= section
.FindS("Package");
159 pkgCache::PkgIterator pkg
=Cache
->FindPkg(pkgname
);
160 // Silently ignore unknown packages and packages with no actual
162 if(!pkg
.end() && !pkg
.VersionList().end()) {
163 short reason
= section
.FindI("Auto-Installed", 0);
165 PkgState
[pkg
->ID
].Flags
|= Flag::Auto
;
166 if(_config
->FindB("Debug::pkgAutoRemove",false))
167 std::cout
<< "Auto-Installed : " << pkgname
<< std::endl
;
170 Prog
->OverallProgress(amt
, file_size
, 1,
171 _("Reading state information"));
174 Prog
->OverallProgress(file_size
, file_size
, 1,
175 _("Reading state information"));
182 bool pkgDepCache::writeStateFile(OpProgress
*prog
, bool InstalledOnly
)
184 if(_config
->FindB("Debug::pkgAutoRemove",false))
185 std::clog
<< "pkgDepCache::writeStateFile()" << std::endl
;
188 string state
= _config
->FindDir("Dir::State") + "extended_states";
190 // if it does not exist, create a empty one
191 if(!FileExists(state
))
193 StateFile
.Open(state
, FileFd::WriteEmpty
);
198 if(!StateFile
.Open(state
, FileFd::ReadOnly
))
199 return _error
->Error(_("Failed to open StateFile %s"),
203 string outfile
= state
+ ".tmp";
204 if((OutFile
= fopen(outfile
.c_str(),"w")) == NULL
)
205 return _error
->Error(_("Failed to write temporary StateFile %s"),
208 // first merge with the existing sections
209 pkgTagFile
tagfile(&StateFile
);
210 pkgTagSection section
;
211 std::set
<string
> pkgs_seen
;
212 const char *nullreorderlist
[] = {0};
213 while(tagfile
.Step(section
)) {
214 string pkgname
= section
.FindS("Package");
215 // Silently ignore unknown packages and packages with no actual
217 pkgCache::PkgIterator pkg
=Cache
->FindPkg(pkgname
);
218 if(pkg
.end() || pkg
.VersionList().end())
220 bool oldAuto
= section
.FindI("Auto-Installed");
221 bool newAuto
= (PkgState
[pkg
->ID
].Flags
& Flag::Auto
);
222 if(_config
->FindB("Debug::pkgAutoRemove",false))
223 std::clog
<< "Update exisiting AutoInstall info: "
224 << pkg
.Name() << std::endl
;
225 TFRewriteData rewrite
[2];
226 rewrite
[0].Tag
= "Auto-Installed";
227 rewrite
[0].Rewrite
= newAuto
? "1" : "0";
228 rewrite
[0].NewTag
= 0;
230 TFRewrite(OutFile
, section
, nullreorderlist
, rewrite
);
231 fprintf(OutFile
,"\n");
232 pkgs_seen
.insert(pkgname
);
235 // then write the ones we have not seen yet
236 std::ostringstream ostr
;
237 for(pkgCache::PkgIterator pkg
=Cache
->PkgBegin(); !pkg
.end(); pkg
++) {
238 if(PkgState
[pkg
->ID
].Flags
& Flag::Auto
) {
239 if (pkgs_seen
.find(pkg
.Name()) != pkgs_seen
.end()) {
240 if(_config
->FindB("Debug::pkgAutoRemove",false))
241 std::clog
<< "Skipping already written " << pkg
.Name() << std::endl
;
244 // skip not installed ones if requested
245 if(InstalledOnly
&& pkg
->CurrentVer
== 0)
247 if(_config
->FindB("Debug::pkgAutoRemove",false))
248 std::clog
<< "Writing new AutoInstall: "
249 << pkg
.Name() << std::endl
;
250 ostr
.str(string(""));
251 ostr
<< "Package: " << pkg
.Name()
252 << "\nAuto-Installed: 1\n\n";
253 fprintf(OutFile
,ostr
.str().c_str());
254 fprintf(OutFile
,"\n");
259 // move the outfile over the real file
260 rename(outfile
.c_str(), state
.c_str());
265 // DepCache::CheckDep - Checks a single dependency /*{{{*/
266 // ---------------------------------------------------------------------
267 /* This first checks the dependency against the main target package and
268 then walks along the package provides list and checks if each provides
269 will be installed then checks the provides against the dep. Res will be
270 set to the package which was used to satisfy the dep. */
271 bool pkgDepCache::CheckDep(DepIterator Dep
,int Type
,PkgIterator
&Res
)
273 Res
= Dep
.TargetPkg();
275 /* Check simple depends. A depends -should- never self match but
276 we allow it anyhow because dpkg does. Technically it is a packaging
277 bug. Conflicts may never self match */
278 if (Dep
.TargetPkg() != Dep
.ParentPkg() ||
279 (Dep
->Type
!= Dep::Conflicts
&& Dep
->Type
!= Dep::DpkgBreaks
&& Dep
->Type
!= Dep::Obsoletes
))
281 PkgIterator Pkg
= Dep
.TargetPkg();
282 // Check the base package
283 if (Type
== NowVersion
&& Pkg
->CurrentVer
!= 0)
284 if (VS().CheckDep(Pkg
.CurrentVer().VerStr(),Dep
->CompareOp
,
285 Dep
.TargetVer()) == true)
288 if (Type
== InstallVersion
&& PkgState
[Pkg
->ID
].InstallVer
!= 0)
289 if (VS().CheckDep(PkgState
[Pkg
->ID
].InstVerIter(*this).VerStr(),
290 Dep
->CompareOp
,Dep
.TargetVer()) == true)
293 if (Type
== CandidateVersion
&& PkgState
[Pkg
->ID
].CandidateVer
!= 0)
294 if (VS().CheckDep(PkgState
[Pkg
->ID
].CandidateVerIter(*this).VerStr(),
295 Dep
->CompareOp
,Dep
.TargetVer()) == true)
299 if (Dep
->Type
== Dep::Obsoletes
)
302 // Check the providing packages
303 PrvIterator P
= Dep
.TargetPkg().ProvidesList();
304 PkgIterator Pkg
= Dep
.ParentPkg();
305 for (; P
.end() != true; P
++)
307 /* Provides may never be applied against the same package if it is
308 a conflicts. See the comment above. */
309 if (P
.OwnerPkg() == Pkg
&&
310 (Dep
->Type
== Dep::Conflicts
|| Dep
->Type
== Dep::DpkgBreaks
))
313 // Check if the provides is a hit
314 if (Type
== NowVersion
)
316 if (P
.OwnerPkg().CurrentVer() != P
.OwnerVer())
320 if (Type
== InstallVersion
)
322 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
323 if (State
.InstallVer
!= (Version
*)P
.OwnerVer())
327 if (Type
== CandidateVersion
)
329 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
330 if (State
.CandidateVer
!= (Version
*)P
.OwnerVer())
334 // Compare the versions.
335 if (VS().CheckDep(P
.ProvideVersion(),Dep
->CompareOp
,Dep
.TargetVer()) == true)
345 // DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
346 // ---------------------------------------------------------------------
347 /* Call with Mult = -1 to preform the inverse opration */
348 void pkgDepCache::AddSizes(const PkgIterator
&Pkg
,signed long Mult
)
350 StateCache
&P
= PkgState
[Pkg
->ID
];
352 if (Pkg
->VersionList
== 0)
355 if (Pkg
.State() == pkgCache::PkgIterator::NeedsConfigure
&&
359 // Compute the size data
360 if (P
.NewInstall() == true)
362 iUsrSize
+= (signed)(Mult
*P
.InstVerIter(*this)->InstalledSize
);
363 iDownloadSize
+= (signed)(Mult
*P
.InstVerIter(*this)->Size
);
368 if (Pkg
->CurrentVer
!= 0 &&
369 (P
.InstallVer
!= (Version
*)Pkg
.CurrentVer() ||
370 (P
.iFlags
& ReInstall
) == ReInstall
) && P
.InstallVer
!= 0)
372 iUsrSize
+= (signed)(Mult
*((signed)P
.InstVerIter(*this)->InstalledSize
-
373 (signed)Pkg
.CurrentVer()->InstalledSize
));
374 iDownloadSize
+= (signed)(Mult
*P
.InstVerIter(*this)->Size
);
379 if (Pkg
.State() == pkgCache::PkgIterator::NeedsUnpack
&&
382 iDownloadSize
+= (signed)(Mult
*P
.InstVerIter(*this)->Size
);
387 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
== 0)
389 iUsrSize
-= (signed)(Mult
*Pkg
.CurrentVer()->InstalledSize
);
394 // DepCache::AddStates - Add the package to the state counter /*{{{*/
395 // ---------------------------------------------------------------------
396 /* This routine is tricky to use, you must make sure that it is never
397 called twice for the same package. This means the Remove/Add section
398 should be as short as possible and not encompass any code that will
399 calld Remove/Add itself. Remember, dependencies can be circular so
400 while processing a dep for Pkg it is possible that Add/Remove
401 will be called on Pkg */
402 void pkgDepCache::AddStates(const PkgIterator
&Pkg
,int Add
)
404 StateCache
&State
= PkgState
[Pkg
->ID
];
406 // The Package is broken (either minimal dep or policy dep)
407 if ((State
.DepState
& DepInstMin
) != DepInstMin
)
409 if ((State
.DepState
& DepInstPolicy
) != DepInstPolicy
)
410 iPolicyBrokenCount
+= Add
;
413 if (Pkg
.State() != PkgIterator::NeedsNothing
)
417 if (Pkg
->CurrentVer
== 0)
419 if (State
.Mode
== ModeDelete
&&
420 (State
.iFlags
| Purge
) == Purge
&& Pkg
.Purge() == false)
423 if (State
.Mode
== ModeInstall
)
428 // Installed, no upgrade
429 if (State
.Status
== 0)
431 if (State
.Mode
== ModeDelete
)
434 if ((State
.iFlags
& ReInstall
) == ReInstall
)
440 // Alll 3 are possible
441 if (State
.Mode
== ModeDelete
)
443 if (State
.Mode
== ModeKeep
)
445 if (State
.Mode
== ModeInstall
)
449 // DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
450 // ---------------------------------------------------------------------
451 /* The or group results are stored in the last item of the or group. This
452 allows easy detection of the state of a whole or'd group. */
453 void pkgDepCache::BuildGroupOrs(VerIterator
const &V
)
455 unsigned char Group
= 0;
457 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
459 // Build the dependency state.
460 unsigned char &State
= DepState
[D
->ID
];
462 /* Invert for Conflicts. We have to do this twice to get the
463 right sense for a conflicts group */
464 if (D
->Type
== Dep::Conflicts
||
465 D
->Type
== Dep::DpkgBreaks
||
466 D
->Type
== Dep::Obsoletes
)
469 // Add to the group if we are within an or..
473 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
476 // Invert for Conflicts
477 if (D
->Type
== Dep::Conflicts
||
478 D
->Type
== Dep::DpkgBreaks
||
479 D
->Type
== Dep::Obsoletes
)
484 // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
485 // ---------------------------------------------------------------------
486 /* This is used to run over a dependency list and determine the dep
487 state of the list, filtering it through both a Min check and a Policy
488 check. The return result will have SetMin/SetPolicy low if a check
489 fails. It uses the DepState cache for it's computations. */
490 unsigned char pkgDepCache::VersionState(DepIterator D
,unsigned char Check
,
491 unsigned char SetMin
,
492 unsigned char SetPolicy
)
494 unsigned char Dep
= 0xFF;
496 while (D
.end() != true)
498 // Compute a single dependency element (glob or)
499 DepIterator Start
= D
;
500 unsigned char State
= 0;
501 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
503 State
|= DepState
[D
->ID
];
504 LastOR
= (D
->CompareOp
& Dep::Or
) == Dep::Or
;
507 // Minimum deps that must be satisfied to have a working package
508 if (Start
.IsCritical() == true)
509 if ((State
& Check
) != Check
)
512 // Policy deps that must be satisfied to install the package
513 if (IsImportantDep(Start
) == true &&
514 (State
& Check
) != Check
)
521 // DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
522 // ---------------------------------------------------------------------
523 /* This is the main dependency computation bit. It computes the 3 main
524 results for a dependencys, Now, Install and Candidate. Callers must
525 invert the result if dealing with conflicts. */
526 unsigned char pkgDepCache::DependencyState(DepIterator
&D
)
528 unsigned char State
= 0;
530 if (CheckDep(D
,NowVersion
) == true)
532 if (CheckDep(D
,InstallVersion
) == true)
534 if (CheckDep(D
,CandidateVersion
) == true)
540 // DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
541 // ---------------------------------------------------------------------
542 /* This determines the combined dependency representation of a package
543 for its two states now and install. This is done by using the pre-generated
544 dependency information. */
545 void pkgDepCache::UpdateVerState(PkgIterator Pkg
)
547 // Empty deps are always true
548 StateCache
&State
= PkgState
[Pkg
->ID
];
549 State
.DepState
= 0xFF;
551 // Check the Current state
552 if (Pkg
->CurrentVer
!= 0)
554 DepIterator D
= Pkg
.CurrentVer().DependsList();
555 State
.DepState
&= VersionState(D
,DepNow
,DepNowMin
,DepNowPolicy
);
558 /* Check the candidate state. We do not compare against the whole as
559 a candidate state but check the candidate version against the
561 if (State
.CandidateVer
!= 0)
563 DepIterator D
= State
.CandidateVerIter(*this).DependsList();
564 State
.DepState
&= VersionState(D
,DepInstall
,DepCandMin
,DepCandPolicy
);
567 // Check target state which can only be current or installed
568 if (State
.InstallVer
!= 0)
570 DepIterator D
= State
.InstVerIter(*this).DependsList();
571 State
.DepState
&= VersionState(D
,DepInstall
,DepInstMin
,DepInstPolicy
);
575 // DepCache::Update - Figure out all the state information /*{{{*/
576 // ---------------------------------------------------------------------
577 /* This will figure out the state of all the packages and all the
578 dependencies based on the current policy. */
579 void pkgDepCache::Update(OpProgress
*Prog
)
589 // Perform the depends pass
591 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
593 if (Prog
!= 0 && Done%20
== 0)
594 Prog
->Progress(Done
);
595 for (VerIterator V
= I
.VersionList(); V
.end() != true; V
++)
597 unsigned char Group
= 0;
599 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
601 // Build the dependency state.
602 unsigned char &State
= DepState
[D
->ID
];
603 State
= DependencyState(D
);
605 // Add to the group if we are within an or..
608 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
611 // Invert for Conflicts
612 if (D
->Type
== Dep::Conflicts
||
613 D
->Type
== Dep::DpkgBreaks
||
614 D
->Type
== Dep::Obsoletes
)
619 // Compute the pacakge dependency state and size additions
626 Prog
->Progress(Done
);
631 // DepCache::Update - Update the deps list of a package /*{{{*/
632 // ---------------------------------------------------------------------
633 /* This is a helper for update that only does the dep portion of the scan.
634 It is mainly meant to scan reverse dependencies. */
635 void pkgDepCache::Update(DepIterator D
)
637 // Update the reverse deps
638 for (;D
.end() != true; D
++)
640 unsigned char &State
= DepState
[D
->ID
];
641 State
= DependencyState(D
);
643 // Invert for Conflicts
644 if (D
->Type
== Dep::Conflicts
||
645 D
->Type
== Dep::DpkgBreaks
||
646 D
->Type
== Dep::Obsoletes
)
649 RemoveStates(D
.ParentPkg());
650 BuildGroupOrs(D
.ParentVer());
651 UpdateVerState(D
.ParentPkg());
652 AddStates(D
.ParentPkg());
656 // DepCache::Update - Update the related deps of a package /*{{{*/
657 // ---------------------------------------------------------------------
658 /* This is called whenever the state of a package changes. It updates
659 all cached dependencies related to this package. */
660 void pkgDepCache::Update(PkgIterator
const &Pkg
)
662 // Recompute the dep of the package
667 // Update the reverse deps
668 Update(Pkg
.RevDependsList());
670 // Update the provides map for the current ver
671 if (Pkg
->CurrentVer
!= 0)
672 for (PrvIterator P
= Pkg
.CurrentVer().ProvidesList();
673 P
.end() != true; P
++)
674 Update(P
.ParentPkg().RevDependsList());
676 // Update the provides map for the candidate ver
677 if (PkgState
[Pkg
->ID
].CandidateVer
!= 0)
678 for (PrvIterator P
= PkgState
[Pkg
->ID
].CandidateVerIter(*this).ProvidesList();
679 P
.end() != true; P
++)
680 Update(P
.ParentPkg().RevDependsList());
685 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
686 // ---------------------------------------------------------------------
688 void pkgDepCache::MarkKeep(PkgIterator
const &Pkg
, bool Soft
, bool FromUser
)
690 // Simplifies other routines.
691 if (Pkg
.end() == true)
694 /* Reject an attempt to keep a non-source broken installed package, those
696 if (Pkg
.State() == PkgIterator::NeedsUnpack
&&
697 Pkg
.CurrentVer().Downloadable() == false)
700 /** \todo Can this be moved later in the method? */
701 ActionGroup
group(*this);
703 /* We changed the soft state all the time so the UI is a bit nicer
705 StateCache
&P
= PkgState
[Pkg
->ID
];
707 P
.iFlags
|= AutoKept
;
709 P
.iFlags
&= ~AutoKept
;
711 // Check that it is not already kept
712 if (P
.Mode
== ModeKeep
)
715 // We dont even try to keep virtual packages..
716 if (Pkg
->VersionList
== 0)
719 if(FromUser
&& !P
.Marked
)
720 P
.Flags
&= ~Flag::Auto
;
725 if (Pkg
->CurrentVer
== 0)
728 P
.InstallVer
= Pkg
.CurrentVer();
737 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
738 // ---------------------------------------------------------------------
740 void pkgDepCache::MarkDelete(PkgIterator
const &Pkg
, bool rPurge
)
742 // Simplifies other routines.
743 if (Pkg
.end() == true)
746 ActionGroup
group(*this);
748 // Check that it is not already marked for delete
749 StateCache
&P
= PkgState
[Pkg
->ID
];
750 P
.iFlags
&= ~(AutoKept
| Purge
);
754 if ((P
.Mode
== ModeDelete
|| P
.InstallVer
== 0) &&
755 (Pkg
.Purge() == true || rPurge
== false))
758 // We dont even try to delete virtual packages..
759 if (Pkg
->VersionList
== 0)
765 if (Pkg
->CurrentVer
== 0 && (Pkg
.Purge() == true || rPurge
== false))
776 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
777 // ---------------------------------------------------------------------
779 void pkgDepCache::MarkInstall(PkgIterator
const &Pkg
,bool AutoInst
,
780 unsigned long Depth
, bool FromUser
,
781 bool ForceImportantDeps
)
786 // Simplifies other routines.
787 if (Pkg
.end() == true)
790 ActionGroup
group(*this);
792 /* Check that it is not already marked for install and that it can be
794 StateCache
&P
= PkgState
[Pkg
->ID
];
795 P
.iFlags
&= ~AutoKept
;
796 if ((P
.InstPolicyBroken() == false && P
.InstBroken() == false) &&
797 (P
.Mode
== ModeInstall
||
798 P
.CandidateVer
== (Version
*)Pkg
.CurrentVer()))
800 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer() && P
.InstallVer
== 0)
801 MarkKeep(Pkg
, false, FromUser
);
805 // See if there is even any possible instalation candidate
806 if (P
.CandidateVer
== 0)
808 // We dont even try to install virtual packages..
809 if (Pkg
->VersionList
== 0)
811 /* Target the candidate version and remove the autoflag. We reset the
812 autoflag below if this was called recursively. Otherwise the user
813 should have the ability to de-auto a package by changing its state */
817 P
.Mode
= ModeInstall
;
818 P
.InstallVer
= P
.CandidateVer
;
822 // Set it to manual if it's a new install or cancelling the
823 // removal of a garbage package.
824 if(P
.Status
== 2 || (!Pkg
.CurrentVer().end() && !P
.Marked
))
825 P
.Flags
&= ~Flag::Auto
;
829 // Set it to auto if this is a new install.
831 P
.Flags
|= Flag::Auto
;
833 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer())
840 if (AutoInst
== false)
843 DepIterator Dep
= P
.InstVerIter(*this).DependsList();
844 for (; Dep
.end() != true;)
847 DepIterator Start
= Dep
;
850 for (bool LastOR
= true; Dep
.end() == false && LastOR
== true; Dep
++,Ors
++)
852 LastOR
= (Dep
->CompareOp
& Dep::Or
) == Dep::Or
;
854 if ((DepState
[Dep
->ID
] & DepInstall
) == DepInstall
)
858 // Dep is satisfied okay.
862 /* Check if this dep should be consider for install. If it is a user
863 defined important dep and we are installed a new package then
864 it will be installed. Otherwise we only check for important
865 deps that have changed from the installed version
867 if (IsImportantDep(Start
) == false)
870 /* check if any ImportantDep() (but not Critial) where added
871 * since we installed the package
873 bool isNewImportantDep
= false;
874 if(!ForceImportantDeps
&& !Start
.IsCritical())
877 VerIterator instVer
= Pkg
.CurrentVer();
880 for (DepIterator D
= instVer
.DependsList(); D
.end() != true; D
++)
882 //FIXME: deal better with or-groups(?)
883 DepIterator LocalStart
= D
;
885 if(IsImportantDep(D
) && Start
.TargetPkg() == D
.TargetPkg())
888 // this is a new dep if it was not found to be already
889 // a important dep of the installed pacakge
890 isNewImportantDep
= !found
;
893 if(isNewImportantDep
)
894 if(_config
->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
895 std::clog
<< "new important dependency: "
896 << Start
.TargetPkg().Name() << std::endl
;
898 // skip important deps if the package is already installed
899 if (Pkg
->CurrentVer
!= 0 && Start
.IsCritical() == false
900 && !isNewImportantDep
&& !ForceImportantDeps
)
903 /* If we are in an or group locate the first or that can
904 succeed. We have already cached this.. */
905 for (; Ors
> 1 && (DepState
[Start
->ID
] & DepCVer
) != DepCVer
; Ors
--)
908 /* This bit is for processing the possibilty of an install/upgrade
909 fixing the problem */
910 SPtrArray
<Version
*> List
= Start
.AllTargets();
911 if (Start
->Type
!= Dep::DpkgBreaks
&&
912 (DepState
[Start
->ID
] & DepCVer
) == DepCVer
)
914 // Right, find the best version to install..
915 Version
**Cur
= List
;
916 PkgIterator P
= Start
.TargetPkg();
917 PkgIterator
InstPkg(*Cache
,0);
919 // See if there are direct matches (at the start of the list)
920 for (; *Cur
!= 0 && (*Cur
)->ParentPkg
== P
.Index(); Cur
++)
922 PkgIterator
Pkg(*Cache
,Cache
->PkgP
+ (*Cur
)->ParentPkg
);
923 if (PkgState
[Pkg
->ID
].CandidateVer
!= *Cur
)
929 // Select the highest priority providing package
930 if (InstPkg
.end() == true)
932 pkgPrioSortList(*Cache
,Cur
);
933 for (; *Cur
!= 0; Cur
++)
935 PkgIterator
Pkg(*Cache
,Cache
->PkgP
+ (*Cur
)->ParentPkg
);
936 if (PkgState
[Pkg
->ID
].CandidateVer
!= *Cur
)
943 if (InstPkg
.end() == false)
945 if(_config
->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
946 std::clog
<< "Installing " << InstPkg
.Name()
947 << " as dep of " << Pkg
.Name()
949 MarkInstall(InstPkg
,true,Depth
+ 1, false, ForceImportantDeps
);
951 // Set the autoflag, after MarkInstall because MarkInstall unsets it
952 if (P
->CurrentVer
== 0)
953 PkgState
[InstPkg
->ID
].Flags
|= Flag::Auto
;
958 /* For conflicts we just de-install the package and mark as auto,
959 Conflicts may not have or groups. For dpkg's Breaks we try to
960 upgrade the package. */
961 if (Start
->Type
== Dep::Conflicts
|| Start
->Type
== Dep::Obsoletes
||
962 Start
->Type
== Dep::DpkgBreaks
)
964 for (Version
**I
= List
; *I
!= 0; I
++)
966 VerIterator
Ver(*this,*I
);
967 PkgIterator Pkg
= Ver
.ParentPkg();
969 if (Start
->Type
!= Dep::DpkgBreaks
)
972 if (PkgState
[Pkg
->ID
].CandidateVer
!= *I
)
973 MarkInstall(Pkg
,true,Depth
+ 1, false, ForceImportantDeps
);
980 // DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
981 // ---------------------------------------------------------------------
983 void pkgDepCache::SetReInstall(PkgIterator
const &Pkg
,bool To
)
985 ActionGroup
group(*this);
990 StateCache
&P
= PkgState
[Pkg
->ID
];
992 P
.iFlags
|= ReInstall
;
994 P
.iFlags
&= ~ReInstall
;
1000 // DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
1001 // ---------------------------------------------------------------------
1003 void pkgDepCache::SetCandidateVersion(VerIterator TargetVer
)
1005 ActionGroup
group(*this);
1007 pkgCache::PkgIterator Pkg
= TargetVer
.ParentPkg();
1008 StateCache
&P
= PkgState
[Pkg
->ID
];
1013 if (P
.CandidateVer
== P
.InstallVer
)
1014 P
.InstallVer
= (Version
*)TargetVer
;
1015 P
.CandidateVer
= (Version
*)TargetVer
;
1016 P
.Update(Pkg
,*this);
1023 void pkgDepCache::MarkAuto(const PkgIterator
&Pkg
, bool Auto
)
1025 StateCache
&state
= PkgState
[Pkg
->ID
];
1027 ActionGroup
group(*this);
1030 state
.Flags
|= Flag::Auto
;
1032 state
.Flags
&= ~Flag::Auto
;
1035 // StateCache::Update - Compute the various static display things /*{{{*/
1036 // ---------------------------------------------------------------------
1037 /* This is called whenever the Candidate version changes. */
1038 void pkgDepCache::StateCache::Update(PkgIterator Pkg
,pkgCache
&Cache
)
1041 VerIterator Ver
= CandidateVerIter(Cache
);
1043 // Use a null string or the version string
1044 if (Ver
.end() == true)
1047 CandVersion
= Ver
.VerStr();
1049 // Find the current version
1051 if (Pkg
->CurrentVer
!= 0)
1052 CurVersion
= Pkg
.CurrentVer().VerStr();
1054 // Strip off the epochs for display
1055 CurVersion
= StripEpoch(CurVersion
);
1056 CandVersion
= StripEpoch(CandVersion
);
1058 // Figure out if its up or down or equal
1059 Status
= Ver
.CompareVer(Pkg
.CurrentVer());
1060 if (Pkg
->CurrentVer
== 0 || Pkg
->VersionList
== 0 || CandidateVer
== 0)
1064 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
1065 // ---------------------------------------------------------------------
1067 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver
)
1073 for (const char *I
= Ver
; *I
!= 0; I
++)
1080 // Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/
1081 // ---------------------------------------------------------------------
1082 /* The default just returns the highest available version that is not
1083 a source and automatic. */
1084 pkgCache::VerIterator
pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg
)
1086 /* Not source/not automatic versions cannot be a candidate version
1087 unless they are already installed */
1088 VerIterator
Last(*(pkgCache
*)this,0);
1090 for (VerIterator I
= Pkg
.VersionList(); I
.end() == false; I
++)
1092 if (Pkg
.CurrentVer() == I
)
1095 for (VerFileIterator J
= I
.FileList(); J
.end() == false; J
++)
1097 if ((J
.File()->Flags
& Flag::NotSource
) != 0)
1100 /* Stash the highest version of a not-automatic source, we use it
1101 if there is nothing better */
1102 if ((J
.File()->Flags
& Flag::NotAutomatic
) != 0)
1104 if (Last
.end() == true)
1118 pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
1119 : constructedSuccessfully(false)
1121 Configuration::Item
const *Opts
;
1122 Opts
= _config
->Tree("APT::NeverAutoRemove");
1123 if (Opts
!= 0 && Opts
->Child
!= 0)
1126 for (; Opts
!= 0; Opts
= Opts
->Next
)
1128 if (Opts
->Value
.empty() == true)
1131 regex_t
*p
= new regex_t
;
1132 if(regcomp(p
,Opts
->Value
.c_str(),
1133 REG_EXTENDED
| REG_ICASE
| REG_NOSUB
) != 0)
1137 _error
->Error("Regex compilation error for APT::NeverAutoRemove");
1141 rootSetRegexp
.push_back(p
);
1145 constructedSuccessfully
= true;
1148 pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
1150 for(unsigned int i
= 0; i
< rootSetRegexp
.size(); i
++)
1152 regfree(rootSetRegexp
[i
]);
1153 delete rootSetRegexp
[i
];
1158 bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator
&pkg
)
1160 for(unsigned int i
= 0; i
< rootSetRegexp
.size(); i
++)
1161 if (regexec(rootSetRegexp
[i
], pkg
.Name(), 0, 0, 0) == 0)
1167 pkgDepCache::InRootSetFunc
*pkgDepCache::GetRootSetFunc()
1169 DefaultRootSetFunc
*f
= new DefaultRootSetFunc
;
1170 if(f
->wasConstructedSuccessfully())
1179 bool pkgDepCache::MarkFollowsRecommends()
1181 return _config
->FindB("APT::AutoRemove::RecommendsImportant", true);
1184 bool pkgDepCache::MarkFollowsSuggests()
1186 return _config
->FindB("APT::AutoRemove::SuggestsImportant", false);
1189 // the main mark algorithm
1190 bool pkgDepCache::MarkRequired(InRootSetFunc
&userFunc
)
1192 bool follow_recommends
;
1193 bool follow_suggests
;
1196 for(PkgIterator p
= PkgBegin(); !p
.end(); ++p
)
1198 PkgState
[p
->ID
].Marked
= false;
1199 PkgState
[p
->ID
].Garbage
= false;
1202 if(_config
->FindB("Debug::pkgAutoRemove",false)
1203 && PkgState
[p
->ID
].Flags
& Flag::Auto
)
1204 std::clog
<< "AutoDep: " << p
.Name() << std::endl
;
1208 follow_recommends
= MarkFollowsRecommends();
1209 follow_suggests
= MarkFollowsSuggests();
1213 // do the mark part, this is the core bit of the algorithm
1214 for(PkgIterator p
= PkgBegin(); !p
.end(); ++p
)
1216 if(!(PkgState
[p
->ID
].Flags
& Flag::Auto
) ||
1217 (p
->Flags
& Flag::Essential
) ||
1218 userFunc
.InRootSet(p
))
1221 // the package is installed (and set to keep)
1222 if(PkgState
[p
->ID
].Keep() && !p
.CurrentVer().end())
1223 MarkPackage(p
, p
.CurrentVer(),
1224 follow_recommends
, follow_suggests
);
1225 // the package is to be installed
1226 else if(PkgState
[p
->ID
].Install())
1227 MarkPackage(p
, PkgState
[p
->ID
].InstVerIter(*this),
1228 follow_recommends
, follow_suggests
);
1235 // mark a single package in Mark-and-Sweep
1236 void pkgDepCache::MarkPackage(const pkgCache::PkgIterator
&pkg
,
1237 const pkgCache::VerIterator
&ver
,
1238 bool follow_recommends
,
1239 bool follow_suggests
)
1241 pkgDepCache::StateCache
&state
= PkgState
[pkg
->ID
];
1242 VerIterator candver
= state
.CandidateVerIter(*this);
1243 VerIterator instver
= state
.InstVerIter(*this);
1246 // If a package was garbage-collected but is now being marked, we
1247 // should re-select it
1248 // For cases when a pkg is set to upgrade and this trigger the
1249 // removal of a no-longer used dependency. if the pkg is set to
1250 // keep again later it will result in broken deps
1251 if(state
.Delete() && state
.RemoveReason
= Unused
)
1254 mark_install(pkg
, false, false, NULL
);
1255 else if(ver
==pkg
.CurrentVer())
1256 MarkKeep(pkg
, false, false);
1258 instver
=state
.InstVerIter(*this);
1262 // Ignore versions other than the InstVer, and ignore packages
1263 // that are already going to be removed or just left uninstalled.
1264 if(!(ver
== instver
&& !instver
.end()))
1267 // if we are marked already we are done
1271 //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
1276 for(DepIterator d
= ver
.DependsList(); !d
.end(); ++d
)
1278 if(d
->Type
== Dep::Depends
||
1279 d
->Type
== Dep::PreDepends
||
1280 (follow_recommends
&&
1281 d
->Type
== Dep::Recommends
) ||
1283 d
->Type
== Dep::Suggests
))
1285 // Try all versions of this package.
1286 for(VerIterator V
= d
.TargetPkg().VersionList();
1289 if(_system
->VS
->CheckDep(V
.VerStr(), d
->CompareOp
, d
.TargetVer()))
1291 MarkPackage(V
.ParentPkg(), V
,
1292 follow_recommends
, follow_suggests
);
1295 // Now try virtual packages
1296 for(PrvIterator prv
=d
.TargetPkg().ProvidesList();
1299 if(_system
->VS
->CheckDep(prv
.ProvideVersion(), d
->CompareOp
,
1302 MarkPackage(prv
.OwnerPkg(), prv
.OwnerVer(),
1303 follow_recommends
, follow_suggests
);
1311 bool pkgDepCache::Sweep()
1314 for(PkgIterator p
=PkgBegin(); !p
.end(); ++p
)
1316 StateCache
&state
=PkgState
[p
->ID
];
1318 // if it is not marked and it is installed, it's garbage
1319 if(!state
.Marked
&& (!p
.CurrentVer().end() || state
.Install()) &&
1323 if(_config
->FindB("Debug::pkgAutoRemove",false))
1324 std::cout
<< "Garbage: " << p
.Name() << std::endl
;
1331 // Policy::IsImportantDep - True if the dependency is important /*{{{*/
1332 // ---------------------------------------------------------------------
1334 bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep
)
1336 if(Dep
.IsCritical())
1338 else if(Dep
->Type
== pkgCache::Dep::Recommends
)
1340 if ( _config
->FindB("APT::Install-Recommends", false))
1342 // we suport a special mode to only install-recommends for certain
1344 // FIXME: this is a meant as a temporarly solution until the
1345 // recommends are cleaned up
1346 string s
= _config
->Find("APT::Install-Recommends-Section","");
1349 const char *sec
= Dep
.ParentVer().Section();
1350 if (sec
&& strcmp(sec
, s
.c_str()) == 0)
1354 else if(Dep
->Type
== pkgCache::Dep::Suggests
)
1355 return _config
->FindB("APT::Install-Suggests", false);