]> git.saurik.com Git - apt.git/commitdiff
* merged the install-recommends branch
authorMichael Vogt <egon@bottom>
Tue, 15 Aug 2006 13:18:51 +0000 (15:18 +0200)
committerMichael Vogt <egon@bottom>
Tue, 15 Aug 2006 13:18:51 +0000 (15:18 +0200)
1  2 
apt-pkg/depcache.cc
apt-pkg/depcache.h
apt-pkg/init.cc
apt-pkg/init.h
apt-pkg/makefile
cmdline/apt-get.cc
configure.in
debian/changelog
doc/examples/configure-index
methods/makefile

diff --combined apt-pkg/depcache.cc
index 369eae70b3418d3a73e86bd2a125c87e42214636,b5b96dbcf3c5bd23932388d8ca6e639a717333e6..5052c62a43de19ff9c9f39a6f3321ecd00a6708c
  #include <apt-pkg/error.h>
  #include <apt-pkg/sptr.h>
  #include <apt-pkg/algorithms.h>
 +
 +#include <apt-pkg/fileutl.h>
  #include <apt-pkg/configuration.h>
 +#include <apt-pkg/pkgsystem.h>
 +#include <apt-pkg/tagfile.h>
 +
 +#include <iostream>
 +#include <sstream>    
 +#include <set>
 +
  #include <apti18n.h>    
 -                                                                      /*}}}*/
 +
 +pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :
 +  cache(cache), released(false)
 +{
 +  ++cache.group_level;
 +}
 +
 +void pkgDepCache::ActionGroup::release()
 +{
 +  if(!released)
 +    {
 +      if(cache.group_level == 0)
 +      std::cerr << "W: Unbalanced action groups, expect badness" << std::endl;
 +      else
 +      {
 +        --cache.group_level;
 +
 +        if(cache.group_level == 0)
 +          cache.MarkAndSweep();
 +      }
 +
 +      released = false;
 +    }
 +}
 +
 +pkgDepCache::ActionGroup::~ActionGroup()
 +{
 +  release();
 +}
  
  // DepCache::pkgDepCache - Constructors                                       /*{{{*/
  // ---------------------------------------------------------------------
  /* */
  pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
 -                Cache(pCache), PkgState(0), DepState(0)
 +  group_level(0), Cache(pCache), PkgState(0), DepState(0)
  {
     delLocalPolicy = 0;
     LocalPolicy = Plcy;
@@@ -84,10 -47,6 +84,10 @@@ pkgDepCache::~pkgDepCache(
  /* This allocats the extension buffers and initializes them. */
  bool pkgDepCache::Init(OpProgress *Prog)
  {
 +   // Suppress mark updates during this operation (just in case) and
 +   // run a mark operation when Init terminates.
 +   ActionGroup actions(*this);
 +
     delete [] PkgState;
     delete [] DepState;
     PkgState = new StateCache[Head().PackageCount];
        // Find the proper cache slot
        StateCache &State = PkgState[I->ID];
        State.iFlags = 0;
 -      
 +
        // Figure out the install version
        State.CandidateVer = GetCandidateVer(I);
        State.InstallVer = I.CurrentVer();
  
     if(Prog != 0)
        Prog->Done();
 -   
 +
     return true;
  } 
                                                                        /*}}}*/
  
 +bool pkgDepCache::readStateFile(OpProgress *Prog)
 +{
 +   FileFd state_file;
 +   string state = _config->FindDir("Dir::State") + "extended_states";
 +   if(FileExists(state)) {
 +      state_file.Open(state, FileFd::ReadOnly);
 +      int file_size = state_file.Size();
 +      if(Prog != NULL)
 +       Prog->OverallProgress(0, file_size, 1, 
 +                             _("Reading state information"));
 +
 +      pkgTagFile tagfile(&state_file);
 +      pkgTagSection section;
 +      int amt=0;
 +      while(tagfile.Step(section)) {
 +       string pkgname = section.FindS("Package");
 +       pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
 +       // Silently ignore unknown packages and packages with no actual
 +       // version.
 +       if(!pkg.end() && !pkg.VersionList().end()) {
 +          short reason = section.FindI("Auto-Installed", 0);
 +          if(reason > 0)
 +             PkgState[pkg->ID].Flags  |= Flag::Auto;
 +          if(_config->FindB("Debug::pkgAutoRemove",false))
 +             std::cout << "Auto-Installed : " << pkgname << std::endl;
 +          amt+=section.size();
 +          if(Prog != NULL)
 +             Prog->OverallProgress(amt, file_size, 1, 
 +                                   _("Reading state information"));
 +       }
 +       if(Prog != NULL)
 +          Prog->OverallProgress(file_size, file_size, 1, 
 +                                _("Reading state information"));
 +      }
 +   }
 +
 +   return true;
 +}
 +
 +bool pkgDepCache::writeStateFile(OpProgress *prog)
 +{
 +   if(_config->FindB("Debug::pkgAutoRemove",false))
 +      std::clog << "pkgDepCache::writeStateFile()" << std::endl;
 +
 +   FileFd StateFile;
 +   string state = _config->FindDir("Dir::State") + "extended_states";
 +
 +   // if it does not exist, create a empty one
 +   if(!FileExists(state)) 
 +   {
 +      StateFile.Open(state, FileFd::WriteEmpty);
 +      StateFile.Close();
 +   }
 +
 +   // open it
 +   if(!StateFile.Open(state, FileFd::ReadOnly))
 +      return _error->Error(_("Failed to open StateFile %s"),
 +                         state.c_str());
 +
 +   FILE *OutFile;
 +   string outfile = state + ".tmp";
 +   if((OutFile = fopen(outfile.c_str(),"w")) == NULL)
 +      return _error->Error(_("Failed to write temporary StateFile %s"),
 +                         outfile.c_str());
 +
 +   // first merge with the existing sections
 +   pkgTagFile tagfile(&StateFile);
 +   pkgTagSection section;
 +   std::set<string> pkgs_seen;
 +   const char *nullreorderlist[] = {0};
 +   while(tagfile.Step(section)) {
 +       string pkgname = section.FindS("Package");
 +       // Silently ignore unknown packages and packages with no actual
 +       // version.
 +       pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
 +       if(pkg.end() || pkg.VersionList().end()) 
 +          continue;
 +       bool oldAuto = section.FindI("Auto-Installed");
 +       bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
 +       if(_config->FindB("Debug::pkgAutoRemove",false))
 +          std::clog << "Update exisiting AutoInstall info: " 
 +                    << pkg.Name() << std::endl;
 +       TFRewriteData rewrite[2];
 +       rewrite[0].Tag = "Auto-Installed";
 +       rewrite[0].Rewrite = newAuto ? "1" : "0";
 +       rewrite[0].NewTag = 0;
 +       rewrite[1].Tag = 0;
 +       TFRewrite(OutFile, section, nullreorderlist, rewrite);
 +       fprintf(OutFile,"\n");
 +       pkgs_seen.insert(pkgname);
 +   }
 +   
 +   // then write the ones we have not seen yet
 +   std::ostringstream ostr;
 +   for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) {
 +      if(PkgState[pkg->ID].Flags & Flag::Auto) {
 +       if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) {
 +          if(_config->FindB("Debug::pkgAutoRemove",false))
 +             std::clog << "Skipping already written " << pkg.Name() << std::endl;
 +          continue;
 +       }
 +       if(_config->FindB("Debug::pkgAutoRemove",false))
 +          std::clog << "Writing new AutoInstall: " 
 +                    << pkg.Name() << std::endl;
 +       ostr.str(string(""));
 +       ostr << "Package: " << pkg.Name() 
 +            << "\nAuto-Installed: 1\n\n";
 +       fprintf(OutFile,ostr.str().c_str());
 +       fprintf(OutFile,"\n");
 +      }
 +   }
 +   fclose(OutFile);
 +
 +   // move the outfile over the real file
 +   rename(outfile.c_str(), state.c_str());
 +
 +   return true;
 +}
 +
  // DepCache::CheckDep - Checks a single dependency                    /*{{{*/
  // ---------------------------------------------------------------------
  /* This first checks the dependency against the main target package and
@@@ -399,9 -239,11 +399,11 @@@ void pkgDepCache::AddStates(const PkgIt
  {
     StateCache &State = PkgState[Pkg->ID];
     
-    // The Package is broken
+    // The Package is broken (either minimal dep or policy dep)
     if ((State.DepState & DepInstMin) != DepInstMin)
        iBrokenCount += Add;
+    if ((State.DepState & DepInstPolicy) != DepInstPolicy)
+       iPolicyBrokenCount += Add;
     
     // Bad state
     if (Pkg.State() != PkgIterator::NeedsNothing)
@@@ -612,14 -454,12 +614,14 @@@ void pkgDepCache::Update(OpProgress *Pr
  
     if (Prog != 0)      
        Prog->Progress(Done);
 +
 +   readStateFile(Prog);
  }
                                                                        /*}}}*/
  // DepCache::Update - Update the deps list of a package                       /*{{{*/
  // ---------------------------------------------------------------------
  /* This is a helper for update that only does the dep portion of the scan. 
 -   It is mainly ment to scan reverse dependencies. */
 +   It is mainly meant to scan reverse dependencies. */
  void pkgDepCache::Update(DepIterator D)
  {
     // Update the reverse deps
@@@ -671,7 -511,7 +673,7 @@@ void pkgDepCache::Update(PkgIterator co
  // DepCache::MarkKeep - Put the package in the keep state             /*{{{*/
  // ---------------------------------------------------------------------
  /* */
 -void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
 +void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
  {
     // Simplifies other routines.
     if (Pkg.end() == true)
         Pkg.CurrentVer().Downloadable() == false)
        return;
     
 +   /** \todo Can this be moved later in the method? */
 +   ActionGroup group(*this);
 +
     /* We changed the soft state all the time so the UI is a bit nicer
        to use */
     StateCache &P = PkgState[Pkg->ID];
     if (Pkg->VersionList == 0)
        return;
     
 -   P.Flags &= ~Flag::Auto;
 +   if(FromUser && !P.Marked)
 +     P.Flags &= ~Flag::Auto;
     RemoveSizes(Pkg);
     RemoveStates(Pkg);
  
@@@ -729,8 -565,6 +731,8 @@@ void pkgDepCache::MarkDelete(PkgIterato
     if (Pkg.end() == true)
        return;
  
 +   ActionGroup group(*this);
 +
     // Check that it is not already marked for delete
     StateCache &P = PkgState[Pkg->ID];
     P.iFlags &= ~(AutoKept | Purge);
     else
        P.Mode = ModeDelete;
     P.InstallVer = 0;
 -   P.Flags &= Flag::Auto;
  
     AddStates(Pkg);   
     Update(Pkg);
  // ---------------------------------------------------------------------
  /* */
  void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
-                             unsigned long Depth, bool FromUser)
 -                            unsigned long Depth, bool ForceImportantDeps)
++                            unsigned long Depth, bool FromUser,
++                            bool ForceImportantDeps)
  {
     if (Depth > 100)
        return;
     if (Pkg.end() == true)
        return;
     
 +   ActionGroup group(*this);
 +
     /* Check that it is not already marked for install and that it can be 
        installed */
     StateCache &P = PkgState[Pkg->ID];
     P.iFlags &= ~AutoKept;
-    if (P.InstBroken() == false && (P.Mode == ModeInstall ||
+    if ((P.InstPolicyBroken() == false && P.InstBroken() == false) && 
+        (P.Mode == ModeInstall ||
        P.CandidateVer == (Version *)Pkg.CurrentVer()))
     {
        if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
 -       MarkKeep(Pkg);
 +       MarkKeep(Pkg, false, FromUser);
        return;
     }
  
     // See if there is even any possible instalation candidate
     if (P.CandidateVer == 0)
        return;
-    
     // We dont even try to install virtual packages..
     if (Pkg->VersionList == 0)
        return;
-    
     /* Target the candidate version and remove the autoflag. We reset the
        autoflag below if this was called recursively. Otherwise the user
        should have the ability to de-auto a package by changing its state */
     
     P.Mode = ModeInstall;
     P.InstallVer = P.CandidateVer;
 -   P.Flags &= ~Flag::Auto;
 +
 +   if(FromUser)
 +     {
 +       // Set it to manual if it's a new install or cancelling the
 +       // removal of a garbage package.
 +       if(P.Status == 2 || (!Pkg.CurrentVer().end() && !P.Marked))
 +       P.Flags &= ~Flag::Auto;
 +     }
 +   else
 +     {
 +       // Set it to auto if this is a new install.
 +       if(P.Status == 2)
 +       P.Flags |= Flag::Auto;
 +     }
     if (P.CandidateVer == (Version *)Pkg.CurrentVer())
        P.Mode = ModeKeep;
         
  
        /* Check if this dep should be consider for install. If it is a user
           defined important dep and we are installed a new package then 
-        it will be installed. Otherwise we only worry about critical deps */
+        it will be installed. Otherwise we only check for important
+          deps that have changed from the installed version
+       */
        if (IsImportantDep(Start) == false)
         continue;
-       if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
+       
+       /* check if any ImportantDep() (but not Critial) where added
+        * since we installed the package
+        */
+       bool isNewImportantDep = false;
+       if(!ForceImportantDeps && !Start.IsCritical())
+       {
+        bool found=false;
+        VerIterator instVer = Pkg.CurrentVer();
+        if(!instVer.end())
+           for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
+           {
+              //FIXME: deal better with or-groups(?)
+              DepIterator LocalStart = D;
+              
+              if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg())
+                 found=true;
+           }
+        // this is a new dep if it was not found to be already
+        // a important dep of the installed pacakge
+        isNewImportantDep = !found;
+       }
+       if(isNewImportantDep)
+        if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
+           std::clog << "new important dependency: " 
+                     << Start.TargetPkg().Name() << std::endl;
+       // skip important deps if the package is already installed
+       if (Pkg->CurrentVer != 0 && Start.IsCritical() == false 
+         && !isNewImportantDep && !ForceImportantDeps)
         continue;
        
        /* If we are in an or group locate the first or that can 
            }
         }
         
 -       if (InstPkg.end() == false)
 +       if (InstPkg.end() == false) 
         {
            if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
               std::clog << "Installing " << InstPkg.Name() 
                         << " as dep of " << Pkg.Name() 
                         << std::endl;
-          MarkInstall(InstPkg, true, Depth + 1, false);
 -          MarkInstall(InstPkg,true,Depth + 1, ForceImportantDeps);
 -
 -          // Set the autoflag, after MarkInstall because MarkInstall unsets it
++         MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps);
++          // Set the autoflag, after MarkInstall because MarkInstall 
++          // unsets it
+           if (P->CurrentVer == 0)
+              PkgState[InstPkg->ID].Flags |= Flag::Auto;
         }
 -       
         continue;
        }
        
            PkgIterator Pkg = Ver.ParentPkg();
        
            MarkDelete(Pkg);
 -          PkgState[Pkg->ID].Flags |= Flag::Auto;
         }
         continue;
        }      
  /* */
  void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
  {
 +   ActionGroup group(*this);
 +
     RemoveSizes(Pkg);
     RemoveStates(Pkg);
     
  /* */
  void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
  {
 +   ActionGroup group(*this);
 +
     pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
     StateCache &P = PkgState[Pkg->ID];
 -   
 +
     RemoveSizes(Pkg);
     RemoveStates(Pkg);
  
     Update(Pkg);
     AddSizes(Pkg);
  }
 +
 +void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
 +{
 +  StateCache &state = PkgState[Pkg->ID];
 +
 +  ActionGroup group(*this);
 +
 +  if(Auto)
 +    state.Flags |= Flag::Auto;
 +  else
 +    state.Flags &= ~Flag::Auto;
 +}
                                                                        /*}}}*/
  // StateCache::Update - Compute the various static display things     /*{{{*/
  // ---------------------------------------------------------------------
@@@ -1060,219 -900,13 +1097,226 @@@ pkgCache::VerIterator pkgDepCache::Poli
  /* */
  bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
  {
-    return Dep.IsCritical();
+    if(Dep.IsCritical())
+       return true;
+    else if(Dep->Type == pkgCache::Dep::Recommends)
+       return  _config->FindB("APT::Install-Recommends", false);
+    else if(Dep->Type == pkgCache::Dep::Suggests)
+      return _config->FindB("APT::Install-Suggests", false);
+    return false;
  }
                                                                        /*}}}*/
 +
 +pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
 +  : constructedSuccessfully(false)
 +{
 +  Configuration::Item const *Opts;
 +  Opts = _config->Tree("APT::NeverAutoRemove");
 +  if (Opts != 0 && Opts->Child != 0)
 +    {
 +      Opts = Opts->Child;
 +      for (; Opts != 0; Opts = Opts->Next)
 +      {
 +        if (Opts->Value.empty() == true)
 +          continue;
 +
 +        regex_t *p = new regex_t;
 +        if(regcomp(p,Opts->Value.c_str(),
 +                   REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
 +          {
 +            regfree(p);
 +            delete p;
 +            _error->Error("Regex compilation error for APT::NeverAutoRemove");
 +            return;
 +          }
 +
 +        rootSetRegexp.push_back(p);
 +      }
 +    }
 +
 +  constructedSuccessfully = true;
 +}
 +
 +pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
 +{
 +  for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
 +    {
 +      regfree(rootSetRegexp[i]);
 +      delete rootSetRegexp[i];
 +    }
 +}
 +
 +
 +bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg)
 +{
 +   for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
 +      if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
 +       return true;
 +
 +   return false;
 +}
 +
 +pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
 +{
 +  DefaultRootSetFunc *f = new DefaultRootSetFunc;
 +  if(f->wasConstructedSuccessfully())
 +    return f;
 +  else
 +    {
 +      delete f;
 +      return NULL;
 +    }
 +}
 +
 +bool pkgDepCache::MarkFollowsRecommends()
 +{
 +  return _config->FindB("APT::AutoRemove::RecommendsImportant", true);
 +}
 +
 +bool pkgDepCache::MarkFollowsSuggests()
 +{
 +  return _config->FindB("APT::AutoRemove::SuggestsImportant", false);
 +}
 +
 +// the main mark algorithm
 +bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
 +{
 +   bool follow_recommends;
 +   bool follow_suggests;
 +
 +   // init the states
 +   for(PkgIterator p = PkgBegin(); !p.end(); ++p)
 +   {
 +      PkgState[p->ID].Marked  = false;
 +      PkgState[p->ID].Garbage = false;
 +
 +      // debug output
 +      if(_config->FindB("Debug::pkgAutoRemove",false) 
 +       && PkgState[p->ID].Flags & Flag::Auto)
 +       std::clog << "AutoDep: " << p.Name() << std::endl;
 +   }
 +
 +   // init vars
 +   follow_recommends = MarkFollowsRecommends();
 +   follow_suggests   = MarkFollowsSuggests();
 +
 +
 +
 +   // do the mark part, this is the core bit of the algorithm
 +   for(PkgIterator p = PkgBegin(); !p.end(); ++p)
 +   {
 +      if(!(PkgState[p->ID].Flags & Flag::Auto) ||
 +        (p->Flags & Flag::Essential) ||
 +        userFunc.InRootSet(p))
 +          
 +      {
 +       // the package is installed (and set to keep)
 +       if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
 +          MarkPackage(p, p.CurrentVer(),
 +                      follow_recommends, follow_suggests);
 +       // the package is to be installed 
 +       else if(PkgState[p->ID].Install())
 +          MarkPackage(p, PkgState[p->ID].InstVerIter(*this),
 +                      follow_recommends, follow_suggests);
 +      }
 +   }
 +
 +   return true;
 +}
 +
 +// mark a single package in Mark-and-Sweep
 +void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
 +                            const pkgCache::VerIterator &ver,
 +                            bool follow_recommends,
 +                            bool follow_suggests)
 +{
 +   pkgDepCache::StateCache &state = PkgState[pkg->ID];
 +   VerIterator candver            = state.CandidateVerIter(*this);
 +   VerIterator instver            = state.InstVerIter(*this);
 +
 +#if 0
 +   // If a package was garbage-collected but is now being marked, we
 +   // should re-select it 
 +   // For cases when a pkg is set to upgrade and this trigger the
 +   // removal of a no-longer used dependency.  if the pkg is set to
 +   // keep again later it will result in broken deps
 +   if(state.Delete() && state.RemoveReason = Unused) 
 +   {
 +      if(ver==candver)
 +       mark_install(pkg, false, false, NULL);
 +      else if(ver==pkg.CurrentVer())
 +       MarkKeep(pkg, false, false);
 +      
 +      instver=state.InstVerIter(*this);
 +   }
 +#endif
 +
 +   // Ignore versions other than the InstVer, and ignore packages
 +   // that are already going to be removed or just left uninstalled.
 +   if(!(ver == instver && !instver.end()))
 +      return;
 +
 +   // if we are marked already we are done
 +   if(state.Marked)
 +      return;
 +
 +   //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
 +   state.Marked=true;
 +
 +   if(!ver.end())
 +   {
 +     for(DepIterator d = ver.DependsList(); !d.end(); ++d)
 +     {
 +      if(d->Type == Dep::Depends ||
 +         d->Type == Dep::PreDepends ||
 +         (follow_recommends &&
 +          d->Type == Dep::Recommends) ||
 +         (follow_suggests &&
 +          d->Type == Dep::Suggests))
 +        {
 +         // Try all versions of this package.
 +         for(VerIterator V = d.TargetPkg().VersionList(); 
 +             !V.end(); ++V)
 +         {
 +            if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
 +            {
 +               MarkPackage(V.ParentPkg(), V, 
 +                           follow_recommends, follow_suggests);
 +            }
 +         }
 +         // Now try virtual packages
 +         for(PrvIterator prv=d.TargetPkg().ProvidesList(); 
 +             !prv.end(); ++prv)
 +         {
 +            if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, 
 +                                     d.TargetVer()))
 +            {
 +               MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
 +                           follow_recommends, follow_suggests);
 +            }
 +         }
 +      }
 +     }
 +   }
 +}
 +
 +bool pkgDepCache::Sweep()
 +{
 +   // do the sweep
 +   for(PkgIterator p=PkgBegin(); !p.end(); ++p)
 +  {
 +     StateCache &state=PkgState[p->ID];
 +
 +     // if it is not marked and it is installed, it's garbage 
 +     if(!state.Marked && (!p.CurrentVer().end() || state.Install()) &&
 +      !state.Delete())
 +     {
 +      state.Garbage=true;
 +      if(_config->FindB("Debug::pkgAutoRemove",false))
 +         std::cout << "Garbage: " << p.Name() << std::endl;
 +     }
 +  }   
 +
 +   return true;
 +}
