]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/acquire-item.cc
sync TFRewrite*Order arrays with dpkg and dak
[apt.git] / apt-pkg / acquire-item.cc
index bdbdcc456489bb28ea3c6b9ad24ebe9addf95658..01ce0e6503029c31ef9712d49edc4ee503e0a3b7 100644 (file)
@@ -74,6 +74,11 @@ static std::string GetPartialFileNameFromURI(std::string const &uri) /*{{{*/
    return GetPartialFileName(URItoFileName(uri));
 }
                                                                        /*}}}*/
+static std::string GetFinalFileNameFromURI(std::string const &uri)     /*{{{*/
+{
+   return _config->FindDir("Dir::State::lists") + URItoFileName(uri);
+}
+                                                                       /*}}}*/
 static std::string GetCompressedFileName(std::string const &URI, std::string const &Name, std::string const &Ext) /*{{{*/
 {
    if (Ext.empty() || Ext == "uncompressed")
@@ -168,6 +173,39 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
       ReportMirrorFailure(ErrorText);
 }
                                                                        /*}}}*/
+bool pkgAcquire::Item::TransactionState(TransactionStates const state) /*{{{*/
+{
+   bool const Debug = _config->FindB("Debug::Acquire::Transaction", false);
+   switch(state)
+   {
+      case TransactionAbort:
+        if(Debug == true)
+           std::clog << "  Cancel: " << DestFile << std::endl;
+        if (Status == pkgAcquire::Item::StatIdle)
+        {
+           Status = pkgAcquire::Item::StatDone;
+           Dequeue();
+        }
+        break;
+      case TransactionCommit:
+        if(PartialFile != "")
+        {
+           if(Debug == true)
+              std::clog << "mv " << PartialFile << " -> "<< DestFile << " # " << DescURI() << std::endl;
+
+           Rename(PartialFile, DestFile);
+        } else {
+           if(Debug == true)
+              std::clog << "rm " << DestFile << " # " << DescURI() << std::endl;
+           unlink(DestFile.c_str());
+        }
+        // mark that this transaction is finished
+        TransactionManager = 0;
+        break;
+   }
+   return true;
+}
+                                                                       /*}}}*/
 // Acquire::Item::Start - Item has begun to download                   /*{{{*/
 // ---------------------------------------------------------------------
 /* Stash status and the file size. Note that setting Complete means 
@@ -208,7 +246,7 @@ void pkgAcquire::Item::Done(string Message,unsigned long long Size,HashStringLis
    step */
 bool pkgAcquire::Item::Rename(string From,string To)
 {
-   if (rename(From.c_str(),To.c_str()) == 0)
+   if (From == To || rename(From.c_str(),To.c_str()) == 0)
       return true;
 
    std::string S;
@@ -219,9 +257,41 @@ bool pkgAcquire::Item::Rename(string From,string To)
    return false;
 }
                                                                        /*}}}*/
-void pkgAcquire::Item::QueueURI(ItemDesc &Item)                                /*{{{*/
+// Acquire::Item::QueueURI and specialisations from child classes      /*{{{*/
+/* The idea here is that an item isn't queued if it exists on disk and the
+   transition manager was a hit as this means that the files it contains
+   the checksums for can't be updated either (or they are and we are asking
+   for a hashsum mismatch to happen which helps nobody) */
+bool pkgAcquire::Item::QueueURI(ItemDesc &Item)
+{
+   std::string const FinalFile = GetFinalFilename();
+   if (TransactionManager != NULL && TransactionManager->IMSHit == true &&
+        FileExists(FinalFile) == true)
+   {
+      PartialFile = DestFile = FinalFile;
+      Status = StatDone;
+      return false;
+   }
+
+   Owner->Enqueue(Item);
+   return true;
+}
+/* The transition manager InRelease itself (or its older sisters-in-law
+   Release & Release.gpg) is always queued as this allows us to rerun gpgv
+   on it to verify that we aren't stalled with old files */
+bool pkgAcqMetaBase::QueueURI(pkgAcquire::ItemDesc &Item)
 {
    Owner->Enqueue(Item);
+   return true;
+}
+/* the Diff/Index needs to queue also the up-to-date complete index file
+   to ensure that the list cleaner isn't eating it */
+bool pkgAcqDiffIndex::QueueURI(pkgAcquire::ItemDesc &Item)
+{
+   if (pkgAcquire::Item::QueueURI(Item) == true)
+      return true;
+   QueueOnIMSHit();
+   return false;
 }
                                                                        /*}}}*/
 void pkgAcquire::Item::Dequeue()                                       /*{{{*/
@@ -263,6 +333,9 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const
         // the method is expected to report a good error for this
         Status = StatError;
         break;
+      case PDiffError:
+        // no handling here, done by callers
+        break;
    }
    return false;
 }
@@ -273,6 +346,12 @@ void pkgAcquire::Item::SetActiveSubprocess(const std::string &subprocess)/*{{{*/
       APT_IGNORE_DEPRECATED(Mode = ActiveSubprocess.c_str();)
 }
                                                                        /*}}}*/
