class Bundler::PubGrub::VersionUnion

def self.normalize_ranges(ranges)

def self.normalize_ranges(ranges)
  ranges = ranges.flat_map do |range|
    range.ranges
  end
  ranges.reject!(&:empty?)
  return [] if ranges.empty?
  mins, ranges = ranges.partition { |r| !r.min }
  original_ranges = mins + ranges.sort_by { |r| [r.min, r.include_min ? 0 : 1] }
  ranges = [original_ranges.shift]
  original_ranges.each do |range|
    if ranges.last.contiguous_to?(range)
      ranges << ranges.pop.span(range)
    else
      ranges << range
    end
  end
  ranges
end

def self.union(ranges, normalize: true)

def self.union(ranges, normalize: true)
  ranges = normalize_ranges(ranges) if normalize
  if ranges.size == 0
    VersionRange.empty
  elsif ranges.size == 1
    ranges[0]
  else
    new(ranges)
  end
end

def ==(other)

def ==(other)
  self.class == other.class &&
    self.ranges == other.ranges
end

def allows_all?(other)

def allows_all?(other)
  my_ranges = ranges.dup
  my_range = my_ranges.shift
  other.ranges.all? do |other_range|
    while my_range
      break if my_range.allows_all?(other_range)
      my_range = my_ranges.shift
    end
    !!my_range
  end
end

def any?

def any?
  false
end

def empty?

def empty?
  false
end

def eql?(other)

def eql?(other)
  ranges.eql?(other.ranges)
end

def hash

def hash
  ranges.hash
end

def include?(version)

def include?(version)
  !!ranges.bsearch {|r| r.compare_version(version) }
end

def initialize(ranges)

def initialize(ranges)
  raise ArgumentError unless ranges.all? { |r| r.instance_of?(VersionRange) }
  @ranges = ranges
end

def inspect

def inspect
  "#<#{self.class} #{to_s}>"
end

def intersect(other)

def intersect(other)
  my_ranges = ranges.dup
  other_ranges = other.ranges.dup
  new_ranges = []
  my_range = my_ranges.shift
  other_range = other_ranges.shift
  while my_range && other_range
    new_ranges << my_range.intersect(other_range)
    if !my_range.max || other_range.empty? || (other_range.max && other_range.max < my_range.max)
      other_range = other_ranges.shift
    else
      my_range = my_ranges.shift
    end
  end
  new_ranges.reject!(&:empty?)
  VersionUnion.union(new_ranges, normalize: false)
end

def intersects?(other)

def intersects?(other)
  my_ranges = ranges.dup
  other_ranges = other.ranges.dup
  my_range = my_ranges.shift
  other_range = other_ranges.shift
  while my_range && other_range
    if my_range.intersects?(other_range)
      return true
    end
    if !my_range.max || other_range.empty? || (other_range.max && other_range.max < my_range.max)
      other_range = other_ranges.shift
    else
      my_range = my_ranges.shift
    end
  end
end

def invert

def invert
  ranges.map(&:invert).inject(:intersect)
end

def select_versions(all_versions)

def select_versions(all_versions)
  versions = []
  ranges.inject(all_versions) do |acc, range|
    _, matching, higher = range.partition_versions(acc)
    versions.concat matching
    higher
  end
  versions
end

def to_s

def to_s
  output = []
  ranges = self.ranges.dup
  while !ranges.empty?
    ne = []
    range = ranges.shift
    while !ranges.empty? && ranges[0].min.to_s == range.max.to_s
      ne << range.max
      range = range.span(ranges.shift)
    end
    ne.map! {|x| "!= #{x}" }
    if ne.empty?
      output << range.to_s
    elsif range.any?
      output << ne.join(', ')
    else
      output << "#{range}, #{ne.join(', ')}"
    end
  end
  output.join(" OR ")
end

def union(other)

def union(other)
  VersionUnion.union([self, other])
end

def upper_invert

def upper_invert
  ranges.last.upper_invert
end