]>
git.saurik.com Git - apt.git/blob - apt-pkg/depcache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: depcache.cc,v 1.7 1998/11/23 07:02:59 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)
30 // DepCache::~pkgDepCache - Destructor /*{{{*/
31 // ---------------------------------------------------------------------
33 pkgDepCache::~pkgDepCache()
39 // DepCache::Init - Generate the initial extra structures. /*{{{*/
40 // ---------------------------------------------------------------------
41 /* This allocats the extension buffers and initializes them. */
42 bool pkgDepCache::Init(OpProgress
*Prog
)
46 PkgState
= new StateCache
[Head().PackageCount
];
47 DepState
= new unsigned char[Head().DependsCount
];
48 memset(PkgState
,0,sizeof(*PkgState
)*Head().PackageCount
);
49 memset(DepState
,0,sizeof(*DepState
)*Head().DependsCount
);
53 Prog
->OverallProgress(0,2*Head().PackageCount
,Head().PackageCount
,
54 "Building Dependency Tree");
55 Prog
->SubProgress(Head().PackageCount
,"Candidate Versions");
58 /* Set the current state of everything. In this state all of the
59 packages are kept exactly as is. See AllUpgrade */
61 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
66 // Find the proper cache slot
67 StateCache
&State
= PkgState
[I
->ID
];
70 // Figure out the install version
71 State
.CandidateVer
= GetCandidateVer(I
);
72 State
.InstallVer
= I
.CurrentVer();
73 State
.Mode
= ModeKeep
;
75 State
.Update(I
,*this);
81 Prog
->OverallProgress(Head().PackageCount
,2*Head().PackageCount
,
83 "Building Dependency Tree");
84 Prog
->SubProgress(Head().PackageCount
,"Dependency Generation");
92 // DepCache::GetCandidateVer - Returns the Candidate install version /*{{{*/
93 // ---------------------------------------------------------------------
94 /* The default just returns the target version if it exists or the
96 pkgDepCache::VerIterator
pkgDepCache::GetCandidateVer(PkgIterator Pkg
)
98 // Try to use an explicit target
99 if (Pkg
->TargetVer
== 0)
101 /* Not source versions cannot be a candidate version unless they
102 are already installed */
103 for (VerIterator I
= Pkg
.VersionList(); I
.end() == false; I
++)
105 if (Pkg
.CurrentVer() == I
)
107 for (VerFileIterator J
= I
.FileList(); J
.end() == false; J
++)
108 if ((J
.File()->Flags
& Flag::NotSource
) == 0)
112 return VerIterator(*this,0);
115 return Pkg
.TargetVer();
118 // DepCache::IsImportantDep - True if the dependency is important /*{{{*/
119 // ---------------------------------------------------------------------
121 bool pkgDepCache::IsImportantDep(DepIterator Dep
)
123 return Dep
.IsCritical();
127 // DepCache::CheckDep - Checks a single dependency /*{{{*/
128 // ---------------------------------------------------------------------
129 /* This first checks the dependency against the main target package and
130 then walks along the package provides list and checks if each provides
131 will be installed then checks the provides against the dep. Res will be
132 set to the package which was used to satisfy the dep. */
133 bool pkgDepCache::CheckDep(DepIterator Dep
,int Type
,PkgIterator
&Res
)
135 Res
= Dep
.TargetPkg();
137 /* Check simple depends. A depends -should- never self match but
138 we allow it anyhow because dpkg does. Technically it is a packaging
139 bug. Conflicts may never self match */
140 if (Dep
.TargetPkg() != Dep
.ParentPkg() || Dep
->Type
!= Dep::Conflicts
)
142 PkgIterator Pkg
= Dep
.TargetPkg();
143 // Check the base package
144 if (Type
== NowVersion
&& Pkg
->CurrentVer
!= 0)
145 if (pkgCheckDep(Dep
.TargetVer(),
146 Pkg
.CurrentVer().VerStr(),Dep
->CompareOp
) == true)
149 if (Type
== InstallVersion
&& PkgState
[Pkg
->ID
].InstallVer
!= 0)
150 if (pkgCheckDep(Dep
.TargetVer(),
151 PkgState
[Pkg
->ID
].InstVerIter(*this).VerStr(),
152 Dep
->CompareOp
) == true)
155 if (Type
== CandidateVersion
&& PkgState
[Pkg
->ID
].CandidateVer
!= 0)
156 if (pkgCheckDep(Dep
.TargetVer(),
157 PkgState
[Pkg
->ID
].CandidateVerIter(*this).VerStr(),
158 Dep
->CompareOp
) == true)
162 // Check the providing packages
163 PrvIterator P
= Dep
.TargetPkg().ProvidesList();
164 PkgIterator Pkg
= Dep
.ParentPkg();
165 for (; P
.end() != true; P
++)
167 /* Provides may never be applied against the same package if it is
168 a conflicts. See the comment above. */
169 if (P
.OwnerPkg() == Pkg
&& Dep
->Type
== Dep::Conflicts
)
172 // Check if the provides is a hit
173 if (Type
== NowVersion
)
175 if (P
.OwnerPkg().CurrentVer() != P
.OwnerVer())
179 if (Type
== InstallVersion
)
181 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
182 if (State
.InstallVer
!= (Version
*)P
.OwnerVer())
186 if (Type
== CandidateVersion
)
188 StateCache
&State
= PkgState
[P
.OwnerPkg()->ID
];
189 if (State
.CandidateVer
!= (Version
*)P
.OwnerVer())
193 // Compare the versions.
194 if (pkgCheckDep(Dep
.TargetVer(),P
.ProvideVersion(),Dep
->CompareOp
) == true)
204 // DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
205 // ---------------------------------------------------------------------
206 /* Call with Mult = -1 to preform the inverse opration */
207 void pkgDepCache::AddSizes(const PkgIterator
&Pkg
,long Mult
)
209 StateCache
&P
= PkgState
[Pkg
->ID
];
211 // Compute the size data
212 if (P
.NewInstall() == true)
214 iUsrSize
+= Mult
*P
.InstVerIter(*this)->InstalledSize
;
215 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
220 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
!= (Version
*)Pkg
.CurrentVer() &&
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
)
232 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
237 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
== 0)
239 iUsrSize
-= Mult
*Pkg
.CurrentVer()->InstalledSize
;
244 // DepCache::AddStates - Add the package to the state counter /*{{{*/
245 // ---------------------------------------------------------------------
246 /* This routine is tricky to use, you must make sure that it is never
247 called twice for the same package. This means the Remove/Add section
248 should be as short as possible and not encompass any code that will
249 calld Remove/Add itself. Remember, dependencies can be circular so
250 while processing a dep for Pkg it is possible that Add/Remove
251 will be called on Pkg */
252 void pkgDepCache::AddStates(const PkgIterator
&Pkg
,int Add
)
254 StateCache
&State
= PkgState
[Pkg
->ID
];
256 // The Package is broken
257 if ((State
.DepState
& DepInstMin
) != DepInstMin
)
261 if (Pkg
.State() != PkgIterator::NeedsNothing
)
265 if (Pkg
->CurrentVer
== 0)
267 if (State
.Mode
== ModeInstall
)
272 // Installed, no upgrade
273 if (State
.Upgradable() == false)
275 if (State
.Mode
== ModeDelete
)
280 // Alll 3 are possible
281 if (State
.Mode
== ModeDelete
)
283 if (State
.Mode
== ModeKeep
)
285 if (State
.Mode
== ModeInstall
)
289 // DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
290 // ---------------------------------------------------------------------
291 /* The or group results are stored in the last item of the or group. This
292 allows easy detection of the state of a whole or'd group. */
293 void pkgDepCache::BuildGroupOrs(VerIterator
const &V
)
295 unsigned char Group
= 0;
297 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
299 // Build the dependency state.
300 unsigned char &State
= DepState
[D
->ID
];
302 /* Invert for Conflicts. We have to do this twice to get the
303 right sense for a conflicts group */
304 if (D
->Type
== Dep::Conflicts
)
307 // Add to the group if we are within an or..
310 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
313 // Invert for Conflicts
314 if (D
->Type
== Dep::Conflicts
)
319 // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
320 // ---------------------------------------------------------------------
321 /* This is used to run over a dependency list and determine the dep
322 state of the list, filtering it through both a Min check and a Policy
323 check. The return result will have SetMin/SetPolicy low if a check
324 fails. It uses the DepState cache for it's computations. */
325 unsigned char pkgDepCache::VersionState(DepIterator D
,unsigned char Check
,
326 unsigned char SetMin
,
327 unsigned char SetPolicy
)
329 unsigned char Dep
= 0xFF;
331 while (D
.end() != true)
333 // Compute a single dependency element (glob or)
334 DepIterator Start
= D
;
335 unsigned char State
= 0;
336 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
338 State
|= DepState
[D
->ID
];
339 LastOR
= (D
->CompareOp
& Dep::Or
) == Dep::Or
;
342 // Minimum deps that must be satisfied to have a working package
343 if (Start
.IsCritical() == true)
344 if ((State
& Check
) != Check
)
347 // Policy deps that must be satisfied to install the package
348 if (IsImportantDep(Start
) == true &&
349 (State
& Check
) != Check
)
356 // DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
357 // ---------------------------------------------------------------------
358 /* This is the main dependency computation bit. It computes the 3 main
359 results for a dependencys, Now, Install and Candidate. Callers must
360 invert the result if dealing with conflicts. */
361 unsigned char pkgDepCache::DependencyState(DepIterator
&D
)
363 unsigned char State
= 0;
365 if (CheckDep(D
,NowVersion
) == true)
367 if (CheckDep(D
,InstallVersion
) == true)
369 if (CheckDep(D
,CandidateVersion
) == true)
375 // DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
376 // ---------------------------------------------------------------------
377 /* This determines the combined dependency representation of a package
378 for its two states now and install. This is done by using the pre-generated
379 dependency information. */
380 void pkgDepCache::UpdateVerState(PkgIterator Pkg
)
382 // Empty deps are always true
383 StateCache
&State
= PkgState
[Pkg
->ID
];
384 State
.DepState
= 0xFF;
386 // Check the Current state
387 if (Pkg
->CurrentVer
!= 0)
389 DepIterator D
= Pkg
.CurrentVer().DependsList();
390 State
.DepState
&= VersionState(D
,DepNow
,DepNowMin
,DepNowPolicy
);
393 /* Check the candidate state. We do not compare against the whole as
394 a candidate state but check the candidate version against the
396 if (State
.CandidateVer
!= 0)
398 DepIterator D
= State
.CandidateVerIter(*this).DependsList();
399 State
.DepState
&= VersionState(D
,DepInstall
,DepCandMin
,DepCandPolicy
);
402 // Check target state which can only be current or installed
403 if (State
.InstallVer
!= 0)
405 DepIterator D
= State
.InstVerIter(*this).DependsList();
406 State
.DepState
&= VersionState(D
,DepInstall
,DepInstMin
,DepInstPolicy
);
410 // DepCache::Update - Figure out all the state information /*{{{*/
411 // ---------------------------------------------------------------------
412 /* This will figure out the state of all the packages and all the
413 dependencies based on the current policy. */
414 void pkgDepCache::Update(OpProgress
*Prog
)
424 // Perform the depends pass
426 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
428 if (Prog
!= 0 && Done%20
== 0)
429 Prog
->Progress(Done
);
430 for (VerIterator V
= I
.VersionList(); V
.end() != true; V
++)
432 unsigned char Group
= 0;
434 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
436 // Build the dependency state.
437 unsigned char &State
= DepState
[D
->ID
];
438 State
= DependencyState(D
);;
440 // Add to the group if we are within an or..
443 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
446 // Invert for Conflicts
447 if (D
->Type
== Dep::Conflicts
)
452 // Compute the pacakge dependency state and size additions
459 Prog
->Progress(Done
);
462 // DepCache::Update - Update the deps list of a package /*{{{*/
463 // ---------------------------------------------------------------------
464 /* This is a helper for update that only does the dep portion of the scan.
465 It is mainly ment to scan reverse dependencies. */
466 void pkgDepCache::Update(DepIterator D
)
468 // Update the reverse deps
469 for (;D
.end() != true; D
++)
471 unsigned char &State
= DepState
[D
->ID
];
472 State
= DependencyState(D
);
474 // Invert for Conflicts
475 if (D
->Type
== Dep::Conflicts
)
478 RemoveStates(D
.ParentPkg());
479 BuildGroupOrs(D
.ParentVer());
480 UpdateVerState(D
.ParentPkg());
481 AddStates(D
.ParentPkg());
485 // DepCache::Update - Update the related deps of a package /*{{{*/
486 // ---------------------------------------------------------------------
487 /* This is called whenever the state of a package changes. It updates
488 all cached dependencies related to this package. */
489 void pkgDepCache::Update(PkgIterator
const &Pkg
)
491 // Recompute the dep of the package
496 // Update the reverse deps
497 Update(Pkg
.RevDependsList());
499 // Update the provides map for the current ver
500 if (Pkg
->CurrentVer
!= 0)
501 for (PrvIterator P
= Pkg
.CurrentVer().ProvidesList();
502 P
.end() != true; P
++)
503 Update(P
.ParentPkg().RevDependsList());
505 // Update the provides map for the candidate ver
506 for (PrvIterator P
= PkgState
[Pkg
->ID
].CandidateVerIter(*this).ProvidesList();
507 P
.end() != true; P
++)
508 Update(P
.ParentPkg().RevDependsList());
513 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
514 // ---------------------------------------------------------------------
516 void pkgDepCache::MarkKeep(PkgIterator
const &Pkg
,bool Soft
)
518 // Simplifies other routines.
519 if (Pkg
.end() == true)
522 /* We changed the soft state all the time so the UI is a bit nicer
524 StateCache
&P
= PkgState
[Pkg
->ID
];
526 P
.iFlags
|= AutoKept
;
528 P
.iFlags
&= ~AutoKept
;
530 // Check that it is not already kept
531 if (P
.Mode
== ModeKeep
)
534 // We dont even try to keep virtual packages..
535 if (Pkg
->VersionList
== 0)
538 P
.Flags
&= ~Flag::Auto
;
543 if (Pkg
->CurrentVer
== 0)
546 P
.InstallVer
= Pkg
.CurrentVer();
555 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
556 // ---------------------------------------------------------------------
558 void pkgDepCache::MarkDelete(PkgIterator
const &Pkg
)
560 // Simplifies other routines.
561 if (Pkg
.end() == true)
564 // Check that it is not already marked for delete
565 StateCache
&P
= PkgState
[Pkg
->ID
];
566 P
.iFlags
&= ~AutoKept
;
567 if (P
.Mode
== ModeDelete
|| P
.InstallVer
== 0)
570 // We dont even try to delete virtual packages..
571 if (Pkg
->VersionList
== 0)
579 P
.Flags
&= Flag::Auto
;
586 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
587 // ---------------------------------------------------------------------
589 void pkgDepCache::MarkInstall(PkgIterator
const &Pkg
,bool AutoInst
)
591 // Simplifies other routines.
592 if (Pkg
.end() == true)
595 /* Check that it is not already marked for install and that it can be
597 StateCache
&P
= PkgState
[Pkg
->ID
];
598 P
.iFlags
&= ~AutoKept
;
599 if (P
.InstBroken() == false && (P
.Mode
== ModeInstall
||
600 P
.CandidateVer
== (Version
*)Pkg
.CurrentVer()))
602 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer() && P
.InstallVer
== 0)
607 // We dont even try to install virtual packages..
608 if (Pkg
->VersionList
== 0)
611 /* Target the candidate version and remove the autoflag. We reset the
612 autoflag below if this was called recursively. Otherwise the user
613 should have the ability to de-auto a package by changing its state */
617 P
.Mode
= ModeInstall
;
618 P
.InstallVer
= P
.CandidateVer
;
619 P
.Flags
&= ~Flag::Auto
;
620 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer())
627 if (AutoInst
== false)
630 DepIterator Dep
= P
.InstVerIter(*this).DependsList();
631 for (; Dep
.end() != true;)
634 DepIterator Start
= Dep
;
636 for (bool LastOR
= true; Dep
.end() == false && LastOR
== true; Dep
++)
638 LastOR
= (Dep
->CompareOp
& Dep::Or
) == Dep::Or
;
640 if ((DepState
[Dep
->ID
] & DepInstall
) == DepInstall
)
644 // Dep is satisfied okay.
648 /* Check if this dep should be consider for install. If it is a user
649 defined important dep and we are installed a new package then
650 it will be installed. Otherwise we only worry about critical deps */
651 if (IsImportantDep(Start
) == false)
653 if (Pkg
->CurrentVer
!= 0 && Start
.IsCritical() == false)
656 // Now we have to take action...
657 PkgIterator P
= Start
.SmartTargetPkg();
658 if ((DepState
[Start
->ID
] & DepCVer
) == DepCVer
)
662 // Set the autoflag, after MarkInstall because MarkInstall unsets it
663 if (P
->CurrentVer
== 0)
664 PkgState
[P
->ID
].Flags
|= Flag::Auto
;
669 // For conflicts we just de-install the package and mark as auto
670 if (Start
->Type
== Dep::Conflicts
)
672 Version
**List
= Start
.AllTargets();
673 for (Version
**I
= List
; *I
!= 0; I
++)
675 VerIterator
Ver(*this,*I
);
676 PkgIterator Pkg
= Ver
.ParentPkg();
679 PkgState
[Pkg
->ID
].Flags
|= Flag::Auto
;
688 // StateCache::Update - Compute the various static display things /*{{{*/
689 // ---------------------------------------------------------------------
690 /* This is called whenever the Candidate version changes. */
691 void pkgDepCache::StateCache::Update(PkgIterator Pkg
,pkgCache
&Cache
)
694 VerIterator Ver
= CandidateVerIter(Cache
);
696 // Use a null string or the version string
697 if (Ver
.end() == true)
700 CandVersion
= Ver
.VerStr();
702 // Find the current version
704 if (Pkg
->CurrentVer
!= 0)
705 CurVersion
= Pkg
.CurrentVer().VerStr();
707 // Strip off the epochs for display
708 CurVersion
= StripEpoch(CurVersion
);
709 CandVersion
= StripEpoch(CandVersion
);
711 // Figure out if its up or down or equal
712 Status
= Ver
.CompareVer(Pkg
.CurrentVer());
713 if (Pkg
->CurrentVer
== 0 || Pkg
->VersionList
== 0 || CandidateVer
== 0)
717 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
718 // ---------------------------------------------------------------------
720 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver
)
726 for (const char *I
= Ver
; *I
!= 0; I
++)