+// Acquire::Item::GetFinalFilename - Return the full final file path   /*{{{*/
+std::string pkgAcquire::Item::GetFinalFilename() const
+{
+   return GetFinalFileNameFromURI(Desc.URI);
+}
+                                                                       /*}}}*/
 // Acquire::Item::ReportMirrorFailure                                  /*{{{*/
 // ---------------------------------------------------------------------
 void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
@@ -331,7 +410,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
                                 HashStringList const &ExpectedHashes,
                                  indexRecords *MetaIndexParser)
    : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHashes, 
-                     MetaIndexParser), PackagesFileReadyInPartial(false)
+                     MetaIndexParser)
 {
    
    Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
@@ -348,8 +427,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
       std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl;
 
    // look for the current package file
-   CurrentPackagesFile = _config->FindDir("Dir::State::lists");
-   CurrentPackagesFile += URItoFileName(RealURI);
+   CurrentPackagesFile = GetFinalFileNameFromURI(RealURI);
 
    // FIXME: this file:/ check is a hack to prevent fetching
    //        from local sources. this is really silly, and
@@ -368,6 +446,13 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
 
    QueueURI(Desc);
 
+}
+                                                                       /*}}}*/
+// Acquire::Item::GetFinalFilename - Return the full final file path   /*{{{*/
+std::string pkgAcqDiffIndex::GetFinalFilename() const
+{
+   // the logic we inherent from pkgAcqBaseIndex isn't what we need here
+   return pkgAcquire::Item::GetFinalFilename();
 }
                                                                        /*}}}*/
 // AcqIndex::Custom600Headers - Insert custom request headers          /*{{{*/
@@ -379,8 +464,7 @@ string pkgAcqDiffIndex::Custom600Headers() const
 string pkgAcqDiffIndex::Custom600Headers()
 #endif
 {
-   string Final = _config->FindDir("Dir::State::lists");
-   Final += URItoFileName(Desc.URI);
+   string const Final = GetFinalFilename();
 
    if(Debug)
       std::clog << "Custom600Header-IMS: " << Final << std::endl;
@@ -392,6 +476,14 @@ string pkgAcqDiffIndex::Custom600Headers()
    return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
                                                                        /*}}}*/
+void pkgAcqDiffIndex::QueueOnIMSHit() const                            /*{{{*/
+{
+   // list cleanup needs to know that this file as well as the already
+   // present index is ours, so we create an empty diff to save it for us
+   new pkgAcqIndexDiffs(Owner, TransactionManager, Target,
+        ExpectedHashes, MetaIndexParser);
+}
+                                                                       /*}}}*/
 bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)             /*{{{*/
 {
    // failing here is fine: our caller will take care of trying to
@@ -454,11 +546,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)         /*{{{*/
       // we have the same sha1 as the server so we are done here
       if(Debug)
         std::clog << "pkgAcqDiffIndex: Package file " << CurrentPackagesFile << " is up-to-date" << std::endl;
-
-      // list cleanup needs to know that this file as well as the already
-      // present index is ours, so we create an empty diff to save it for us
-      new pkgAcqIndexDiffs(Owner, TransactionManager, Target,
-                           ExpectedHashes, MetaIndexParser);
+      QueueOnIMSHit();
       return true;
    }
 
@@ -619,20 +707,6 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)         /*{{{*/
       return false;
    }
 
-   // FIXME: make this use the method
-   PackagesFileReadyInPartial = true;
-   std::string const Partial = GetPartialFileNameFromURI(RealURI);
-   
-   FileFd From(CurrentPackagesFile, FileFd::ReadOnly);
-   FileFd To(Partial, FileFd::WriteEmpty);
-   if(CopyFile(From, To) == false)
-      return _error->Errno("CopyFile", "failed to copy");
-   
-   if(Debug)
-      std::cerr << "Done copying " << CurrentPackagesFile
-                << " -> " << Partial
-                << std::endl;
-
    // we have something, queue the diffs
    string::size_type const last_space = Description.rfind(" ");
    if(last_space != string::npos)
@@ -686,6 +760,24 @@ void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{
    new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser);
 }
                                                                        /*}}}*/
+bool pkgAcqDiffIndex::TransactionState(TransactionStates const state)  /*{{{*/
+{
+   if (pkgAcquire::Item::TransactionState(state) == false)
+      return false;
+
+   switch (state)
+   {
+      case TransactionCommit:
+        break;
+      case TransactionAbort:
+        std::string const Partial = GetPartialFileNameFromURI(RealURI);
+        unlink(Partial.c_str());
+        break;
+   }
+
+   return true;
+}
+                                                                       /*}}}*/
 void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes,        /*{{{*/
                           pkgAcquire::MethodConfig *Cnf)
 {
@@ -709,22 +801,25 @@ void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList
 
    }
 
