]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-get.cc
* apt-pkg/contrib/strutl.cc:
[apt.git] / cmdline / apt-get.cc
index 92a263e502c26914976d46c6975c7ffad0676394..8efcd0e2e7aa7f5affa9881c2bedb007465e2b73 100644 (file)
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+
+#include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/cmndline.h>
 #include <apt-pkg/init.h>
 #include <apt-pkg/srcrecords.h>
 #include <apt-pkg/version.h>
 #include <apt-pkg/cachefile.h>
+#include <apt-pkg/cacheset.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/versionmatch.h>
-    
+
 #include <config.h>
 #include <apti18n.h>
 
@@ -62,6 +67,9 @@
 #include <regex.h>
 #include <sys/wait.h>
 #include <sstream>
+
+#define statfs statfs64
+#define statvfs statvfs64
                                                                        /*}}}*/
 
 #define RAMFS_MAGIC     0x858458f6
@@ -90,14 +98,14 @@ class CacheFile : public pkgCacheFile
    bool BuildCaches(bool WithLock = true)
    {
       OpTextProgress Prog(*_config);
-      if (pkgCacheFile::BuildCaches(Prog,WithLock) == false)
+      if (pkgCacheFile::BuildCaches(&Prog,WithLock) == false)
         return false;
       return true;
    }
    bool Open(bool WithLock = true) 
    {
       OpTextProgress Prog(*_config);
-      if (pkgCacheFile::Open(Prog,WithLock) == false)
+      if (pkgCacheFile::Open(&Prog,WithLock) == false)
         return false;
       Sort();
       
@@ -111,6 +119,9 @@ class CacheFile : public pkgCacheFile
         return Open(true);
    }
    CacheFile() : List(0) {};
+   ~CacheFile() {
+      delete[] List;
+   }
 };
                                                                        /*}}}*/
 
@@ -255,8 +266,8 @@ void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
       }
       
       // Print out each package and the failed dependencies
-      out <<"  " <<  I.Name() << ":";
-      unsigned Indent = strlen(I.Name()) + 3;
+      out << " " << I.FullName(true) << " :";
+      unsigned const Indent = I.FullName(true).size() + 3;
       bool First = true;
       pkgCache::VerIterator Ver;
       
@@ -309,7 +320,7 @@ void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
               out << ' ' << End.DepType() << ": ";
            FirstOr = false;
            
-           out << Start.TargetPkg().Name();
+           out << Start.TargetPkg().FullName(true);
         
            // Show a quick summary of the version requirements
            if (Start.TargetVer() != 0)
@@ -371,7 +382,9 @@ void ShowNew(ostream &out,CacheFile &Cache)
    {
       pkgCache::PkgIterator I(Cache,Cache.List[J]);
       if (Cache[I].NewInstall() == true) {
-         List += string(I.Name()) + " ";
+        if (Cache[I].CandidateVerIter(Cache).Pseudo() == true)
+           continue;
+         List += I.FullName(true) + " ";
          VersionsList += string(Cache[I].CandVersion) + "\n";
       }
    }
@@ -393,10 +406,12 @@ void ShowDel(ostream &out,CacheFile &Cache)
       pkgCache::PkgIterator I(Cache,Cache.List[J]);
       if (Cache[I].Delete() == true)
       {
+        if (Cache[I].CandidateVerIter(Cache).Pseudo() == true)
+           continue;
         if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
-           List += string(I.Name()) + "* ";
+           List += I.FullName(true) + "* ";
         else
-           List += string(I.Name()) + " ";
+           List += I.FullName(true) + " ";
      
      VersionsList += string(Cache[I].CandVersion)+ "\n";
       }
@@ -421,7 +436,7 @@ void ShowKept(ostream &out,CacheFile &Cache)
          I->CurrentVer == 0 || Cache[I].Delete() == true)
         continue;
       
-      List += string(I.Name()) + " ";
+      List += I.FullName(true) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
    ShowList(out,_("The following packages have been kept back:"),List,VersionsList);
@@ -441,8 +456,10 @@ void ShowUpgraded(ostream &out,CacheFile &Cache)
       // Not interesting
       if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
         continue;
-      
-      List += string(I.Name()) + " ";
+      if (Cache[I].CandidateVerIter(Cache).Pseudo() == true)
+        continue;
+
+      List += I.FullName(true) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
    ShowList(out,_("The following packages will be upgraded:"),List,VersionsList);
@@ -462,8 +479,10 @@ bool ShowDowngraded(ostream &out,CacheFile &Cache)
       // Not interesting
       if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true)
         continue;
-      
-      List += string(I.Name()) + " ";
+      if (Cache[I].CandidateVerIter(Cache).Pseudo() == true)
+        continue;
+
+      List += I.FullName(true) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
    return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList);
@@ -481,7 +500,7 @@ bool ShowHold(ostream &out,CacheFile &Cache)
       pkgCache::PkgIterator I(Cache,Cache.List[J]);
       if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
           I->SelectedState == pkgCache::State::Hold) {
-         List += string(I.Name()) + " ";
+         List += I.FullName(true) + " ";
                 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
       }
    }
@@ -515,7 +534,7 @@ bool ShowEssential(ostream &out,CacheFile &Cache)
         if (Added[I->ID] == false)
         {
            Added[I->ID] = true;
-           List += string(I.Name()) + " ";
+           List += I.FullName(true) + " ";
         //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
         }
       }
@@ -539,7 +558,7 @@ bool ShowEssential(ostream &out,CacheFile &Cache)
            Added[P->ID] = true;
            
            char S[300];
-           snprintf(S,sizeof(S),_("%s (due to %s) "),P.Name(),I.Name());
+           snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str());
            List += S;
         //VersionsList += "\n"; ???
         }       
@@ -563,6 +582,9 @@ void Stats(ostream &out,pkgDepCache &Dep)
    unsigned long ReInstall = 0;
    for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
    {
+      if (pkgCache::VerIterator(Dep, Dep[I].CandidateVer).Pseudo() == true)
+        continue;
+
       if (Dep[I].NewInstall() == true)
         Install++;
       else
@@ -594,7 +616,256 @@ void Stats(ostream &out,pkgDepCache &Dep)
               Dep.BadCount());
 }
                                                                        /*}}}*/
+// CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/
+class CacheSetHelperAPTGet : public APT::CacheSetHelper {
+       /** \brief stream message should be printed to */
+       std::ostream &out;
+       /** \brief were things like Task or RegEx used to select packages? */
+       bool explicitlyNamed;
+
+       APT::PackageSet virtualPkgs;
+
+public:
+       CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) {
+               explicitlyNamed = true;
+       }
+
+       virtual void showTaskSelection(APT::PackageSet const &pkgset, string const &pattern) {
+               for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+                       ioprintf(out, _("Note, selecting '%s' for task '%s'\n"),
+                                Pkg.FullName(true).c_str(), pattern.c_str());
+               explicitlyNamed = false;
+       }
+       virtual void showRegExSelection(APT::PackageSet const &pkgset, string const &pattern) {
+               for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+                       ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"),
+                                Pkg.FullName(true).c_str(), pattern.c_str());
+               explicitlyNamed = false;
+       }
+       virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
+                                string const &ver, bool const &verIsRel) {
+               if (ver != Ver.VerStr())
+                       ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
+                                Ver.VerStr(), Ver.RelStr().c_str(), Pkg.FullName(true).c_str());
+       }
+
+       bool showVirtualPackageErrors(pkgCacheFile &Cache) {
+               if (virtualPkgs.empty() == true)
+                       return true;
+               for (APT::PackageSet::const_iterator Pkg = virtualPkgs.begin();
+                    Pkg != virtualPkgs.end(); ++Pkg) {
+                       if (Pkg->ProvidesList != 0) {
+                               ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
+                                        Pkg.FullName(true).c_str());
+
+                               pkgCache::PrvIterator I = Pkg.ProvidesList();
+                               unsigned short provider = 0;
+                               for (; I.end() == false; ++I) {
+                                       pkgCache::PkgIterator Pkg = I.OwnerPkg();
+
+                                       if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer()) {
+                                               out << "  " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr();
+                                               if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
+                                                       out << _(" [Installed]");
+                                               out << endl;
+                                               ++provider;
+                                       }
+                               }
+                               // if we found no candidate which provide this package, show non-candidates
+                               if (provider == 0)
+                                       for (I = Pkg.ProvidesList(); I.end() == false; I++)
+                                               out << "  " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr()
+                                                   << _(" [Not candidate version]") << endl;
+                               else
+                                       out << _("You should explicitly select one to install.") << endl;
+                       } else {
+                               ioprintf(out,
+                                       _("Package %s is not available, but is referred to by another package.\n"
+                                         "This may mean that the package is missing, has been obsoleted, or\n"
+                                         "is only available from another source\n"),Pkg.FullName(true).c_str());
+
+                               string List;
+                               string VersionsList;
+                               SPtrArray<bool> Seen = new bool[Cache.GetPkgCache()->Head().PackageCount];
+                               memset(Seen,0,Cache.GetPkgCache()->Head().PackageCount*sizeof(*Seen));
+                               for (pkgCache::DepIterator Dep = Pkg.RevDependsList();
+                                    Dep.end() == false; Dep++) {
+                                       if (Dep->Type != pkgCache::Dep::Replaces)
+                                               continue;
+                                       if (Seen[Dep.ParentPkg()->ID] == true)
+                                               continue;
+                                       Seen[Dep.ParentPkg()->ID] = true;
+                                       List += Dep.ParentPkg().FullName(true) + " ";
+                                       //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
+                               }
+                               ShowList(out,_("However the following packages replace it:"),List,VersionsList);
+                       }
+                       out << std::endl;
+               }
+               return false;
+       }
+
+       virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+               APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDIDATE);
+               if (verset.empty() == false)
+                       return *(verset.begin());
+               if (ShowError == true) {
+                       _error->Error(_("Package '%s' has no installation candidate"),Pkg.FullName(true).c_str());
+                       virtualPkgs.insert(Pkg);
+               }
+               return pkgCache::VerIterator(Cache, 0);
+       }
+
+       virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+               APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST);
+               if (verset.empty() == false)
+                       return *(verset.begin());
+               if (ShowError == true)
+                       ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str());
+               return pkgCache::VerIterator(Cache, 0);
+       }
+
+       APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg,
+                                               APT::VersionSet::Version const &select) {
+               /* This is a pure virtual package and there is a single available
+                  candidate providing it. */
+               if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0)
+                       return APT::VersionSet();
+
+               pkgCache::PkgIterator Prov;
+               bool found_one = false;
+               for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; ++P) {
+                       pkgCache::VerIterator const PVer = P.OwnerVer();
+                       pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
+
+                       /* Ignore versions that are not a candidate. */
+                       if (Cache[PPkg].CandidateVer != PVer)
+                               continue;
+
+                       if (found_one == false) {
+                               Prov = PPkg;
+                               found_one = true;
+                       } else if (PPkg != Prov) {
+                               found_one = false; // we found at least two
+                               break;
+                       }
+               }
+
+               if (found_one == true) {
+                       ioprintf(out, _("Note, selecting '%s' instead of '%s'\n"),
+                                Prov.FullName(true).c_str(), Pkg.FullName(true).c_str());
+                       return APT::VersionSet::FromPackage(Cache, Prov, select, *this);
+               }
+               return APT::VersionSet();
+       }
+
+       inline bool allPkgNamedExplicitly() const { return explicitlyNamed; }
+
+};
+                                                                       /*}}}*/
+// TryToInstall - Mark a package for installation                      /*{{{*/
+struct TryToInstall {
+   pkgCacheFile* Cache;
+   pkgProblemResolver* Fix;
+   bool FixBroken;
+   unsigned long AutoMarkChanged;
+   APT::PackageSet doAutoInstallLater;
+
+   TryToInstall(pkgCacheFile &Cache, pkgProblemResolver &PM, bool const &FixBroken) : Cache(&Cache), Fix(&PM),
+                       FixBroken(FixBroken), AutoMarkChanged(0) {};
+
+   void operator() (pkgCache::VerIterator const &Ver) {
+      pkgCache::PkgIterator Pkg = Ver.ParentPkg();
 
+      Cache->GetDepCache()->SetCandidateVersion(Ver);
+      pkgDepCache::StateCache &State = (*Cache)[Pkg];
+
+      // Handle the no-upgrade case
+      if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0)
+        ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
+                 Pkg.FullName(true).c_str());
+      // Ignore request for install if package would be new
+      else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0)
+        ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
+                 Pkg.FullName(true).c_str());
+      else {
+        Fix->Clear(Pkg);
+        Fix->Protect(Pkg);
+        Cache->GetDepCache()->MarkInstall(Pkg,false);
+
+        if (State.Install() == false) {
+           if (_config->FindB("APT::Get::ReInstall",false) == true) {
+              if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
+                 ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
+                          Pkg.FullName(true).c_str());
+              else
+                 Cache->GetDepCache()->SetReInstall(Pkg, true);
+           } else
+              ioprintf(c1out,_("%s is already the newest version.\n"),
+                       Pkg.FullName(true).c_str());
+        }
+
+        // Install it with autoinstalling enabled (if we not respect the minial
+        // required deps or the policy)
+        if (FixBroken == false)
+           doAutoInstallLater.insert(Pkg);
+      }
+
+      // see if we need to fix the auto-mark flag
+      // e.g. apt-get install foo
+      // where foo is marked automatic
+      if (State.Install() == false &&
+         (State.Flags & pkgCache::Flag::Auto) &&
+         _config->FindB("APT::Get::ReInstall",false) == false &&
+         _config->FindB("APT::Get::Only-Upgrade",false) == false &&
+         _config->FindB("APT::Get::Download-Only",false) == false)
+      {
+        ioprintf(c1out,_("%s set to manually installed.\n"),
+                 Pkg.FullName(true).c_str());
+        Cache->GetDepCache()->MarkAuto(Pkg,false);
+        AutoMarkChanged++;
+      }
+   }
+
+   void doAutoInstall() {
+      for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
+          P != doAutoInstallLater.end(); ++P) {
+        pkgDepCache::StateCache &State = (*Cache)[P];
+        if (State.InstBroken() == false && State.InstPolicyBroken() == false)
+           continue;
+        Cache->GetDepCache()->MarkInstall(P, true);
+      }
+      doAutoInstallLater.clear();
+   }
+};
+                                                                       /*}}}*/
+// TryToRemove - Mark a package for removal                            /*{{{*/
+struct TryToRemove {
+   pkgCacheFile* Cache;
+   pkgProblemResolver* Fix;
+   bool FixBroken;
+   bool PurgePkgs;
+   unsigned long AutoMarkChanged;
+
+   TryToRemove(pkgCacheFile &Cache, pkgProblemResolver &PM) : Cache(&Cache), Fix(&PM),
+                               PurgePkgs(_config->FindB("APT::Get::Purge", false)) {};
+
+   void operator() (pkgCache::VerIterator const &Ver)
+   {
+      pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+
+      Fix->Clear(Pkg);
+      Fix->Protect(Pkg);
+      Fix->Remove(Pkg);
+
+      if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
+         (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
+        ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str());
+      else
+        Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs);
+   }
+};
+                                                                       /*}}}*/
 // CacheFile::NameComp - QSort compare by name                         /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -679,7 +950,7 @@ bool CacheFile::CheckDeps(bool AllowBroken)
    }
    else
    {
-      c1out << _("You might want to run `apt-get -f install' to correct these.") << endl;
+      c1out << _("You might want to run 'apt-get -f install' to correct these.") << endl;
       ShowBroken(c1out,*this,true);
 
       return _error->Error(_("Unmet dependencies. Try using -f."));
@@ -687,7 +958,10 @@ bool CacheFile::CheckDeps(bool AllowBroken)
       
    return true;
 }
-
+                                                                       /*}}}*/
+// CheckAuth - check if each download comes form a trusted source      /*{{{*/
+// ---------------------------------------------------------------------
+/* */
 static bool CheckAuth(pkgAcquire& Fetcher)
 {
    string UntrustedList;
@@ -728,10 +1002,7 @@ static bool CheckAuth(pkgAcquire& Fetcher)
 
    return _error->Error(_("There are problems and -y was used without --force-yes"));
 }
-
-
                                                                        /*}}}*/
