diff --git a/lib/jars/installer.rb b/lib/jars/installer.rb index 213f628..acc3988 100644 --- a/lib/jars/installer.rb +++ b/lib/jars/installer.rb @@ -6,9 +6,13 @@ module Jars class Installer class Dependency - REG = /:jar:|:pom:|:test:|:compile:|:runtime:|:provided:|:system:/.freeze EMPTY = "" + # the trailing ":" of a dependency line; the file may itself contain + # a ':' on Windows (C:\...), hence the optional drive-letter prefix + TRAILING_FILE = /:(?(?:[A-Z]:\\)?[^:]+)\z/.freeze + # A dependency:list line has the form + # groupId:artifactId:type[:classifier]:version:scope:/path/to/file def self.parse(line) return unless /:jar:|:pom:/.match?(line) @@ -18,47 +22,49 @@ def self.parse(line) line.gsub!(/ -- module.*/, EMPTY) line.strip! - if line.index(':pom:') - type = :pom - elsif line.index(':jar:') - type = :jar + # Peel off the trailing file path first: since it may contain a ':' it + # cannot take part in the split below. What is left (pre_match) is + # colon-clean, so every field is addressed by position -- never by + # matching a keyword, which breaks when an artifact id is itself a scope + # or type keyword (e.g. "com.dylibso.chicory:runtime:jar:1.7.5"). + tail = line.match(TRAILING_FILE) + file = tail[:file] + + # classifier is the only optional field, so there are exactly 5 or 6 + components = tail.pre_match.split(':') + if components.size == 6 + group_id, artifact_id, type, classifier, version, scope_name = components + else + group_id, artifact_id, type, version, scope_name = components end - coord = line.sub(/:[^:]+:([A-Z]:\\)?[^:]+$/, EMPTY) - first, second = coord.split(/:#{type}:/) - group_id, artifact_id = first.split(':') - parts = group_id.split('.') - parts << artifact_id - parts << second.split(':')[-1] - file = line.slice(coord.length, line.length).sub(REG, EMPTY).strip - last = file.reverse.index(%r{\\|/}) - parts << line[-last..] - path = File.join(parts).strip + coord = [group_id, artifact_id, type, classifier, version].compact.join(':') + gav = [group_id, artifact_id, classifier, version].compact.join(':') + path = File.join(*group_id.split('.'), artifact_id, version, file[%r{[^\\/]+\z}]) scope = - case line - when /:provided:/ + case scope_name + when 'provided' :provided - when /:test:/ + when 'test' :test else :runtime end - new(type, scope, coord, file, path, !line.index(':system:').nil?) + new(type.to_sym, scope, coord, gav, file, path, scope_name == 'system') end attr_reader :path, :file, :gav, :scope, :type, :coord - def initialize(type, scope, coord, file, path, system) + def initialize(type, scope, coord, gav, file, path, system) @type = type @scope = scope @coord = coord + @gav = gav @file = file @path = path - @system = system - @gav = @coord.sub(REG, ':') end def system? diff --git a/specs/dependency_spec.rb b/specs/dependency_spec.rb index 32d901d..0f01d8f 100644 --- a/specs/dependency_spec.rb +++ b/specs/dependency_spec.rb @@ -60,6 +60,27 @@ _(dep.file).must_equal '/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.pom' end + it 'should parse dependency where artifact_id is a scope keyword' do + %w[runtime compile test provided system].each do |keyword| + dep = Jars::Installer::Dependency.parse(" com.dylibso.chicory:#{keyword}:jar:1.7.5:compile:/usr/local/repository/com/dylibso/chicory/#{keyword}/1.7.5/#{keyword}-1.7.5.jar") + _(dep.type).must_equal :jar + _(dep.scope).must_equal :runtime + _(dep.system?).must_equal false + _(dep.gav).must_equal "com.dylibso.chicory:#{keyword}:1.7.5" + _(dep.coord).must_equal "com.dylibso.chicory:#{keyword}:jar:1.7.5" + _(dep.path).must_equal "com/dylibso/chicory/#{keyword}/1.7.5/#{keyword}-1.7.5.jar" + _(dep.file).must_equal "/usr/local/repository/com/dylibso/chicory/#{keyword}/1.7.5/#{keyword}-1.7.5.jar" + end + end + + it 'should generate the correct require_jar line when artifact_id is a scope keyword' do + require 'stringio' + dep = Jars::Installer::Dependency.parse(' com.dylibso.chicory:runtime:jar:1.7.5:compile:/usr/local/repository/com/dylibso/chicory/runtime/1.7.5/runtime-1.7.5.jar') + io = StringIO.new + Jars::Installer.print_require_jar(io, dep) + _(io.string.strip).must_equal "require_jar 'com.dylibso.chicory', 'runtime', '1.7.5'" + end + it 'should parse dependency where artifact_id has dots' do dep = Jars::Installer::Dependency.parse(+' org.eclipse.sisu:org.eclipse.sisu.plexus:jar:0.0.0.M2a:compile:/usr/local/repository/org/eclipse/sisu/org.eclipse.sisu.plexus/0.0.0.M2a/org.eclipse.sisu.plexus-0.0.0.M2a.jar') _(dep.type).must_equal :jar