]>
git.saurik.com Git - apt.git/blob - apt-pkg/depcache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: depcache.cc,v 1.14 1998/12/22 08:01: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>
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
)
220 iUsrSize
+= Mult
*P
.InstVerIter(*this)->InstalledSize
;
224 // Compute the size data
225 if (P
.NewInstall() == true)
227 iUsrSize
+= Mult
*P
.InstVerIter(*this)->InstalledSize
;
228 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
233 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
!= (Version
*)Pkg
.CurrentVer() &&
236 iUsrSize
+= Mult
*((signed)P
.InstVerIter(*this)->InstalledSize
-
237 (signed)Pkg
.CurrentVer()->InstalledSize
);
238 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
243 if (Pkg
.State() == pkgCache::PkgIterator::NeedsUnpack
&&
246 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
251 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
== 0)
253 iUsrSize
-= Mult
*Pkg
.CurrentVer()->InstalledSize
;
258 // DepCache::AddStates - Add the package to the state counter /*{{{*/
259 // ---------------------------------------------------------------------
260 /* This routine is tricky to use, you must make sure that it is never
261 called twice for the same package. This means the Remove/Add section
262 should be as short as possible and not encompass any code that will
263 calld Remove/Add itself. Remember, dependencies can be circular so
264 while processing a dep for Pkg it is possible that Add/Remove
265 will be called on Pkg */
266 void pkgDepCache::AddStates(const PkgIterator
&Pkg
,int Add
)
268 StateCache
&State
= PkgState
[Pkg
->ID
];
270 // The Package is broken
271 if ((State
.DepState
& DepInstMin
) != DepInstMin
)
275 if (Pkg
.State() != PkgIterator::NeedsNothing
)
279 if (Pkg
->CurrentVer
== 0)
281 if (State
.Mode
== ModeInstall
)
286 // Installed, no upgrade
287 if (State
.Upgradable() == false)
289 if (State
.Mode
== ModeDelete
)
294 // Alll 3 are possible
295 if (State
.Mode
== ModeDelete
)
297 if (State
.Mode
== ModeKeep
)
299 if (State
.Mode
== ModeInstall
)
303 // DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
304 // ---------------------------------------------------------------------
305 /* The or group results are stored in the last item of the or group. This
306 allows easy detection of the state of a whole or'd group. */
307 void pkgDepCache::BuildGroupOrs(VerIterator
const &V
)
309 unsigned char Group
= 0;
311 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
313 // Build the dependency state.
314 unsigned char &State
= DepState
[D
->ID
];
316 /* Invert for Conflicts. We have to do this twice to get the
317 right sense for a conflicts group */
318 if (D
->Type
== Dep::Conflicts
)
321 // Add to the group if we are within an or..
325 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
328 // Invert for Conflicts
329 if (D
->Type
== Dep::Conflicts
)
334 // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
335 // ---------------------------------------------------------------------
336 /* This is used to run over a dependency list and determine the dep
337 state of the list, filtering it through both a Min check and a Policy
338 check. The return result will have SetMin/SetPolicy low if a check
339 fails. It uses the DepState cache for it's computations. */
340 unsigned char pkgDepCache::VersionState(DepIterator D
,unsigned char Check
,
341 unsigned char SetMin
,
342 unsigned char SetPolicy
)
344 unsigned char Dep
= 0xFF;
346 while (D
.end() != true)
348 // Compute a single dependency element (glob or)
349 DepIterator Start
= D
;
350 unsigned char State
= 0;
351 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
353 State
|= DepState
[D
->ID
];
354 LastOR
= (D
->CompareOp
& Dep::Or
) == Dep::Or
;
357 // Minimum deps that must be satisfied to have a working package
358 if (Start
.IsCritical() == true)
359 if ((State
& Check
) != Check
)
362 // Policy deps that must be satisfied to install the package
363 if (IsImportantDep(Start
) == true &&
364 (State
& Check
) != Check
)
371 // DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
372 // ---------------------------------------------------------------------
373 /* This is the main dependency computation bit. It computes the 3 main
374 results for a dependencys, Now, Install and Candidate. Callers must
375 invert the result if dealing with conflicts. */
376 unsigned char pkgDepCache::DependencyState(DepIterator
&D
)
378 unsigned char State
= 0;
380 if (CheckDep(D
,NowVersion
) == true)
382 if (CheckDep(D
,InstallVersion
) == true)
384 if (CheckDep(D
,CandidateVersion
) == true)
390 // DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
391 // ---------------------------------------------------------------------
392 /* This determines the combined dependency representation of a package
393 for its two states now and install. This is done by using the pre-generated
394 dependency information. */
395 void pkgDepCache::UpdateVerState(PkgIterator Pkg
)
397 // Empty deps are always true
398 StateCache
&State
= PkgState
[Pkg
->ID
];
399 State
.DepState
= 0xFF;
401 // Check the Current state
402 if (Pkg
->CurrentVer
!= 0)
404 DepIterator D
= Pkg
.CurrentVer().DependsList();
405 State
.DepState
&= VersionState(D
,DepNow
,DepNowMin
,DepNowPolicy
);
408 /* Check the candidate state. We do not compare against the whole as
409 a candidate state but check the candidate version against the
411 if (State
.CandidateVer
!= 0)
413 DepIterator D
= State
.CandidateVerIter(*this).DependsList();
414 State
.DepState
&= VersionState(D
,DepInstall
,DepCandMin
,DepCandPolicy
);
417 // Check target state which can only be current or installed
418 if (State
.InstallVer
!= 0)
420 DepIterator D
= State
.InstVerIter(*this).DependsList();
421 State
.DepState
&= VersionState(D
,DepInstall
,DepInstMin
,DepInstPolicy
);
425 // DepCache::Update - Figure out all the state information /*{{{*/
426 // ---------------------------------------------------------------------
427 /* This will figure out the state of all the packages and all the
428 dependencies based on the current policy. */
429 void pkgDepCache::Update(OpProgress
*Prog
)
439 // Perform the depends pass
441 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
443 if (Prog
!= 0 && Done%20
== 0)
444 Prog
->Progress(Done
);
445 for (VerIterator V
= I
.VersionList(); V
.end() != true; V
++)
447 unsigned char Group
= 0;
449 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
451 // Build the dependency state.
452 unsigned char &State
= DepState
[D
->ID
];
453 State
= DependencyState(D
);;
455 // Add to the group if we are within an or..
458 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
461 // Invert for Conflicts
462 if (D
->Type
== Dep::Conflicts
)
467 // Compute the pacakge dependency state and size additions
474 Prog
->Progress(Done
);
477 // DepCache::Update - Update the deps list of a package /*{{{*/
478 // ---------------------------------------------------------------------
479 /* This is a helper for update that only does the dep portion of the scan.
480 It is mainly ment to scan reverse dependencies. */
481 void pkgDepCache::Update(DepIterator D
)
483 // Update the reverse deps
484 for (;D
.end() != true; D
++)
486 unsigned char &State
= DepState
[D
->ID
];
487 State
= DependencyState(D
);
489 // Invert for Conflicts
490 if (D
->Type
== Dep::Conflicts
)
493 RemoveStates(D
.ParentPkg());
494 BuildGroupOrs(D
.ParentVer());
495 UpdateVerState(D
.ParentPkg());
496 AddStates(D
.ParentPkg());
500 // DepCache::Update - Update the related deps of a package /*{{{*/
501 // ---------------------------------------------------------------------
502 /* This is called whenever the state of a package changes. It updates
503 all cached dependencies related to this package. */
504 void pkgDepCache::Update(PkgIterator
const &Pkg
)
506 // Recompute the dep of the package
511 // Update the reverse deps
512 Update(Pkg
.RevDependsList());
514 // Update the provides map for the current ver
515 if (Pkg
->CurrentVer
!= 0)
516 for (PrvIterator P
= Pkg
.CurrentVer().ProvidesList();
517 P
.end() != true; P
++)
518 Update(P
.ParentPkg().RevDependsList());
520 // Update the provides map for the candidate ver
521 for (PrvIterator P
= PkgState
[Pkg
->ID
].CandidateVerIter(*this).ProvidesList();
522 P
.end() != true; P
++)
523 Update(P
.ParentPkg().RevDependsList());
528 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
529 // ---------------------------------------------------------------------
531 void pkgDepCache::MarkKeep(PkgIterator
const &Pkg
,bool Soft
)
533 // Simplifies other routines.
534 if (Pkg
.end() == true)
537 /* We changed the soft state all the time so the UI is a bit nicer
539 StateCache
&P
= PkgState
[Pkg
->ID
];
541 P
.iFlags
|= AutoKept
;
543 P
.iFlags
&= ~AutoKept
;
545 // Check that it is not already kept
546 if (P
.Mode
== ModeKeep
)
549 // We dont even try to keep virtual packages..
550 if (Pkg
->VersionList
== 0)
553 P
.Flags
&= ~Flag::Auto
;
558 if (Pkg
->CurrentVer
== 0)
561 P
.InstallVer
= Pkg
.CurrentVer();
570 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
571 // ---------------------------------------------------------------------
573 void pkgDepCache::MarkDelete(PkgIterator
const &Pkg
)
575 // Simplifies other routines.
576 if (Pkg
.end() == true)
579 // Check that it is not already marked for delete
580 StateCache
&P
= PkgState
[Pkg
->ID
];
581 P
.iFlags
&= ~AutoKept
;
582 if (P
.Mode
== ModeDelete
|| P
.InstallVer
== 0)
585 // We dont even try to delete virtual packages..
586 if (Pkg
->VersionList
== 0)
592 if (Pkg
->CurrentVer
== 0)
597 P
.Flags
&= Flag::Auto
;
604 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
605 // ---------------------------------------------------------------------
607 void pkgDepCache::MarkInstall(PkgIterator
const &Pkg
,bool AutoInst
)
609 // Simplifies other routines.
610 if (Pkg
.end() == true)
613 /* Check that it is not already marked for install and that it can be
615 StateCache
&P
= PkgState
[Pkg
->ID
];
616 P
.iFlags
&= ~AutoKept
;
617 if (P
.InstBroken() == false && (P
.Mode
== ModeInstall
||
618 P
.CandidateVer
== (Version
*)Pkg
.CurrentVer()))
620 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer() && P
.InstallVer
== 0)
625 // We dont even try to install virtual packages..
626 if (Pkg
->VersionList
== 0)
629 /* Target the candidate version and remove the autoflag. We reset the
630 autoflag below if this was called recursively. Otherwise the user
631 should have the ability to de-auto a package by changing its state */
635 P
.Mode
= ModeInstall
;
636 P
.InstallVer
= P
.CandidateVer
;
637 P
.Flags
&= ~Flag::Auto
;
638 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer())
645 if (AutoInst
== false)
648 DepIterator Dep
= P
.InstVerIter(*this).DependsList();
649 for (; Dep
.end() != true;)
652 DepIterator Start
= Dep
;
654 for (bool LastOR
= true; Dep
.end() == false && LastOR
== true; Dep
++)
656 LastOR
= (Dep
->CompareOp
& Dep::Or
) == Dep::Or
;
658 if ((DepState
[Dep
->ID
] & DepInstall
) == DepInstall
)
662 // Dep is satisfied okay.
666 /* Check if this dep should be consider for install. If it is a user
667 defined important dep and we are installed a new package then
668 it will be installed. Otherwise we only worry about critical deps */
669 if (IsImportantDep(Start
) == false)
671 if (Pkg
->CurrentVer
!= 0 && Start
.IsCritical() == false)
674 // Now we have to take action...
675 PkgIterator P
= Start
.SmartTargetPkg();
676 if ((DepState
[Start
->ID
] & DepCVer
) == DepCVer
)
680 // Set the autoflag, after MarkInstall because MarkInstall unsets it
681 if (P
->CurrentVer
== 0)
682 PkgState
[P
->ID
].Flags
|= Flag::Auto
;
687 // For conflicts we just de-install the package and mark as auto
688 if (Start
->Type
== Dep::Conflicts
)
690 Version
**List
= Start
.AllTargets();
691 for (Version
**I
= List
; *I
!= 0; I
++)
693 VerIterator
Ver(*this,*I
);
694 PkgIterator Pkg
= Ver
.ParentPkg();
697 PkgState
[Pkg
->ID
].Flags
|= Flag::Auto
;
706 // StateCache::Update - Compute the various static display things /*{{{*/
707 // ---------------------------------------------------------------------
708 /* This is called whenever the Candidate version changes. */
709 void pkgDepCache::StateCache::Update(PkgIterator Pkg
,pkgCache
&Cache
)
712 VerIterator Ver
= CandidateVerIter(Cache
);
714 // Use a null string or the version string
715 if (Ver
.end() == true)
718 CandVersion
= Ver
.VerStr();
720 // Find the current version
722 if (Pkg
->CurrentVer
!= 0)
723 CurVersion
= Pkg
.CurrentVer().VerStr();
725 // Strip off the epochs for display
726 CurVersion
= StripEpoch(CurVersion
);
727 CandVersion
= StripEpoch(CandVersion
);
729 // Figure out if its up or down or equal
730 Status
= Ver
.CompareVer(Pkg
.CurrentVer());
731 if (Pkg
->CurrentVer
== 0 || Pkg
->VersionList
== 0 || CandidateVer
== 0)
735 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
736 // ---------------------------------------------------------------------
738 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver
)
744 for (const char *I
= Ver
; *I
!= 0; I
++)