From d2749c845954fc1ea38133b050ee49d6f6544235 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 25 Jan 2017 03:38:59 +0100 Subject: Only merge acquire items with the same meta key Since the introduction of by-hash, two differently named files might have the same real URL. In our case, the files icons-64x64.tar.gz and icons-128x128.tar.gz of empty tarballs. APT would try to merge them and end with weird errors because it completed the first download and enters the second stage for decompressing and verifying. After that it would queue a new item to copy the original file to the location, but that copy item would be in the wrong stage, causing it to use the hashes for the decompressed item. Closes: #838441 (cherry picked from commit 7b78e8bef1fc9de22d826db1db9df25f97d3710c) --- apt-pkg/acquire.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 291e29fea..0b0154133 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -900,11 +900,27 @@ pkgAcquire::Queue::~Queue() /* */ bool pkgAcquire::Queue::Enqueue(ItemDesc &Item) { + // MetaKeysMatch checks whether the two items have no non-matching + // meta-keys. If the items are not transaction items, it returns + // true, so other items can still be merged. + auto MetaKeysMatch = [](pkgAcquire::ItemDesc const &A, pkgAcquire::Queue::QItem const *B) { + auto OwnerA = dynamic_cast(A.Owner); + if (OwnerA == nullptr) + return true; + + for (auto const & OwnerBUncast : B->Owners) { + auto OwnerB = dynamic_cast(OwnerBUncast); + + if (OwnerB != nullptr && OwnerA->GetMetaKey() != OwnerB->GetMetaKey()) + return false; + } + return true; + }; QItem **OptimalI = &Items; QItem **I = &Items; // move to the end of the queue and check for duplicates here for (; *I != 0; ) { - if (Item.URI == (*I)->URI) + if (Item.URI == (*I)->URI && MetaKeysMatch(Item, *I)) { if (_config->FindB("Debug::pkgAcquire::Worker",false) == true) std::cerr << " @ Queue: Action combined for " << Item.URI << " and " << (*I)->URI << std::endl; -- cgit v1.2.3