~mvo/apt/dep8

« back to all changes in this revision

Viewing changes to apt-pkg/depcache.cc


* merged the debian/experimental changes back
  into the debian/sid branch
* merged from Christian Perrier:
  * mr.po: New Marathi translation  Closes: #416806
  * zh_CN.po: Updated by Eric Pareja  Closes: #416822
  * tl.po: Updated by Eric Pareja   Closes: #416638
  * gl.po: Updated by Jacobo Tarrio
  * da.po: Updated by Claus Hindsgaul
  * fr.po: Remove a non-breakable space for usability
  * ru.po: Updated Russian translation. Closes: #405476
  * *.po: Unfuzzy after upstream typo corrections
* buildlib/archtable:
  - added support for sh3/sh4 (closes: #424870)
  - added support for m32r (closes: #394096)
* buildlib/systemtable:
  - added support for lpia
* configure.in:
  - check systemtable for architecture mapping too

* Package that contains tall the new features
* Removed all #pragma interface/implementation
* Branch that contains tall the new features:
* translated package descriptions
* task install support
* automatic dependency removal (thanks to Daniel Burrows)
* merged support for the new dpkg "Breaks" field 
  (thanks to Ian Jackson)
* handle network failures more gracefully on "update"
* support for unattended-upgrades (via unattended-upgrades
  package)
* added apt-transport-https method
* merged "install-recommends" branch (ABI break): 
  - new "--install-recommends"
  - install new recommends on "upgrade" if --install-recommends is 
    given
  - new "--fix-policy" option to install all packages with unmet
    important dependencies (usefull with --install-recommends to
    see what not-installed recommends are on the system)
  - fix of recommended packages display (only show CandidateVersion
    fix or-group handling)
* merged "install-task" branch (use with "apt-get install taskname^")
* Applied patch from Daniel Schepler to make apt bin-NMU able.
  * eu.po: Updated
* fix apt-get dist-upgrade
* fix warning if no /var/lib/apt/extended_states is present
* don't download Translations for deb-src sources.list lines
* apt-pkg/tagfile.cc:
  - support not-mmapable files again
* added support for i18n of the package descriptions
* added support for aptitude like auto-install tracking (a HUGE
  HUGE thanks to Daniel Burrows who made this possible) 
* synced with the http://people.debian.org/~mvo/bzr/apt/debian-sid branch
* build from http://people.debian.org/~mvo/bzr/apt/debian-experimental
* apt-pkg/depcache.cc:
  - added Debug::pkgDepCache::AutoInstall (thanks to infinity)
* apt-pkg/acquire-item.cc:
  - fix missing chmod() in the new aquire code 
    (thanks to Bastian Blank, Closes: #367425)
* merged from 
  http://www.perrier.eu.org/debian/packages/d-i/level4/apt-main:
  * sk.po: Completed to 512t
  * eu.po: Completed to 512t
  * fr.po: Completed to 512t
  * sv.po: Completed to 512t
  * Update all PO and the POT. Gives 506t6f for formerly
    complete translations
* Fix a incorrect example in the man-page (closes: #282918)

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
   ##################################################################### */
9
9
                                                                        /*}}}*/
10
10
// Include Files                                                        /*{{{*/
11
 
#ifdef __GNUG__
12
 
#pragma implementation "apt-pkg/depcache.h"
13
 
#endif
14
11
#include <apt-pkg/depcache.h>
15
12
#include <apt-pkg/version.h>
16
13
#include <apt-pkg/error.h>
17
14
#include <apt-pkg/sptr.h>
18
15
#include <apt-pkg/algorithms.h>
 
16
 
 
17
#include <apt-pkg/fileutl.h>
19
18
#include <apt-pkg/configuration.h>
 
19
#include <apt-pkg/pkgsystem.h>
 
20
#include <apt-pkg/tagfile.h>
 
21
 
 
22
#include <iostream>
 
23
#include <sstream>    
 
24
#include <set>
20
25
 
21
26
#include <apti18n.h>    
22
 
                                                                        /*}}}*/
 
27
 
 
28
pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :
 
29
  cache(cache), released(false)
 
30
{
 
31
  ++cache.group_level;
 
32
}
 
33
 
 
34
void pkgDepCache::ActionGroup::release()
 
35
{
 
36
  if(!released)
 
37
    {
 
38
      if(cache.group_level == 0)
 
39
        std::cerr << "W: Unbalanced action groups, expect badness" << std::endl;
 
40
      else
 
41
        {
 
42
          --cache.group_level;
 
43
 
 
44
          if(cache.group_level == 0)
 
45
            cache.MarkAndSweep();
 
46
        }
 
47
 
 
48
      released = false;
 
49
    }
 
50
}
 
51
 
 
52
pkgDepCache::ActionGroup::~ActionGroup()
 
53
{
 
54
  release();
 
55
}
23
56
 
24
57
// DepCache::pkgDepCache - Constructors                                 /*{{{*/
25
58
// ---------------------------------------------------------------------
26
59
/* */
27
60
pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
28
 
                Cache(pCache), PkgState(0), DepState(0)
 
61
  group_level(0), Cache(pCache), PkgState(0), DepState(0)
29
62
{
30
63
   delLocalPolicy = 0;
31
64
   LocalPolicy = Plcy;
48
81
/* This allocats the extension buffers and initializes them. */
49
82
bool pkgDepCache::Init(OpProgress *Prog)
50
83
{
 
84
   // Suppress mark updates during this operation (just in case) and
 
85
   // run a mark operation when Init terminates.
 
86
   ActionGroup actions(*this);
 
87
 
51
88
   delete [] PkgState;
52
89
   delete [] DepState;
53
90
   PkgState = new StateCache[Head().PackageCount];
73
110
      // Find the proper cache slot
74
111
      StateCache &State = PkgState[I->ID];
75
112
      State.iFlags = 0;
76
 
      
 
113
 
77
114
      // Figure out the install version
78
115
      State.CandidateVer = GetCandidateVer(I);
79
116
      State.InstallVer = I.CurrentVer();
95
132
 
96
133
   if(Prog != 0)
97
134
      Prog->Done();
98
 
   
 
135
 
99
136
   return true;
100
137
101
138
                                                                        /*}}}*/
102
139
 
 
140
bool pkgDepCache::readStateFile(OpProgress *Prog)
 
141
{
 
142
   FileFd state_file;
 
143
   string state = _config->FindDir("Dir::State") + "extended_states";
 
144
   if(FileExists(state)) {
 
145
      state_file.Open(state, FileFd::ReadOnly);
 
146
      int file_size = state_file.Size();
 
147
      if(Prog != NULL)
 
148
         Prog->OverallProgress(0, file_size, 1, 
 
149
                               _("Reading state information"));
 
150
 
 
151
      pkgTagFile tagfile(&state_file);
 
152
      pkgTagSection section;
 
153
      int amt=0;
 
154
      while(tagfile.Step(section)) {
 
155
         string pkgname = section.FindS("Package");
 
156
         pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
 
157
         // Silently ignore unknown packages and packages with no actual
 
158
         // version.
 
159
         if(!pkg.end() && !pkg.VersionList().end()) {
 
160
            short reason = section.FindI("Auto-Installed", 0);
 
161
            if(reason > 0)
 
162
               PkgState[pkg->ID].Flags  |= Flag::Auto;
 
163
            if(_config->FindB("Debug::pkgAutoRemove",false))
 
164
               std::cout << "Auto-Installed : " << pkgname << std::endl;
 
165
            amt+=section.size();
 
166
            if(Prog != NULL)
 
167
               Prog->OverallProgress(amt, file_size, 1, 
 
168
                                     _("Reading state information"));
 
169
         }
 
170
         if(Prog != NULL)
 
171
            Prog->OverallProgress(file_size, file_size, 1, 
 
172
                                  _("Reading state information"));
 
173
      }
 
174
   }
 
175
 
 
176
   return true;
 
177
}
 
178
 
 
179
bool pkgDepCache::writeStateFile(OpProgress *prog)
 
180
{
 
181
   if(_config->FindB("Debug::pkgAutoRemove",false))
 
182
      std::clog << "pkgDepCache::writeStateFile()" << std::endl;
 
183
 
 
184
   FileFd StateFile;
 
185
   string state = _config->FindDir("Dir::State") + "extended_states";
 
186
 
 
187
   // if it does not exist, create a empty one
 
188
   if(!FileExists(state)) 
 
189
   {
 
190
      StateFile.Open(state, FileFd::WriteEmpty);
 
191
      StateFile.Close();
 
192
   }
 
193
 
 
194
   // open it
 
195
   if(!StateFile.Open(state, FileFd::ReadOnly))
 
196
      return _error->Error(_("Failed to open StateFile %s"),
 
197
                           state.c_str());
 
198
 
 
199
   FILE *OutFile;
 
200
   string outfile = state + ".tmp";
 
201
   if((OutFile = fopen(outfile.c_str(),"w")) == NULL)
 
202
      return _error->Error(_("Failed to write temporary StateFile %s"),
 
203
                           outfile.c_str());
 
204
 
 
205
   // first merge with the existing sections
 
206
   pkgTagFile tagfile(&StateFile);
 
207
   pkgTagSection section;
 
208
   std::set<string> pkgs_seen;
 
209
   const char *nullreorderlist[] = {0};
 
210
   while(tagfile.Step(section)) {
 
211
         string pkgname = section.FindS("Package");
 
212
         // Silently ignore unknown packages and packages with no actual
 
213
         // version.
 
214
         pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
 
215
         if(pkg.end() || pkg.VersionList().end()) 
 
216
            continue;
 
217
         bool oldAuto = section.FindI("Auto-Installed");
 
218
         bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
 
219
         if(_config->FindB("Debug::pkgAutoRemove",false))
 
220
            std::clog << "Update exisiting AutoInstall info: " 
 
221
                      << pkg.Name() << std::endl;
 
222
         TFRewriteData rewrite[2];
 
223
         rewrite[0].Tag = "Auto-Installed";
 
224
         rewrite[0].Rewrite = newAuto ? "1" : "0";
 
225
         rewrite[0].NewTag = 0;
 
226
         rewrite[1].Tag = 0;
 
227
         TFRewrite(OutFile, section, nullreorderlist, rewrite);
 
228
         fprintf(OutFile,"\n");
 
229
         pkgs_seen.insert(pkgname);
 
230
   }
 
231
   
 
232
   // then write the ones we have not seen yet
 
233
   std::ostringstream ostr;
 
234
   for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) {
 
235
      if(PkgState[pkg->ID].Flags & Flag::Auto) {
 
236
         if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) {
 
237
            if(_config->FindB("Debug::pkgAutoRemove",false))
 
238
               std::clog << "Skipping already written " << pkg.Name() << std::endl;
 
239
            continue;
 
240
         }
 
241
         if(_config->FindB("Debug::pkgAutoRemove",false))
 
242
            std::clog << "Writing new AutoInstall: " 
 
243
                      << pkg.Name() << std::endl;
 
244
         ostr.str(string(""));
 
245
         ostr << "Package: " << pkg.Name() 
 
246
              << "\nAuto-Installed: 1\n\n";
 
247
         fprintf(OutFile,ostr.str().c_str());
 
248
         fprintf(OutFile,"\n");
 
249
      }
 
250
   }
 
251
   fclose(OutFile);
 
252
 
 
253
   // move the outfile over the real file
 
254
   rename(outfile.c_str(), state.c_str());
 
255
 
 
256
   return true;
 
257
}
 
258
 
103
259
// DepCache::CheckDep - Checks a single dependency                      /*{{{*/
104
260
// ---------------------------------------------------------------------
105
261
/* This first checks the dependency against the main target package and
114
270
      we allow it anyhow because dpkg does. Technically it is a packaging
115
271
      bug. Conflicts may never self match */
116
272
   if (Dep.TargetPkg() != Dep.ParentPkg() || 
117
 
       (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes))
 
273
       (Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
118
274
   {
119
275
      PkgIterator Pkg = Dep.TargetPkg();
120
276
      // Check the base package
144
300
   {
145
301
      /* Provides may never be applied against the same package if it is
146
302
         a conflicts. See the comment above. */
147
 
      if (P.OwnerPkg() == Pkg && Dep->Type == Dep::Conflicts)
 
303
      if (P.OwnerPkg() == Pkg &&
 
304
          (Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks))
148
305
         continue;
149
306
      
150
307
      // Check if the provides is a hit
240
397
{
241
398
   StateCache &State = PkgState[Pkg->ID];
242
399
   
243
 
   // The Package is broken
 
400
   // The Package is broken (either minimal dep or policy dep)
244
401
   if ((State.DepState & DepInstMin) != DepInstMin)
245
402
      iBrokenCount += Add;
 
403
   if ((State.DepState & DepInstPolicy) != DepInstPolicy)
 
404
      iPolicyBrokenCount += Add;
246
405
   
247
406
   // Bad state
248
407
   if (Pkg.State() != PkgIterator::NeedsNothing)
296
455
 
297
456
      /* Invert for Conflicts. We have to do this twice to get the
298
457
         right sense for a conflicts group */
299
 
      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
 
458
      if (D->Type == Dep::Conflicts ||
 
459
          D->Type == Dep::DpkgBreaks ||
 
460
          D->Type == Dep::Obsoletes)
300
461
         State = ~State;
301
462
      
302
463
      // Add to the group if we are within an or..
307
468
         Group = 0;
308
469
      
309
470
      // Invert for Conflicts
310
 
      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
 
471
      if (D->Type == Dep::Conflicts ||
 
472
          D->Type == Dep::DpkgBreaks ||
 
473
          D->Type == Dep::Obsoletes)
311
474
         State = ~State;
312
475
   }     
313
476
}
440
603
               Group = 0;
441
604
 
442
605
            // Invert for Conflicts
443
 
            if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
 
606
            if (D->Type == Dep::Conflicts ||
 
607
                D->Type == Dep::DpkgBreaks ||
 
608
                D->Type == Dep::Obsoletes)
444
609
               State = ~State;
445
610
         }       
446
611
      }
453
618
 
454
619
   if (Prog != 0)      
455
620
      Prog->Progress(Done);
 
621
 
 
622
   readStateFile(Prog);
456
623
}
457
624
                                                                        /*}}}*/
458
625
// DepCache::Update - Update the deps list of a package                 /*{{{*/
459
626
// ---------------------------------------------------------------------
460
627
/* This is a helper for update that only does the dep portion of the scan. 
461
 
   It is mainly ment to scan reverse dependencies. */
 
628
   It is mainly meant to scan reverse dependencies. */
462
629
void pkgDepCache::Update(DepIterator D)
463
630
{
464
631
   // Update the reverse deps
468
635
      State = DependencyState(D);
469
636
    
470
637
      // Invert for Conflicts
471
 
      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
 
638
      if (D->Type == Dep::Conflicts ||
 
639
          D->Type == Dep::DpkgBreaks ||
 
640
          D->Type == Dep::Obsoletes)
472
641
         State = ~State;
473
642
 
474
643
      RemoveStates(D.ParentPkg());
510
679
// DepCache::MarkKeep - Put the package in the keep state               /*{{{*/
511
680
// ---------------------------------------------------------------------
512
681
/* */
513
 
void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
 
682
void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
514
683
{
515
684
   // Simplifies other routines.
516
685
   if (Pkg.end() == true)
522
691
       Pkg.CurrentVer().Downloadable() == false)
523
692
      return;
524
693
   
 
694
   /** \todo Can this be moved later in the method? */
 
695
   ActionGroup group(*this);
 
696
 
525
697
   /* We changed the soft state all the time so the UI is a bit nicer
526
698
      to use */
527
699
   StateCache &P = PkgState[Pkg->ID];
537
709
   // We dont even try to keep virtual packages..
538
710
   if (Pkg->VersionList == 0)
539
711
      return;
540
 
   
541
 
   P.Flags &= ~Flag::Auto;
 
712
#if 0 // reseting the autoflag here means we lose the 
 
713
      // auto-mark information if a user selects a package for removal
 
714
      // but changes  his mind then and sets it for keep again
 
715
      // - this makes sense as default when all Garbage dependencies
 
716
      //   are automatically marked for removal (as aptitude does).
 
717
      //   setting a package for keep then makes it no longer autoinstalled
 
718
      //   for all other use-case this action is rather suprising
 
719
   if(FromUser && !P.Marked)
 
720
     P.Flags &= ~Flag::Auto;
 
721
#endif
 
722
 
542
723
   RemoveSizes(Pkg);
543
724
   RemoveStates(Pkg);
544
725
 
564
745
   if (Pkg.end() == true)
565
746
      return;
566
747
 
 
748
   ActionGroup group(*this);
 
749
 
567
750
   // Check that it is not already marked for delete
568
751
   StateCache &P = PkgState[Pkg->ID];
569
752
   P.iFlags &= ~(AutoKept | Purge);
586
769
   else
587
770
      P.Mode = ModeDelete;
588
771
   P.InstallVer = 0;
589
 
   P.Flags &= Flag::Auto;
590
772
 
591
773
   AddStates(Pkg);   
592
774
   Update(Pkg);
597
779
// ---------------------------------------------------------------------
598
780
/* */
599
781
void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
600
 
                              unsigned long Depth)
 
782
                              unsigned long Depth, bool FromUser,
 
783
                              bool ForceImportantDeps)
601
784
{
602
785
   if (Depth > 100)
603
786
      return;
606
789
   if (Pkg.end() == true)
607
790
      return;
608
791
   
 
792
   ActionGroup group(*this);
 
793
 
609
794
   /* Check that it is not already marked for install and that it can be 
610
795
      installed */
611
796
   StateCache &P = PkgState[Pkg->ID];
612
797
   P.iFlags &= ~AutoKept;
613
 
   if (P.InstBroken() == false && (P.Mode == ModeInstall ||
 
798
   if ((P.InstPolicyBroken() == false && P.InstBroken() == false) && 
 
799
       (P.Mode == ModeInstall ||
614
800
        P.CandidateVer == (Version *)Pkg.CurrentVer()))
615
801
   {
616
802
      if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
617
 
         MarkKeep(Pkg);
 
803
         MarkKeep(Pkg, false, FromUser);
618
804
      return;
619
805
   }
620
806
 
621
807
   // See if there is even any possible instalation candidate
622
808
   if (P.CandidateVer == 0)
623
809
      return;
624
 
   
625
810
   // We dont even try to install virtual packages..
626
811
   if (Pkg->VersionList == 0)
627
812
      return;
628
 
   
629
813
   /* Target the candidate version and remove the autoflag. We reset the
630
814
      autoflag below if this was called recursively. Otherwise the user
631
815
      should have the ability to de-auto a package by changing its state */
634
818
   
635
819
   P.Mode = ModeInstall;
636
820
   P.InstallVer = P.CandidateVer;
637
 
   P.Flags &= ~Flag::Auto;
 
821
 
 
822
   if(FromUser)
 
823
     {
 
824
       // Set it to manual if it's a new install or cancelling the
 
825
       // removal of a garbage package.
 
826
       if(P.Status == 2 || (!Pkg.CurrentVer().end() && !P.Marked))
 
827
         P.Flags &= ~Flag::Auto;
 
828
     }
 
829
   else
 
830
     {
 
831
       // Set it to auto if this is a new install.
 
832
       if(P.Status == 2)
 
833
         P.Flags |= Flag::Auto;
 
834
     }
638
835
   if (P.CandidateVer == (Version *)Pkg.CurrentVer())
639
836
      P.Mode = ModeKeep;
640
837
       
666
863
 
667
864
      /* Check if this dep should be consider for install. If it is a user
668
865
         defined important dep and we are installed a new package then 
669
 
         it will be installed. Otherwise we only worry about critical deps */
 
866
         it will be installed. Otherwise we only check for important
 
867
         deps that have changed from the installed version
 
868
      */
670
869
      if (IsImportantDep(Start) == false)
671
870
         continue;
672
 
      if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
 
871
      
 
872
      /* check if any ImportantDep() (but not Critial) where added
 
873
       * since we installed the package
 
874
       */
 
875
      bool isNewImportantDep = false;
 
876
      if(!ForceImportantDeps && !Start.IsCritical())
 
877
      {
 
878
         bool found=false;
 
879
         VerIterator instVer = Pkg.CurrentVer();
 
880
         if(!instVer.end())
 
881
         {
 
882
            for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
 
883
            {
 
884
               //FIXME: deal better with or-groups(?)
 
885
               DepIterator LocalStart = D;
 
886
               
 
887
               if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg())
 
888
                  found=true;
 
889
            }
 
890
            // this is a new dep if it was not found to be already
 
891
            // a important dep of the installed pacakge
 
892
            isNewImportantDep = !found;
 
893
         }
 
894
      }
 
895
      if(isNewImportantDep)
 
896
         if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
 
897
            std::clog << "new important dependency: " 
 
898
                      << Start.TargetPkg().Name() << std::endl;
 
899
 
 
900
      // skip important deps if the package is already installed
 
901
      if (Pkg->CurrentVer != 0 && Start.IsCritical() == false 
 
902
          && !isNewImportantDep && !ForceImportantDeps)
673
903
         continue;
674
904
      
675
905
      /* If we are in an or group locate the first or that can 
680
910
      /* This bit is for processing the possibilty of an install/upgrade
681
911
         fixing the problem */
682
912
      SPtrArray<Version *> List = Start.AllTargets();
683
 
      if ((DepState[Start->ID] & DepCVer) == DepCVer)
 
913
      if (Start->Type != Dep::DpkgBreaks &&
 
914
          (DepState[Start->ID] & DepCVer) == DepCVer)
684
915
      {
685
916
         // Right, find the best version to install..
686
917
         Version **Cur = List;
711
942
            }
712
943
         }
713
944
         
714
 
         if (InstPkg.end() == false)
 
945
         if (InstPkg.end() == false) 
715
946
         {
716
947
            if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
717
948
               std::clog << "Installing " << InstPkg.Name() 
718
949
                         << " as dep of " << Pkg.Name() 
719
950
                         << std::endl;
720
 
            MarkInstall(InstPkg,true,Depth + 1);
721
 
 
722
 
            // Set the autoflag, after MarkInstall because MarkInstall unsets it
723
 
            if (P->CurrentVer == 0)
724
 
               PkgState[InstPkg->ID].Flags |= Flag::Auto;
 
951
            // now check if we should consider it a automatic dependency or not
 
952
            string sec = _config->Find("APT::Never-MarkAuto-Section","");
 
953
            if(Pkg.Section() && (string(Pkg.Section()) ==  sec))
 
954
            {
 
955
               if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
 
956
                  std::clog << "Setting NOT as auto-installed because its a direct dep of a package in section " << sec << std::endl;
 
957
               MarkInstall(InstPkg,true,Depth + 1, true);
 
958
            }
 
959
            else 
 
960
            {
 
961
               // mark automatic dependency
 
962
               MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps);
 
963
               // Set the autoflag, after MarkInstall because MarkInstall unsets it
 
964
               if (P->CurrentVer == 0)
 
965
                  PkgState[InstPkg->ID].Flags |= Flag::Auto;
 
966
            }
725
967
         }
726
 
         
727
968
         continue;
728
969
      }
729
 
      
 
970
 
730
971
      /* For conflicts we just de-install the package and mark as auto,
731
 
         Conflicts may not have or groups */
732
 
      if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes)
 
972
         Conflicts may not have or groups.  For dpkg's Breaks we try to
 
973
         upgrade the package. */
 
974
      if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes ||
 
975
          Start->Type == Dep::DpkgBreaks)
733
976
      {
734
977
         for (Version **I = List; *I != 0; I++)
735
978
         {
736
979
            VerIterator Ver(*this,*I);
737
980
            PkgIterator Pkg = Ver.ParentPkg();
738
 
      
739
 
            MarkDelete(Pkg);
740
 
            PkgState[Pkg->ID].Flags |= Flag::Auto;
 
981
 
 
982
            if (Start->Type != Dep::DpkgBreaks)
 
983
               MarkDelete(Pkg);
 
984
            else
 
985
               if (PkgState[Pkg->ID].CandidateVer != *I)
 
986
                  MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
741
987
         }
742
988
         continue;
743
989
      }      
749
995
/* */
750
996
void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
751
997
{
 
998
   ActionGroup group(*this);
 
999
 
752
1000
   RemoveSizes(Pkg);
753
1001
   RemoveStates(Pkg);
754
1002
   
767
1015
/* */
768
1016
void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
769
1017
{
 
1018
   ActionGroup group(*this);
 
1019
 
770
1020
   pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
771
1021
   StateCache &P = PkgState[Pkg->ID];
772
 
   
 
1022
 
773
1023
   RemoveSizes(Pkg);
774
1024
   RemoveStates(Pkg);
775
1025
 
782
1032
   Update(Pkg);
783
1033
   AddSizes(Pkg);
784
1034
}
 
1035
 
 
1036
void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
 
1037
{
 
1038
  StateCache &state = PkgState[Pkg->ID];
 
1039
 
 
1040
  ActionGroup group(*this);
 
1041
 
 
1042
  if(Auto)
 
1043
    state.Flags |= Flag::Auto;
 
1044
  else
 
1045
    state.Flags &= ~Flag::Auto;
 
1046
}
785
1047
                                                                        /*}}}*/
786
1048
// StateCache::Update - Compute the various static display things       /*{{{*/
787
1049
// ---------------------------------------------------------------------
869
1131
/* */
870
1132
bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
871
1133
{
872
 
   return Dep.IsCritical();
 
1134
   if(Dep.IsCritical())
 
1135
      return true;
 
1136
   else if(Dep->Type == pkgCache::Dep::Recommends) 
 
1137
   {
 
1138
      if ( _config->FindB("APT::Install-Recommends", false))
 
1139
         return true;
 
1140
      // we suport a special mode to only install-recommends for certain
 
1141
      // sections
 
1142
      // FIXME: this is a meant as a temporarly solution until the 
 
1143
      //        recommends are cleaned up
 
1144
      string s = _config->Find("APT::Install-Recommends-Section","");
 
1145
      if(s.size() > 0) 
 
1146
      {
 
1147
         const char *sec = Dep.TargetPkg().Section();
 
1148
         if (sec && strcmp(sec, s.c_str()) == 0)
 
1149
            return true;
 
1150
      }
 
1151
   }
 
1152
   else if(Dep->Type == pkgCache::Dep::Suggests)
 
1153
     return _config->FindB("APT::Install-Suggests", false);
 
1154
 
 
1155
   return false;
873
1156
}
874
1157
                                                                        /*}}}*/
 
1158
 
 
1159
pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
 
1160
  : constructedSuccessfully(false)
 
1161
{
 
1162
  Configuration::Item const *Opts;
 
1163
  Opts = _config->Tree("APT::NeverAutoRemove");
 
1164
  if (Opts != 0 && Opts->Child != 0)
 
1165
    {
 
1166
      Opts = Opts->Child;
 
1167
      for (; Opts != 0; Opts = Opts->Next)
 
1168
        {
 
1169
          if (Opts->Value.empty() == true)
 
1170
            continue;
 
1171
 
 
1172
          regex_t *p = new regex_t;
 
1173
          if(regcomp(p,Opts->Value.c_str(),
 
1174
                     REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
 
1175
            {
 
1176
              regfree(p);
 
1177
              delete p;
 
1178
              _error->Error("Regex compilation error for APT::NeverAutoRemove");
 
1179
              return;
 
1180
            }
 
1181
 
 
1182
          rootSetRegexp.push_back(p);
 
1183
        }
 
1184
    }
 
1185
 
 
1186
  constructedSuccessfully = true;
 
1187
}
 
1188
 
 
1189
pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
 
1190
{
 
1191
  for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
 
1192
    {
 
1193
      regfree(rootSetRegexp[i]);
 
1194
      delete rootSetRegexp[i];
 
1195
    }
 
1196
}
 
1197
 
 
1198
 
 
1199
bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg)
 
1200
{
 
1201
   for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
 
1202
      if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
 
1203
         return true;
 
1204
 
 
1205
   return false;
 
1206
}
 
1207
 
 
1208
pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
 
1209
{
 
1210
  DefaultRootSetFunc *f = new DefaultRootSetFunc;
 
1211
  if(f->wasConstructedSuccessfully())
 
1212
    return f;
 
1213
  else
 
1214
    {
 
1215
      delete f;
 
1216
      return NULL;
 
1217
    }
 
1218
}
 
1219
 
 
1220
bool pkgDepCache::MarkFollowsRecommends()
 
1221
{
 
1222
  return _config->FindB("APT::AutoRemove::RecommendsImportant", true);
 
1223
}
 
1224
 
 
1225
bool pkgDepCache::MarkFollowsSuggests()
 
1226
{
 
1227
  return _config->FindB("APT::AutoRemove::SuggestsImportant", false);
 
1228
}
 
1229
 
 
1230
// the main mark algorithm
 
1231
bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
 
1232
{
 
1233
   bool follow_recommends;
 
1234
   bool follow_suggests;
 
1235
 
 
1236
   // init the states
 
1237
   for(PkgIterator p = PkgBegin(); !p.end(); ++p)
 
1238
   {
 
1239
      PkgState[p->ID].Marked  = false;
 
1240
      PkgState[p->ID].Garbage = false;
 
1241
 
 
1242
      // debug output
 
1243
      if(_config->FindB("Debug::pkgAutoRemove",false) 
 
1244
         && PkgState[p->ID].Flags & Flag::Auto)
 
1245
         std::clog << "AutoDep: " << p.Name() << std::endl;
 
1246
   }
 
1247
 
 
1248
   // init vars
 
1249
   follow_recommends = MarkFollowsRecommends();
 
1250
   follow_suggests   = MarkFollowsSuggests();
 
1251
 
 
1252
 
 
1253
 
 
1254
   // do the mark part, this is the core bit of the algorithm
 
1255
   for(PkgIterator p = PkgBegin(); !p.end(); ++p)
 
1256
   {
 
1257
      if(!(PkgState[p->ID].Flags & Flag::Auto) ||
 
1258
          (p->Flags & Flag::Essential) ||
 
1259
          userFunc.InRootSet(p))
 
1260
          
 
1261
      {
 
1262
         // the package is installed (and set to keep)
 
1263
         if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
 
1264
            MarkPackage(p, p.CurrentVer(),
 
1265
                        follow_recommends, follow_suggests);
 
1266
         // the package is to be installed 
 
1267
         else if(PkgState[p->ID].Install())
 
1268
            MarkPackage(p, PkgState[p->ID].InstVerIter(*this),
 
1269
                        follow_recommends, follow_suggests);
 
1270
      }
 
1271
   }
 
1272
 
 
1273
   return true;
 
1274
}
 
1275
 
 
1276
// mark a single package in Mark-and-Sweep
 
1277
void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
 
1278
                              const pkgCache::VerIterator &ver,
 
1279
                              bool follow_recommends,
 
1280
                              bool follow_suggests)
 
1281
{
 
1282
   pkgDepCache::StateCache &state = PkgState[pkg->ID];
 
1283
   VerIterator candver            = state.CandidateVerIter(*this);
 
1284
   VerIterator instver            = state.InstVerIter(*this);
 
1285
 
 
1286
#if 0
 
1287
   // If a package was garbage-collected but is now being marked, we
 
1288
   // should re-select it 
 
1289
   // For cases when a pkg is set to upgrade and this trigger the
 
1290
   // removal of a no-longer used dependency.  if the pkg is set to
 
1291
   // keep again later it will result in broken deps
 
1292
   if(state.Delete() && state.RemoveReason = Unused) 
 
1293
   {
 
1294
      if(ver==candver)
 
1295
         mark_install(pkg, false, false, NULL);
 
1296
      else if(ver==pkg.CurrentVer())
 
1297
         MarkKeep(pkg, false, false);
 
1298
      
 
1299
      instver=state.InstVerIter(*this);
 
1300
   }
 
1301
#endif
 
1302
 
 
1303
   // Ignore versions other than the InstVer, and ignore packages
 
1304
   // that are already going to be removed or just left uninstalled.
 
1305
   if(!(ver == instver && !instver.end()))
 
1306
      return;
 
1307
 
 
1308
   // if we are marked already we are done
 
1309
   if(state.Marked)
 
1310
      return;
 
1311
 
 
1312
   //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
 
1313
   state.Marked=true;
 
1314
 
 
1315
   if(!ver.end())
 
1316
   {
 
1317
     for(DepIterator d = ver.DependsList(); !d.end(); ++d)
 
1318
     {
 
1319
        if(d->Type == Dep::Depends ||
 
1320
           d->Type == Dep::PreDepends ||
 
1321
           (follow_recommends &&
 
1322
            d->Type == Dep::Recommends) ||
 
1323
           (follow_suggests &&
 
1324
            d->Type == Dep::Suggests))
 
1325
        {
 
1326
           // Try all versions of this package.
 
1327
           for(VerIterator V = d.TargetPkg().VersionList(); 
 
1328
               !V.end(); ++V)
 
1329
           {
 
1330
              if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
 
1331
              {
 
1332
                 MarkPackage(V.ParentPkg(), V, 
 
1333
                             follow_recommends, follow_suggests);
 
1334
              }
 
1335
           }
 
1336
           // Now try virtual packages
 
1337
           for(PrvIterator prv=d.TargetPkg().ProvidesList(); 
 
1338
               !prv.end(); ++prv)
 
1339
           {
 
1340
              if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, 
 
1341
                                       d.TargetVer()))
 
1342
              {
 
1343
                 MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
 
1344
                             follow_recommends, follow_suggests);
 
1345
              }
 
1346
           }
 
1347
        }
 
1348
     }
 
1349
   }
 
1350
}
 
1351
 
 
1352
bool pkgDepCache::Sweep()
 
1353
{
 
1354
   // do the sweep
 
1355
   for(PkgIterator p=PkgBegin(); !p.end(); ++p)
 
1356
  {
 
1357
     StateCache &state=PkgState[p->ID];
 
1358
 
 
1359
     // skip required packages
 
1360
     if (!p.CurrentVer().end() && 
 
1361
         (p.CurrentVer()->Priority == pkgCache::State::Required))
 
1362
        continue;
 
1363
 
 
1364
     // if it is not marked and it is installed, it's garbage 
 
1365
     if(!state.Marked && (!p.CurrentVer().end() || state.Install()))
 
1366
     {
 
1367
        state.Garbage=true;
 
1368
        if(_config->FindB("Debug::pkgAutoRemove",false))
 
1369
           std::cout << "Garbage: " << p.Name() << std::endl;
 
1370
     }
 
1371
  }   
 
1372
 
 
1373
   return true;
 
1374
}