-   string FinalFile;
-   FinalFile = _config->FindDir("Dir::State::lists");
-   FinalFile += URItoFileName(Desc.URI);
-
+   string const FinalFile = GetFinalFilename();
    if(StringToBool(LookupTag(Message,"IMS-Hit"),false))
       DestFile = FinalFile;
 
-   if(!ParseDiffIndex(DestFile))
-      return Failed("Message: Couldn't parse pdiff index", Cnf);
+   if(ParseDiffIndex(DestFile) == false)
+   {
+      Failed("Message: Couldn't parse pdiff index", Cnf);
+      // queue for final move - this should happen even if we fail
+      // while parsing (e.g. on sizelimit) and download the complete file.
+      TransactionManager->TransactionStageCopy(this, DestFile, FinalFile);
+      return;
+   }
 
-   // queue for final move
    TransactionManager->TransactionStageCopy(this, DestFile, FinalFile);
 
    Complete = true;
    Status = StatDone;
    Dequeue();
+
    return;
 }
                                                                        /*}}}*/
@@ -754,12 +849,22 @@ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
    if(available_patches.empty() == true)
    {
       // we are done (yeah!), check hashes against the final file
-      DestFile = _config->FindDir("Dir::State::lists");
-      DestFile += URItoFileName(Target->URI);
+      DestFile = GetFinalFileNameFromURI(Target->URI);
       Finish(true);
    }
    else
    {
+      // patching needs to be bootstrapped with the 'old' version
+      std::string const PartialFile = GetPartialFileNameFromURI(RealURI);
+      if (RealFileExists(PartialFile) == false)
+      {
+        if (symlink(GetFinalFilename().c_str(), PartialFile.c_str()) != 0)
+        {
+           Failed("Link creation of " + PartialFile + " to " + GetFinalFilename() + " failed", NULL);
+           return;
+        }
+      }
+
       // get the next diff
       State = StateFetchDiff;
       QueueNextDiff();
@@ -774,6 +879,8 @@ void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{
    if(Debug)
       std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << " with " << Message << std::endl
                << "Falling back to normal index file acquire" << std::endl;
+   DestFile = GetPartialFileNameFromURI(Target->URI);
+   RenameOnError(PDiffError);
    new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser);
    Finish();
 }
@@ -797,10 +904,7 @@ void pkgAcqIndexDiffs::Finish(bool allDone)
         return;
       }
 
-      // queue for copy
-      std::string FinalFile = _config->FindDir("Dir::State::lists");
-      FinalFile += URItoFileName(RealURI);
-      TransactionManager->TransactionStageCopy(this, DestFile, FinalFile);
+      TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename());
 
       // this is for the "real" finish
       Complete = true;
@@ -905,6 +1009,8 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringLi
       if (fd.Size() != available_patches[0].patch_size ||
            available_patches[0].patch_hashes != LocalHashes)
       {
+        // patchfiles are dated, so bad indicates a bad download, so kill it
+        unlink(DestFile.c_str());
         Failed("Patch has Size/Hashsum mismatch", NULL);
         return;
       }
@@ -999,7 +1105,10 @@ void pkgAcqIndexMergeDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf
 
    // first failure means we should fallback
    State = StateErrorDiff;
-   std::clog << "Falling back to normal index file acquire" << std::endl;
+   if (Debug)
+      std::clog << "Falling back to normal index file acquire" << std::endl;
+   DestFile = GetPartialFileNameFromURI(Target->URI);
+   RenameOnError(PDiffError);
    new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser);
 }
                                                                        /*}}}*/
@@ -1023,6 +1132,8 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri
 
       if (fd.Size() != patch.patch_size || patch.patch_hashes != LocalHashes)
       {
+        // patchfiles are dated, so bad indicates a bad download, so kill it
+        unlink(DestFile.c_str());
         Failed("Patch has Size/Hashsum mismatch", NULL);
         return;
       }
@@ -1044,6 +1155,13 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri
       // this is the last completed diff, so we are ready to apply now
       State = StateApplyDiff;
 
+      // patching needs to be bootstrapped with the 'old' version
+      if (symlink(GetFinalFilename().c_str(), FinalFile.c_str()) != 0)
+      {
+        Failed("Link creation of " + FinalFile + " to " + GetFinalFilename() + " failed", NULL);
+        return;
+      }
+
       if(Debug)
         std::clog << "Sending to rred method: " << FinalFile << std::endl;
 
@@ -1063,17 +1181,14 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri
         return;
       }
 
-
-      std::string FinalFile = _config->FindDir("Dir::State::lists");
-      FinalFile += URItoFileName(RealURI);
-
       // move the result into place
+      std::string const Final = GetFinalFilename();
       if(Debug)
         std::clog << "Queue patched file in place: " << std::endl
-                  << DestFile << " -> " << FinalFile << std::endl;
+                  << DestFile << " -> " << Final << std::endl;
 
       // queue for copy by the transaction manager