diff --combined apt-pkg/depcache.h
index fd935c2680f1f1cf68a9456dc3067e07a31af6bc,042abb5cc1619b675b7b8cd6a1b48d5d9c334673..5cd5ea354fa353bf33fb4f7e9738d283f7bb35eb
@@@ -1,4 -1,4 +1,4 @@@
 -// -*- mode: cpp; mode: fold -*-
 +// -*- mode: c++; mode: fold -*-
  // Description                                                                /*{{{*/
  // $Id: depcache.h,v 1.14 2001/02/20 07:03:17 jgg Exp $
  /* ######################################################################
  #include <apt-pkg/pkgcache.h>
  #include <apt-pkg/progress.h>
  
 +#include <regex.h>
 +
 +#include <vector>
 +
  class pkgDepCache : protected pkgCache::Namespace
  {
     public:
 +
 +   /** \brief An arbitrary predicate on packages. */
 +   class InRootSetFunc
 +   {
 +   public:
 +     virtual bool InRootSet(const pkgCache::PkgIterator &pkg) {return false;};
 +     virtual ~InRootSetFunc() {};
 +   };
 +
 +   private:
 +   /** \brief Mark a single package and all its unmarked important
 +    *  dependencies during mark-and-sweep.
 +    *
 +    *  Recursively invokes itself to mark all dependencies of the
 +    *  package.
 +    *
 +    *  \param pkg The package to mark.
 +    *
 +    *  \param ver The version of the package that is to be marked.
 +    *
 +    *  \param follow_recommends If \b true, recommendations of the
 +    *  package will be recursively marked.
 +    *
 +    *  \param follow_suggests If \b true, suggestions of the package
 +    *  will be recursively marked.
 +    */
 +   void MarkPackage(const pkgCache::PkgIterator &pkg,
 +                  const pkgCache::VerIterator &ver,
 +                  bool follow_recommends,
 +                  bool follow_suggests);
 +
 +   /** \brief Update the Marked field of all packages.
 +    *
 +    *  Each package's StateCache::Marked field will be set to \b true
 +    *  if and only if it can be reached from the root set.  By
 +    *  default, the root set consists of the set of manually installed
 +    *  or essential packages, but it can be extended using the
 +    *  parameter #rootFunc.
 +    *
 +    *  \param rootFunc A callback that can be used to add extra
 +    *  packages to the root set.
 +    *
 +    *  \return \b false if an error occured.
 +    */
 +   bool MarkRequired(InRootSetFunc &rootFunc);
 +
 +   /** \brief Set the StateCache::Garbage flag on all packages that
 +    *  should be removed.
 +    *
 +    *  Packages that were not marked by the last call to #MarkRequired
 +    *  are tested to see whether they are actually garbage.  If so,
 +    *  they are marked as such.
 +    *
 +    *  \return \b false if an error occured.
 +    */
 +   bool Sweep();
 +
 +   public:
     
     // These flags are used in DepState
     enum DepFlags {DepNow = (1 << 0),DepInstall = (1 << 1),DepCVer = (1 << 2),
        
     enum VersionTypes {NowVersion, InstallVersion, CandidateVersion};
     enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2};
 +
 +   /** \brief Represents an active action group.
 +    *
 +    *  An action group is a group of actions that are currently being
 +    *  performed.  While an active group is active, certain routine
 +    *  clean-up actions that would normally be performed after every
 +    *  cache operation are delayed until the action group is
 +    *  completed.  This is necessary primarily to avoid inefficiencies
 +    *  when modifying a large number of packages at once.
 +    *
 +    *  This class represents an active action group.  Creating an
 +    *  instance will create an action group; destroying one will
 +    *  destroy the corresponding action group.
 +    *
 +    *  The following operations are suppressed by this class:
 +    *
 +    *    - Keeping the Marked and Garbage flags up to date.
 +    *
 +    *  \note This can be used in the future to easily accumulate
 +    *  atomic actions for undo or to display "what apt did anyway";
 +    *  e.g., change the counter of how many action groups are active
 +    *  to a std::set of pointers to them and use those to store
 +    *  information about what happened in a group in the group.
 +    */
 +   class ActionGroup
 +   {
 +       pkgDepCache &cache;
 +
 +       bool released;
 +
 +       /** Action groups are noncopyable. */
 +       ActionGroup(const ActionGroup &other);
 +   public:
 +       /** \brief Create a new ActionGroup.
 +      *
 +      *  \param cache The cache that this ActionGroup should
 +      *  manipulate.
 +      *
 +      *  As long as this object exists, no automatic cleanup
 +      *  operations will be undertaken.
 +      */
 +       ActionGroup(pkgDepCache &cache);
 +
 +       /** \brief Clean up the action group before it is destroyed.
 +        *
 +        *  If it is destroyed later, no second cleanup wil be run.
 +      */
 +       void release();
 +
 +       /** \brief Destroy the action group.
 +      *
 +      *  If this is the last action group, the automatic cache
 +      *  cleanup operations will be undertaken.
 +      */
 +       ~ActionGroup();
 +   };
 +
 +   /** \brief Returns \b true for packages matching a regular
 +    *  expression in APT::NeverAutoRemove.
 +    */
 +   class DefaultRootSetFunc : public InRootSetFunc
 +   {
 +     std::vector<regex_t *> rootSetRegexp;
 +     bool constructedSuccessfully;
 +
 +   public:
 +     DefaultRootSetFunc();
 +     ~DefaultRootSetFunc();
 +
 +     /** \return \b true if the class initialized successfully, \b
 +      *  false otherwise.  Used to avoid throwing an exception, since
 +      *  APT classes generally don't.
 +      */
 +     bool wasConstructedSuccessfully() const { return constructedSuccessfully; }
 +
 +     bool InRootSet(const pkgCache::PkgIterator &pkg);
 +   };
 +
     struct StateCache
     {
        // Epoch stripped text versions of the two version fields
        unsigned short Flags;
        unsigned short iFlags;           // Internal flags
  
 +      /** \brief \b true if this package can be reached from the root set. */
 +      bool Marked;
 +
 +      /** \brief \b true if this package is unused and should be removed.
 +       *
 +       *  This differs from !#Marked, because it is possible that some
 +       *  unreachable packages will be protected from becoming
 +       *  garbage.
 +       */
 +      bool Garbage;
 +
        // Various tree indicators
        signed char Status;              // -1,0,1,2
        unsigned char Mode;              // ModeList
        inline bool Downgrade() const {return Status < 0 && Mode == ModeInstall;};
        inline bool Held() const {return Status != 0 && Keep();};
        inline bool NowBroken() const {return (DepState & DepNowMin) != DepNowMin;};
+       inline bool NowPolicyBroken() const {return (DepState & DepNowPolicy) != DepNowPolicy;};
        inline bool InstBroken() const {return (DepState & DepInstMin) != DepInstMin;};
+       inline bool InstPolicyBroken() const {return (DepState & DepInstPolicy) != DepInstPolicy;};
        inline bool Install() const {return Mode == ModeInstall;};
        inline VerIterator InstVerIter(pkgCache &Cache)
                  {return VerIterator(Cache,InstallVer);};
        
        virtual ~Policy() {};
     };
 +
 +   private:
 +   /** The number of open "action groups"; certain post-action
 +    *  operations are suppressed if this number is > 0.
 +    */
 +   int group_level;
 +
 +   friend class ActionGroup;
       
     protected:
  
     unsigned long iDelCount;
     unsigned long iKeepCount;
     unsigned long iBrokenCount;
