From 73fc703f7cbb2e6dfd50897d26b37fe8e76064e3 Mon Sep 17 00:00:00 2001 From: drbrain Date: Sat, 30 Nov 2013 23:27:52 +0000 Subject: [PATCH] * lib/rubygems: Update to RubyGems master 66e5c39. Notable changes: Implement gem.deps.rb (Gemfile) .lock support Fixed `gem uninstall` for a relative directory in GEM_HOME. * test/rubygems: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43939 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 10 ++ lib/rubygems.rb | 4 +- lib/rubygems/basic_specification.rb | 22 +++- lib/rubygems/ext/builder.rb | 2 +- lib/rubygems/ext/rake_builder.rb | 2 +- lib/rubygems/rdoc.rb | 2 +- lib/rubygems/request_set.rb | 20 +++- lib/rubygems/request_set/lockfile.rb | 25 +++- lib/rubygems/resolver/best_set.rb | 10 ++ lib/rubygems/resolver/git_set.rb | 23 ++++ lib/rubygems/resolver/index_set.rb | 24 ++++ lib/rubygems/resolver/lock_set.rb | 18 ++- lib/rubygems/resolver/vendor_set.rb | 15 +++ lib/rubygems/source.rb | 2 + lib/rubygems/source/git.rb | 34 +++++- lib/rubygems/source/installed.rb | 3 +- lib/rubygems/source/local.rb | 3 +- lib/rubygems/source/lock.rb | 44 +++++++ lib/rubygems/source/vendor.rb | 2 + lib/rubygems/specification.rb | 2 +- lib/rubygems/test_utilities.rb | 18 +++ lib/rubygems/validator.rb | 1 + test/rubygems/test_gem_request_set.rb | 74 +++++++++++- .../rubygems/test_gem_request_set_lockfile.rb | 26 +++++ test/rubygems/test_gem_resolver_git_set.rb | 28 +++++ .../test_gem_resolver_git_specification.rb | 34 ++++++ test/rubygems/test_gem_resolver_lock_set.rb | 7 +- test/rubygems/test_gem_source_git.rb | 39 +++++++ test/rubygems/test_gem_source_lock.rb | 107 ++++++++++++++++++ test/rubygems/test_gem_specification.rb | 14 +++ test/rubygems/test_gem_validator.rb | 9 ++ 31 files changed, 598 insertions(+), 26 deletions(-) create mode 100644 lib/rubygems/source/lock.rb create mode 100644 test/rubygems/test_gem_source_lock.rb diff --git a/ChangeLog b/ChangeLog index ed5261eefb..75b0ae0c5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Sun Dec 1 08:27:28 2013 Eric Hodel + + * lib/rubygems: Update to RubyGems master 66e5c39. Notable changes: + + Implement gem.deps.rb (Gemfile) .lock support + + Fixed `gem uninstall` for a relative directory in GEM_HOME. + + * test/rubygems: ditto. + Sun Dec 1 06:00:49 2013 Aman Gupta * test/ruby/test_gc.rb (test_gc_reason): Force minor GC by consuming diff --git a/lib/rubygems.rb b/lib/rubygems.rb index 7570e4ad24..4ff5a0cf4e 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -178,8 +178,8 @@ module Gem def self.try_activate path # finds the _latest_ version... regardless of loaded specs and their deps # if another gem had a requirement that would mean we shouldn't - # activate the latest version, then either it would alreaby be activated - # or if it was ambigious (and thus unresolved) the code in our custom + # activate the latest version, then either it would already be activated + # or if it was ambiguous (and thus unresolved) the code in our custom # require will try to activate the more specific version. spec = Gem::Specification.find_inactive_by_path path diff --git a/lib/rubygems/basic_specification.rb b/lib/rubygems/basic_specification.rb index cfbfbdde92..bb4fa281a0 100644 --- a/lib/rubygems/basic_specification.rb +++ b/lib/rubygems/basic_specification.rb @@ -4,6 +4,16 @@ class Gem::BasicSpecification + ## + # Allows installation of extensions for git: gems. + + attr_writer :base_dir # :nodoc: + + ## + # Sets the directory where extensions for this gem will be installed. + + attr_writer :extension_install_dir # :nodoc: + ## # The path this gemspec was loaded from. This attribute is not persisted. @@ -68,8 +78,9 @@ class Gem::BasicSpecification # end def extension_install_dir - File.join base_dir, 'extensions', Gem::Platform.local.to_s, - Gem.extension_api_version, full_name + @extension_install_dir ||= + File.join base_dir, 'extensions', Gem::Platform.local.to_s, + Gem.extension_api_version, full_name end def find_full_gem_path # :nodoc: @@ -141,9 +152,10 @@ class Gem::BasicSpecification def loaded_from= path @loaded_from = path && path.to_s - @full_gem_path = nil - @gems_dir = nil - @base_dir = nil + @extension_install_dir = nil + @full_gem_path = nil + @gems_dir = nil + @base_dir = nil end ## diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb index e9244c760c..110576e685 100644 --- a/lib/rubygems/ext/builder.rb +++ b/lib/rubygems/ext/builder.rb @@ -98,7 +98,7 @@ class Gem::Ext::Builder def initialize spec, build_args = spec.build_args @spec = spec @build_args = build_args - @gem_dir = spec.gem_dir + @gem_dir = spec.full_gem_path @ran_rake = nil end diff --git a/lib/rubygems/ext/rake_builder.rb b/lib/rubygems/ext/rake_builder.rb index 2093bcabdd..d5ebf597ae 100644 --- a/lib/rubygems/ext/rake_builder.rb +++ b/lib/rubygems/ext/rake_builder.rb @@ -19,7 +19,7 @@ class Gem::Ext::RakeBuilder < Gem::Ext::Builder rake = ENV['rake'] rake ||= begin - "\"#{Gem.ruby}\" -rubygems #{Gem.bin_path('rake', 'rake')}" + "#{Gem.ruby} -rubygems #{Gem.bin_path('rake', 'rake')}" rescue Gem::Exception end diff --git a/lib/rubygems/rdoc.rb b/lib/rubygems/rdoc.rb index f16c8696f0..52249dc267 100644 --- a/lib/rubygems/rdoc.rb +++ b/lib/rubygems/rdoc.rb @@ -8,7 +8,7 @@ rescue Gem::LoadError # swallow else # This will force any deps that 'rdoc' might have - # (such as json) that are ambigious to be activated, which + # (such as json) that are ambiguous to be activated, which # is important because we end up using Specification.reset # and we don't want the warning it pops out. Gem.finish_resolve diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb index d6337e32d8..54e4d9dee4 100644 --- a/lib/rubygems/request_set.rb +++ b/lib/rubygems/request_set.rb @@ -67,6 +67,7 @@ class Gem::RequestSet @dependency_names = {} @development = false @git_set = nil + @install_dir = Gem.dir @requests = [] @sets = [] @soft_missing = false @@ -143,7 +144,11 @@ class Gem::RequestSet # dependencies file are not used. See Gem::Installer for other +options+. def install_from_gemdeps options, &block - load_gemdeps options[:gemdeps], options[:without_groups] + gemdeps = options[:gemdeps] + + @install_dir = options[:install_dir] || Gem.dir + + load_gemdeps gemdeps, options[:without_groups] resolve @@ -154,7 +159,12 @@ class Gem::RequestSet puts " #{s}" end else - install options, &block + installed = install options, &block + + lockfile = Gem::RequestSet::Lockfile.new self, gemdeps + lockfile.write + + installed end end @@ -194,6 +204,11 @@ class Gem::RequestSet @git_set = Gem::Resolver::GitSet.new @vendor_set = Gem::Resolver::VendorSet.new + @git_set.root_dir = @install_dir + + lockfile = Gem::RequestSet::Lockfile.new self, path + lockfile.parse + gf = Gem::RequestSet::GemDependencyAPI.new self, path gf.without_groups = without_groups if without_groups gf.load @@ -264,3 +279,4 @@ class Gem::RequestSet end require 'rubygems/request_set/gem_dependency_api' +require 'rubygems/request_set/lockfile' diff --git a/lib/rubygems/request_set/lockfile.rb b/lib/rubygems/request_set/lockfile.rb index 0073bfdcc5..d70b09f7a2 100644 --- a/lib/rubygems/request_set/lockfile.rb +++ b/lib/rubygems/request_set/lockfile.rb @@ -1,3 +1,8 @@ +## +# Parses a gem.deps.rb.lock file and constructs a LockSet containing the +# dependencies found inside. If the lock file is missing no LockSet is +# constructed. + class Gem::RequestSet::Lockfile ## @@ -100,7 +105,7 @@ class Gem::RequestSet::Lockfile out << nil end - def relative_path_from(dest, base) + def relative_path_from dest, base # :nodoc: dest = File.expand_path(dest) base = File.expand_path(base) @@ -263,6 +268,9 @@ class Gem::RequestSet::Lockfile get while not @tokens.empty? and peek.first == type end + ## + # The contents of the lock file. + def to_s @set.resolve @@ -293,6 +301,10 @@ class Gem::RequestSet::Lockfile [byte_offset - @line_pos, @line] end + ## + # Converts a lock file into an Array of tokens. If the lock file is missing + # an empty Array is returned. + def tokenize # :nodoc: @line = 0 @line_pos = 0 @@ -342,6 +354,8 @@ class Gem::RequestSet::Lockfile end end + @tokens + rescue Errno::ENOENT @tokens end @@ -352,5 +366,14 @@ class Gem::RequestSet::Lockfile @tokens.unshift @current_token end + ## + # Writes the lock file alongside the gem dependencies file + + def write + open "#{@gem_deps_file}.lock", 'w' do |io| + io.write to_s + end + end + end diff --git a/lib/rubygems/resolver/best_set.rb b/lib/rubygems/resolver/best_set.rb index 533a0db58f..fa6c9f84c0 100644 --- a/lib/rubygems/resolver/best_set.rb +++ b/lib/rubygems/resolver/best_set.rb @@ -17,5 +17,15 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet end end + def pretty_print q # :nodoc: + q.group 2, '[BestSet', ']' do + q.breakable + q.text 'sets:' + + q.breakable + q.pp @sets + end + end + end diff --git a/lib/rubygems/resolver/git_set.rb b/lib/rubygems/resolver/git_set.rb index c912e367d9..ed809c124f 100644 --- a/lib/rubygems/resolver/git_set.rb +++ b/lib/rubygems/resolver/git_set.rb @@ -10,6 +10,12 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set + ## + # The root directory for git gems in this set. This is usually Gem.dir, the + # installation directory for regular gems. + + attr_accessor :root_dir + ## # Contains repositories needing submodules @@ -30,6 +36,7 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set @git = ENV['git'] || 'git' @need_submodules = {} @repositories = {} + @root_dir = Gem.dir @specs = {} end @@ -57,6 +64,7 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set @repositories.each do |name, (repository, reference)| source = Gem::Source::Git.new name, repository, reference + source.root_dir = @root_dir source.specs.each do |spec| git_spec = Gem::Resolver::GitSpecification.new self, spec, source @@ -66,5 +74,20 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set end end + def pretty_print q # :nodoc: + q.group 2, '[GitSet', ']' do + next if @repositories.empty? + q.breakable + + repos = @repositories.map do |name, (repository, reference)| + "#{name}: #{repository}@#{reference}" + end + + q.seplist repos do |repo| + q.text repo + end + end + end + end diff --git a/lib/rubygems/resolver/index_set.rb b/lib/rubygems/resolver/index_set.rb index 0ba3c78a44..a6ef56bb7f 100644 --- a/lib/rubygems/resolver/index_set.rb +++ b/lib/rubygems/resolver/index_set.rb @@ -46,5 +46,29 @@ class Gem::Resolver::IndexSet < Gem::Resolver::Set res end + def pretty_print q # :nodoc: + q.group 2, '[IndexSet', ']' do + q.breakable + q.text 'sources:' + q.breakable + q.pp @f.sources + + q.breakable + q.text 'specs:' + + q.breakable + + names = @all.values.map do |tuples| + tuples.map do |_, tuple| + tuple.full_name + end + end.flatten + + q.seplist names do |name| + q.text name + end + end + end + end diff --git a/lib/rubygems/resolver/lock_set.rb b/lib/rubygems/resolver/lock_set.rb index 6885e70945..ef5395597d 100644 --- a/lib/rubygems/resolver/lock_set.rb +++ b/lib/rubygems/resolver/lock_set.rb @@ -9,7 +9,7 @@ class Gem::Resolver::LockSet < Gem::Resolver::Set # Creates a new LockSet from the given +source+ def initialize source - @source = source + @source = Gem::Source::Lock.new source @specs = [] end @@ -56,5 +56,21 @@ class Gem::Resolver::LockSet < Gem::Resolver::Set found.source.fetch_spec tuple end + def pretty_print q # :nodoc: + q.group 2, '[LockSet', ']' do + q.breakable + q.text 'source:' + + q.breakable + q.pp @source + + q.breakable + q.text 'specs:' + + q.breakable + q.pp @specs.map { |spec| spec.full_name } + end + end + end diff --git a/lib/rubygems/resolver/vendor_set.rb b/lib/rubygems/resolver/vendor_set.rb index c8826005a7..339492f690 100644 --- a/lib/rubygems/resolver/vendor_set.rb +++ b/lib/rubygems/resolver/vendor_set.rb @@ -64,5 +64,20 @@ class Gem::Resolver::VendorSet < Gem::Resolver::Set @specs.fetch key end + def pretty_print q # :nodoc: + q.group 2, '[VendorSet', ']' do + next if @directories.empty? + q.breakable + + dirs = @directories.map do |spec, directory| + "#{spec.full_name}: #{directory}" + end + + q.seplist dirs do |dir| + q.text dir + end + end + end + end diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb index b6e2d97523..9553db18c6 100644 --- a/lib/rubygems/source.rb +++ b/lib/rubygems/source.rb @@ -49,6 +49,7 @@ class Gem::Source case other when Gem::Source::Installed, Gem::Source::Local, + Gem::Source::Lock, Gem::Source::SpecificFile, Gem::Source::Git, Gem::Source::Vendor then @@ -213,5 +214,6 @@ require 'rubygems/source/git' require 'rubygems/source/installed' require 'rubygems/source/specific_file' require 'rubygems/source/local' +require 'rubygems/source/lock' require 'rubygems/source/vendor' diff --git a/lib/rubygems/source/git.rb b/lib/rubygems/source/git.rb index 2794735c96..e8b03165c1 100644 --- a/lib/rubygems/source/git.rb +++ b/lib/rubygems/source/git.rb @@ -30,6 +30,11 @@ class Gem::Source::Git < Gem::Source attr_reader :repository + ## + # The directory for cache and git gem installation + + attr_accessor :root_dir + ## # Does this repository need submodules checked out too? @@ -50,14 +55,16 @@ class Gem::Source::Git < Gem::Source @reference = reference @need_submodules = submodules - @git = ENV['git'] || 'git' + @root_dir = Gem.dir + @git = ENV['git'] || 'git' end def <=> other case other when Gem::Source::Git then 0 - when Gem::Source::Installed then + when Gem::Source::Installed, + Gem::Source::Lock then -1 when Gem::Source then 1 @@ -113,6 +120,13 @@ class Gem::Source::Git < Gem::Source end end + ## + # Directory where git gems get unpacked and so-forth. + + def base_dir # :nodoc: + File.join @root_dir, 'bundler' + end + ## # A short reference for use in git gem directories @@ -130,14 +144,14 @@ class Gem::Source::Git < Gem::Source # The directory where the git gem will be installed. def install_dir # :nodoc: - File.join Gem.dir, 'bundler', 'gems', "#{@name}-#{dir_shortref}" + File.join base_dir, 'gems', "#{@name}-#{dir_shortref}" end ## # The directory where the git gem's repository will be cached. def repo_cache_dir # :nodoc: - File.join Gem.dir, 'cache', 'bundler', 'git', "#{@name}-#{uri_hash}" + File.join @root_dir, 'cache', 'bundler', 'git', "#{@name}-#{uri_hash}" end ## @@ -162,7 +176,17 @@ class Gem::Source::Git < Gem::Source Dir.chdir directory do spec = Gem::Specification.load file - spec.full_gem_path = File.expand_path '.' if spec + if spec then + loaded_from = File.expand_path file + spec.loaded_from = loaded_from + spec.base_dir = base_dir + + spec.extension_install_dir = + File.join base_dir, 'extensions', Gem::Platform.local.to_s, + Gem.extension_api_version, "#{name}-#{dir_shortref}" + + spec.full_gem_path = File.dirname loaded_from if spec + end spec end end.compact diff --git a/lib/rubygems/source/installed.rb b/lib/rubygems/source/installed.rb index 2661dd6844..6d343c2439 100644 --- a/lib/rubygems/source/installed.rb +++ b/lib/rubygems/source/installed.rb @@ -12,7 +12,8 @@ class Gem::Source::Installed < Gem::Source def <=> other case other - when Gem::Source::Vendor then + when Gem::Source::Lock, + Gem::Source::Vendor then -1 when Gem::Source::Installed then 0 diff --git a/lib/rubygems/source/local.rb b/lib/rubygems/source/local.rb index 3aae20c8ed..8057921163 100644 --- a/lib/rubygems/source/local.rb +++ b/lib/rubygems/source/local.rb @@ -15,7 +15,8 @@ class Gem::Source::Local < Gem::Source def <=> other case other - when Gem::Source::Installed then + when Gem::Source::Installed, + Gem::Source::Lock then -1 when Gem::Source::Local then 0 diff --git a/lib/rubygems/source/lock.rb b/lib/rubygems/source/lock.rb new file mode 100644 index 0000000000..d8a46d8d10 --- /dev/null +++ b/lib/rubygems/source/lock.rb @@ -0,0 +1,44 @@ +## +# A Lock source wraps an installed gem's source and sorts before other sources +# during dependency resolution. This allows RubyGems to prefer gems from +# dependency lock files. + +class Gem::Source::Lock < Gem::Source + + ## + # The wrapped Gem::Source + + attr_reader :wrapped + + ## + # Creates a new Lock source that wraps +source+ and moves it earlier in the + # sort list. + + def initialize source + @wrapped = source + end + + def <=> other # :nodoc: + case other + when Gem::Source::Lock then + @wrapped <=> other.wrapped + when Gem::Source then + 1 + else + nil + end + end + + def == other # :nodoc: + 0 == (self <=> other) + end + + ## + # Delegates to the wrapped source's fetch_spec method. + + def fetch_spec name_tuple + @wrapped.fetch_spec name_tuple + end + +end + diff --git a/lib/rubygems/source/vendor.rb b/lib/rubygems/source/vendor.rb index 244c4201d8..2d936231c1 100644 --- a/lib/rubygems/source/vendor.rb +++ b/lib/rubygems/source/vendor.rb @@ -12,6 +12,8 @@ class Gem::Source::Vendor < Gem::Source::Installed def <=> other case other + when Gem::Source::Lock then + -1 when Gem::Source::Vendor then 0 when Gem::Source then diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 2bcc2c0ef2..abfd139581 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -1031,7 +1031,7 @@ class Gem::Specification < Gem::BasicSpecification spec = eval code, binding, file if Gem::Specification === spec - spec.loaded_from = file.to_s + spec.loaded_from = File.expand_path file.to_s LOAD_CACHE[file] = spec return spec end diff --git a/lib/rubygems/test_utilities.rb b/lib/rubygems/test_utilities.rb index f7943adcee..ee5ef01203 100644 --- a/lib/rubygems/test_utilities.rb +++ b/lib/rubygems/test_utilities.rb @@ -101,6 +101,24 @@ class Gem::FakeFetcher response end + def pretty_print q # :nodoc: + q.group 2, '[FakeFetcher', ']' do + q.breakable + q.text 'URIs:' + + q.breakable + q.pp @data.keys + + unless @api_endpoints.empty? then + q.breakable + q.text 'API endpoints:' + + q.breakable + q.pp @api_endpoints.keys + end + end + end + def fetch_size(path) path = path.to_s @paths << path diff --git a/lib/rubygems/validator.rb b/lib/rubygems/validator.rb index 1436a93ae6..6992af16ba 100644 --- a/lib/rubygems/validator.rb +++ b/lib/rubygems/validator.rb @@ -86,6 +86,7 @@ class Gem::Validator Gem::Specification.each do |spec| next unless gems.include? spec.name unless gems.empty? + next if spec.default_gem? gem_name = spec.file_name gem_path = spec.cache_file diff --git a/test/rubygems/test_gem_request_set.rb b/test/rubygems/test_gem_request_set.rb index 6719be372c..324d0cd7a8 100644 --- a/test/rubygems/test_gem_request_set.rb +++ b/test/rubygems/test_gem_request_set.rb @@ -45,16 +45,88 @@ class TestGemRequestSet < Gem::TestCase rs = Gem::RequestSet.new installed = [] + open 'gem.deps.rb', 'w' do |io| + io.puts 'gem "a"' + io.flush + + result = rs.install_from_gemdeps :gemdeps => io.path do |req, installer| + installed << req.full_name + end + + assert_kind_of Array, result # what is supposed to be in here? + end + + assert_includes installed, 'a-2' + assert_path_exists File.join @gemhome, 'gems', 'a-2' + assert_path_exists 'gem.deps.rb.lock' + end + + def test_install_from_gemdeps_install_dir + spec_fetcher do |fetcher| + fetcher.gem 'a', 2 + end + + util_clear_gems + refute_path_exists File.join Gem.dir, 'gems', 'a-2' + + rs = Gem::RequestSet.new + installed = [] + Tempfile.open 'gem.deps.rb' do |io| io.puts 'gem "a"' io.flush - rs.install_from_gemdeps :gemdeps => io.path do |req, installer| + options = { + :gemdeps => io.path, + :install_dir => "#{@gemhome}2", + } + + rs.install_from_gemdeps options do |req, installer| installed << req.full_name end end assert_includes installed, 'a-2' + refute_path_exists File.join Gem.dir, 'gems', 'a-2' + end + + def test_install_from_gemdeps_lockfile + spec_fetcher do |fetcher| + fetcher.gem 'a', 1 + fetcher.gem 'a', 2 + fetcher.gem 'b', 1, 'a' => '>= 0' + end + + rs = Gem::RequestSet.new + installed = [] + + open 'gem.deps.rb.lock', 'w' do |io| + io.puts <<-LOCKFILE +GEM + remote: #{@gem_repo} + specs: + a (1) + b (1) + a + +PLATFORMS + #{Gem::Platform::RUBY} + +DEPENDENCIES + b + LOCKFILE + end + + open 'gem.deps.rb', 'w' do |io| + io.puts 'gem "b"' + end + + rs.install_from_gemdeps :gemdeps => 'gem.deps.rb' do |req, installer| + installed << req.full_name + end + + assert_includes installed, 'b-1' + assert_includes installed, 'a-1' end def test_load_gemdeps diff --git a/test/rubygems/test_gem_request_set_lockfile.rb b/test/rubygems/test_gem_request_set_lockfile.rb index fcd4ecfaf7..18c44144fa 100644 --- a/test/rubygems/test_gem_request_set_lockfile.rb +++ b/test/rubygems/test_gem_request_set_lockfile.rb @@ -104,6 +104,16 @@ DEPENDENCIES assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name } end + def test_parse_missing + @lockfile.parse + + lockfile_set = @set.sets.find do |set| + Gem::Resolver::LockSet === set + end + + refute lockfile_set + end + def test_peek @lockfile.instance_variable_set :@tokens, [:token] @@ -211,6 +221,12 @@ DEPENDENCIES e.message end + def test_tokenize_missing + tokens = @lockfile.tokenize + + assert_empty tokens + end + def test_to_s_gem spec_fetcher do |fetcher| fetcher.spec 'a', 2 @@ -400,5 +416,15 @@ DEPENDENCIES assert_equal :token, @lockfile.get end + def test_write + @lockfile.write + + gem_deps_lock_file = "#{@gem_deps_file}.lock" + + assert_path_exists gem_deps_lock_file + + refute_empty File.read gem_deps_lock_file + end + end diff --git a/test/rubygems/test_gem_resolver_git_set.rb b/test/rubygems/test_gem_resolver_git_set.rb index 1ca12a7251..b1a8d838bb 100644 --- a/test/rubygems/test_gem_resolver_git_set.rb +++ b/test/rubygems/test_gem_resolver_git_set.rb @@ -52,6 +52,14 @@ class TestGemResolverGitSet < Gem::TestCase assert_equal [@set.specs['a']], found end + def test_root_dir + assert_equal Gem.dir, @set.root_dir + + @set.root_dir = "#{@gemhome}2" + + assert_equal "#{@gemhome}2", @set.root_dir + end + def test_prefetch name, _, repository, = git_gem @@ -98,5 +106,25 @@ class TestGemResolverGitSet < Gem::TestCase refute_empty @set.specs, 'the git source does not filter' end + def test_prefetch_root_dir + name, _, repository, = git_gem + + @set.add_git_gem name, repository, 'master', false + + dependency = dep name + req = Gem::Resolver::ActivationRequest.new dependency, nil + @reqs.add req + + @set.root_dir = "#{@gemhome}2" + + @set.prefetch @reqs + + refute_empty @set.specs + + spec = @set.specs.values.first + + assert_equal "#{@gemhome}2", spec.source.root_dir + end + end diff --git a/test/rubygems/test_gem_resolver_git_specification.rb b/test/rubygems/test_gem_resolver_git_specification.rb index d724106f08..b0163bc782 100644 --- a/test/rubygems/test_gem_resolver_git_specification.rb +++ b/test/rubygems/test_gem_resolver_git_specification.rb @@ -46,5 +46,39 @@ class TestGemResolverGitSpecification < Gem::TestCase assert called end + # functional test for Gem::Ext::Builder + + def test_install_extension + name, _, repository, = git_gem 'a', 1 do |s| + s.extensions << 'ext/extconf.rb' + end + + Dir.chdir 'git/a' do + FileUtils.mkdir_p 'ext/lib' + + open 'ext/extconf.rb', 'w' do |io| + io.puts 'require "mkmf"' + io.puts 'create_makefile "a"' + end + + FileUtils.touch 'ext/lib/b.rb' + + system @git, 'add', 'ext/extconf.rb' + system @git, 'add', 'ext/lib/b.rb' + + system @git, 'commit', '--quiet', '-m', 'Add extension files' + end + + source = Gem::Source::Git.new name, repository, 'master', true + + spec = source.specs.first + + git_spec = Gem::Resolver::GitSpecification.new @set, spec, source + + git_spec.install({}) + + assert_path_exists File.join git_spec.spec.extension_install_dir, 'b.rb' + end + end diff --git a/test/rubygems/test_gem_resolver_lock_set.rb b/test/rubygems/test_gem_resolver_lock_set.rb index 71b28efd4f..6d904fbaee 100644 --- a/test/rubygems/test_gem_resolver_lock_set.rb +++ b/test/rubygems/test_gem_resolver_lock_set.rb @@ -5,7 +5,8 @@ class TestGemResolverLockSet < Gem::TestCase def setup super - @source = Gem::Source.new @gem_repo + @source = Gem::Source.new @gem_repo + @lock_source = Gem::Source::Lock.new @source @set = Gem::Resolver::LockSet.new @source end @@ -21,7 +22,7 @@ class TestGemResolverLockSet < Gem::TestCase assert_equal 'a', spec.name assert_equal v(2), spec.version assert_equal Gem::Platform::RUBY, spec.platform - assert_equal @source, spec.source + assert_equal @lock_source, spec.source end def test_find_all @@ -41,7 +42,7 @@ class TestGemResolverLockSet < Gem::TestCase version = v(2) @set.add 'a', version, Gem::Platform::RUBY - loaded = @set.load_spec 'a', version, Gem::Platform::RUBY, @source + loaded = @set.load_spec 'a', version, Gem::Platform::RUBY, nil assert_kind_of Gem::Specification, loaded diff --git a/test/rubygems/test_gem_source_git.rb b/test/rubygems/test_gem_source_git.rb index 838ae562a7..fc89de474a 100644 --- a/test/rubygems/test_gem_source_git.rb +++ b/test/rubygems/test_gem_source_git.rb @@ -13,6 +13,14 @@ class TestGemSourceGit < Gem::TestCase @source = Gem::Source::Git.new @name, @repository, 'master', false end + def test_base_dir + assert_equal File.join(Gem.dir, 'bundler'), @source.base_dir + + @source.root_dir = "#{@gemhome}2" + + assert_equal File.join("#{@gemhome}2", 'bundler'), @source.base_dir + end + def test_checkout @source.checkout @@ -96,6 +104,13 @@ class TestGemSourceGit < Gem::TestCase File.join Gem.dir, 'cache', 'bundler', 'git', "a-#{@hash}" assert_equal expected, @source.repo_cache_dir + + @source.root_dir = "#{@gemhome}2" + + expected = + File.join "#{@gemhome}2", 'cache', 'bundler', 'git', "a-#{@hash}" + + assert_equal expected, @source.repo_cache_dir end def test_rev_parse @@ -118,6 +133,14 @@ class TestGemSourceGit < Gem::TestCase refute_equal master_head, source.rev_parse end + def test_root_dir + assert_equal Gem.dir, @source.root_dir + + @source.root_dir = "#{@gemhome}2" + + assert_equal "#{@gemhome}2", @source.root_dir + end + def test_spaceship git = Gem::Source::Git.new 'a', 'git/a', 'master', false remote = Gem::Source.new @gem_repo @@ -165,11 +188,27 @@ class TestGemSourceGit < Gem::TestCase a_spec = specs.shift + base_dir = File.dirname File.dirname source.install_dir + assert_equal source.install_dir, a_spec.full_gem_path + assert_equal File.join(source.install_dir, 'a.gemspec'), a_spec.loaded_from + assert_equal base_dir, a_spec.base_dir + + extension_install_dir = + File.join Gem.dir, 'bundler', 'extensions', + Gem::Platform.local.to_s, Gem.extension_api_version, + "a-#{source.dir_shortref}" + + assert_equal extension_install_dir, a_spec.extension_install_dir b_spec = specs.shift assert_equal File.join(source.install_dir, 'b'), b_spec.full_gem_path + assert_equal File.join(source.install_dir, 'b', 'b.gemspec'), + b_spec.loaded_from + assert_equal base_dir, b_spec.base_dir + + assert_equal extension_install_dir, b_spec.extension_install_dir end def test_uri_hash diff --git a/test/rubygems/test_gem_source_lock.rb b/test/rubygems/test_gem_source_lock.rb new file mode 100644 index 0000000000..d114dccbb7 --- /dev/null +++ b/test/rubygems/test_gem_source_lock.rb @@ -0,0 +1,107 @@ +require 'rubygems/test_case' + +class TestGemSourceLock < Gem::TestCase + + def test_fetch_spec + spec_fetcher do |fetcher| + fetcher.spec 'a', 1 + end + + name_tuple = Gem::NameTuple.new 'a', v(1), 'ruby' + + remote = Gem::Source.new @gem_repo + lock = Gem::Source::Lock.new remote + + spec = lock.fetch_spec name_tuple + + assert_equal 'a-1', spec.full_name + end + + def test_equals2 + git = Gem::Source::Git.new 'a', 'git/a', 'master', false + g_lock = Gem::Source::Lock.new git + + installed = Gem::Source::Installed.new + i_lock = Gem::Source::Lock.new installed + + assert_equal g_lock, g_lock + refute_equal g_lock, i_lock + refute_equal g_lock, Object.new + end + + def test_spaceship + git = Gem::Source::Git.new 'a', 'git/a', 'master', false + g_lock = Gem::Source::Lock.new git + + installed = Gem::Source::Installed.new + i_lock = Gem::Source::Lock.new installed + + vendor = Gem::Source::Vendor.new 'vendor/a' + v_lock = Gem::Source::Lock.new vendor + + assert_equal( 0, g_lock.<=>(g_lock), 'g_lock <=> g_lock') + assert_equal( 0, i_lock.<=>(i_lock), 'i_lock <=> i_lock') + assert_equal( 0, v_lock.<=>(v_lock), 'v_lock <=> v_lock') + + assert_equal(-1, g_lock.<=>(i_lock), 'g_lock <=> i_lock') + assert_equal( 1, i_lock.<=>(g_lock), 'i_lock <=> g_lock') + + assert_equal(-1, g_lock.<=>(v_lock), 'g_lock <=> v_lock') + assert_equal( 1, v_lock.<=>(g_lock), 'v_lock <=> g_lock') + + assert_equal(-1, i_lock.<=>(v_lock), 'i_lock <=> v_lock') + assert_equal( 1, v_lock.<=>(i_lock), 'i_lock <=> v_lock') + end + + def test_spaceship_git + git = Gem::Source::Git.new 'a', 'git/a', 'master', false + lock = Gem::Source::Lock.new git + + assert_equal( 1, lock.<=>(git), 'lock <=> git') + assert_equal(-1, git .<=>(lock), 'git <=> lock') + end + + def test_spaceship_installed + installed = Gem::Source::Installed.new + lock = Gem::Source::Lock.new installed + + assert_equal( 1, lock. <=>(installed), 'lock <=> installed') + assert_equal(-1, installed.<=>(lock), 'installed <=> lock') + end + + def test_spaceship_local + local = Gem::Source::Local.new + lock = Gem::Source::Lock.new local # nonsense + + assert_equal( 1, lock. <=>(local), 'lock <=> local') + assert_equal(-1, local.<=>(lock), 'local <=> lock') + end + + def test_spaceship_remote + remote = Gem::Source.new @gem_repo + lock = Gem::Source::Lock.new remote + + assert_equal( 1, lock. <=>(remote), 'lock <=> remote') + assert_equal(-1, remote.<=>(lock), 'remote <=> lock') + end + + def test_spaceship_specific_file + _, gem = util_gem 'a', 1 + + specific = Gem::Source::SpecificFile.new gem + lock = Gem::Source::Lock.new specific # nonsense + + assert_equal( 1, lock .<=>(specific), 'lock <=> specific') + assert_equal(-1, specific.<=>(lock), 'specific <=> lock') + end + + def test_spaceship_vendor + vendor = Gem::Source::Vendor.new 'vendor/a' + lock = Gem::Source::Lock.new vendor + + assert_equal( 1, lock. <=>(vendor), 'lock <=> vendor') + assert_equal(-1, vendor.<=>(lock), 'vendor <=> lock') + end + +end + diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index b63721270e..76cb12ca58 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -716,6 +716,20 @@ dependencies: [] assert_equal @a2, spec end + def test_self_load_relative + open 'a-2.gemspec', 'w' do |io| + io.write @a2.to_ruby_for_cache + end + + spec = Gem::Specification.load 'a-2.gemspec' + + @a2.files.clear + + assert_equal @a2, spec + + assert_equal File.join(@tempdir, 'a-2.gemspec'), spec.loaded_from + end + def test_self_load_tainted full_path = @a2.spec_file write_file full_path do |io| diff --git a/test/rubygems/test_gem_validator.rb b/test/rubygems/test_gem_validator.rb index ab2a9b82a7..4af8b524e1 100644 --- a/test/rubygems/test_gem_validator.rb +++ b/test/rubygems/test_gem_validator.rb @@ -32,5 +32,14 @@ class TestGemValidator < Gem::TestCase assert_equal expected, alien end + + def test_alien_default + new_default_spec 'c', 1, nil, 'lib/c.rb' + + alien = @validator.alien 'c' + + assert_empty alien + end + end