]>
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>
33 pkgDepCache::ActionGroup::ActionGroup(pkgDepCache
&cache
) :
34 cache(cache
), released(false)
39 void pkgDepCache::ActionGroup::release()
43 if(cache
.group_level
== 0)
44 std::cerr
<< "W: Unbalanced action groups, expect badness" << std::endl
;
49 if(cache
.group_level
== 0)
57 pkgDepCache::ActionGroup::~ActionGroup()
62 // DepCache::pkgDepCache - Constructors /*{{{*/
63 // ---------------------------------------------------------------------
65 pkgDepCache::pkgDepCache(pkgCache
*pCache
,Policy
*Plcy
) :
66 group_level(0), Cache(pCache
), PkgState(0), DepState(0)
71 delLocalPolicy
= LocalPolicy
= new Policy
;
74 // DepCache::~pkgDepCache - Destructor /*{{{*/
75 // ---------------------------------------------------------------------
77 pkgDepCache::~pkgDepCache()
81 delete delLocalPolicy
;
84 // DepCache::Init - Generate the initial extra structures. /*{{{*/
85 // ---------------------------------------------------------------------
86 /* This allocats the extension buffers and initializes them. */
87 bool pkgDepCache::Init(OpProgress
*Prog
)
89 // Suppress mark updates during this operation (just in case) and
90 // run a mark operation when Init terminates.
91 ActionGroup
actions(*this);
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
);
102 Prog
->OverallProgress(0,2*Head().PackageCount
,Head().PackageCount
,
103 _("Building dependency tree"));
104 Prog
->SubProgress(Head().PackageCount
,_("Candidate versions"));
107 /* Set the current state of everything. In this state all of the
108 packages are kept exactly as is. See AllUpgrade */
110 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
113 Prog
->Progress(Done
);
115 // Find the proper cache slot
116 StateCache
&State
= PkgState
[I
->ID
];
119 // Figure out the install version
120 State
.CandidateVer
= GetCandidateVer(I
);
121 State
.InstallVer
= I
.CurrentVer();
122 State
.Mode
= ModeKeep
;
124 State
.Update(I
,*this);
130 Prog
->OverallProgress(Head().PackageCount
,2*Head().PackageCount
,
132 _("Building dependency tree"));
133 Prog
->SubProgress(Head().PackageCount
,_("Dependency generation"));
145 bool pkgDepCache::readStateFile(OpProgress
*Prog
)
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();
153 Prog
->OverallProgress(0, file_size
, 1,
154 _("Reading state information"));
156 pkgTagFile
tagfile(&state_file
);
157 pkgTagSection section
;
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
164 if(!pkg
.end() && !pkg
.VersionList().end()) {
165 short reason
= section
.FindI("Auto-Installed", 0);
167 PkgState
[pkg
->ID
].Flags
|= Flag::Auto
;
168 if(_config
->FindB("Debug::pkgAutoRemove",false))
169 std::cout
<< "Auto-Installed : " << pkgname
<< std::endl
;
172 Prog
->OverallProgress(amt
, file_size
, 1,
173 _("Reading state information"));
176 Prog
->OverallProgress(file_size
, file_size
, 1,
177 _("Reading state information"));
184 bool pkgDepCache::writeStateFile(OpProgress
*prog
)
186 if(_config
->FindB("Debug::pkgAutoRemove",false))
187 std::clog
<< "pkgDepCache::writeStateFile()" << std::endl
;
190 string state
= _config
->FindDir("Dir::State") + "extended_states";
192 // if it does not exist, create a empty one
193 if(!FileExists(state
))
195 StateFile
.Open(state
, FileFd::WriteEmpty
);
200 if(!StateFile
.Open(state
, FileFd::ReadOnly
))
201 return _error
->Error(_("Failed to open StateFile %s"),
205 string outfile
= state
+ ".tmp";
206 if((OutFile
= fopen(outfile
.c_str(),"w")) == NULL
)
207 return _error
->Error(_("Failed to write temporary StateFile %s"),
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
219 pkgCache::PkgIterator pkg
=Cache
->FindPkg(pkgname
);
220 if(pkg
.end() || pkg
.VersionList().end())
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;
232 TFRewrite(OutFile
, section
, nullreorderlist
, rewrite
);
233 fprintf(OutFile
,"\n");
234 pkgs_seen
.insert(pkgname
);
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
;
246 if(_config
->FindB("Debug::pkgAutoRemove",false))
247 std::clog
<< "Writing new AutoInstall: "
248 << pkg
.Name() << std::endl
;
249 ostr
.str(string(""));
250 ostr
<< "Package: " << pkg
.Name()
251 << "\nAuto-Installed: 1\n\n";
252 fprintf(OutFile
,ostr
.str().c_str());
253 fprintf(OutFile
,"\n");
258 // move the outfile over the real file and set permissions
259 rename(outfile
.c_str(), state
.c_str());
260 chmod(state
.c_str(), 0644);
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::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
&& Dep
->Type
== Dep::Conflicts
)
312 // Check if the provides is a hit
313 if (Type
== NowVersion
)
315 if (P
.OwnerPkg().CurrentVer() != P
.OwnerVer())
319 if (Type
== InstallVersion
)
321 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
322 if (State
.InstallVer
!= (Version
*)P
.OwnerVer())
326 if (Type
== CandidateVersion
)
328 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
329 if (State
.CandidateVer
!= (Version
*)P
.OwnerVer())
333 // Compare the versions.
334 if (VS().CheckDep(P
.ProvideVersion(),Dep
->CompareOp
,Dep
.TargetVer()) == true)
344 // DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
345 // ---------------------------------------------------------------------
346 /* Call with Mult = -1 to preform the inverse opration */
347 void pkgDepCache::AddSizes(const PkgIterator
&Pkg
,signed long Mult
)
349 StateCache
&P
= PkgState
[Pkg
->ID
];
351 if (Pkg
->VersionList
== 0)
354 if (Pkg
.State() == pkgCache::PkgIterator::NeedsConfigure
&&
358 // Compute the size data
359 if (P
.NewInstall() == true)
361 iUsrSize
+= (signed)(Mult
*P
.InstVerIter(*this)->InstalledSize
);
362 iDownloadSize
+= (signed)(Mult
*P
.InstVerIter(*this)->Size
);
367 if (Pkg
->CurrentVer
!= 0 &&
368 (P
.InstallVer
!= (Version
*)Pkg
.CurrentVer() ||
369 (P
.iFlags
& ReInstall
) == ReInstall
) && P
.InstallVer
!= 0)
371 iUsrSize
+= (signed)(Mult
*((signed)P
.InstVerIter(*this)->InstalledSize
-
372 (signed)Pkg
.CurrentVer()->InstalledSize
));
373 iDownloadSize
+= (signed)(Mult
*P
.InstVerIter(*this)->Size
);
378 if (Pkg
.State() == pkgCache::PkgIterator::NeedsUnpack
&&
381 iDownloadSize
+= (signed)(Mult
*P
.InstVerIter(*this)->Size
);
386 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
== 0)
388 iUsrSize
-= (signed)(Mult
*Pkg
.CurrentVer()->InstalledSize
);
393 // DepCache::AddStates - Add the package to the state counter /*{{{*/
394 // ---------------------------------------------------------------------
395 /* This routine is tricky to use, you must make sure that it is never
396 called twice for the same package. This means the Remove/Add section
397 should be as short as possible and not encompass any code that will
398 calld Remove/Add itself. Remember, dependencies can be circular so
399 while processing a dep for Pkg it is possible that Add/Remove
400 will be called on Pkg */
401 void pkgDepCache::AddStates(const PkgIterator
&Pkg
,int Add
)
403 StateCache
&State
= PkgState
[Pkg
->ID
];
405 // The Package is broken
406 if ((State
.DepState
& DepInstMin
) != DepInstMin
)
410 if (Pkg
.State() != PkgIterator::NeedsNothing
)
414 if (Pkg
->CurrentVer
== 0)
416 if (State
.Mode
== ModeDelete
&&
417 (State
.iFlags
| Purge
) == Purge
&& Pkg
.Purge() == false)
420 if (State
.Mode
== ModeInstall
)
425 // Installed, no upgrade
426 if (State
.Status
== 0)
428 if (State
.Mode
== ModeDelete
)
431 if ((State
.iFlags
& ReInstall
) == ReInstall
)
437 // Alll 3 are possible
438 if (State
.Mode
== ModeDelete
)
440 if (State
.Mode
== ModeKeep
)
442 if (State
.Mode
== ModeInstall
)
446 // DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
447 // ---------------------------------------------------------------------
448 /* The or group results are stored in the last item of the or group. This
449 allows easy detection of the state of a whole or'd group. */
450 void pkgDepCache::BuildGroupOrs(VerIterator
const &V
)
452 unsigned char Group
= 0;
454 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
456 // Build the dependency state.
457 unsigned char &State
= DepState
[D
->ID
];
459 /* Invert for Conflicts. We have to do this twice to get the
460 right sense for a conflicts group */
461 if (D
->Type
== Dep::Conflicts
|| D
->Type
== Dep::Obsoletes
)
464 // Add to the group if we are within an or..
468 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
471 // Invert for Conflicts
472 if (D
->Type
== Dep::Conflicts
|| D
->Type
== Dep::Obsoletes
)
477 // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
478 // ---------------------------------------------------------------------
479 /* This is used to run over a dependency list and determine the dep
480 state of the list, filtering it through both a Min check and a Policy
481 check. The return result will have SetMin/SetPolicy low if a check
482 fails. It uses the DepState cache for it's computations. */
483 unsigned char pkgDepCache::VersionState(DepIterator D
,unsigned char Check
,
484 unsigned char SetMin
,
485 unsigned char SetPolicy
)
487 unsigned char Dep
= 0xFF;
489 while (D
.end() != true)
491 // Compute a single dependency element (glob or)
492 DepIterator Start
= D
;
493 unsigned char State
= 0;
494 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
496 State
|= DepState
[D
->ID
];
497 LastOR
= (D
->CompareOp
& Dep::Or
) == Dep::Or
;
500 // Minimum deps that must be satisfied to have a working package
501 if (Start
.IsCritical() == true)
502 if ((State
& Check
) != Check
)
505 // Policy deps that must be satisfied to install the package
506 if (IsImportantDep(Start
) == true &&
507 (State
& Check
) != Check
)
514 // DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
515 // ---------------------------------------------------------------------
516 /* This is the main dependency computation bit. It computes the 3 main
517 results for a dependencys, Now, Install and Candidate. Callers must
518 invert the result if dealing with conflicts. */
519 unsigned char pkgDepCache::DependencyState(DepIterator
&D
)
521 unsigned char State
= 0;
523 if (CheckDep(D
,NowVersion
) == true)
525 if (CheckDep(D
,InstallVersion
) == true)
527 if (CheckDep(D
,CandidateVersion
) == true)
533 // DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
534 // ---------------------------------------------------------------------
535 /* This determines the combined dependency representation of a package
536 for its two states now and install. This is done by using the pre-generated
537 dependency information. */
538 void pkgDepCache::UpdateVerState(PkgIterator Pkg
)
540 // Empty deps are always true
541 StateCache
&State
= PkgState
[Pkg
->ID
];
542 State
.DepState
= 0xFF;
544 // Check the Current state
545 if (Pkg
->CurrentVer
!= 0)
547 DepIterator D
= Pkg
.CurrentVer().DependsList();
548 State
.DepState
&= VersionState(D
,DepNow
,DepNowMin
,DepNowPolicy
);
551 /* Check the candidate state. We do not compare against the whole as
552 a candidate state but check the candidate version against the
554 if (State
.CandidateVer
!= 0)
556 DepIterator D
= State
.CandidateVerIter(*this).DependsList();
557 State
.DepState
&= VersionState(D
,DepInstall
,DepCandMin
,DepCandPolicy
);
560 // Check target state which can only be current or installed
561 if (State
.InstallVer
!= 0)
563 DepIterator D
= State
.InstVerIter(*this).DependsList();
564 State
.DepState
&= VersionState(D
,DepInstall
,DepInstMin
,DepInstPolicy
);
568 // DepCache::Update - Figure out all the state information /*{{{*/
569 // ---------------------------------------------------------------------
570 /* This will figure out the state of all the packages and all the
571 dependencies based on the current policy. */
572 void pkgDepCache::Update(OpProgress
*Prog
)
582 // Perform the depends pass
584 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
586 if (Prog
!= 0 && Done%20
== 0)
587 Prog
->Progress(Done
);
588 for (VerIterator V
= I
.VersionList(); V
.end() != true; V
++)
590 unsigned char Group
= 0;
592 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
594 // Build the dependency state.
595 unsigned char &State
= DepState
[D
->ID
];
596 State
= DependencyState(D
);
598 // Add to the group if we are within an or..
601 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
604 // Invert for Conflicts
605 if (D
->Type
== Dep::Conflicts
|| D
->Type
== Dep::Obsoletes
)
610 // Compute the pacakge dependency state and size additions
617 Prog
->Progress(Done
);
622 // DepCache::Update - Update the deps list of a package /*{{{*/
623 // ---------------------------------------------------------------------
624 /* This is a helper for update that only does the dep portion of the scan.
625 It is mainly meant to scan reverse dependencies. */
626 void pkgDepCache::Update(DepIterator D
)
628 // Update the reverse deps
629 for (;D
.end() != true; D
++)
631 unsigned char &State
= DepState
[D
->ID
];
632 State
= DependencyState(D
);
634 // Invert for Conflicts
635 if (D
->Type
== Dep::Conflicts
|| D
->Type
== Dep::Obsoletes
)
638 RemoveStates(D
.ParentPkg());
639 BuildGroupOrs(D
.ParentVer());
640 UpdateVerState(D
.ParentPkg());
641 AddStates(D
.ParentPkg());
645 // DepCache::Update - Update the related deps of a package /*{{{*/
646 // ---------------------------------------------------------------------
647 /* This is called whenever the state of a package changes. It updates
648 all cached dependencies related to this package. */
649 void pkgDepCache::Update(PkgIterator
const &Pkg
)
651 // Recompute the dep of the package
656 // Update the reverse deps
657 Update(Pkg
.RevDependsList());
659 // Update the provides map for the current ver
660 if (Pkg
->CurrentVer
!= 0)
661 for (PrvIterator P
= Pkg
.CurrentVer().ProvidesList();
662 P
.end() != true; P
++)
663 Update(P
.ParentPkg().RevDependsList());
665 // Update the provides map for the candidate ver
666 if (PkgState
[Pkg
->ID
].CandidateVer
!= 0)
667 for (PrvIterator P
= PkgState
[Pkg
->ID
].CandidateVerIter(*this).ProvidesList();
668 P
.end() != true; P
++)
669 Update(P
.ParentPkg().RevDependsList());
674 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
675 // ---------------------------------------------------------------------
677 void pkgDepCache::MarkKeep(PkgIterator
const &Pkg
, bool Soft
, bool FromUser
)
679 // Simplifies other routines.
680 if (Pkg
.end() == true)
683 /* Reject an attempt to keep a non-source broken installed package, those
685 if (Pkg
.State() == PkgIterator::NeedsUnpack
&&
686 Pkg
.CurrentVer().Downloadable() == false)
689 /** \todo Can this be moved later in the method? */
690 ActionGroup
group(*this);
692 /* We changed the soft state all the time so the UI is a bit nicer
694 StateCache
&P
= PkgState
[Pkg
->ID
];
696 P
.iFlags
|= AutoKept
;
698 P
.iFlags
&= ~AutoKept
;
700 // Check that it is not already kept
701 if (P
.Mode
== ModeKeep
)
704 // We dont even try to keep virtual packages..
705 if (Pkg
->VersionList
== 0)
708 #if 0 // reseting the autoflag here means we lose the
709 // auto-mark information if a user selects a package for removal
710 // but changes his mind then and sets it for keep again
711 // - this makes sense as default when all Garbage dependencies
712 // are automatically marked for removal (as aptitude does).
713 // setting a package for keep then makes it no longer autoinstalled
714 // for all other use-case this action is rather suprising
715 if(FromUser
&& !P
.Marked
)
716 P
.Flags
&= ~Flag::Auto
;
723 if (Pkg
->CurrentVer
== 0)
726 P
.InstallVer
= Pkg
.CurrentVer();
735 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
736 // ---------------------------------------------------------------------
738 void pkgDepCache::MarkDelete(PkgIterator
const &Pkg
, bool rPurge
)
740 // Simplifies other routines.
741 if (Pkg
.end() == true)
744 ActionGroup
group(*this);
746 // Check that it is not already marked for delete
747 StateCache
&P
= PkgState
[Pkg
->ID
];
748 P
.iFlags
&= ~(AutoKept
| Purge
);
752 if ((P
.Mode
== ModeDelete
|| P
.InstallVer
== 0) &&
753 (Pkg
.Purge() == true || rPurge
== false))
756 // We dont even try to delete virtual packages..
757 if (Pkg
->VersionList
== 0)
763 if (Pkg
->CurrentVer
== 0 && (Pkg
.Purge() == true || rPurge
== false))
774 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
775 // ---------------------------------------------------------------------
777 void pkgDepCache::MarkInstall(PkgIterator
const &Pkg
,bool AutoInst
,
778 unsigned long Depth
, bool FromUser
)
783 // Simplifies other routines.
784 if (Pkg
.end() == true)
787 ActionGroup
group(*this);
789 /* Check that it is not already marked for install and that it can be
791 StateCache
&P
= PkgState
[Pkg
->ID
];
792 P
.iFlags
&= ~AutoKept
;
793 if (P
.InstBroken() == false && (P
.Mode
== ModeInstall
||
794 P
.CandidateVer
== (Version
*)Pkg
.CurrentVer()))
796 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer() && P
.InstallVer
== 0)
797 MarkKeep(Pkg
, false, FromUser
);
801 // See if there is even any possible instalation candidate
802 if (P
.CandidateVer
== 0)
805 // We dont even try to install virtual packages..
806 if (Pkg
->VersionList
== 0)
809 /* Target the candidate version and remove the autoflag. We reset the
810 autoflag below if this was called recursively. Otherwise the user
811 should have the ability to de-auto a package by changing its state */
815 P
.Mode
= ModeInstall
;
816 P
.InstallVer
= P
.CandidateVer
;
820 // Set it to manual if it's a new install or cancelling the
821 // removal of a garbage package.
822 if(P
.Status
== 2 || (!Pkg
.CurrentVer().end() && !P
.Marked
))
823 P
.Flags
&= ~Flag::Auto
;
827 // Set it to auto if this is a new install.
829 P
.Flags
|= Flag::Auto
;
831 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer())
838 if (AutoInst
== false)
841 DepIterator Dep
= P
.InstVerIter(*this).DependsList();
842 for (; Dep
.end() != true;)
845 DepIterator Start
= Dep
;
848 for (bool LastOR
= true; Dep
.end() == false && LastOR
== true; Dep
++,Ors
++)
850 LastOR
= (Dep
->CompareOp
& Dep::Or
) == Dep::Or
;
852 if ((DepState
[Dep
->ID
] & DepInstall
) == DepInstall
)
856 // Dep is satisfied okay.
860 /* Check if this dep should be consider for install. If it is a user
861 defined important dep and we are installed a new package then
862 it will be installed. Otherwise we only worry about critical deps */
863 if (IsImportantDep(Start
) == false)
865 if (Pkg
->CurrentVer
!= 0 && Start
.IsCritical() == false)
868 /* If we are in an or group locate the first or that can
869 succeed. We have already cached this.. */
870 for (; Ors
> 1 && (DepState
[Start
->ID
] & DepCVer
) != DepCVer
; Ors
--)
873 /* This bit is for processing the possibilty of an install/upgrade
874 fixing the problem */
875 SPtrArray
<Version
*> List
= Start
.AllTargets();
876 if ((DepState
[Start
->ID
] & DepCVer
) == DepCVer
)
878 // Right, find the best version to install..
879 Version
**Cur
= List
;
880 PkgIterator P
= Start
.TargetPkg();
881 PkgIterator
InstPkg(*Cache
,0);
883 // See if there are direct matches (at the start of the list)
884 for (; *Cur
!= 0 && (*Cur
)->ParentPkg
== P
.Index(); Cur
++)
886 PkgIterator
Pkg(*Cache
,Cache
->PkgP
+ (*Cur
)->ParentPkg
);
887 if (PkgState
[Pkg
->ID
].CandidateVer
!= *Cur
)
893 // Select the highest priority providing package
894 if (InstPkg
.end() == true)
896 pkgPrioSortList(*Cache
,Cur
);
897 for (; *Cur
!= 0; Cur
++)
899 PkgIterator
Pkg(*Cache
,Cache
->PkgP
+ (*Cur
)->ParentPkg
);
900 if (PkgState
[Pkg
->ID
].CandidateVer
!= *Cur
)
907 if (InstPkg
.end() == false)
909 if(_config
->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
910 std::clog
<< "Installing " << InstPkg
.Name()
911 << " as dep of " << Pkg
.Name()
913 // now check if we should consider it a automatic dependency or not
914 string sec
= _config
->Find("APT::Never-MarkAuto-Section","");
915 if(Pkg
.Section() && (string(Pkg
.Section()) == sec
))
917 if(_config
->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
918 std::clog
<< "Setting NOT as auto-installed because its a direct dep of a package in section " << sec
<< std::endl
;
919 MarkInstall(InstPkg
,true,Depth
+ 1, true);
923 // mark automatic dependency
924 MarkInstall(InstPkg
,true,Depth
+ 1, false);
925 // Set the autoflag, after MarkInstall because MarkInstall unsets it
926 if (P
->CurrentVer
== 0)
927 PkgState
[InstPkg
->ID
].Flags
|= Flag::Auto
;
933 /* For conflicts we just de-install the package and mark as auto,
934 Conflicts may not have or groups */
935 if (Start
->Type
== Dep::Conflicts
|| Start
->Type
== Dep::Obsoletes
)
937 for (Version
**I
= List
; *I
!= 0; I
++)
939 VerIterator
Ver(*this,*I
);
940 PkgIterator Pkg
= Ver
.ParentPkg();
949 // DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
950 // ---------------------------------------------------------------------
952 void pkgDepCache::SetReInstall(PkgIterator
const &Pkg
,bool To
)
954 ActionGroup
group(*this);
959 StateCache
&P
= PkgState
[Pkg
->ID
];
961 P
.iFlags
|= ReInstall
;
963 P
.iFlags
&= ~ReInstall
;
969 // DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
970 // ---------------------------------------------------------------------
972 void pkgDepCache::SetCandidateVersion(VerIterator TargetVer
)
974 ActionGroup
group(*this);
976 pkgCache::PkgIterator Pkg
= TargetVer
.ParentPkg();
977 StateCache
&P
= PkgState
[Pkg
->ID
];
982 if (P
.CandidateVer
== P
.InstallVer
)
983 P
.InstallVer
= (Version
*)TargetVer
;
984 P
.CandidateVer
= (Version
*)TargetVer
;
992 void pkgDepCache::MarkAuto(const PkgIterator
&Pkg
, bool Auto
)
994 StateCache
&state
= PkgState
[Pkg
->ID
];
996 ActionGroup
group(*this);
999 state
.Flags
|= Flag::Auto
;
1001 state
.Flags
&= ~Flag::Auto
;
1004 // StateCache::Update - Compute the various static display things /*{{{*/
1005 // ---------------------------------------------------------------------
1006 /* This is called whenever the Candidate version changes. */
1007 void pkgDepCache::StateCache::Update(PkgIterator Pkg
,pkgCache
&Cache
)
1010 VerIterator Ver
= CandidateVerIter(Cache
);
1012 // Use a null string or the version string
1013 if (Ver
.end() == true)
1016 CandVersion
= Ver
.VerStr();
1018 // Find the current version
1020 if (Pkg
->CurrentVer
!= 0)
1021 CurVersion
= Pkg
.CurrentVer().VerStr();
1023 // Strip off the epochs for display
1024 CurVersion
= StripEpoch(CurVersion
);
1025 CandVersion
= StripEpoch(CandVersion
);
1027 // Figure out if its up or down or equal
1028 Status
= Ver
.CompareVer(Pkg
.CurrentVer());
1029 if (Pkg
->CurrentVer
== 0 || Pkg
->VersionList
== 0 || CandidateVer
== 0)
1033 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
1034 // ---------------------------------------------------------------------
1036 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver
)
1042 for (const char *I
= Ver
; *I
!= 0; I
++)
1049 // Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/
1050 // ---------------------------------------------------------------------
1051 /* The default just returns the highest available version that is not
1052 a source and automatic. */
1053 pkgCache::VerIterator
pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg
)
1055 /* Not source/not automatic versions cannot be a candidate version
1056 unless they are already installed */
1057 VerIterator
Last(*(pkgCache
*)this,0);
1059 for (VerIterator I
= Pkg
.VersionList(); I
.end() == false; I
++)
1061 if (Pkg
.CurrentVer() == I
)
1064 for (VerFileIterator J
= I
.FileList(); J
.end() == false; J
++)
1066 if ((J
.File()->Flags
& Flag::NotSource
) != 0)
1069 /* Stash the highest version of a not-automatic source, we use it
1070 if there is nothing better */
1071 if ((J
.File()->Flags
& Flag::NotAutomatic
) != 0)
1073 if (Last
.end() == true)
1085 // Policy::IsImportantDep - True if the dependency is important /*{{{*/
1086 // ---------------------------------------------------------------------
1088 bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep
)
1090 return Dep
.IsCritical();
1094 pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
1095 : constructedSuccessfully(false)
1097 Configuration::Item
const *Opts
;
1098 Opts
= _config
->Tree("APT::NeverAutoRemove");
1099 if (Opts
!= 0 && Opts
->Child
!= 0)
1102 for (; Opts
!= 0; Opts
= Opts
->Next
)
1104 if (Opts
->Value
.empty() == true)
1107 regex_t
*p
= new regex_t
;
1108 if(regcomp(p
,Opts
->Value
.c_str(),
1109 REG_EXTENDED
| REG_ICASE
| REG_NOSUB
) != 0)
1113 _error
->Error("Regex compilation error for APT::NeverAutoRemove");
1117 rootSetRegexp
.push_back(p
);
1121 constructedSuccessfully
= true;
1124 pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
1126 for(unsigned int i
= 0; i
< rootSetRegexp
.size(); i
++)
1128 regfree(rootSetRegexp
[i
]);
1129 delete rootSetRegexp
[i
];
1134 bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator
&pkg
)
1136 for(unsigned int i
= 0; i
< rootSetRegexp
.size(); i
++)
1137 if (regexec(rootSetRegexp
[i
], pkg
.Name(), 0, 0, 0) == 0)
1143 pkgDepCache::InRootSetFunc
*pkgDepCache::GetRootSetFunc()
1145 DefaultRootSetFunc
*f
= new DefaultRootSetFunc
;
1146 if(f
->wasConstructedSuccessfully())
1155 bool pkgDepCache::MarkFollowsRecommends()
1157 return _config
->FindB("APT::AutoRemove::RecommendsImportant", true);
1160 bool pkgDepCache::MarkFollowsSuggests()
1162 return _config
->FindB("APT::AutoRemove::SuggestsImportant", false);
1165 // the main mark algorithm
1166 bool pkgDepCache::MarkRequired(InRootSetFunc
&userFunc
)
1168 bool follow_recommends
;
1169 bool follow_suggests
;
1172 for(PkgIterator p
= PkgBegin(); !p
.end(); ++p
)
1174 PkgState
[p
->ID
].Marked
= false;
1175 PkgState
[p
->ID
].Garbage
= false;
1178 if(_config
->FindB("Debug::pkgAutoRemove",false)
1179 && PkgState
[p
->ID
].Flags
& Flag::Auto
)
1180 std::clog
<< "AutoDep: " << p
.Name() << std::endl
;
1184 follow_recommends
= MarkFollowsRecommends();
1185 follow_suggests
= MarkFollowsSuggests();
1189 // do the mark part, this is the core bit of the algorithm
1190 for(PkgIterator p
= PkgBegin(); !p
.end(); ++p
)
1192 if(!(PkgState
[p
->ID
].Flags
& Flag::Auto
) ||
1193 (p
->Flags
& Flag::Essential
) ||
1194 userFunc
.InRootSet(p
))
1197 // the package is installed (and set to keep)
1198 if(PkgState
[p
->ID
].Keep() && !p
.CurrentVer().end())
1199 MarkPackage(p
, p
.CurrentVer(),
1200 follow_recommends
, follow_suggests
);
1201 // the package is to be installed
1202 else if(PkgState
[p
->ID
].Install())
1203 MarkPackage(p
, PkgState
[p
->ID
].InstVerIter(*this),
1204 follow_recommends
, follow_suggests
);
1211 // mark a single package in Mark-and-Sweep
1212 void pkgDepCache::MarkPackage(const pkgCache::PkgIterator
&pkg
,
1213 const pkgCache::VerIterator
&ver
,
1214 bool follow_recommends
,
1215 bool follow_suggests
)
1217 pkgDepCache::StateCache
&state
= PkgState
[pkg
->ID
];
1218 VerIterator candver
= state
.CandidateVerIter(*this);
1219 VerIterator instver
= state
.InstVerIter(*this);
1222 // If a package was garbage-collected but is now being marked, we
1223 // should re-select it
1224 // For cases when a pkg is set to upgrade and this trigger the
1225 // removal of a no-longer used dependency. if the pkg is set to
1226 // keep again later it will result in broken deps
1227 if(state
.Delete() && state
.RemoveReason
= Unused
)
1230 mark_install(pkg
, false, false, NULL
);
1231 else if(ver
==pkg
.CurrentVer())
1232 MarkKeep(pkg
, false, false);
1234 instver
=state
.InstVerIter(*this);
1238 // Ignore versions other than the InstVer, and ignore packages
1239 // that are already going to be removed or just left uninstalled.
1240 if(!(ver
== instver
&& !instver
.end()))
1243 // if we are marked already we are done
1247 //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
1252 for(DepIterator d
= ver
.DependsList(); !d
.end(); ++d
)
1254 if(d
->Type
== Dep::Depends
||
1255 d
->Type
== Dep::PreDepends
||
1256 (follow_recommends
&&
1257 d
->Type
== Dep::Recommends
) ||
1259 d
->Type
== Dep::Suggests
))
1261 // Try all versions of this package.
1262 for(VerIterator V
= d
.TargetPkg().VersionList();
1265 if(_system
->VS
->CheckDep(V
.VerStr(), d
->CompareOp
, d
.TargetVer()))
1267 MarkPackage(V
.ParentPkg(), V
,
1268 follow_recommends
, follow_suggests
);
1271 // Now try virtual packages
1272 for(PrvIterator prv
=d
.TargetPkg().ProvidesList();
1275 if(_system
->VS
->CheckDep(prv
.ProvideVersion(), d
->CompareOp
,
1278 MarkPackage(prv
.OwnerPkg(), prv
.OwnerVer(),
1279 follow_recommends
, follow_suggests
);
1287 bool pkgDepCache::Sweep()
1290 for(PkgIterator p
=PkgBegin(); !p
.end(); ++p
)
1292 StateCache
&state
=PkgState
[p
->ID
];
1294 // skip required packages
1295 if (!p
.CurrentVer().end() &&
1296 (p
.CurrentVer()->Priority
== pkgCache::State::Required
))
1299 // if it is not marked and it is installed, it's garbage
1300 if(!state
.Marked
&& (!p
.CurrentVer().end() || state
.Install()))
1303 if(_config
->FindB("Debug::pkgAutoRemove",false))
1304 std::cout
<< "Garbage: " << p
.Name() << std::endl
;