+    unsigned long iPolicyBrokenCount;
     unsigned long iBadCount;
     
     Policy *delLocalPolicy;           // For memory clean up..
     inline StateCache &operator [](PkgIterator const &I) {return PkgState[I->ID];};
     inline unsigned char &operator [](DepIterator const &I) {return DepState[I->ID];};
  
 -   // Manipulators
 -   void MarkKeep(PkgIterator const &Pkg,bool Soft = false);
 +   /** \return A function identifying packages in the root set other
 +    *  than manually installed packages and essential packages, or \b
 +    *  NULL if an error occurs.
 +    *
 +    *  \todo Is this the best place for this function?  Perhaps the
 +    *  settings for mark-and-sweep should be stored in a single
 +    *  external class?
 +    */
 +   virtual InRootSetFunc *GetRootSetFunc();
 +
 +   /** \return \b true if the garbage collector should follow recommendations.
 +    */
 +   virtual bool MarkFollowsRecommends();
 +
 +   /** \return \b true if the garbage collector should follow suggestions.
 +    */
 +   virtual bool MarkFollowsSuggests();
 +
 +   /** \brief Update the Marked and Garbage fields of all packages.
 +    *
 +    *  This routine is implicitly invoked after all state manipulators
 +    *  and when an ActionGroup is destroyed.  It invokes #MarkRequired
 +    *  and #Sweep to do its dirty work.
 +    *
 +    *  \param rootFunc A predicate that returns \b true for packages
 +    *  that should be added to the root set.
 +    */
 +   bool MarkAndSweep(InRootSetFunc &rootFunc)
 +   {
 +     return MarkRequired(rootFunc) && Sweep();
 +   }
 +
 +   bool MarkAndSweep()
 +   {
 +     std::auto_ptr<InRootSetFunc> f(GetRootSetFunc());
 +     if(f.get() != NULL)
 +       return MarkAndSweep(*f.get());
 +     else
 +       return false;
 +   }
 +
 +   /** \name State Manipulators
 +    */
 +   // @{
 +   void MarkKeep(PkgIterator const &Pkg, bool Soft = false,
 +               bool FromUser = true);
     void MarkDelete(PkgIterator const &Pkg,bool Purge = false);
     void MarkInstall(PkgIterator const &Pkg,bool AutoInst = true,
-                   unsigned long Depth = 0, bool FromUser = true);
 -                  unsigned long Depth = 0, bool ForceImportantDeps = false);
++                  unsigned long Depth = 0, bool FromUser = true,
++                  bool ForceImportantDeps = false);
     void SetReInstall(PkgIterator const &Pkg,bool To);
     void SetCandidateVersion(VerIterator TargetVer);
 +
 +   /** Set the "is automatically installed" flag of Pkg. */
 +   void MarkAuto(const PkgIterator &Pkg, bool Auto);
 +   // @}
     
     // This is for debuging
     void Update(OpProgress *Prog = 0);
 +
 +   // read persistent states
 +   bool readStateFile(OpProgress *prog);
 +   bool writeStateFile(OpProgress *prog);
     
     // Size queries
     inline double UsrSize() {return iUsrSize;};
     inline unsigned long KeepCount() {return iKeepCount;};
     inline unsigned long InstCount() {return iInstCount;};
     inline unsigned long BrokenCount() {return iBrokenCount;};
+    inline unsigned long PolicyBrokenCount() {return iPolicyBrokenCount;};
     inline unsigned long BadCount() {return iBadCount;};
  
     bool Init(OpProgress *Prog);
diff --combined apt-pkg/init.cc
index 6aa486a7f3d8b5650d6a6c4845681ef49cd8a1f6,a26f1d01cb8cb67e8fb66dafeb97f8cb34f8ef6c..579a19ab9ee1c5184a608685ba57d3db2671df27
@@@ -40,6 -40,8 +40,8 @@@ bool pkgInitConfig(Configuration &Cnf
     else
        Cnf.Set("APT::Architecture",COMMON_OS "-" COMMON_CPU);
     Cnf.Set("APT::Build-Essential::", "build-essential");
+    Cnf.Set("APT::Install-Recommends", false);
+    Cnf.Set("APT::Install-Suggests", false);
     Cnf.Set("Dir","/");
     
     // State   
        bindtextdomain(textdomain(0),Cnf.FindDir("Dir::Locale").c_str());
     }
  #endif
 +
 +   // Translation
 +   Cnf.Set("APT::Acquire::Translation", "environment");
     
     return true;
  }
