diff options
author | Julian Andres Klode <jak@debian.org> | 2017-01-25 03:38:59 +0100 |
---|---|---|
committer | Julian Andres Klode <jak@debian.org> | 2017-01-28 14:06:29 +0100 |
commit | 7b78e8bef1fc9de22d826db1db9df25f97d3710c (patch) | |
tree | 3d0fb96a6bac9e27ed2ccf2c552bea6a970f4709 /apt-pkg | |
parent | 84285d17bab32a0ceafe31a5b2be61cc4f520b42 (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
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/acquire.cc | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 5c195786b..b62c50c00 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; |