X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/af5a94f4c7b1f2cc797cd1e023e36a1bb359689d..12ea996c64f8085474f5fcbed909e4d2cb7ae798:/cmdline/apt-get.cc

diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index 6979fa8f2..27e16d3f3 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -53,6 +53,7 @@
 #include <termios.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
+#include <sys/statfs.h>
 #include <sys/statvfs.h>
 #include <signal.h>
 #include <unistd.h>
@@ -60,8 +61,11 @@
 #include <errno.h>
 #include <regex.h>
 #include <sys/wait.h>
+#include <sstream>
 									/*}}}*/
 
+#define RAMFS_MAGIC     0x858458f6
+
 using namespace std;
 
 ostream c0out(0);
@@ -628,6 +632,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;
 
@@ -639,12 +645,24 @@ bool CacheFile::CheckDeps(bool AllowBroken)
    if (pkgApplyStatus(*DCache) == false)
       return false;
    
+   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)
@@ -820,16 +838,16 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    if (DebBytes != FetchBytes)
       ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
 	       SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
-   else
+   else if (DebBytes != 0)
       ioprintf(c1out,_("Need to get %sB of archives.\n"),
 	       SizeToStr(DebBytes).c_str());
 
    // Size delta
    if (Cache->UsrSize() >= 0)
-      ioprintf(c1out,_("After unpacking %sB of additional disk space will be used.\n"),
+      ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"),
 	       SizeToStr(Cache->UsrSize()).c_str());
    else
-      ioprintf(c1out,_("After unpacking %sB disk space will be freed.\n"),
+      ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
 	       SizeToStr(-1*Cache->UsrSize()).c_str());
 
    if (_error->PendingError() == true)
@@ -846,8 +864,13 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
 	 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
 			      OutputDir.c_str());
       if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
-	 return _error->Error(_("You don't have enough free space in %s."),
-			      OutputDir.c_str());
+      {
+         struct statfs Stat;
+         if (statfs(OutputDir.c_str(),&Stat) != 0 ||
+			 unsigned(Stat.f_type) != RAMFS_MAGIC)
+            return _error->Error(_("You don't have enough free space in %s."),
+                OutputDir.c_str());
+      }
    }
    
    // Fail safe check
@@ -903,7 +926,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
       for (; I != Fetcher.UriEnd(); I++)
 	 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
-	       I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
+	       I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
       return true;
    }
 
@@ -995,7 +1018,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
 	 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);
@@ -1249,16 +1272,23 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
 	 }
       }   
    }
-   
-   // No source package name..
-   if (Src.empty() == true)
-      Src = TmpSrc;
-   
+
    // The best hit
    pkgSrcRecords::Parser *Last = 0;
    unsigned long Offset = 0;
    string Version;
    bool IsMatch = false;
+   bool MatchSrcOnly = false;
+
+   // 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 we are matching by version then we need exact matches to be happy
    if (VerTag.empty() == false)
@@ -1268,13 +1298,13 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
       binary packages in the search */
    pkgSrcRecords::Parser *Parse;
    SrcRecs.Restart();
-   while ((Parse = SrcRecs.Find(Src.c_str(),false)) != 0)
+   while ((Parse = SrcRecs.Find(Src.c_str(), MatchSrcOnly)) != 0)
    {
       string Ver = Parse->Version();
       
-      // Skip name mismatches
-      if (IsMatch == true && Parse->Package() != Src)
-	 continue;
+      // show name mismatches
+      if (IsMatch == true && Parse->Package() != Src) 
+	 ioprintf(c1out,  _("No source package '%s' picking '%s' instead\n"), Parse->Package().c_str(), Src.c_str());
       
       if (VerTag.empty() == false)
       {
@@ -1328,14 +1358,15 @@ bool DoUpdate(CommandLine &CmdL)
 	 return _error->Error(_("Unable to lock the list directory"));
    }
    
-   // Create the download object
+   // Create the progress
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
-   pkgAcquire Fetcher(&Stat);
-
-   
+      
    // Just print out the uris an exit if the --print-uris flag was used
    if (_config->FindB("APT::Get::Print-URIs") == true)
    {
+      // get a fetcher
+      pkgAcquire Fetcher(&Stat);
+
       // Populate it with the source selection and get all Indexes 
       // (GetAll=true)
       if (List.GetIndexes(&Fetcher,true) == false)
@@ -1344,50 +1375,89 @@ bool DoUpdate(CommandLine &CmdL)
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
       for (; I != Fetcher.UriEnd(); I++)
 	 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
-	       I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
+	       I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
       return true;
    }
 
-   // Populate it with the source selection
-   if (List.GetIndexes(&Fetcher) == false)
-	 return false;
-   
-   // Run it
-   if (Fetcher.Run() == pkgAcquire::Failed)
+   // do the work
+   CacheFile Cache;
+   if (_config->FindB("APT::Get::Download",true) == true)
+       ListUpdate(Stat, List);
+
+   // Rebuild the cache.   
+   if (Cache.BuildCaches() == false)
       return false;
+   
+   return true;
+}
+									/*}}}*/
+// DoAutomaticRemove - Remove all automatic unused packages		/*{{{*/
+// ---------------------------------------------------------------------
+/* Remove unused automatic packages */
+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);
 
