#include <ctime>
#include <sstream>
#include <numeric>
+#include <random>
#include <apti18n.h>
/*}}}*/
<< FailCode << std::endl;
#endif
string const report = _config->Find("Methods::Mirror::ProblemReporting",
- "/usr/lib/apt/apt-report-mirror-failure");
+ LIBEXEC_DIR "/apt-report-mirror-failure");
if(!FileExists(report))
return;
if (TargetIsAllowedToBe(TransactionManager->Target, msg) == true)
{
- MessageInsecureRepository(false, msgstr, repo);
+ //MessageInsecureRepository(false, msgstr, repo);
return true;
}
return false;
}
// If we got the InRelease file via a mirror, pick all indexes directly from this mirror, too
- if (TransactionManager->BaseURI.empty() == false &&
+ if (TransactionManager->BaseURI.empty() == false && UsedMirror.empty() &&
URI::SiteOnly(Item.URI) != URI::SiteOnly(TransactionManager->BaseURI))
{
// this ensures we rewrite only once and only the first step
}
std::string pkgAcqDiffIndex::GetFinalFilename() const
{
- return GetFinalFileNameFromURI(GetDiffIndexURI(Target));
+ std::string const FinalFile = GetFinalFileNameFromURI(GetDiffIndexURI(Target));
+ // we don't want recompress, so lets keep whatever we got
+ if (CurrentCompressionExtension == "uncompressed")
+ return FinalFile;
+ return FinalFile + "." + CurrentCompressionExtension;
}
std::string pkgAcqIndex::GetFinalFilename() const
{
}
std::string pkgAcqDiffIndex::GetMetaKey() const
{
- return GetDiffIndexFileName(Target.MetaKey);
+ auto const metakey = GetDiffIndexFileName(Target.MetaKey);
+ if (CurrentCompressionExtension == "uncompressed")
+ return metakey;
+ return metakey + "." + CurrentCompressionExtension;
}
/*}}}*/
//pkgAcqTransactionItem::TransactionState and specialisations for child classes /*{{{*/
/*}}}*/
// Acquire::Item::Item - Constructor /*{{{*/
+class pkgAcquire::Item::Private
+{
+public:
+ std::vector<std::string> PastRedirections;
+};
APT_IGNORE_DEPRECATED_PUSH
pkgAcquire::Item::Item(pkgAcquire * const owner) :
FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false), Local(false),
- QueueCounter(0), ExpectedAdditionalItems(0), Owner(owner), d(NULL)
+ QueueCounter(0), ExpectedAdditionalItems(0), Owner(owner), d(new Private())
{
Owner->Add(this);
Status = StatIdle;
pkgAcquire::Item::~Item()
{
Owner->Remove(this);
+ delete d;
}
/*}}}*/
std::string pkgAcquire::Item::Custom600Headers() const /*{{{*/
// ---------------------------------------------------------------------
/* We return to an idle state if there are still other queues that could
fetch this object */
+static void formatHashsum(std::ostream &out, HashString const &hs)
+{
+ auto const type = hs.HashType();
+ if (type == "Checksum-FileSize")
+ out << " - Filesize";
+ else
+ out << " - " << type;
+ out << ':' << hs.HashValue();
+ if (hs.usable() == false)
+ out << " [weak]";
+ out << std::endl;
+}
void pkgAcquire::Item::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)
{
if (QueueCounter <= 1)
}
string const FailReason = LookupTag(Message, "FailReason");
- enum { MAXIMUM_SIZE_EXCEEDED, HASHSUM_MISMATCH, WEAK_HASHSUMS, OTHER } failreason = OTHER;
+ enum { MAXIMUM_SIZE_EXCEEDED, HASHSUM_MISMATCH, WEAK_HASHSUMS, REDIRECTION_LOOP, OTHER } failreason = OTHER;
if ( FailReason == "MaximumSizeExceeded")
failreason = MAXIMUM_SIZE_EXCEEDED;
else if ( FailReason == "WeakHashSums")
failreason = WEAK_HASHSUMS;
+ else if (FailReason == "RedirectionLoop")
+ failreason = REDIRECTION_LOOP;
else if (Status == StatAuthError)
failreason = HASHSUM_MISMATCH;
if(ErrorText.empty())
{
+ std::ostringstream out;
+ switch (failreason)
+ {
+ case HASHSUM_MISMATCH:
+ out << _("Hash Sum mismatch") << std::endl;
+ break;
+ case WEAK_HASHSUMS:
+ out << _("Insufficient information available to perform this download securely") << std::endl;
+ break;
+ case REDIRECTION_LOOP:
+ out << "Redirection loop encountered" << std::endl;
+ break;
+ case MAXIMUM_SIZE_EXCEEDED:
+ out << LookupTag(Message, "Message") << std::endl;
+ break;
+ case OTHER:
+ out << LookupTag(Message, "Message");
+ break;
+ }
+
if (Status == StatAuthError)
{
- std::ostringstream out;
- switch (failreason)
- {
- case HASHSUM_MISMATCH:
- out << _("Hash Sum mismatch") << std::endl;
- break;
- case WEAK_HASHSUMS:
- out << _("Insufficient information available to perform this download securely") << 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();
- if (hs.usable() == false)
- out << " [weak]";
- out << std::endl;
- }
+ formatHashsum(out, hs);
}
if (failreason == HASHSUM_MISMATCH)
{
std::string const tagname = std::string(*type) + "-Hash";
std::string const hashsum = LookupTag(Message, tagname.c_str());
if (hashsum.empty() == false)
- {
- auto const hs = HashString(*type, hashsum);
- out << " - " << hs.toStr();
- if (hs.usable() == false)
- out << " [weak]";
- out << std::endl;
- }
+ formatHashsum(out, HashString(*type, hashsum));
}
- out << "Last modification reported: " << LookupTag(Message, "Last-Modified", "<none>") << std::endl;
}
- ErrorText = out.str();
+ auto const lastmod = LookupTag(Message, "Last-Modified", "");
+ if (lastmod.empty() == false)
+ out << "Last modification reported: " << lastmod << std::endl;
}
- else
- ErrorText = LookupTag(Message,"Message");
+ ErrorText = out.str();
}
switch (failreason)
case MAXIMUM_SIZE_EXCEEDED: RenameOnError(MaximumSizeExceeded); break;
case HASHSUM_MISMATCH: RenameOnError(HashSumMismatch); break;
case WEAK_HASHSUMS: break;
+ case REDIRECTION_LOOP: break;
case OTHER: break;
}
return hs != NULL ? hs->toStr() : "";
}
/*}}}*/
+bool pkgAcquire::Item::IsRedirectionLoop(std::string const &NewURI) /*{{{*/
+{
+ // store can fail due to permission errors and the item will "loop" then
+ if (APT::String::Startswith(NewURI, "store:"))
+ return false;
+ if (d->PastRedirections.empty())
+ {
+ d->PastRedirections.push_back(NewURI);
+ return false;
+ }
+ auto const LastURI = std::prev(d->PastRedirections.end());
+ // redirections to the same file are a way of restarting/resheduling,
+ // individual methods will have to make sure that they aren't looping this way
+ if (*LastURI == NewURI)
+ return false;
+ if (std::find(d->PastRedirections.begin(), LastURI, NewURI) != LastURI)
+ return true;
+ d->PastRedirections.push_back(NewURI);
+ return false;
+}
+ /*}}}*/
+int pkgAcquire::Item::Priority() /*{{{*/
+{
+ // Stage 1: Meta indices and diff indices
+ // - those need to be fetched first to have progress reporting working
+ // for the rest
+ if (dynamic_cast<pkgAcqMetaSig*>(this) != nullptr
+ || dynamic_cast<pkgAcqMetaBase*>(this) != nullptr
+ || dynamic_cast<pkgAcqDiffIndex*>(this) != nullptr)
+ return 1000;
+ // Stage 2: Diff files
+ // - fetch before complete indexes so we can apply the diffs while fetching
+ // larger files.
+ if (dynamic_cast<pkgAcqIndexDiffs*>(this) != nullptr ||
+ dynamic_cast<pkgAcqIndexMergeDiffs*>(this) != nullptr)
+ return 800;
+
+ // Stage 3: The rest - complete index files and other stuff
+ return 500;
+}
+ /*}}}*/
pkgAcqTransactionItem::pkgAcqTransactionItem(pkgAcquire * const Owner, /*{{{*/
pkgAcqMetaClearSig * const transactionManager, IndexTarget const &target) :
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"));
+ TransactionManager->UsedMirror = I->UsedMirror;
+ }
else if (APT::String::Endswith(I->Desc.URI, "Release"))
+ {
TransactionManager->BaseURI = I->Desc.URI.substr(0, I->Desc.URI.length() - strlen("Release"));
+ TransactionManager->UsedMirror = I->UsedMirror;
+ }
}
std::string const FileName = LookupTag(Message,"Filename");
if (hasReleaseFile && verify == false)
hasHashes = std::any_of(IndexTargets.begin(), IndexTargets.end(),
[&](IndexTarget const &Target) { return TransactionManager->MetaIndexParser->Exists(Target.MetaKey); });
+ if (_config->FindB("Acquire::IndexTargets::Randomized", true) && likely(IndexTargets.empty() == false))
+ {
+ /* For fallback handling and to have some reasonable progress information
+ we can't randomize everything, but at least the order in the same type
+ can be as we shouldn't be telling the mirrors (and everyone else watching)
+ which is native/foreign arch, specific order of preference of translations, … */
+ auto range_start = IndexTargets.begin();
+ std::random_device rd;
+ std::default_random_engine g(rd());
+ do {
+ auto const type = range_start->Option(IndexTarget::CREATED_BY);
+ auto const range_end = std::find_if_not(range_start, IndexTargets.end(),
+ [&type](IndexTarget const &T) { return type == T.Option(IndexTarget::CREATED_BY); });
+ std::shuffle(range_start, range_end, g);
+ range_start = range_end;
+ } while (range_start != IndexTargets.end());
+ }
for (auto&& Target: IndexTargets)
{
// if we have seen a target which is created-by a target this one here is declared a
// than invent an entirely new flag we would need to carry for all of eternity.
if (hasReleaseFile && Target.Option(IndexTarget::ARCHITECTURE) == "all")
{
- if (TransactionManager->MetaIndexParser->IsArchitectureSupported("all") == false ||
- TransactionManager->MetaIndexParser->IsArchitectureAllSupportedFor(Target) == false)
+ if (TransactionManager->MetaIndexParser->IsArchitectureAllSupportedFor(Target) == false)
{
new CleanupItem(Owner, TransactionManager, Target);
continue;
/*}}}*/
bool pkgAcqMetaBase::VerifyVendor(string const &) /*{{{*/
{
- string Transformed = TransactionManager->MetaIndexParser->GetExpectedDist();
-
- if (Transformed == "../project/experimental")
- {
- Transformed = "experimental";
- }
-
- auto pos = Transformed.rfind('/');
- if (pos != string::npos)
- {
- Transformed = Transformed.substr(0, pos);
- }
-
- if (Transformed == ".")
- {
- Transformed = "";
- }
-
if (TransactionManager->MetaIndexParser->GetValidUntil() > 0)
{
time_t const invalid_since = time(NULL) - TransactionManager->MetaIndexParser->GetValidUntil();
TransactionManager->LastMetaIndexParser = NULL;
}
- if (_config->FindB("Debug::pkgAcquire::Auth", false))
+ if (_config->FindB("Debug::pkgAcquire::Auth", false))
{
std::cerr << "Got Codename: " << TransactionManager->MetaIndexParser->GetCodename() << std::endl;
+ std::cerr << "Got Suite: " << TransactionManager->MetaIndexParser->GetSuite() << std::endl;
std::cerr << "Expecting Dist: " << TransactionManager->MetaIndexParser->GetExpectedDist() << std::endl;
- std::cerr << "Transformed Dist: " << Transformed << std::endl;
}
- if (TransactionManager->MetaIndexParser->CheckDist(Transformed) == false)
+ // One day that might become fatal…
+ auto const ExpectedDist = TransactionManager->MetaIndexParser->GetExpectedDist();
+ auto const NowCodename = TransactionManager->MetaIndexParser->GetCodename();
+ if (TransactionManager->MetaIndexParser->CheckDist(ExpectedDist) == false)
+ _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"),
+ Desc.Description.c_str(), ExpectedDist.c_str(), NowCodename.c_str());
+ // might be okay, might be not
+ if (TransactionManager->LastMetaIndexParser != nullptr)
{
- // This might become fatal one day
-// Status = StatAuthError;
-// ErrorText = "Conflicting distribution; expected "
-// + MetaIndexParser->GetExpectedDist() + " but got "
-// + MetaIndexParser->GetCodename();
-// return false;
- if (!Transformed.empty())
- {
- _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"),
- Desc.Description.c_str(),
- Transformed.c_str(),
- TransactionManager->MetaIndexParser->GetCodename().c_str());
- }
+ auto const LastCodename = TransactionManager->LastMetaIndexParser->GetCodename();
+ if (LastCodename.empty() == false && NowCodename.empty() == false && LastCodename != NowCodename)
+ _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"),
+ Desc.Description.c_str(), LastCodename.c_str(), NowCodename.c_str());
}
-
return true;
}
/*}}}*/
}
else if(MetaIndex->CheckAuthDone(Message) == true)
{
- if (TransactionManager->IMSHit == false)
+ auto const Releasegpg = GetFinalFilename();
+ auto const Release = MetaIndex->GetFinalFilename();
+ // if this is an IMS-Hit on Release ensure we also have the the Release.gpg file stored
+ // (previously an unknown pubkey) – but only if the Release file exists locally (unlikely
+ // event of InRelease removed from the mirror causing fallback but still an IMS-Hit)
+ if (TransactionManager->IMSHit == false ||
+ (FileExists(Releasegpg) == false && FileExists(Release) == true))
{
- TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename());
- TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename());
+ TransactionManager->TransactionStageCopy(this, DestFile, Releasegpg);
+ TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, Release);
}
}
else if (MetaIndex->Status != StatAuthError)
pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire * const Owner,
pkgAcqMetaClearSig * const TransactionManager,
IndexTarget const &Target)
- : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL), diffs(NULL)
+ : pkgAcqIndex(Owner, TransactionManager, Target, true), d(NULL), diffs(NULL)
{
// FIXME: Magic number as an upper bound on pdiffs we will reasonably acquire
ExpectedAdditionalItems = 40;
-
Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
- Desc.Owner = this;
- Desc.Description = GetDiffIndexFileName(Target.Description);
- Desc.ShortDesc = Target.ShortDesc;
- Desc.URI = GetDiffIndexURI(Target);
-
- DestFile = GetPartialFileNameFromURI(Desc.URI);
+ CompressionExtensions.clear();
+ {
+ std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+ if (types.empty() == false)
+ {
+ std::ostringstream os;
+ std::copy_if(types.begin(), types.end()-1, std::ostream_iterator<std::string>(os, " "), [&](std::string const type) {
+ if (type == "uncompressed")
+ return true;
+ return TransactionManager->MetaIndexParser->Exists(GetDiffIndexFileName(Target.MetaKey) + '.' + type);
+ });
+ os << *types.rbegin();
+ CompressionExtensions = os.str();
+ }
+ }
+ if (Target.Option(IndexTarget::COMPRESSIONTYPES).find("by-hash") != std::string::npos)
+ CompressionExtensions = "by-hash " + CompressionExtensions;
+ Init(GetDiffIndexURI(Target), GetDiffIndexFileName(Target.Description), Target.ShortDesc);
if(Debug)
std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl;
-
- QueueURI(Desc);
-}
- /*}}}*/
-// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
-// ---------------------------------------------------------------------
-/* The only header we use is the last-modified header. */
-string pkgAcqDiffIndex::Custom600Headers() const
-{
- if (TransactionManager->LastMetaIndexParser != NULL)
- return "\nIndex-File: true";
-
- string const Final = GetFinalFilename();
-
- if(Debug)
- std::clog << "Custom600Header-IMS: " << Final << std::endl;
-
- struct stat Buf;
- if (stat(Final.c_str(),&Buf) != 0)
- return "\nIndex-File: true";
-
- return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime, false);
}
/*}}}*/
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);
+ new pkgAcqIndexDiffs(Owner, TransactionManager, Target, UsedMirror, Target.URI);
+}
+ /*}}}*/
+static bool RemoveFileForBootstrapLinking(bool const Debug, std::string const &For, std::string const &Boot)/*{{{*/
+{
+ if (FileExists(Boot) && RemoveFile("Bootstrap-linking", Boot) == false)
+ {
+ if (Debug)
+ std::clog << "Bootstrap-linking for patching " << For
+ << " by removing stale " << Boot << " failed!" << std::endl;
+ return false;
+ }
+ return true;
}
/*}}}*/
bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/
std::clog << "pkgAcqDiffIndex::ParseIndexDiff() " << IndexDiffFile
<< std::endl;
- FileFd Fd(IndexDiffFile,FileFd::ReadOnly);
+ FileFd Fd(IndexDiffFile, FileFd::ReadOnly, FileFd::Extension);
pkgTagFile TF(&Fd);
if (Fd.IsOpen() == false || Fd.Failed())
return false;
HashStringList ServerHashes;
unsigned long long ServerSize = 0;
- auto const &posix = std::locale("C.UTF-8");
+ auto const &posix = std::locale::classic();
for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
{
std::string tagname = *type;
if (unlikely(Final.empty())) // because we wouldn't be called in such a case
return false;
std::string const PartialFile = GetPartialFileNameFromURI(Target.URI);
- if (FileExists(PartialFile) && RemoveFile("Bootstrap-linking", PartialFile) == false)
- {
- if (Debug)
- std::clog << "Bootstrap-linking for patching " << CurrentPackagesFile
- << " by removing stale " << PartialFile << " failed!" << std::endl;
+ std::string const PatchedFile = GetKeepCompressedFileName(PartialFile + "-patched", Target);
+ if (RemoveFileForBootstrapLinking(Debug, CurrentPackagesFile, PartialFile) == false ||
+ RemoveFileForBootstrapLinking(Debug, CurrentPackagesFile, PatchedFile) == false)
return false;
- }
for (auto const &ext : APT::Configuration::getCompressorExtensions())
{
- std::string const Partial = PartialFile + ext;
- if (FileExists(Partial) && RemoveFile("Bootstrap-linking", Partial) == false)
- {
- if (Debug)
- std::clog << "Bootstrap-linking for patching " << CurrentPackagesFile
- << " by removing stale " << Partial << " failed!" << std::endl;
+ if (RemoveFileForBootstrapLinking(Debug, CurrentPackagesFile, PartialFile + ext) == false ||
+ RemoveFileForBootstrapLinking(Debug, CurrentPackagesFile, PatchedFile + ext) == false)
return false;
- }
}
std::string const Ext = Final.substr(CurrentPackagesFile.length());
std::string const Partial = PartialFile + Ext;
}
}
+ std::string indexURI = Desc.URI;
+ auto const byhashidx = indexURI.find("/by-hash/");
+ if (byhashidx != std::string::npos)
+ indexURI = indexURI.substr(0, byhashidx - strlen(".diff"));
+ else
+ {
+ auto end = indexURI.length() - strlen(".diff/Index");
+ if (CurrentCompressionExtension != "uncompressed")
+ end -= (1 + CurrentCompressionExtension.length());
+ indexURI = indexURI.substr(0, end);
+ }
+
if (pdiff_merge == false)
- new pkgAcqIndexDiffs(Owner, TransactionManager, Target, available_patches);
+ new pkgAcqIndexDiffs(Owner, TransactionManager, Target, UsedMirror, indexURI, available_patches);
else
{
diffs = new std::vector<pkgAcqIndexMergeDiffs*>(available_patches.size());
for(size_t i = 0; i < available_patches.size(); ++i)
(*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, TransactionManager,
- Target,
+ Target, UsedMirror, indexURI,
available_patches[i],
diffs);
}
/*}}}*/
void pkgAcqDiffIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/
{
- pkgAcqBaseIndex::Failed(Message,Cnf);
+ if (CommonFailed(GetDiffIndexURI(Target), GetDiffIndexFileName(Target.Description), Message, Cnf))
+ return;
+
Status = StatDone;
ExpectedAdditionalItems = 0;
pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire * const Owner,
pkgAcqMetaClearSig * const TransactionManager,
IndexTarget const &Target,
+ std::string const &indexUsedMirror, std::string const &indexURI,
vector<DiffInfo> const &diffs)
- : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL),
+ : pkgAcqBaseIndex(Owner, TransactionManager, Target), indexURI(indexURI),
available_patches(diffs)
{
DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI), Target);
Description = Target.Description;
Desc.ShortDesc = Target.ShortDesc;
+ UsedMirror = indexUsedMirror;
+ if (UsedMirror == "DIRECT")
+ UsedMirror.clear();
+ else if (UsedMirror.empty() == false && Description.find(" ") != string::npos)
+ Description.replace(0, Description.find(" "), UsedMirror);
+
if(available_patches.empty() == true)
{
// we are done (yeah!), check hashes against the final file
}
// queue the right diff
- Desc.URI = Target.URI + ".diff/" + available_patches[0].file + ".gz";
+ Desc.URI = indexURI + ".diff/" + available_patches[0].file + ".gz";
Desc.Description = Description + " " + available_patches[0].file + string(".pdiff");
DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI + ".diff/" + available_patches[0].file), Target);
// see if there is more to download
if(available_patches.empty() == false)
{
- new pkgAcqIndexDiffs(Owner, TransactionManager, Target, available_patches);
+ new pkgAcqIndexDiffs(Owner, TransactionManager, Target, UsedMirror, indexURI, available_patches);
Finish();
} else {
DestFile = PatchedFile;
if(State != StateApplyDiff)
return pkgAcqBaseIndex::Custom600Headers();
std::ostringstream patchhashes;
- HashStringList const ExpectedHashes = available_patches[0].patch_hashes;
- for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs)
- patchhashes << "\nPatch-0-" << hs->HashType() << "-Hash: " << hs->HashValue();
+ for (auto && hs : available_patches[0].result_hashes)
+ patchhashes << "\nStart-" << hs.HashType() << "-Hash: " << hs.HashValue();
+ for (auto && hs : available_patches[0].patch_hashes)
+ patchhashes << "\nPatch-0-" << hs.HashType() << "-Hash: " << hs.HashValue();
patchhashes << pkgAcqBaseIndex::Custom600Headers();
return patchhashes.str();
}
pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner,
pkgAcqMetaClearSig * const TransactionManager,
IndexTarget const &Target,
+ std::string const &indexUsedMirror, std::string const &indexURI,
DiffInfo const &patch,
std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches)
- : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL),
- patch(patch), allPatches(allPatches), State(StateFetchDiff)
+ : pkgAcqBaseIndex(Owner, TransactionManager, Target), indexURI(indexURI),
+ patch(patch), allPatches(allPatches), State(StateFetchDiff)
{
Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
- Desc.Owner = this;
Description = Target.Description;
+ UsedMirror = indexUsedMirror;
+ if (UsedMirror == "DIRECT")
+ UsedMirror.clear();
+ else if (UsedMirror.empty() == false && Description.find(" ") != string::npos)
+ Description.replace(0, Description.find(" "), UsedMirror);
+
+ Desc.Owner = this;
Desc.ShortDesc = Target.ShortDesc;
- Desc.URI = Target.URI + ".diff/" + patch.file + ".gz";
+ Desc.URI = indexURI + ".diff/" + patch.file + ".gz";
Desc.Description = Description + " " + patch.file + ".pdiff";
- DestFile = GetPartialFileNameFromURI(Desc.URI);
+ DestFile = GetPartialFileNameFromURI(Target.URI + ".diff/" + patch.file + ".gz");
if(Debug)
std::clog << "pkgAcqIndexMergeDiffs: " << Desc.URI << std::endl;
return pkgAcqBaseIndex::Custom600Headers();
std::ostringstream patchhashes;
unsigned int seen_patches = 0;
+ for (auto && hs : (*allPatches)[0]->patch.result_hashes)
+ patchhashes << "\nStart-" << hs.HashType() << "-Hash: " << hs.HashValue();
for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin();
I != allPatches->end(); ++I)
{
HashStringList const ExpectedHashes = (*I)->patch.patch_hashes;
for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs)
- patchhashes << "\nPatch-" << seen_patches << "-" << hs->HashType() << "-Hash: " << hs->HashValue();
+ patchhashes << "\nPatch-" << std::to_string(seen_patches) << "-" << hs->HashType() << "-Hash: " << hs->HashValue();
++seen_patches;
}
patchhashes << pkgAcqBaseIndex::Custom600Headers();
// AcqIndex::AcqIndex - Constructor /*{{{*/
pkgAcqIndex::pkgAcqIndex(pkgAcquire * const Owner,
pkgAcqMetaClearSig * const TransactionManager,
- IndexTarget const &Target)
+ IndexTarget const &Target, bool const Derived)
: pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL), Stage(STAGE_DOWNLOAD),
CompressionExtensions(Target.Option(IndexTarget::COMPRESSIONTYPES))
{
+ if (Derived)
+ return;
Init(Target.URI, Target.Description, Target.ShortDesc);
if(_config->FindB("Debug::Acquire::Transaction", false) == true)
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;
Desc.URI = URI + '.' + CurrentCompressionExtension;
DestFile = DestFile + '.' + CurrentCompressionExtension;
}
+ else
+ Desc.URI = URI;
HashStringList const Hashes = GetExpectedHashes();
HashString const * const TargetHash = Hashes.find(NULL);
DestFile = DestFile + '.' + CurrentCompressionExtension;
}
+ // store file size of the download to ensure the fetcher gives
+ // accurate progress reporting
+ FileSize = GetExpectedHashes().FileSize();
Desc.Description = URIDesc;
Desc.Owner = this;
}
/*}}}*/
// AcqIndex::Failed - getting the indexfile failed /*{{{*/
-void pkgAcqIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)
+bool pkgAcqIndex::CommonFailed(std::string const &TargetURI, std::string const TargetDesc,
+ std::string const &Message, pkgAcquire::MethodConfig const * const Cnf)
{
pkgAcqBaseIndex::Failed(Message,Cnf);
+ if (UsedMirror.empty() == false && UsedMirror != "DIRECT" &&
+ LookupTag(Message, "FailReason") == "HttpError404")
+ {
+ UsedMirror = "DIRECT";
+ if (Desc.URI.find("/by-hash/") != std::string::npos)
+ CompressionExtensions = "by-hash " + CompressionExtensions;
+ else
+ CompressionExtensions = CurrentCompressionExtension + ' ' + CompressionExtensions;
+ Init(TargetURI, TargetDesc, Desc.ShortDesc);
+ Status = StatIdle;
+ return true;
+ }
+
// authorisation matches will not be fixed by other compression types
if (Status != StatAuthError)
{
if (CompressionExtensions.empty() == false)
{
- Init(Target.URI, Desc.Description, Desc.ShortDesc);
+ Init(TargetURI, Desc.Description, Desc.ShortDesc);
Status = StatIdle;
- return;
+ return true;
}
}
+ return false;
+}
+void pkgAcqIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)
+{
+ if (CommonFailed(Target.URI, Target.Description, Message, Cnf))
+ return;
if(Target.IsOptional && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD)
Status = StatDone;
{
// copy FinalFile into partial/ so that we check the hash again
string const FinalFile = GetExistingFilename(GetFinalFileNameFromURI(Target.URI));
+ DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI), Target);
if (symlink(FinalFile.c_str(), DestFile.c_str()) != 0)
_error->WarningE("pkgAcqIndex::StageDownloadDone", "Symlinking final file %s back to %s failed", FinalFile.c_str(), DestFile.c_str());
else
Filename = DestFile;
}
Stage = STAGE_DECOMPRESS_AND_VERIFY;
- Desc.URI = "store:" + Filename;
+ if (Filename != DestFile && flExtension(Filename) == flExtension(DestFile))
+ Desc.URI = "copy:" + Filename;
+ else
+ Desc.URI = "store:" + Filename;
QueueURI(Desc);
SetActiveSubprocess(::URI(Desc.URI).Access);
return;
// Create the item
Local = false;
- QueueURI(Desc);
-
++Vf;
+ QueueURI(Desc);
return true;
}
return false;
TemporaryDirectory = tmpname;
ChangeOwnerAndPermissionOfFile("Item::QueueURI", TemporaryDirectory.c_str(),
- SandboxUser.c_str(), "root", 0700);
+ SandboxUser.c_str(), ROOT_GROUP, 0700);
DestFile = flCombine(TemporaryDirectory, DestFileName);
if (DestDir.empty() == false)
pkgCache::PkgIterator const Pkg = Ver.ParentPkg();
if (Pkg->CurrentVer != 0 && Pkg.CurrentVer() == Ver)
{
- std::string const basename = std::string("/usr/share/doc/") + Pkg.Name() + "/changelog";
+ std::string const root = _config->FindDir("Dir");
+ std::string const basename = root + std::string("usr/share/doc/") + Pkg.Name() + "/changelog";
std::string const debianname = basename + ".Debian";
if (FileExists(debianname))
return "copy://" + debianname;
should be so this could produce request order-dependent anomalies */
if (OpenMaybeClearSignedFile(Rls.FileName(), rf) == true)
{
- pkgTagFile TagFile(&rf, rf.Size());
+ pkgTagFile TagFile(&rf);
pkgTagSection Section;
if (TagFile.Step(Section) == true)
server = Section.FindS("Changelogs");