-
 // InstallPackages - Actually download and install the packages                /*{{{*/
 // ---------------------------------------------------------------------
 /* This displays the informative messages describing what is going to 
@@ -798,36 +1069,35 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    pkgRecords Recs(Cache);
    if (_error->PendingError() == true)
       return false;
-   
-   // Lock the archive directory
-   FileFd Lock;
-   if (_config->FindB("Debug::NoLocking",false) == false &&
-       _config->FindB("APT::Get::Print-URIs") == false)
-   {
-      Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
-      if (_error->PendingError() == true)
-        return _error->Error(_("Unable to lock the download directory"));
-   }
-   
+
    // Create the download object
+   pkgAcquire Fetcher;
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
-   pkgAcquire Fetcher(&Stat);
+   if (_config->FindB("APT::Get::Print-URIs", false) == true)
+   {
+      // force a hashsum for compatibility reasons
+      _config->CndSet("Acquire::ForceHash", "md5sum");
+      if (Fetcher.Setup(&Stat, "") == false)
+        return false;
+   }
+   else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false)
+      return false;
 
    // Read the source list
-   pkgSourceList List;
-   if (List.ReadMainList() == false)
-      return _error->Error(_("The list of sources could not be read."));
+   if (Cache.BuildSourceList() == false)
+      return false;
+   pkgSourceList *List = Cache.GetSourceList();
    
    // Create the package manager and prepare to download
    SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
-   if (PM->GetArchives(&Fetcher,&List,&Recs) == false || 
+   if (PM->GetArchives(&Fetcher,List,&Recs) == false || 
        _error->PendingError() == true)
       return false;
 
    // Display statistics
-   double FetchBytes = Fetcher.FetchNeeded();
-   double FetchPBytes = Fetcher.PartialPresent();
-   double DebBytes = Fetcher.TotalNeeded();
+   unsigned long long FetchBytes = Fetcher.FetchNeeded();
+   unsigned long long FetchPBytes = Fetcher.PartialPresent();
+   unsigned long long DebBytes = Fetcher.TotalNeeded();
    if (DebBytes != Cache->DebSize())
    {
       c0out << DebBytes << ',' << Cache->DebSize() << endl;
@@ -836,17 +1106,25 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    
    // Number of bytes
    if (DebBytes != FetchBytes)
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
               SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
    else if (DebBytes != 0)
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("Need to get %sB of archives.\n"),
               SizeToStr(DebBytes).c_str());
 
    // Size delta
    if (Cache->UsrSize() >= 0)
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"),
               SizeToStr(Cache->UsrSize()).c_str());
    else
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
               SizeToStr(-1*Cache->UsrSize()).c_str());
 
@@ -860,14 +1138,21 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    {
       struct statvfs Buf;
       string OutputDir = _config->FindDir("Dir::Cache::Archives");
-      if (statvfs(OutputDir.c_str(),&Buf) != 0)
-        return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
-                             OutputDir.c_str());
-      if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
+      if (statvfs(OutputDir.c_str(),&Buf) != 0) {
+        if (errno == EOVERFLOW)
+           return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
+                                OutputDir.c_str());
+        else
+           return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
+                                OutputDir.c_str());
+      } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
       {
          struct statfs Stat;
-         if (statfs(OutputDir.c_str(),&Stat) != 0 ||
-                        unsigned(Stat.f_type) != RAMFS_MAGIC)
+         if (statfs(OutputDir.c_str(),&Stat) != 0
+#if HAVE_STRUCT_STATFS_F_TYPE
+             || unsigned(Stat.f_type) != RAMFS_MAGIC
+#endif
+             )
             return _error->Error(_("You don't have enough free space in %s."),
                 OutputDir.c_str());
       }
@@ -1025,187 +1310,67 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
       if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
         return false;
       if (Res == pkgPackageManager::Completed)
-        return true;
+        break;
       
       // Reload the fetcher object and loop again for media swapping
       Fetcher.Shutdown();
-      if (PM->GetArchives(&Fetcher,&List,&Recs) == false)
+      if (PM->GetArchives(&Fetcher,List,&Recs) == false)
         return false;
       
       _system->Lock();
-   }   
+   }
+
+   std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
+   if (disappearedPkgs.empty() == true)
+      return true;
+
+   string disappear;
+   for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
+       d != disappearedPkgs.end(); ++d)
+      disappear.append(*d).append(" ");
+
+   ShowList(c1out, P_("The following package disappeared from your system as\n"
+       "all files have been overwritten by other packages:",
+       "The following packages disappeared from your system as\n"
+       "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, "");
+   c0out << _("Note: This is done automatic and on purpose by dpkg.") << std::endl;
+
+   return true;
 }
                                                                        /*}}}*/
-// TryToInstall - Try to install a single package                      /*{{{*/
+// TryToInstallBuildDep - Try to install a single package              /*{{{*/
 // ---------------------------------------------------------------------
 /* This used to be inlined in DoInstall, but with the advent of regex package
    name matching it was split out.. */
-bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
+bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache,
                  pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
-                 unsigned int &ExpectedInst,bool AllowFail = true)
+                 bool AllowFail = true)
 {
-   /* This is a pure virtual package and there is a single available 
-      provides */
-   if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0 &&
-       Pkg.ProvidesList()->NextProvides == 0)
-   {
-      pkgCache::PkgIterator Tmp = Pkg.ProvidesList().OwnerPkg();
-      ioprintf(c1out,_("Note, selecting %s instead of %s\n"),
-              Tmp.Name(),Pkg.Name());
-      Pkg = Tmp;
-   }
-   
-   // Handle the no-upgrade case
-   if (_config->FindB("APT::Get::upgrade",true) == false &&
-       Pkg->CurrentVer != 0)
-   {
-      if (AllowFail == true)
-        ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
-                 Pkg.Name());
-      return true;
-   }
-   
-   // Check if there is something at all to install
-   pkgDepCache::StateCache &State = Cache[Pkg];
-   if (Remove == true && Pkg->CurrentVer == 0)
+   if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0)
    {
-      Fix.Clear(Pkg);
-      Fix.Protect(Pkg);
-      Fix.Remove(Pkg);
-      
-      /* We want to continue searching for regex hits, so we return false here
-         otherwise this is not really an error. */
-      if (AllowFail == false)
-        return false;
-      
-      ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.Name());
-      return true;
-   }
-   
-   if (State.CandidateVer == 0 && Remove == false)
-   {
-      if (AllowFail == false)
-        return false;
-      
-      if (Pkg->ProvidesList != 0)
-      {
-        ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
-                 Pkg.Name());
-        
-        pkgCache::PrvIterator I = Pkg.ProvidesList();
-        for (; I.end() == false; I++)
-        {
-           pkgCache::PkgIterator Pkg = I.OwnerPkg();
-           
-           if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
-           {
-              if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
-                 c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
-                 _(" [Installed]") << endl;
-              else
-                 c1out << "  " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
-           }      
-        }
-        c1out << _("You should explicitly select one to install.") << endl;
-      }
-      else
-      {
-        ioprintf(c1out,
-        _("Package %s is not available, but is referred to by another package.\n"
-          "This may mean that the package is missing, has been obsoleted, or\n"
-           "is only available from another source\n"),Pkg.Name());
-        
-        string List;
-        string VersionsList;
-        SPtrArray<bool> Seen = new bool[Cache.Head().PackageCount];
-        memset(Seen,0,Cache.Head().PackageCount*sizeof(*Seen));
-        pkgCache::DepIterator Dep = Pkg.RevDependsList();
-        for (; Dep.end() == false; Dep++)
-        {
-           if (Dep->Type != pkgCache::Dep::Replaces)
-              continue;
-           if (Seen[Dep.ParentPkg()->ID] == true)
-              continue;
-           Seen[Dep.ParentPkg()->ID] = true;
-           List += string(Dep.ParentPkg().Name()) + " ";
-        //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
-        }          
-        ShowList(c1out,_("However the following packages replace it:"),List,VersionsList);
-      }
-      
-      _error->Error(_("Package %s has no installation candidate"),Pkg.Name());
-      return false;
+      CacheSetHelperAPTGet helper(c1out);
+      helper.showErrors(AllowFail == false);
+      pkgCache::VerIterator Ver = helper.canNotFindNewestVer(Cache, Pkg);
+      if (Ver.end() == false)
+        Pkg = Ver.ParentPkg();
+      else if (helper.showVirtualPackageErrors(Cache) == false)
+        return AllowFail;
    }
 
-   Fix.Clear(Pkg);
-   Fix.Protect(Pkg);   
    if (Remove == true)
    {
-      Fix.Remove(Pkg);
-      Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
-      return true;
-   }
-   
-   // Install it
-   Cache.MarkInstall(Pkg,false);
-   if (State.Install() == false)
-   {
-      if (_config->FindB("APT::Get::ReInstall",false) == true)
-      {
-        if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
-           ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
-                    Pkg.Name());
-        else
-           Cache.SetReInstall(Pkg,true);
-      }      
-      else
-      {
-        if (AllowFail == true)
-           ioprintf(c1out,_("%s is already the newest version.\n"),
-                    Pkg.Name());
-      }      
-   }   
-   else
-      ExpectedInst++;
-   
-   // 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);
+      TryToRemove RemoveAction(Cache, Fix);
+      RemoveAction(Pkg.VersionList());
+   } else if (Cache[Pkg].CandidateVer != 0) {
+      TryToInstall InstallAction(Cache, Fix, BrokenFix);
+      InstallAction(Cache[Pkg].CandidateVerIter(Cache));
+      InstallAction.doAutoInstall();
+   } else
+      return AllowFail;
 
    return true;
 }
                                                                        /*}}}*/
-// TryToChangeVer - Try to change a candidate version                  /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool TryToChangeVer(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
-                   const char *VerTag,bool IsRel)
-{
-   pkgVersionMatch Match(VerTag,(IsRel == true?pkgVersionMatch::Release : 
-                                pkgVersionMatch::Version));
-   
-   pkgCache::VerIterator Ver = Match.Find(Pkg);
-                        
-   if (Ver.end() == true)
-   {
-      if (IsRel == true)
-        return _error->Error(_("Release '%s' for '%s' was not found"),
-                             VerTag,Pkg.Name());
-      return _error->Error(_("Version '%s' for '%s' was not found"),
-                          VerTag,Pkg.Name());
-   }
-   
-   if (strcmp(VerTag,Ver.VerStr()) != 0)
-   {
-      ioprintf(c1out,_("Selected version %s (%s) for %s\n"),
-              Ver.VerStr(),Ver.RelStr().c_str(),Pkg.Name());
-   }
-   
-   Cache.SetCandidateVersion(Ver);
-   return true;
-}
-                                                                       /*}}}*/
 // FindSrc - Find a source record                                      /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1213,122 +1378,171 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
                               pkgSrcRecords &SrcRecs,string &Src,
                               pkgDepCache &Cache)
 {
-   // We want to pull the version off the package specification..
    string VerTag;
+   string DefRel = _config->Find("APT::Default-Release");
    string TmpSrc = Name;
-   string::size_type Slash = TmpSrc.rfind('=');
 
-   // honor default release
-   string DefRel = _config->Find("APT::Default-Release");
-   pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc);
+   // extract the version/release from the pkgname
+   const size_t found = TmpSrc.find_last_of("/=");
+   if (found != string::npos) {
+      if (TmpSrc[found] == '/')
+        DefRel = TmpSrc.substr(found+1);
+      else
+        VerTag = TmpSrc.substr(found+1);
+      TmpSrc = TmpSrc.substr(0,found);
+   }
 
-   if (Slash != string::npos)
-   {
-      VerTag = string(TmpSrc.begin() + Slash + 1,TmpSrc.end());
-      TmpSrc = string(TmpSrc.begin(),TmpSrc.begin() + Slash);
-   } 
-   else  if(!Pkg.end() && DefRel.empty() == false)
+   /* Lookup the version of the package we would install if we were to
+      install a version and determine the source package name, then look
+      in the archive for a source package of the same name. */
+   bool MatchSrcOnly = _config->FindB("APT::Get::Only-Source");
+   const pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc);
+   if (MatchSrcOnly == false && Pkg.end() == false) 
    {
-      // we have a default release, try to locate the pkg. we do it like
-      // this because GetCandidateVer() will not "downgrade", that means
-      // "apt-get source -t stable apt" won't work on a unstable system
-      for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; 
-          Ver++)
+      if(VerTag.empty() == false || DefRel.empty() == false) 
       {
-        for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false;
-             VF++)
+        bool fuzzy = false;
+        // we have a default release, try to locate the pkg. we do it like
+        // this because GetCandidateVer() will not "downgrade", that means
+        // "apt-get source -t stable apt" won't work on a unstable system
+        for (pkgCache::VerIterator Ver = Pkg.VersionList();; Ver++)
         {
-           /* If this is the status file, and the current version is not the
-              version in the status file (ie it is not installed, or somesuch)
-              then it is not a candidate for installation, ever. This weeds
-              out bogus entries that may be due to config-file states, or
-              other. */
-           if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 
-               pkgCache::Flag::NotSource && Pkg.CurrentVer() != Ver)
-           continue;
-           
-           //std::cout << VF.File().Archive() << std::endl;
-           if(VF.File().Archive() && (VF.File().Archive() == DefRel)) 
+           // try first only exact matches, later fuzzy matches
+           if (Ver.end() == true)
+           {
+              if (fuzzy == true)
+                 break;
+              fuzzy = true;
+              Ver = Pkg.VersionList();
+              // exit right away from the Pkg.VersionList() loop if we
+              // don't have any versions
+              if (Ver.end() == true)
+                 break;
+           }
+           // We match against a concrete version (or a part of this version)
+           if (VerTag.empty() == false &&
+               (fuzzy == true || Cache.VS().CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match
+               (fuzzy == false || strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0)) // fuzzy match
+              continue;
+
+           for (pkgCache::VerFileIterator VF = Ver.FileList();
+                VF.end() == false; VF++) 
            {
-              VerTag = Ver.VerStr();
+              /* If this is the status file, and the current version is not the
+                 version in the status file (ie it is not installed, or somesuch)
+                 then it is not a candidate for installation, ever. This weeds
+                 out bogus entries that may be due to config-file states, or
+                 other. */
+              if ((VF.File()->Flags & pkgCache::Flag::NotSource) ==
+                  pkgCache::Flag::NotSource && Pkg.CurrentVer() != Ver)
+                 continue;
+
+              // or we match against a release
+              if(VerTag.empty() == false ||
+                 (VF.File().Archive() != 0 && VF.File().Archive() == DefRel) ||
+                 (VF.File().Codename() != 0 && VF.File().Codename() == DefRel)) 
+              {
+                 pkgRecords::Parser &Parse = Recs.Lookup(VF);
+                 Src = Parse.SourcePkg();
+                 // no SourcePkg name, so it is the "binary" name
+                 if (Src.empty() == true)
+                    Src = TmpSrc;
+                 // the Version we have is possibly fuzzy or includes binUploads,
+                 // so we use the Version of the SourcePkg (empty if same as package)
+                 VerTag = Parse.SourceVer();
+                 if (VerTag.empty() == true)
+                    VerTag = Ver.VerStr();
+                 break;
+              }
+           }
+           if (Src.empty() == false)
               break;
+        }
+        if (Src.empty() == true) 
+        {
+           // Sources files have no codename information
+           if (VerTag.empty() == true && DefRel.empty() == false) 
+           {
+              _error->Error(_("Ignore unavailable target release '%s' of package '%s'"), DefRel.c_str(), TmpSrc.c_str());
+              return 0;
            }
         }
       }
-   }
-
-   /* Lookup the version of the package we would install if we were to
-      install a version and determine the source package name, then look
-      in the archive for a source package of the same name. */
-   if (_config->FindB("APT::Get::Only-Source") == false)
-   {
-      if (Pkg.end() == false)
+      if (Src.empty() == true)
       {
+        // if we don't have found a fitting package yet so we will
+        // choose a good candidate and proceed with that.
+        // Maybe we will find a source later on with the right VerTag
         pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg);
-        if (Ver.end() == false)
+        if (Ver.end() == false) 
         {
            pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
            Src = Parse.SourcePkg();
+           if (VerTag.empty() == true)
+              VerTag = Parse.SourceVer();
         }
-      }   
+      }
    }
-   
-   // No source package name..
+
    if (Src.empty() == true)
       Src = TmpSrc;
-   
+   else 
+   {
+      /* if we have a source pkg name, make sure to only search
+        for srcpkg names, otherwise apt gets confused if there
+        is a binary package "pkg1" and a source package "pkg1"
+        with the same name but that comes from different packages */
+      MatchSrcOnly = true;
+      if (Src != TmpSrc) 
+      {
+        ioprintf(c1out, _("Picking '%s' as source package instead of '%s'\n"), Src.c_str(), TmpSrc.c_str());
+      }
+   }
+
    // The best hit
    pkgSrcRecords::Parser *Last = 0;
    unsigned long Offset = 0;
    string Version;
-   bool IsMatch = false;
-   
-   // If we are matching by version then we need exact matches to be happy
-   if (VerTag.empty() == false)
-      IsMatch = true;
-   
+
    /* Iterate over all of the hits, which includes the resulting
       binary packages in the search */
    pkgSrcRecords::Parser *Parse;
-   SrcRecs.Restart();
-   while ((Parse = SrcRecs.Find(Src.c_str(),false)) != 0)
+   while (true) 
    {
-      string Ver = Parse->Version();
-      
-      // Skip name mismatches
-      if (IsMatch == true && Parse->Package() != Src)
-        continue;
-      
-      if (VerTag.empty() == false)
+      SrcRecs.Restart();
+      while ((Parse = SrcRecs.Find(Src.c_str(), MatchSrcOnly)) != 0) 
       {
-        /* Don't want to fall through because we are doing exact version 
-           matching. */
-        if (Cache.VS().CmpVersion(VerTag,Ver) != 0)
+        const string Ver = Parse->Version();
+
+        // Ignore all versions which doesn't fit
+        if (VerTag.empty() == false &&
+            Cache.VS().CmpVersion(VerTag, Ver) != 0) // exact match
            continue;
-        
-        Last = Parse;
-        Offset = Parse->Offset();
-        break;
+
+        // Newer version or an exact match? Save the hit
+        if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0) {
+           Last = Parse;
+           Offset = Parse->Offset();
+           Version = Ver;
+        }
+
+        // was the version check above an exact match? If so, we don't need to look further
+        if (VerTag.empty() == false && VerTag.size() == Ver.size())
+           break;
       }
-                                 
-      // Newer version or an exact match
-      if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0 || 
-         (Parse->Package() == Src && IsMatch == false))
-      {
-        IsMatch = Parse->Package() == Src;
-        Last = Parse;
-        Offset = Parse->Offset();
-        Version = Ver;
-      }      
+      if (Last != 0 || VerTag.empty() == true)
+        break;
+      //if (VerTag.empty() == false && Last == 0)
+      _error->Error(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str());
+      return 0;
    }
-   
+
    if (Last == 0 || Last->Jump(Offset) == false)
       return 0;
-   
+
    return Last;
 }
                                                                        /*}}}*/
-
 // DoUpdate - Update the package lists                                 /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1336,33 +1550,31 @@ bool DoUpdate(CommandLine &CmdL)
 {
    if (CmdL.FileSize() != 1)
       return _error->Error(_("The update command takes no arguments"));
-   
+
+   CacheFile Cache;
+
    // Get the source list
-   pkgSourceList List;
-   if (List.ReadMainList() == false)
+   if (Cache.BuildSourceList() == false)
       return false;
+   pkgSourceList *List = Cache.GetSourceList();
 
-   // Lock the list directory
-   FileFd Lock;
-   if (_config->FindB("Debug::NoLocking",false) == false)
-   {
-      Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
-      if (_error->PendingError() == true)
-        return _error->Error(_("Unable to lock the list directory"));
-   }
-   
    // Create the progress
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
       
    // Just print out the uris an exit if the --print-uris flag was used
    if (_config->FindB("APT::Get::Print-URIs") == true)
    {
+      // force a hashsum for compatibility reasons
+      _config->CndSet("Acquire::ForceHash", "md5sum");
+
       // get a fetcher
-      pkgAcquire Fetcher(&Stat);
+      pkgAcquire Fetcher;
+      if (Fetcher.Setup(&Stat) == false)
+        return false;
 
       // Populate it with the source selection and get all Indexes 
       // (GetAll=true)
-      if (List.GetIndexes(&Fetcher,true) == false)
+      if (List->GetIndexes(&Fetcher,true) == false)
         return false;
 
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
@@ -1373,9 +1585,9 @@ bool DoUpdate(CommandLine &CmdL)
    }
 
    // do the work
-   CacheFile Cache;
-   bool res = ListUpdate(Stat, List);
-     
+   if (_config->FindB("APT::Get::Download",true) == true)
+       ListUpdate(Stat, *List);
+
    // Rebuild the cache.   
    if (Cache.BuildCaches() == false)
       return false;
@@ -1391,20 +1603,29 @@ bool DoAutomaticRemove(CacheFile &Cache)
    bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
    bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
    bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
-   pkgDepCache::ActionGroup group(*Cache);
 
+   pkgDepCache::ActionGroup group(*Cache);
    if(Debug)
       std::cout << "DoAutomaticRemove()" << std::endl;
 
-   if (_config->FindB("APT::Get::Remove",true) == false &&
-       doAutoRemove == true)
+   // we don't want to autoremove and we don't want to see it, so why calculating?
+   if (doAutoRemove == false && hideAutoRemove == true)
+      return true;
+
+   if (doAutoRemove == true &&
+       _config->FindB("APT::Get::Remove",true) == false)
    {
       c1out << _("We are not supposed to delete stuff, can't start "
                 "AutoRemover") << std::endl;
-      doAutoRemove = false;
+      return false;
    }
 
+   bool purgePkgs = _config->FindB("APT::Get::Purge", false);
+   bool smallList = (hideAutoRemove == false &&
+       strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
+
    string autoremovelist, autoremoveversions;
+   unsigned long autoRemoveCount = 0;
    // look over the cache to see what can be removed
    for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg)
    {
@@ -1412,31 +1633,46 @@ bool DoAutomaticRemove(CacheFile &Cache)
       {
         if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
            if(Debug)
-              std::cout << "We could delete %s" <<  Pkg.Name() << std::endl;
-         
-        // only show stuff in the list that is not yet marked for removal
-        if(Cache[Pkg].Delete() == false) 
-        {
-           autoremovelist += string(Pkg.Name()) + " ";
-           autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
-        }
+              std::cout << "We could delete %s" <<  Pkg.FullName(true).c_str() << std::endl;
+
         if (doAutoRemove)
         {
            if(Pkg.CurrentVer() != 0 && 
               Pkg->CurrentState != pkgCache::State::ConfigFiles)
-              Cache->MarkDelete(Pkg, _config->FindB("APT::Get::Purge", false));
+              Cache->MarkDelete(Pkg, purgePkgs);
            else
               Cache->MarkKeep(Pkg, false, false);
         }
+        else
+        {
+           // only show stuff in the list that is not yet marked for removal
+           if(Cache[Pkg].Delete() == false) 
+           {
+              ++autoRemoveCount;
+              // we don't need to fill the strings if we don't need them
+              if (smallList == false)
+              {
+                autoremovelist += Pkg.FullName(true) + " ";
+                autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
+              }
+           }
+        }
       }
    }
-   if (!hideAutoRemove) 
-      ShowList(c1out, _("The following packages were automatically installed and are no longer required:"), autoremovelist, autoremoveversions);
-   if (!doAutoRemove && !hideAutoRemove && autoremovelist.size() > 0)
+   // if we don't remove them, we should show them!
+   if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
+   {
+      if (smallList == false)
+        ShowList(c1out, P_("The following package was automatically installed and is no longer required:",
+                 "The following packages were automatically installed and are no longer required:",
+                 autoRemoveCount), autoremovelist, autoremoveversions);
+      else
+        ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
+                 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
       c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
-
-   // Now see if we destroyed anything
-   if (Cache->BrokenCount() != 0)
+   }
+   // Now see if we had destroyed anything (if we had done anything)
+   else 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;
@@ -1449,7 +1685,7 @@ bool DoAutomaticRemove(CacheFile &Cache)
    }
    return true;
 }
-
+                                                                       /*}}}*/
 // DoUpgrade - Upgrade all packages                                    /*{{{*/
 // ---------------------------------------------------------------------
 /* Upgrade all packages without installing new packages or erasing old
@@ -1470,61 +1706,6 @@ bool DoUpgrade(CommandLine &CmdL)
    return InstallPackages(Cache,true);
 }
                                                                        /*}}}*/