-   bool Failed = false;
-   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
+   if(Debug)
+      std::cout << "DoAutomaticRemove()" << std::endl;
+
+   if (_config->FindB("APT::Get::Remove",true) == false &&
+       doAutoRemove == true)
    {
-      if ((*I)->Status == pkgAcquire::Item::StatDone)
-	 continue;
+      c1out << _("We are not supposed to delete stuff, can't start "
+		 "AutoRemover") << std::endl;
+      doAutoRemove = false;
+   }
 
-      (*I)->Finished();
-      
-      fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
-	      (*I)->ErrorText.c_str());
-      Failed = true;
+   string autoremovelist, autoremoveversions;
+   // 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())
+	    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";
+	 }
+	 if (doAutoRemove)
+	 {
+	    if(Pkg.CurrentVer() != 0 && 
+	       Pkg->CurrentState != pkgCache::State::ConfigFiles)
+	       Cache->MarkDelete(Pkg, _config->FindB("APT::Get::Purge", false));
+	    else
+	       Cache->MarkKeep(Pkg, false, false);
+	 }
+      }
    }
-   
-   // Clean out any old list files
-   if (!Failed && _config->FindB("APT::Get::List-Cleanup",true) == true)
+   if (!hideAutoRemove) 
+      ShowList(c1out, _("The following packages were automatically installed and are no longer required:"), autoremovelist, autoremoveversions);
+   if (!doAutoRemove && !hideAutoRemove && autoremovelist.size() > 0)
+      c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
+
+   // Now see if we destroyed anything
+   if (Cache->BrokenCount() != 0)
    {
-      if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
-	  Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
-	 return false;
+      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"));
    }
-   
-   // Prepare the cache.   
-   CacheFile Cache;
-   if (Cache.BuildCaches() == false)
-      return false;
-   
-   if (Failed == true)
-      return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead."));
-   
    return true;
 }
-									/*}}}*/
+
 // DoUpgrade - Upgrade all packages					/*{{{*/
 // ---------------------------------------------------------------------
 /* Upgrade all packages without installing new packages or erasing old
@@ -1408,6 +1478,61 @@ 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 */
@@ -1423,6 +1548,7 @@ 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);
@@ -1430,155 +1556,198 @@ bool DoInstall(CommandLine &CmdL)
    bool DefRemove = false;
    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
       DefRemove = true;
