diff --git a/.rubocop.yml b/.rubocop.yml index b2f2ed1..85ce27e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -3,9 +3,17 @@ plugins: - rubocop-performance - rubocop-minitest +inherit_mode: + merge: + - Exclude + AllCops: TargetRubyVersion: 2.6 NewCops: enable + Exclude: + - target/**/* + - vendor/**/* + - tmp/**/* Metrics: Enabled: false diff --git a/Gemfile b/Gemfile index 04be930..4685c72 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ source 'https://gem.coop' gemspec -group :development do +group :development do gem 'rake', require: false gem 'ruby-debug', '~> 0.11', require: false @@ -13,3 +13,8 @@ group :development do gem 'rubocop-performance', require: false gem 'rubocop-rake', require: false end + +group :test do + gem 'minitest', '~> 5.27' + gem 'minitest-mock', '~> 5.27' +end diff --git a/Rakefile b/Rakefile index bf0ce86..a524882 100644 --- a/Rakefile +++ b/Rakefile @@ -48,7 +48,7 @@ task :download_jars do puts " downloading #{filename}..." URI.open(info[:url]) do |remote| # rubocop:disable Security/Open - File.open(target, 'wb') { |f| f.write(remote.read) } + File.binwrite(target, remote.read) end verify_checksum(target, info[:sha1]) puts " saved: #{target}" @@ -60,7 +60,7 @@ def verify_checksum(path, expected_sha1) return if actual == expected_sha1 File.delete(path) - raise "SHA-1 mismatch for #{path}:\n" \ - " expected: #{expected_sha1}\n" \ - " actual: #{actual}" + raise "SHA-1 mismatch for #{path}:\n " \ + "expected: #{expected_sha1}\n " \ + "actual: #{actual}" end diff --git a/jar-dependencies.gemspec b/jar-dependencies.gemspec index 9532d7b..73c2afc 100644 --- a/jar-dependencies.gemspec +++ b/jar-dependencies.gemspec @@ -1,12 +1,17 @@ # frozen_string_literal: true -require_relative 'lib/jars/version' -require_relative 'lib/jars/mima/version' +File.expand_path('lib', File.dirname(__FILE__)).tap do |lib| + $LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib) +end + +require 'jars/version' +require 'jars/mima/version' Gem::Specification.new do |s| s.name = 'jar-dependencies' s.version = Jars::VERSION + s.platform = 'java' s.author = 'christian meier' s.email = ['mkristian@web.de'] @@ -20,7 +25,7 @@ Gem::Specification.new do |s| s.files = Dir['{lib}/**/*'] + %w[Mavenfile Rakefile Readme.md jar-dependencies.gemspec MIT-LICENSE] # explicitly require the jars - s.files += Jars::Mima::JARS.each_key.map {File.join(Jars::Mima::MIMA_DIR, _1)} + s.files += Jars::Mima::JARS.each_key.map { File.join(Jars::Mima::MIMA_DIR, _1) } s.description = <<~TEXT manage jar dependencies for gems and keep track which jar was already @@ -32,7 +37,5 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 2.6' - s.add_development_dependency 'minitest', '~> 5.10' - s.metadata['rubygems_mfa_required'] = 'true' end diff --git a/lib/jar_dependencies.rb b/lib/jar_dependencies.rb index f8cc5fa..61a7dbd 100644 --- a/lib/jar_dependencies.rb +++ b/lib/jar_dependencies.rb @@ -55,8 +55,9 @@ module Jars autoload :MavenSettings, 'jars/maven_settings' autoload :Mima, 'jars/mima' - @jars_lock = false @jars = {} + @jars_lock = false + @jars_locked = nil class JarLoadError < LoadError; end @@ -119,10 +120,15 @@ def quiet? @quiet end + # @deprecated def no_more_warnings @quiet = true end + def locked_jar?(coordinate) + @jars_locked&.include?(coordinate) + end + def jarfile ENV['JARFILE'] || ENV_JAVA['jarfile'] || ENV['JBUNDLER_JARFILE'] || ENV_JAVA['jbundler.jarfile'] || 'Jarfile' end @@ -177,6 +183,7 @@ def reset end Jars::MavenSettings.reset @jars = {} + @jars_locked = nil end def maven_local_settings @@ -209,6 +216,7 @@ def home def require_jars_lock!(scope = :runtime) urls = jars_lock_from_class_loader if to_prop(LOCK).nil? + pre_lock_jars = @jars.keys.dup if urls && !urls.empty? @jars_lock = true @@ -223,15 +231,19 @@ def require_jars_lock!(scope = :runtime) done << url end end - no_more_warnings elsif (jars_lock = Jars.lock_path) Jars.debug { "--- load jars from #{jars_lock}" } @jars_lock = jars_lock classpath = Jars::Classpath.new(nil, jars_lock) classpath.require(scope) - no_more_warnings end + + return unless @jars_lock + + @jars_locked = (@jars.keys - pre_lock_jars).freeze + return if @jars_locked.empty? + Jars.debug do loaded = @jars.collect { |k, v| "#{k}:#{v}" } "--- loaded jars ---\n\t#{loaded.join("\n\t")}" @@ -275,6 +287,13 @@ def require_jar(group_id, artifact_id, *classifier_version) end end + def info(msg = nil, newline: true) + return if quiet? + + msg = yield if msg.nil? && block_given? + Kernel.print("#{msg}#{"\n" if newline}") + end + def warn(msg = nil) return if quiet? && !debug? @@ -306,9 +325,8 @@ def require_jar_with_block(group_id, artifact_id, *classifier_version) version = classifier_version[-1] classifier = classifier_version[-2] - coordinate = +"#{group_id}:#{artifact_id}" - coordinate << ":#{classifier}" if classifier - if @jars.key? coordinate + coordinate = "#{group_id}:#{artifact_id}#{":#{classifier}" if classifier}" + if @jars.key?(coordinate) if @jars[coordinate] == version false else @@ -346,8 +364,8 @@ def to_jar(group_id, artifact_id, version, classifier = nil) file end - def do_require(*args) - jar = to_jar(*args) + def do_require(group_id, artifact_id, version, classifier) + jar = to_jar(group_id, artifact_id, version, classifier) # use jar from PWD/vendor/jars if exists if File.exist?(vendor = File.join(Dir.pwd, 'vendor', 'jars', jar)) require vendor @@ -373,15 +391,18 @@ def require_jar(*args, &block) return unless Jars.require? result = Jars.require_jar(*args, &block) - if result.is_a? String + if result.is_a?(String) args << (yield || Jars::UNKNOWN) if args.size == 2 && block - Jars.warn do - "jar conflict: #{args[0..-2].join(':')} already loaded with version #{result}; " \ - "skipping requested version #{args[-1]}" + coordinate = args[0..-2].join(':') + unless Jars.locked_jar?(coordinate) + Jars.warn do + "jar conflict: #{coordinate} already loaded with version #{result}; " \ + "skipping requested version #{args[-1]}" + end end Jars.debug("\n\t#{caller.join("\n\t")}") if Jars.debug? return false end - Jars.debug { "jar registration: #{args.inspect}; loaded=#{result == true}" } + Jars.debug { "jar registration: #{args.inspect}; loaded=#{result}" } result end diff --git a/lib/jars/gemspec_artifacts.rb b/lib/jars/gemspec_artifacts.rb index 4e84bc0..e3571b3 100644 --- a/lib/jars/gemspec_artifacts.rb +++ b/lib/jars/gemspec_artifacts.rb @@ -1,20 +1,14 @@ # frozen_string_literal: true module Jars - class MavenVersion < String + module MavenVersion 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 + def resolve(*args) + return nil if args.empty? || (args.size == 1 && args[0].nil?) + + low, high = convert(args[0]) + low, high = convert(args[1], low, high) if /[=~><]/.match?(args[1]) + (low == high) ? low : "#{low || '[0'},#{high || ')'}" end private @@ -94,14 +88,19 @@ class Artifact ALLOWED_TYPES = %w[jar pom].freeze - def initialize(options, *args) - @type, @group_id, @artifact_id, @classifier, @version, @exclusions = *args + def initialize(type, group_id, artifact_id, classifier, version, exclusions, **options) + @type = type + @group_id = group_id + @artifact_id = artifact_id + @classifier = classifier + @version = version + @exclusions = exclusions options.each do |k, v| instance_variable_set(:"@#{k}", v) end end - def self.new(line) + def self.parse(line) line = line.strip index = line.index(/\s/) return nil if index.nil? @@ -151,7 +150,7 @@ def self.new(line) warn line return nil end - super(options, type, group_id, artifact_id, classifier, version, exclusions) + new(type, group_id, artifact_id, classifier, version, exclusions, **options) end def to_s @@ -169,18 +168,11 @@ def to_gacv 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 + def to_coord(classifier: true) args = [@group_id, @artifact_id] - args << @classifier if @classifier + args << @classifier if classifier && @classifier args << @type - args << MavenVersion.new(@version) + args << MavenVersion.resolve(@version) args.join(':') end @@ -197,9 +189,8 @@ def initialize(spec) @artifacts = [] spec.requirements.each do |req| req.split("\n").each do |line| - if (a = Artifact.new(line)) - @artifacts << a - end + artifact = Artifact.parse(line) + @artifacts << artifact if artifact end end @artifacts.freeze diff --git a/lib/jars/installer.rb b/lib/jars/installer.rb index d51d279..213f628 100644 --- a/lib/jars/installer.rb +++ b/lib/jars/installer.rb @@ -6,23 +6,36 @@ module Jars class Installer class Dependency - attr_reader :path, :file, :gav, :scope, :type, :coord + REG = /:jar:|:pom:|:test:|:compile:|:runtime:|:provided:|:system:/.freeze + EMPTY = "" - def self.new(line) - super if /:jar:|:pom:/.match?(line) - end + def self.parse(line) + return unless /:jar:|:pom:/.match?(line) + + line = line.dup + # remove ANSI escape sequences and module section (https://issues.apache.org/jira/browse/MDEP-974) + line.gsub!(/\e\[\d*m/, EMPTY) + line.gsub!(/ -- module.*/, EMPTY) + line.strip! - def setup_type(line) if line.index(':pom:') - @type = :pom + type = :pom elsif line.index(':jar:') - @type = :jar + type = :jar end - end - private :setup_type - def setup_scope(line) - @scope = + 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 + + scope = case line when /:provided:/ :provided @@ -31,34 +44,20 @@ def setup_scope(line) else :runtime end - end - private :setup_scope - REG = /:jar:|:pom:|:test:|:compile:|:runtime:|:provided:|:system:/.freeze - EMPTY = '' - def initialize(line) - # remove ANSI escape sequences and module section (https://issues.apache.org/jira/browse/MDEP-974) - line = line.gsub(/\e\[\d*m/, '') - line = line.gsub(/ -- module.*/, '') - - setup_type(line) - - line.strip! + new(type, scope, coord, file, path, !line.index(':system:').nil?) + 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 + attr_reader :path, :file, :gav, :scope, :type, :coord - setup_scope(line) + def initialize(type, scope, coord, file, path, system) + @type = type + @scope = scope + @coord = coord + @file = file + @path = path - @system = !line.index(':system:').nil? + @system = system @gav = @coord.sub(REG, ':') end @@ -74,7 +73,7 @@ def self.install_jars(write_require_file: false) def self.load_from_maven(file) result = [] File.read(file).each_line do |line| - dep = Dependency.new(line) + dep = Dependency.parse(line) result << dep if dep && dep.scope == :runtime end result @@ -103,12 +102,11 @@ def self.print_require_jar(file, dep, fallback: false) end COMMENT = '# this is a generated file, to avoid over-writing it just delete this comment' - def self.needs_to_write?(require_filename) - require_filename && (!File.exist?(require_filename) || File.read(require_filename).match(COMMENT)) - end def self.write_require_jars(deps, require_filename) - return unless needs_to_write?(require_filename) + return if !require_filename || ( + File.exist?(require_filename) && !File.read(require_filename).index(COMMENT) + ) FileUtils.mkdir_p(File.dirname(require_filename)) File.open(require_filename, 'w') do |f| @@ -175,18 +173,15 @@ def ruby_maven_install_options=(options) end def jars? - # first look if there are any requirements in the spec - # and then if gem depends on jar-dependencies for runtime. - # only then install the jars declared in the requirements spec = self.spec - result = spec && !spec.requirements.empty? && - spec.dependencies.detect { |d| d.name == 'jar-dependencies' && d.type == :runtime } - if result && spec.platform.to_s != 'java' - Jars.warn "jar-dependencies found on non-java platform gem; skipping jar installation" - false - else - result - end + return if spec.nil? # rubocop:disable Style/ReturnNilInPredicateMethodDefinition + return false unless spec.requirements&.any? + return false unless spec.runtime_dependencies.find { |s| s.name == 'jar-dependencies' } + + return true if spec.platform.to_s == 'java' + + Jars.warn "jar-dependencies found on non-java platform gem; skipping jar installation" + nil # rubocop:disable Style/ReturnNilInPredicateMethodDefinition end private @@ -213,8 +208,9 @@ def do_install(vendor_dir, write_require_file) def install_dependencies deps = File.join(@mvn.basedir, 'deps.lst') - puts " jar dependencies for #{spec.spec_name} . . ." unless Jars.quiet? + Jars.info("jar dependencies for #{spec.spec_name} ", newline: false) @mvn.resolve_dependencies_list(deps) + Jars.info("") # newline after progress dots self.class.load_from_maven(deps) ensure diff --git a/lib/jars/mima.rb b/lib/jars/mima.rb index aeb8c34..5cab010 100644 --- a/lib/jars/mima.rb +++ b/lib/jars/mima.rb @@ -132,18 +132,22 @@ def aether_repository_listener when :metadataInvalid Jars.debug { "[mima] invalid metadata #{metadata_label(event.getMetadata)}" } when :artifactResolving + progress_dot Jars.debug { "[mima] resolving artifact #{artifact_label(event.getArtifact)}" } when :artifactResolved Jars.debug { resolved_message('artifact', event) } when :metadataResolving + progress_dot Jars.debug { "[mima] resolving metadata #{metadata_label(event.getMetadata)}" } when :metadataResolved Jars.debug { resolved_message('metadata', event) } when :artifactDownloading + progress_dot Jars.debug { download_message('artifact', event) } when :artifactDownloaded Jars.debug { downloaded_message('artifact', event) } when :metadataDownloading + progress_dot Jars.debug { download_message('metadata', event) } when :metadataDownloaded Jars.debug { downloaded_message('metadata', event) } @@ -168,6 +172,11 @@ def aether_transfer_listener end end + # Emits a single progress dot (no newline) unless in debug mode + def progress_dot + Jars.info('.', newline: false) unless Jars.debug? + end + def resolved_message(kind, event) message = +"[mima] resolved #{kind} #{repository_item_label(event)}" message << " -> #{event.getFile.getAbsolutePath}" if event.getFile @@ -251,7 +260,7 @@ def artifacts_to_dependencies(artifacts, all_dependencies: false) # @param artifact [Jars::GemspecArtifacts::Artifact] # @return [org.eclipse.aether.artifact.DefaultArtifact] def build_aether_artifact(artifact) - version = Jars::MavenVersion.new(artifact.version) || artifact.version + version = Jars::MavenVersion.resolve(artifact.version) || artifact.version if artifact.classifier org.eclipse.aether.artifact.DefaultArtifact.new( artifact.group_id, artifact.artifact_id, artifact.classifier, diff --git a/specs/dependency_spec.rb b/specs/dependency_spec.rb index 9b949f2..32d901d 100644 --- a/specs/dependency_spec.rb +++ b/specs/dependency_spec.rb @@ -7,13 +7,13 @@ # rubocop:disable Layout/LineLength describe Jars::Installer::Dependency do it 'should parse dependency line only if it is jar or pom' do - assert_nil Jars::Installer::Dependency.new(+'something') - assert Jars::Installer::Dependency.new(+' org.apache.maven:maven-repository-metadata:jar:3.1.0:compile:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') - assert Jars::Installer::Dependency.new(+' org.apache.maven:maven-repository-metadata:pom:3.1.0:compile:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') + assert_nil Jars::Installer::Dependency.parse(+'something') + assert Jars::Installer::Dependency.parse(' org.apache.maven:maven-repository-metadata:jar:3.1.0:compile:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') + assert Jars::Installer::Dependency.parse(' org.apache.maven:maven-repository-metadata:pom:3.1.0:compile:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') end it 'should parse dependency line test scope' do - dep = Jars::Installer::Dependency.new(+' org.apache.maven:maven-repository-metadata:jar:3.1.0:test:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') + dep = Jars::Installer::Dependency.parse(' org.apache.maven:maven-repository-metadata:jar:3.1.0:test:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') _(dep.type).must_equal :jar _(dep.scope).must_equal :test _(dep.gav).must_equal 'org.apache.maven:maven-repository-metadata:3.1.0' @@ -23,7 +23,7 @@ end it 'should parse dependency line provided scope' do - dep = Jars::Installer::Dependency.new(+' org.apache.maven:maven-repository-metadata:jar:3.1.0:provided:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') + dep = Jars::Installer::Dependency.parse(' org.apache.maven:maven-repository-metadata:jar:3.1.0:provided:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') _(dep.type).must_equal :jar _(dep.scope).must_equal :provided _(dep.gav).must_equal 'org.apache.maven:maven-repository-metadata:3.1.0' @@ -33,7 +33,7 @@ end it 'should parse dependency line runtim scope' do - dep = Jars::Installer::Dependency.new(+' org.apache.maven:maven-repository-metadata:jar:3.1.0:compile:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') + dep = Jars::Installer::Dependency.parse(+' org.apache.maven:maven-repository-metadata:jar:3.1.0:compile:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') _(dep.type).must_equal :jar _(dep.scope).must_equal :runtime _(dep.gav).must_equal 'org.apache.maven:maven-repository-metadata:3.1.0' @@ -41,7 +41,7 @@ _(dep.path).must_equal 'org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar' _(dep.file).must_equal '/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar' - dep = Jars::Installer::Dependency.new(+' org.apache.maven:maven-repository-metadata:jar:3.1.0:runtime:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') + dep = Jars::Installer::Dependency.parse(+' org.apache.maven:maven-repository-metadata:jar:3.1.0:runtime:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.jar') _(dep.type).must_equal :jar _(dep.scope).must_equal :runtime _(dep.gav).must_equal 'org.apache.maven:maven-repository-metadata:3.1.0' @@ -51,7 +51,7 @@ end it 'should parse pom dependency' do - dep = Jars::Installer::Dependency.new(+' org.apache.maven:maven-repository-metadata:pom:3.1.0:compile:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.pom') + dep = Jars::Installer::Dependency.parse(+' org.apache.maven:maven-repository-metadata:pom:3.1.0:compile:/usr/local/repository/org/apache/maven/maven-repository-metadata/3.1.0/maven-repository-metadata-3.1.0.pom') _(dep.type).must_equal :pom _(dep.scope).must_equal :runtime _(dep.gav).must_equal 'org.apache.maven:maven-repository-metadata:3.1.0' @@ -61,7 +61,7 @@ end it 'should parse dependency where artifact_id has dots' do - dep = Jars::Installer::Dependency.new(+' 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 = 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 _(dep.scope).must_equal :runtime _(dep.gav).must_equal 'org.eclipse.sisu:org.eclipse.sisu.plexus:0.0.0.M2a' @@ -71,7 +71,7 @@ end it 'should parse dependency with classifier' do - dep = Jars::Installer::Dependency.new(+' org.sonatype.sisu:sisu-guice:jar:no_aop:3.1.0:compile:/usr/local/repository/org/sonatype/sisu/sisu-guice/3.1.0/sisu-guice-3.1.0-no_aop.jar') + dep = Jars::Installer::Dependency.parse(+' org.sonatype.sisu:sisu-guice:jar:no_aop:3.1.0:compile:/usr/local/repository/org/sonatype/sisu/sisu-guice/3.1.0/sisu-guice-3.1.0-no_aop.jar') _(dep.type).must_equal :jar _(dep.scope).must_equal :runtime _(dep.gav).must_equal 'org.sonatype.sisu:sisu-guice:no_aop:3.1.0' @@ -81,7 +81,7 @@ end it 'should parse dependency on windows' do - dep = Jars::Installer::Dependency.new(+' org.sonatype.sisu:sisu-guice:jar:no_aop:3.1.0:compile:C:\\Users\\Local\\repository\\org\\sonatype\\sisu\\sisu-guice\\3.1.0\\sisu-guice-3.1.0-no_aop.jar') + dep = Jars::Installer::Dependency.parse(+' org.sonatype.sisu:sisu-guice:jar:no_aop:3.1.0:compile:C:\\Users\\Local\\repository\\org\\sonatype\\sisu\\sisu-guice\\3.1.0\\sisu-guice-3.1.0-no_aop.jar') _(dep.type).must_equal :jar _(dep.scope).must_equal :runtime _(dep.gav).must_equal 'org.sonatype.sisu:sisu-guice:no_aop:3.1.0' @@ -93,7 +93,7 @@ # these next two combine every possible oddity to try to cover all combinations (classifier, windows path, ANSI and module) it 'should parse dependency with module section' do - dep = Jars::Installer::Dependency.new(+' org.eclipse.sisu:org.eclipse.sisu.plexus:jar:no_aop:0.0.0.M2a:compile:C:\\Users\\Local\\repository\\org\\sonatype\\sisu\\org.eclipse.sisu.plexus\\0.0.0.M2a\\org.eclipse.sisu.plexus-0.0.0.M2a-no_aop.jar -- module org.sonatype.sisu.sisu-guice') + dep = Jars::Installer::Dependency.parse(+' org.eclipse.sisu:org.eclipse.sisu.plexus:jar:no_aop:0.0.0.M2a:compile:C:\\Users\\Local\\repository\\org\\sonatype\\sisu\\org.eclipse.sisu.plexus\\0.0.0.M2a\\org.eclipse.sisu.plexus-0.0.0.M2a-no_aop.jar -- module org.sonatype.sisu.sisu-guice') _(dep.type).must_equal :jar _(dep.scope).must_equal :runtime _(dep.gav).must_equal 'org.eclipse.sisu:org.eclipse.sisu.plexus:no_aop:0.0.0.M2a' @@ -103,7 +103,7 @@ end it 'should parse dependency with ANSI-colored module section' do - dep = Jars::Installer::Dependency.new(+" org.eclipse.sisu:org.eclipse.sisu.plexus:jar:no_aop:0.0.0.M2a:compile:C:\\Users\\Local\\repository\\org\\sonatype\\sisu\\org.eclipse.sisu.plexus\\0.0.0.M2a\\org.eclipse.sisu.plexus-0.0.0.M2a-no_aop.jar\e[31m -- module org.sonatype.sisu.sisu-guice\e[m") + dep = Jars::Installer::Dependency.parse(+" org.eclipse.sisu:org.eclipse.sisu.plexus:jar:no_aop:0.0.0.M2a:compile:C:\\Users\\Local\\repository\\org\\sonatype\\sisu\\org.eclipse.sisu.plexus\\0.0.0.M2a\\org.eclipse.sisu.plexus-0.0.0.M2a-no_aop.jar\e[31m -- module org.sonatype.sisu.sisu-guice\e[m") _(dep.type).must_equal :jar _(dep.scope).must_equal :runtime _(dep.gav).must_equal 'org.eclipse.sisu:org.eclipse.sisu.plexus:no_aop:0.0.0.M2a' diff --git a/specs/gemspec_artifacts_spec.rb b/specs/gemspec_artifacts_spec.rb index f2ba2b3..2035e90 100644 --- a/specs/gemspec_artifacts_spec.rb +++ b/specs/gemspec_artifacts_spec.rb @@ -56,140 +56,140 @@ describe Jars::GemspecArtifacts::Artifact do it 'ignore unknow type' do - _(Jars::GemspecArtifacts::Artifact.new('bla')).must_be_nil - _(Jars::GemspecArtifacts::Artifact.new(' _(bla')).must_be_nil - _(Jars::GemspecArtifacts::Artifact.new('bla bla _(bla')).must_be_nil + _(Jars::GemspecArtifacts::Artifact.parse('bla')).must_be_nil + _(Jars::GemspecArtifacts::Artifact.parse(' _(bla')).must_be_nil + _(Jars::GemspecArtifacts::Artifact.parse('bla bla _(bla')).must_be_nil end %i[jar pom].each do |type| it "parse and to_s of simple GAV #{type}" do expected = "#{type} g:a, 1" - a = Jars::GemspecArtifacts::Artifact.new(expected) + a = Jars::GemspecArtifacts::Artifact.parse(expected) _(a.to_s).must_equal expected line = "#{type} 'g:a', '1'" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} g,a,1" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} 'g',\"a\", 1" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} g:a:1" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} 'g:a:1'" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected end it "parse and to_s of simple GAV #{type} with range" do expected = "#{type} g:a, [1, 2)" - a = Jars::GemspecArtifacts::Artifact.new(expected) + a = Jars::GemspecArtifacts::Artifact.parse(expected) _(a.to_s).must_equal expected line = "#{type} g:a:[1, 2)" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} g:a,'[1, 2)'" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} 'g', \"a\", ' [1, 2) '" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected end it "parse and to_s of simple GAV #{type} with one exclusion" do expected = "#{type} g:a, 1, [a:b]" - a = Jars::GemspecArtifacts::Artifact.new(expected) + a = Jars::GemspecArtifacts::Artifact.parse(expected) _(a.to_s).must_equal expected line = "#{type} 'g:a', '1', '[a:b]'" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} 'g:a', '1', ['a:b']" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} g,a,1,[a:b]" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected end it "parse and to_s of simple GAV #{type} with exclusions" do expected = "#{type} g:a, 1, [a:b, c:d]" - a = Jars::GemspecArtifacts::Artifact.new(expected) + a = Jars::GemspecArtifacts::Artifact.parse(expected) _(a.to_s).must_equal expected line = "#{type} 'g:a', '1', ['a:b', 'c:d']'" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} g,a,1,[a:b,c:d]" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected end it "parse and to_s of simple GAV #{type} with exclusions and range" do expected = "#{type} g:a, (1, 2], [a:b, c:d]" - a = Jars::GemspecArtifacts::Artifact.new(expected) + a = Jars::GemspecArtifacts::Artifact.parse(expected) _(a.to_s).must_equal expected line = "#{type} 'g:a', '(1,2]', ['a:b', 'c:d']'" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} g,a,(1,2],[a:b,c:d]" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} g,a,(1,2], :exclusions : [a:b,c:d]" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected end it "parse and to_s of simple GACV #{type}" do expected = "#{type} g:a, c, 1" - a = Jars::GemspecArtifacts::Artifact.new(expected) + a = Jars::GemspecArtifacts::Artifact.parse(expected) _(a.to_s).must_equal expected line = "#{type} 'g:a', 'c', '1'" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} g,a,\"c\",1" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} g,a, 1 ,:classifier : c" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected end it "parse and to_s of simple GACV #{type} with range" do expected = "#{type} g:a, c, [1, 2)" - a = Jars::GemspecArtifacts::Artifact.new(expected) + a = Jars::GemspecArtifacts::Artifact.parse(expected) _(a.to_s).must_equal expected _(a.scope).must_be_nil line = "#{type} g:a:c:[1, 2),:scope=>:runtime" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected _(a.scope).must_equal 'runtime' line = "#{type} g:a:c,'[1, 2)'" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} 'g', \"a\", 'c', ' [1, 2) '" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected line = "#{type} g,a,[1, 2),:classifier => c" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected end it "parse and to_s of simple GACV #{type} with exclusions and range" do expected = "#{type} g:a, c, (1, 2], [a:b, c:d]" - a = Jars::GemspecArtifacts::Artifact.new(expected) + a = Jars::GemspecArtifacts::Artifact.parse(expected) _(a.to_s).must_equal expected _(a.scope).must_be_nil line = "#{type} 'g:a:c', '(1,2]', ['a:b', 'c:d']'" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected _(a.scope).must_be_nil line = "#{type} g,a,c,(1,2],[a:b,c:d], :scope => :compile" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected _(a.scope).must_equal 'compile' line = "#{type} g,a,(1,2],:classifier => c,:exclusions => [a:b,c:d]" - a = Jars::GemspecArtifacts::Artifact.new(line) + a = Jars::GemspecArtifacts::Artifact.parse(line) _(a.to_s).must_equal expected end end @@ -230,7 +230,7 @@ _(artifacts[5].exclusions).must_be_nil artifacts.each do |a| - _(a.to_s).must_equal Jars::GemspecArtifacts::Artifact.new(a.to_s).to_s + _(a.to_s).must_equal Jars::GemspecArtifacts::Artifact.parse(a.to_s).to_s end _(artifacts.size).must_equal 7 diff --git a/specs/jar_installer_spec.rb b/specs/jar_installer_spec.rb index d522142..5040afa 100644 --- a/specs/jar_installer_spec.rb +++ b/specs/jar_installer_spec.rb @@ -60,10 +60,8 @@ def do_install(vendor, write) it 'just skips install_jars and vendor_jars if there are no requirements' do jar = Jars::Installer.new jar.install_jars - # vendor method is a mocked method - _(jar.vendor).must_be_nil + _(jar.vendor).must_be_nil # vendor method is a mocked method jar.vendor_jars - # vendor method is a mocked method _(jar.vendor).must_be_nil end @@ -72,30 +70,24 @@ def do_install(vendor, write) spec.platform = 'ruby' jar = Jars::Installer.new(spec) jar.install_jars - # vendor method is a mocked method - _(jar.vendor).must_be_nil + _(jar.vendor).must_be_nil # vendor method is a mocked method jar.vendor_jars - # vendor method is a mocked method - _(jar.vendor).must_be_nil + _(jar.vendor).must_be_nil # vendor method is a mocked method end it 'does install_jars and vendor_jars' do ENV['JARS_VENDOR'] = nil jar = Jars::Installer.new(example_spec) jar.install_jars - # vendor method is a mocked method - assert_nil jar.vendor + assert_nil jar.vendor # vendor method is a mocked method ENV['JARS_VENDOR'] = 'false' jar.vendor_jars - # vendor method is a mocked method assert_nil jar.vendor ENV['JARS_VENDOR'] = 'true' jar.vendor_jars - # vendor method is a mocked method _(jar.vendor).must_equal 'lib' java.lang.System.set_property('jars.vendor', 'false') jar.vendor_jars - # vendor method is a mocked method assert_nil jar.vendor end diff --git a/specs/jars_spec.rb b/specs/jars_spec.rb index 3514ded..9334c99 100644 --- a/specs/jars_spec.rb +++ b/specs/jars_spec.rb @@ -1,12 +1,13 @@ # frozen_string_literal: true require File.expand_path('setup', File.dirname(__FILE__)) +require 'minitest/mock' require 'stringio' + describe Jars do before do - @env = ENV.to_h - # helpful when debugging + @env = ENV.to_h # helpful when debugging Jars.reset end @@ -122,7 +123,7 @@ Jars.reset fake = Object.new - def fake.lock_down(_vendor_dir = nil, **_kwargs) + def fake.lock_down(...) [Jars.debug?, Jars.verbose?, ENV['JARS_SKIP_LOCK']] end @@ -364,4 +365,37 @@ def fake.lock_down(_vendor_dir = nil, **_kwargs) Jars.setup jars_lock: 'Jars_no_jline.lock' _(Jars.lock).must_equal 'Jars_no_jline.lock' end + + it 'only suppresses version conflict warnings for jars in the lockfile' do + lock_file = File.join(Dir.pwd, 'Jars_test_46.lock') + File.write(lock_file, "org.slf4j:slf4j-simple:1.6.6:compile:\n") + ENV['JARS_HOME'] = File.join('specs', 'repo') + ENV['JARS_LOCK'] = lock_file + Jars.instance_variable_set(:@jars_lock, false) + Jars.reset + + # trigger lock file loading + $stderr = StringIO.new + require_jar('org.slf4j', 'slf4j-simple', '1.6.6') + + _($stderr.string).must_equal '' + assert_nil Jars.quiet? + # verify only the lock jar is tracked + _(Jars.locked_jar?('org.slf4j:slf4j-simple')).must_equal true + _(Jars.locked_jar?('some:other')).must_equal false + + require 'jopenssl/version' + # verify conflict for a lock jar is suppressed + require_jar('org.slf4j', 'slf4j-simple', '1.7.4') + _($stderr.string).must_equal '' + require_jar('org.bouncycastle', 'bcpkix-jdk18on', JOpenSSL::BOUNCY_CASTLE_VERSION) + require_jar('org.bouncycastle', 'bcpkix-jdk18on', '1.42') + # warn still happens for non-lock jars + _($stderr.string).must_match 'jar conflict: org.bouncycastle:bcpkix-jdk18on already loaded' + ensure + $stderr = STDERR + FileUtils.rm_rf(lock_file) if lock_file + ENV['JARS_HOME'] = nil + ENV['JARS_LOCK'] = nil + end end diff --git a/specs/mima_spec.rb b/specs/mima_spec.rb index 1c92fd6..f875e6d 100644 --- a/specs/mima_spec.rb +++ b/specs/mima_spec.rb @@ -28,9 +28,9 @@ ENV['JARS_DEBUG'] = 'true' $stderr = StringIO.new - artifact = Jars::GemspecArtifacts::Artifact.new('jar org.example:example, 1.0') + artifact = Jars::GemspecArtifacts::Artifact.parse('jar org.example:example, 1.0') begin - Jars::Mima.resolve_artifacts([ artifact ]) + Jars::Mima.resolve_artifacts([artifact]) rescue org.eclipse.aether.resolution.DependencyResolutionException # expected end diff --git a/specs/setup.rb b/specs/setup.rb index 0a893aa..917fbc1 100644 --- a/specs/setup.rb +++ b/specs/setup.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true -# single spec setup -$LOAD_PATH.unshift File.join(File.dirname(File.expand_path(__FILE__)), '../lib') +require 'bundler/setup' ENV['JARS_HOME'] = nil require 'jar_dependencies' @@ -9,9 +8,4 @@ p ENV['JARS_LOCAL_MAVEN_REPO'] = Jars.home Jars.reset -begin - require 'minitest' -rescue LoadError - # ignore -end require 'minitest/autorun'