So I got motivated to do enough cargo cult programming in ruby to try to figure this out, and it looks like it's actually very simple, and is nothing more than a classic "modify list during iteration" bug.
When it removes an item as a duplicate, it seems to cause the list iteration to end up skipping an item. I added debug code to show each step of the "remove duplicates" loop. Here's the start of that debug, using the ctools project data, up until the error becomes visible. D: Examining item 7:1.7 status 2 D: Examining other 7:1.7 status 2 D: Examining other 6:1.12 status 2 D: Examining other 7:1~~dev status 2 D: Examining other 6:1~~dev status 2 D: Examining other 7:1~~dev status 0 D: Examining other 6:1~~dev status 0 D: Examining item 6:1.12 status 2 D: Examining other 7:1.7 status 2 D: Examining other 6:1.12 status 2 D: Examining other 7:1~~dev status 2 D: Examining other 6:1~~dev status 2 D: Examining other 7:1~~dev status 0 D: Examining other 6:1~~dev status 0 D: Examining item 7:1~~dev status 2 D: Examining other 7:1.7 status 2 D: Examining other 6:1.12 status 2 D: Examining other 7:1~~dev status 2 D: Examining other 6:1~~dev status 2 D: Examining other 7:1~~dev status 0 D: Removing duplicate version 1~~dev (status 2) D: Examining item 7:1~~dev status 0 Notice that after removing "7:1~~dev status 2" it should go on to examine item = "6:1~~dev status 2", but instead it skips to the next item "7:1~~dev status 0". Removing the element from the array during iteration has broken the iteration. I've attached a patch that includes the above debug messages and my ugly(?) fix for it, which works for me. This is the first time I've ever tried to write ruby code, so apologies if I'm missing some ruby-isms. Mainly I guessed the syntax by reading other parts of this script :) Cheers, -- Matt
--- /usr/bin/dh-make-drupal 2014-05-13 15:06:27.000000000 -0400 +++ /tmp/dh-make-drupal 2015-03-24 19:39:58.589820630 -0400 @@ -778,16 +778,23 @@ # Remove wrongly detected duplicate versions on different # support levels (leave the lowest one, that's how Drupal's site # is structured. Ugly :-( + duplicates = Array.new list.each do |item| + Logger.instance.debug('Examining item %s:%s status %s' % [item.drupal_version, item.version, item.status]) list.each do |other| + Logger.instance.debug('Examining other %s:%s status %s' % [other.drupal_version, other.version, other.status]) next if item == other next if item.version != other.version if other.status < item.status - Logger.instance.debug('Removing duplicate version %s (status %s)' % [item.version, item.status]) - list.delete(item) if other.status < item.status + Logger.instance.debug('Marking duplicate version %s (status %s)' % [item.version, item.status]) + duplicates << item if other.status < item.status end end end + duplicates.each do |item| + Logger.instance.debug('Removing duplicate version %s (status %s)' % [item.version, item.status]) + list.delete(item) + end list end