-
-   for (const char **I = CmdL.FileList + 1; *I != 0; I++)
+   else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
    {
-      // 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;
-      while (Cache->FindPkg(S).end() == true)
+      _config->Set("APT::Get::Purge", true);
+      DefRemove = true;
+   }
+   else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
+   {
+      _config->Set("APT::Get::AutomaticRemove", "true");
+      DefRemove = true;
+   }
+   // new scope for the ActionGroup
+   {
+      pkgDepCache::ActionGroup group(Cache);
+      for (const char **I = CmdL.FileList + 1; *I != 0; I++)
       {
-	 // Handle an optional end tag indicating what to do
-	 if (Length >= 1 && S[Length - 1] == '-')
-	 {
-	    Remove = true;
-	    S[--Length] = 0;
+	 // Duplicate the string
+	 unsigned int Length = strlen(*I);
+	 char S[300];
+	 if (Length >= sizeof(S))
 	    continue;
-	 }
-	 
-	 if (Length >= 1 && S[Length - 1] == '+')
+	 strcpy(S,*I);
+      
+	 // See if we are removing and special indicators..
+	 bool Remove = DefRemove;
+	 char *VerTag = 0;
+	 bool VerIsRel = 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;
+         }
+
+	 while (Cache->FindPkg(S).end() == true)
 	 {
-	    Remove = false;
-	    S[--Length] = 0;
-	    continue;
-	 }
+	    // Handle an optional end tag indicating what to do
+	    if (Length >= 1 && S[Length - 1] == '-')
+	    {
+	       Remove = true;
+	       S[--Length] = 0;
+	       continue;
+	    }
 	 
-	 char *Slash = strchr(S,'=');
-	 if (Slash != 0)
-	 {
-	    VerIsRel = false;
-	    *Slash = 0;
-	    VerTag = Slash + 1;
-	 }
+	    if (Length >= 1 && S[Length - 1] == '+')
+	    {
+	       Remove = false;
+	       S[--Length] = 0;
+	       continue;
+	    }
 	 
-	 Slash = strchr(S,'/');
-	 if (Slash != 0)
-	 {
-	    VerIsRel = true;
-	    *Slash = 0;
-	    VerTag = Slash + 1;
-	 }
+	    char *Slash = strchr(S,'=');
+	    if (Slash != 0)
+	    {
+	       VerIsRel = false;
+	       *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);
-
-	 // Regexs must always be confirmed
-	 ExpectedInst += 1000;
+	    Slash = strchr(S,'/');
+	    if (Slash != 0)
+	    {
+	       VerIsRel = true;
+	       *Slash = 0;
+	       VerTag = Slash + 1;
+	    }
 	 
-	 // 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);
+	    break;
 	 }
-	 
-	 // Run over the matches
-	 bool Hit = false;
-	 for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
+      
+	 // Locate the package
+	 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
+	 Packages++;
+	 if (Pkg.end() == true)
 	 {
-	    if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
-	       continue;
+	    // 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);
+
+	    // 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);
 	    
-	    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);
+	 }
+	 else
+	 {
 	    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);
-      }
-      else
-      {
-	 if (VerTag != 0)
-	    if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
+	    if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
 	       return false;
-	 if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
-	    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;
-      ShowBroken(c1out,Cache,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++;
+	    }
+	 }      
+      }
 
-      return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
-   }
+      /* 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;
+	 ShowBroken(c1out,Cache,false);
+
+	 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
+      }
    
-   // Call the scored problem resolver
-   Fix.InstallProtect();
-   if (Fix.Resolve(true) == false)
-      _error->Discard();
+      // Call the scored problem resolver
+      Fix.InstallProtect();
+      if (Fix.Resolve(true) == false)
+	 _error->Discard();
 
-   // Now we check the state of the packages,
-   if (Cache->BrokenCount() != 0)
-   {
-      c1out << 
-       _("Some packages could not be installed. This may mean that you have\n" 
-	 "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)
+      // Now we check the state of the packages,
+      if (Cache->BrokenCount() != 0)
       {
-	 c1out << endl;
 	 c1out << 
-	  _("Since you only requested a single operation it is extremely likely that\n"
-	    "the package is simply not installable and a bug report against\n" 
-	    "that package should be filed.") << endl;
-      }
+	    _("Some packages could not be installed. This may mean that you have\n" 
+	      "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;
+	    c1out << 
+	       _("Since you only requested a single operation it is extremely likely that\n"
+		 "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;
+	 ShowBroken(c1out,Cache,false);
+	 return _error->Error(_("Broken packages"));
+      }   
+   }
+   if (!DoAutomaticRemove(Cache)) 
+      return false;
 
-      c1out << _("The following information may help to resolve the situation:") << endl;
-      c1out << endl;
-      ShowBroken(c1out,Cache,false);
-      return _error->Error(_("Broken packages"));
-   }   
-   
    /* Print out a list of packages that are going to be installed extra
       to what the user asked */
    if (Cache->InstCount() != ExpectedInst)
@@ -1598,8 +1767,8 @@ bool DoInstall(CommandLine &CmdL)
 	 
 	 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);
@@ -1611,73 +1780,99 @@ bool DoInstall(CommandLine &CmdL)
       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);
 
    }
 
+   // 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 &&
+       Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
+       Cache->BadCount() == 0)
+      Cache->writeStateFile(NULL);
+
    // See if we need to prompt
    if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
       return InstallPackages(Cache,false,false);
@@ -1716,6 +1911,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++)
@@ -1934,6 +2131,11 @@ bool DoSource(CommandLine &CmdL)
 	     I->Type != "tar")
 	    continue;
 
