]>
git.saurik.com Git - apt.git/blob - apt-pkg/depcache.cc
9535a79f160119f2e88d43056ddecbf57aa60358
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: depcache.cc,v 1.9 1998/12/07 23:54:42 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 if (Pkg
.State() == pkgCache::PkgIterator::NeedsConfigure
)
213 iUsrSize
+= Mult
*P
.InstVerIter(*this)->InstalledSize
;
217 // Compute the size data
218 if (P
.NewInstall() == true)
220 iUsrSize
+= Mult
*P
.InstVerIter(*this)->InstalledSize
;
221 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
226 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
!= (Version
*)Pkg
.CurrentVer() &&
229 iUsrSize
+= Mult
*((signed)P
.InstVerIter(*this)->InstalledSize
-
230 (signed)Pkg
.CurrentVer()->InstalledSize
);
231 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
236 if (Pkg
.State() == pkgCache::PkgIterator::NeedsUnpack
&&
239 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
244 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
== 0)
246 iUsrSize
-= Mult
*Pkg
.CurrentVer()->InstalledSize
;
251 // DepCache::AddStates - Add the package to the state counter /*{{{*/
252 // ---------------------------------------------------------------------
253 /* This routine is tricky to use, you must make sure that it is never
254 called twice for the same package. This means the Remove/Add section
255 should be as short as possible and not encompass any code that will
256 calld Remove/Add itself. Remember, dependencies can be circular so
257 while processing a dep for Pkg it is possible that Add/Remove
258 will be called on Pkg */
259 void pkgDepCache::AddStates(const PkgIterator
&Pkg
,int Add
)
261 StateCache
&State
= PkgState
[Pkg
->ID
];
263 // The Package is broken
264 if ((State
.DepState
& DepInstMin
) != DepInstMin
)
268 if (Pkg
.State() != PkgIterator::NeedsNothing
)
272 if (Pkg
->CurrentVer
== 0)
274 if (State
.Mode
== ModeInstall
)
279 // Installed, no upgrade
280 if (State
.Upgradable() == false)
282 if (State
.Mode
== ModeDelete
)
287 // Alll 3 are possible
288 if (State
.Mode
== ModeDelete
)
290 if (State
.Mode
== ModeKeep
)
292 if (State
.Mode
== ModeInstall
)
296 // DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
297 // ---------------------------------------------------------------------
298 /* The or group results are stored in the last item of the or group. This
299 allows easy detection of the state of a whole or'd group. */
300 void pkgDepCache::BuildGroupOrs(VerIterator
const &V
)
302 unsigned char Group
= 0;
304 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
306 // Build the dependency state.
307 unsigned char &State
= DepState
[D
->ID
];
309 /* Invert for Conflicts. We have to do this twice to get the
310 right sense for a conflicts group */
311 if (D
->Type
== Dep::Conflicts
)
314 // Add to the group if we are within an or..
318 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
321 // Invert for Conflicts
322 if (D
->Type
== Dep::Conflicts
)
327 // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
328 // ---------------------------------------------------------------------
329 /* This is used to run over a dependency list and determine the dep
330 state of the list, filtering it through both a Min check and a Policy
331 check. The return result will have SetMin/SetPolicy low if a check
332 fails. It uses the DepState cache for it's computations. */
333 unsigned char pkgDepCache::VersionState(DepIterator D
,unsigned char Check
,
334 unsigned char SetMin
,
335 unsigned char SetPolicy
)
337 unsigned char Dep
= 0xFF;
339 while (D
.end() != true)
341 // Compute a single dependency element (glob or)
342 DepIterator Start
= D
;
343 unsigned char State
= 0;
344 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
346 State
|= DepState
[D
->ID
];
347 LastOR
= (D
->CompareOp
& Dep::Or
) == Dep::Or
;
350 // Minimum deps that must be satisfied to have a working package
351 if (Start
.IsCritical() == true)
352 if ((State
& Check
) != Check
)
355 // Policy deps that must be satisfied to install the package
356 if (IsImportantDep(Start
) == true &&
357 (State
& Check
) != Check
)
364 // DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
365 // ---------------------------------------------------------------------
366 /* This is the main dependency computation bit. It computes the 3 main
367 results for a dependencys, Now, Install and Candidate. Callers must
368 invert the result if dealing with conflicts. */
369 unsigned char pkgDepCache::DependencyState(DepIterator
&D
)
371 unsigned char State
= 0;
373 if (CheckDep(D
,NowVersion
) == true)
375 if (CheckDep(D
,InstallVersion
) == true)
377 if (CheckDep(D
,CandidateVersion
) == true)
383 // DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
384 // ---------------------------------------------------------------------
385 /* This determines the combined dependency representation of a package
386 for its two states now and install. This is done by using the pre-generated
387 dependency information. */
388 void pkgDepCache::UpdateVerState(PkgIterator Pkg
)
390 // Empty deps are always true
391 StateCache
&State
= PkgState
[Pkg
->ID
];
392 State
.DepState
= 0xFF;
394 // Check the Current state
395 if (Pkg
->CurrentVer
!= 0)
397 DepIterator D
= Pkg
.CurrentVer().DependsList();
398 State
.DepState
&= VersionState(D
,DepNow
,DepNowMin
,DepNowPolicy
);
401 /* Check the candidate state. We do not compare against the whole as
402 a candidate state but check the candidate version against the
404 if (State
.CandidateVer
!= 0)
406 DepIterator D
= State
.CandidateVerIter(*this).DependsList();
407 State
.DepState
&= VersionState(D
,DepInstall
,DepCandMin
,DepCandPolicy
);
410 // Check target state which can only be current or installed
411 if (State
.InstallVer
!= 0)
413 DepIterator D
= State
.InstVerIter(*this).DependsList();
414 State
.DepState
&= VersionState(D
,DepInstall
,DepInstMin
,DepInstPolicy
);
418 // DepCache::Update - Figure out all the state information /*{{{*/
419 // ---------------------------------------------------------------------
420 /* This will figure out the state of all the packages and all the
421 dependencies based on the current policy. */
422 void pkgDepCache::Update(OpProgress
*Prog
)
432 // Perform the depends pass
434 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
436 if (Prog
!= 0 && Done%20
== 0)
437 Prog
->Progress(Done
);
438 for (VerIterator V
= I
.VersionList(); V
.end() != true; V
++)
440 unsigned char Group
= 0;
442 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
444 // Build the dependency state.
445 unsigned char &State
= DepState
[D
->ID
];
446 State
= DependencyState(D
);;
448 // Add to the group if we are within an or..
451 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
454 // Invert for Conflicts
455 if (D
->Type
== Dep::Conflicts
)
460 // Compute the pacakge dependency state and size additions
467 Prog
->Progress(Done
);
470 // DepCache::Update - Update the deps list of a package /*{{{*/
471 // ---------------------------------------------------------------------
472 /* This is a helper for update that only does the dep portion of the scan.
473 It is mainly ment to scan reverse dependencies. */
474 void pkgDepCache::Update(DepIterator D
)
476 // Update the reverse deps
477 for (;D
.end() != true; D
++)
479 unsigned char &State
= DepState
[D
->ID
];
480 State
= DependencyState(D
);
482 // Invert for Conflicts
483 if (D
->Type
== Dep::Conflicts
)
486 RemoveStates(D
.ParentPkg());
487 BuildGroupOrs(D
.ParentVer());
488 UpdateVerState(D
.ParentPkg());
489 AddStates(D
.ParentPkg());
493 // DepCache::Update - Update the related deps of a package /*{{{*/
494 // ---------------------------------------------------------------------
495 /* This is called whenever the state of a package changes. It updates
496 all cached dependencies related to this package. */
497 void pkgDepCache::Update(PkgIterator
const &Pkg
)
499 // Recompute the dep of the package
504 // Update the reverse deps
505 Update(Pkg
.RevDependsList());
507 // Update the provides map for the current ver
508 if (Pkg
->CurrentVer
!= 0)
509 for (PrvIterator P
= Pkg
.CurrentVer().ProvidesList();
510 P
.end() != true; P
++)
511 Update(P
.ParentPkg().RevDependsList());
513 // Update the provides map for the candidate ver
514 for (PrvIterator P
= PkgState
[Pkg
->ID
].CandidateVerIter(*this).ProvidesList();
515 P
.end() != true; P
++)
516 Update(P
.ParentPkg().RevDependsList());
521 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
522 // ---------------------------------------------------------------------
524 void pkgDepCache::MarkKeep(PkgIterator
const &Pkg
,bool Soft
)
526 // Simplifies other routines.
527 if (Pkg
.end() == true)
530 /* We changed the soft state all the time so the UI is a bit nicer
532 StateCache
&P
= PkgState
[Pkg
->ID
];
534 P
.iFlags
|= AutoKept
;
536 P
.iFlags
&= ~AutoKept
;
538 // Check that it is not already kept
539 if (P
.Mode
== ModeKeep
)
542 // We dont even try to keep virtual packages..
543 if (Pkg
->VersionList
== 0)
546 P
.Flags
&= ~Flag::Auto
;
551 if (Pkg
->CurrentVer
== 0)
554 P
.InstallVer
= Pkg
.CurrentVer();
563 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
564 // ---------------------------------------------------------------------
566 void pkgDepCache::MarkDelete(PkgIterator
const &Pkg
)
568 // Simplifies other routines.
569 if (Pkg
.end() == true)
572 // Check that it is not already marked for delete
573 StateCache
&P
= PkgState
[Pkg
->ID
];
574 P
.iFlags
&= ~AutoKept
;
575 if (P
.Mode
== ModeDelete
|| P
.InstallVer
== 0)
578 // We dont even try to delete virtual packages..
579 if (Pkg
->VersionList
== 0)
587 P
.Flags
&= Flag::Auto
;
594 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
595 // ---------------------------------------------------------------------
597 void pkgDepCache::MarkInstall(PkgIterator
const &Pkg
,bool AutoInst
)
599 // Simplifies other routines.
600 if (Pkg
.end() == true)
603 /* Check that it is not already marked for install and that it can be
605 StateCache
&P
= PkgState
[Pkg
->ID
];
606 P
.iFlags
&= ~AutoKept
;
607 if (P
.InstBroken() == false && (P
.Mode
== ModeInstall
||
608 P
.CandidateVer
== (Version
*)Pkg
.CurrentVer()))
610 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer() && P
.InstallVer
== 0)
615 // We dont even try to install virtual packages..
616 if (Pkg
->VersionList
== 0)
619 /* Target the candidate version and remove the autoflag. We reset the
620 autoflag below if this was called recursively. Otherwise the user
621 should have the ability to de-auto a package by changing its state */
625 P
.Mode
= ModeInstall
;
626 P
.InstallVer
= P
.CandidateVer
;
627 P
.Flags
&= ~Flag::Auto
;
628 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer())
635 if (AutoInst
== false)
638 DepIterator Dep
= P
.InstVerIter(*this).DependsList();
639 for (; Dep
.end() != true;)
642 DepIterator Start
= Dep
;
644 for (bool LastOR
= true; Dep
.end() == false && LastOR
== true; Dep
++)
646 LastOR
= (Dep
->CompareOp
& Dep::Or
) == Dep::Or
;
648 if ((DepState
[Dep
->ID
] & DepInstall
) == DepInstall
)
652 // Dep is satisfied okay.
656 /* Check if this dep should be consider for install. If it is a user
657 defined important dep and we are installed a new package then
658 it will be installed. Otherwise we only worry about critical deps */
659 if (IsImportantDep(Start
) == false)
661 if (Pkg
->CurrentVer
!= 0 && Start
.IsCritical() == false)
664 // Now we have to take action...
665 PkgIterator P
= Start
.SmartTargetPkg();
666 if ((DepState
[Start
->ID
] & DepCVer
) == DepCVer
)
670 // Set the autoflag, after MarkInstall because MarkInstall unsets it
671 if (P
->CurrentVer
== 0)
672 PkgState
[P
->ID
].Flags
|= Flag::Auto
;
677 // For conflicts we just de-install the package and mark as auto
678 if (Start
->Type
== Dep::Conflicts
)
680 Version
**List
= Start
.AllTargets();
681 for (Version
**I
= List
; *I
!= 0; I
++)
683 VerIterator
Ver(*this,*I
);
684 PkgIterator Pkg
= Ver
.ParentPkg();
687 PkgState
[Pkg
->ID
].Flags
|= Flag::Auto
;
696 // StateCache::Update - Compute the various static display things /*{{{*/
697 // ---------------------------------------------------------------------
698 /* This is called whenever the Candidate version changes. */
699 void pkgDepCache::StateCache::Update(PkgIterator Pkg
,pkgCache
&Cache
)
702 VerIterator Ver
= CandidateVerIter(Cache
);
704 // Use a null string or the version string
705 if (Ver
.end() == true)
708 CandVersion
= Ver
.VerStr();
710 // Find the current version
712 if (Pkg
->CurrentVer
!= 0)
713 CurVersion
= Pkg
.CurrentVer().VerStr();
715 // Strip off the epochs for display
716 CurVersion
= StripEpoch(CurVersion
);
717 CandVersion
= StripEpoch(CandVersion
);
719 // Figure out if its up or down or equal
720 Status
= Ver
.CompareVer(Pkg
.CurrentVer());
721 if (Pkg
->CurrentVer
== 0 || Pkg
->VersionList
== 0 || CandidateVer
== 0)
725 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
726 // ---------------------------------------------------------------------
728 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver
)
734 for (const char *I
= Ver
; *I
!= 0; I
++)