]>
git.saurik.com Git - apt.git/blob - apt-pkg/depcache.cc
68c452f31f95504ba67b08ac5b03c26cf5dd4940
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: depcache.cc,v 1.4 1998/10/24 04:58:05 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 Dependancy 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 Dependancy 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
;
219 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
!= (Version
*)Pkg
.CurrentVer() &&
222 iUsrSize
+= Mult
*(P
.InstVerIter(*this)->InstalledSize
-
223 Pkg
.CurrentVer()->InstalledSize
);
224 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
228 if (Pkg
->CurrentVer
!= 0 && P
.InstallVer
== 0)
229 iUsrSize
-= Mult
*Pkg
.CurrentVer()->InstalledSize
;
232 // DepCache::AddStates - Add the package to the state counter /*{{{*/
233 // ---------------------------------------------------------------------
234 /* This routine is tricky to use, you must make sure that it is never
235 called twice for the same package. This means the Remove/Add section
236 should be as short as possible and not encompass any code that will
237 calld Remove/Add itself. Remember, dependencies can be circular so
238 while processing a dep for Pkg it is possible that Add/Remove
239 will be called on Pkg */
240 void pkgDepCache::AddStates(const PkgIterator
&Pkg
,int Add
)
242 StateCache
&State
= PkgState
[Pkg
->ID
];
244 // The Package is broken
245 if ((State
.DepState
& DepInstMin
) != DepInstMin
)
249 if (Pkg
.State() != PkgIterator::NeedsNothing
)
253 if (Pkg
->CurrentVer
== 0)
255 if (State
.Mode
== ModeInstall
)
260 // Installed, no upgrade
261 if (State
.Upgradable() == false)
263 if (State
.Mode
== ModeDelete
)
268 // Alll 3 are possible
269 if (State
.Mode
== ModeDelete
)
271 if (State
.Mode
== ModeKeep
)
273 if (State
.Mode
== ModeInstall
)
277 // DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
278 // ---------------------------------------------------------------------
279 /* The or group results are stored in the last item of the or group. This
280 allows easy detection of the state of a whole or'd group. */
281 void pkgDepCache::BuildGroupOrs(VerIterator
const &V
)
283 unsigned char Group
= 0;
285 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
287 // Build the dependency state.
288 unsigned char &State
= DepState
[D
->ID
];
290 /* Invert for Conflicts. We have to do this twice to get the
291 right sense for a conflicts group */
292 if (D
->Type
== Dep::Conflicts
)
295 // Add to the group if we are within an or..
298 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
301 // Invert for Conflicts
302 if (D
->Type
== Dep::Conflicts
)
307 // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
308 // ---------------------------------------------------------------------
309 /* This is used to run over a dependency list and determine the dep
310 state of the list, filtering it through both a Min check and a Policy
311 check. The return result will have SetMin/SetPolicy low if a check
312 fails. It uses the DepState cache for it's computations. */
313 unsigned char pkgDepCache::VersionState(DepIterator D
,unsigned char Check
,
314 unsigned char SetMin
,
315 unsigned char SetPolicy
)
317 unsigned char Dep
= 0xFF;
319 while (D
.end() != true)
321 // Compute a single dependency element (glob or)
322 DepIterator Start
= D
;
323 unsigned char State
= 0;
324 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
326 State
|= DepState
[D
->ID
];
327 LastOR
= (D
->CompareOp
& Dep::Or
) == Dep::Or
;
330 // Minimum deps that must be satisfied to have a working package
331 if (Start
.IsCritical() == true)
332 if ((State
& Check
) != Check
)
335 // Policy deps that must be satisfied to install the package
336 if (IsImportantDep(Start
) == true &&
337 (State
& Check
) != Check
)
344 // DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
345 // ---------------------------------------------------------------------
346 /* This is the main dependency computation bit. It computes the 3 main
347 results for a dependencys, Now, Install and Candidate. Callers must
348 invert the result if dealing with conflicts. */
349 unsigned char pkgDepCache::DependencyState(DepIterator
&D
)
351 unsigned char State
= 0;
353 if (CheckDep(D
,NowVersion
) == true)
355 if (CheckDep(D
,InstallVersion
) == true)
357 if (CheckDep(D
,CandidateVersion
) == true)
363 // DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
364 // ---------------------------------------------------------------------
365 /* This determines the combined dependency representation of a package
366 for its two states now and install. This is done by using the pre-generated
367 dependency information. */
368 void pkgDepCache::UpdateVerState(PkgIterator Pkg
)
370 // Empty deps are always true
371 StateCache
&State
= PkgState
[Pkg
->ID
];
372 State
.DepState
= 0xFF;
374 // Check the Current state
375 if (Pkg
->CurrentVer
!= 0)
377 DepIterator D
= Pkg
.CurrentVer().DependsList();
378 State
.DepState
&= VersionState(D
,DepNow
,DepNowMin
,DepNowPolicy
);
381 /* Check the candidate state. We do not compare against the whole as
382 a candidate state but check the candidate version against the
384 if (State
.CandidateVer
!= 0)
386 DepIterator D
= State
.CandidateVerIter(*this).DependsList();
387 State
.DepState
&= VersionState(D
,DepInstall
,DepCandMin
,DepCandPolicy
);
390 // Check target state which can only be current or installed
391 if (State
.InstallVer
!= 0)
393 DepIterator D
= State
.InstVerIter(*this).DependsList();
394 State
.DepState
&= VersionState(D
,DepInstall
,DepInstMin
,DepInstPolicy
);
398 // DepCache::Update - Figure out all the state information /*{{{*/
399 // ---------------------------------------------------------------------
400 /* This will figure out the state of all the packages and all the
401 dependencies based on the current policy. */
402 void pkgDepCache::Update(OpProgress
*Prog
)
412 // Perform the depends pass
414 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
416 if (Prog
!= 0 && Done%20
== 0)
417 Prog
->Progress(Done
);
418 for (VerIterator V
= I
.VersionList(); V
.end() != true; V
++)
420 unsigned char Group
= 0;
422 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
424 // Build the dependency state.
425 unsigned char &State
= DepState
[D
->ID
];
426 State
= DependencyState(D
);;
428 // Add to the group if we are within an or..
431 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
434 // Invert for Conflicts
435 if (D
->Type
== Dep::Conflicts
)
440 // Compute the pacakge dependency state and size additions
447 Prog
->Progress(Done
);
450 // DepCache::Update - Update the deps list of a package /*{{{*/
451 // ---------------------------------------------------------------------
452 /* This is a helper for update that only does the dep portion of the scan.
453 It is mainly ment to scan reverse dependencies. */
454 void pkgDepCache::Update(DepIterator D
)
456 // Update the reverse deps
457 for (;D
.end() != true; D
++)
459 unsigned char &State
= DepState
[D
->ID
];
460 State
= DependencyState(D
);
462 // Invert for Conflicts
463 if (D
->Type
== Dep::Conflicts
)
466 RemoveStates(D
.ParentPkg());
467 BuildGroupOrs(D
.ParentVer());
468 UpdateVerState(D
.ParentPkg());
469 AddStates(D
.ParentPkg());
473 // DepCache::Update - Update the related deps of a package /*{{{*/
474 // ---------------------------------------------------------------------
475 /* This is called whenever the state of a package changes. It updates
476 all cached dependencies related to this package. */
477 void pkgDepCache::Update(PkgIterator
const &Pkg
)
479 // Recompute the dep of the package
484 // Update the reverse deps
485 Update(Pkg
.RevDependsList());
487 // Update the provides map for the current ver
488 if (Pkg
->CurrentVer
!= 0)
489 for (PrvIterator P
= Pkg
.CurrentVer().ProvidesList();
490 P
.end() != true; P
++)
491 Update(P
.ParentPkg().RevDependsList());
493 // Update the provides map for the candidate ver
494 for (PrvIterator P
= PkgState
[Pkg
->ID
].CandidateVerIter(*this).ProvidesList();
495 P
.end() != true; P
++)
496 Update(P
.ParentPkg().RevDependsList());
501 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
502 // ---------------------------------------------------------------------
504 void pkgDepCache::MarkKeep(PkgIterator
const &Pkg
,bool Soft
)
506 // Simplifies other routines.
507 if (Pkg
.end() == true)
510 /* We changed the soft state all the time so the UI is a bit nicer
512 StateCache
&P
= PkgState
[Pkg
->ID
];
514 P
.iFlags
|= AutoKept
;
516 P
.iFlags
&= ~AutoKept
;
518 // Check that it is not already kept
519 if (P
.Mode
== ModeKeep
)
522 // We dont even try to keep virtual packages..
523 if (Pkg
->VersionList
== 0)
526 P
.Flags
&= ~Flag::Auto
;
531 if (Pkg
->CurrentVer
== 0)
534 P
.InstallVer
= Pkg
.CurrentVer();
543 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
544 // ---------------------------------------------------------------------
546 void pkgDepCache::MarkDelete(PkgIterator
const &Pkg
)
548 // Simplifies other routines.
549 if (Pkg
.end() == true)
552 // Check that it is not already marked for delete
553 StateCache
&P
= PkgState
[Pkg
->ID
];
554 P
.iFlags
&= ~AutoKept
;
555 if (P
.Mode
== ModeDelete
|| P
.InstallVer
== 0)
558 // We dont even try to delete virtual packages..
559 if (Pkg
->VersionList
== 0)
567 P
.Flags
&= Flag::Auto
;
574 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
575 // ---------------------------------------------------------------------
577 void pkgDepCache::MarkInstall(PkgIterator
const &Pkg
,bool AutoInst
)
579 // Simplifies other routines.
580 if (Pkg
.end() == true)
583 /* Check that it is not already marked for install and that it can be
585 StateCache
&P
= PkgState
[Pkg
->ID
];
586 P
.iFlags
&= ~AutoKept
;
587 if (P
.InstBroken() == false && (P
.Mode
== ModeInstall
||
588 P
.CandidateVer
== (Version
*)Pkg
.CurrentVer()))
590 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer() && P
.InstallVer
== 0)
595 // We dont even try to install virtual packages..
596 if (Pkg
->VersionList
== 0)
599 /* Target the candidate version and remove the autoflag. We reset the
600 autoflag below if this was called recursively. Otherwise the user
601 should have the ability to de-auto a package by changing its state */
605 P
.Mode
= ModeInstall
;
606 P
.InstallVer
= P
.CandidateVer
;
607 P
.Flags
&= ~Flag::Auto
;
608 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer())
615 if (AutoInst
== false)
618 DepIterator Dep
= P
.InstVerIter(*this).DependsList();
619 for (; Dep
.end() != true;)
622 DepIterator Start
= Dep
;
624 for (bool LastOR
= true; Dep
.end() == false && LastOR
== true; Dep
++)
626 LastOR
= (Dep
->CompareOp
& Dep::Or
) == Dep::Or
;
628 if ((DepState
[Dep
->ID
] & DepInstall
) == DepInstall
)
632 // Dep is satisfied okay.
636 /* Check if this dep should be consider for install. If it is a user
637 defined important dep and we are installed a new package then
638 it will be installed. Otherwise we only worry about critical deps */
639 if (IsImportantDep(Start
) == false)
641 if (Pkg
->CurrentVer
!= 0 && Start
.IsCritical() == false)
644 // Now we have to take action...
645 PkgIterator P
= Start
.SmartTargetPkg();
646 if ((DepState
[Start
->ID
] & DepCVer
) == DepCVer
)
650 // Set the autoflag, after MarkInstall because MarkInstall unsets it
651 if (P
->CurrentVer
== 0)
652 PkgState
[P
->ID
].Flags
|= Flag::Auto
;
657 // For conflicts we just de-install the package and mark as auto
658 if (Start
->Type
== Dep::Conflicts
)
660 Version
**List
= Start
.AllTargets();
661 for (Version
**I
= List
; *I
!= 0; I
++)
663 VerIterator
Ver(*this,*I
);
664 PkgIterator Pkg
= Ver
.ParentPkg();
667 PkgState
[Pkg
->ID
].Flags
|= Flag::Auto
;
676 // StateCache::Update - Compute the various static display things /*{{{*/
677 // ---------------------------------------------------------------------
678 /* This is called whenever the Candidate version changes. */
679 void pkgDepCache::StateCache::Update(PkgIterator Pkg
,pkgCache
&Cache
)
682 VerIterator Ver
= CandidateVerIter(Cache
);
684 // Use a null string or the version string
685 if (Ver
.end() == true)
688 CandVersion
= Ver
.VerStr();
690 // Find the current version
692 if (Pkg
->CurrentVer
!= 0)
693 CurVersion
= Pkg
.CurrentVer().VerStr();
695 // Strip off the epochs for display
696 CurVersion
= StripEpoch(CurVersion
);
697 CandVersion
= StripEpoch(CandVersion
);
699 // Figure out if its up or down or equal
700 Status
= Ver
.CompareVer(Pkg
.CurrentVer());
701 if (Pkg
->CurrentVer
== 0 || Pkg
->VersionList
== 0 || CandidateVer
== 0)
705 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
706 // ---------------------------------------------------------------------
708 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver
)
714 for (const char *I
= Ver
; *I
!= 0; I
++)