lib/jars/gemspec_artifacts.rb
# frozen_string_literal: true
module Jars
class MavenVersion < String
class << self
def new(*args)
if args.empty? || (args.size == 1 && args[0].nil?)
nil
else
low, high = convert(args[0])
low, high = convert(args[1], low, high) if /[=~><]/.match?(args[1])
if low == high
low
else
super "#{low || '[0'},#{high || ')'}"
end
end
end
private
def convert(arg, low = nil, high = nil)
if arg.include?('~>')
val = arg.sub(/~>\s*/, '')
last = val.include?('.') ? val.sub(/\.[0-9]*[a-z]+.*$/, '').sub(/\.[^.]+$/, '.99999') : '99999'
["[#{snapshot_version(val)}", "#{snapshot_version(last)}]"]
elsif arg.include?('>=')
val = arg.sub(/>=\s*/, '')
["[#{snapshot_version(val)}", (nil || high)]
elsif arg.include?('<=')
val = arg.sub(/<=\s*/, '')
[(nil || low), "#{snapshot_version(val)}]"]
# treat '!' the same way as '>' since maven can not describe such range
elsif /[!>]/.match?(arg)
val = arg.sub(/[!>]\s*/, '')
["(#{snapshot_version(val)}", (nil || high)]
elsif arg.include?('<')
val = arg.sub(/<\s*/, '')
[(nil || low), "#{snapshot_version(val)})"]
elsif arg.include?('=')
val = arg.sub(/=\s*/, '')
# for prereleased version pick the maven version (no version range)
if /[a-z]|[A-Z]/.match?(val)
[val, val]
else
["[#{val}", "#{val}.0.0.0.0.1)"]
end
else
# no conversion here, i.e. assume maven version
[arg, arg]
end
end
def snapshot_version(val)
if val.match(/[a-z]|[A-Z]/) && !val.match(/-SNAPSHOT|[${}]/)
"#{val}-SNAPSHOT"
else
val
end
end
end
end
class GemspecArtifacts
class Exclusion
attr_reader :group_id, :artifact_id
def initialize(line)
@group_id, @artifact_id = line.gsub(/['"]/, '').strip.split(':')
@artifact_id.strip!
end
def to_s
"#{@group_id}:#{@artifact_id}"
end
end
class Exclusions < Array
def to_s
"[#{join(', ')}]"
end
def initialize(line)
super()
line.gsub(/'"|^\s*\[|\]\s*$/, '').split(/,\s*/).each do |exclusion|
self.<< Exclusion.new(exclusion)
end
freeze
end
end
class Artifact
attr_reader :type, :group_id, :artifact_id, :classifier, :version, :scope, :exclusions
ALLOWED_TYPES = %w[jar pom].freeze
def initialize(options, *args)
@type, @group_id, @artifact_id, @classifier, @version, @exclusions = *args
options.each do |k, v|
instance_variable_set("@#{k}", v)
end
end
def self.new(line)
line = line.strip
index = line.index(/\s/)
return nil if index.nil?
type = line[0..index].strip
return nil unless ALLOWED_TYPES.member?(type)
line = line[index..]
line.gsub!(/['"]/, '')
line.strip!
options = {}
line.sub!(/,\s*:exclusions\s*(:|=>)\s*(\[[^\]]+\])/) do
options[:exclusions] = Exclusions.new(Regexp.last_match(2).strip)
''
end
line.sub!(/,\s*:([a-z]+)\s*(:|=>)\s*(:?[a-zA-Z0-9_]+)/) do
options[Regexp.last_match(1).to_sym] = Regexp.last_match(3).sub(/^:/, '')
''
end
exclusions = nil
line.sub!(/[,:]\s*\[(.+:.+,?\s*)+\]$/) do |a|
exclusions = Exclusions.new(a[1..].strip)
''
end
line.strip!
line.gsub!(/,\s*/, ':')
if /[\[()\]]/.match?(line)
index = line.index(/[\[(].+$/)
version = line[index..].sub(/:/, ', ')
line = line[0..index - 1].strip.sub(/:$/, '')
else
index = line.index(/:[^:]+$/)
version = line[index + 1..]
line = line[0..index - 1].strip
end
case line.count(':')
when 2
group_id, artifact_id, classifier = line.split(':')
when 1
group_id, artifact_id = line.split(':')
classifier = nil
else
warn line
return nil
end
super(options, type, group_id, artifact_id, classifier, version, exclusions)
end
def to_s
args = [@group_id, @artifact_id]
args << @classifier if @classifier
args << @version
args << @exclusions.to_s if @exclusions
"#{@type} #{group_id}:#{args[1..].join(', ')}"
end
def to_gacv
args = [@group_id, @artifact_id]
args << @classifier if @classifier
args << @version
args.join(':')
end
def to_coord_no_classifier
args = [@group_id, @artifact_id]
args << @type
args << MavenVersion.new(@version)
args.join(':')
end
def to_coord
args = [@group_id, @artifact_id]
args << @classifier if @classifier
args << @type
args << MavenVersion.new(@version)
args.join(':')
end
def key
args = [@group_id, @artifact_id]
args << @classifier if @classifier
args.join(':')
end
end
attr_reader :artifacts
def initialize(spec)
@artifacts = []
spec.requirements.each do |req|
req.split("\n").each do |line|
if (a = Artifact.new(line))
@artifacts << a
end
end
end
@artifacts.freeze
end
def [](index)
@artifacts[index]
end
def each(&block)
@artifacts.each(&block)
end
def size
@artifacts.size
end
end
end