-// DoInstallTask - Install task from the command line                  /*{{{*/
-// ---------------------------------------------------------------------
-/* Install named task */
-bool TryInstallTask(pkgDepCache &Cache, pkgProblemResolver &Fix, 
-                   bool BrokenFix,
-                   unsigned int& ExpectedInst, 
-                   const char *taskname,
-                   bool Remove)
-{
-   const char *start, *end;
-   pkgCache::PkgIterator Pkg;
-   char buf[64*1024];
-   regex_t Pattern;
-
-   // get the records
-   pkgRecords Recs(Cache);
-
-   // build regexp for the task
-   char S[300];
-   snprintf(S, sizeof(S), "^Task:.*[, ]%s([, ]|$)", taskname);
-   if(regcomp(&Pattern,S, REG_EXTENDED | REG_NOSUB | REG_NEWLINE) != 0)
-      return _error->Error("Failed to compile task regexp");
-   
-   bool found = false;
-   bool res = true;
-
-   // two runs, first ignore dependencies, second install any missing
-   for(int IgnoreBroken=1; IgnoreBroken >= 0; IgnoreBroken--)
-   {
-      for (Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
-      {
-        pkgCache::VerIterator ver = Cache[Pkg].CandidateVerIter(Cache);
-        if(ver.end())
-           continue;
-        pkgRecords::Parser &parser = Recs.Lookup(ver.FileList());
-        parser.GetRec(start,end);
-        strncpy(buf, start, end-start);
-        buf[end-start] = 0x0;
-        if (regexec(&Pattern,buf,0,0,0) != 0)
-           continue;
-        res &= TryToInstall(Pkg,Cache,Fix,Remove,IgnoreBroken,ExpectedInst);
-        found = true;
-      }
-   }
-   
-   // now let the problem resolver deal with any issues
-   Fix.Resolve(true);
-
-   if(!found)
-      _error->Error(_("Couldn't find task %s"),taskname);
-
-   regfree(&Pattern);
-   return res;
-}
-
 // DoInstall - Install packages from the command line                  /*{{{*/
 // ---------------------------------------------------------------------
 /* Install named packages */
@@ -1540,168 +1721,75 @@ bool DoInstall(CommandLine &CmdL)
    if (Cache->BrokenCount() != 0)
       BrokenFix = true;
    
-   unsigned int AutoMarkChanged = 0;
-   unsigned int ExpectedInst = 0;
-   unsigned int Packages = 0;
    pkgProblemResolver Fix(Cache);
-   
-   bool DefRemove = false;
+
+   static const unsigned short MOD_REMOVE = 1;
+   static const unsigned short MOD_INSTALL = 2;
+
+   unsigned short fallback = MOD_INSTALL;
    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
-      DefRemove = true;
+      fallback = MOD_REMOVE;
    else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
    {
       _config->Set("APT::Get::Purge", true);
-      DefRemove = true;
+      fallback = MOD_REMOVE;
    }
    else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
    {
       _config->Set("APT::Get::AutomaticRemove", "true");
-      DefRemove = true;
+      fallback = MOD_REMOVE;
    }
-   // new scope for the ActionGroup
+
+   std::list<APT::VersionSet::Modifier> mods;
+   mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
+               APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE));
+   mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
+               APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST));
+   CacheSetHelperAPTGet helper(c0out);
+   std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache,
+               CmdL.FileList + 1, mods, fallback, helper);
+
+   if (_error->PendingError() == true)
    {
-      pkgDepCache::ActionGroup group(Cache);
-      for (const char **I = CmdL.FileList + 1; *I != 0; I++)
-      {
-        // Duplicate the string
-        unsigned int Length = strlen(*I);
-        char S[300];
-        if (Length >= sizeof(S))
-           continue;
-        strcpy(S,*I);
-      
-        // See if we are removing and special indicators..
-        bool Remove = DefRemove;
-        char *VerTag = 0;
-        bool VerIsRel = false;
+      helper.showVirtualPackageErrors(Cache);
+      return false;
+   }
 
-         // this is a task!
-         if (Length >= 1 && S[Length - 1] == '^')
-         {
-            S[--Length] = 0;
-            // tasks must always be confirmed
-            ExpectedInst += 1000;
-            // see if we can install it
-            TryInstallTask(Cache, Fix, BrokenFix, ExpectedInst, S, Remove);
-            continue;
-         }
+   unsigned short order[] = { 0, 0, 0 };
+   if (fallback == MOD_INSTALL) {
+      order[0] = MOD_INSTALL;
+      order[1] = MOD_REMOVE;
+   } else {
+      order[0] = MOD_REMOVE;
+      order[1] = MOD_INSTALL;
+   }
 
-        while (Cache->FindPkg(S).end() == true)
-        {
-           // Handle an optional end tag indicating what to do
-           if (Length >= 1 && S[Length - 1] == '-')
-           {
-              Remove = true;
-              S[--Length] = 0;
-              continue;
-           }
-        
-           if (Length >= 1 && S[Length - 1] == '+')
-           {
-              Remove = false;
-              S[--Length] = 0;
-              continue;
-           }
-        
-           char *Slash = strchr(S,'=');
-           if (Slash != 0)
-           {
-              VerIsRel = false;
-              *Slash = 0;
-              VerTag = Slash + 1;
-           }
-        
-           Slash = strchr(S,'/');
-           if (Slash != 0)
-           {
-              VerIsRel = true;
-              *Slash = 0;
-              VerTag = Slash + 1;
-           }
-        
-           break;
-        }
-      
-        // Locate the package
-        pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
-        Packages++;
-        if (Pkg.end() == true)
-        {
-           // Check if the name is a regex
-           const char *I;
-           for (I = S; *I != 0; I++)
-              if (*I == '?' || *I == '*' || *I == '|' ||
-                  *I == '[' || *I == '^' || *I == '$')
-                 break;
-           if (*I == 0)
-              return _error->Error(_("Couldn't find package %s"),S);
+  TryToInstall InstallAction(Cache, Fix, BrokenFix);
+  TryToRemove RemoveAction(Cache, Fix);
 
-           // Regexs must always be confirmed
-           ExpectedInst += 1000;
-        
-           // Compile the regex pattern
-           regex_t Pattern;
-           int Res;
-           if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
-                              REG_NOSUB)) != 0)
-           {
-              char Error[300];     
-              regerror(Res,&Pattern,Error,sizeof(Error));
-              return _error->Error(_("Regex compilation error - %s"),Error);
-           }
-        
-           // Run over the matches
-           bool Hit = false;
-           for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
-           {
-              if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
-                 continue;
-           
-              ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"),
-                       Pkg.Name(),S);
-           
-              if (VerTag != 0)
-                 if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
-                    return false;
-           
-              Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
-                                  ExpectedInst,false);
-           }
-           regfree(&Pattern);
-        
-           if (Hit == false)
-              return _error->Error(_("Couldn't find package %s"),S);
+   // new scope for the ActionGroup
+   {
+      pkgDepCache::ActionGroup group(Cache);
+
+      for (unsigned short i = 0; order[i] != 0; ++i)
+      {
+        if (order[i] == MOD_INSTALL) {
+           InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
+           InstallAction.doAutoInstall();
         }
-        else
-        {
-           if (VerTag != 0)
-              if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
-                 return false;
-           if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
-              return false;
-
-           // see if we need to fix the auto-mark flag 
-           // e.g. apt-get install foo 
-           // where foo is marked automatic
-           if(!Remove && 
-              Cache[Pkg].Install() == false && 
-              (Cache[Pkg].Flags & pkgCache::Flag::Auto) &&
-              _config->FindB("APT::Get::ReInstall",false) == false)
-           {
-              ioprintf(c1out,_("%s set to manually installed.\n"),
-                       Pkg.Name());
-              Cache->MarkAuto(Pkg,false);
-              AutoMarkChanged++;
-           }
-        }      
+        else if (order[i] == MOD_REMOVE)
+           RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
       }
 
+      if (_error->PendingError() == true)
+        return false;
+
       /* If we are in the Broken fixing mode we do not attempt to fix the
         problems. This is if the user invoked install without -f and gave
         packages */
       if (BrokenFix == true && Cache->BrokenCount() != 0)
       {
-        c1out << _("You might want to run `apt-get -f install' to correct these:") << endl;
+        c1out << _("You might want to run 'apt-get -f install' to correct these:") << endl;
         ShowBroken(c1out,Cache,false);
 
         return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
@@ -1720,6 +1808,7 @@ bool DoInstall(CommandLine &CmdL)
              "requested an impossible situation or if you are using the unstable\n" 
              "distribution that some required packages have not yet been created\n"
              "or been moved out of Incoming.") << endl;
+        /*
         if (Packages == 1)
         {
            c1out << endl;
@@ -1728,6 +1817,7 @@ bool DoInstall(CommandLine &CmdL)
                 "the package is simply not installable and a bug report against\n" 
                 "that package should be filed.") << endl;
         }
+        */
 
         c1out << _("The following information may help to resolve the situation:") << endl;
         c1out << endl;
@@ -1740,7 +1830,7 @@ bool DoInstall(CommandLine &CmdL)
 
    /* Print out a list of packages that are going to be installed extra
       to what the user asked */
-   if (Cache->InstCount() != ExpectedInst)
+   if (Cache->InstCount() != verset[MOD_INSTALL].size())
    {
       string List;
       string VersionsList;
@@ -1756,7 +1846,7 @@ bool DoInstall(CommandLine &CmdL)
                break;
         
         if (*J == 0) {
-           List += string(I.Name()) + " ";
+           List += I.FullName(true) + " ";
            VersionsList += string(Cache[I].CandVersion) + "\n";
         }
       }
@@ -1792,10 +1882,11 @@ bool DoInstall(CommandLine &CmdL)
            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())
+              string target = Start.TargetPkg().FullName(true) + " ";
+              pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
+              if (TarPkg->SelectedState == pkgCache::State::Install ||
+                  TarPkg->SelectedState == pkgCache::State::Hold ||
+                  Cache[Start.TargetPkg()].Install())
               {
                  foundInstalledInOrGroup=true;
                  break;
@@ -1858,17 +1949,59 @@ bool DoInstall(CommandLine &CmdL)
    // if nothing changed in the cache, but only the automark information
    // we write the StateFile here, otherwise it will be written in 
    // cache.commit()
-   if (AutoMarkChanged > 0 &&
+   if (InstallAction.AutoMarkChanged > 0 &&
        Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
-       Cache->BadCount() == 0)
+       Cache->BadCount() == 0 &&
+       _config->FindB("APT::Get::Simulate",false) == false)
       Cache->writeStateFile(NULL);
 
    // See if we need to prompt
-   if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
+   // FIXME: check if really the packages in the set are going to be installed
+   if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
       return InstallPackages(Cache,false,false);
 
    return InstallPackages(Cache,false);   
 }
