aboutsummaryrefslogtreecommitdiffstats
path: root/lib/rubygems/specification.rb
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-09-13 19:58:57 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-09-13 19:58:57 +0000
commit1daa0b113d853bfa57b776cc569939b61ca14292 (patch)
treef8c4acb08a551820299dff2b13966d6ac38d31e4 /lib/rubygems/specification.rb
parent85995e88d49c442b5b113c2676456133e79f5c02 (diff)
downloadruby-1daa0b113d853bfa57b776cc569939b61ca14292.tar.gz
* lib/rubygems: Update to RubyGems 2.1.3
Fixed installing platform gems Restored concurrent requires Fixed installing gems with extensions with --install-dir Fixed `gem fetch -v` to install the latest version Fixed installing gems with "./" in their files entries * test/rubygems/test_gem_package.rb: Tests for the above. * NEWS: Updated for RubyGems 2.1.3 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42938 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rubygems/specification.rb')
-rw-r--r--lib/rubygems/specification.rb291
1 files changed, 148 insertions, 143 deletions
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index 12943a3e24..87557cee5f 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -5,13 +5,10 @@
# See LICENSE.txt for permissions.
#++
-
require 'rubygems/version'
require 'rubygems/requirement'
require 'rubygems/platform'
require 'rubygems/deprecate'
-require 'rubygems/basic_specification'
-require 'rubygems/stub_specification'
# :stopdoc:
# date.rb can't be loaded for `make install` due to miniruby
@@ -34,7 +31,7 @@ class Date; end
# s.homepage = 'https://rubygems.org/gems/example'
# end
#
-# Starting in RubyGems 2.0, a Specification can hold arbitrary
+# Starting in RubyGems 1.9.0, a Specification can hold arbitrary
# metadata. This metadata is accessed via Specification#metadata
# and has the following restrictions:
#
@@ -48,7 +45,7 @@ class Date; end
#
# s.metadata = { "bugtracker" => "http://somewhere.com/blah" }
-class Gem::Specification < Gem::BasicSpecification
+class Gem::Specification
# REFACTOR: Consider breaking out this version stuff into a separate
# module. There's enough special stuff around it that it may justify
@@ -110,10 +107,6 @@ class Gem::Specification < Gem::BasicSpecification
today = Time.now.utc
TODAY = Time.utc(today.year, today.month, today.day)
- LOAD_CACHE = {}
-
- private_constant :LOAD_CACHE if defined? private_constant
-
# :startdoc:
##
@@ -163,17 +156,6 @@ class Gem::Specification < Gem::BasicSpecification
:version => nil,
}
- Dupable = { }
-
- @@default_value.each do |k,v|
- case v
- when Time, Numeric, Symbol, true, false, nil
- Dupable[k] = false
- else
- Dupable[k] = true
- end
- end
-
@@attributes = @@default_value.keys.sort_by { |s| s.to_s }
@@array_attributes = @@default_value.reject { |k,v| v != [] }.keys
@@nil_attributes, @@non_nil_attributes = @@default_value.keys.partition { |k|
@@ -458,7 +440,7 @@ class Gem::Specification < Gem::BasicSpecification
#
# For example, the rake gem has rake as an executable. You don’t specify the
# full path (as in bin/rake); all application-style files are expected to be
- # found in bindir. These files must be executable Ruby files. Files that
+ # found in bindir. These files must be executable ruby files. Files that
# use bash or other interpreters will not work.
#
# Usage:
@@ -617,12 +599,17 @@ class Gem::Specification < Gem::BasicSpecification
attr_writer :default_executable
##
+ # Path this gemspec was loaded from. This attribute is not persisted.
+
+ attr_reader :loaded_from
+
+ ##
# Allows deinstallation of gems with legacy platforms.
attr_writer :original_platform # :nodoc:
##
- # The version of Ruby required by this gem
+ # The version of ruby required by this gem
attr_reader :required_ruby_version
@@ -646,68 +633,58 @@ class Gem::Specification < Gem::BasicSpecification
attr_accessor :specification_version
- def self._all # :nodoc:
- unless defined?(@@all) && @@all then
- @@all = stubs.map(&:to_spec)
-
- # After a reset, make sure already loaded specs
- # are still marked as activated.
- specs = {}
- Gem.loaded_specs.each_value{|s| specs[s] = true}
- @@all.each{|s| s.activated = true if specs[s]}
-
- _resort!(@@all)
+ class << self
+ def default_specifications_dir
+ File.join(Gem.default_dir, "specifications", "default")
end
- @@all
- end
- def self._clear_load_cache # :nodoc:
- LOAD_CACHE.clear
- end
-
- # :nodoc:
- def self.each_gemspec(dirs)
- dirs.each do |dir|
- Dir[File.join(dir, "*.gemspec")].each do |path|
- yield path.untaint
- end
+ def each_spec(search_dirs) # :nodoc:
+ search_dirs.each { |dir|
+ Dir[File.join(dir, "*.gemspec")].each { |path|
+ spec = Gem::Specification.load path.untaint
+ # #load returns nil if the spec is bad, so we just ignore
+ # it at this stage
+ yield(spec) if spec
+ }
+ }
end
- end
- # :nodoc:
- def self.each_stub(dirs)
- each_gemspec(dirs) do |path|
- stub = Gem::StubSpecification.new(path)
- yield stub if stub.valid?
+ def each_default(&block) # :nodoc:
+ each_spec([default_specifications_dir],
+ &block)
end
- end
- # :nodoc:
- def self.each_spec(dirs)
- each_gemspec(dirs) do |path|
- spec = self.load path
- yield spec if spec
+ def each_normal(&block) # :nodoc:
+ each_spec(dirs, &block)
end
end
- ##
- # Returns a Gem::StubSpecification for every installed gem
+ def self._all # :nodoc:
+ unless defined?(@@all) && @@all then
- def self.stubs
- @@stubs ||= begin
- stubs = {}
- each_stub([default_specifications_dir] + dirs) do |stub|
- stubs[stub.full_name] ||= stub
+ specs = {}
+ each_default do |spec|
+ specs[spec.full_name] ||= spec
end
+ each_normal do |spec|
+ specs[spec.full_name] ||= spec
+ end
+
+ @@all = specs.values
- stubs = stubs.values
- _resort!(stubs)
- stubs
+ # After a reset, make sure already loaded specs
+ # are still marked as activated.
+ specs = {}
+ Gem.loaded_specs.each_value{|s| specs[s] = true}
+ @@all.each{|s| s.activated = true if specs[s]}
+
+ _resort!
end
+ @@all
end
- def self._resort!(specs) # :nodoc:
- specs.sort! { |a, b|
+ def self._resort! # :nodoc:
+ @@all.sort! { |a, b|
names = a.name <=> b.name
next names if names.nonzero?
b.version <=> a.version
@@ -718,9 +695,7 @@ class Gem::Specification < Gem::BasicSpecification
# Loads the default specifications. It should be called only once.
def self.load_defaults
- each_spec([default_specifications_dir]) do |spec|
- # #load returns nil if the spec is bad, so we just ignore
- # it at this stage
+ each_default do |spec|
Gem.register_default_spec(spec)
end
end
@@ -743,9 +718,7 @@ class Gem::Specification < Gem::BasicSpecification
return if _all.include? spec
_all << spec
- stubs << spec
- _resort!(_all)
- _resort!(stubs)
+ _resort!
end
##
@@ -786,7 +759,7 @@ class Gem::Specification < Gem::BasicSpecification
# -- wilsonb
def self.all= specs
- @@all = @@stubs = specs
+ @@all = specs
end
##
@@ -888,10 +861,9 @@ class Gem::Specification < Gem::BasicSpecification
# amongst the specs that are not activated.
def self.find_inactive_by_path path
- stub = stubs.find { |s|
- s.contains_requirable_file? path unless s.activated?
+ self.find { |spec|
+ spec.contains_requirable_file? path unless spec.activated?
}
- stub && stub.to_spec
end
##
@@ -972,7 +944,7 @@ class Gem::Specification < Gem::BasicSpecification
result.map(&:last).map(&:values).flatten.reject { |spec|
minimum = native[spec.name]
minimum && spec.version < minimum
- }.sort_by{ |tup| tup.name }
+ }
end
##
@@ -983,9 +955,6 @@ class Gem::Specification < Gem::BasicSpecification
file = file.dup.untaint
return unless File.file?(file)
- spec = LOAD_CACHE[file]
- return spec if spec
-
code = if defined? Encoding
File.read file, :mode => 'r:UTF-8:-'
else
@@ -999,7 +968,6 @@ class Gem::Specification < Gem::BasicSpecification
if Gem::Specification === spec
spec.loaded_from = file.to_s
- LOAD_CACHE[file] = spec
return spec
end
@@ -1034,43 +1002,25 @@ class Gem::Specification < Gem::BasicSpecification
end
##
- # Return a list of all outdated local gem names. This method is HEAVY
+ # Return a list of all outdated specifications. This method is HEAVY
# as it must go fetch specifications from the server.
- #
- # Use outdated_and_latest_version if you wish to retrieve the latest remote
- # version as well.
def self.outdated
- outdated_and_latest_version.map { |local, _| local.name }
- end
-
- ##
- # Enumerates the outdated local gems yielding the local specification and
- # the latest remote version.
- #
- # This method may take some time to return as it must check each local gem
- # against the server's index.
-
- def self.outdated_and_latest_version
- return enum_for __method__ unless block_given?
+ outdateds = []
# TODO: maybe we should switch to rubygems' version service?
fetcher = Gem::SpecFetcher.fetcher
- latest_specs(true).each do |local_spec|
- dependency =
- Gem::Dependency.new local_spec.name, ">= #{local_spec.version}"
+ latest_specs(true).each do |local|
+ dependency = Gem::Dependency.new local.name, ">= #{local.version}"
+ remotes, _ = fetcher.search_for_dependency dependency
+ remotes = remotes.map { |n, _| n.version }
+ latest = remotes.sort.last
- remotes, = fetcher.search_for_dependency dependency
- remotes = remotes.map { |n, _| n.version }
-
- latest_remote = remotes.sort.last
-
- yield [local_spec, latest_remote] if
- latest_remote and local_spec.version < latest_remote
+ outdateds << local.name if latest and local.version < latest
end
- nil
+ outdateds
end
##
@@ -1081,7 +1031,6 @@ class Gem::Specification < Gem::BasicSpecification
raise "wtf: #{spec.full_name} not in #{all_names.inspect}" unless
_all.include? spec
_all.delete spec
- stubs.delete_if { |s| s.full_name == spec.full_name }
end
##
@@ -1106,8 +1055,6 @@ class Gem::Specification < Gem::BasicSpecification
@@dirs = nil
Gem.pre_reset_hooks.each { |hook| hook.call }
@@all = nil
- @@stubs = nil
- _clear_load_cache
unresolved = unresolved_deps
unless unresolved.empty? then
w = "W" + "ARN"
@@ -1354,6 +1301,20 @@ class Gem::Specification < Gem::BasicSpecification
end
##
+ # Returns the full path to the base gem directory.
+ #
+ # eg: /usr/local/lib/ruby/gems/1.8
+
+ def base_dir
+ return Gem.dir unless loaded_from
+ @base_dir ||= if default_gem? then
+ File.dirname File.dirname File.dirname loaded_from
+ else
+ File.dirname File.dirname loaded_from
+ end
+ end
+
+ ##
# Returns the full path to installed gem's bin directory.
#
# NOTE: do not confuse this with +bindir+, which is just 'bin', not
@@ -1427,6 +1388,19 @@ class Gem::Specification < Gem::BasicSpecification
end
##
+ # Return true if this spec can require +file+.
+
+ def contains_requirable_file? file
+ root = full_gem_path
+ suffixes = Gem.suffixes
+
+ require_paths.any? do |lib|
+ base = "#{root}/#{lib}/#{file}"
+ suffixes.any? { |suf| File.file? "#{base}#{suf}" }
+ end
+ end
+
+ ##
# The date this gem was created. Lazily defaults to the current UTC date.
#
# There is no need to set this in your gem specification.
@@ -1671,14 +1645,35 @@ class Gem::Specification < Gem::BasicSpecification
spec
end
- # :nodoc:
- def find_full_gem_path
- super || File.expand_path(File.join(gems_dir, original_name))
+ ##
+ # The full path to the gem (install path + full name).
+
+ def full_gem_path
+ # TODO: This is a heavily used method by gems, so we'll need
+ # to aleast just alias it to #gem_dir rather than remove it.
+
+ # TODO: also, shouldn't it default to full_name if it hasn't been written?
+ return @full_gem_path if defined?(@full_gem_path) && @full_gem_path
+
+ @full_gem_path = File.expand_path File.join(gems_dir, full_name)
+ @full_gem_path.untaint
+
+ return @full_gem_path if File.directory? @full_gem_path
+
+ @full_gem_path = File.expand_path File.join(gems_dir, original_name)
end
- private :find_full_gem_path
+
+ ##
+ # Returns the full name (name-version) of this Gem. Platform information
+ # is included (name-version-platform) if it is specified and not the
+ # default Ruby platform.
def full_name
- @full_name ||= super
+ @full_name ||= if platform == Gem::Platform::RUBY or platform.nil? then
+ "#{@name}-#{@version}".untaint
+ else
+ "#{@name}-#{@version}-#{platform}".untaint
+ end
end
##
@@ -1690,6 +1685,15 @@ class Gem::Specification < Gem::BasicSpecification
end
##
+ # Returns the full path to the gems directory containing this spec's
+ # gem directory. eg: /usr/local/lib/ruby/1.8/gems
+
+ def gems_dir
+ # TODO: this logic seems terribly broken, but tests fail if just base_dir
+ @gems_dir ||= File.join(loaded_from && base_dir || Gem.dir, "gems")
+ end
+
+ ##
# Deprecated and ignored, defaults to true.
#
# Formerly used to indicate this gem was RDoc-capable.
@@ -1721,7 +1725,9 @@ class Gem::Specification < Gem::BasicSpecification
# :startdoc:
def hash # :nodoc:
- name.hash ^ version.hash
+ @@attributes.inject(0) { |hash_code, (name, _)|
+ hash_code ^ self.send(name).hash
+ }
end
def init_with coder # :nodoc:
@@ -1736,7 +1742,7 @@ class Gem::Specification < Gem::BasicSpecification
def initialize name = nil, version = nil
@loaded = false
@activated = false
- self.loaded_from = nil
+ @loaded_from = nil
@original_platform = nil
@@nil_attributes.each do |key|
@@ -1745,7 +1751,11 @@ class Gem::Specification < Gem::BasicSpecification
@@non_nil_attributes.each do |key|
default = default_value(key)
- value = Dupable[key] ? default.dup : default
+ value = case default
+ when Time, Numeric, Symbol, true, false, nil then default
+ else default.dup
+ end
+
instance_variable_set "@#{key}", value
end
@@ -1840,14 +1850,22 @@ class Gem::Specification < Gem::BasicSpecification
@licenses ||= []
end
- def loaded_from= path # :nodoc:
- super
+ ##
+ # Set the location a Specification was loaded from. +obj+ is converted
+ # to a String.
+
+ def loaded_from= path
+ @loaded_from = path.to_s
+ # reset everything @loaded_from depends upon
+ @base_dir = nil
@bin_dir = nil
@cache_dir = nil
@cache_file = nil
@doc_dir = nil
+ @full_gem_path = nil
@gem_dir = nil
+ @gems_dir = nil
@ri_dir = nil
@spec_dir = nil
@spec_file = nil
@@ -2032,10 +2050,6 @@ class Gem::Specification < Gem::BasicSpecification
@requirements = Array req
end
- def respond_to_missing? m, include_private = false # :nodoc:
- false
- end
-
##
# Returns the full path to this spec's ri directory.
@@ -2097,17 +2111,11 @@ class Gem::Specification < Gem::BasicSpecification
# Returns an object you can use to sort specifications in #sort_by.
def sort_obj
+ # TODO: this is horrible. Deprecate it.
[@name, @version, @new_platform == Gem::Platform::RUBY ? -1 : 1]
end
##
- # Used by Gem::DependencyResolver to order Gem::Specification objects
-
- def source # :nodoc:
- self
- end
-
- ##
# Returns the full path to the directory containing this spec's
# gemspec file. eg: /usr/local/lib/ruby/gems/1.8/specifications
@@ -2186,7 +2194,6 @@ class Gem::Specification < Gem::BasicSpecification
mark_version
result = []
result << "# -*- encoding: utf-8 -*-"
- result << "#{Gem::StubSpecification::PREFIX}#{name} #{version} #{platform} #{require_paths.join("\0")}"
result << nil
result << "Gem::Specification.new do |s|"
@@ -2274,13 +2281,6 @@ class Gem::Specification < Gem::BasicSpecification
"#<Gem::Specification name=#{@name} version=#{@version}>"
end
- ##
- # Returns self
-
- def to_spec
- self
- end
-
def to_yaml(opts = {}) # :nodoc:
if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? then
# Because the user can switch the YAML engine behind our
@@ -2581,6 +2581,11 @@ class Gem::Specification < Gem::BasicSpecification
end
end
+ def default_gem?
+ loaded_from &&
+ File.dirname(loaded_from) == self.class.default_specifications_dir
+ end
+
extend Gem::Deprecate
# TODO: