]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/acquire-item.cc
Another error message for failed updates
[apt.git] / apt-pkg / acquire-item.cc
index aef96687e6eb75d2ffa6304f63eacaff9acd518d..019fb66a9ac16f1df33b7cdc7e3187de9cf80f42 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: acquire-item.cc,v 1.18 1999/01/24 21:16:04 jgg Exp $
+// $Id: acquire-item.cc,v 1.37 1999/09/01 07:01:14 jgg Exp $
 /* ######################################################################
 
    Acquire Item - Item to acquire
@@ -19,7 +19,8 @@
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/error.h>
-#include <strutl.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/fileutl.h>
 
 #include <sys/stat.h>
 #include <unistd.h>
@@ -32,8 +33,8 @@
 // ---------------------------------------------------------------------
 /* */
 pkgAcquire::Item::Item(pkgAcquire *Owner) : Owner(Owner), FileSize(0),
-                       Mode(0), ID(0), Complete(false), Local(false), 
-                       QueueCounter(0)
+                       PartialSize(0), Mode(0), ID(0), Complete(false), 
+                       Local(false), QueueCounter(0)
 {
    Owner->Add(this);
    Status = StatIdle;
@@ -51,31 +52,33 @@ pkgAcquire::Item::~Item()
 // ---------------------------------------------------------------------
 /* We return to an idle state if there are still other queues that could
    fetch this object */
-void pkgAcquire::Item::Failed(string Message)
+void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 {
    Status = StatIdle;
    ErrorText = LookupTag(Message,"Message");
    if (QueueCounter <= 1)
    {
       /* This indicates that the file is not available right now but might
-         be sometime later. If we do a retry cycle then this should be 
-        retried */
-      if (StringToBool(LookupTag(Message,"Transient-Failure"),false) == true)
+         be sometime later. If we do a retry cycle then this should be
+        retried [CDROMs] */
+      if (Cnf->LocalOnly == true &&
+         StringToBool(LookupTag(Message,"Transient-Failure"),false) == true)
       {
         Status = StatIdle;
-        Owner->Dequeue(this);
+        Dequeue();
         return;
       }
       
       Status = StatError;
-      Owner->Dequeue(this);
+      Dequeue();
    }   
 }
                                                                        /*}}}*/
 // Acquire::Item::Start - Item has begun to download                   /*{{{*/
 // ---------------------------------------------------------------------
-/* */
-void pkgAcquire::Item::Start(string Message,unsigned long Size)
+/* Stash status and the file size. Note that setting Complete means 
+   sub-phases of the acquire process such as decompresion are operating */
+void pkgAcquire::Item::Start(string /*Message*/,unsigned long Size)
 {
    Status = StatFetching;
    if (FileSize == 0 && Complete == false)
@@ -94,6 +97,9 @@ void pkgAcquire::Item::Done(string Message,unsigned long Size,string)
       if (Owner->Log != 0)
         Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str()));
    }
+
+   if (FileSize == 0)
+      FileSize= Size;
    
    Status = StatDone;
    ErrorText = string();
@@ -234,14 +240,6 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5)
    Mode = "gzip";
 }
                                                                        /*}}}*/
-// AcqIndex::Describe - Describe the Item                              /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string pkgAcqIndex::Describe()
-{
-   return Location->PackagesURI();
-}
-                                                                       /*}}}*/
 
 // AcqIndexRel::pkgAcqIndexRel - Constructor                           /*{{{*/
 // ---------------------------------------------------------------------
@@ -320,24 +318,50 @@ void pkgAcqIndexRel::Done(string Message,unsigned long Size,string MD5)
    Rename(DestFile,FinalFile);
 }
                                                                        /*}}}*/
-// AcqIndexRel::Describe - Describe the Item                           /*{{{*/
+// AcqIndexRel::Failed - Silence failure messages for missing rel files        /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-string pkgAcqIndexRel::Describe()
+void pkgAcqIndexRel::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 {
-   return Location->ReleaseURI();
+   if (Cnf->LocalOnly == true || 
+       StringToBool(LookupTag(Message,"Transient-Failure"),false) == false)
+   {      
+      // Ignore this
+      Status = StatDone;
+      Complete = false;
+      Dequeue();
+      return;
+   }
+   
+   Item::Failed(Message,Cnf);
 }
                                                                        /*}}}*/
 
 // AcqArchive::AcqArchive - Constructor                                        /*{{{*/
 // ---------------------------------------------------------------------
-/* */
+/* This just sets up the initial fetch environment and queues the first
+   possibilitiy */
 pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
                             pkgRecords *Recs,pkgCache::VerIterator const &Version,
                             string &StoreFilename) :
                Item(Owner), Version(Version), Sources(Sources), Recs(Recs), 
                StoreFilename(StoreFilename), Vf(Version.FileList())
 {
+   Retries = _config->FindI("Acquire::Retries",0);
+
+   if (Version.Arch() == 0)
+   {
+      _error->Error("I wasn't able to locate file for the %s package. "
+                   "This might mean you need to manually fix this package. (due to missing arch)",
+                   Version.ParentPkg().Name());
+      return;
+   }
+   
+   // Generate the final file name as: package_version_arch.deb
+   StoreFilename = QuoteString(Version.ParentPkg().Name(),"_:") + '_' +
+                   QuoteString(Version.VerStr(),"_:") + '_' +
+                   QuoteString(Version.Arch(),"_:.") + ".deb";
+
    // Select a source
    if (QueueNext() == false && _error->PendingError() == false)
       _error->Error("I wasn't able to locate file for the %s package. "
@@ -347,7 +371,9 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
                                                                        /*}}}*/
 // AcqArchive::QueueNext - Queue the next file source                  /*{{{*/
 // ---------------------------------------------------------------------
-/* This queues the next available file version for download. */
+/* This queues the next available file version for download. It checks if
+   the archive is already available in the cache and stashs the MD5 for
+   checking later. */
 bool pkgAcqArchive::QueueNext()
 {
    for (; Vf.end() == false; Vf++)
@@ -378,7 +404,7 @@ bool pkgAcqArchive::QueueNext()
                              "field for package %s."
                              ,Version.ParentPkg().Name());
 
-      // See if we already have the file.
+      // See if we already have the file. (Legacy filenames)
       FileSize = Version->Size;
       string FinalFile = _config->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile);
       struct stat Buf;
@@ -394,12 +420,41 @@ bool pkgAcqArchive::QueueNext()
            return true;
         }
         
+        /* Hmm, we have a file and its size does not match, this means it is
+           an old style mismatched arch */
+        unlink(FinalFile.c_str());
+      }
+
+      // Check it again using the new style output filenames
+      FinalFile = _config->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename);
+      if (stat(FinalFile.c_str(),&Buf) == 0)
+      {
+        // Make sure the size matches
+        if ((unsigned)Buf.st_size == Version->Size)
+        {
+           Complete = true;
+           Local = true;
+           Status = StatDone;
+           StoreFilename = DestFile = FinalFile;
+           return true;
+        }
+        
         /* Hmm, we have a file and its size does not match, this shouldnt
            happen.. */
         unlink(FinalFile.c_str());
       }
+
+      DestFile = _config->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(StoreFilename);
       
-      DestFile = _config->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(PkgFile);
+      // Check the destination file
+      if (stat(DestFile.c_str(),&Buf) == 0)
+      {
+        // Hmm, the partial file is too big, erase it
+        if ((unsigned)Buf.st_size > Version->Size)
+           unlink(DestFile.c_str());
+        else
+           PartialSize = Buf.st_size;
+      }
       
       // Create the item
       Desc.URI = Location->ArchiveURI(PkgFile);
@@ -424,7 +479,8 @@ void pkgAcqArchive::Done(string Message,unsigned long Size,string Md5Hash)
    // Check the size
    if (Size != Version->Size)
    {
-      _error->Error("Size mismatch for package %s",Version.ParentPkg().Name());
+      Status = StatError;
+      ErrorText = "Size mismatch";
       return;
    }
    
@@ -433,7 +489,9 @@ void pkgAcqArchive::Done(string Message,unsigned long Size,string Md5Hash)
    {
       if (Md5Hash != MD5)
       {
-        _error->Error("MD5Sum mismatch for package %s",Version.ParentPkg().Name());
+        Status = StatError;
+        ErrorText = "MD5Sum mismatch";
+        Rename(DestFile,DestFile + ".FAILED");
         return;
       }
    }