diff --combined apt-pkg/init.h
index 51a7ba2ebb3b7207fed5a754fcc89720df092066,8255b406a6bd65d694ef7cdd68d2adda2ad6b54b..c6457cbcaf3d6902913d2734d9049032e87c1898
@@@ -17,8 -17,8 +17,8 @@@
  #include <apt-pkg/pkgsystem.h>
  
  // See the makefile
 -#define APT_PKG_MAJOR 3
 -#define APT_PKG_MINOR 11
 +#define APT_PKG_MAJOR 4
- #define APT_PKG_MINOR 1
++#define APT_PKG_MINOR 2
  #define APT_PKG_RELEASE 0
      
  extern const char *pkgVersion;
diff --combined apt-pkg/makefile
index 29c8ee135ceeb45e24a1cc82c542c2cae543e928,7e5feae53b4b11082c1d3973bab0772c5ce7085d..59df6c0ef20f69c6845476eb10acb523171599e6
@@@ -13,7 -13,7 +13,7 @@@ include ../buildlib/defaults.ma
  # methods/makefile - FIXME
  LIBRARY=apt-pkg
  LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
- MAJOR=4.1
 -MAJOR=3.11
++MAJOR=4.2
  MINOR=0
  SLIBS=$(PTHREADLIB) $(INTLLIBS)
  APT_DOMAIN:=libapt-pkg$(MAJOR)
diff --combined cmdline/apt-get.cc
index 8b3c6857366d5e929a9020affa5de056057cda7c,58976351cb73e236b31e231fa2065bef7eaf39fe..4dfb3325c07009141bec0989bf6782946874a730
@@@ -60,7 -60,6 +60,7 @@@
  #include <errno.h>
  #include <regex.h>
  #include <sys/wait.h>
 +#include <sstream>
                                                                        /*}}}*/
  
  using namespace std;
