Permalink
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...
1 parent de3c1fc commit 3d3f699461df256614dbecbcd4bcc22e87b7842f @zenspider zenspider committed Apr 4, 2011
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
@@ -46,7 +46,7 @@ def require path
end
found_specs.each do |found_spec|
- Gem.activate_spec found_spec
+ found_spec.activate
end
end
@@ -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
@@ -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
Oops, something went wrong.

0 comments on commit 3d3f699

Please sign in to comment.