-      TransactionManager->TransactionStageCopy(this, DestFile, FinalFile);
+      TransactionManager->TransactionStageCopy(this, DestFile, Final);
 
       // ensure the ed's are gone regardless of list-cleanup
       for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin();
@@ -1083,12 +1198,24 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStri
         std::string patch = PartialFile + ".ed." + (*I)->patch.file + ".gz";
         unlink(patch.c_str());
       }
+      unlink(FinalFile.c_str());
 
       // all set and done
       Complete = true;
       if(Debug)
         std::clog << "allDone: " << DestFile << "\n" << std::endl;
    }
+}
+                                                                       /*}}}*/
+// AcqBaseIndex - Constructor                                          /*{{{*/
+pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire *Owner,
+      pkgAcqMetaBase *TransactionManager,
+      struct IndexTarget const * const Target,
+      HashStringList const &ExpectedHashes,
+      indexRecords *MetaIndexParser)
+: Item(Owner, ExpectedHashes, TransactionManager), Target(Target),
+   MetaIndexParser(MetaIndexParser)
+{
 }
                                                                        /*}}}*/
 // AcqBaseIndex::VerifyHashByMetaKey - verify hash for the given metakey /*{{{*/
@@ -1106,6 +1233,12 @@ bool pkgAcqBaseIndex::VerifyHashByMetaKey(HashStringList const &Hashes)
    return true;
 }
                                                                        /*}}}*/
+// AcqBaseIndex::GetFinalFilename - Return the full final file path    /*{{{*/
+std::string pkgAcqBaseIndex::GetFinalFilename() const
+{
+   return GetFinalFileNameFromURI(RealURI);
+}
+                                                                       /*}}}*/
 // AcqIndex::AcqIndex - Constructor                                    /*{{{*/
 // ---------------------------------------------------------------------
 /* The package file is added to the queue and a second class is
@@ -1276,12 +1409,6 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
       return;
    }
 
-   // on decompression failure, remove bad versions in partial/
-   if (Stage == STAGE_DECOMPRESS_AND_VERIFY)
-   {
-      unlink(EraseFileName.c_str());
-   }
-
    Item::Failed(Message,Cnf);
 
    if(Target->IsOptional() && ExpectedHashes.empty() && Stage == STAGE_DOWNLOAD)
@@ -1290,11 +1417,34 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
       TransactionManager->AbortTransaction();
 }
                                                                        /*}}}*/
+bool pkgAcqIndex::TransactionState(TransactionStates const state)      /*{{{*/
+{
+   if (pkgAcquire::Item::TransactionState(state) == false)
+      return false;
+
+   switch (state)
+   {
+      case TransactionAbort:
+        if (Stage == STAGE_DECOMPRESS_AND_VERIFY)
+        {
+           // keep the compressed file, but drop the decompressed
+           EraseFileName.clear();
+           if (PartialFile.empty() == false && flExtension(PartialFile) == "decomp")
+              unlink(PartialFile.c_str());
+        }
+        break;
+      case TransactionCommit:
+        if (EraseFileName.empty() == false)
+           unlink(EraseFileName.c_str());
+        break;
+   }
+   return true;
+}
+                                                                       /*}}}*/
 // pkgAcqIndex::GetFinalFilename - Return the full final file path     /*{{{*/
 std::string pkgAcqIndex::GetFinalFilename() const
 {
-   std::string FinalFile = _config->FindDir("Dir::State::lists");
-   FinalFile += URItoFileName(RealURI);
+   std::string const FinalFile = GetFinalFileNameFromURI(RealURI);
    return GetCompressedFileName(RealURI, FinalFile, CurrentCompressionExtension);
 }
                                                                        /*}}}*/
@@ -1470,13 +1620,23 @@ void pkgAcqIndex::StageDecompressDone(string Message,
       return;
    }
 
-   // remove the compressed version of the file
-   unlink(EraseFileName.c_str());
-
    // Done, queue for rename on transaction finished
    TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename());
 
    return;
+}
+                                                                       /*}}}*/
+// AcqMetaBase - Constructor                                           /*{{{*/
+pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire *Owner,
+      const std::vector<IndexTarget*>* IndexTargets,
+      indexRecords* MetaIndexParser,
+      std::string const &RealURI,
+      HashStringList const &ExpectedHashes,
+      pkgAcqMetaBase *TransactionManager)
+: Item(Owner, ExpectedHashes, TransactionManager),
+   MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets),
+   AuthPass(false), RealURI(RealURI), IMSHit(false)
+{
 }
                                                                        /*}}}*/
 // AcqMetaBase::Add - Add a item to the current Transaction            /*{{{*/