@@@ -629,6 -628,8 +629,8 @@@ void CacheFile::Sort(
     and verifies that the system is OK. */
  bool CacheFile::CheckDeps(bool AllowBroken)
  {
+    bool FixBroken = _config->FindB("APT::Get::Fix-Broken",false);
     if (_error->PendingError() == true)
        return false;
  
     if (pkgApplyStatus(*DCache) == false)
        return false;
     
 -             DCache->MarkInstall(I,true,0,true);
+    if (_config->FindB("APT::Get::Fix-Policy-Broken",false) == true)
+    {
+       FixBroken = true;
+       if ((DCache->PolicyBrokenCount() > 0))
+       {
+        // upgrade all policy-broken packages with ForceImportantDeps=True
+        for (pkgCache::PkgIterator I = Cache->PkgBegin(); !I.end(); I++)
+           if ((*DCache)[I].NowPolicyBroken() == true) 
++             DCache->MarkInstall(I,true,0, false, true);
+       }
+    }
     // Nothing is broken
     if (DCache->BrokenCount() == 0 || AllowBroken == true)
        return true;
  
     // Attempt to fix broken things
-    if (_config->FindB("APT::Get::Fix-Broken",false) == true)
+    if (FixBroken == true)
     {
        c1out << _("Correcting dependencies...") << flush;
        if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0)
@@@ -996,7 -1009,7 +1010,7 @@@ bool InstallPackages(CacheFile &Cache,b
         cerr << _("Unable to correct missing packages.") << endl;
         return _error->Error(_("Aborting install."));
        }
 -               
 +
        _system->UnLock();
        int status_fd = _config->FindI("APT::Status-Fd",-1);
        pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd);
@@@ -1146,9 -1159,11 +1160,11 @@@ bool TryToInstall(pkgCache::PkgIterato
     else
        ExpectedInst++;
     
-    // Install it with autoinstalling enabled.
-    if (State.InstBroken() == true && BrokenFix == false)
+    // Install it with autoinstalling enabled (if we not respect the minial
+    // required deps or the policy)
+    if ((State.InstBroken() == true || State.InstPolicyBroken() == true) && BrokenFix == false)
        Cache.MarkInstall(Pkg,true);
     return true;
  }
                                                                        /*}}}*/
@@@ -1387,52 -1402,6 +1403,52 @@@ bool DoUpdate(CommandLine &CmdL
     return true;
  }
                                                                        /*}}}*/
 +// DoAutomaticRemove - Remove all automatic unused packages           /*{{{*/
 +// ---------------------------------------------------------------------
 +/* Remove unused automatic packages */
 +bool DoAutomaticRemove(CacheFile &Cache)
 +{
 +   if(_config->FindI("Debug::pkgAutoRemove",false))
 +      std::cout << "DoAutomaticRemove()" << std::endl;
 +
 +   if (_config->FindB("APT::Get::Remove",true) == false)
 +      return _error->Error(_("We are not supposed to delete stuff, can't "
 +                           "start AutoRemover"));
 +
 +   {
 +     pkgDepCache::ActionGroup group(*Cache);
 +
 +     // look over the cache to see what can be removed
 +     for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg)
 +       {
 +       if (Cache[Pkg].Garbage)
 +         {
 +           if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
 +             fprintf(stdout,"We could delete %s\n", Pkg.Name());
 +
 +           if(Pkg.CurrentVer() != 0 && Pkg->CurrentState != pkgCache::State::ConfigFiles)
 +             Cache->MarkDelete(Pkg, _config->FindB("APT::Get::Purge", false));
 +           else
 +             Cache->MarkKeep(Pkg, false, false);
 +         }
 +       }
 +   }
 +
 +   // Now see if we destroyed anything
 +   if (Cache->BrokenCount() != 0)
 +   {
 +      c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
 +               "shouldn't happen. Please file a bug report against apt.") << endl;
 +      c1out << endl;
 +      c1out << _("The following information may help to resolve the situation:") << endl;
 +      c1out << endl;
 +      ShowBroken(c1out,Cache,false);
 +
 +      return _error->Error(_("Internal Error, AutoRemover broke stuff"));
 +   }
 +   return true;
 +}
 +
  // DoUpgrade - Upgrade all packages                                   /*{{{*/
  // ---------------------------------------------------------------------
  /* Upgrade all packages without installing new packages or erasing old
@@@ -1475,11 -1444,6 +1491,11 @@@ bool DoInstall(CommandLine &CmdL
     bool DefRemove = false;
     if (strcasecmp(CmdL.FileList[0],"remove") == 0)
        DefRemove = true;
 +   else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
 +     {
 +       _config->Set("APT::Get::AutomaticRemove", "true");
 +       DefRemove = true;
 +     }
  
     for (const char **I = CmdL.FileList + 1; *I != 0; I++)
     {
        return _error->Error(_("Broken packages"));
     }   
     
 +   if (_config->FindB("APT::Get::AutomaticRemove")) {
 +      if (!DoAutomaticRemove(Cache)) 
 +       return false;
 +   }
 +
     /* Print out a list of packages that are going to be installed extra
        to what the user asked */
     if (Cache->InstCount() != ExpectedInst)
         
         if (*J == 0) {
            List += string(I.Name()) + " ";
 -        VersionsList += string(Cache[I].CandVersion) + "\n";
 -     }
 +          VersionsList += string(Cache[I].CandVersion) + "\n";
 +       }
        }
        
        ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
        string SuggestsVersions, RecommendsVersions;
        for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
        {
-        pkgCache::PkgIterator I(Cache,Cache.List[J]);
+        pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
  
         /* Just look at the ones we want to install */
-        if ((*Cache)[I].Install() == false)
+        if ((*Cache)[Pkg].Install() == false)
           continue;
  
-        for (pkgCache::VerIterator V = I.VersionList(); V.end() == false; V++)
-          {
-            for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; )
-              {
-                pkgCache::DepIterator Start;
-                pkgCache::DepIterator End;
-                D.GlobOr(Start,End); // advances D
-                /* 
-                 * If this is a virtual package, we need to check the list of
-                 * packages that provide it and see if any of those are
-                 * installed
-                 */
-                
-                bool providedBySomething = false;
-                for (pkgCache::PrvIterator Prv = Start.TargetPkg().ProvidesList();
-                       Prv.end() != true;
-                       Prv++)
-                   if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
-                     {
-                      providedBySomething = true;
-                      break;
-                   }
-                if (providedBySomething) continue;
-             
-                  for(;;)
-                  {
-                      /* Skip if package is  installed already, or is about to be */
-                      string target = string(Start.TargetPkg().Name()) + " ";
-                      if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install
-                          || Cache[Start.TargetPkg()].Install())
-                        break;
-                      /* Skip if we already saw it */
-                      if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
-                        break; 
-                    if (Start->Type == pkgCache::Dep::Suggests) {
-                      SuggestsList += target;
-                      SuggestsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
-                    }
-                    
-                    if (Start->Type == pkgCache::Dep::Recommends) {
-                      RecommendsList += target;
-                      RecommendsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
-                    }
-                      if (Start >= End)
-                         break;
-                      Start++;
-                  }
-              }
-          }
+        // get the recommends/suggests for the candidate ver
+        pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
+        for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
+        {
+           pkgCache::DepIterator Start;
+           pkgCache::DepIterator End;
+           D.GlobOr(Start,End); // advances D
+           // FIXME: we really should display a or-group as a or-group to the user
+           //        the problem is that ShowList is incapable of doing this
+           string RecommendsOrList,RecommendsOrVersions;
+           string SuggestsOrList,SuggestsOrVersions;
+           bool foundInstalledInOrGroup = false;
+           for(;;)
+           {
+              /* Skip if package is  installed already, or is about to be */
+              string target = string(Start.TargetPkg().Name()) + " ";
+              
+              if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install
+                  || Cache[Start.TargetPkg()].Install())
+              {
+                 foundInstalledInOrGroup=true;
+                 break;
+              }
+              /* Skip if we already saw it */
+              if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
+              {
+                 foundInstalledInOrGroup=true;
+                 break; 
+              }
+              // this is a dep on a virtual pkg, check if any package that provides it
+              // should be installed
+              if(Start.TargetPkg().ProvidesList() != 0)
+              {
+                 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
+                 for (; I.end() == false; I++)
+                 {
+                    pkgCache::PkgIterator Pkg = I.OwnerPkg();
+                    if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() && 
+                        Pkg.CurrentVer() != 0)
+                       foundInstalledInOrGroup=true;
+                 }
+              }
+              if (Start->Type == pkgCache::Dep::Suggests) 
+              {
+                 SuggestsOrList += target;
+                 SuggestsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
+              }
+              
+              if (Start->Type == pkgCache::Dep::Recommends) 
+              {
+                 RecommendsOrList += target;
+                 RecommendsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
+              }
+              if (Start >= End)
+                 break;
+              Start++;
+           }
+           
+           if(foundInstalledInOrGroup == false)
+           {
+              RecommendsList += RecommendsOrList;
+              RecommendsVersions += RecommendsOrVersions;
+              SuggestsList += SuggestsOrList;
+              SuggestsVersions += SuggestsOrVersions;
+           }
+              
+        }
        }
        ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
        ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
  