+	 // Dsc only mode only fetches .dsc files
+	 if (_config->FindB("APT::Get::Dsc-Only",false) == true &&
+	     I->Type != "dsc")
+	    continue;
+
 	 // don't download the same uri twice (should this be moved to
 	 // the fetcher interface itself?)
 	 if(queued.find(Last->Index().ArchiveURI(I->Path)) != queued.end())
@@ -1973,8 +2175,13 @@ bool DoSource(CommandLine &CmdL)
       return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
 			   OutputDir.c_str());
    if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
-      return _error->Error(_("You don't have enough free space in %s"),
-			   OutputDir.c_str());
+     {
+       struct statfs Stat;
+       if (statfs(OutputDir.c_str(),&Stat) != 0 || 
+           unsigned(Stat.f_type) != RAMFS_MAGIC) 
+          return _error->Error(_("You don't have enough free space in %s"),
+              OutputDir.c_str());
+      }
    
    // Number of bytes
    if (DebBytes != FetchBytes)
@@ -1997,7 +2204,7 @@ bool DoSource(CommandLine &CmdL)
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
       for (; I != Fetcher.UriEnd(); I++)
 	 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
-	       I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
+	       I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
       return true;
    }
    
@@ -2257,6 +2464,7 @@ bool DoBuildDep(CommandLine &CmdL)
                            break;
                  }
                  if (CV.end() == true)
+		 {
 		   if (hasAlternatives)
 		   {
 		      continue;
@@ -2269,6 +2477,7 @@ bool DoBuildDep(CommandLine &CmdL)
                                            Last->BuildDepType((*D).Type),Src.c_str(),
                                            (*D).Package.c_str());
 		   }
+		 }
             }
             else
             {
@@ -2313,6 +2522,8 @@ bool DoBuildDep(CommandLine &CmdL)
             {
                // We successfully installed something; skip remaining alternatives
                skipAlternatives = hasAlternatives;
+	       if(_config->FindB("APT::Get::Build-Dep-Automatic", true) == true)
+		  Cache->MarkAuto(Pkg, true);
                continue;
             }
             else if (hasAlternatives)
@@ -2368,8 +2579,8 @@ bool DoMoo(CommandLine &CmdL)
 /* */
 bool ShowHelp(CommandLine &CmdL)
 {
-   ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
-	    COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
+   ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION,
+	    COMMON_ARCH,__DATE__,__TIME__);
 	    
    if (_config->FindB("version") == true)
    {
@@ -2427,6 +2638,8 @@ bool ShowHelp(CommandLine &CmdL)
       "   upgrade - Perform an upgrade\n"
       "   install - Install new packages (pkg is libc6 not libc6.deb)\n"
       "   remove - Remove packages\n"
+      "   autoremove - Remove automatically all unused 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"
@@ -2442,7 +2655,7 @@ bool ShowHelp(CommandLine &CmdL)
       "  -d  Download only - do NOT install or unpack archives\n"
       "  -s  No-act. Perform ordering simulation\n"
       "  -y  Assume Yes to all queries and do not prompt\n"
-      "  -f  Attempt to continue if the integrity check fails\n"
+      "  -f  Attempt to correct a system with broken dependencies in place\n"
       "  -m  Attempt to continue if archives are unlocatable\n"
       "  -u  Show a list of upgraded packages as well\n"
       "  -b  Build the source package after fetching it\n"
@@ -2468,6 +2681,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				/*{{{*/
@@ -2515,7 +2729,8 @@ int main(int argc,const char *argv[])
       {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,"tar-only","APT::Get::tar-Only",0},
+      {0,"tar-only","APT::Get::Tar-Only",0},
+      {0,"dsc-only","APT::Get::Dsc-Only",0},
       {0,"purge","APT::Get::Purge",0},
       {0,"list-cleanup","APT::Get::List-Cleanup",0},
       {0,"reinstall","APT::Get::ReInstall",0},
@@ -2523,7 +2738,11 @@ 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,"build-dep-automatic","APT::Get::Build-Dep-Automatic",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}};
@@ -2531,6 +2750,9 @@ int main(int argc,const char *argv[])
                                    {"upgrade",&DoUpgrade},
                                    {"install",&DoInstall},
                                    {"remove",&DoInstall},
+                                   {"purge",&DoInstall},
+				   {"autoremove",&DoInstall},
+				   {"purge",&DoInstall},
                                    {"dist-upgrade",&DoDistUpgrade},
                                    {"dselect-upgrade",&DoDSelectUpgrade},
 				   {"build-dep",&DoBuildDep},