@@ -1495,14 +1655,7 @@ void pkgAcqMetaBase::AbortTransaction()
    for (std::vector<Item*>::iterator I = Transaction.begin();
         I != Transaction.end(); ++I)
    {
-      if(_config->FindB("Debug::Acquire::Transaction", false) == true)
-         std::clog << "  Cancel: " << (*I)->DestFile << std::endl;
-      // the transaction will abort, so stop anything that is idle
-      if ((*I)->Status == pkgAcquire::Item::StatIdle)
-      {
-         (*I)->Status = pkgAcquire::Item::StatDone;
-         (*I)->Dequeue();
-      }
+      (*I)->TransactionState(TransactionAbort);
    }
    Transaction.clear();
 }
@@ -1512,10 +1665,16 @@ bool pkgAcqMetaBase::TransactionHasError()
 {
    for (pkgAcquire::ItemIterator I = Transaction.begin();
         I != Transaction.end(); ++I)
-      if((*I)->Status != pkgAcquire::Item::StatDone &&
-         (*I)->Status != pkgAcquire::Item::StatIdle)
-         return true;
-
+   {
+      switch((*I)->Status) {
+        case StatDone: break;
+        case StatIdle: break;
+        case StatAuthError: return true;
+        case StatError: return true;
+        case StatTransientNetworkError: return true;
+        case StatFetching: break;
+      }
+   }
    return false;
 }
                                                                        /*}}}*/
@@ -1530,24 +1689,7 @@ void pkgAcqMetaBase::CommitTransaction()
    for (std::vector<Item*>::iterator I = Transaction.begin();
         I != Transaction.end(); ++I)
    {
-      if((*I)->PartialFile != "")
-      {
-        if(_config->FindB("Debug::Acquire::Transaction", false) == true)
-           std::clog << "mv " << (*I)->PartialFile << " -> "<< (*I)->DestFile << " "
-              << (*I)->DescURI() << std::endl;
-
-        Rename((*I)->PartialFile, (*I)->DestFile);
-      } else {
-         if(_config->FindB("Debug::Acquire::Transaction", false) == true)
-            std::clog << "rm "
-                      <<  (*I)->DestFile
-                      << " "
-                      << (*I)->DescURI()
-                      << std::endl;
-         unlink((*I)->DestFile.c_str());
-      }
-      // mark that this transaction is finished
-      (*I)->TransactionManager = 0;
+      (*I)->TransactionState(TransactionCommit);
    }
    Transaction.clear();
 }
@@ -1561,23 +1703,21 @@ void pkgAcqMetaBase::TransactionStageCopy(Item *I,
    I->DestFile = To;
 }
                                                                        /*}}}*/
-// AcqMetaBase::TransactionStageRemoval - Sage a file for removal      /*{{{*/
+// AcqMetaBase::TransactionStageRemoval - Stage a file for removal     /*{{{*/
 void pkgAcqMetaBase::TransactionStageRemoval(Item *I,
                                              const std::string &FinalFile)
 {
    I->PartialFile = "";
-   I->DestFile = FinalFile; 
+   I->DestFile = FinalFile;
 }
                                                                        /*}}}*/
 // AcqMetaBase::GenerateAuthWarning - Check gpg authentication error   /*{{{*/
-bool pkgAcqMetaBase::CheckStopAuthentication(const std::string &RealURI,
-                                             const std::string &Message)
+bool pkgAcqMetaBase::CheckStopAuthentication(const std::string &Message)
 {
    // FIXME: this entire function can do now that we disallow going to
    //        a unauthenticated state and can cleanly rollback
 
-   string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
-
+   string const Final = GetFinalFilename();
    if(FileExists(Final))
    {
       Status = StatTransientNetworkError;
@@ -1613,13 +1753,12 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,
                              string MetaIndexFile,
                             const vector<IndexTarget*>* IndexTargets,
                             indexRecords* MetaIndexParser) :
-   pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser,
+   pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser, URI,
                   HashStringList(), TransactionManager),