@@@ -1771,8 -1748,6 +1805,8 @@@ bool DoDSelectUpgrade(CommandLine &CmdL
     if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
        return false;
     
 +   pkgDepCache::ActionGroup group(Cache);
 +
     // Install everything with the install flag set
     pkgCache::PkgIterator I = Cache->PkgBegin();
     for (;I.end() != true; I++)
@@@ -2525,7 -2500,6 +2559,7 @@@ void GetInitialize(
     _config->Set("APT::Get::Fix-Broken",false);
     _config->Set("APT::Get::Force-Yes",false);
     _config->Set("APT::Get::List-Cleanup",true);
 +   _config->Set("APT::Get::AutomaticRemove",false);
  }
                                                                        /*}}}*/
  // SigWinch - Window size change signal handler                               /*{{{*/
@@@ -2581,8 -2555,9 +2615,10 @@@ int main(int argc,const char *argv[]
        {0,"remove","APT::Get::Remove",0},
        {0,"only-source","APT::Get::Only-Source",0},
        {0,"arch-only","APT::Get::Arch-Only",0},
 +      {0,"auto-remove","APT::Get::AutomaticRemove",0},
        {0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0},
+       {0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean},
+       {0,"fix-policy","APT::Get::Fix-Policy-Broken",0},
        {'c',"config-file",0,CommandLine::ConfigFile},
        {'o',"option",0,CommandLine::ArbItem},
        {0,0,0,0}};
                                     {"upgrade",&DoUpgrade},
                                     {"install",&DoInstall},
                                     {"remove",&DoInstall},
 +                                 {"autoremove",&DoInstall},
                                     {"dist-upgrade",&DoDistUpgrade},
                                     {"dselect-upgrade",&DoDSelectUpgrade},
                                   {"build-dep",&DoBuildDep},
diff --combined configure.in
index e8e89e028a8996c2ef1ba996d637bb43bc28b211,f0b0d6703af0f057455389e7258eefc6230852fd..830fef82a783e76ae61ee247db4224886843a7be
@@@ -18,7 -18,7 +18,7 @@@ AC_CONFIG_AUX_DIR(buildlib
  AC_CONFIG_HEADER(include/config.h:buildlib/config.h.in include/apti18n.h:buildlib/apti18n.h.in)
  
  dnl -- SET THIS TO THE RELEASE VERSION --
- AC_DEFINE_UNQUOTED(VERSION,"0.6.45exp1")
 -AC_DEFINE_UNQUOTED(VERSION,"0.6.45.1")
++AC_DEFINE_UNQUOTED(VERSION,"0.6.45exp2")
  PACKAGE="apt"
  AC_DEFINE_UNQUOTED(PACKAGE,"$PACKAGE")
  AC_SUBST(PACKAGE)
@@@ -175,21 -175,12 +175,21 @@@ dnl Check for debiando
  AC_PATH_PROG(DEBIANDOC_HTML,debiandoc2html)
  AC_PATH_PROG(DEBIANDOC_TEXT,debiandoc2text)
  
 +dnl Check for doxygen
 +AC_PATH_PROG(DOXYGEN, doxygen)
 +
  dnl Check for the SGML tools needed to build man pages
  AC_PATH_PROG(DOCBOOK2MAN,docbook2man)
  
  dnl Check for the XML tools needed to build man pages
  AC_PATH_PROG(XMLTO,xmlto)
  
 +dnl Check for graphviz
 +AC_CHECK_PROG([HAVE_DOT], [dot], [YES], [NO])
 +AC_PATH_PROG([DOT], [dot], [])
 +DOTDIR=$(dirname $DOT)
 +AC_SUBST(DOTDIR)
 +
  dnl Check for YODL
  dnl AC_CHECK_PROG(YODL_MAN,yodl2man,"yes","")
  
@@@ -209,4 -200,4 +209,4 @@@ f
  AC_SUBST(USE_NLS)
  AC_PATH_PROG(BASH, bash)
  
 -AC_OUTPUT(environment.mak:buildlib/environment.mak.in makefile:buildlib/makefile.in,make -s dirs)
 +AC_OUTPUT(environment.mak:buildlib/environment.mak.in makefile:buildlib/makefile.in doc/Doxyfile,make -s dirs)
diff --combined debian/changelog
index 25b015ddffdaea04411e3092a3c68048149a7c44,65ec82cc1c37b25586ce04acbce9bf02c2128207..fb07ca68289a73e7e3c4228af593be61945ba741
@@@ -1,9 -1,28 +1,15 @@@
 -apt (0.6.45.2) unstable; urgency=low
++apt (0.6.45exp2) experimental; urgency=low
 -  * added "--install-recommends" to handle recommends as 
 -    dependencies (closes: #42266)
++  * merged "install-recommends" branch (ABI break)
 - --
++ -- Michael Vogt <mvo@debian.org>  Mon, 14 Aug 2006 17:47:25 +0200
 -apt (0.6.45.1) unstable; urgency=low
 -
 -  * debian/control:
 -    - switched to libdb4.4 for building (closes: #381019)
 -  * cmdline/apt-get.cc:
 -    - show only the recommends/suggests for the candidate-version, not for all
 -      versions of the package (closes: #257054)
 -    - properly handle recommends/suggests or-groups when printing the list of
 -      suggested/recommends packages (closes: #311619)
 -
 - -- Michael Vogt <michael.vogt@ubuntu.com>  Wed,  9 Aug 2006 14:27:54 +0200
 -
 -apt (0.6.45) unstable; urgency=low
 +apt (0.6.45exp1) experimental; urgency=low
  
    * apt-pkg/contrib/sha256.cc:
      - fixed the sha256 generation (closes: #378183)
    * ftparchive/cachedb.cc:
 -    - applied patch from Anthony Towns to fix Clean() function
 +    - applied patch from ajt to fix Clean() function
        (closes: #379576)
    * doc/apt-get.8.xml:
      - fix path to the apt user build (Closes: #375640)
@@@ -21,6 -40,9 +27,6 @@@
      - fix for string mangling, closes: #373864
    * apt-pkg/acquire-item.cc:
      - check for bzip2 in /bin (closes: #377391)
 -  * apt-pkg/tagfile.cc:
 -    - make it work on non-mapable files again, thanks 
 -      to James Troup for confirming the fix (closes: #376777)
    * Merged from Christian Perrier bzr branch:
      * ko.po: Updated to 512t. Closes: #378901
      * hu.po: Updated to 512t. Closes: #376330
      * dz.po: New Dzongkha translation: 512t
      * ro.po: Updated to 512t
      * eu.po: Updated
 +    * 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
  
 - -- Michael Vogt <mvo@debian.org>  Thu, 27 Jul 2006 00:52:05 +0200
 + -- Michael Vogt <michael.vogt@ubuntu.com>  Tue, 25 Jul 2006 11:55:22 +0200
  
 -apt  (0.6.44.2) unstable; urgency=low 
 -  
 -   * 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
 -
 - -- Michael Vogt <mvo@debian.org>  Wed, 14 Jun 2006 12:00:57 +0200 
 +apt (0.6.44.2exp1) experimental; urgency=low
 +
 +  * 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
 +
 + -- Michael Vogt <mvo@debian.org>  Mon,  3 Jul 2006 21:50:31 +0200
 +
 +apt (0.6.44.2) unstable; urgency=low
 +
 +  * 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
 +
 + -- Michael Vogt <mvo@debian.org>  Wed, 14 Jun 2006 12:00:57 +0200
  
  apt (0.6.44.1-0.1) unstable; urgency=low
  
  
  apt (0.6.44.1) unstable; urgency=low
  
 +  * apt-pkg/acquire-item.cc:
 +    - fix reversed logic of the "Acquire::PDiffs" option
    * merged from 
      http://www.perrier.eu.org/debian/packages/d-i/level4/apt-main:
      - po/LINGUAS: added "bg" Closes: #360262
      - po/gl.po: Galician translation update. Closes: #366849
      - po/hu.po: Hungarian translation update. Closes: #365448
      - po/cs.po: Czech translation updated. Closes: #367244
 +  * apt-pkg/contrib/sha256.cc:
 +    - applied patch to fix unaligned access problem. Closes: #367417
 +      (thanks to David Mosberger)
  
   -- Michael Vogt <mvo@debian.org>  Tue, 16 May 2006 21:51:16 +0200
  
  apt (0.6.44) unstable; urgency=low
  
    * apt-pkg/acquire.cc: don't show ETA if it is 0 or absurdely large
 +  * apt-pkg/contrib/sha256.{cc,h},hashes.{cc,h}: support for sha256 
 +    (thanks to Anthony Towns)
 +  * ftparchive/cachedb.{cc,h},writer.{cc,h}: optimizations 
 +    (thanks to Anthony Towns)
 +  * apt pdiff support from experimental merged
 +  * apt-pkg/deb/dpkgpm.cc: wording fixes (thanks to Matt Zimmerman)
    * apt-pkg/deb/dpkgpm.cc: 
      - wording fixes (thanks to Matt Zimmerman)
 -    - fix error in dpkg interaction (closes: #364513, 
 -      thanks to Martin Dickopp)
 +    - fix error in dpkg interaction (closes: #364513, thanks to Martin Dickopp)
    * apt-pkg/tagfile.{cc,h}:
      - use MMap to read the entries (thanks to Zephaniah E. Hull for the
        patch) Closes: #350025
@@@ -298,7 -294,7 +304,7 @@@ apt (0.6.42) unstable; urgency=lo
    * cmdline/apt-cdrom.cc: 
      - fix some missing gettext() calls (closes: #334539)
    * doc/apt-cache.8.xml: fix typo (closes: #334714)
 -  
 +
   -- Michael Vogt <mvo@debian.org>  Wed, 19 Oct 2005 22:02:09 +0200
  
  apt (0.6.41) unstable; urgency=low
@@@ -398,7 -394,6 +404,7 @@@ apt (0.6.37) breezy; urgency=lo
    * Add Welsh translation from Dafydd Harries
      (daf@muse.19inch.net--2005/apt--main--0--patch-1)
    * Change debian/bugscript to use #!/bin/bash (Closes: #313402)
 +  * Fix a incorrect example in the man-page (closes: #282918)
  
   -- Matt Zimmerman <mdz@ubuntu.com>  Tue, 24 May 2005 14:38:25 -0700
  
index d57874dd1c245063e16d8126ce3de5146b32a40d,c4329dfa0a4cc1a8a0f4bd2aee4493d3494bb200..b4d42e123acb1baab0a9a159ddd7ae201d1f1444
@@@ -24,15 -24,11 +24,15 @@@ AP
  {
    Architecture "i386";
    Build-Essential "build-essential";
 -  
 +
 +  NeverAutoRemove  { "linux-kernel.*";  };  // packages that should never
 +                                            // considered for autoRemove
 +
    // Options for apt-get
    Get 
    {
       Arch-Only "false";
 +     AutomaticRemove "false";       
       Download-Only "false";
       Simulate "false";
       Assume-Yes "false";
    Cache-Limit "4194304";
    Default-Release "";
  
+   // consider Recommends, Suggests as important dependencies that should
+   // be installed by default
+   APT::Install-Recommends "false";
+   APT::Install-Suggests "false";
  
    // Write progress messages on this fd (for stuff like base-config)
    Status-Fd "-1";
@@@ -108,8 -108,6 +112,8 @@@ Acquir
    Queue-Mode "host";       // host|access
    Retries "0";
    Source-Symlinks "true";
 +
 +  PDiffs "true";     // try to get the IndexFile diffs
    
    // HTTP method configuration
    http 
@@@ -257,8 -255,7 +261,8 @@@ Debu
    pkgDPkgPM "false";
    pkgDPkgProgressReporting "false";
    pkgOrderList "false";
 -  
 +  pkgAutoRemove "false";   // show information about automatic removes
 +
    pkgInitialize "false";   // This one will dump the configuration space
    NoLocking "false";
    Acquire::Ftp "false";    // Show ftp command traffic
diff --combined methods/makefile
index 10fce8bfca66c4d6b6b23614ed289be4ab69eb97,1e3b1ef850b128f8fd97ec77c7442cced44a0e34..5bd05eae106f5e62c15c70e15a45eec117445b7a
@@@ -7,7 -7,7 +7,7 @@@ include ../buildlib/defaults.ma
  BIN := $(BIN)/methods
  
  # FIXME..
- LIB_APT_PKG_MAJOR = 4.1
 -LIB_APT_PKG_MAJOR = 3.11
++LIB_APT_PKG_MAJOR = 4.2
  APT_DOMAIN := libapt-pkg$(LIB_APT_PKG_MAJOR)
  
  # The file method
@@@ -59,13 -59,6 +59,13 @@@ LIB_MAKES = apt-pkg/makefil
  SOURCE = ftp.cc rfc2553emu.cc connect.cc
  include $(PROGRAM_H)
  
 +# The rred method
 +PROGRAM=rred
 +SLIBS = -lapt-pkg $(SOCKETLIBS)
 +LIB_MAKES = apt-pkg/makefile
 +SOURCE = rred.cc
 +include $(PROGRAM_H)
 +
  # The rsh method
  PROGRAM=rsh
  SLIBS = -lapt-pkg