]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-get.cc
Minimal CD swaps
[apt.git] / cmdline / apt-get.cc
index 1ee47e8c4554be1533175f9e7a1a30384cfdf4aa..92efd1b1e6d5ddca31d66ed345c8cdcf80695654 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: apt-get.cc,v 1.71 1999/07/12 04:39:37 jgg Exp $
+// $Id: apt-get.cc,v 1.95 2000/01/14 06:26:37 jgg Exp $
 /* ######################################################################
    
    apt-get - Cover for dpkg
 /* ######################################################################
    
    apt-get - Cover for dpkg
 #include <termios.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <termios.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
-#include <sys/vfs.h>
+#include <sys/statvfs.h>
 #include <signal.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <errno.h>
+#include <regex.h>
 #include <sys/wait.h>
                                                                        /*}}}*/
 
 #include <sys/wait.h>
                                                                        /*}}}*/
 
@@ -154,7 +155,7 @@ bool ShowList(ostream &out,string Title,string List)
 /* This prints out the names of all the packages that are broken along
    with the name of each each broken dependency and a quite version 
    description. */
 /* This prints out the names of all the packages that are broken along
    with the name of each each broken dependency and a quite version 
    description. */
-void ShowBroken(ostream &out,CacheFile &Cache)
+void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
 {
    out << "Sorry, but the following packages have unmet dependencies:" << endl;
    for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
 {
    out << "Sorry, but the following packages have unmet dependencies:" << endl;
    for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
@@ -166,7 +167,7 @@ void ShowBroken(ostream &out,CacheFile &Cache)
          
       // Print out each package and the failed dependencies
       out <<"  " <<  I.Name() << ":";
          
       // Print out each package and the failed dependencies
       out <<"  " <<  I.Name() << ":";
-      int Indent = strlen(I.Name()) + 3;
+      unsigned Indent = strlen(I.Name()) + 3;
       bool First = true;
       if (Cache[I].InstVerIter(Cache).end() == true)
       {
       bool First = true;
       if (Cache[I].InstVerIter(Cache).end() == true)
       {
@@ -184,44 +185,62 @@ void ShowBroken(ostream &out,CacheFile &Cache)
         if (Cache->IsImportantDep(End) == false || 
             (Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
            continue;
         if (Cache->IsImportantDep(End) == false || 
             (Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
            continue;
-        
-        if (First == false)
-           for (int J = 0; J != Indent; J++)
-              out << ' ';
-        First = false;
 
 
-        out << ' ' << End.DepType() << ": " << End.TargetPkg().Name();
-        
-        // Show a quick summary of the version requirements
-        if (End.TargetVer() != 0)
-           out << " (" << End.CompType() << " " << End.TargetVer() << 
-           ")";
-        
-        /* Show a summary of the target package if possible. In the case
-         of virtual packages we show nothing */
-        
-        pkgCache::PkgIterator Targ = End.TargetPkg();
-        if (Targ->ProvidesList == 0)
+        bool FirstOr = true;
+        while (1)
         {
         {
-           out << " but ";
-           pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
-           if (Ver.end() == false)
-              out << Ver.VerStr() << " is installed";
+           if (First == false)
+              for (unsigned J = 0; J != Indent; J++)
+                 out << ' ';
+           First = false;
+
+           if (FirstOr == false)
+           {
+              for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
+                 out << ' ';
+           }
            else
            else
+              out << ' ' << End.DepType() << ": ";
+           FirstOr = false;
+           
+           out << Start.TargetPkg().Name();
+        
+           // Show a quick summary of the version requirements
+           if (Start.TargetVer() != 0)
+              out << " (" << Start.CompType() << " " << Start.TargetVer() << 
+              ")";
+           
+           /* Show a summary of the target package if possible. In the case
+              of virtual packages we show nothing */    
+           pkgCache::PkgIterator Targ = Start.TargetPkg();
+           if (Targ->ProvidesList == 0)
            {
            {
-              if (Cache[Targ].CandidateVerIter(Cache).end() == true)
+              out << " but ";
+              pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
+              if (Ver.end() == false)
+                 out << Ver.VerStr() << (Now?" is installed":" is to be installed");
+              else
               {
               {
-                 if (Targ->ProvidesList == 0)
-                    out << "it is not installable";
+                 if (Cache[Targ].CandidateVerIter(Cache).end() == true)
+                 {
+                    if (Targ->ProvidesList == 0)
+                       out << "it is not installable";
+                    else
+                       out << "it is a virtual package";
+                 }               
                  else
                  else
-                    out << "it is a virtual package";
-              }                  
-              else
-                 out << "it is not installed";
-           }          
-        }
-        
-        out << endl;
+                    out << (Now?"it is not installed":"it is not going to be installed");
+              }               
+           }
+           
+           if (Start != End)
+              cout << " or";
+           out << endl;
+           
+           if (Start == End)
+              break;
+           Start++;
+        }       
       }            
    }   
 }
       }            
    }   
 }
@@ -270,15 +289,16 @@ void ShowDel(ostream &out,CacheFile &Cache)
 // ShowKept - Show kept packages                                       /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // ShowKept - Show kept packages                                       /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void ShowKept(ostream &out,pkgDepCache &Dep)
+void ShowKept(ostream &out,CacheFile &Cache)
 {
 {
-   pkgCache::PkgIterator I = Dep.PkgBegin();
    string List;
    string List;
-   for (;I.end() != true; I++)
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
    {    
    {    
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      
       // Not interesting
       // Not interesting
-      if (Dep[I].Upgrade() == true || Dep[I].Upgradable() == false ||
-         I->CurrentVer == 0 || Dep[I].Delete() == true)
+      if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false ||
+         I->CurrentVer == 0 || Cache[I].Delete() == true)
         continue;
       
       List += string(I.Name()) + " ";
         continue;
       
       List += string(I.Name()) + " ";
@@ -388,6 +408,7 @@ void Stats(ostream &out,pkgDepCache &Dep)
 {
    unsigned long Upgrade = 0;
    unsigned long Install = 0;
 {
    unsigned long Upgrade = 0;
    unsigned long Install = 0;
+   unsigned long ReInstall = 0;
    for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
    {
       if (Dep[I].NewInstall() == true)
    for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
    {
       if (Dep[I].NewInstall() == true)
@@ -395,11 +416,15 @@ void Stats(ostream &out,pkgDepCache &Dep)
       else
         if (Dep[I].Upgrade() == true)
            Upgrade++;
       else
         if (Dep[I].Upgrade() == true)
            Upgrade++;
+      if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
+        ReInstall++;
    }   
 
    out << Upgrade << " packages upgraded, " << 
    }   
 
    out << Upgrade << " packages upgraded, " << 
-      Install << " newly installed, " <<
-      Dep.DelCount() << " to remove and " << 
+      Install << " newly installed, ";
+   if (ReInstall != 0)
+      out << ReInstall << " reinstalled, ";
+   out << Dep.DelCount() << " to remove and " << 
       Dep.KeepCount() << " not upgraded." << endl;
 
    if (Dep.BadCount() != 0)
       Dep.KeepCount() << " not upgraded." << endl;
 
    if (Dep.BadCount() != 0)
@@ -413,12 +438,8 @@ void Stats(ostream &out,pkgDepCache &Dep)
 pkgCache *CacheFile::SortCache = 0;
 int CacheFile::NameComp(const void *a,const void *b)
 {
 pkgCache *CacheFile::SortCache = 0;
 int CacheFile::NameComp(const void *a,const void *b)
 {
-   if (a == 0 && b == 0)
-      return 0;
-   if (a == 0)
-      return -1;
-   if (b == 0)
-      return 1;
+   if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0)
+      return *(pkgCache::Package **)a - *(pkgCache::Package **)b;
    
    const pkgCache::Package &A = **(pkgCache::Package **)a;
    const pkgCache::Package &B = **(pkgCache::Package **)b;
    
    const pkgCache::Package &A = **(pkgCache::Package **)a;
    const pkgCache::Package &B = **(pkgCache::Package **)b;
@@ -470,7 +491,7 @@ bool CacheFile::CheckDeps(bool AllowBroken)
       if (pkgFixBroken(*Cache) == false || Cache->BrokenCount() != 0)
       {
         c1out << " failed." << endl;
       if (pkgFixBroken(*Cache) == false || Cache->BrokenCount() != 0)
       {
         c1out << " failed." << endl;
-        ShowBroken(c1out,*this);
+        ShowBroken(c1out,*this,true);
 
         return _error->Error("Unable to correct dependencies");
       }
 
         return _error->Error("Unable to correct dependencies");
       }
@@ -482,7 +503,7 @@ bool CacheFile::CheckDeps(bool AllowBroken)
    else
    {
       c1out << "You might want to run `apt-get -f install' to correct these." << endl;
    else
    {
       c1out << "You might want to run `apt-get -f install' to correct these." << endl;
-      ShowBroken(c1out,*this);
+      ShowBroken(c1out,*this,true);
 
       return _error->Error("Unmet dependencies. Try using -f.");
    }
 
       return _error->Error("Unmet dependencies. Try using -f.");
    }
@@ -495,7 +516,8 @@ bool CacheFile::CheckDeps(bool AllowBroken)
 // ---------------------------------------------------------------------
 /* This displays the informative messages describing what is going to 
    happen and then calls the download routines */
 // ---------------------------------------------------------------------
 /* This displays the informative messages describing what is going to 
    happen and then calls the download routines */
-bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = true)
+bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
+                    bool Saftey = true)
 {
    if (_config->FindB("APT::Get::Purge",false) == true)
    {
 {
    if (_config->FindB("APT::Get::Purge",false) == true)
    {
@@ -525,14 +547,18 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
    // Sanity check
    if (Cache->BrokenCount() != 0)
    {
    // Sanity check
    if (Cache->BrokenCount() != 0)
    {
-      ShowBroken(c1out,Cache);
+      ShowBroken(c1out,Cache,false);
       return _error->Error("Internal Error, InstallPackages was called with broken packages!");
    }
 
       return _error->Error("Internal Error, InstallPackages was called with broken packages!");
    }
 
-   if (Cache->DelCount() == 0 && Cache->InstCount() == 0 && 
+   if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
        Cache->BadCount() == 0)
       return true;
 
        Cache->BadCount() == 0)
       return true;
 
+   // No remove flag
+   if (Cache->DelCount() != 0 && _config->FindB("APT::Get::No-Remove",false) == true)
+      return _error->Error("Packages need to be removed but No Remove was specified.");
+       
    // Run the simulator ..
    if (_config->FindB("APT::Get::Simulate") == true)
    {
    // Run the simulator ..
    if (_config->FindB("APT::Get::Simulate") == true)
    {
@@ -583,16 +609,6 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
       c0out << DebBytes << ',' << Cache->DebSize() << endl;
       c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
    }
       c0out << DebBytes << ',' << Cache->DebSize() << endl;
       c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
    }
-
-   // Check for enough free space
-   struct statfs Buf;
-   string OutputDir = _config->FindDir("Dir::Cache::Archives");
-   if (statfs(OutputDir.c_str(),&Buf) != 0)
-      return _error->Errno("statfs","Couldn't determine free space in %s",
-                          OutputDir.c_str());
-   if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
-      return _error->Error("Sorry, you don't have enough free space in %s",
-                          OutputDir.c_str());
    
    // Number of bytes
    c1out << "Need to get ";
    
    // Number of bytes
    c1out << "Need to get ";
@@ -612,6 +628,16 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
    if (_error->PendingError() == true)
       return false;
 
    if (_error->PendingError() == true)
       return false;
 
+   // Check for enough free space
+   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)
+      return _error->Error("Sorry, you don't have enough free space in %s to hold all the .debs.",
+                          OutputDir.c_str());
+
    // Fail safe check
    if (_config->FindI("quiet",0) >= 2 ||
        _config->FindB("APT::Get::Assume-Yes",false) == true)
    // Fail safe check
    if (_config->FindI("quiet",0) >= 2 ||
        _config->FindB("APT::Get::Assume-Yes",false) == true)
@@ -622,6 +648,9 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
 
    if (Essential == true && Saftey == true)
    {
 
    if (Essential == true && Saftey == true)
    {
+      if (_config->FindB("APT::Get::Trivial-Only",false) == true)
+        return _error->Error("Trivial Only specified but this is not a trivial operation.");
+      
       c2out << "You are about to do something potentially harmful" << endl;
       c2out << "To continue type in the phrase 'Yes, I understand this may be bad'" << endl;
       c2out << " ?] " << flush;
       c2out << "You are about to do something potentially harmful" << endl;
       c2out << "To continue type in the phrase 'Yes, I understand this may be bad'" << endl;
       c2out << " ?] " << flush;
@@ -632,10 +661,13 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
       }     
    }
    else
       }     
    }
    else
-   {
+   {      
       // Prompt to continue
       if (Ask == true || Fail == true)
       {            
       // Prompt to continue
       if (Ask == true || Fail == true)
       {            
+        if (_config->FindB("APT::Get::Trivial-Only",false) == true)
+           return _error->Error("Trivial Only specified but this is not a trivial operation.");
+        
         if (_config->FindI("quiet",0) < 2 &&
             _config->FindB("APT::Get::Assume-Yes",false) == false)
         {
         if (_config->FindI("quiet",0) < 2 &&
             _config->FindB("APT::Get::Assume-Yes",false) == false)
         {
@@ -663,32 +695,60 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
    // Run it
    while (1)
    {
    // Run it
    while (1)
    {
-      if (_config->FindB("APT::Get::No-Download",false) == false)
-        if( Fetcher.Run() == pkgAcquire::Failed)
-           return false;
+      bool Transient = false;
+      if (_config->FindB("APT::Get::No-Download",false) == true)
+      {
+        for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
+        {
+           if ((*I)->Local == true)
+           {
+              I++;
+              continue;
+           }
+
+           // Close the item and check if it was found in cache
+           (*I)->Finished();
+           if ((*I)->Complete == false)
+              Transient = true;
+           
+           // Clear it out of the fetch list
+           delete *I;
+           I = Fetcher.ItemsBegin();
+        }       
+      }
+      
+      if (Fetcher.Run() == pkgAcquire::Failed)
+        return false;
       
       // Print out errors
       bool Failed = false;
       
       // Print out errors
       bool Failed = false;
-      bool Transient = false;
       for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
       {
         if ((*I)->Status == pkgAcquire::Item::StatDone &&
             (*I)->Complete == true)
            continue;
         
       for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
       {
         if ((*I)->Status == pkgAcquire::Item::StatDone &&
             (*I)->Complete == true)
            continue;
         
-        (*I)->Finished();
-        
         if ((*I)->Status == pkgAcquire::Item::StatIdle)
         {
            Transient = true;
            // Failed = true;
            continue;
         }
         if ((*I)->Status == pkgAcquire::Item::StatIdle)
         {
            Transient = true;
            // Failed = true;
            continue;
         }
-        
+
         cerr << "Failed to fetch " << (*I)->DescURI() << endl;
         cerr << "  " << (*I)->ErrorText << endl;
         Failed = true;
       }
         cerr << "Failed to fetch " << (*I)->DescURI() << endl;
         cerr << "  " << (*I)->ErrorText << endl;
         Failed = true;
       }
+
+      /* If we are in no download mode and missing files and there were
+         'failures' then the user must specify -m. Furthermore, there 
+         is no such thing as a transient error in no-download mode! */
+      if (Transient == true &&
+         _config->FindB("APT::Get::No-Download",false) == true)
+      {
+        Transient = false;
+        Failed = true;
+      }
       
       if (_config->FindB("APT::Get::Download-Only",false) == true)
       {
       
       if (_config->FindB("APT::Get::Download-Only",false) == true)
       {
@@ -699,12 +759,6 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
       
       if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
       {
       
       if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
       {
-        /*if (Transient == true)
-        {
-           c2out << "Upgrading with disk swapping is not supported in this version." << endl;
-           c2out << "Try running multiple times with --fix-missing" << endl;
-        }*/
-        
         return _error->Error("Unable to fetch some archives, maybe try with --fix-missing?");
       }
       
         return _error->Error("Unable to fetch some archives, maybe try with --fix-missing?");
       }
       
@@ -717,7 +771,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
         cerr << "Unable to correct missing packages." << endl;
         return _error->Error("Aborting Install.");
       }
         cerr << "Unable to correct missing packages." << endl;
         return _error->Error("Aborting Install.");
       }
-      
+                
       Cache.ReleaseLock();
       pkgPackageManager::OrderResult Res = PM.DoInstall();
       if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
       Cache.ReleaseLock();
       pkgPackageManager::OrderResult Res = PM.DoInstall();
       if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
@@ -732,6 +786,124 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
    }   
 }
                                                                        /*}}}*/
    }   
 }
                                                                        /*}}}*/
+// TryToInstall - 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,
+                 pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
+                 unsigned int &ExpectedInst,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();
+      c1out << "Note, selecting " << Tmp.Name() << " instead of " << Pkg.Name() << endl;
+      Pkg = Tmp;
+   }
+   
+   // Handle the no-upgrade case
+   if (_config->FindB("APT::Get::no-upgrade",false) == true &&
+       Pkg->CurrentVer != 0)
+   {
+      if (AllowFail == true)
+        c1out << "Skipping " << Pkg.Name() << ", it is already installed and no-upgrade is set." << endl;
+      return true;
+   }
+   
+   // Check if there is something at all to install
+   pkgDepCache::StateCache &State = Cache[Pkg];
+   if (Remove == true && Pkg->CurrentVer == 0)
+   {
+      if (AllowFail == false)
+        return false;
+      return _error->Error("Package %s is not installed",Pkg.Name());
+   }
+   
+   if (State.CandidateVer == 0 && Remove == false)
+   {
+      if (AllowFail == false)
+        return false;
+      
+      if (Pkg->ProvidesList != 0)
+      {
+        c1out << "Package " << Pkg.Name() << " is a virtual package provided by:" << endl;
+        
+        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
+      {
+        c1out << "Package " << Pkg.Name() << " has no available version, but exists in the database." << endl;
+        c1out << "This typically means that the package was mentioned in a dependency and " << endl;
+        c1out << "never uploaded, has been obsoleted or is not available with the contents " << endl;
+        c1out << "of sources.list" << endl;
+        
+        string List;
+        pkgCache::DepIterator Dep = Pkg.RevDependsList();
+        for (; Dep.end() == false; Dep++)
+        {
+           if (Dep->Type != pkgCache::Dep::Replaces)
+              continue;
+           List += string(Dep.ParentPkg().Name()) + " ";
+        }          
+        ShowList(c1out,"However the following packages replace it:",List);
+      }
+      
+      _error->Error("Package %s has no installation candidate",Pkg.Name());
+      return false;
+   }
+
+   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)
+           c1out << "Sorry, re-installation of " << Pkg.Name() << " is not possible, it cannot be downloaded" << endl;
+        else
+           Cache.SetReInstall(Pkg,true);
+      }      
+      else
+      {
+        if (AllowFail == true)
+           c1out << "Sorry, " << Pkg.Name() << " is already the newest version"  << endl;
+      }      
+   }   
+   else
+      ExpectedInst++;
+   
+   // Install it with autoinstalling enabled.
+   if (State.InstBroken() == true && BrokenFix == false)
+      Cache.MarkInstall(Pkg,true);
+   return true;
+}
+                                                                       /*}}}*/
 
 // DoUpdate - Update the package lists                                 /*{{{*/
 // ---------------------------------------------------------------------
 
 // DoUpdate - Update the package lists                                 /*{{{*/
 // ---------------------------------------------------------------------
@@ -777,11 +949,13 @@ bool DoUpdate(CommandLine &)
 
       (*I)->Finished();
       
 
       (*I)->Finished();
       
+      cerr << "Failed to fetch " << (*I)->DescURI() << endl;
+      cerr << "  " << (*I)->ErrorText << endl;
       Failed = true;
    }
    
    // Clean out any old list files
       Failed = true;
    }
    
    // Clean out any old list files
-   if (_config->FindB("APT::Get::List-Cleanup",false) == false)
+   if (_config->FindB("APT::Get::List-Cleanup",true) == true)
    {
       if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
          Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
    {
       if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
          Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
@@ -811,7 +985,7 @@ bool DoUpgrade(CommandLine &CmdL)
    // Do the upgrade
    if (pkgAllUpgrade(Cache) == false)
    {
    // Do the upgrade
    if (pkgAllUpgrade(Cache) == false)
    {
-      ShowBroken(c1out,Cache);
+      ShowBroken(c1out,Cache,false);
       return _error->Error("Internal Error, AllUpgrade broke stuff");
    }
    
       return _error->Error("Internal Error, AllUpgrade broke stuff");
    }
    
@@ -874,78 +1048,44 @@ bool DoInstall(CommandLine &CmdL)
       pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
       Packages++;
       if (Pkg.end() == true)
       pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
       Packages++;
       if (Pkg.end() == true)
-        return _error->Error("Couldn't find package %s",S);
-      
-      // Handle the no-upgrade case
-      if (_config->FindB("APT::Get::no-upgrade",false) == true &&
-         Pkg->CurrentVer != 0)
-      {
-        c1out << "Skipping " << Pkg.Name() << ", it is already installed and no-upgrade is set." << endl;
-        continue;
-      }
-      
-      // Check if there is something new to install
-      pkgDepCache::StateCache &State = (*Cache)[Pkg];
-      if (State.CandidateVer == 0)
       {
       {
-        if (Pkg->ProvidesList != 0)
-        {
-           c1out << "Package " << S << " is a virtual package provided by:" << endl;
-
-           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 explicly select one to install." << endl;
-        }
-        else
+        // Check if the name is a regex
+        const char *I;
+        for (I = S; *I != 0; I++)
+           if (*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;
+        if (regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE | 
+                    REG_NOSUB) != 0)
+           return _error->Error("Regex compilation error");
+        
+        // Run over the matches
+        bool Hit = false;
+        for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
         {
         {
-           c1out << "Package " << S << " has no available version, but exists in the database." << endl;
-           c1out << "This typically means that the package was mentioned in a dependency and " << endl;
-           c1out << "never uploaded, or that it is an obsolete package." << endl;
+           if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
+              continue;
            
            
-           string List;
-           pkgCache::DepIterator Dep = Pkg.RevDependsList();
-           for (; Dep.end() == false; Dep++)
-           {
-              if (Dep->Type != pkgCache::Dep::Replaces)
-                 continue;
-              List += string(Dep.ParentPkg().Name()) + " ";
-           }       
-           ShowList(c1out,"However the following packages replace it:",List);
+           Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
+                               ExpectedInst,false);
         }
         }
+        regfree(&Pattern);
         
         
-        return _error->Error("Package %s has no installation candidate",S);
+        if (Hit == false)
+           return _error->Error("Couldn't find package %s",S);
       }
       }
-      
-      Fix.Protect(Pkg);
-      if (Remove == true)
-      {
-        Fix.Remove(Pkg);
-        Cache->MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
-        continue;
-      }
-      
-      // Install it
-      Cache->MarkInstall(Pkg,false);
-      if (State.Install() == false)
-        c1out << "Sorry, " << S << " is already the newest version"  << endl;
       else
       else
-        ExpectedInst++;
-
-      // Install it with autoinstalling enabled.
-      if (State.InstBroken() == true && BrokenFix == false)
-        Cache->MarkInstall(Pkg,true);
+      {
+        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
    }
 
    /* If we are in the Broken fixing mode we do not attempt to fix the
@@ -954,7 +1094,7 @@ bool DoInstall(CommandLine &CmdL)
    if (BrokenFix == true && Cache->BrokenCount() != 0)
    {
       c1out << "You might want to run `apt-get -f install' to correct these:" << endl;
    if (BrokenFix == true && Cache->BrokenCount() != 0)
    {
       c1out << "You might want to run `apt-get -f install' to correct these:" << endl;
-      ShowBroken(c1out,Cache);
+      ShowBroken(c1out,Cache,false);
 
       return _error->Error("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).");
    }
 
       return _error->Error("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).");
    }
@@ -981,7 +1121,7 @@ bool DoInstall(CommandLine &CmdL)
 
       c1out << "The following information may help to resolve the situation:" << endl;
       c1out << endl;
 
       c1out << "The following information may help to resolve the situation:" << endl;
       c1out << endl;
-      ShowBroken(c1out,Cache);
+      ShowBroken(c1out,Cache,false);
       return _error->Error("Sorry, broken packages");
    }   
    
       return _error->Error("Sorry, broken packages");
    }   
    
@@ -1028,7 +1168,7 @@ bool DoDistUpgrade(CommandLine &CmdL)
    if (pkgDistUpgrade(*Cache) == false)
    {
       c0out << "Failed" << endl;
    if (pkgDistUpgrade(*Cache) == false)
    {
       c0out << "Failed" << endl;
-      ShowBroken(c1out,Cache);
+      ShowBroken(c1out,Cache,false);
       return false;
    }
    
       return false;
    }
    
@@ -1096,7 +1236,7 @@ bool DoDSelectUpgrade(CommandLine &CmdL)
    
       if (Fix.Resolve() == false)
       {
    
       if (Fix.Resolve() == false)
       {
-        ShowBroken(c1out,Cache);
+        ShowBroken(c1out,Cache,false);
         return _error->Error("Internal Error, problem resolver broke stuff");
       }
    }
         return _error->Error("Internal Error, problem resolver broke stuff");
       }
    }
@@ -1104,7 +1244,7 @@ bool DoDSelectUpgrade(CommandLine &CmdL)
    // Now upgrade everything
    if (pkgAllUpgrade(Cache) == false)
    {
    // Now upgrade everything
    if (pkgAllUpgrade(Cache) == false)
    {
-      ShowBroken(c1out,Cache);
+      ShowBroken(c1out,Cache,false);
       return _error->Error("Internal Error, problem resolver broke stuff");
    }
    
       return _error->Error("Internal Error, problem resolver broke stuff");
    }
    
@@ -1116,6 +1256,22 @@ bool DoDSelectUpgrade(CommandLine &CmdL)
 /* */
 bool DoClean(CommandLine &CmdL)
 {
 /* */
 bool DoClean(CommandLine &CmdL)
 {
+   if (_config->FindB("APT::Get::Simulate") == true)
+   {
+      cout << "Del " << _config->FindDir("Dir::Cache::archives") << "* " <<
+        _config->FindDir("Dir::Cache::archives") << "partial/*" << endl;
+      return true;
+   }
+   
+   // Lock the archive directory
+   FileFd Lock;
+   if (_config->FindB("Debug::NoLocking",false) == false)
+   {
+      Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
+      if (_error->PendingError() == true)
+        return _error->Error("Unable to lock the download directory");
+   }
+   
    pkgAcquire Fetcher;
    Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
    Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
    pkgAcquire Fetcher;
    Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
    Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
@@ -1140,6 +1296,15 @@ class LogCleaner : public pkgArchiveCleaner
 
 bool DoAutoClean(CommandLine &CmdL)
 {
 
 bool DoAutoClean(CommandLine &CmdL)
 {
+   // Lock the archive directory
+   FileFd Lock;
+   if (_config->FindB("Debug::NoLocking",false) == false)
+   {
+      Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
+      if (_error->PendingError() == true)
+        return _error->Error("Unable to lock the download directory");
+   }
+   
    CacheFile Cache;
    if (Cache.Open() == false)
       return false;
    CacheFile Cache;
    if (Cache.Open() == false)
       return false;
@@ -1280,6 +1445,16 @@ bool DoSource(CommandLine &CmdL)
         if (I->Path.find(".diff.gz") != string::npos)
            Comp = "diff";
         
         if (I->Path.find(".diff.gz") != string::npos)
            Comp = "diff";
         
+        // Diff only mode only fetches .diff files
+        if (_config->FindB("APT::Get::Diff-Only",false) == true &&
+            Comp != "diff")
+           continue;
+        
+        // Tar only mode only fetches .tar files
+        if (_config->FindB("APT::Get::Tar-Only",false) == true &&
+            Comp != "tar")
+           continue;
+        
         new pkgAcqFile(&Fetcher,Last->Source()->ArchiveURI(I->Path),
                        I->MD5Hash,I->Size,Last->Source()->SourceInfo(Src,
                        Last->Version(),Comp),Src);
         new pkgAcqFile(&Fetcher,Last->Source()->ArchiveURI(I->Path),
                        I->MD5Hash,I->Size,Last->Source()->SourceInfo(Src,
                        Last->Version(),Comp),Src);
@@ -1292,10 +1467,10 @@ bool DoSource(CommandLine &CmdL)
    unsigned long DebBytes = Fetcher.TotalNeeded();
 
    // Check for enough free space
    unsigned long DebBytes = Fetcher.TotalNeeded();
 
    // Check for enough free space
-   struct statfs Buf;
+   struct statvfs Buf;
    string OutputDir = ".";
    string OutputDir = ".";
-   if (statfs(OutputDir.c_str(),&Buf) != 0)
-      return _error->Errno("statfs","Couldn't determine free space in %s",
+   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)
       return _error->Error("Sorry, you don't have enough free space in %s",
                           OutputDir.c_str());
    if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
       return _error->Error("Sorry, you don't have enough free space in %s",
@@ -1357,6 +1532,12 @@ bool DoSource(CommandLine &CmdL)
       {
         string Dir = Dsc[I].Package + '-' + pkgBaseVersion(Dsc[I].Version.c_str());
         
       {
         string Dir = Dsc[I].Package + '-' + pkgBaseVersion(Dsc[I].Version.c_str());
         
+        // Diff only mode only fetches .diff files
+        if (_config->FindB("APT::Get::Diff-Only",false) == true ||
+            _config->FindB("APT::Get::Tar-Only",false) == true ||
+            Dsc[I].Dsc.empty() == true)
+           continue;
+
         // See if the package is already unpacked
         struct stat Stat;
         if (stat(Dir.c_str(),&Stat) == 0 &&
         // See if the package is already unpacked
         struct stat Stat;
         if (stat(Dir.c_str(),&Stat) == 0 &&
@@ -1502,11 +1683,11 @@ int main(int argc,const char *argv[])
       {'d',"download-only","APT::Get::Download-Only",0},
       {'b',"compile","APT::Get::Compile",0},
       {'b',"build","APT::Get::Compile",0},
       {'d',"download-only","APT::Get::Download-Only",0},
       {'b',"compile","APT::Get::Compile",0},
       {'b',"build","APT::Get::Compile",0},
-      {'s',"simulate","APT::Get::Simulate",0},      
-      {'s',"just-print","APT::Get::Simulate",0},      
-      {'s',"recon","APT::Get::Simulate",0},      
-      {'s',"no-act","APT::Get::Simulate",0},      
-      {'y',"yes","APT::Get::Assume-Yes",0},      
+      {'s',"simulate","APT::Get::Simulate",0},
+      {'s',"just-print","APT::Get::Simulate",0},
+      {'s',"recon","APT::Get::Simulate",0},
+      {'s',"no-act","APT::Get::Simulate",0},
+      {'y',"yes","APT::Get::Assume-Yes",0},
       {'y',"assume-yes","APT::Get::Assume-Yes",0},      
       {'f',"fix-broken","APT::Get::Fix-Broken",0},
       {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
       {'y',"assume-yes","APT::Get::Assume-Yes",0},      
       {'f',"fix-broken","APT::Get::Fix-Broken",0},
       {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
@@ -1517,8 +1698,13 @@ int main(int argc,const char *argv[])
       {0,"no-upgrade","APT::Get::no-upgrade",0},
       {0,"force-yes","APT::Get::force-yes",0},
       {0,"print-uris","APT::Get::Print-URIs",0},
       {0,"no-upgrade","APT::Get::no-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,"tar-only","APT::Get::tar-Only",0},
       {0,"purge","APT::Get::Purge",0},
       {0,"list-cleanup","APT::Get::List-Cleanup",0},
       {0,"purge","APT::Get::Purge",0},
       {0,"list-cleanup","APT::Get::List-Cleanup",0},
+      {0,"reinstall","APT::Get::ReInstall",0},
+      {0,"trivial-only","APT::Get::Trivial-Only",0},
+      {0,"no-remove","APT::Get::No-Remove",0},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
       {0,0,0,0}};
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
       {0,0,0,0}};
@@ -1549,7 +1735,7 @@ int main(int argc,const char *argv[])
        _config->FindB("version") == true ||
        CmdL.FileSize() == 0)
       return ShowHelp(CmdL);
        _config->FindB("version") == true ||
        CmdL.FileSize() == 0)
       return ShowHelp(CmdL);
-
+   
    // Deal with stdout not being a tty
    if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
       _config->Set("quiet","1");
    // Deal with stdout not being a tty
    if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
       _config->Set("quiet","1");