]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-get.cc
mips and cps changes
[apt.git] / cmdline / apt-get.cc
index 69e986978c09607e14980ef11370148486baa51e..6353adf33518f017ca53b010030d50a77aabfa82 100644 (file)
@@ -1,30 +1,3 @@
-// -*- mode: cpp; mode: fold -*-
-// Description                                                         /*{{{*/
-// $Id: apt-get.cc,v 1.65 1999/06/13 05:06:40 jgg Exp $
-/* ######################################################################
-   
-   apt-get - Cover for dpkg
-   
-   This is an allout cover for dpkg implementing a safer front end. It is
-   based largely on libapt-pkg.
-
-   The syntax is different, 
-      apt-get [opt] command [things]
-   Where command is:
-      update - Resyncronize the package files from their sources
-      upgrade - Smart-Download the newest versions of all packages
-      dselect-upgrade - Follows dselect's changes to the Status: field
-                       and installes new and removes old packages
-      dist-upgrade - Powerfull upgrader designed to handle the issues with
-                    a new distribution.
-      install - Download and install a given package (by name, not by .deb)
-      check - Update the package cache and check for broken packages
-      clean - Erase the .debs downloaded to /var/cache/apt/archives and
-              the partial dir too
-
-   ##################################################################### */
-                                                                       /*}}}*/
-// Include Files                                                       /*{{{*/
 #include <apt-pkg/error.h>
 #include <apt-pkg/cmndline.h>
 #include <apt-pkg/init.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/cmndline.h>
 #include <apt-pkg/init.h>
@@ -61,6 +34,31 @@ ostream c2out;
 ofstream devnull("/dev/null");
 unsigned int ScreenWidth = 80;
 
 ofstream devnull("/dev/null");
 unsigned int ScreenWidth = 80;
 
+// class CacheFile - Cover class for some dependency cache functions   /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+class CacheFile : public pkgCacheFile
+{
+   static pkgCache *SortCache;
+   static int NameComp(const void *a,const void *b);
+   
+   public:
+   pkgCache::Package **List;
+   
+   void Sort();
+   bool CheckDeps(bool AllowBroken = false);
+   bool Open(bool WithLock = true) 
+   {
+      OpTextProgress Prog(*_config);
+      if (pkgCacheFile::Open(Prog,WithLock) == false)
+        return false;
+      Sort();
+      return true;
+   };
+   CacheFile() : List(0) {};
+};
+                                                                       /*}}}*/
+
 // YnPrompt - Yes No Prompt.                                           /*{{{*/
 // ---------------------------------------------------------------------
 /* Returns true on a Yes.*/
 // YnPrompt - Yes No Prompt.                                           /*{{{*/
 // ---------------------------------------------------------------------
 /* Returns true on a Yes.*/
