Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

+ Added Dependency#to_spec

+ Added Specification#find(name_or_dep, *requirements).
+ Added Specification#activate.
Refactored activate into a sane set of methods.
Switched Gem.activate* to use the new Spec/Dep API.
Fixed all uses of deprecated code in impl and test.
  • Loading branch information...
commit 3d3f699461df256614dbecbcd4bcc22e87b7842f 1 parent de3c1fc
Ryan Davis zenspider authored
126 lib/rubygems.rb
View
@@ -196,6 +196,7 @@ class LoadError < ::LoadError
# activated. Returns false if it can't find the path in a gem.
def self.try_activate path
+ # TODO: deprecate when 1.9.3 comes out.
# finds the _latest_ version... regardless of loaded specs and their deps
# TODO: use find_all and bork if ambiguous
@@ -204,9 +205,10 @@ def self.try_activate path
return false unless spec
begin
- Gem.activate spec.name, "= #{spec.version}"
+ spec.activate
rescue Gem::LoadError # this could fail due to gem dep collisions, go lax
- Gem.activate spec.name
+ # TODO: actually test this
+ Gem::Specification.find(spec.name).activate
end
return true
@@ -229,111 +231,15 @@ def self.try_activate path
# Gem::Requirement and Gem::Version documentation.
def self.activate(dep, *requirements)
- activate_dep dep, *requirements
+ Gem::Specification.find(dep, *requirements).activate
end
- def self.activate_dep dep, *requirements
- requirements = Gem::Requirement.default if requirements.empty?
- dep = Gem::Dependency.new(dep, requirements) unless Gem::Dependency === dep
-
- matches = Gem.source_index.search dep, true
- report_activate_error(dep) if matches.empty?
-
- existing_spec = @loaded_specs[dep.name]
-
- # TODO: move this to Dependency
- if existing_spec then
- # This gem is already loaded. If the currently loaded gem is not in the
- # list of candidate gems, then we have a version conflict.
-
- # TODO: unless dep.matches_spec? existing_spec then
- unless matches.any? { |spec| spec.version == existing_spec.version } then
- msg = "can't activate #{dep}, "
- msg << "already activated #{existing_spec.full_name}"
-
- e = Gem::LoadError.new msg
- e.name = dep.name
- e.requirement = dep.requirement
-
- raise e
- end
-
- return false
- end
-
- # TODO: this + spec.conflicts hint that activation is still dumb
- spec = matches.last
-
- activate_spec spec
+ def self.activate_dep dep, *requirements # :nodoc:
+ Gem::Specification.find(dep, *requirements).activate
end
- def self.activate_spec spec
- existing_spec = @loaded_specs[spec.name]
-
- # TODO: move this to Specification
- if existing_spec then
- if spec.version != existing_spec.version then
- # This gem is already loaded. If the currently loaded gem is not in the
- # list of candidate gems, then we have a version conflict.
-
- msg = "can't activate #{dep}, "
- msg << "already activated #{existing_spec.full_name}"
-
- e = Gem::LoadError.new msg
- e.name = dep.name
- e.requirement = dep.requirement
-
- raise e
- end
-
- return false
- end
-
- conf = spec.conflicts
-
- unless conf.empty? then
- why = conf.map { |act,con|
- "#{act.full_name} conflicts with #{con.join(", ")}"
- }.join ", "
-
- # TODO: improve message by saying who activated `con`
-
- raise LoadError, "Unable to activate #{spec.full_name}, because #{why}"
- end
-
- spec.loaded = true
- @loaded_specs[spec.name] = spec
-
- spec.runtime_dependencies.each do |spec_dep|
- next if Gem.loaded_specs.include? spec_dep.name
- specs = Gem.source_index.search spec_dep, true
-
- if specs.size == 1 then
- self.activate spec_dep
- else
- name = spec_dep.name
- unresolved_deps[name] = unresolved_deps[name].merge spec_dep
- end
- end
-
- unresolved_deps.delete spec.name
-
- require_paths = spec.require_paths.map do |path|
- spec.full_gem_path.add(path)
- end
-
- # gem directories must come after -I and ENV['RUBYLIB']
- insert_index = load_path_insert_index
-
- if insert_index then
- # gem directories must come after -I and ENV['RUBYLIB']
- $LOAD_PATH.insert(insert_index, *require_paths)
- else
- # we are probably testing in core, -I and RUBYLIB don't apply
- $LOAD_PATH.unshift(*require_paths)
- end
-
- return true
+ def self.activate_spec spec # :nodoc:
+ spec.activate
end
def self.unresolved_deps
@@ -436,16 +342,9 @@ def self.bindir(install_dir=Gem.dir)
# mainly used by the unit tests to provide test isolation.
def self.clear_paths
-<<<<<<< HEAD
- @paths = nil
- @user_home = nil
-
-=======
- @gem_home = nil
- @gem_path = nil
- @user_home = nil
->>>>>>> minor formatting and moved all deprecations to the end of the file sorted by date.
@@source_index = nil
+ @paths = nil
+ @user_home = nil
@searcher = nil
end
@@ -1245,7 +1144,8 @@ module Kernel
def gem(gem_name, *requirements) # :doc:
skip_list = (ENV['GEM_SKIP'] || "").split(/:/)
raise Gem::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name
- Gem.activate(gem_name, *requirements)
+ spec = Gem::Dependency.new(gem_name, *requirements).to_spec
+ spec.activate if spec
end
private :gem
2  lib/rubygems/custom_require.rb
View
@@ -46,7 +46,7 @@ def require path
end
found_specs.each do |found_spec|
- Gem.activate_spec found_spec
+ found_spec.activate
end
end
17 lib/rubygems/dependency.rb
View
@@ -206,5 +206,20 @@ def merge other
self.class.new name, self_req.as_list.concat(other_req.as_list)
end
-end
+ def to_spec
+ matches = Gem.source_index.search self, true
+
+ # TODO: check Gem.activated_spec[self.name] in case matches falls outside
+
+ if matches.empty? then
+ error = Gem::LoadError.new "Could not find #{name} (#{requirement})"
+ error.name = self.name
+ error.requirement = self.requirement
+ raise error
+ end
+ # TODO: any other resolver validations should go here
+
+ matches.find { |spec| spec.loaded? } or matches.last
+ end
+end
92 lib/rubygems/specification.rb
View
@@ -447,6 +447,21 @@ def self.normalize_yaml_input(input)
end
##
+ # Find the best specification matching a dependency or a name +
+ # requirements.
+
+ def self.find name_or_dep, *requirements
+ dep = name_or_dep
+
+ unless Gem::Dependency === dep then
+ requirements = Gem::Requirement.default if requirements.empty?
+ dep = Gem::Dependency.new(dep, requirements)
+ end
+
+ dep.to_spec
+ end
+
+ ##
# Sets the rubygems_version to the current RubyGems version
def mark_version
@@ -1526,6 +1541,83 @@ def dependent_specs
runtime_dependencies.map { |dep| Gem.source_index.search dep, true }.flatten
end
+ def raise_if_conflicts
+ other = Gem.loaded_specs[self.name]
+
+ if other and self.version != other.version then
+ # This gem is already loaded. If the currently loaded gem is not in the
+ # list of candidate gems, then we have a version conflict.
+
+ msg = "can't activate #{full_name}, already activated #{other.full_name}"
+
+ e = Gem::LoadError.new msg
+ e.name = self.name
+ # TODO: e.requirement = dep.requirement
+
+ raise e
+ end
+
+ conf = self.conflicts
+
+ unless conf.empty? then
+ y = conf.map { |act,con|
+ "#{act.full_name} conflicts with #{con.join(", ")}"
+ }.join ", "
+
+ # TODO: improve message by saying who activated `con`
+
+ raise Gem::LoadError, "Unable to activate #{self.full_name}, because #{y}"
+ end
+ end
+
+ def activate
+ raise_if_conflicts
+
+ return false if Gem.loaded_specs[self.name]
+
+ self.loaded = true
+ Gem.loaded_specs[self.name] = self
+
+ activate_dependencies
+ add_self_to_load_path
+
+ return true
+ end
+
+ def add_self_to_load_path
+ require_paths = self.require_paths.map do |path|
+ self.full_gem_path.add(path)
+ end
+
+ # gem directories must come after -I and ENV['RUBYLIB']
+ insert_index = Gem.load_path_insert_index
+
+ if insert_index then
+ # gem directories must come after -I and ENV['RUBYLIB']
+ $LOAD_PATH.insert(insert_index, *require_paths)
+ else
+ # we are probably testing in core, -I and RUBYLIB don't apply
+ $LOAD_PATH.unshift(*require_paths)
+ end
+ end
+
+ def activate_dependencies
+ self.runtime_dependencies.each do |spec_dep|
+ # TODO: check for conflicts! not just name!
+ next if Gem.loaded_specs.include? spec_dep.name
+ specs = Gem.source_index.search spec_dep, true
+
+ if specs.size == 1 then
+ specs.first.activate
+ else
+ name = spec_dep.name
+ Gem.unresolved_deps[name] = Gem.unresolved_deps[name].merge spec_dep
+ end
+ end
+
+ Gem.unresolved_deps.delete self.name
+ end
+
extend Deprecate
deprecate :test_suite_file, :test_file, 2011, 10
59 test/rubygems/test_gem.rb
View
@@ -24,11 +24,11 @@ def assert_activate expected, *specs
specs.each do |spec|
case spec
when Array
- Gem.activate(*spec)
+ Gem::Specification.find(*spec).activate
when String
- Gem.activate spec
+ Gem::Specification.find(spec).activate
else
- Gem.activate spec.name
+ spec.activate
end
end
@@ -51,17 +51,19 @@ def unresolved_names
Gem.unresolved_deps.values.map(&:to_s).sort
end
+ # TODO: move these to specification
def test_self_activate_via_require
- new_spec "a", "1", "b" => "= 1"
+ a1 = new_spec "a", "1", "b" => "= 1"
new_spec "b", "1", nil, "lib/b/c.rb"
new_spec "b", "2", nil, "lib/b/c.rb"
- Gem.activate "a", "= 1"
+ a1.activate
require "b/c"
assert_equal %w(a-1 b-1), loaded_spec_names
end
+ # TODO: move these to specification
def test_self_activate_deep_unambiguous
a1 = new_spec "a", "1", "b" => "= 1"
b1 = new_spec "b", "1", "c" => "= 1"
@@ -71,7 +73,7 @@ def test_self_activate_deep_unambiguous
install_specs a1, b1, b2, c1, c2
- Gem.activate "a", "= 1"
+ a1.activate
assert_equal %w(a-1 b-1 c-1), loaded_spec_names
end
@@ -82,6 +84,7 @@ def save_loaded_features
$LOADED_FEATURES.replace old_loaded_features
end
+ # TODO: move these to specification
def test_self_activate_ambiguous_direct
save_loaded_features do
a1 = new_spec "a", "1", "b" => "> 0"
@@ -92,7 +95,7 @@ def test_self_activate_ambiguous_direct
install_specs a1, b1, b2, c1, c2
- Gem.activate "a", "= 1"
+ a1.activate
assert_equal %w(a-1), loaded_spec_names
assert_equal ["b (> 0)"], unresolved_names
@@ -103,6 +106,7 @@ def test_self_activate_ambiguous_direct
end
end
+ # TODO: move these to specification
def test_self_activate_ambiguous_indirect
save_loaded_features do
a1 = new_spec "a", "1", "b" => "> 0"
@@ -113,7 +117,7 @@ def test_self_activate_ambiguous_indirect
install_specs a1, b1, b2, c1, c2
- Gem.activate "a", "= 1"
+ a1.activate
assert_equal %w(a-1), loaded_spec_names
assert_equal ["b (> 0)"], unresolved_names
@@ -124,6 +128,7 @@ def test_self_activate_ambiguous_indirect
end
end
+ # TODO: move these to specification
def test_self_activate_ambiguous_unrelated
save_loaded_features do
a1 = new_spec "a", "1", "b" => "> 0"
@@ -135,7 +140,7 @@ def test_self_activate_ambiguous_unrelated
install_specs a1, b1, b2, c1, c2, d1
- Gem.activate "a", "= 1"
+ a1.activate
assert_equal %w(a-1), loaded_spec_names
assert_equal ["b (> 0)"], unresolved_names
@@ -146,6 +151,7 @@ def test_self_activate_ambiguous_unrelated
end
end
+ # TODO: move these to specification
def test_self_activate_ambiguous_indirect_conflict
save_loaded_features do
a1 = new_spec "a", "1", "b" => "> 0"
@@ -157,7 +163,7 @@ def test_self_activate_ambiguous_indirect_conflict
install_specs a1, a2, b1, b2, c1, c2
- Gem.activate "a", "= 2"
+ a2.activate
assert_equal %w(a-2), loaded_spec_names
assert_equal ["b (> 0)"], unresolved_names
@@ -168,13 +174,14 @@ def test_self_activate_ambiguous_indirect_conflict
end
end
+ # TODO: move these to specification
def test_require_already_activated
save_loaded_features do
a1 = new_spec "a", "1", nil, "lib/d.rb"
install_specs a1 # , a2, b1, b2, c1, c2
- Gem.activate "a", "= 1"
+ a1.activate
assert_equal %w(a-1), loaded_spec_names
assert_equal [], unresolved_names
@@ -185,6 +192,7 @@ def test_require_already_activated
end
end
+ # TODO: move these to specification
def test_require_already_activated_indirect_conflict
save_loaded_features do
a1 = new_spec "a", "1", "b" => "> 0"
@@ -196,8 +204,8 @@ def test_require_already_activated_indirect_conflict
install_specs a1, a2, b1, b2, c1, c2
- Gem.activate "a", "= 1"
- Gem.activate "c", "= 1"
+ a1.activate
+ c1.activate
assert_equal %w(a-1 c-1), loaded_spec_names
assert_equal ["b (> 0)"], unresolved_names
@@ -216,11 +224,12 @@ def test_require_missing
end
end
+ # TODO: move these to specification
def test_self_activate_loaded
- util_spec 'foo', '1'
+ foo = util_spec 'foo', '1'
- assert Gem.activate 'foo'
- refute Gem.activate 'foo'
+ assert foo.activate
+ refute foo.activate
end
##
@@ -243,15 +252,16 @@ def test_self_activate_unrelated
# [B] ~> 1.0
#
# and should resolve using b-1.0
+ # TODO: move these to specification
def test_self_activate_over
- util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0'
+ a = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0'
util_spec 'b', '1.0'
util_spec 'b', '1.1'
util_spec 'b', '2.0'
util_spec 'c', '1.0', 'b' => '~> 1.0'
- Gem.activate "a"
+ a.activate
assert_equal %w[a-1.0 c-1.0], loaded_spec_names
assert_equal ["b (>= 1.0, ~> 1.0)"], unresolved_names
@@ -672,7 +682,7 @@ def test_self_loaded_specs
install_gem foo
Gem.source_index = nil
- Gem.activate 'foo'
+ foo.activate
assert_equal true, Gem.loaded_specs.keys.include?('foo')
end
@@ -809,17 +819,6 @@ def test_self_refresh
assert_equal nil, Gem.instance_variable_get(:@searcher)
end
- def test_self_required_location
- util_make_gems
-
- assert_equal File.join(@tempdir, *%w[gemhome gems c-1.2 lib code.rb]),
- Gem.required_location("c", "code.rb")
- assert_equal File.join(@tempdir, *%w[gemhome gems a-1 lib code.rb]),
- Gem.required_location("a", "code.rb", "< 2")
- assert_equal File.join(@tempdir, *%w[gemhome gems a-2 lib code.rb]),
- Gem.required_location("a", "code.rb", "= 2")
- end
-
def test_self_ruby_escaping_spaces_in_path
orig_ruby = Gem.ruby
orig_bindir = Gem::ConfigMap[:bindir]
3  test/rubygems/test_kernel.rb
View
@@ -40,10 +40,9 @@ def test_gem_conflicting
gem 'a', '= 2'
end
- assert_match(/activate a \(= 2\)/, ex.message)
+ assert_equal "can't activate a-2, already activated a-1", ex.message
assert_match(/activated a-1/, ex.message)
assert_equal 'a', ex.name
- assert_equal Gem::Requirement.new('= 2'), ex.requirement
assert $:.any? { |p| %r{a-1/lib} =~ p }
refute $:.any? { |p| %r{a-2/lib} =~ p }
Please sign in to comment.
Something went wrong with that request. Please try again.