]>
git.saurik.com Git - apt.git/blob - apt-pkg/depcache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: depcache.cc,v 1.15 1999/03/26 07:38:43 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>
16 #include <apt-pkg/version.h>
17 #include <apt-pkg/error.h>
20 // DepCache::pkgDepCache - Constructors /*{{{*/
21 // ---------------------------------------------------------------------
23 pkgDepCache::pkgDepCache(MMap
&Map
,OpProgress
&Prog
) :
24 pkgCache(Map
), PkgState(0), DepState(0)
26 if (_error
->PendingError() == false)
29 pkgDepCache::pkgDepCache(MMap
&Map
) :
30 pkgCache(Map
), PkgState(0), DepState(0)
32 if (_error
->PendingError() == false)
36 // DepCache::~pkgDepCache - Destructor /*{{{*/
37 // ---------------------------------------------------------------------
39 pkgDepCache::~pkgDepCache()
45 // DepCache::Init - Generate the initial extra structures. /*{{{*/
46 // ---------------------------------------------------------------------
47 /* This allocats the extension buffers and initializes them. */
48 bool pkgDepCache::Init(OpProgress
*Prog
)
52 PkgState
= new StateCache
[Head().PackageCount
];
53 DepState
= new unsigned char[Head().DependsCount
];
54 memset(PkgState
,0,sizeof(*PkgState
)*Head().PackageCount
);
55 memset(DepState
,0,sizeof(*DepState
)*Head().DependsCount
);
59 Prog
->OverallProgress(0,2*Head().PackageCount
,Head().PackageCount
,
60 "Building Dependency Tree");
61 Prog
->SubProgress(Head().PackageCount
,"Candidate Versions");
64 /* Set the current state of everything. In this state all of the
65 packages are kept exactly as is. See AllUpgrade */
67 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
72 // Find the proper cache slot
73 StateCache
&State
= PkgState
[I
->ID
];
76 // Figure out the install version
77 State
.CandidateVer
= GetCandidateVer(I
);
78 State
.InstallVer
= I
.CurrentVer();
79 State
.Mode
= ModeKeep
;
81 State
.Update(I
,*this);
87 Prog
->OverallProgress(Head().PackageCount
,2*Head().PackageCount
,
89 "Building Dependency Tree");
90 Prog
->SubProgress(Head().PackageCount
,"Dependency Generation");
98 // DepCache::GetCandidateVer - Returns the Candidate install version /*{{{*/
99 // ---------------------------------------------------------------------
100 /* The default just returns the target version if it exists or the
102 pkgDepCache::VerIterator
pkgDepCache::GetCandidateVer(PkgIterator Pkg
)
104 // Try to use an explicit target
105 if (Pkg
->TargetVer
== 0)
107 /* Not source/not automatic versions cannot be a candidate version
108 unless they are already installed */
109 for (VerIterator I
= Pkg
.VersionList(); I
.end() == false; I
++)
111 if (Pkg
.CurrentVer() == I
)
113 for (VerFileIterator J
= I
.FileList(); J
.end() == false; J
++)
114 if ((J
.File()->Flags
& Flag::NotSource
) == 0 &&
115 (J
.File()->Flags
& Flag::NotAutomatic
) == 0)
119 return VerIterator(*this,0);
122 return Pkg
.TargetVer();
125 // DepCache::IsImportantDep - True if the dependency is important /*{{{*/
126 // ---------------------------------------------------------------------
128 bool pkgDepCache::IsImportantDep(DepIterator Dep
)
130 return Dep
.IsCritical();
134 // DepCache::CheckDep - Checks a single dependency /*{{{*/
135 // ---------------------------------------------------------------------
136 /* This first checks the dependency against the main target package and
137 then walks along the package provides list and checks if each provides
138 will be installed then checks the provides against the dep. Res will be
139 set to the package which was used to satisfy the dep. */
140 bool pkgDepCache::CheckDep(DepIterator Dep
,int Type
,PkgIterator
&Res
)
142 Res
= Dep
.TargetPkg();
144 /* Check simple depends. A depends -should- never self match but
145 we allow it anyhow because dpkg does. Technically it is a packaging
146 bug. Conflicts may never self match */
147 if (Dep
.TargetPkg() != Dep
.ParentPkg() || Dep
->Type
!= Dep::Conflicts
)
149 PkgIterator Pkg
= Dep
.TargetPkg();
150 // Check the base package
151 if (Type
== NowVersion
&& Pkg
->CurrentVer
!= 0)
152 if (pkgCheckDep(Dep
.TargetVer(),
153 Pkg
.CurrentVer().VerStr(),Dep
->CompareOp
) == true)
156 if (Type
== InstallVersion
&& PkgState
[Pkg
->ID
].InstallVer
!= 0)
157 if (pkgCheckDep(Dep
.TargetVer(),
158 PkgState
[Pkg
->ID
].InstVerIter(*this).VerStr(),
159 Dep
->CompareOp
) == true)
162 if (Type
== CandidateVersion
&& PkgState
[Pkg
->ID
].CandidateVer
!= 0)
163 if (pkgCheckDep(Dep
.TargetVer(),
164 PkgState
[Pkg
->ID
].CandidateVerIter(*this).VerStr(),
165 Dep
->CompareOp
) == true)
169 // Check the providing packages
170 PrvIterator P
= Dep
.TargetPkg().ProvidesList();
171 PkgIterator Pkg
= Dep
.ParentPkg();
172 for (; P
.end() != true; P
++)
174 /* Provides may never be applied against the same package if it is
175 a conflicts. See the comment above. */
176 if (P
.OwnerPkg() == Pkg
&& Dep
->Type
== Dep::Conflicts
)
179 // Check if the provides is a hit
180 if (Type
== NowVersion
)
182 if (P
.OwnerPkg().CurrentVer() != P
.OwnerVer())
186 if (Type
== InstallVersion
)
188 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
189 if (State
.InstallVer
!= (Version
*)P
.OwnerVer())
193 if (Type
== CandidateVersion
)
195 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
196 if (State
.CandidateVer
!= (Version
*)P
.OwnerVer())
200 // Compare the versions.
201 if (pkgCheckDep(Dep
.TargetVer(),P
.ProvideVersion(),Dep
->CompareOp
) == true)
211 // DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
212 // ---------------------------------------------------------------------
213 /* Call with Mult = -1 to preform the inverse opration */
214 void pkgDepCache::AddSizes(const PkgIterator
&Pkg
,long Mult
)
216 StateCache
&P
= PkgState
[Pkg
->ID
];
218 if (Pkg
.State() == pkgCache::PkgIterator::NeedsConfigure
&&
221 iUsrSize
+= Mult
*P
.InstVerIter(*this)->InstalledSize
;
225 // Compute the size data
226 if (P
.NewInstall() == true)
228 iUsrSize
+= Mult
*P
.InstVerIter(*this)->InstalledSize
;
229 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
234 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
!= (Version
*)Pkg
.CurrentVer() &&
237 iUsrSize
+= Mult
*((signed)P
.InstVerIter(*this)->InstalledSize
-
238 (signed)Pkg
.CurrentVer()->InstalledSize
);
239 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
244 if (Pkg
.State() == pkgCache::PkgIterator::NeedsUnpack
&&
247 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
252 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
== 0)
254 iUsrSize
-= Mult
*Pkg
.CurrentVer()->InstalledSize
;
259 // DepCache::AddStates - Add the package to the state counter /*{{{*/
260 // ---------------------------------------------------------------------
261 /* This routine is tricky to use, you must make sure that it is never
262 called twice for the same package. This means the Remove/Add section
263 should be as short as possible and not encompass any code that will
264 calld Remove/Add itself. Remember, dependencies can be circular so
265 while processing a dep for Pkg it is possible that Add/Remove
266 will be called on Pkg */
267 void pkgDepCache::AddStates(const PkgIterator
&Pkg
,int Add
)
269 StateCache
&State
= PkgState
[Pkg
->ID
];
271 // The Package is broken
272 if ((State
.DepState
& DepInstMin
) != DepInstMin
)
276 if (Pkg
.State() != PkgIterator::NeedsNothing
)
280 if (Pkg
->CurrentVer
== 0)
282 if (State
.Mode
== ModeInstall
)
287 // Installed, no upgrade
288 if (State
.Upgradable() == false)
290 if (State
.Mode
== ModeDelete
)
295 // Alll 3 are possible
296 if (State
.Mode
== ModeDelete
)
298 if (State
.Mode
== ModeKeep
)
300 if (State
.Mode
== ModeInstall
)
304 // DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
305 // ---------------------------------------------------------------------
306 /* The or group results are stored in the last item of the or group. This
307 allows easy detection of the state of a whole or'd group. */
308 void pkgDepCache::BuildGroupOrs(VerIterator
const &V
)
310 unsigned char Group
= 0;
312 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
314 // Build the dependency state.
315 unsigned char &State
= DepState
[D
->ID
];
317 /* Invert for Conflicts. We have to do this twice to get the
318 right sense for a conflicts group */
319 if (D
->Type
== Dep::Conflicts
)
322 // Add to the group if we are within an or..
326 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
329 // Invert for Conflicts
330 if (D
->Type
== Dep::Conflicts
)
335 // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
336 // ---------------------------------------------------------------------
337 /* This is used to run over a dependency list and determine the dep
338 state of the list, filtering it through both a Min check and a Policy
339 check. The return result will have SetMin/SetPolicy low if a check
340 fails. It uses the DepState cache for it's computations. */
341 unsigned char pkgDepCache::VersionState(DepIterator D
,unsigned char Check
,
342 unsigned char SetMin
,
343 unsigned char SetPolicy
)
345 unsigned char Dep
= 0xFF;
347 while (D
.end() != true)
349 // Compute a single dependency element (glob or)
350 DepIterator Start
= D
;
351 unsigned char State
= 0;
352 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
354 State
|= DepState
[D
->ID
];
355 LastOR
= (D
->CompareOp
& Dep::Or
) == Dep::Or
;
358 // Minimum deps that must be satisfied to have a working package
359 if (Start
.IsCritical() == true)
360 if ((State
& Check
) != Check
)
363 // Policy deps that must be satisfied to install the package
364 if (IsImportantDep(Start
) == true &&
365 (State
& Check
) != Check
)
372 // DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
373 // ---------------------------------------------------------------------
374 /* This is the main dependency computation bit. It computes the 3 main
375 results for a dependencys, Now, Install and Candidate. Callers must
376 invert the result if dealing with conflicts. */
377 unsigned char pkgDepCache::DependencyState(DepIterator
&D
)
379 unsigned char State
= 0;
381 if (CheckDep(D
,NowVersion
) == true)
383 if (CheckDep(D
,InstallVersion
) == true)
385 if (CheckDep(D
,CandidateVersion
) == true)
391 // DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
392 // ---------------------------------------------------------------------
393 /* This determines the combined dependency representation of a package
394 for its two states now and install. This is done by using the pre-generated
395 dependency information. */
396 void pkgDepCache::UpdateVerState(PkgIterator Pkg
)
398 // Empty deps are always true
399 StateCache
&State
= PkgState
[Pkg
->ID
];
400 State
.DepState
= 0xFF;
402 // Check the Current state
403 if (Pkg
->CurrentVer
!= 0)
405 DepIterator D
= Pkg
.CurrentVer().DependsList();
406 State
.DepState
&= VersionState(D
,DepNow
,DepNowMin
,DepNowPolicy
);
409 /* Check the candidate state. We do not compare against the whole as
410 a candidate state but check the candidate version against the
412 if (State
.CandidateVer
!= 0)
414 DepIterator D
= State
.CandidateVerIter(*this).DependsList();
415 State
.DepState
&= VersionState(D
,DepInstall
,DepCandMin
,DepCandPolicy
);
418 // Check target state which can only be current or installed
419 if (State
.InstallVer
!= 0)
421 DepIterator D
= State
.InstVerIter(*this).DependsList();
422 State
.DepState
&= VersionState(D
,DepInstall
,DepInstMin
,DepInstPolicy
);
426 // DepCache::Update - Figure out all the state information /*{{{*/
427 // ---------------------------------------------------------------------
428 /* This will figure out the state of all the packages and all the
429 dependencies based on the current policy. */
430 void pkgDepCache::Update(OpProgress
*Prog
)
440 // Perform the depends pass
442 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
444 if (Prog
!= 0 && Done%20
== 0)
445 Prog
->Progress(Done
);
446 for (VerIterator V
= I
.VersionList(); V
.end() != true; 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
];
454 State
= DependencyState(D
);;
456 // Add to the group if we are within an or..
459 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
462 // Invert for Conflicts
463 if (D
->Type
== Dep::Conflicts
)
468 // Compute the pacakge dependency state and size additions
475 Prog
->Progress(Done
);
478 // DepCache::Update - Update the deps list of a package /*{{{*/
479 // ---------------------------------------------------------------------
480 /* This is a helper for update that only does the dep portion of the scan.
481 It is mainly ment to scan reverse dependencies. */
482 void pkgDepCache::Update(DepIterator D
)
484 // Update the reverse deps
485 for (;D
.end() != true; D
++)
487 unsigned char &State
= DepState
[D
->ID
];
488 State
= DependencyState(D
);
490 // Invert for Conflicts
491 if (D
->Type
== Dep::Conflicts
)
494 RemoveStates(D
.ParentPkg());
495 BuildGroupOrs(D
.ParentVer());
496 UpdateVerState(D
.ParentPkg());
497 AddStates(D
.ParentPkg());
501 // DepCache::Update - Update the related deps of a package /*{{{*/
502 // ---------------------------------------------------------------------
503 /* This is called whenever the state of a package changes. It updates
504 all cached dependencies related to this package. */
505 void pkgDepCache::Update(PkgIterator
const &Pkg
)
507 // Recompute the dep of the package
512 // Update the reverse deps
513 Update(Pkg
.RevDependsList());
515 // Update the provides map for the current ver
516 if (Pkg
->CurrentVer
!= 0)
517 for (PrvIterator P
= Pkg
.CurrentVer().ProvidesList();
518 P
.end() != true; P
++)
519 Update(P
.ParentPkg().RevDependsList());
521 // Update the provides map for the candidate ver
522 for (PrvIterator P
= PkgState
[Pkg
->ID
].CandidateVerIter(*this).ProvidesList();
523 P
.end() != true; P
++)
524 Update(P
.ParentPkg().RevDependsList());
529 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
530 // ---------------------------------------------------------------------
532 void pkgDepCache::MarkKeep(PkgIterator
const &Pkg
,bool Soft
)
534 // Simplifies other routines.
535 if (Pkg
.end() == true)
538 /* We changed the soft state all the time so the UI is a bit nicer
540 StateCache
&P
= PkgState
[Pkg
->ID
];
542 P
.iFlags
|= AutoKept
;
544 P
.iFlags
&= ~AutoKept
;
546 // Check that it is not already kept
547 if (P
.Mode
== ModeKeep
)
550 // We dont even try to keep virtual packages..
551 if (Pkg
->VersionList
== 0)
554 P
.Flags
&= ~Flag::Auto
;
559 if (Pkg
->CurrentVer
== 0)
562 P
.InstallVer
= Pkg
.CurrentVer();
571 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
572 // ---------------------------------------------------------------------
574 void pkgDepCache::MarkDelete(PkgIterator
const &Pkg
)
576 // Simplifies other routines.
577 if (Pkg
.end() == true)
580 // Check that it is not already marked for delete
581 StateCache
&P
= PkgState
[Pkg
->ID
];
582 P
.iFlags
&= ~AutoKept
;
583 if (P
.Mode
== ModeDelete
|| P
.InstallVer
== 0)
586 // We dont even try to delete virtual packages..
587 if (Pkg
->VersionList
== 0)
593 if (Pkg
->CurrentVer
== 0)
598 P
.Flags
&= Flag::Auto
;
605 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
606 // ---------------------------------------------------------------------
608 void pkgDepCache::MarkInstall(PkgIterator
const &Pkg
,bool AutoInst
)
610 // Simplifies other routines.
611 if (Pkg
.end() == true)
614 /* Check that it is not already marked for install and that it can be
616 StateCache
&P
= PkgState
[Pkg
->ID
];
617 P
.iFlags
&= ~AutoKept
;
618 if (P
.InstBroken() == false && (P
.Mode
== ModeInstall
||
619 P
.CandidateVer
== (Version
*)Pkg
.CurrentVer()))
621 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer() && P
.InstallVer
== 0)
626 // We dont even try to install virtual packages..
627 if (Pkg
->VersionList
== 0)
630 /* Target the candidate version and remove the autoflag. We reset the
631 autoflag below if this was called recursively. Otherwise the user
632 should have the ability to de-auto a package by changing its state */
636 P
.Mode
= ModeInstall
;
637 P
.InstallVer
= P
.CandidateVer
;
638 P
.Flags
&= ~Flag::Auto
;
639 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer())
646 if (AutoInst
== false)
649 DepIterator Dep
= P
.InstVerIter(*this).DependsList();
650 for (; Dep
.end() != true;)
653 DepIterator Start
= Dep
;
655 for (bool LastOR
= true; Dep
.end() == false && LastOR
== true; Dep
++)
657 LastOR
= (Dep
->CompareOp
& Dep::Or
) == Dep::Or
;
659 if ((DepState
[Dep
->ID
] & DepInstall
) == DepInstall
)
663 // Dep is satisfied okay.
667 /* Check if this dep should be consider for install. If it is a user
668 defined important dep and we are installed a new package then
669 it will be installed. Otherwise we only worry about critical deps */
670 if (IsImportantDep(Start
) == false)
672 if (Pkg
->CurrentVer
!= 0 && Start
.IsCritical() == false)
675 // Now we have to take action...
676 PkgIterator P
= Start
.SmartTargetPkg();
677 if ((DepState
[Start
->ID
] & DepCVer
) == DepCVer
)
681 // Set the autoflag, after MarkInstall because MarkInstall unsets it
682 if (P
->CurrentVer
== 0)
683 PkgState
[P
->ID
].Flags
|= Flag::Auto
;
688 // For conflicts we just de-install the package and mark as auto
689 if (Start
->Type
== Dep::Conflicts
)
691 Version
**List
= Start
.AllTargets();
692 for (Version
**I
= List
; *I
!= 0; I
++)
694 VerIterator
Ver(*this,*I
);
695 PkgIterator Pkg
= Ver
.ParentPkg();
698 PkgState
[Pkg
->ID
].Flags
|= Flag::Auto
;
707 // StateCache::Update - Compute the various static display things /*{{{*/
708 // ---------------------------------------------------------------------
709 /* This is called whenever the Candidate version changes. */
710 void pkgDepCache::StateCache::Update(PkgIterator Pkg
,pkgCache
&Cache
)
713 VerIterator Ver
= CandidateVerIter(Cache
);
715 // Use a null string or the version string
716 if (Ver
.end() == true)
719 CandVersion
= Ver
.VerStr();
721 // Find the current version
723 if (Pkg
->CurrentVer
!= 0)
724 CurVersion
= Pkg
.CurrentVer().VerStr();
726 // Strip off the epochs for display
727 CurVersion
= StripEpoch(CurVersion
);
728 CandVersion
= StripEpoch(CandVersion
);
730 // Figure out if its up or down or equal
731 Status
= Ver
.CompareVer(Pkg
.CurrentVer());
732 if (Pkg
->CurrentVer
== 0 || Pkg
->VersionList
== 0 || CandidateVer
== 0)
736 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
737 // ---------------------------------------------------------------------
739 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver
)
745 for (const char *I
= Ver
; *I
!= 0; I
++)