-   RealURI(URI), MetaIndexFile(MetaIndexFile), URIDesc(URIDesc),
+   MetaIndexFile(MetaIndexFile), URIDesc(URIDesc),
    ShortDesc(ShortDesc)
 {
-   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
-   DestFile += URItoFileName(RealURI);
+   DestFile = GetPartialFileNameFromURI(RealURI);
 
    // remove any partial downloaded sig-file in partial/.
    // it may confuse proxies and is too small to warrant a
@@ -1642,18 +1781,6 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,
                                                                        /*}}}*/
 pkgAcqMetaSig::~pkgAcqMetaSig()                                                /*{{{*/
 {
-}
-                                                                       /*}}}*/
-// pkgAcqMetaSig::Custom600Headers - Insert custom request headers     /*{{{*/
-// ---------------------------------------------------------------------
-#if APT_PKG_ABI >= 413
-string pkgAcqMetaSig::Custom600Headers() const
-#else
-string pkgAcqMetaSig::Custom600Headers()
-#endif
-{
-   std::string Header = GetCustom600Headers(RealURI);
-   return Header;
 }
                                                                        /*}}}*/
 // pkgAcqMetaSig::Done - The signature was downloaded/verified         /*{{{*/
@@ -1667,7 +1794,7 @@ void pkgAcqMetaSig::Done(string Message,unsigned long long Size,
 
    if(AuthPass == false)
    {
-      if(CheckDownloadDone(Message, RealURI) == true)
+      if(CheckDownloadDone(Message) == true)
       {
          // destfile will be modified to point to MetaIndexFile for the
          // gpgv method, so we need to save it here
@@ -1676,15 +1803,8 @@ void pkgAcqMetaSig::Done(string Message,unsigned long long Size,
       }
       return;
    }
-   else
-   {
-      if(CheckAuthDone(Message, RealURI) == true)
-      {
-         std::string FinalFile = _config->FindDir("Dir::State::lists");
-         FinalFile += URItoFileName(RealURI);
-         TransactionManager->TransactionStageCopy(this, MetaIndexFileSignature, FinalFile);
-      }
-   }
+   else if(CheckAuthDone(Message) == true)
+      TransactionManager->TransactionStageCopy(this, MetaIndexFileSignature, GetFinalFilename());
 }
                                                                        /*}}}*/
 void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
@@ -1692,14 +1812,14 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
    Item::Failed(Message,Cnf);
 
    // check if we need to fail at this point 
-   if (AuthPass == true && CheckStopAuthentication(RealURI, Message))
+   if (AuthPass == true && CheckStopAuthentication(Message))
          return;
 
    // FIXME: meh, this is not really elegant
-   string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
+   string const Final = GetFinalFileNameFromURI(RealURI);
    string const InReleaseURI = RealURI.replace(RealURI.rfind("Release.gpg"), 12,
                                          "InRelease");
-   string const FinalInRelease = _config->FindDir("Dir::State::lists") + URItoFileName(InReleaseURI);
+   string const FinalInRelease = GetFinalFileNameFromURI(InReleaseURI);
 
    if (RealFileExists(Final) || RealFileExists(FinalInRelease))
    {
@@ -1739,7 +1859,7 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
       // we parse the indexes here because at this point the user wanted
       // a repository that may potentially harm him
       MetaIndexParser->Load(MetaIndexFile);
-      if (!VerifyVendor(Message, RealURI))
+      if (!VerifyVendor(Message))
         /* expired Release files are still a problem you need extra force for */;
       else
         QueueIndexes(true);
@@ -1760,9 +1880,9 @@ pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner,                       /*{{{*/
                                  string MetaIndexSigURI,string MetaIndexSigURIDesc, string MetaIndexSigShortDesc,
                                 const vector<IndexTarget*>* IndexTargets,
                                 indexRecords* MetaIndexParser) :
-   pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser, HashStringList(),
+   pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser, URI, HashStringList(),
                   TransactionManager), 
-   RealURI(URI), URIDesc(URIDesc), ShortDesc(ShortDesc),
+   URIDesc(URIDesc), ShortDesc(ShortDesc),
    MetaIndexSigURI(MetaIndexSigURI), MetaIndexSigURIDesc(MetaIndexSigURIDesc),
    MetaIndexSigShortDesc(MetaIndexSigShortDesc)
 {
@@ -1796,24 +1916,13 @@ void pkgAcqMetaIndex::Init(std::string URIDesc, std::string ShortDesc)
    QueueURI(Desc);
 }
                                                                        /*}}}*/
-// pkgAcqMetaIndex::Custom600Headers - Insert custom request headers   /*{{{*/
-// ---------------------------------------------------------------------
-#if APT_PKG_ABI >= 413
-string pkgAcqMetaIndex::Custom600Headers() const
-#else
-string pkgAcqMetaIndex::Custom600Headers()
-#endif
-{
-   return GetCustom600Headers(RealURI);
-}
-                                                                       /*}}}*/
 void pkgAcqMetaIndex::Done(string Message,unsigned long long Size,     /*{{{*/
                            HashStringList const &Hashes,
                           pkgAcquire::MethodConfig *Cfg)
 {
    Item::Done(Message,Size,Hashes,Cfg);
 
-   if(CheckDownloadDone(Message, RealURI))
+   if(CheckDownloadDone(Message))
    {
       // we have a Release file, now download the Signature, all further
       // verify/queue for additional downloads will be done in the
@@ -1824,13 +1933,11 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long long Size,      /*{{{*/
                         MetaIndexSigShortDesc, MetaIndexFile, IndexTargets, 
                         MetaIndexParser);
 
-      string FinalFile = _config->FindDir("Dir::State::lists");
-      FinalFile += URItoFileName(RealURI);
-      TransactionManager->TransactionStageCopy(this, DestFile, FinalFile);
+      TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename());
    }
 }
                                                                        /*}}}*/
