From a35798450864ee9515e1742627fb592a40c0c44a Mon Sep 17 00:00:00 2001 From: drbrain Date: Thu, 17 Oct 2013 02:08:53 +0000 Subject: [PATCH] * lib/rubygems: Update to RubyGems master 941c21a. Changes: Restored method bundler wants to remove for compatibility. Improvements to Gemfile compatibility. * test/rubygems: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43323 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 10 ++ lib/rubygems/exceptions.rb | 6 + lib/rubygems/request_set.rb | 2 +- .../request_set/gem_dependency_api.rb | 98 ++++++++++- lib/rubygems/specification.rb | 7 + ...test_gem_request_set_gem_dependency_api.rb | 154 ++++++++++++++++++ 6 files changed, 268 insertions(+), 9 deletions(-) create mode 100644 test/rubygems/test_gem_request_set_gem_dependency_api.rb diff --git a/ChangeLog b/ChangeLog index d61c10a199..40e11a5038 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Thu Oct 17 11:07:06 2013 Eric Hodel + + * lib/rubygems: Update to RubyGems master 941c21a. Changes: + + Restored method bundler wants to remove for compatibility. + + Improvements to Gemfile compatibility. + + * test/rubygems: ditto. + Thu Oct 17 08:08:11 2013 Koichi Sasada * ext/objspace/object_tracing.c (newobj_i): add workaround. diff --git a/lib/rubygems/exceptions.rb b/lib/rubygems/exceptions.rb index 4a988f9edf..9aef89956e 100644 --- a/lib/rubygems/exceptions.rb +++ b/lib/rubygems/exceptions.rb @@ -154,6 +154,12 @@ class Gem::RemoteInstallationSkipped < Gem::Exception; end # Represents an error communicating via HTTP. class Gem::RemoteSourceException < Gem::Exception; end +## +# Raised when a gem dependencies file specifies a ruby version that does not +# match the current version. + +class Gem::RubyVersionMismatch < Gem::Exception; end + class Gem::VerificationError < Gem::Exception; end ## diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb index 3ff3e83ca6..0d52423f8f 100644 --- a/lib/rubygems/request_set.rb +++ b/lib/rubygems/request_set.rb @@ -143,7 +143,7 @@ class Gem::RequestSet # Load a dependency management file. def load_gemdeps path - gf = Gem::RequestSet::GemDepedencyAPI.new self, path + gf = Gem::RequestSet::GemDependencyAPI.new self, path gf.load end diff --git a/lib/rubygems/request_set/gem_dependency_api.rb b/lib/rubygems/request_set/gem_dependency_api.rb index 178ed1b59d..435e157861 100644 --- a/lib/rubygems/request_set/gem_dependency_api.rb +++ b/lib/rubygems/request_set/gem_dependency_api.rb @@ -1,39 +1,121 @@ ## -# A semi-compatible DSL for Bundler's Gemfile format +# A semi-compatible DSL for the Bundler Gemfile and Isolate formats. -class Gem::RequestSet::GemDepedencyAPI +class Gem::RequestSet::GemDependencyAPI + + ## + # The dependency groups created by #group in the dependency API file. + + attr_reader :dependency_groups + + ## + # Creates a new GemDependencyAPI that will add dependencies to the + # Gem::RequestSet +set+ based on the dependency API description in +path+. def initialize set, path @set = set @path = path + + @current_groups = nil + @dependency_groups = Hash.new { |h, group| h[group] = [] } end + ## + # Loads the gem dependency file + def load instance_eval File.read(@path).untaint, @path, 1 end - # :category: Bundler Gemfile DSL + ## + # :category: Gem Dependencies DSL + # :call-seq: + # gem(name) + # gem(name, *requirements) + # gem(name, *requirements, options) + # + # Specifies a gem dependency with the given +name+ and +requirements+. You + # may also supply +options+ following the +requirements+ - def gem name, *reqs - # Ignore the opts for now. - reqs.pop if reqs.last.kind_of?(Hash) + def gem name, *requirements + options = requirements.pop if requirements.last.kind_of?(Hash) + options ||= {} - @set.gem name, *reqs + groups = + (group = options.delete(:group) and Array(group)) || + options.delete(:groups) || + @current_groups + + if groups then + groups.each do |group| + gem_arguments = [name, *requirements] + gem_arguments << options unless options.empty? + @dependency_groups[group] << gem_arguments + end + + return + end + + @set.gem name, *requirements end - def group *what + ## + # Returns the basename of the file the dependencies were loaded from + + def gem_deps_file # :nodoc: + File.basename @path end + ## + # :category: Gem Dependencies DSL + # Block form for placing a dependency in the given +groups+. + + def group *groups + @current_groups = groups + + yield + + ensure + @current_groups = nil + end + + ## + # :category: Gem Dependencies DSL + def platform what if what == :ruby yield end end + ## + # :category: Gem Dependencies DSL + alias :platforms :platform + ## + # :category: Gem Dependencies DSL + # Restricts this gem dependencies file to the given ruby +version+. The + # +:engine+ options from Bundler are currently ignored. + + def ruby version, options = {} + return true if version == RUBY_VERSION + + message = "Your Ruby version is #{RUBY_VERSION}, " + + "but your #{gem_deps_file} specified #{version}" + + raise Gem::RubyVersionMismatch, message + end + + ## + # :category: Gem Dependencies DSL + def source url end + # TODO: remove this typo name at RubyGems 3.0 + + Gem::RequestSet::DepedencyAPI = self # :nodoc: + end diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index f63f6282d3..21119b901a 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -1720,6 +1720,13 @@ class Gem::Specification < Gem::BasicSpecification File.join extension_install_dir, 'gem.build_complete' end + ## + # Work around bundler removing my methods + + def gem_dir # :nodoc: + super + end + ## # Deprecated and ignored, defaults to true. # diff --git a/test/rubygems/test_gem_request_set_gem_dependency_api.rb b/test/rubygems/test_gem_request_set_gem_dependency_api.rb new file mode 100644 index 0000000000..4747250f60 --- /dev/null +++ b/test/rubygems/test_gem_request_set_gem_dependency_api.rb @@ -0,0 +1,154 @@ +require 'rubygems/test_case' +require 'rubygems/request_set' + +class TestGemRequestSetGemDependencyAPI < Gem::TestCase + + def setup + super + + @GDA = Gem::RequestSet::GemDependencyAPI + + @set = Gem::RequestSet.new + + @gda = @GDA.new @set, 'gem.deps.rb' + end + + def test_gem + @gda.gem 'a' + + assert_equal [dep('a')], @set.dependencies + end + + def test_gem_group + @gda.gem 'a', :group => :test + + expected = { + :test => [['a']], + } + + assert_equal expected, @gda.dependency_groups + + assert_empty @set.dependencies + end + + def test_gem_groups + @gda.gem 'a', :groups => [:test, :development] + + expected = { + :development => [['a']], + :test => [['a']], + } + + assert_equal expected, @gda.dependency_groups + + assert_empty @set.dependencies + end + + def test_gem_requirement + @gda.gem 'a', '~> 1.0' + + assert_equal [dep('a', '~> 1.0')], @set.dependencies + end + + def test_gem_requirements + @gda.gem 'b', '~> 1.0', '>= 1.0.2' + + assert_equal [dep('b', '~> 1.0', '>= 1.0.2')], @set.dependencies + end + + def test_gem_requirements_options + @gda.gem 'c', :git => 'https://example/c.git' + + assert_equal [dep('c')], @set.dependencies + end + + def test_gem_deps_file + assert_equal 'gem.deps.rb', @gda.gem_deps_file + + gda = @GDA.new @set, 'foo/Gemfile' + + assert_equal 'Gemfile', gda.gem_deps_file + end + + def test_group + @gda.group :test do + @gda.gem 'a' + end + + assert_equal [['a']], @gda.dependency_groups[:test] + + assert_empty @set.dependencies + end + + def test_load + Tempfile.open 'gem.deps.rb' do |io| + io.write <<-GEM_DEPS +gem 'a' + +group :test do + gem 'b' +end + GEM_DEPS + io.flush + + gda = @GDA.new @set, io.path + + gda.load + + expected = { + :test => [['b']], + } + + assert_equal expected, gda.dependency_groups + + assert_equal [dep('a')], @set.dependencies + end + end + + def test_name_typo + assert_same @GDA, Gem::RequestSet::DepedencyAPI + end + + def test_platform_mswin + @gda.platform :mswin do + @gda.gem 'a' + end + + assert_empty @set.dependencies + end + + def test_platform_ruby + @gda.platform :ruby do + @gda.gem 'a' + end + + assert_equal [dep('a')], @set.dependencies + end + + def test_platforms + @gda.platforms :ruby do + @gda.gem 'a' + end + + assert_equal [dep('a')], @set.dependencies + end + + def test_ruby + assert @gda.ruby RUBY_VERSION + end + + def test_ruby_engine + assert @gda.ruby RUBY_VERSION, + :engine => 'jruby', :engine_version => '1.7.4' + end + + def test_ruby_mismatch + e = assert_raises Gem::RubyVersionMismatch do + @gda.ruby '1.8.0' + end + + assert_equal "Your Ruby version is #{RUBY_VERSION}, but your gem.deps.rb specified 1.8.0", e.message + end + +end +