@@ -129,12 +127,13 @@ 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,pkgDepCache &Cache)
+void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
 {
    out << "Sorry, but the following packages have unmet dependencies:" << endl;
 {
    out << "Sorry, but the following packages have unmet dependencies:" << endl;
-   pkgCache::PkgIterator I = Cache.PkgBegin();
-   for (;I.end() != true; I++)
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
    {
    {
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      
       if (Cache[I].InstBroken() == false)
          continue;
          
       if (Cache[I].InstBroken() == false)
          continue;
          
@@ -155,7 +154,7 @@ void ShowBroken(ostream &out,pkgDepCache &Cache)
         pkgCache::DepIterator End;
         D.GlobOr(Start,End);
 
         pkgCache::DepIterator End;
         D.GlobOr(Start,End);
 
-        if (Cache.IsImportantDep(End) == false || 
+        if (Cache->IsImportantDep(End) == false || 
             (Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
            continue;
         
             (Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
            continue;
         
@@ -172,15 +171,14 @@ void ShowBroken(ostream &out,pkgDepCache &Cache)
            ")";
         
         /* Show a summary of the target package if possible. In the case
            ")";
         
         /* Show a summary of the target package if possible. In the case
-         of virtual packages we show nothing */
-        
+           of virtual packages we show nothing */       
         pkgCache::PkgIterator Targ = End.TargetPkg();
         if (Targ->ProvidesList == 0)
         {
            out << " but ";
            pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
            if (Ver.end() == false)
         pkgCache::PkgIterator Targ = End.TargetPkg();
         if (Targ->ProvidesList == 0)
         {
            out << " but ";
            pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
            if (Ver.end() == false)
-              out << Ver.VerStr() << " is installed";
+              out << Ver.VerStr() << (Now?" is installed":" is to be installed");
            else
            {
               if (Cache[Targ].CandidateVerIter(Cache).end() == true)
            else
            {
               if (Cache[Targ].CandidateVerIter(Cache).end() == true)
@@ -191,7 +189,7 @@ void ShowBroken(ostream &out,pkgDepCache &Cache)
                     out << "it is a virtual package";
               }                  
               else
                     out << "it is a virtual package";
               }                  
               else
-                 out << "it is not installed";
+                 out << (Now?"it is not installed":"it is not going to be installed");
            }          
         }
         
            }          
         }
         
@@ -203,30 +201,40 @@ void ShowBroken(ostream &out,pkgDepCache &Cache)
 // ShowNew - Show packages to newly install                            /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // ShowNew - Show packages to newly install                            /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void ShowNew(ostream &out,pkgDepCache &Dep)
+void ShowNew(ostream &out,CacheFile &Cache)
 {
    /* Print out a list of packages that are going to be removed extra
       to what the user asked */
 {
    /* Print out a list of packages that are going to be removed extra
       to what the user asked */
-   pkgCache::PkgIterator I = Dep.PkgBegin();
    string List;
    string List;
-   for (;I.end() != true; I++)
-      if (Dep[I].NewInstall() == true)
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      if (Cache[I].NewInstall() == true)
         List += string(I.Name()) + " ";
         List += string(I.Name()) + " ";
+   }
+   
    ShowList(out,"The following NEW packages will be installed:",List);
 }
                                                                        /*}}}*/
 // ShowDel - Show packages to delete                                   /*{{{*/
 // ---------------------------------------------------------------------
 /* */
    ShowList(out,"The following NEW packages will be installed:",List);
 }
                                                                        /*}}}*/
 // ShowDel - Show packages to delete                                   /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void ShowDel(ostream &out,pkgDepCache &Dep)
+void ShowDel(ostream &out,CacheFile &Cache)
 {
    /* Print out a list of packages that are going to be removed extra
       to what the user asked */
 {
    /* Print out a list of packages that are going to be removed extra
       to what the user asked */
-   pkgCache::PkgIterator I = Dep.PkgBegin();
    string List;
    string List;
-   for (;I.end() != true; I++)
-      if (Dep[I].Delete() == true)
-        List += string(I.Name()) + " ";
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+   {
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      if (Cache[I].Delete() == true)
+      {
+        if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
+           List += string(I.Name()) + "* ";
+        else
+           List += string(I.Name()) + " ";
+      }
+   }
    
    ShowList(out,"The following packages will be REMOVED:",List);
 }
    
    ShowList(out,"The following packages will be REMOVED:",List);
 }
@@ -234,15 +242,16 @@ void ShowDel(ostream &out,pkgDepCache &Dep)
 // 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()) + " ";
@@ -253,14 +262,15 @@ void ShowKept(ostream &out,pkgDepCache &Dep)
 // ShowUpgraded - Show upgraded packages                               /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // ShowUpgraded - Show upgraded packages                               /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void ShowUpgraded(ostream &out,pkgDepCache &Dep)
+void ShowUpgraded(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() == false || Dep[I].NewInstall() == true)
+      if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
         continue;
       
       List += string(I.Name()) + " ";
         continue;
       
       List += string(I.Name()) + " ";
@@ -271,13 +281,13 @@ void ShowUpgraded(ostream &out,pkgDepCache &Dep)
 // ShowHold - Show held but changed packages                           /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // ShowHold - Show held but changed packages                           /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool ShowHold(ostream &out,pkgDepCache &Dep)
+bool ShowHold(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++)
    {
    {
-      if (Dep[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
+      if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
          I->SelectedState == pkgCache::State::Hold)
         List += string(I.Name()) + " ";
    }
          I->SelectedState == pkgCache::State::Hold)
         List += string(I.Name()) + " ";
    }
@@ -290,21 +300,21 @@ bool ShowHold(ostream &out,pkgDepCache &Dep)
 /* This prints out a warning message that is not to be ignored. It shows
    all essential packages and their dependents that are to be removed. 
    It is insanely risky to remove the dependents of an essential package! */
 /* This prints out a warning message that is not to be ignored. It shows
    all essential packages and their dependents that are to be removed. 
    It is insanely risky to remove the dependents of an essential package! */
-bool ShowEssential(ostream &out,pkgDepCache &Dep)
+bool ShowEssential(ostream &out,CacheFile &Cache)
 {
 {
-   pkgCache::PkgIterator I = Dep.PkgBegin();
    string List;
    string List;
-   bool *Added = new bool[Dep.HeaderP->PackageCount];
-   for (unsigned int I = 0; I != Dep.HeaderP->PackageCount; I++)
+   bool *Added = new bool[Cache->HeaderP->PackageCount];
+   for (unsigned int I = 0; I != Cache->HeaderP->PackageCount; I++)
       Added[I] = false;
    
       Added[I] = false;
    
-   for (;I.end() != true; I++)
+   for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
    {
    {
+      pkgCache::PkgIterator I(Cache,Cache.List[J]);
       if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
         continue;
       
       // The essential package is being removed
       if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
         continue;
       
       // The essential package is being removed
-      if (Dep[I].Delete() == true)
+      if (Cache[I].Delete() == true)
       {
         if (Added[I->ID] == false)
         {
       {
         if (Added[I->ID] == false)
         {
@@ -325,7 +335,7 @@ bool ShowEssential(ostream &out,pkgDepCache &Dep)
            continue;
         
         pkgCache::PkgIterator P = D.SmartTargetPkg();
            continue;
         
         pkgCache::PkgIterator P = D.SmartTargetPkg();
-        if (Dep[P].Delete() == true)
+        if (Cache[P].Delete() == true)
         {
            if (Added[P->ID] == true)
               continue;
         {
            if (Added[P->ID] == true)
               continue;
@@ -370,20 +380,36 @@ void Stats(ostream &out,pkgDepCache &Dep)
 }
                                                                        /*}}}*/
 
 }
                                                                        /*}}}*/
 
-// class CacheFile - Cover class for some dependency cache functions   /*{{{*/
+// CacheFile::NameComp - QSort compare by name                         /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 // ---------------------------------------------------------------------
 /* */
-class CacheFile : public pkgCacheFile
+pkgCache *CacheFile::SortCache = 0;
+int CacheFile::NameComp(const void *a,const void *b)
 {
 {
-   public:
+   if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0)
+      return *(pkgCache::Package **)a - *(pkgCache::Package **)b;
    
    
-   bool CheckDeps(bool AllowBroken = false);
-   bool Open(bool WithLock = true) 
-   {
-      OpTextProgress Prog(*_config); 
-      return pkgCacheFile::Open(Prog,WithLock);
-   };
-};
+   const pkgCache::Package &A = **(pkgCache::Package **)a;
+   const pkgCache::Package &B = **(pkgCache::Package **)b;
+
+   return strcmp(SortCache->StrP + A.Name,SortCache->StrP + B.Name);
+}
+                                                                       /*}}}*/
+// CacheFile::Sort - Sort by name                                      /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void CacheFile::Sort()
+{
+   delete [] List;
+   List = new pkgCache::Package *[Cache->Head().PackageCount];
+   memset(List,0,sizeof(*List)*Cache->Head().PackageCount);
+   pkgCache::PkgIterator I = Cache->PkgBegin();
+   for (;I.end() != true; I++)
+      List[I->ID] = I;
+
+   SortCache = *this;
+   qsort(List,Cache->Head().PackageCount,sizeof(*List),NameComp);
+}
                                                                        /*}}}*/
 // CacheFile::Open - Open the cache file                               /*{{{*/
 // ---------------------------------------------------------------------
                                                                        /*}}}*/
 // CacheFile::Open - Open the cache file                               /*{{{*/
 // ---------------------------------------------------------------------
@@ -413,7 +439,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");
       }
@@ -425,7 +451,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.");
    }
@@ -440,6 +466,16 @@ bool CacheFile::CheckDeps(bool AllowBroken)
    happen and then calls the download routines */
 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = true)
 {
    happen and then calls the download routines */
 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = true)
 {
+   if (_config->FindB("APT::Get::Purge",false) == true)
+   {
+      pkgCache::PkgIterator I = Cache->PkgBegin();
+      for (; I.end() == false; I++)
+      {
+        if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
+           Cache->MarkDelete(I,true);
+      }
+   }
+   
    bool Fail = false;
    bool Essential = false;
    
    bool Fail = false;
    bool Essential = false;
    
@@ -458,7 +494,7 @@ 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!");
    }
 
@@ -470,7 +506,12 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
    if (_config->FindB("APT::Get::Simulate") == true)
    {
       pkgSimulate PM(Cache);
    if (_config->FindB("APT::Get::Simulate") == true)
    {
       pkgSimulate PM(Cache);
-      return PM.DoInstall();
+      pkgPackageManager::OrderResult Res = PM.DoInstall();
+      if (Res == pkgPackageManager::Failed)
+        return false;
+      if (Res != pkgPackageManager::Completed)
+        return _error->Error("Internal Error, Ordering didn't finish");
+      return true;
    }
    
    // Create the text record parser
    }
    
    // Create the text record parser
@@ -511,16 +552,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 ";
@@ -530,6 +561,16 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
       c1out << SizeToStr(DebBytes) << 'B';
       
    c1out << " of archives. After unpacking ";
       c1out << SizeToStr(DebBytes) << 'B';
       
    c1out << " of archives. After unpacking ";
+
+   // 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 to hold all the .debs.",
+                          OutputDir.c_str());
    
    // Size delta
    if (Cache->UsrSize() >= 0)
    
    // Size delta
    if (Cache->UsrSize() >= 0)
@@ -589,60 +630,75 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey =
    }
    
    // Run it
    }
    
    // Run it
-   if (_config->FindB("APT::Get::No-Download",false) == false)
-      if( Fetcher.Run() == pkgAcquire::Failed)
-        return false;
-
-   // Print out errors
-   bool Failed = false;
-   bool Transient = false;
-   for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
+   while (1)
    {
    {
-      if ((*I)->Status == pkgAcquire::Item::StatDone &&
-         (*I)->Complete == true)
-        continue;
-      
-      (*I)->Finished();
+      if (_config->FindB("APT::Get::No-Download",false) == false)
+        if( Fetcher.Run() == pkgAcquire::Failed)
+           return false;
       
       
-      if ((*I)->Status == pkgAcquire::Item::StatIdle)
+      // Print out errors
+      bool Failed = false;
+      bool Transient = false;
+      for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
       {
       {
-        Transient = true;
+        if ((*I)->Status == pkgAcquire::Item::StatDone &&
+            (*I)->Complete == true)
+           continue;
+        
+        (*I)->Finished();
+        
+        if ((*I)->Status == pkgAcquire::Item::StatIdle)
+        {
+           Transient = true;
+           // Failed = true;
+           continue;
+        }
+        
+        cerr << "Failed to fetch " << (*I)->DescURI() << endl;
+        cerr << "  " << (*I)->ErrorText << endl;
         Failed = true;
         Failed = true;
-        continue;
       }
       
       }
       
-      cerr << "Failed to fetch " << (*I)->DescURI() << endl;
-      cerr << "  " << (*I)->ErrorText << endl;
-      Failed = true;
-   }
-
-   if (_config->FindB("APT::Get::Download-Only",false) == true)
-   {
+      if (_config->FindB("APT::Get::Download-Only",false) == true)
+      {
+        if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
+           return _error->Error("Some files failed to download");
+        return true;
+      }
+      
       if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
       if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
-        return _error->Error("Some files failed to download");
-      return true;
-   }
-   
-   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;
+        /*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?");
-   }
-   
-   // Try to deal with missing package files
-   if (PM.FixMissing() == false)
-   {
-      cerr << "Unable to correct missing packages." << endl;
-      return _error->Error("Aborting Install.");
-   }
-   
-   Cache.ReleaseLock();
-   return PM.DoInstall();
+      if (Transient == true && Failed == true)
+        return _error->Error("--fix-missing and media swapping is not currently supported");
+      
+      // Try to deal with missing package files
+      if (Failed == true && PM.FixMissing() == false)
+      {
+        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)
+        return false;
+      if (Res == pkgPackageManager::Completed)
+        return true;
+      
+      // Reload the fetcher object and loop again for media swapping
+      Fetcher.Shutdown();
+      if (PM.GetArchives(&Fetcher,&List,&Recs) == false)
+        return false;
+   }   
 }
                                                                        /*}}}*/
 
 }
                                                                        /*}}}*/
 
@@ -682,16 +738,34 @@ bool DoUpdate(CommandLine &)
    if (Fetcher.Run() == pkgAcquire::Failed)
       return false;
 
    if (Fetcher.Run() == pkgAcquire::Failed)
       return false;
 
+   bool Failed = false;
+   for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
+   {
+      if ((*I)->Status == pkgAcquire::Item::StatDone)
+        continue;
+
+      (*I)->Finished();
+      
+      cerr << "Failed to fetch " << (*I)->DescURI() << endl;
+      cerr << "  " << (*I)->ErrorText << endl;
+      Failed = true;
+   }
+   
    // Clean out any old list files
    // Clean out any old list files
-   if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
-       Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
-      return false;
+   if (_config->FindB("APT::Get::List-Cleanup",false) == false)
+   {
+      if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
+         Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
+        return false;
+   }
    
    // Prepare the cache.   
    CacheFile Cache;
    if (Cache.Open() == false)
       return false;
    
    
    // Prepare the cache.   
    CacheFile Cache;
    if (Cache.Open() == 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;
 }
                                                                        /*}}}*/
    return true;
 }
                                                                        /*}}}*/
@@ -708,7 +782,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");
    }
    
@@ -748,19 +822,23 @@ bool DoInstall(CommandLine &CmdL)
       
       // See if we are removing the package
       bool Remove = DefRemove;
       
       // See if we are removing the package
       bool Remove = DefRemove;
-      if (Cache->FindPkg(S).end() == true)
+      while (Cache->FindPkg(S).end() == true)
       {
         // Handle an optional end tag indicating what to do
         if (S[Length - 1] == '-')
         {
            Remove = true;
            S[--Length] = 0;
       {
         // Handle an optional end tag indicating what to do
         if (S[Length - 1] == '-')
         {
            Remove = true;
            S[--Length] = 0;
+           continue;
         }
         }
+        
         if (S[Length - 1] == '+')
         {
            Remove = false;
            S[--Length] = 0;
         if (S[Length - 1] == '+')
         {
            Remove = false;
            S[--Length] = 0;
+           continue;
         }
         }
+        break;
       }
       
       // Locate the package
       }
       
       // Locate the package
@@ -825,7 +903,7 @@ bool DoInstall(CommandLine &CmdL)
       if (Remove == true)
       {
         Fix.Remove(Pkg);
       if (Remove == true)
       {
         Fix.Remove(Pkg);
-        Cache->MarkDelete(Pkg);
+        Cache->MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
         continue;
       }
       
         continue;
       }
       
@@ -847,7 +925,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).");
    }
@@ -874,7 +952,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");
    }   
    
@@ -883,9 +961,9 @@ bool DoInstall(CommandLine &CmdL)
    if (Cache->InstCount() != ExpectedInst)
    {
       string List;
    if (Cache->InstCount() != ExpectedInst)
    {
       string List;
-      pkgCache::PkgIterator I = Cache->PkgBegin();
-      for (;I.end() != true; I++)
+      for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
       {
       {
+        pkgCache::PkgIterator I(Cache,Cache.List[J]);
         if ((*Cache)[I].Install() == false)
            continue;
 
         if ((*Cache)[I].Install() == false)
            continue;
 
@@ -921,7 +999,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;
    }
    
@@ -965,7 +1043,7 @@ bool DoDSelectUpgrade(CommandLine &CmdL)
       // Remove packages 
       if (I->SelectedState == pkgCache::State::DeInstall ||
          I->SelectedState == pkgCache::State::Purge)
       // Remove packages 
       if (I->SelectedState == pkgCache::State::DeInstall ||
          I->SelectedState == pkgCache::State::Purge)
-        Cache->MarkDelete(I);
+        Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
    }
 
    /* Resolve any problems that dselect created, allupgrade cannot handle
    }
 
    /* Resolve any problems that dselect created, allupgrade cannot handle
@@ -989,7 +1067,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");
       }
    }
@@ -997,7 +1075,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");
    }
    
@@ -1025,6 +1103,9 @@ class LogCleaner : public pkgArchiveCleaner
    virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St) 
    {
       cout << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
    virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St) 
    {
       cout << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
+      
+      if (_config->FindB("APT::Get::Simulate") == false)
+        unlink(File);      
    };
 };
 
    };
 };
 
@@ -1170,6 +1251,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);
@@ -1247,6 +1338,11 @@ 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)
+           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 &&
@@ -1348,7 +1444,7 @@ bool ShowHelp(CommandLine &CmdL)
    cout << "  -c=? Read this configuration file" << endl;
    cout << "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp" << endl;
    cout << "See the apt-get(8), sources.list(5) and apt.conf(5) manual" << endl;
    cout << "  -c=? Read this configuration file" << endl;
    cout << "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp" << endl;
    cout << "See the apt-get(8), sources.list(5) and apt.conf(5) manual" << endl;
-   cout << "pages for more information." << endl;
+   cout << "pages for more information and options." << endl;
    return 100;
 }
                                                                        /*}}}*/
    return 100;
 }
                                                                        /*}}}*/
@@ -1364,6 +1460,7 @@ void GetInitialize()
    _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::Assume-Yes",false);
    _config->Set("APT::Get::Fix-Broken",false);
    _config->Set("APT::Get::Force-Yes",false);
+   _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
 }
                                                                        /*}}}*/
 // SigWinch - Window size change signal handler                                /*{{{*/
 }
                                                                        /*}}}*/
 // SigWinch - Window size change signal handler                                /*{{{*/
@@ -1406,6 +1503,10 @@ 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},
       {'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}};