-bool pkgAcqMetaBase::CheckAuthDone(string Message, const string &RealURI)      /*{{{*/
+bool pkgAcqMetaBase::CheckAuthDone(string Message)                     /*{{{*/
 {
    // At this point, the gpgv method has succeeded, so there is a
    // valid signature from a key in the trusted keyring.  We
@@ -1844,7 +1951,7 @@ bool pkgAcqMetaBase::CheckAuthDone(string Message, const string &RealURI) /*{{{*
       return false;
    }
 
-   if (!VerifyVendor(Message, RealURI))
+   if (!VerifyVendor(Message))
    {
       Status = StatAuthError;
       return false;
@@ -1854,21 +1961,19 @@ bool pkgAcqMetaBase::CheckAuthDone(string Message, const string &RealURI)       /*{{{*
       std::cerr << "Signature verification succeeded: "
                 << DestFile << std::endl;
 
-   // Download further indexes with verification 
-   //
-   // it would be really nice if we could simply do
-   //    if (IMSHit == false) QueueIndexes(true)
-   // and skip the download if the Release file has not changed
-   // - but right now the list cleaner will needs to be tricked
-   //   to not delete all our packages/source indexes in this case
+   // Download further indexes with verification
    QueueIndexes(true);
 
    return true;
 }
                                                                        /*}}}*/
-// pkgAcqMetaBase::GetCustom600Headers - Get header for AcqMetaBase     /*{{{*/
+// pkgAcqMetaBase::Custom600Headers - Get header for AcqMetaBase       /*{{{*/
 // ---------------------------------------------------------------------
-string pkgAcqMetaBase::GetCustom600Headers(const string &RealURI) const
+#if APT_PKG_ABI >= 413
+string pkgAcqMetaBase::Custom600Headers() const
+#else
+string pkgAcqMetaBase::Custom600Headers()
+#endif
 {
    std::string Header = "\nIndex-File: true";
    std::string MaximumSize;
@@ -1876,8 +1981,7 @@ string pkgAcqMetaBase::GetCustom600Headers(const string &RealURI) const
              _config->FindI("Acquire::MaxReleaseFileSize", 10*1000*1000));
    Header += MaximumSize;
 
-   string FinalFile = _config->FindDir("Dir::State::lists");
-   FinalFile += URItoFileName(RealURI);
+   string const FinalFile = GetFinalFilename();
 
    struct stat Buf;
    if (stat(FinalFile.c_str(),&Buf) == 0)
@@ -1886,6 +1990,12 @@ string pkgAcqMetaBase::GetCustom600Headers(const string &RealURI) const
    return Header;
 }
                                                                        /*}}}*/
+// pkgAcqMetaBase::GetFinalFilename - Return the full final file path  /*{{{*/
+std::string pkgAcqMetaBase::GetFinalFilename() const
+{
+   return GetFinalFileNameFromURI(RealURI);
+}
+                                                                       /*}}}*/
 // pkgAcqMetaBase::QueueForSignatureVerify                             /*{{{*/
 void pkgAcqMetaBase::QueueForSignatureVerify(const std::string &MetaIndexFile,
                                     const std::string &MetaIndexFileSignature)
@@ -1898,8 +2008,7 @@ void pkgAcqMetaBase::QueueForSignatureVerify(const std::string &MetaIndexFile,
 }
                                                                        /*}}}*/
 // pkgAcqMetaBase::CheckDownloadDone                                   /*{{{*/
-bool pkgAcqMetaBase::CheckDownloadDone(const std::string &Message,
-                                       const std::string &RealURI)
+bool pkgAcqMetaBase::CheckDownloadDone(const std::string &Message)
 {
    // We have just finished downloading a Release file (it is not
    // verified yet)
@@ -1924,9 +2033,11 @@ bool pkgAcqMetaBase::CheckDownloadDone(const std::string &Message,
    IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false);
    if(IMSHit)
    {
-      string FinalFile = _config->FindDir("Dir::State::lists");
-      FinalFile += URItoFileName(RealURI);
-      DestFile = FinalFile;
+      // for simplicity, the transaction manager is always InRelease
+      // even if it doesn't exist.
+      if (TransactionManager != NULL)
+        TransactionManager->IMSHit = true;
+      DestFile = GetFinalFilename();
    }
 
    // set Item to complete as the remaining work is all local (verify etc)
@@ -1970,7 +2081,7 @@ void pkgAcqMetaBase::QueueIndexes(bool verify)                            /*{{{*/
                    << "Expected Hash:" << std::endl;
          for (HashStringList::const_iterator hs = ExpectedIndexHashes.begin(); hs != ExpectedIndexHashes.end(); ++hs)
             std::cerr <<  "\t- " << hs->toStr() << std::endl;
-         std::cerr << "For: " << Record->MetaKeyFilename << std::endl;
+         std::cerr << "For: " << ((Record == NULL) ? "<NULL>" : Record->MetaKeyFilename) << std::endl;
 
       }
       if (verify == true && ExpectedIndexHashes.empty() == true)
@@ -1993,7 +2104,7 @@ void pkgAcqMetaBase::QueueIndexes(bool verify)                            /*{{{*/
    }
 }
                                                                        /*}}}*/
