- initial import of revision 374 from cnc
[apt.git] / apt-pkg / depcache.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description                                                          /*{{{*/
3 // $Id: depcache.cc,v 1.1 2002/07/23 17:54:50 niemeyer Exp $
4 /* ######################################################################
5
6    Dependency Cache - Caches Dependency information.
7    
8    ##################################################################### */
9                                                                         /*}}}*/
10 // Include Files                                                        /*{{{*/
11 #ifdef __GNUG__
12 #pragma implementation "apt-pkg/depcache.h"
13 #endif
14 #include <apt-pkg/depcache.h>
15 #include <apt-pkg/version.h>
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/sptr.h>
18 #include <apt-pkg/algorithms.h>
19
20 // CNC:2002-07-05
21 #include <apt-pkg/pkgsystem.h>
22
23 // CNC:2003-03-17
24 #include <config.h>
25 #include <apt-pkg/luaiface.h>
26     
27 #include <apti18n.h>    
28                                                                         /*}}}*/
29
30 // DepCache::pkgDepCache - Constructors                                 /*{{{*/
31 // ---------------------------------------------------------------------
32 /* */
33 pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
34                 Cache(pCache), PkgState(0), DepState(0)
35 {
36    delLocalPolicy = 0;
37    LocalPolicy = Plcy;
38    if (LocalPolicy == 0)
39       delLocalPolicy = LocalPolicy = new Policy;
40 }
41                                                                         /*}}}*/
42 // DepCache::~pkgDepCache - Destructor                                  /*{{{*/
43 // ---------------------------------------------------------------------
44 /* */
45 pkgDepCache::~pkgDepCache()
46 {
47    delete [] PkgState;
48    delete [] DepState;
49    delete delLocalPolicy;
50 }
51                                                                         /*}}}*/
52 // DepCache::Init - Generate the initial extra structures.              /*{{{*/
53 // ---------------------------------------------------------------------
54 /* This allocats the extension buffers and initializes them. */
55 bool pkgDepCache::Init(OpProgress *Prog)
56 {
57    delete [] PkgState;
58    delete [] DepState;
59    PkgState = new StateCache[Head().PackageCount];
60    DepState = new unsigned char[Head().DependsCount];
61    memset(PkgState,0,sizeof(*PkgState)*Head().PackageCount);
62    memset(DepState,0,sizeof(*DepState)*Head().DependsCount); 
63
64    if (Prog != 0)
65    {
66       Prog->OverallProgress(0,2*Head().PackageCount,Head().PackageCount,
67                             _("Building Dependency Tree"));
68       Prog->SubProgress(Head().PackageCount,_("Candidate Versions"));
69    }
70    
71    /* Set the current state of everything. In this state all of the
72       packages are kept exactly as is. See AllUpgrade */
73    int Done = 0;
74    for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
75    {
76       if (Prog != 0)
77          Prog->Progress(Done);
78       
79       // Find the proper cache slot
80       StateCache &State = PkgState[I->ID];
81       State.iFlags = 0;
82       
83       // Figure out the install version
84       State.CandidateVer = GetCandidateVer(I);
85       State.InstallVer = I.CurrentVer();
86       State.Mode = ModeKeep;
87       
88       State.Update(I,*this);
89    }   
90    
91    if (Prog != 0)
92    {
93       
94       Prog->OverallProgress(Head().PackageCount,2*Head().PackageCount,
95                             Head().PackageCount,
96                             _("Building Dependency Tree"));
97       Prog->SubProgress(Head().PackageCount,_("Dependency Generation"));
98    }
99    
100    Update(Prog);
101
102 // CNC:2003-03-17
103 #ifdef WITH_LUA
104    _lua->SetDepCache(this);
105    _lua->RunScripts("Scripts::Cache::Init", true);
106    _lua->ResetCaches();
107 #endif
108    
109    return true;
110
111                                                                         /*}}}*/
112
113 // DepCache::CheckDep - Checks a single dependency                      /*{{{*/
114 // ---------------------------------------------------------------------
115 /* This first checks the dependency against the main target package and
116    then walks along the package provides list and checks if each provides 
117    will be installed then checks the provides against the dep. Res will be 
118    set to the package which was used to satisfy the dep. */
119 bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
120 {
121 // CNC:2003-02-17 - This function is the main path when checking
122 //                  dependencies, so we must avoid as much overhead
123 //                  as possible. It has several changes to improve
124 //                  performance.
125 #if 0
126    Res = Dep.TargetPkg();
127
128    /* Check simple depends. A depends -should- never self match but 
129       we allow it anyhow because dpkg does. Technically it is a packaging
130       bug. Conflicts may never self match */
131    if (Dep.TargetPkg() != Dep.ParentPkg() || 
132        (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes))
133    {
134       PkgIterator Pkg = Dep.TargetPkg();
135       // Check the base package
136       if (Type == NowVersion && Pkg->CurrentVer != 0)
137          // CNC:2002-07-10 - RPM must check the dependency type to properly
138          //                  define if it would be satisfied or not.
139          if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep) == true)
140             return true;
141       
142       if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
143          if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
144                                  Dep) == true)
145             return true;
146       
147       if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
148          if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
149                                  Dep) == true)
150             return true;
151    }
152    
153    if (Dep->Type == Dep::Obsoletes)
154       return false;
155    
156    // Check the providing packages
157    PrvIterator P = Dep.TargetPkg().ProvidesList();
158    PkgIterator Pkg = Dep.ParentPkg();
159    for (; P.end() != true; P++)
160    {
161       /* Provides may never be applied against the same package if it is
162          a conflicts. See the comment above. */
163       if (P.OwnerPkg() == Pkg && Dep->Type == Dep::Conflicts)
164          continue;
165       
166       // Check if the provides is a hit
167       if (Type == NowVersion)
168       {
169          if (P.OwnerPkg().CurrentVer() != P.OwnerVer())
170             continue;
171       }
172       
173       if (Type == InstallVersion)
174       {
175          StateCache &State = PkgState[P.OwnerPkg()->ID];
176          if (State.InstallVer != (Version *)P.OwnerVer())
177             continue;
178       }
179
180       if (Type == CandidateVersion)
181       {
182          StateCache &State = PkgState[P.OwnerPkg()->ID];
183          if (State.CandidateVer != (Version *)P.OwnerVer())
184             continue;
185       }
186       
187       // Compare the versions.
188       if (VS().CheckDep(P.ProvideVersion(),Dep) == true) // CNC:2002-07-10
189       {
190          Res = P.OwnerPkg();
191          return true;
192       }
193    }
194
195    // CNC:2002-07-05
196    if (_system->IgnoreDep(VS(),Dep) == true)
197    {
198       Res = Dep.TargetPkg();
199       return true;
200    }
201    
202 #else
203
204    Res = Dep.TargetPkg();
205
206    // CNC:2003-02-17 - Res is currently not changed. If it happens to
207    //                  be changed in this function (besides when
208    //                  returning anyway), assign a new Dep.TargetPkg()
209    //                  to Dep_TargetPkg instead of using Res.
210    //
211    PkgIterator &Dep_TargetPkg = Res;
212    PkgIterator Dep_ParentPkg = Dep.ParentPkg();
213    pkgVersioningSystem &VS = this->VS();
214
215    /* Check simple depends. A depends -should- never self match but 
216       we allow it anyhow because dpkg does. Technically it is a packaging
217       bug. Conflicts may never self match */
218    if (Dep_TargetPkg != Dep_ParentPkg || 
219        (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes))
220    {
221       PkgIterator &Pkg = Dep_TargetPkg;
222
223       // Check the base package
224       switch (Type)
225       {
226          case NowVersion:
227             if (Pkg->CurrentVer != 0)
228                // CNC:2002-07-10 - RPM must check the dependency type to
229                //                  properly define if it would be satisfied
230                //                  or not.
231                if (VS.CheckDep(Pkg.CurrentVer().VerStr(),Dep) == true)
232                   return true;
233             break;
234
235          case InstallVersion:
236             if (PkgState[Pkg->ID].InstallVer != 0)
237                if (VS.CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
238                                        Dep) == true)
239                   return true;
240             break;
241       
242          case CandidateVersion:
243             if (PkgState[Pkg->ID].CandidateVer != 0)
244                if (VS.CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
245                                        Dep) == true)
246                   return true;
247             break;
248       }
249
250       
251    }
252    
253    if (Dep->Type == Dep::Obsoletes)
254       return false;
255    
256    // Check the providing packages
257    PrvIterator P = Dep_TargetPkg.ProvidesList();
258    PkgIterator &Pkg = Dep_ParentPkg;
259    for (; P.end() != true; P++)
260    {
261       PkgIterator P_OwnerPkg = P.OwnerPkg();
262
263       /* Provides may never be applied against the same package if it is
264          a conflicts. See the comment above. */
265       if (P_OwnerPkg == Pkg && Dep->Type == Dep::Conflicts)
266          continue;
267       
268       // Check if the provides is a hit
269       switch (Type)
270       {
271          case NowVersion:
272             {
273                if (P_OwnerPkg.CurrentVer() != P.OwnerVer())
274                   continue;
275                break;
276             }
277          case InstallVersion:
278             {
279                StateCache &State = PkgState[P_OwnerPkg->ID];
280                if (State.InstallVer != (Version *)P.OwnerVer())
281                   continue;
282                break;
283             }
284          case CandidateVersion:
285             {
286                StateCache &State = PkgState[P_OwnerPkg->ID];
287                if (State.CandidateVer != (Version *)P.OwnerVer())
288                   continue;
289                break;
290             }
291       }
292       
293       // Compare the versions.
294       if (VS.CheckDep(P.ProvideVersion(),Dep) == true) // CNC:2002-07-10
295       {
296          Res = P_OwnerPkg;
297          return true;
298       }
299    }
300
301    // CNC:2002-07-05
302    if (_system->IgnoreDep(VS,Dep) == true)
303    {
304       Res = Dep_TargetPkg;
305       return true;
306    }
307 #endif
308
309    return false;
310 }
311                                                                         /*}}}*/
312 // DepCache::AddSizes - Add the packages sizes to the counters          /*{{{*/
313 // ---------------------------------------------------------------------
314 /* Call with Mult = -1 to preform the inverse opration */
315 void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
316 {
317    StateCache &P = PkgState[Pkg->ID];
318    
319    if (Pkg->VersionList == 0)
320       return;
321    
322    if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && 
323        P.Keep() == true)
324       return;
325    
326    // Compute the size data
327    if (P.NewInstall() == true)
328    {
329       iUsrSize += (signed)(Mult*P.InstVerIter(*this)->InstalledSize);
330       iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
331       return;
332    }
333    
334    // Upgrading
335    if (Pkg->CurrentVer != 0 && 
336        (P.InstallVer != (Version *)Pkg.CurrentVer() || 
337         (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
338    {
339       iUsrSize += (signed)(Mult*((signed)P.InstVerIter(*this)->InstalledSize - 
340                         (signed)Pkg.CurrentVer()->InstalledSize));
341       iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
342       return;
343    }
344    
345    // Reinstall
346    if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
347        P.Delete() == false)
348    {
349       iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
350       return;
351    }
352    
353    // Removing
354    if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
355    {
356       iUsrSize -= (signed)(Mult*Pkg.CurrentVer()->InstalledSize);
357       return;
358    }   
359 }
360                                                                         /*}}}*/
361 // DepCache::AddStates - Add the package to the state counter           /*{{{*/
362 // ---------------------------------------------------------------------
363 /* This routine is tricky to use, you must make sure that it is never 
364    called twice for the same package. This means the Remove/Add section
365    should be as short as possible and not encompass any code that will 
366    calld Remove/Add itself. Remember, dependencies can be circular so
367    while processing a dep for Pkg it is possible that Add/Remove
368    will be called on Pkg */
369 void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add)
370 {
371    StateCache &State = PkgState[Pkg->ID];
372    
373    // The Package is broken
374    if ((State.DepState & DepInstMin) != DepInstMin)
375       iBrokenCount += Add;
376    
377    // Bad state
378    if (Pkg.State() != PkgIterator::NeedsNothing)
379       iBadCount += Add;
380    
381    // Not installed
382    if (Pkg->CurrentVer == 0)
383    {
384       if (State.Mode == ModeDelete && 
385           (State.iFlags | Purge) == Purge && Pkg.Purge() == false)
386          iDelCount += Add;
387       
388       if (State.Mode == ModeInstall)
389          iInstCount += Add;
390       return;
391    }
392    
393    // Installed, no upgrade
394    if (State.Status == 0)
395    {     
396       if (State.Mode == ModeDelete)
397          iDelCount += Add;
398       else
399          if ((State.iFlags & ReInstall) == ReInstall)
400             iInstCount += Add;
401       
402       return;
403    }
404    
405    // Alll 3 are possible
406    if (State.Mode == ModeDelete)
407       iDelCount += Add;   
408    if (State.Mode == ModeKeep)
409       iKeepCount += Add;
410    if (State.Mode == ModeInstall)
411       iInstCount += Add;
412 }
413                                                                         /*}}}*/
414 // DepCache::BuildGroupOrs - Generate the Or group dep data             /*{{{*/
415 // ---------------------------------------------------------------------
416 /* The or group results are stored in the last item of the or group. This
417    allows easy detection of the state of a whole or'd group. */
418 void pkgDepCache::BuildGroupOrs(VerIterator const &V)
419 {
420    unsigned char Group = 0;
421    
422    for (DepIterator D = V.DependsList(); D.end() != true; D++)
423    {
424       // Build the dependency state.
425       unsigned char &State = DepState[D->ID];
426
427       /* Invert for Conflicts. We have to do this twice to get the
428          right sense for a conflicts group */
429       if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
430          State = ~State;
431       
432       // Add to the group if we are within an or..
433       State &= 0x7;
434       Group |= State;
435       State |= Group << 3;
436       if ((D->CompareOp & Dep::Or) != Dep::Or)
437          Group = 0;
438       
439       // Invert for Conflicts
440       if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
441          State = ~State;
442    }     
443 }
444                                                                         /*}}}*/
445 // DepCache::VersionState - Perform a pass over a dependency list       /*{{{*/
446 // ---------------------------------------------------------------------
447 /* This is used to run over a dependency list and determine the dep
448    state of the list, filtering it through both a Min check and a Policy
449    check. The return result will have SetMin/SetPolicy low if a check
450    fails. It uses the DepState cache for it's computations. */
451 unsigned char pkgDepCache::VersionState(DepIterator D,unsigned char Check,
452                                        unsigned char SetMin,
453                                        unsigned char SetPolicy)
454 {
455    unsigned char Dep = 0xFF;
456    
457    while (D.end() != true)
458    {
459       // Compute a single dependency element (glob or)
460       DepIterator Start = D;
461       unsigned char State = 0;
462       for (bool LastOR = true; D.end() == false && LastOR == true; D++)
463       {
464          State |= DepState[D->ID];
465          LastOR = (D->CompareOp & Dep::Or) == Dep::Or;
466       }
467         
468       // CNC:2003-02-17 - IsImportantDep() currently calls IsCritical(), so
469       //                  these two are currently doing the same thing. Check
470       //                  comments in IsImportantDep() definition.
471 #if 0
472       // Minimum deps that must be satisfied to have a working package
473       if (Start.IsCritical() == true)
474          if ((State & Check) != Check)
475             Dep &= ~SetMin;
476       
477       // Policy deps that must be satisfied to install the package
478       if (IsImportantDep(Start) == true && 
479           (State & Check) != Check)
480          Dep &= ~SetPolicy;
481 #else
482       if (Start.IsCritical() == true)
483          if ((State & Check) != Check) {
484             Dep &= ~SetMin;
485             Dep &= ~SetPolicy;
486          }
487 #endif
488    }
489
490    return Dep;
491 }
492                                                                         /*}}}*/
493 // DepCache::DependencyState - Compute the 3 results for a dep          /*{{{*/
494 // ---------------------------------------------------------------------
495 /* This is the main dependency computation bit. It computes the 3 main
496    results for a dependencys, Now, Install and Candidate. Callers must
497    invert the result if dealing with conflicts. */
498 unsigned char pkgDepCache::DependencyState(DepIterator &D)
499 {
500    unsigned char State = 0;
501    
502    if (CheckDep(D,NowVersion) == true)
503       State |= DepNow;
504    if (CheckDep(D,InstallVersion) == true)
505       State |= DepInstall;
506    if (CheckDep(D,CandidateVersion) == true)
507       State |= DepCVer;
508    
509    return State;
510 }
511                                                                         /*}}}*/
512 // DepCache::UpdateVerState - Compute the Dep member of the state       /*{{{*/
513 // ---------------------------------------------------------------------
514 /* This determines the combined dependency representation of a package
515    for its two states now and install. This is done by using the pre-generated
516    dependency information. */
517 void pkgDepCache::UpdateVerState(PkgIterator Pkg)
518 {   
519    // Empty deps are always true
520    StateCache &State = PkgState[Pkg->ID];
521    State.DepState = 0xFF;
522    
523    // Check the Current state
524    if (Pkg->CurrentVer != 0)
525    {
526       DepIterator D = Pkg.CurrentVer().DependsList();
527       State.DepState &= VersionState(D,DepNow,DepNowMin,DepNowPolicy);
528    }
529    
530    /* Check the candidate state. We do not compare against the whole as
531       a candidate state but check the candidate version against the 
532       install states */
533    if (State.CandidateVer != 0)
534    {
535       DepIterator D = State.CandidateVerIter(*this).DependsList();
536       State.DepState &= VersionState(D,DepInstall,DepCandMin,DepCandPolicy);
537    }
538    
539    // Check target state which can only be current or installed
540    if (State.InstallVer != 0)
541    {
542       DepIterator D = State.InstVerIter(*this).DependsList();
543       State.DepState &= VersionState(D,DepInstall,DepInstMin,DepInstPolicy);
544    }
545 }
546                                                                         /*}}}*/
547 // DepCache::Update - Figure out all the state information              /*{{{*/
548 // ---------------------------------------------------------------------
549 /* This will figure out the state of all the packages and all the 
550    dependencies based on the current policy. */
551 void pkgDepCache::Update(OpProgress *Prog)
552 {   
553    iUsrSize = 0;
554    iDownloadSize = 0;
555    iDelCount = 0;
556    iInstCount = 0;
557    iKeepCount = 0;
558    iBrokenCount = 0;
559    iBadCount = 0;
560    
561    // Perform the depends pass
562    int Done = 0;
563    for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
564    {
565       if (Prog != 0 && Done%20 == 0)
566          Prog->Progress(Done);
567       for (VerIterator V = I.VersionList(); V.end() != true; V++)
568       {
569          unsigned char Group = 0;
570          
571          for (DepIterator D = V.DependsList(); D.end() != true; D++)
572          {
573             // Build the dependency state.
574             unsigned char &State = DepState[D->ID];
575             State = DependencyState(D);
576
577             // Add to the group if we are within an or..
578             Group |= State;
579             State |= Group << 3;
580             if ((D->CompareOp & Dep::Or) != Dep::Or)
581                Group = 0;
582
583             // Invert for Conflicts
584             if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
585                State = ~State;
586          }       
587       }
588
589       // Compute the pacakge dependency state and size additions
590       AddSizes(I);
591       UpdateVerState(I);
592       AddStates(I);
593    }
594
595    if (Prog != 0)      
596       Prog->Progress(Done);
597 }
598                                                                         /*}}}*/
599 // DepCache::Update - Update the deps list of a package                 /*{{{*/
600 // ---------------------------------------------------------------------
601 /* This is a helper for update that only does the dep portion of the scan. 
602    It is mainly ment to scan reverse dependencies. */
603 void pkgDepCache::Update(DepIterator D)
604 {
605    // Update the reverse deps
606    for (;D.end() != true; D++)
607    {      
608       unsigned char &State = DepState[D->ID];
609       State = DependencyState(D);
610     
611       // Invert for Conflicts
612       if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
613          State = ~State;
614
615       RemoveStates(D.ParentPkg());
616       BuildGroupOrs(D.ParentVer());
617       UpdateVerState(D.ParentPkg());
618       AddStates(D.ParentPkg());
619    }
620 }
621                                                                         /*}}}*/
622 // DepCache::Update - Update the related deps of a package              /*{{{*/
623 // ---------------------------------------------------------------------
624 /* This is called whenever the state of a package changes. It updates
625    all cached dependencies related to this package. */
626 void pkgDepCache::Update(PkgIterator const &Pkg)
627 {   
628    // Recompute the dep of the package
629    RemoveStates(Pkg);
630    UpdateVerState(Pkg);
631    AddStates(Pkg);
632    
633    // Update the reverse deps
634    Update(Pkg.RevDependsList());
635
636    // Update the provides map for the current ver
637    if (Pkg->CurrentVer != 0)
638       for (PrvIterator P = Pkg.CurrentVer().ProvidesList(); 
639            P.end() != true; P++)
640          Update(P.ParentPkg().RevDependsList());
641
642    // Update the provides map for the candidate ver
643    if (PkgState[Pkg->ID].CandidateVer != 0)
644       for (PrvIterator P = PkgState[Pkg->ID].CandidateVerIter(*this).ProvidesList();
645            P.end() != true; P++)
646          Update(P.ParentPkg().RevDependsList());
647 }
648
649                                                                         /*}}}*/
650
651 // DepCache::MarkKeep - Put the package in the keep state               /*{{{*/
652 // ---------------------------------------------------------------------
653 /* */
654 void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
655 {
656    // Simplifies other routines.
657    if (Pkg.end() == true)
658       return;
659
660    /* Reject an attempt to keep a non-source broken installed package, those
661       must be upgraded */
662    if (Pkg.State() == PkgIterator::NeedsUnpack && 
663        Pkg.CurrentVer().Downloadable() == false)
664       return;
665    
666    /* We changed the soft state all the time so the UI is a bit nicer
667       to use */
668    StateCache &P = PkgState[Pkg->ID];
669    if (Soft == true)
670       P.iFlags |= AutoKept;
671    else
672       P.iFlags &= ~AutoKept;
673    
674    // Check that it is not already kept
675    if (P.Mode == ModeKeep)
676       return;
677
678    // We dont even try to keep virtual packages..
679    if (Pkg->VersionList == 0)
680       return;
681    
682    P.Flags &= ~Flag::Auto;
683    RemoveSizes(Pkg);
684    RemoveStates(Pkg);
685
686    P.Mode = ModeKeep;
687    if (Pkg->CurrentVer == 0)
688       P.InstallVer = 0;
689    else
690       P.InstallVer = Pkg.CurrentVer();
691
692    AddStates(Pkg);
693
694    Update(Pkg);
695
696    AddSizes(Pkg);
697 }
698                                                                         /*}}}*/
699 // DepCache::MarkDelete - Put the package in the delete state           /*{{{*/
700 // ---------------------------------------------------------------------
701 /* */
702 void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
703 {
704    // Simplifies other routines.
705    if (Pkg.end() == true)
706       return;
707
708    // Check that it is not already marked for delete
709    StateCache &P = PkgState[Pkg->ID];
710    P.iFlags &= ~(AutoKept | Purge);
711    if (rPurge == true)
712       P.iFlags |= Purge;
713    
714    if ((P.Mode == ModeDelete || P.InstallVer == 0) && 
715        (Pkg.Purge() == true || rPurge == false))
716       return;
717    
718    // We dont even try to delete virtual packages..
719    if (Pkg->VersionList == 0)
720       return;
721
722    RemoveSizes(Pkg);
723    RemoveStates(Pkg);
724    
725    if (Pkg->CurrentVer == 0 && (Pkg.Purge() == true || rPurge == false))
726       P.Mode = ModeKeep;
727    else
728       P.Mode = ModeDelete;
729    P.InstallVer = 0;
730    P.Flags &= Flag::Auto;
731
732    AddStates(Pkg);   
733    Update(Pkg);
734    AddSizes(Pkg);
735 }
736                                                                         /*}}}*/
737 // DepCache::MarkInstall - Put the package in the install state         /*{{{*/
738 // ---------------------------------------------------------------------
739 /* */
740 void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
741                               unsigned long Depth)
742 {
743    if (Depth > 100)
744       return;
745    
746    // Simplifies other routines.
747    if (Pkg.end() == true)
748       return;
749    
750    /* Check that it is not already marked for install and that it can be 
751       installed */
752    StateCache &P = PkgState[Pkg->ID];
753    P.iFlags &= ~AutoKept;
754    if (P.InstBroken() == false && (P.Mode == ModeInstall ||
755         P.CandidateVer == (Version *)Pkg.CurrentVer()))
756    {
757       if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
758          MarkKeep(Pkg);
759       return;
760    }
761
762    // See if there is even any possible instalation candidate
763    if (P.CandidateVer == 0)
764       return;
765    
766    // We dont even try to install virtual packages..
767    if (Pkg->VersionList == 0)
768       return;
769    
770    /* Target the candidate version and remove the autoflag. We reset the
771       autoflag below if this was called recursively. Otherwise the user
772       should have the ability to de-auto a package by changing its state */
773    RemoveSizes(Pkg);
774    RemoveStates(Pkg);
775    
776    P.Mode = ModeInstall;
777    P.InstallVer = P.CandidateVer;
778    P.Flags &= ~Flag::Auto;
779    if (P.CandidateVer == (Version *)Pkg.CurrentVer())
780       P.Mode = ModeKeep;
781        
782    AddStates(Pkg);
783    Update(Pkg);
784    AddSizes(Pkg);
785    
786    if (AutoInst == false)
787       return;
788
789    DepIterator Dep = P.InstVerIter(*this).DependsList();
790    for (; Dep.end() != true;)
791    {
792       // Grok or groups
793       DepIterator Start = Dep;
794       bool Result = true;
795       unsigned Ors = 0;
796       for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++,Ors++)
797       {
798          LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or;
799
800          if ((DepState[Dep->ID] & DepInstall) == DepInstall)
801             Result = false;
802       }
803       
804       // Dep is satisfied okay.
805       if (Result == false)
806          continue;
807
808       // CNC:2003-02-17 - IsImportantDep() currently calls IsCritical(), so
809       //                  these two are currently doing the same thing. Check
810       //                  comments in IsImportantDep() definition.
811 #if 0
812       /* Check if this dep should be consider for install. If it is a user
813          defined important dep and we are installed a new package then 
814          it will be installed. Otherwise we only worry about critical deps */
815       if (IsImportantDep(Start) == false)
816          continue;
817       if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
818          continue;
819 #else
820       if (Start.IsCritical() == false)
821          continue;
822 #endif
823       
824       /* If we are in an or group locate the first or that can 
825          succeed. We have already cached this.. */
826       for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; Ors--)
827          Start++;
828
829       /* This bit is for processing the possibilty of an install/upgrade
830          fixing the problem */
831       SPtrArray<Version *> List = Start.AllTargets();
832       if ((DepState[Start->ID] & DepCVer) == DepCVer)
833       {
834          // Right, find the best version to install..
835          Version **Cur = List;
836          PkgIterator P = Start.TargetPkg();
837          PkgIterator InstPkg(*Cache,0);
838          
839          // See if there are direct matches (at the start of the list)
840          for (; *Cur != 0 && (*Cur)->ParentPkg == P.Index(); Cur++)
841          {
842             PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
843             if (PkgState[Pkg->ID].CandidateVer != *Cur)
844                continue;
845             InstPkg = Pkg;
846             break;
847          }
848
849          // Select the highest priority providing package
850          if (InstPkg.end() == true)
851          {
852             pkgPrioSortList(*Cache,Cur);
853             for (; *Cur != 0; Cur++)
854             {
855                PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
856                if (PkgState[Pkg->ID].CandidateVer != *Cur)
857                   continue;
858                InstPkg = Pkg;
859                break;
860             }
861          }
862          
863          if (InstPkg.end() == false)
864          {
865             MarkInstall(InstPkg,true,Depth + 1);
866
867             // Set the autoflag, after MarkInstall because MarkInstall unsets it
868             if (P->CurrentVer == 0)
869                PkgState[InstPkg->ID].Flags |= Flag::Auto;
870          }
871          
872          continue;
873       }
874       
875       /* For conflicts we just de-install the package and mark as auto,
876          Conflicts may not have or groups */
877       if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes)
878       {
879          for (Version **I = List; *I != 0; I++)
880          {
881             VerIterator Ver(*this,*I);
882             PkgIterator Pkg = Ver.ParentPkg();
883       
884             MarkDelete(Pkg);
885             PkgState[Pkg->ID].Flags |= Flag::Auto;
886          }
887          continue;
888       }      
889    }
890 }
891                                                                         /*}}}*/
892 // DepCache::SetReInstall - Set the reinstallation flag                 /*{{{*/
893 // ---------------------------------------------------------------------
894 /* */
895 void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
896 {
897    RemoveSizes(Pkg);
898    RemoveStates(Pkg);
899    
900    StateCache &P = PkgState[Pkg->ID];
901    if (To == true)
902       P.iFlags |= ReInstall;
903    else
904       P.iFlags &= ~ReInstall;
905    
906    AddStates(Pkg);
907    AddSizes(Pkg);
908 }
909                                                                         /*}}}*/
910 // DepCache::SetCandidateVersion - Change the candidate version         /*{{{*/
911 // ---------------------------------------------------------------------
912 /* */
913 void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
914 {
915    pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
916    StateCache &P = PkgState[Pkg->ID];
917    
918    RemoveSizes(Pkg);
919    RemoveStates(Pkg);
920
921    if (P.CandidateVer == P.InstallVer)
922       P.InstallVer = (Version *)TargetVer;
923    P.CandidateVer = (Version *)TargetVer;
924    P.Update(Pkg,*this);
925    
926    AddStates(Pkg);
927    Update(Pkg);
928    AddSizes(Pkg);
929 }
930                                                                         /*}}}*/
931 // StateCache::Update - Compute the various static display things       /*{{{*/
932 // ---------------------------------------------------------------------
933 /* This is called whenever the Candidate version changes. */
934 void pkgDepCache::StateCache::Update(PkgIterator Pkg,pkgCache &Cache)
935 {
936    // Some info
937    VerIterator Ver = CandidateVerIter(Cache);
938    
939    // Use a null string or the version string
940    if (Ver.end() == true)
941       CandVersion = "";
942    else
943       CandVersion = Ver.VerStr();
944    
945    // Find the current version
946    CurVersion = "";
947    if (Pkg->CurrentVer != 0)
948       CurVersion = Pkg.CurrentVer().VerStr();
949    
950    // Strip off the epochs for display
951    CurVersion = StripEpoch(CurVersion);
952    CandVersion = StripEpoch(CandVersion);
953    
954    // Figure out if its up or down or equal
955    Status = Ver.CompareVer(Pkg.CurrentVer());
956    if (Pkg->CurrentVer == 0 || Pkg->VersionList == 0 || CandidateVer == 0)
957      Status = 2;      
958 }
959                                                                         /*}}}*/
960 // StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
961 // ---------------------------------------------------------------------
962 /* */
963 const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
964 {
965    if (Ver == 0)
966       return 0;
967
968    // Strip any epoch
969    for (const char *I = Ver; *I != 0; I++)
970       if (*I == ':')
971          return I + 1;
972    return Ver;
973 }
974                                                                         /*}}}*/
975
976 // Policy::GetCandidateVer - Returns the Candidate install version      /*{{{*/
977 // ---------------------------------------------------------------------
978 /* The default just returns the highest available version that is not
979    a source and automatic. */
980 pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
981 {
982    /* Not source/not automatic versions cannot be a candidate version 
983       unless they are already installed */
984    VerIterator Last(*(pkgCache *)this,0);
985    
986    for (VerIterator I = Pkg.VersionList(); I.end() == false; I++)
987    {
988       if (Pkg.CurrentVer() == I)
989          return I;
990       
991       for (VerFileIterator J = I.FileList(); J.end() == false; J++)
992       {
993          if ((J.File()->Flags & Flag::NotSource) != 0)
994             continue;
995
996          /* Stash the highest version of a not-automatic source, we use it
997             if there is nothing better */
998          if ((J.File()->Flags & Flag::NotAutomatic) != 0)
999          {
1000             if (Last.end() == true)
1001                Last = I;
1002             continue;
1003          }
1004
1005          return I;
1006       }
1007    }
1008    
1009    return Last;
1010 }
1011                                                                         /*}}}*/
1012 // Policy::IsImportantDep - True if the dependency is important         /*{{{*/
1013 // ---------------------------------------------------------------------
1014 /* */
1015 bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
1016 {
1017    // CNC:2002-03-17 - Every place that uses this function seems to
1018    //                  currently check for IsCritical() as well. Since
1019    //                  this is a virtual (heavy) function, we'll try
1020    //                  not to use it while not necessary.
1021    return Dep.IsCritical();
1022 }
1023                                                                         /*}}}*/
1024
1025 // CNC:2003-02-24
1026 // pkgDepCache::State::* - Routines to work on the state of a DepCache. /*{{{*/
1027 // ---------------------------------------------------------------------
1028 /* */
1029 void pkgDepCache::State::Copy(pkgDepCache::State const &Other)
1030 {
1031    memcpy(this, &Other, sizeof(*this));
1032    int Size = Dep->Head().PackageCount;
1033    int DepSize = Dep->Head().DependsCount;
1034    PkgState = new StateCache[Size];
1035    PkgIgnore = new bool[Size];
1036    DepState = new unsigned char[DepSize];
1037    memcpy(PkgState, Other.PkgState, Size*sizeof(*PkgState));
1038    memcpy(PkgIgnore, Other.PkgIgnore, Size*sizeof(*PkgIgnore));
1039    memcpy(DepState, Other.DepState, DepSize*sizeof(*DepState));
1040 }
1041
1042 void pkgDepCache::State::Save(pkgDepCache *dep)
1043 {
1044    Dep = dep;
1045    delete[] PkgState;
1046    delete[] DepState;
1047    delete[] PkgIgnore;
1048    int Size = Dep->Head().PackageCount;
1049    int DepSize = Dep->Head().DependsCount;
1050    PkgState = new StateCache[Size];
1051    PkgIgnore = new bool[Size];
1052    DepState = new unsigned char[DepSize];
1053    memcpy(PkgState, Dep->PkgState, Size*sizeof(*PkgState));
1054    memset(PkgIgnore, 0, Size*sizeof(*PkgIgnore));
1055    memcpy(DepState, Dep->DepState, DepSize*sizeof(*DepState));
1056    iUsrSize = Dep->iUsrSize;
1057    iDownloadSize= Dep->iDownloadSize;
1058    iInstCount = Dep->iInstCount;
1059    iDelCount = Dep->iDelCount;
1060    iKeepCount = Dep->iKeepCount;
1061    iBrokenCount = Dep->iBrokenCount;
1062    iBadCount = Dep->iBadCount;
1063 }
1064
1065 void pkgDepCache::State::Restore()
1066 {
1067    memcpy(Dep->PkgState, PkgState, Dep->Head().PackageCount*sizeof(*PkgState));
1068    memcpy(Dep->DepState, DepState, Dep->Head().DependsCount*sizeof(*DepState));
1069    Dep->iUsrSize = iUsrSize;
1070    Dep->iDownloadSize= iDownloadSize;
1071    Dep->iInstCount = iInstCount;
1072    Dep->iDelCount = iDelCount;
1073    Dep->iKeepCount = iKeepCount;
1074    Dep->iBrokenCount = iBrokenCount;
1075    Dep->iBadCount = iBadCount;
1076 }
1077
1078 bool pkgDepCache::State::Changed()
1079 {
1080    int Size = Dep->Head().PackageCount;
1081    StateCache *NewPkgState = Dep->PkgState;
1082    for (int i = 0; i != Size; i++) {
1083       if (PkgIgnore[i] == false &&
1084           ((PkgState[i].Status != NewPkgState[i].Status) ||
1085           (PkgState[i].Mode != NewPkgState[i].Mode)))
1086          return true;
1087    }
1088    return false;
1089 }
1090
1091 void pkgDepCache::State::UnIgnoreAll()
1092 {
1093    memset(PkgIgnore, 0, Dep->Head().PackageCount*sizeof(*PkgIgnore));
1094 }
1095
1096                                                                         /*}}}*/
1097
1098 // vim:sts=3:sw=3