summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2017-01-25 03:38:59 +0100
committerJulian Andres Klode <jak@debian.org>2017-02-22 16:53:46 +0100
commitd2749c845954fc1ea38133b050ee49d6f6544235 (patch)
treeebd9ed115728d11848ec869e4e6a9452ad103784
parente87c862cbd3aee8200f9752a0023ff53312e6dbd (diff)
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)
-rw-r--r--apt-pkg/acquire.cc18
1 files changed, 17 insertions, 1 deletions
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<pkgAcqTransactionItem*>(A.Owner);
+ if (OwnerA == nullptr)
+ return true;
+
+ for (auto const & OwnerBUncast : B->Owners) {
+ auto OwnerB = dynamic_cast<pkgAcqTransactionItem*>(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;