X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/b7a1076f18022cbeb7baf4d82ab8bae0f725a573..03a34b88df3a74dac91c2f3b609d2c44e9462022:/apt-pkg/acquire-item.cc?ds=sidebyside diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 717751a6e..9b809db71 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -132,6 +132,49 @@ static std::string GetDiffIndexURI(IndexTarget const &Target) /*{{{*/ } /*}}}*/ +static void ReportMirrorFailureToCentral(pkgAcquire::Item const &I, std::string const &FailCode, std::string const &Details)/*{{{*/ +{ + // we only act if a mirror was used at all + if(I.UsedMirror.empty()) + return; +#if 0 + std::cerr << "\nReportMirrorFailure: " + << UsedMirror + << " Uri: " << DescURI() + << " FailCode: " + << FailCode << std::endl; +#endif + string const report = _config->Find("Methods::Mirror::ProblemReporting", + "/usr/lib/apt/apt-report-mirror-failure"); + if(!FileExists(report)) + return; + + std::vector const Args = { + report.c_str(), + I.UsedMirror.c_str(), + I.DescURI().c_str(), + FailCode.c_str(), + Details.c_str(), + NULL + }; + + pid_t pid = ExecFork(); + if(pid < 0) + { + _error->Error("ReportMirrorFailure Fork failed"); + return; + } + else if(pid == 0) + { + execvp(Args[0], (char**)Args.data()); + std::cerr << "Could not exec " << Args[0] << std::endl; + _exit(100); + } + if(!ExecWait(pid, "report-mirror-failure")) + _error->Warning("Couldn't report problem to '%s'", report.c_str()); +} + /*}}}*/ + static bool MessageInsecureRepository(bool const isError, std::string const &msg)/*{{{*/ { if (isError) @@ -281,6 +324,12 @@ bool pkgAcquire::Item::QueueURI(pkgAcquire::ItemDesc &Item) for a hashsum mismatch to happen which helps nobody) */ bool pkgAcqTransactionItem::QueueURI(pkgAcquire::ItemDesc &Item) { + if (TransactionManager->State != TransactionStarted) + { + if (_config->FindB("Debug::Acquire::Transaction", false)) + std::clog << "Skip " << Target.URI << " as transaction was already dealt with!" << std::endl; + return false; + } std::string const FinalFile = GetFinalFilename(); if (TransactionManager != NULL && TransactionManager->IMSHit == true && FileExists(FinalFile) == true) @@ -289,6 +338,21 @@ bool pkgAcqTransactionItem::QueueURI(pkgAcquire::ItemDesc &Item) Status = StatDone; return false; } + // If we got the InRelease file via a mirror, pick all indexes directly from this mirror, too + if (TransactionManager != nullptr && TransactionManager->BaseURI.empty() == false && + URI::SiteOnly(Item.URI) != URI::SiteOnly(TransactionManager->BaseURI)) + { + // this ensures we rewrite only once and only the first step + auto const OldBaseURI = Target.Option(IndexTarget::BASE_URI); + if (OldBaseURI.empty() == false && APT::String::Startswith(Item.URI, OldBaseURI)) + { + auto const ExtraPath = Item.URI.substr(OldBaseURI.length()); + Item.URI = flCombine(TransactionManager->BaseURI, ExtraPath); + UsedMirror = TransactionManager->UsedMirror; + if (Item.Description.find(" ") != string::npos) + Item.Description.replace(0, Item.Description.find(" "), UsedMirror); + } + } return pkgAcquire::Item::QueueURI(Item); } /* The transition manager InRelease itself (or its older sisters-in-law @@ -362,6 +426,7 @@ bool pkgAcqTransactionItem::TransactionState(TransactionStates const state) bool const Debug = _config->FindB("Debug::Acquire::Transaction", false); switch(state) { + case TransactionStarted: _error->Fatal("Item %s changed to invalid transaction start state!", Target.URI.c_str()); break; case TransactionAbort: if(Debug == true) std::clog << " Cancel: " << DestFile << std::endl; @@ -430,7 +495,7 @@ bool pkgAcqTransactionItem::TransactionState(TransactionStates const state) } else { if(Debug == true) std::clog << "rm " << DestFile << " # " << DescURI() << std::endl; - if (RemoveFile("TransactionCommit", DestFile) == false) + if (RemoveFile("TransItem::TransactionCommit", DestFile) == false) return false; } break; @@ -451,6 +516,7 @@ bool pkgAcqIndex::TransactionState(TransactionStates const state) switch (state) { + case TransactionStarted: _error->Fatal("AcqIndex %s changed to invalid transaction start state!", Target.URI.c_str()); break; case TransactionAbort: if (Stage == STAGE_DECOMPRESS_AND_VERIFY) { @@ -462,7 +528,7 @@ bool pkgAcqIndex::TransactionState(TransactionStates const state) break; case TransactionCommit: if (EraseFileName.empty() == false) - RemoveFile("TransactionCommit", EraseFileName); + RemoveFile("AcqIndex::TransactionCommit", EraseFileName); break; } return true; @@ -474,6 +540,7 @@ bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) switch (state) { + case TransactionStarted: _error->Fatal("Item %s changed to invalid transaction start state!", Target.URI.c_str()); break; case TransactionCommit: break; case TransactionAbort: @@ -510,6 +577,41 @@ class APT_HIDDEN NoActionItem : public pkgAcquire::Item /*{{{*/ } }; /*}}}*/ +class APT_HIDDEN CleanupItem : public pkgAcqTransactionItem /*{{{*/ +/* This class ensures that a file which was configured but isn't downloaded + for various reasons isn't kept in an old version in the lists directory. + In a way its the reverse of NoActionItem as it helps with removing files + even if the lists-cleanup is deactivated. */ +{ + public: + virtual std::string DescURI() const APT_OVERRIDE {return Target.URI;}; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE {return HashStringList();}; + + CleanupItem(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target) : + pkgAcqTransactionItem(Owner, TransactionManager, Target) + { + Status = StatDone; + DestFile = GetFinalFileNameFromURI(Target.URI); + } + bool TransactionState(TransactionStates const state) APT_OVERRIDE + { + switch (state) + { + case TransactionStarted: + break; + case TransactionAbort: + break; + case TransactionCommit: + if (_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "rm " << DestFile << " # " << DescURI() << std::endl; + if (RemoveFile("TransItem::TransactionCommit", DestFile) == false) + return false; + break; + } + return true; + } +}; + /*}}}*/ // Acquire::Item::Item - Constructor /*{{{*/ APT_IGNORE_DEPRECATED_PUSH @@ -563,8 +665,6 @@ APT_CONST bool pkgAcquire::Item::IsTrusted() const /*{{{*/ fetch this object */ void pkgAcquire::Item::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) { - if(ErrorText.empty()) - ErrorText = LookupTag(Message,"Message"); if (QueueCounter <= 1) { /* This indicates that the file is not available right now but might @@ -595,16 +695,63 @@ void pkgAcquire::Item::Failed(string const &Message,pkgAcquire::MethodConfig con } string const FailReason = LookupTag(Message, "FailReason"); - if (FailReason == "MaximumSizeExceeded") - RenameOnError(MaximumSizeExceeded); + enum { MAXIMUM_SIZE_EXCEEDED, HASHSUM_MISMATCH, OTHER } failreason = OTHER; + if ( FailReason == "MaximumSizeExceeded") + failreason = MAXIMUM_SIZE_EXCEEDED; else if (Status == StatAuthError) - RenameOnError(HashSumMismatch); + failreason = HASHSUM_MISMATCH; + + if(ErrorText.empty()) + { + if (Status == StatAuthError) + { + std::ostringstream out; + switch (failreason) + { + case HASHSUM_MISMATCH: + out << _("Hash Sum mismatch") << std::endl; + break; + case MAXIMUM_SIZE_EXCEEDED: + case OTHER: + out << LookupTag(Message, "Message") << std::endl; + break; + } + auto const ExpectedHashes = GetExpectedHashes(); + if (ExpectedHashes.empty() == false) + { + out << "Hashes of expected file:" << std::endl; + for (auto const &hs: ExpectedHashes) + out << " - " << hs.toStr() << std::endl; + } + if (failreason == HASHSUM_MISMATCH) + { + out << "Hashes of received file:" << std::endl; + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + { + std::string const tagname = std::string(*type) + "-Hash"; + std::string const hashsum = LookupTag(Message, tagname.c_str()); + if (hashsum.empty() == false) + out << " - " << HashString(*type, hashsum).toStr() << std::endl; + } + out << "Last modification reported: " << LookupTag(Message, "Last-Modified", "") << std::endl; + } + ErrorText = out.str(); + } + else + ErrorText = LookupTag(Message,"Message"); + } + + switch (failreason) + { + case MAXIMUM_SIZE_EXCEEDED: RenameOnError(MaximumSizeExceeded); break; + case HASHSUM_MISMATCH: RenameOnError(HashSumMismatch); break; + case OTHER: break; + } - // report mirror failure back to LP if we actually use a mirror if (FailReason.empty() == false) - ReportMirrorFailure(FailReason); + ReportMirrorFailureToCentral(*this, FailReason, ErrorText); else - ReportMirrorFailure(ErrorText); + ReportMirrorFailureToCentral(*this, ErrorText, ErrorText); if (QueueCounter > 1) Status = StatIdle; @@ -692,13 +839,10 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const { case HashSumMismatch: errtext = _("Hash Sum mismatch"); - Status = StatAuthError; - ReportMirrorFailure("HashChecksumFailure"); break; case SizeMismatch: errtext = _("Size mismatch"); Status = StatAuthError; - ReportMirrorFailure("SizeFailure"); break; case InvalidFormat: errtext = _("Invalid file format"); @@ -715,7 +859,6 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const break; case MaximumSizeExceeded: // the method is expected to report a good error for this - Status = StatError; break; case PDiffError: // no handling here, done by callers @@ -733,47 +876,9 @@ void pkgAcquire::Item::SetActiveSubprocess(const std::string &subprocess)/*{{{*/ } /*}}}*/ // Acquire::Item::ReportMirrorFailure /*{{{*/ -void pkgAcquire::Item::ReportMirrorFailure(string const &FailCode) +void pkgAcquire::Item::ReportMirrorFailure(std::string const &FailCode) { - // we only act if a mirror was used at all - if(UsedMirror.empty()) - return; -#if 0 - std::cerr << "\nReportMirrorFailure: " - << UsedMirror - << " Uri: " << DescURI() - << " FailCode: " - << FailCode << std::endl; -#endif - string report = _config->Find("Methods::Mirror::ProblemReporting", - "/usr/lib/apt/apt-report-mirror-failure"); - if(!FileExists(report)) - return; - - std::vector Args; - Args.push_back(report.c_str()); - Args.push_back(UsedMirror.c_str()); - Args.push_back(DescURI().c_str()); - Args.push_back(FailCode.c_str()); - Args.push_back(NULL); - - pid_t pid = ExecFork(); - if(pid < 0) - { - _error->Error("ReportMirrorFailure Fork failed"); - return; - } - else if(pid == 0) - { - execvp(Args[0], (char**)Args.data()); - std::cerr << "Could not exec " << Args[0] << std::endl; - _exit(100); - } - if(!ExecWait(pid, "report-mirror-failure")) - { - _error->Warning("Couldn't report problem to '%s'", - _config->Find("Methods::Mirror::ProblemReporting").c_str()); - } + ReportMirrorFailureToCentral(*this, FailCode, FailCode); } /*}}}*/ std::string pkgAcquire::Item::HashSum() const /*{{{*/ @@ -802,6 +907,32 @@ HashStringList pkgAcqTransactionItem::GetExpectedHashesFor(std::string const &Me } /*}}}*/ +static void LoadLastMetaIndexParser(pkgAcqMetaClearSig * const TransactionManager, std::string const &FinalRelease, std::string const &FinalInRelease)/*{{{*/ +{ + if (TransactionManager->IMSHit == true) + return; + if (RealFileExists(FinalInRelease) || RealFileExists(FinalRelease)) + { + TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone(); + if (TransactionManager->LastMetaIndexParser != NULL) + { + _error->PushToStack(); + if (RealFileExists(FinalInRelease)) + TransactionManager->LastMetaIndexParser->Load(FinalInRelease, NULL); + else + TransactionManager->LastMetaIndexParser->Load(FinalRelease, NULL); + // its unlikely to happen, but if what we have is bad ignore it + if (_error->PendingError()) + { + delete TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; + } + _error->RevertToStack(); + } + } +} + /*}}}*/ + // AcqMetaBase - Constructor /*{{{*/ pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, @@ -809,7 +940,7 @@ pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire * const Owner, IndexTarget const &DataTarget) : pkgAcqTransactionItem(Owner, TransactionManager, DataTarget), d(NULL), IndexTargets(IndexTargets), - AuthPass(false), IMSHit(false) + AuthPass(false), IMSHit(false), State(TransactionStarted) { } /*}}}*/ @@ -825,10 +956,20 @@ void pkgAcqMetaBase::AbortTransaction() if(_config->FindB("Debug::Acquire::Transaction", false) == true) std::clog << "AbortTransaction: " << TransactionManager << std::endl; + switch (TransactionManager->State) + { + case TransactionStarted: break; + case TransactionAbort: _error->Fatal("Transaction %s was already aborted and is aborted again", TransactionManager->Target.URI.c_str()); return; + case TransactionCommit: _error->Fatal("Transaction %s was already aborted and is now commited", TransactionManager->Target.URI.c_str()); return; + } + TransactionManager->State = TransactionAbort; + // ensure the toplevel is in error state too for (std::vector::iterator I = Transaction.begin(); I != Transaction.end(); ++I) { + if ((*I)->Status != pkgAcquire::Item::StatFetching) + Owner->Dequeue(*I); (*I)->TransactionState(TransactionAbort); } Transaction.clear(); @@ -858,6 +999,14 @@ void pkgAcqMetaBase::CommitTransaction() if(_config->FindB("Debug::Acquire::Transaction", false) == true) std::clog << "CommitTransaction: " << this << std::endl; + switch (TransactionManager->State) + { + case TransactionStarted: break; + case TransactionAbort: _error->Fatal("Transaction %s was already commited and is now aborted", TransactionManager->Target.URI.c_str()); return; + case TransactionCommit: _error->Fatal("Transaction %s was already commited and is again commited", TransactionManager->Target.URI.c_str()); return; + } + TransactionManager->State = TransactionCommit; + // move new files into place *and* remove files that are not // part of the transaction but are still on disk for (std::vector::iterator I = Transaction.begin(); @@ -886,37 +1035,36 @@ void pkgAcqMetaBase::TransactionStageRemoval(pkgAcqTransactionItem * const I, } /*}}}*/ // AcqMetaBase::GenerateAuthWarning - Check gpg authentication error /*{{{*/ +/* This method is called from ::Failed handlers. If it returns true, + no fallback to other files or modi is performed */ bool pkgAcqMetaBase::CheckStopAuthentication(pkgAcquire::Item * const I, const std::string &Message) { - // FIXME: this entire function can do now that we disallow going to - // a unauthenticated state and can cleanly rollback - string const Final = I->GetFinalFilename(); - if(FileExists(Final)) + std::string const GPGError = LookupTag(Message, "Message"); + if (FileExists(Final)) { I->Status = StatTransientNetworkError; - _error->Warning(_("An error occurred during the signature " - "verification. The repository is not updated " - "and the previous index files will be used. " - "GPG error: %s: %s"), - Desc.Description.c_str(), - LookupTag(Message,"Message").c_str()); + _error->Warning(_("An error occurred during the signature verification. " + "The repository is not updated and the previous index files will be used. " + "GPG error: %s: %s"), + Desc.Description.c_str(), + GPGError.c_str()); RunScripts("APT::Update::Auth-Failure"); return true; } else if (LookupTag(Message,"Message").find("NODATA") != string::npos) { /* Invalid signature file, reject (LP: #346386) (Closes: #627642) */ _error->Error(_("GPG error: %s: %s"), - Desc.Description.c_str(), - LookupTag(Message,"Message").c_str()); + Desc.Description.c_str(), + GPGError.c_str()); I->Status = StatAuthError; return true; } else { _error->Warning(_("GPG error: %s: %s"), - Desc.Description.c_str(), - LookupTag(Message,"Message").c_str()); + Desc.Description.c_str(), + GPGError.c_str()); } // gpgv method failed - ReportMirrorFailure("GPGFailure"); + ReportMirrorFailureToCentral(*this, "GPGFailure", GPGError); return false; } /*}}}*/ @@ -954,6 +1102,15 @@ bool pkgAcqMetaBase::CheckDownloadDone(pkgAcqTransactionItem * const I, const st // We have just finished downloading a Release file (it is not // verified yet) + // Save the final base URI we got this Release file from + if (I->UsedMirror.empty() == false && _config->FindB("Acquire::SameMirrorForAllIndexes", true)) + { + if (APT::String::Endswith(I->Desc.URI, "InRelease")) + TransactionManager->BaseURI = I->Desc.URI.substr(0, I->Desc.URI.length() - strlen("InRelease")); + else if (APT::String::Endswith(I->Desc.URI, "Release")) + TransactionManager->BaseURI = I->Desc.URI.substr(0, I->Desc.URI.length() - strlen("Release")); + } + std::string const FileName = LookupTag(Message,"Filename"); if (FileName != I->DestFile && RealFileExists(I->DestFile) == false) { @@ -1014,25 +1171,7 @@ bool pkgAcqMetaBase::CheckAuthDone(string const &Message) /*{{{*/ FinalInRelease = FinalFile.substr(0, FinalFile.length() - strlen("Release")) + "InRelease"; FinalRelease = FinalFile; } - if (RealFileExists(FinalInRelease) || RealFileExists(FinalRelease)) - { - TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone(); - if (TransactionManager->LastMetaIndexParser != NULL) - { - _error->PushToStack(); - if (RealFileExists(FinalInRelease)) - TransactionManager->LastMetaIndexParser->Load(FinalInRelease, NULL); - else - TransactionManager->LastMetaIndexParser->Load(FinalRelease, NULL); - // its unlikely to happen, but if what we have is bad ignore it - if (_error->PendingError()) - { - delete TransactionManager->LastMetaIndexParser; - TransactionManager->LastMetaIndexParser = NULL; - } - _error->RevertToStack(); - } - } + LoadLastMetaIndexParser(TransactionManager, FinalRelease, FinalInRelease); } if (TransactionManager->MetaIndexParser->Load(DestFile, &ErrorText) == false) @@ -1078,10 +1217,12 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ // than invent an entirely new flag we would need to carry for all of eternity. if (Target->Option(IndexTarget::ARCHITECTURE) == "all") { - if (TransactionManager->MetaIndexParser->IsArchitectureSupported("all") == false) - continue; - if (TransactionManager->MetaIndexParser->IsArchitectureAllSupportedFor(*Target) == false) + if (TransactionManager->MetaIndexParser->IsArchitectureSupported("all") == false || + TransactionManager->MetaIndexParser->IsArchitectureAllSupportedFor(*Target) == false) + { + new CleanupItem(Owner, TransactionManager, *Target); continue; + } } bool trypdiff = Target->OptionBool(IndexTarget::PDIFFS); @@ -1091,13 +1232,17 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ { // optional targets that we do not have in the Release file are skipped if (Target->IsOptional) + { + new CleanupItem(Owner, TransactionManager, *Target); continue; + } std::string const &arch = Target->Option(IndexTarget::ARCHITECTURE); if (arch.empty() == false) { if (TransactionManager->MetaIndexParser->IsArchitectureSupported(arch) == false) { + new CleanupItem(Owner, TransactionManager, *Target); _error->Notice(_("Skipping acquire of configured file '%s' as repository '%s' doesn't support architecture '%s'"), Target->MetaKey.c_str(), TransactionManager->Target.Description.c_str(), arch.c_str()); continue; @@ -1106,7 +1251,10 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ // ignore silently as this is pretty much the same as just shipping an empty file. // if we don't know which architectures are supported, we do NOT ignore it to notify user about this if (TransactionManager->MetaIndexParser->IsArchitectureSupported("*undefined*") == false) + { + new CleanupItem(Owner, TransactionManager, *Target); continue; + } } Status = StatAuthError; @@ -1116,11 +1264,21 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ else { auto const hashes = GetExpectedHashesFor(Target->MetaKey); - if (hashes.usable() == false && hashes.empty() == false) + if (hashes.empty() == false) { - _error->Warning(_("Skipping acquire of configured file '%s' as repository '%s' provides only weak security information for it"), + if (hashes.usable() == false) + { + new CleanupItem(Owner, TransactionManager, *Target); + _error->Warning(_("Skipping acquire of configured file '%s' as repository '%s' provides only weak security information for it"), Target->MetaKey.c_str(), TransactionManager->Target.Description.c_str()); - continue; + continue; + } + // empty files are skipped as acquiring the very small compressed files is a waste of time + else if (hashes.FileSize() == 0) + { + new CleanupItem(Owner, TransactionManager, *Target); + continue; + } } } @@ -1207,25 +1365,8 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ } } /*}}}*/ -bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ +bool pkgAcqMetaBase::VerifyVendor(string const &) /*{{{*/ { - string::size_type pos; - - // check for missing sigs (that where not fatal because otherwise we had - // bombed earlier) - string missingkeys; - string msg = _("There is no public key available for the " - "following key IDs:\n"); - pos = Message.find("NO_PUBKEY "); - if (pos != std::string::npos) - { - string::size_type start = pos+strlen("NO_PUBKEY "); - string Fingerprint = Message.substr(start, Message.find("\n")-start); - missingkeys += (Fingerprint); - } - if(!missingkeys.empty()) - _error->Warning("%s", (msg + missingkeys).c_str()); - string Transformed = TransactionManager->MetaIndexParser->GetExpectedDist(); if (Transformed == "../project/experimental") @@ -1233,7 +1374,7 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ Transformed = "experimental"; } - pos = Transformed.rfind('/'); + auto pos = Transformed.rfind('/'); if (pos != string::npos) { Transformed = Transformed.substr(0, pos); @@ -1342,6 +1483,15 @@ string pkgAcqMetaClearSig::Custom600Headers() const return Header; } /*}}}*/ +void pkgAcqMetaClearSig::Finished() /*{{{*/ +{ + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "Finished: " << DestFile <State == TransactionStarted && + TransactionManager->TransactionHasError() == false) + TransactionManager->CommitTransaction(); +} + /*}}}*/ bool pkgAcqMetaClearSig::VerifyDone(std::string const &Message, /*{{{*/ pkgAcquire::MethodConfig const * const Cnf) { @@ -1428,30 +1578,7 @@ void pkgAcqMetaClearSig::Failed(string const &Message,pkgAcquire::MethodConfig c string const FinalInRelease = GetFinalFilename(); Rename(DestFile, PartialRelease); TransactionManager->TransactionStageCopy(this, PartialRelease, FinalRelease); - - if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) - { - // open the last Release if we have it - if (TransactionManager->IMSHit == false) - { - TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone(); - if (TransactionManager->LastMetaIndexParser != NULL) - { - _error->PushToStack(); - if (RealFileExists(FinalInRelease)) - TransactionManager->LastMetaIndexParser->Load(FinalInRelease, NULL); - else - TransactionManager->LastMetaIndexParser->Load(FinalRelease, NULL); - // its unlikely to happen, but if what we have is bad ignore it - if (_error->PendingError()) - { - delete TransactionManager->LastMetaIndexParser; - TransactionManager->LastMetaIndexParser = NULL; - } - _error->RevertToStack(); - } - } - } + LoadLastMetaIndexParser(TransactionManager, FinalRelease, FinalInRelease); // we parse the indexes here because at this point the user wanted // a repository that may potentially harm him @@ -1524,15 +1651,6 @@ void pkgAcqMetaIndex::Failed(string const &Message, } } /*}}}*/ -void pkgAcqMetaIndex::Finished() /*{{{*/ -{ - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "Finished: " << DestFile <TransactionHasError() == false) - TransactionManager->CommitTransaction(); -} - /*}}}*/ std::string pkgAcqMetaIndex::DescURI() const /*{{{*/ { return Target.URI; @@ -1667,29 +1785,7 @@ void pkgAcqMetaSig::Failed(string const &Message,pkgAcquire::MethodConfig const // only allow going further if the user explicitly wants it if (AllowInsecureRepositories(_("The repository '%s' is not signed."), MetaIndex->Target.Description, TransactionManager->MetaIndexParser, TransactionManager, this) == true) { - if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) - { - // open the last Release if we have it - if (TransactionManager->IMSHit == false) - { - TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone(); - if (TransactionManager->LastMetaIndexParser != NULL) - { - _error->PushToStack(); - if (RealFileExists(FinalInRelease)) - TransactionManager->LastMetaIndexParser->Load(FinalInRelease, NULL); - else - TransactionManager->LastMetaIndexParser->Load(FinalRelease, NULL); - // its unlikely to happen, but if what we have is bad ignore it - if (_error->PendingError()) - { - delete TransactionManager->LastMetaIndexParser; - TransactionManager->LastMetaIndexParser = NULL; - } - _error->RevertToStack(); - } - } - } + LoadLastMetaIndexParser(TransactionManager, FinalRelease, FinalInRelease); // we parse the indexes here because at this point the user wanted // a repository that may potentially harm him @@ -1719,6 +1815,22 @@ pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire * const Owner, IndexTarget const &Target) : pkgAcqTransactionItem(Owner, TransactionManager, Target), d(NULL) { +} + /*}}}*/ +void pkgAcqBaseIndex::Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ +{ + pkgAcquire::Item::Failed(Message, Cnf); + if (TransactionManager == nullptr || TransactionManager->MetaIndexParser == nullptr || + Status != StatAuthError) + return; + + ErrorText.append("Release file created at: "); + auto const timespec = TransactionManager->MetaIndexParser->GetDate(); + if (timespec == 0) + ErrorText.append(""); + else + ErrorText.append(TimeRFC1123(timespec)); + ErrorText.append("\n"); } /*}}}*/ pkgAcqBaseIndex::~pkgAcqBaseIndex() {} @@ -2160,7 +2272,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ /*}}}*/ void pkgAcqDiffIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ { - Item::Failed(Message,Cnf); + pkgAcqBaseIndex::Failed(Message,Cnf); Status = StatDone; if(Debug) @@ -2241,7 +2353,7 @@ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire * const Owner, /*}}}*/ void pkgAcqIndexDiffs::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ { - Item::Failed(Message,Cnf); + pkgAcqBaseIndex::Failed(Message,Cnf); Status = StatDone; DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI), Target); @@ -2446,7 +2558,7 @@ void pkgAcqIndexMergeDiffs::Failed(string const &Message,pkgAcquire::MethodConfi if(Debug) std::clog << "pkgAcqIndexMergeDiffs failed: " << Desc.URI << " with " << Message << std::endl; - Item::Failed(Message,Cnf); + pkgAcqBaseIndex::Failed(Message,Cnf); Status = StatDone; // check if we are the first to fail, otherwise we are done here @@ -2610,6 +2722,10 @@ void pkgAcqIndex::Init(string const &URI, string const &URIDesc, DestFile = GetPartialFileNameFromURI(URI); NextCompressionExtension(CurrentCompressionExtension, CompressionExtensions, false); + // store file size of the download to ensure the fetcher gives + // accurate progress reporting + FileSize = GetExpectedHashes().FileSize(); + if (CurrentCompressionExtension == "uncompressed") { Desc.URI = URI; @@ -2680,7 +2796,7 @@ string pkgAcqIndex::Custom600Headers() const // AcqIndex::Failed - getting the indexfile failed /*{{{*/ void pkgAcqIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) { - Item::Failed(Message,Cnf); + pkgAcqBaseIndex::Failed(Message,Cnf); // authorisation matches will not be fixed by other compression types if (Status != StatAuthError) @@ -2754,9 +2870,8 @@ void pkgAcqIndex::StageDownloadDone(string const &Message) // methods like file:// give us an alternative (uncompressed) file else if (Target.KeepCompressed == false && AltFilename.empty() == false) { - if (CurrentCompressionExtension != "uncompressed") - DestFile.erase(DestFile.length() - (CurrentCompressionExtension.length() + 1)); Filename = AltFilename; + EraseFileName.clear(); } // Methods like e.g. "file:" will give us a (compressed) FileName that is // not the "DestFile" we set, in this case we uncompress from the local file @@ -2786,7 +2901,7 @@ void pkgAcqIndex::StageDownloadDone(string const &Message) DestFile = "/dev/null"; } - if (EraseFileName.empty()) + if (EraseFileName.empty() && Filename != AltFilename) EraseFileName = Filename; // queue uri for the next stage