]>
git.saurik.com Git - apt.git/blob - apt-pkg/depcache.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: depcache.cc,v 1.18 1999/04/28 22:48:45 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 && P
.InstallVer
!= (Version
*)Pkg
.CurrentVer() &&
222 iUsrSize
+= Mult
*((signed)P
.InstVerIter(*this)->InstalledSize
-
223 (signed)Pkg
.CurrentVer()->InstalledSize
);
224 iDownloadSize
+= Mult
*P
.InstVerIter(*this)->Size
;
229 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..
311 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
314 // Invert for Conflicts
315 if (D
->Type
== Dep::Conflicts
)
320 // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
321 // ---------------------------------------------------------------------
322 /* This is used to run over a dependency list and determine the dep
323 state of the list, filtering it through both a Min check and a Policy
324 check. The return result will have SetMin/SetPolicy low if a check
325 fails. It uses the DepState cache for it's computations. */
326 unsigned char pkgDepCache::VersionState(DepIterator D
,unsigned char Check
,
327 unsigned char SetMin
,
328 unsigned char SetPolicy
)
330 unsigned char Dep
= 0xFF;
332 while (D
.end() != true)
334 // Compute a single dependency element (glob or)
335 DepIterator Start
= D
;
336 unsigned char State
= 0;
337 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
339 State
|= DepState
[D
->ID
];
340 LastOR
= (D
->CompareOp
& Dep::Or
) == Dep::Or
;
343 // Minimum deps that must be satisfied to have a working package
344 if (Start
.IsCritical() == true)
345 if ((State
& Check
) != Check
)
348 // Policy deps that must be satisfied to install the package
349 if (IsImportantDep(Start
) == true &&
350 (State
& Check
) != Check
)
357 // DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
358 // ---------------------------------------------------------------------
359 /* This is the main dependency computation bit. It computes the 3 main
360 results for a dependencys, Now, Install and Candidate. Callers must
361 invert the result if dealing with conflicts. */
362 unsigned char pkgDepCache::DependencyState(DepIterator
&D
)
364 unsigned char State
= 0;
366 if (CheckDep(D
,NowVersion
) == true)
368 if (CheckDep(D
,InstallVersion
) == true)
370 if (CheckDep(D
,CandidateVersion
) == true)
376 // DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
377 // ---------------------------------------------------------------------
378 /* This determines the combined dependency representation of a package
379 for its two states now and install. This is done by using the pre-generated
380 dependency information. */
381 void pkgDepCache::UpdateVerState(PkgIterator Pkg
)
383 // Empty deps are always true
384 StateCache
&State
= PkgState
[Pkg
->ID
];
385 State
.DepState
= 0xFF;
387 // Check the Current state
388 if (Pkg
->CurrentVer
!= 0)
390 DepIterator D
= Pkg
.CurrentVer().DependsList();
391 State
.DepState
&= VersionState(D
,DepNow
,DepNowMin
,DepNowPolicy
);
394 /* Check the candidate state. We do not compare against the whole as
395 a candidate state but check the candidate version against the
397 if (State
.CandidateVer
!= 0)
399 DepIterator D
= State
.CandidateVerIter(*this).DependsList();
400 State
.DepState
&= VersionState(D
,DepInstall
,DepCandMin
,DepCandPolicy
);
403 // Check target state which can only be current or installed
404 if (State
.InstallVer
!= 0)
406 DepIterator D
= State
.InstVerIter(*this).DependsList();
407 State
.DepState
&= VersionState(D
,DepInstall
,DepInstMin
,DepInstPolicy
);
411 // DepCache::Update - Figure out all the state information /*{{{*/
412 // ---------------------------------------------------------------------
413 /* This will figure out the state of all the packages and all the
414 dependencies based on the current policy. */
415 void pkgDepCache::Update(OpProgress
*Prog
)
425 // Perform the depends pass
427 for (PkgIterator I
= PkgBegin(); I
.end() != true; I
++,Done
++)
429 if (Prog
!= 0 && Done%20
== 0)
430 Prog
->Progress(Done
);
431 for (VerIterator V
= I
.VersionList(); V
.end() != true; V
++)
433 unsigned char Group
= 0;
435 for (DepIterator D
= V
.DependsList(); D
.end() != true; D
++)
437 // Build the dependency state.
438 unsigned char &State
= DepState
[D
->ID
];
439 State
= DependencyState(D
);;
441 // Add to the group if we are within an or..
444 if ((D
->CompareOp
& Dep::Or
) != Dep::Or
)
447 // Invert for Conflicts
448 if (D
->Type
== Dep::Conflicts
)
453 // Compute the pacakge dependency state and size additions
460 Prog
->Progress(Done
);
463 // DepCache::Update - Update the deps list of a package /*{{{*/
464 // ---------------------------------------------------------------------
465 /* This is a helper for update that only does the dep portion of the scan.
466 It is mainly ment to scan reverse dependencies. */
467 void pkgDepCache::Update(DepIterator D
)
469 // Update the reverse deps
470 for (;D
.end() != true; D
++)
472 unsigned char &State
= DepState
[D
->ID
];
473 State
= DependencyState(D
);
475 // Invert for Conflicts
476 if (D
->Type
== Dep::Conflicts
)
479 RemoveStates(D
.ParentPkg());
480 BuildGroupOrs(D
.ParentVer());
481 UpdateVerState(D
.ParentPkg());
482 AddStates(D
.ParentPkg());
486 // DepCache::Update - Update the related deps of a package /*{{{*/
487 // ---------------------------------------------------------------------
488 /* This is called whenever the state of a package changes. It updates
489 all cached dependencies related to this package. */
490 void pkgDepCache::Update(PkgIterator
const &Pkg
)
492 // Recompute the dep of the package
497 // Update the reverse deps
498 Update(Pkg
.RevDependsList());
500 // Update the provides map for the current ver
501 if (Pkg
->CurrentVer
!= 0)
502 for (PrvIterator P
= Pkg
.CurrentVer().ProvidesList();
503 P
.end() != true; P
++)
504 Update(P
.ParentPkg().RevDependsList());
506 // Update the provides map for the candidate ver
507 for (PrvIterator P
= PkgState
[Pkg
->ID
].CandidateVerIter(*this).ProvidesList();
508 P
.end() != true; P
++)
509 Update(P
.ParentPkg().RevDependsList());
514 // DepCache::MarkKeep - Put the package in the keep state /*{{{*/
515 // ---------------------------------------------------------------------
517 void pkgDepCache::MarkKeep(PkgIterator
const &Pkg
,bool Soft
)
519 // Simplifies other routines.
520 if (Pkg
.end() == true)
523 /* Reject an attempt to keep a non-source broken installed package, those
525 if (Pkg
.State() == PkgIterator::NeedsUnpack
&&
526 Pkg
.CurrentVer().Downloadable() == false)
529 /* We changed the soft state all the time so the UI is a bit nicer
531 StateCache
&P
= PkgState
[Pkg
->ID
];
533 P
.iFlags
|= AutoKept
;
535 P
.iFlags
&= ~AutoKept
;
537 // Check that it is not already kept
538 if (P
.Mode
== ModeKeep
)
541 // We dont even try to keep virtual packages..
542 if (Pkg
->VersionList
== 0)
545 P
.Flags
&= ~Flag::Auto
;
550 if (Pkg
->CurrentVer
== 0)
553 P
.InstallVer
= Pkg
.CurrentVer();
562 // DepCache::MarkDelete - Put the package in the delete state /*{{{*/
563 // ---------------------------------------------------------------------
565 void pkgDepCache::MarkDelete(PkgIterator
const &Pkg
)
567 // Simplifies other routines.
568 if (Pkg
.end() == true)
571 // Check that it is not already marked for delete
572 StateCache
&P
= PkgState
[Pkg
->ID
];
573 P
.iFlags
&= ~AutoKept
;
574 if (P
.Mode
== ModeDelete
|| P
.InstallVer
== 0)
577 // We dont even try to delete virtual packages..
578 if (Pkg
->VersionList
== 0)
584 if (Pkg
->CurrentVer
== 0)
589 P
.Flags
&= Flag::Auto
;
596 // DepCache::MarkInstall - Put the package in the install state /*{{{*/
597 // ---------------------------------------------------------------------
599 void pkgDepCache::MarkInstall(PkgIterator
const &Pkg
,bool AutoInst
)
601 // Simplifies other routines.
602 if (Pkg
.end() == true)
605 /* Check that it is not already marked for install and that it can be
607 StateCache
&P
= PkgState
[Pkg
->ID
];
608 P
.iFlags
&= ~AutoKept
;
609 if (P
.InstBroken() == false && (P
.Mode
== ModeInstall
||
610 P
.CandidateVer
== (Version
*)Pkg
.CurrentVer()))
612 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer() && P
.InstallVer
== 0)
617 // We dont even try to install virtual packages..
618 if (Pkg
->VersionList
== 0)
621 /* Target the candidate version and remove the autoflag. We reset the
622 autoflag below if this was called recursively. Otherwise the user
623 should have the ability to de-auto a package by changing its state */
627 P
.Mode
= ModeInstall
;
628 P
.InstallVer
= P
.CandidateVer
;
629 P
.Flags
&= ~Flag::Auto
;
630 if (P
.CandidateVer
== (Version
*)Pkg
.CurrentVer())
637 if (AutoInst
== false)
640 DepIterator Dep
= P
.InstVerIter(*this).DependsList();
641 for (; Dep
.end() != true;)
644 DepIterator Start
= Dep
;
646 for (bool LastOR
= true; Dep
.end() == false && LastOR
== true; Dep
++)
648 LastOR
= (Dep
->CompareOp
& Dep::Or
) == Dep::Or
;
650 if ((DepState
[Dep
->ID
] & DepInstall
) == DepInstall
)
654 // Dep is satisfied okay.
658 /* Check if this dep should be consider for install. If it is a user
659 defined important dep and we are installed a new package then
660 it will be installed. Otherwise we only worry about critical deps */
661 if (IsImportantDep(Start
) == false)
663 if (Pkg
->CurrentVer
!= 0 && Start
.IsCritical() == false)
666 // Now we have to take action...
667 PkgIterator P
= Start
.SmartTargetPkg();
668 if ((DepState
[Start
->ID
] & DepCVer
) == DepCVer
)
672 // Set the autoflag, after MarkInstall because MarkInstall unsets it
673 if (P
->CurrentVer
== 0)
674 PkgState
[P
->ID
].Flags
|= Flag::Auto
;
679 // For conflicts we just de-install the package and mark as auto
680 if (Start
->Type
== Dep::Conflicts
)
682 Version
**List
= Start
.AllTargets();
683 for (Version
**I
= List
; *I
!= 0; I
++)
685 VerIterator
Ver(*this,*I
);
686 PkgIterator Pkg
= Ver
.ParentPkg();
689 PkgState
[Pkg
->ID
].Flags
|= Flag::Auto
;
698 // StateCache::Update - Compute the various static display things /*{{{*/
699 // ---------------------------------------------------------------------
700 /* This is called whenever the Candidate version changes. */
701 void pkgDepCache::StateCache::Update(PkgIterator Pkg
,pkgCache
&Cache
)
704 VerIterator Ver
= CandidateVerIter(Cache
);
706 // Use a null string or the version string
707 if (Ver
.end() == true)
710 CandVersion
= Ver
.VerStr();
712 // Find the current version
714 if (Pkg
->CurrentVer
!= 0)
715 CurVersion
= Pkg
.CurrentVer().VerStr();
717 // Strip off the epochs for display
718 CurVersion
= StripEpoch(CurVersion
);
719 CandVersion
= StripEpoch(CandVersion
);
721 // Figure out if its up or down or equal
722 Status
= Ver
.CompareVer(Pkg
.CurrentVer());
723 if (Pkg
->CurrentVer
== 0 || Pkg
->VersionList
== 0 || CandidateVer
== 0)
727 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
728 // ---------------------------------------------------------------------
730 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver
)
736 for (const char *I
= Ver
; *I
!= 0; I
++)