@@ -459,28 +517,131 @@ void pkgAcqArchive::Done(string Message,unsigned long Size,string Md5Hash)
    
    // Done, move it into position
    string FinalFile = _config->FindDir("Dir::Cache::Archives");
-   FinalFile += flNotDir(DestFile);
+   FinalFile += flNotDir(StoreFilename);
    Rename(DestFile,FinalFile);
    
    StoreFilename = DestFile = FinalFile;
    Complete = true;
 }
                                                                        /*}}}*/
-// AcqArchive::Describe - Describe the Item                            /*{{{*/
+// AcqArchive::Failed - Failure handler                                        /*{{{*/
+// ---------------------------------------------------------------------
+/* Here we try other sources */
+void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+{
+   ErrorText = LookupTag(Message,"Message");
+   if (QueueNext() == false)
+   {
+      // This is the retry counter
+      if (Retries != 0 &&
+         Cnf->LocalOnly == false &&
+         StringToBool(LookupTag(Message,"Transient-Failure"),false) == true)
+      {
+        Retries--;
+        Vf = Version.FileList();
+        if (QueueNext() == true)
+           return;
+      }
+      
+      StoreFilename = string();
+      Item::Failed(Message,Cnf);
+   }
+}
+                                                                       /*}}}*/
+// AcqArchive::Finished - Fetching has finished, tidy up               /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-string pkgAcqArchive::Describe()
+void pkgAcqArchive::Finished()
 {
-   return Desc.URI;
+   if (Status == pkgAcquire::Item::StatDone &&
+       Complete == true)
+      return;
+   StoreFilename = string();
 }
                                                                        /*}}}*/
-// AcqArchive::Failed - Failure handler                                        /*{{{*/
+
+// AcqFile::pkgAcqFile - Constructor                                   /*{{{*/
 // ---------------------------------------------------------------------
-/* Here we try other sources */
-void pkgAcqArchive::Failed(string Message)
+/* The file is added to the queue */
+pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string MD5,
+                      unsigned long Size,string Dsc,string ShortDesc) :
+                       Item(Owner), Md5Hash(MD5)
 {
-   ErrorText = LookupTag(Message,"Message");
-   if (QueueNext() == false)
-      Item::Failed(Message);
+   DestFile = flNotDir(URI);
+   
+   // Create the item
+   Desc.URI = URI;
+   Desc.Description = Dsc;
+   Desc.Owner = this;
+
+   // Set the short description to the archive component
+   Desc.ShortDesc = ShortDesc;
+      
+   // Get the transfer sizes
+   FileSize = Size;
+   struct stat Buf;
+   if (stat(DestFile.c_str(),&Buf) == 0)
+   {
+      // Hmm, the partial file is too big, erase it
+      if ((unsigned)Buf.st_size > Size)
+        unlink(DestFile.c_str());
+      else
+        PartialSize = Buf.st_size;
+   }
+   
+   QueueURI(Desc);
+}
+                                                                       /*}}}*/
+// AcqFile::Done - Item downloaded OK                                  /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqFile::Done(string Message,unsigned long Size,string MD5)
+{
+   // Check the md5
+   if (Md5Hash.empty() == false && MD5.empty() == false)
+   {
+      if (Md5Hash != MD5)
+      {
+        Status = StatError;
+        ErrorText = "MD5Sum mismatch";
+        Rename(DestFile,DestFile + ".FAILED");
+        return;
+      }
+   }
+   
+   Item::Done(Message,Size,MD5);
+
+   string FileName = LookupTag(Message,"Filename");
+   if (FileName.empty() == true)
+   {
+      Status = StatError;
+      ErrorText = "Method gave a blank filename";
+      return;
+   }
+
+   Complete = true;
+   
+   // The files timestamp matches
+   if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
+      return;
+   
+   // We have to copy it into place
+   if (FileName != DestFile)
+   {
+      Local = true;
+      if (_config->FindB("Acquire::Source-Symlinks",true) == false)
+      {
+        Desc.URI = "copy:" + FileName;
+        QueueURI(Desc);
+        return;
+      }
+      
+      if (symlink(FileName.c_str(),DestFile.c_str()) != 0)
+      {
+        ErrorText = "Link to " + DestFile + "failure ";
+        Status = StatError;
+        Complete = false;
+      }      
+   }
 }
                                                                        /*}}}*/