-bool pkgAcqMetaBase::VerifyVendor(string Message, const string &RealURI)/*{{{*/
+bool pkgAcqMetaBase::VerifyVendor(string Message)                      /*{{{*/
 {
    string::size_type pos;
 
@@ -2083,8 +2194,6 @@ void pkgAcqMetaIndex::Failed(string Message,
    pkgAcquire::Item::Failed(Message, Cnf);
    Status = StatDone;
 
-   string FinalFile = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
-
    _error->Warning(_("The repository '%s' does not have a Release file. "
                      "This is deprecated, please contact the owner of the "
                      "repository."), URIDesc.c_str());
@@ -2096,7 +2205,7 @@ void pkgAcqMetaIndex::Failed(string Message,
    {
       // Done, queue for rename on transaction finished
       if (FileExists(DestFile)) 
-         TransactionManager->TransactionStageCopy(this, DestFile, FinalFile);
+         TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename());
 
       // queue without any kind of hashsum support
       QueueIndexes(false);
@@ -2132,19 +2241,18 @@ pkgAcqMetaClearSig::~pkgAcqMetaClearSig()                               /*{{{*/
 }
                                                                        /*}}}*/
 // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers        /*{{{*/
-// ---------------------------------------------------------------------
 #if APT_PKG_ABI >= 413
 string pkgAcqMetaClearSig::Custom600Headers() const
 #else
 string pkgAcqMetaClearSig::Custom600Headers()
 #endif
 {
-   string Header = GetCustom600Headers(RealURI);
+   string Header = pkgAcqMetaBase::Custom600Headers();
    Header += "\nFail-Ignore: true";
    return Header;
 }
                                                                        /*}}}*/
-// pkgAcqMetaClearSig::Done - We got a file                            /*{{{*/
+// pkgAcqMetaClearSig::Done - We got a file                            /*{{{*/
 // ---------------------------------------------------------------------
 void pkgAcqMetaClearSig::Done(std::string Message,unsigned long long Size,
                               HashStringList const &Hashes,
@@ -2165,21 +2273,12 @@ void pkgAcqMetaClearSig::Done(std::string Message,unsigned long long Size,
 
    if(AuthPass == false)
    {
-      if(CheckDownloadDone(Message, RealURI) == true)
+      if(CheckDownloadDone(Message) == true)
          QueueForSignatureVerify(DestFile, DestFile);
       return;
    }
-   else
-   {
-      if(CheckAuthDone(Message, RealURI) == true)
-      {
-         string FinalFile = _config->FindDir("Dir::State::lists");
-         FinalFile += URItoFileName(RealURI);
-
-         // queue for copy in place
-         TransactionManager->TransactionStageCopy(this, DestFile, FinalFile);
-      }
-   }
+   else if(CheckAuthDone(Message) == true)
+      TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename());
 }
                                                                        /*}}}*/
 void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
@@ -2194,9 +2293,7 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*
       // Queue the 'old' InRelease file for removal if we try Release.gpg
       // as otherwise the file will stay around and gives a false-auth
       // impression (CVE-2012-0214)
-      string FinalFile = _config->FindDir("Dir::State::lists");
-      FinalFile.append(URItoFileName(RealURI));
-      TransactionManager->TransactionStageRemoval(this, FinalFile);
+      TransactionManager->TransactionStageRemoval(this, GetFinalFilename());
       Status = StatDone;
 
       new pkgAcqMetaIndex(Owner, TransactionManager,
@@ -2206,7 +2303,7 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*
    }
    else
    {
-      if(CheckStopAuthentication(RealURI, Message))
+      if(CheckStopAuthentication(Message))
          return;
 
       _error->Warning(_("The data from '%s' is not signed. Packages "
@@ -2224,8 +2321,7 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*
           * that PackageFile objects are correctly filled in */
          if (FileExists(DestFile))
          {
-            string FinalFile = _config->FindDir("Dir::State::lists");
-            FinalFile += URItoFileName(RealURI);
+            string FinalFile = GetFinalFilename();
             /* InRelease files become Release files, otherwise
              * they would be considered as trusted later on */
             RealURI = RealURI.replace(RealURI.rfind("InRelease"), 9,
@@ -2482,13 +2578,18 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size, HashStringList
    }
 
    // Done, move it into position
-   string FinalFile = _config->FindDir("Dir::Cache::Archives");
-   FinalFile += flNotDir(StoreFilename);
+   string const FinalFile = GetFinalFilename();
    Rename(DestFile,FinalFile);
    StoreFilename = DestFile = FinalFile;
    Complete = true;
 }
                                                                        /*}}}*/
+// Acquire::Item::GetFinalFilename - Return the full final file path   /*{{{*/
+std::string pkgAcqArchive::GetFinalFilename() const
+{
+   return _config->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename);
+}
+                                                                       /*}}}*/
 // AcqArchive::Failed - Failure handler                                        /*{{{*/
 // ---------------------------------------------------------------------
 /* Here we try other sources */