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 18:11:44 +0100
commit58b51ecee7fb14c52e50ca530c009604de4d965e (patch)
tree887a772e2f704cc89e7a88d315a856c74d5c07f9
parent6d3422af675caa41d5c4575c2212baa6fcd76ac2 (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) (cherry picked from commit d2749c845954fc1ea38133b050ee49d6f6544235)
-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 f2b80a5be..59b1fd3c4 100644
--- a/apt-pkg/acquire.cc
+++ b/apt-pkg/acquire.cc
@@ -843,10 +843,26 @@ 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 **I = &Items;
// move to the end of the queue and check for duplicates here
for (; *I != 0; I = &(*I)->Next)
- 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;