+
+/* mark packages as automatically/manually installed. */
+bool DoMarkAuto(CommandLine &CmdL)
+{
+   bool Action = true;
+   int AutoMarkChanged = 0;
+   OpTextProgress progress;
+   CacheFile Cache;
+   if (Cache.Open() == false)
+      return false;
+
+   if (strcasecmp(CmdL.FileList[0],"markauto") == 0)
+      Action = true;
+   else if (strcasecmp(CmdL.FileList[0],"unmarkauto") == 0)
+      Action = false;
+
+   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   {
+      const char *S = *I;
+      // Locate the package
+      pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
+      if (Pkg.end() == true) {
+         return _error->Error(_("Couldn't find package %s"),S);
+      }
+      else
+      {
+         if (!Action)
+            ioprintf(c1out,_("%s set to manually installed.\n"), Pkg.Name());
+         else
+            ioprintf(c1out,_("%s set to automatically installed.\n"),
+                      Pkg.Name());
+
+         Cache->MarkAuto(Pkg,Action);
+         AutoMarkChanged++;
+      }
+   }
+   if (AutoMarkChanged && ! _config->FindB("APT::Get::Simulate",false))
+      return Cache->writeStateFile(NULL);
+   return false;
+}
                                                                        /*}}}*/
 // DoDistUpgrade - Automatic smart upgrader                            /*{{{*/
 // ---------------------------------------------------------------------
@@ -2065,25 +2198,35 @@ bool DoSource(CommandLine &CmdL)
       return _error->Error(_("Must specify at least one package to fetch source for"));
    
    // Read the source list
-   pkgSourceList List;
-   if (List.ReadMainList() == false)
-      return _error->Error(_("The list of sources could not be read."));
+   if (Cache.BuildSourceList() == false)
+      return false;
+   pkgSourceList *List = Cache.GetSourceList();
    
    // Create the text record parsers
    pkgRecords Recs(Cache);
-   pkgSrcRecords SrcRecs(List);
+   pkgSrcRecords SrcRecs(*List);
    if (_error->PendingError() == true)
       return false;
 
    // Create the download object
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
-   pkgAcquire Fetcher(&Stat);
+   pkgAcquire Fetcher;
+   if (Fetcher.Setup(&Stat) == false)
+      return false;
 
    DscFile *Dsc = new DscFile[CmdL.FileSize()];
    
    // insert all downloaded uris into this set to avoid downloading them
    // twice
    set<string> queued;
+
+   // Diff only mode only fetches .diff files
+   bool const diffOnly = _config->FindB("APT::Get::Diff-Only", false);
+   // Tar only mode only fetches .tar files
+   bool const tarOnly = _config->FindB("APT::Get::Tar-Only", false);
+   // Dsc only mode only fetches .dsc files
+   bool const dscOnly = _config->FindB("APT::Get::Dsc-Only", false);
+
    // Load the requestd sources into the fetcher
    unsigned J = 0;
    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
@@ -2094,6 +2237,33 @@ bool DoSource(CommandLine &CmdL)
       if (Last == 0)
         return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
       
+      string srec = Last->AsStr();
+      string::size_type pos = srec.find("\nVcs-");
+      while (pos != string::npos)
+      {
+        pos += strlen("\nVcs-");
+        string vcs = srec.substr(pos,srec.find(":",pos)-pos);
+        if(vcs == "Browser") 
+        {
+           pos = srec.find("\nVcs-", pos);
+           continue;
+        }
+        pos += vcs.length()+2;
+        string::size_type epos = srec.find("\n", pos);
+        string uri = srec.substr(pos,epos-pos).c_str();
+        ioprintf(c1out, _("NOTICE: '%s' packaging is maintained in "
+                          "the '%s' version control system at:\n"
+                          "%s\n"),
+                 Src.c_str(), vcs.c_str(), uri.c_str());
+        if(vcs == "Bzr") 
+           ioprintf(c1out,_("Please use:\n"
+                            "bzr get %s\n"
+                            "to retrieve the latest (possibly unreleased) "
+                            "updates to the package.\n"),
+                    uri.c_str());
+        break;
+      }
+
       // Back track
       vector<pkgSrcRecords::File> Lst;
       if (Last->Files(Lst) == false)
@@ -2110,21 +2280,17 @@ bool DoSource(CommandLine &CmdL)
            Dsc[J].Version = Last->Version();
            Dsc[J].Dsc = flNotDir(I->Path);
         }
-        
-        // Diff only mode only fetches .diff files
-        if (_config->FindB("APT::Get::Diff-Only",false) == true &&
-            I->Type != "diff")
-           continue;
-        
-        // Tar only mode only fetches .tar files
-        if (_config->FindB("APT::Get::Tar-Only",false) == true &&
-            I->Type != "tar")
-           continue;
 
-        // Dsc only mode only fetches .dsc files
-        if (_config->FindB("APT::Get::Dsc-Only",false) == true &&
-            I->Type != "dsc")
-           continue;
+        // Handle the only options so that multiple can be used at once
+        if (diffOnly == true || tarOnly == true || dscOnly == true)
+        {
+           if ((diffOnly == true && I->Type == "diff") ||
+               (tarOnly == true && I->Type == "tar") ||
+               (dscOnly == true && I->Type == "dsc"))
+               ; // Fine, we want this file downloaded
+           else
+              continue;
+        }
 
         // don't download the same uri twice (should this be moved to
         // the fetcher interface itself?)
@@ -2154,30 +2320,41 @@ bool DoSource(CommandLine &CmdL)
    }
    
    // Display statistics
-   double FetchBytes = Fetcher.FetchNeeded();
-   double FetchPBytes = Fetcher.PartialPresent();
-   double DebBytes = Fetcher.TotalNeeded();
+   unsigned long long FetchBytes = Fetcher.FetchNeeded();
+   unsigned long long FetchPBytes = Fetcher.PartialPresent();
+   unsigned long long DebBytes = Fetcher.TotalNeeded();
 
    // Check for enough free space
    struct statvfs Buf;
    string OutputDir = ".";
-   if (statvfs(OutputDir.c_str(),&Buf) != 0)
-      return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
-                          OutputDir.c_str());
-   if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
+   if (statvfs(OutputDir.c_str(),&Buf) != 0) {
+      if (errno == EOVERFLOW)
+        return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
+                               OutputDir.c_str());
+      else
+        return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
+                               OutputDir.c_str());
+   } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
      {
        struct statfs Stat;
-       if (statfs(OutputDir.c_str(),&Stat) != 0 || 
-           unsigned(Stat.f_type) != RAMFS_MAGIC) 
+       if (statfs(OutputDir.c_str(),&Stat) != 0
+#if HAVE_STRUCT_STATFS_F_TYPE
+           || unsigned(Stat.f_type) != RAMFS_MAGIC
+#endif
+           ) 
           return _error->Error(_("You don't have enough free space in %s"),
               OutputDir.c_str());
       }
    
    // Number of bytes
    if (DebBytes != FetchBytes)
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("Need to get %sB/%sB of source archives.\n"),
               SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
    else
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("Need to get %sB of source archives.\n"),
               SizeToStr(DebBytes).c_str());
    
@@ -2185,6 +2362,7 @@ bool DoSource(CommandLine &CmdL)
    {
       for (unsigned I = 0; I != J; I++)
         ioprintf(cout,_("Fetch source %s\n"),Dsc[I].Package.c_str());
+      delete[] Dsc;
       return true;
    }
    
@@ -2195,6 +2373,7 @@ bool DoSource(CommandLine &CmdL)
       for (; I != Fetcher.UriEnd(); I++)
         cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
               I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
+      delete[] Dsc;
       return true;
    }
    
@@ -2220,6 +2399,7 @@ bool DoSource(CommandLine &CmdL)
    if (_config->FindB("APT::Get::Download-only",false) == true)
    {
       c1out << _("Download complete and in download only mode") << endl;
+      delete[] Dsc;
       return true;
    }
 
