]>
git.saurik.com Git - apt.git/blob - apt-pkg/depcache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: depcache.cc,v 1.21 1999/10/22 05:58:54 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
,
105 // Try to use an explicit target
106 if (Pkg
->TargetVer
== 0 ||
107 (AllowCurrent
== false && Pkg
.TargetVer() == Pkg
.CurrentVer()))
108 return pkgCache::GetCandidateVer(Pkg
,AllowCurrent
);
110 return Pkg
.TargetVer();
113 // DepCache::IsImportantDep - True if the dependency is important /*{{{*/
114 // ---------------------------------------------------------------------
116 bool pkgDepCache::IsImportantDep(DepIterator Dep
)
118 return Dep
.IsCritical();
122 // DepCache::CheckDep - Checks a single dependency /*{{{*/
123 // ---------------------------------------------------------------------
124 /* This first checks the dependency against the main target package and
125 then walks along the package provides list and checks if each provides
126 will be installed then checks the provides against the dep. Res will be
127 set to the package which was used to satisfy the dep. */
128 bool pkgDepCache::CheckDep(DepIterator Dep
,int Type
,PkgIterator
&Res
)
130 Res
= Dep
.TargetPkg();
132 /* Check simple depends. A depends -should- never self match but
133 we allow it anyhow because dpkg does. Technically it is a packaging
134 bug. Conflicts may never self match */
135 if (Dep
.TargetPkg() != Dep
.ParentPkg() || Dep
->Type
!= Dep::Conflicts
)
137 PkgIterator Pkg
= Dep
.TargetPkg();
138 // Check the base package
139 if (Type
== NowVersion
&& Pkg
->CurrentVer
!= 0)
140 if (pkgCheckDep(Dep
.TargetVer(),
141 Pkg
.CurrentVer().VerStr(),Dep
->CompareOp
) == true)
144 if (Type
== InstallVersion
&& PkgState
[Pkg
->ID
].InstallVer
!= 0)
145 if (pkgCheckDep(Dep
.TargetVer(),
146 PkgState
[Pkg
->ID
].InstVerIter(*this).VerStr(),
147 Dep
->CompareOp
) == true)
150 if (Type
== CandidateVersion
&& PkgState
[Pkg
->ID
].CandidateVer
!= 0)
151 if (pkgCheckDep(Dep
.TargetVer(),
152 PkgState
[Pkg
->ID
].CandidateVerIter(*this).VerStr(),
153 Dep
->CompareOp
) == true)
157 // Check the providing packages
158 PrvIterator P
= Dep
.TargetPkg().ProvidesList();
159 PkgIterator Pkg
= Dep
.ParentPkg();
160 for (; P
.end() != true; P
++)
162 /* Provides may never be applied against the same package if it is
163 a conflicts. See the comment above. */
164 if (P
.OwnerPkg() == Pkg
&& Dep
->Type
== Dep::Conflicts
)
167 // Check if the provides is a hit
168 if (Type
== NowVersion
)
170 if (P
.OwnerPkg().CurrentVer() != P
.OwnerVer())
174 if (Type
== InstallVersion
)
176 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
177 if (State
.InstallVer
!= (Version
*)P
.OwnerVer())
181 if (Type
== CandidateVersion
)
183 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
184 if (State
.CandidateVer
!= (Version
*)P
.OwnerVer())
188 // Compare the versions.
189 if (pkgCheckDep(Dep
.TargetVer(),P
.ProvideVersion(),Dep
->CompareOp
) == true)
199 // DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
200 // ---------------------------------------------------------------------
201 /* Call with Mult = -1 to preform the inverse opration */
202 void pkgDepCache::AddSizes(const PkgIterator
&Pkg
,long Mult
)
204 StateCache
&P
= PkgState
[Pkg
->ID
];
206 if (Pkg
.State() == pkgCache::PkgIterator::NeedsConfigure
&&
210 // Compute the size data
211 if (P
.NewInstall() == true)
213 iUsrSize
+= Mult
*P
.InstVerIter(*this)->InstalledSize
;
214 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
219 if (Pkg
->CurrentVer
!= 0 &&
220 (P
.InstallVer
!= (Version
*)Pkg
.CurrentVer() ||
221 (P
.iFlags
& ReInstall
) == ReInstall
) && P
.InstallVer
!= 0)
223 iUsrSize
+= Mult
*((signed)P
.InstVerIter(*this)->InstalledSize
-
224 (signed)Pkg
.CurrentVer()->InstalledSize
);
225 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
230 if (Pkg
.State() == pkgCache::PkgIterator::NeedsUnpack
&&
233 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
238 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
== 0)
240 iUsrSize
-= Mult
*Pkg
.CurrentVer()->InstalledSize
;
245 // DepCache::AddStates - Add the package to the state counter /*{{{*/
246 // ---------------------------------------------------------------------
247 /* This routine is tricky to use, you must make sure that it is never
248 called twice for the same package. This means the Remove/Add section
249 should be as short as possible and not encompass any code that will
250 calld Remove/Add itself. Remember, dependencies can be circular so
251 while processing a dep for Pkg it is possible that Add/Remove
252 will be called on Pkg */
253 void pkgDepCache::AddStates(const PkgIterator
&Pkg
,int Add
)
255 StateCache
&State
= PkgState
[Pkg
->ID
];
257 // The Package is broken
258 if ((State
.DepState
& DepInstMin
) != DepInstMin
)
262 if (Pkg
.State() != PkgIterator::NeedsNothing
)
266 if (Pkg
->CurrentVer
== 0)
268 if (State
.Mode
== ModeDelete
&&
269 (State
.iFlags
| Purge
) == Purge
&& Pkg
.Purge() == false)
272 if (State
.Mode
== ModeInstall
)
277 // Installed, no upgrade
278 if (State
.Upgradable() == false)
280 if (State
.Mode
== ModeDelete
)
283 if ((State
.iFlags
& ReInstall
) == ReInstall
)
289 // Alll 3 are possible
290 if (State
.Mode
== ModeDelete
)
292 if (State
.Mode
== ModeKeep
)
294 if (State
.Mode
== ModeInstall
)
298 // DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
299 // ---------------------------------------------------------------------
300 /* The or group results are stored in the last item of the or group. This
301 allows easy detection of the state of a whole or'd group. */
302 void pkgDepCache::BuildGroupOrs(VerIterator
const &V
)
304 unsigned char Group
= 0;
306 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
308 // Build the dependency state.
309 unsigned char &State
= DepState
[D
->ID
];
311 /* Invert for Conflicts. We have to do this twice to get the
312 right sense for a conflicts group */
313 if (D
->Type
== Dep::Conflicts
)
316 // Add to the group if we are within an or..
320 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
323 // Invert for Conflicts
324 if (D
->Type
== Dep::Conflicts
)
329 // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
330 // ---------------------------------------------------------------------
331 /* This is used to run over a dependency list and determine the dep
332 state of the list, filtering it through both a Min check and a Policy
333 check. The return result will have SetMin/SetPolicy low if a check
334 fails. It uses the DepState cache for it's computations. */
335 unsigned char pkgDepCache::VersionState(DepIterator D
,unsigned char Check
,
336 unsigned char SetMin
,
337 unsigned char SetPolicy
)
339 unsigned char Dep
= 0xFF;
341 while (D
.end() != true)
343 // Compute a single dependency element (glob or)
344 DepIterator Start
= D
;
345 unsigned char State
= 0;
346 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
348 State
|= DepState
[D
->ID
];
349 LastOR
= (D
->CompareOp
& Dep::Or
) == Dep::Or
;
352 // Minimum deps that must be satisfied to have a working package
353 if (Start
.IsCritical() == true)
354 if ((State
& Check
) != Check
)
357 // Policy deps that must be satisfied to install the package
358 if (IsImportantDep(Start
) == true &&
359 (State
& Check
) != Check
)
366 // DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
367 // ---------------------------------------------------------------------
368 /* This is the main dependency computation bit. It computes the 3 main
369 results for a dependencys, Now, Install and Candidate. Callers must
370 invert the result if dealing with conflicts. */
371 unsigned char pkgDepCache::DependencyState(DepIterator
&D
)
373 unsigned char State
= 0;
375 if (CheckDep(D
,NowVersion
) == true)
377 if (CheckDep(D
,InstallVersion
) == true)
379 if (CheckDep(D
,CandidateVersion
) == true)
385 // DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
386 // ---------------------------------------------------------------------
387 /* This determines the combined dependency representation of a package
388 for its two states now and install. This is done by using the pre-generated
389 dependency information. */
390 void pkgDepCache::UpdateVerState(PkgIterator Pkg
)
392 // Empty deps are always true
393 StateCache
&State
= PkgState
[Pkg
->ID
];
394 State
.DepState
= 0xFF;
396 // Check the Current state
397 if (Pkg
->CurrentVer
!= 0)
399 DepIterator D
= Pkg
.CurrentVer().DependsList();
400 State
.DepState
&= VersionState(D
,DepNow
,DepNowMin
,DepNowPolicy
);
403 /* Check the candidate state. We do not compare against the whole as
404 a candidate state but check the candidate version against the
406 if (State
.CandidateVer
!= 0)
408 DepIterator D
= State
.CandidateVerIter(*this).DependsList();
409 State
.DepState
&= VersionState(D
,DepInstall
,DepCandMin
,DepCandPolicy
);
412 // Check target state which can only be current or installed
413 if (State
.InstallVer
!= 0)
415 DepIterator D
= State
.InstVerIter(*this).DependsList();
416 State
.DepState
&= VersionState(D
,DepInstall
,DepInstMin
,DepInstPolicy
);
420 // DepCache::Update - Figure out all the state information /*{{{*/
421 // ---------------------------------------------------------------------
422 /* This will figure out the state of all the packages and all the
423 dependencies based on the current policy. */
424 void pkgDepCache::Update(OpProgress
*Prog
)
434 // Perform the depends pass
436 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
438 if (Prog
!= 0 && Done%20
== 0)
439 Prog
->Progress(Done
);
440 for (VerIterator V
= I
.VersionList(); V
.end() != true; V
++)
442 unsigned char Group
= 0;
444 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
446 // Build the dependency state.
447 unsigned char &State
= DepState
[D
->ID
];
448 State
= DependencyState(D
);;
450 // Add to the group if we are within an or..
453 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
456 // Invert for Conflicts
457 if (D
->Type
== Dep::Conflicts
)
462 // Compute the pacakge dependency state and size additions
469 Prog
->Progress(Done
);
472 // DepCache::Update - Update the deps list of a package /*{{{*/
473 // ---------------------------------------------------------------------
474 /* This is a helper for update that only does the dep portion of the scan.
475 It is mainly ment to scan reverse dependencies. */
476 void pkgDepCache::Update(DepIterator D
)
478 // Update the reverse deps
479 for (;D
.end() != true; D
++)
481 unsigned char &State
= DepState
[D
->ID
];
482 State
= DependencyState(D
);
484 // Invert for Conflicts
485 if (D
->Type
== Dep::Conflicts
)
488 RemoveStates(D
.ParentPkg());
489 BuildGroupOrs(D
.ParentVer());
490 UpdateVerState(D
.ParentPkg());
491 AddStates(D
.ParentPkg());
495 // DepCache::Update - Update the related deps of a package /*{{{*/
496 // ---------------------------------------------------------------------
497 /* This is called whenever the state of a package changes. It updates
498 all cached dependencies related to this package. */
499 void pkgDepCache::Update(PkgIterator
const &Pkg
)
501 // Recompute the dep of the package
506 // Update the reverse deps
507 Update(Pkg
.RevDependsList());
509 // Update the provides map for the current ver
510 if (Pkg
->CurrentVer
!= 0)
511 for (PrvIterator P
= Pkg
.CurrentVer().ProvidesList();
512 P
.end() != true; P
++)
513 Update(P
.ParentPkg().RevDependsList());
515 // Update the provides map for the candidate ver
516 if (PkgState
[Pkg
->ID
].CandidateVer
!= 0)
517 for (PrvIterator P
= PkgState
[Pkg
->ID
].CandidateVerIter(*this).ProvidesList();
518 P
.end() != true; P
++)
519 Update(P
.ParentPkg().RevDependsList());
524 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
525 // ---------------------------------------------------------------------
527 void pkgDepCache::MarkKeep(PkgIterator
const &Pkg
,bool Soft
)
529 // Simplifies other routines.
530 if (Pkg
.end() == true)
533 /* Reject an attempt to keep a non-source broken installed package, those
535 if (Pkg
.State() == PkgIterator::NeedsUnpack
&&
536 Pkg
.CurrentVer().Downloadable() == false)
539 /* We changed the soft state all the time so the UI is a bit nicer
541 StateCache
&P
= PkgState
[Pkg
->ID
];
543 P
.iFlags
|= AutoKept
;
545 P
.iFlags
&= ~AutoKept
;
547 // Check that it is not already kept
548 if (P
.Mode
== ModeKeep
)
551 // We dont even try to keep virtual packages..
552 if (Pkg
->VersionList
== 0)
555 P
.Flags
&= ~Flag::Auto
;
560 if (Pkg
->CurrentVer
== 0)
563 P
.InstallVer
= Pkg
.CurrentVer();
572 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
573 // ---------------------------------------------------------------------
575 void pkgDepCache::MarkDelete(PkgIterator
const &Pkg
, bool rPurge
)
577 // Simplifies other routines.
578 if (Pkg
.end() == true)
581 // Check that it is not already marked for delete
582 StateCache
&P
= PkgState
[Pkg
->ID
];
583 P
.iFlags
&= ~(AutoKept
| Purge
);
587 if ((P
.Mode
== ModeDelete
|| P
.InstallVer
== 0) &&
588 (Pkg
.Purge() == true || rPurge
== false))
591 // We dont even try to delete virtual packages..
592 if (Pkg
->VersionList
== 0)
598 if (Pkg
->CurrentVer
== 0 && (Pkg
.Purge() == true || rPurge
== false))
603 P
.Flags
&= Flag::Auto
;
610 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
611 // ---------------------------------------------------------------------
613 void pkgDepCache::MarkInstall(PkgIterator
const &Pkg
,bool AutoInst
)
615 // Simplifies other routines.
616 if (Pkg
.end() == true)
619 /* Check that it is not already marked for install and that it can be
621 StateCache
&P
= PkgState
[Pkg
->ID
];
622 P
.iFlags
&= ~AutoKept
;
623 if (P
.InstBroken() == false && (P
.Mode
== ModeInstall
||
624 P
.CandidateVer
== (Version
*)Pkg
.CurrentVer()))
626 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer() && P
.InstallVer
== 0)
631 // We dont even try to install virtual packages..
632 if (Pkg
->VersionList
== 0)
635 /* Target the candidate version and remove the autoflag. We reset the
636 autoflag below if this was called recursively. Otherwise the user
637 should have the ability to de-auto a package by changing its state */
641 P
.Mode
= ModeInstall
;
642 P
.InstallVer
= P
.CandidateVer
;
643 P
.Flags
&= ~Flag::Auto
;
644 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer())
651 if (AutoInst
== false)
654 DepIterator Dep
= P
.InstVerIter(*this).DependsList();
655 for (; Dep
.end() != true;)
658 DepIterator Start
= Dep
;
660 for (bool LastOR
= true; Dep
.end() == false && LastOR
== true; Dep
++)
662 LastOR
= (Dep
->CompareOp
& Dep::Or
) == Dep::Or
;
664 if ((DepState
[Dep
->ID
] & DepInstall
) == DepInstall
)
668 // Dep is satisfied okay.
672 /* Check if this dep should be consider for install. If it is a user
673 defined important dep and we are installed a new package then
674 it will be installed. Otherwise we only worry about critical deps */
675 if (IsImportantDep(Start
) == false)
677 if (Pkg
->CurrentVer
!= 0 && Start
.IsCritical() == false)
680 // Now we have to take action...
681 PkgIterator P
= Start
.SmartTargetPkg();
682 if ((DepState
[Start
->ID
] & DepCVer
) == DepCVer
)
686 // Set the autoflag, after MarkInstall because MarkInstall unsets it
687 if (P
->CurrentVer
== 0)
688 PkgState
[P
->ID
].Flags
|= Flag::Auto
;
693 // For conflicts we just de-install the package and mark as auto
694 if (Start
->Type
== Dep::Conflicts
)
696 Version
**List
= Start
.AllTargets();
697 for (Version
**I
= List
; *I
!= 0; I
++)
699 VerIterator
Ver(*this,*I
);
700 PkgIterator Pkg
= Ver
.ParentPkg();
703 PkgState
[Pkg
->ID
].Flags
|= Flag::Auto
;
711 // DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
712 // ---------------------------------------------------------------------
714 void pkgDepCache::SetReInstall(PkgIterator
const &Pkg
,bool To
)
719 StateCache
&P
= PkgState
[Pkg
->ID
];
721 P
.iFlags
|= ReInstall
;
723 P
.iFlags
&= ~ReInstall
;
729 // StateCache::Update - Compute the various static display things /*{{{*/
730 // ---------------------------------------------------------------------
731 /* This is called whenever the Candidate version changes. */
732 void pkgDepCache::StateCache::Update(PkgIterator Pkg
,pkgCache
&Cache
)
735 VerIterator Ver
= CandidateVerIter(Cache
);
737 // Use a null string or the version string
738 if (Ver
.end() == true)
741 CandVersion
= Ver
.VerStr();
743 // Find the current version
745 if (Pkg
->CurrentVer
!= 0)
746 CurVersion
= Pkg
.CurrentVer().VerStr();
748 // Strip off the epochs for display
749 CurVersion
= StripEpoch(CurVersion
);
750 CandVersion
= StripEpoch(CandVersion
);
752 // Figure out if its up or down or equal
753 Status
= Ver
.CompareVer(Pkg
.CurrentVer());
754 if (Pkg
->CurrentVer
== 0 || Pkg
->VersionList
== 0 || CandidateVer
== 0)
758 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
759 // ---------------------------------------------------------------------
761 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver
)
767 for (const char *I
= Ver
; *I
!= 0; I
++)