@@ -2228,6 +2408,7 @@ bool DoSource(CommandLine &CmdL)
    
    if (Process == 0)
    {
+      bool const fixBroken = _config->FindB("APT::Get::Fix-Broken", false);
       for (unsigned I = 0; I != J; I++)
       {
         string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str());
@@ -2240,7 +2421,7 @@ bool DoSource(CommandLine &CmdL)
 
         // See if the package is already unpacked
         struct stat Stat;
-        if (stat(Dir.c_str(),&Stat) == 0 &&
+        if (fixBroken == false && stat(Dir.c_str(),&Stat) == 0 &&
             S_ISDIR(Stat.st_mode) != 0)
         {
            ioprintf(c0out ,_("Skipping unpack of already unpacked source in %s\n"),
@@ -2281,7 +2462,8 @@ bool DoSource(CommandLine &CmdL)
       
       _exit(0);
    }
-   
+   delete[] Dsc;
+
    // Wait for the subprocess
    int Status = 0;
    while (waitpid(Process,&Status,0) != Process)
@@ -2311,21 +2493,24 @@ bool DoBuildDep(CommandLine &CmdL)
       return _error->Error(_("Must specify at least one package to check builddeps for"));
    
    // Read the source list
-   pkgSourceList List;
-   if (List.ReadMainList() == false)
-      return _error->Error(_("The list of sources could not be read."));
+   if (Cache.BuildSourceList() == false)
+      return false;
+   pkgSourceList *List = Cache.GetSourceList();
    
    // Create the text record parsers
    pkgRecords Recs(Cache);
-   pkgSrcRecords SrcRecs(List);
+   pkgSrcRecords SrcRecs(*List);
    if (_error->PendingError() == true)
       return false;
 
    // Create the download object
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
-   pkgAcquire Fetcher(&Stat);
+   pkgAcquire Fetcher;
+   if (Fetcher.Setup(&Stat) == false)
+      return false;
 
    unsigned J = 0;
+   bool const StripMultiArch = APT::Configuration::getArchitectures().size() <= 1;
    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
    {
       string Src;
@@ -2335,7 +2520,7 @@ bool DoBuildDep(CommandLine &CmdL)
             
       // Process the build-dependencies
       vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
-      if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",false)) == false)
+      if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only", false), StripMultiArch) == false)
        return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
    
       // Also ensure that build-essential packages are present
@@ -2361,7 +2546,6 @@ bool DoBuildDep(CommandLine &CmdL)
       }
       
       // Install the requested packages
-      unsigned int ExpectedInst = 0;
       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
       pkgProblemResolver Fix(Cache);
       bool skipAlternatives = false; // skip remaining alternatives in an or group
@@ -2392,7 +2576,7 @@ bool DoBuildDep(CommandLine &CmdL)
              */
             if (IV.end() == false && 
                 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
-               TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst);
+               TryToInstallBuildDep(Pkg,Cache,Fix,true,false);
          }
         else // BuildDep || BuildDepIndep
          {
@@ -2434,7 +2618,7 @@ bool DoBuildDep(CommandLine &CmdL)
             for (; Prv.end() != true; Prv++)
            {
                if (_config->FindB("Debug::BuildDeps",false) == true)
-                    cout << "  Checking provider " << Prv.OwnerPkg().Name() << endl;
+                    cout << "  Checking provider " << Prv.OwnerPkg().FullName() << endl;
 
               if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
                  break;
@@ -2475,7 +2659,7 @@ bool DoBuildDep(CommandLine &CmdL)
                if (Prv.end() == false)
                {
                   if (_config->FindB("Debug::BuildDeps",false) == true)
-                     cout << "  Is provided by installed package " << Prv.OwnerPkg().Name() << endl;
+                     cout << "  Is provided by installed package " << Prv.OwnerPkg().FullName() << endl;
                   skipAlternatives = hasAlternatives;
                   continue;
                }
@@ -2500,7 +2684,7 @@ bool DoBuildDep(CommandLine &CmdL)
                   return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
                                        Last->BuildDepType((*D).Type),
                                        Src.c_str(),
-                                       Pkg.Name());
+                                       Pkg.FullName(true).c_str());
                }
             }
 
@@ -2508,10 +2692,12 @@ bool DoBuildDep(CommandLine &CmdL)
             if (_config->FindB("Debug::BuildDeps",false) == true)
                cout << "  Trying to install " << (*D).Package << endl;
 
-            if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
+            if (TryToInstallBuildDep(Pkg,Cache,Fix,false,false) == true)
             {
                // We successfully installed something; skip remaining alternatives
                skipAlternatives = hasAlternatives;
+              if(_config->FindB("APT::Get::Build-Dep-Automatic", false) == true)
+                 Cache->MarkAuto(Pkg, true);
                continue;
             }
             else if (hasAlternatives)
@@ -2536,7 +2722,10 @@ bool DoBuildDep(CommandLine &CmdL)
       
       // Now we check the state of the packages,
       if (Cache->BrokenCount() != 0)
-         return _error->Error(_("Build-dependencies for %s could not be satisfied."),*I);
+      {
+        ShowBroken(cout, Cache, false);
+        return _error->Error(_("Build-dependencies for %s could not be satisfied."),*I);
+      }
    }
   
    if (InstallPackages(Cache, false, true) == false)
@@ -2544,7 +2733,6 @@ bool DoBuildDep(CommandLine &CmdL)
    return true;
 }
                                                                        /*}}}*/
-
 // DoMoo - Never Ask, Never Tell                                       /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -2627,7 +2815,7 @@ bool ShowHelp(CommandLine &CmdL)
       "   install - Install new packages (pkg is libc6 not libc6.deb)\n"
       "   remove - Remove packages\n"
       "   autoremove - Remove automatically all unused packages\n"
-      "   purge - Remove and purge packages\n"
+      "   purge - Remove packages and config files\n"
       "   source - Download source archives\n"
       "   build-dep - Configure build-dependencies for source packages\n"
       "   dist-upgrade - Distribution upgrade, see apt-get(8)\n"
@@ -2635,6 +2823,8 @@ bool ShowHelp(CommandLine &CmdL)
       "   clean - Erase downloaded archive files\n"
       "   autoclean - Erase old downloaded archive files\n"
       "   check - Verify that there are no broken dependencies\n"
+      "   markauto - Mark the given packages as automatically installed\n"
+      "   unmarkauto - Mark the given packages as manually installed\n"
       "\n"
       "Options:\n"
       "  -h  This help text.\n"
@@ -2656,22 +2846,6 @@ bool ShowHelp(CommandLine &CmdL)
    return true;
 }
                                                                        /*}}}*/
-// GetInitialize - Initialize things for apt-get                       /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void GetInitialize()
-{
-   _config->Set("quiet",0);
-   _config->Set("help",false);
-   _config->Set("APT::Get::Download-Only",false);
-   _config->Set("APT::Get::Simulate",false);
-   _config->Set("APT::Get::Assume-Yes",false);
-   _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                                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -2686,8 +2860,7 @@ void SigWinch(int)
 #endif
 }
                                                                        /*}}}*/
-
-int main(int argc,const char *argv[])
+int main(int argc,const char *argv[])                                  /*{{{*/
 {
    CommandLine::Args Args[] = {
       {'h',"help","help",0},
@@ -2714,9 +2887,11 @@ int main(int argc,const char *argv[])
       {0,"fix-missing","APT::Get::Fix-Missing",0},
       {0,"ignore-hold","APT::Ignore-Hold",0},      
       {0,"upgrade","APT::Get::upgrade",0},
+      {0,"only-upgrade","APT::Get::Only-Upgrade",0},
       {0,"force-yes","APT::Get::force-yes",0},
       {0,"print-uris","APT::Get::Print-URIs",0},
       {0,"diff-only","APT::Get::Diff-Only",0},
+      {0,"debian-only","APT::Get::Diff-Only",0},
       {0,"tar-only","APT::Get::Tar-Only",0},
       {0,"dsc-only","APT::Get::Dsc-Only",0},
       {0,"purge","APT::Get::Purge",0},
@@ -2739,7 +2914,8 @@ int main(int argc,const char *argv[])
                                    {"remove",&DoInstall},
                                    {"purge",&DoInstall},
                                   {"autoremove",&DoInstall},
-                                  {"purge",&DoInstall},
+                                  {"markauto",&DoMarkAuto},
+                                  {"unmarkauto",&DoMarkAuto},
                                    {"dist-upgrade",&DoDistUpgrade},
                                    {"dselect-upgrade",&DoDSelectUpgrade},
                                   {"build-dep",&DoBuildDep},
@@ -2776,9 +2952,21 @@ int main(int argc,const char *argv[])
       ShowHelp(CmdL);
       return 0;
    }
-   
+
+   // simulate user-friendly if apt-get has no root privileges
+   if (getuid() != 0 && _config->FindB("APT::Get::Simulate") == true)
+   {
+      if (_config->FindB("APT::Get::Show-User-Simulation-Note",true) == true)
+        cout << _("NOTE: This is only a simulation!\n"
+           "      apt-get needs root privileges for real execution.\n"
+           "      Keep also in mind that locking is deactivated,\n"
+           "      so don't depend on the relevance to the real current situation!"
+        ) << std::endl;
+      _config->Set("Debug::NoLocking",true);
+   }
+
    // Deal with stdout not being a tty
-   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
+   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
       _config->Set("quiet","1");
 
    // Setup the output streams
@@ -2799,12 +2987,11 @@ int main(int argc,const char *argv[])
    CmdL.DispatchArg(Cmds);
 
    // Print any errors or warnings found during parsing
-   if (_error->empty() == false)
-   {
-      bool Errors = _error->PendingError();
+   bool const Errors = _error->PendingError();
+   if (_config->FindI("quiet",0) > 0)
       _error->DumpErrors();
-      return Errors == true?100:0;
-   }
-   
-   return 0;   
+   else
+      _error->DumpErrors(GlobalError::DEBUG);
+   return Errors == true ? 100 : 0;
 }
+                                                                       /*}}}*/