Class: Gem::Specification
- Inherits:
-
Object
- Object
- Gem::Specification
- Defined in:
- lib/rubygems/specification.rb
Overview
Gem::Specification
The Specification class contains the metadata for a Gem. Typically defined in a .gemspec file or a Rakefile, and looks like this:
spec = Gem::Specification.new do |s|
s.name = 'rfoo'
s.version = '1.0'
s.summary = 'Example gem specification'
...
end
There are many gemspec attributes, and the best place to learn about them in the “Gemspec Reference” linked from the RubyGems wiki.
Constant Summary collapse
- NONEXISTENT_SPECIFICATION_VERSION =
The the version number of a specification that does not specify one (i.e. RubyGems 0.7 or earlier).
-1
- CURRENT_SPECIFICATION_VERSION =
The specification version applied to any new Specification instances created. This should be bumped whenever something in the spec format changes.
1
- SPECIFICATION_VERSION_HISTORY =
An informal list of changes to the specification. The highest-valued key should be equal to the CURRENT_SPECIFICATION_VERSION.
{ -1 => ['(RubyGems versions up to and including 0.7 did not have versioned specifications)'], 1 => [ 'Deprecated "test_suite_file" in favor of the new, but equivalent, "test_files"', '"test_file=x" is a shortcut for "test_files=[x]"' ] }
- @@list =
List of Specification instances.
[]
- @@gather =
Optional block used to gather newly defined instances.
nil
- @@required_attributes =
List of attribute names: [:name, :version, …]
[]
- @@attributes =
List of all attributes and default values: [[:name, nil], [:bindir, ‘bin’], …]
[]
- @@array_attributes =
List of array attributes
[]
- @@default_value =
Map of attribute names to default values.
{}
Instance Attribute Summary collapse
-
#loaded ⇒ Object
writeonly
RUNTIME attributes (not persisted) —————————–.
-
#loaded_from ⇒ Object
Returns the value of attribute loaded_from.
Class Method Summary collapse
-
.array_attribute(name) ⇒ Object
Same as :attribute, but ensures that values assigned to the attribute are array values by applying :to_a to the value.
- .array_attributes ⇒ Object
-
.attribute(name, default = nil) ⇒ Object
Used to specify the name and default value of a specification attribute.
-
.attribute_alias_singular(singular, plural) ⇒ Object
Defines a singular version of an existing plural attribute (i.e. one whose value is expected to be an array).
- .attribute_defaults ⇒ Object
-
.attribute_names ⇒ Object
————————- Convenience class methods.
-
.attributes(*args) ⇒ Object
Shortcut for creating several attributes at once (each with a default value of
nil
). - .default_value(name) ⇒ Object
-
.from_yaml(input) ⇒ Object
Special loader for YAML files.
-
.list ⇒ Object
A list of Specification instances that have been defined in this Ruby instance.
- .load(filename) ⇒ Object
-
.normalize_yaml_input(input) ⇒ Object
Make sure the yaml specification is properly formatted with dashes.
-
.overwrite_accessor(name, &block) ⇒ Object
Some attributes require special behaviour when they are accessed.
-
.read_only(*names) ⇒ Object
Sometimes we don’t want the world to use a setter method for a particular attribute.
-
.required_attribute(*args) ⇒ Object
Same as attribute above, but also records this attribute as mandatory.
- .required_attribute?(name) ⇒ Boolean
- .required_attributes ⇒ Object
Instance Method Summary collapse
-
#<=>(other) ⇒ Object
Compare specs (name then version).
-
#==(other) ⇒ Object
(also: #eql?)
Tests specs for equality (across all attributes).
- #add_bindir(executables) ⇒ Object
-
#add_dependency(gem, *requirements) ⇒ Object
Adds a dependency to this Gem.
-
#dependent_gems ⇒ Object
Return a list of all gems that have a dependency on this gemspec.
-
#full_gem_path ⇒ Object
The full path to the gem (install path + full name).
-
#full_name ⇒ Object
Returns the full name (name-version) of this Gem.
- #has_rdoc? ⇒ Boolean
- #has_unit_tests? ⇒ Boolean (also: #has_test_suite?)
-
#hash ⇒ Object
:nodoc:.
-
#initialize {|_self| ... } ⇒ Specification
constructor
Specification constructor.
-
#installation_path ⇒ Object
The root directory that the gem was installed into.
-
#loaded? ⇒ Boolean
Predicates —————————————————–.
-
#mark_version ⇒ Object
Sets the rubygems_version to Gem::RubyGemsVersion.
-
#normalize ⇒ Object
Normalize the list of files so that: * All file lists have redundancies removed.
-
#satisfies_requirement?(dependency) ⇒ Boolean
Checks if this Specification meets the requirement of the supplied dependency.
-
#test_suite_file ⇒ Object
DEPRECATED gemspec attributes ———————————-.
- #test_suite_file=(val) ⇒ Object
-
#to_ruby ⇒ Object
Returns a Ruby code representation of this specification, such that it can be eval’ed and reconstruct the same specification later.
- #to_s ⇒ Object
-
#to_yaml_properties ⇒ Object
Returns an array of attribute names to be used when generating a YAML representation of this object.
-
#validate ⇒ Object
Checks that the specification contains all required fields, and does a very basic sanity check.
- #warn_deprecated(old, new) ⇒ Object
Constructor Details
#initialize {|_self| ... } ⇒ Specification
Specification constructor. Assigns the default values to the attributes, adds this spec to the list of loaded specs (see Specification.list), and yields itself for further initialization.
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
# File 'lib/rubygems/specification.rb', line 406 def initialize # Each attribute has a default value (possibly nil). Here, we # initialize all attributes to their default value. This is # done through the accessor methods, so special behaviours will # be honored. Furthermore, we take a _copy_ of the default so # each specification instance has its own empty arrays, etc. @@attributes.each do |name, default| if RUBY_VERSION >= "1.9" then self.funcall "#{name}=", copy_of(default) else self.send "#{name}=", copy_of(default) end end @loaded = false @@list << self yield self if block_given? @@gather.call(self) if @@gather end |
Instance Attribute Details
#loaded=(value) ⇒ Object (writeonly)
RUNTIME attributes (not persisted) —————————–
282 283 284 |
# File 'lib/rubygems/specification.rb', line 282 def loaded=(value) @loaded = value end |
#loaded_from ⇒ Object
Returns the value of attribute loaded_from.
283 284 285 |
# File 'lib/rubygems/specification.rb', line 283 def loaded_from @loaded_from end |
Class Method Details
.array_attribute(name) ⇒ Object
Same as :attribute, but ensures that values assigned to the attribute are array values by applying :to_a to the value.
149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/rubygems/specification.rb', line 149 def self.array_attribute(name) @@array_attributes << name @@attributes << [name, []] @@default_value[name] = [] module_eval %{ def #{name} @#{name} ||= [] end def #{name}=(value) @#{name} = value.to_a end } end |
.array_attributes ⇒ Object
115 116 117 |
# File 'lib/rubygems/specification.rb', line 115 def self.array_attributes @@array_attributes.dup end |
.attribute(name, default = nil) ⇒ Object
Used to specify the name and default value of a specification attribute. The side effects are:
-
the name and default value are added to the @@attributes list and @@default_value map
-
a standard writer method (
attribute=
) is created -
a non-standard _reader method (
attribute
) is created
The reader method behaves like this:
def attribute
@attribute ||= (copy of default value)
end
This allows lazy initialization of attributes to their default values.
141 142 143 144 145 |
# File 'lib/rubygems/specification.rb', line 141 def self.attribute(name, default=nil) @@attributes << [name, default] @@default_value[name] = default attr_accessor(name) end |
.attribute_alias_singular(singular, plural) ⇒ Object
Defines a singular version of an existing plural attribute (i.e. one whose value is expected to be an array). This means just creating a helper method that takes a single value and appends it to the array. These are created for convenience, so that in a spec, one can write
s.require_path = 'mylib'
instead of
s.require_paths = ['mylib']
That above convenience is available courtesy of
attribute_alias_singular :require_path, :require_paths
208 209 210 211 212 213 214 215 216 |
# File 'lib/rubygems/specification.rb', line 208 def self.attribute_alias_singular(singular, plural) define_method("#{singular}=") { |val| send("#{plural}=", [val]) } define_method("#{singular}") { val = send("#{plural}") val.nil? ? nil : val.first } end |
.attribute_defaults ⇒ Object
99 100 101 |
# File 'lib/rubygems/specification.rb', line 99 def self.attribute_defaults @@attributes.dup end |
.attribute_names ⇒ Object
————————- Convenience class methods.
95 96 97 |
# File 'lib/rubygems/specification.rb', line 95 def self.attribute_names @@attributes.map { |name, default| name } end |
.attributes(*args) ⇒ Object
Shortcut for creating several attributes at once (each with a default value of nil
).
179 180 181 182 183 |
# File 'lib/rubygems/specification.rb', line 179 def self.attributes(*args) args.each do |arg| attribute(arg, nil) end end |
.default_value(name) ⇒ Object
103 104 105 |
# File 'lib/rubygems/specification.rb', line 103 def self.default_value(name) @@default_value[name] end |
.from_yaml(input) ⇒ Object
Special loader for YAML files. When a Specification object is loaded from a YAML file, it bypasses the normal Ruby object initialization routine (#initialize). This method makes up for that and deals with gems of different ages.
‘input’ can be anything that YAML.load() accepts: String or IO.
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 |
# File 'lib/rubygems/specification.rb', line 432 def Specification.from_yaml(input) input = normalize_yaml_input(input) spec = YAML.load(input) if(spec && spec.class == FalseClass) then raise Gem::EndOfYAMLException end unless Specification === spec raise Gem::Exception, "YAML data doesn't evaluate to gem specification" end unless spec.instance_variables.include? '@specification_version' and spec.instance_variable_get :@specification_version spec.instance_variable_set :@specification_version, NONEXISTENT_SPECIFICATION_VERSION end spec end |
.list ⇒ Object
A list of Specification instances that have been defined in this Ruby instance.
122 123 124 |
# File 'lib/rubygems/specification.rb', line 122 def self.list @@list end |
.load(filename) ⇒ Object
449 450 451 452 453 454 455 456 457 458 |
# File 'lib/rubygems/specification.rb', line 449 def Specification.load(filename) gemspec = nil fail "NESTED Specification.load calls not allowed!" if @@gather @@gather = proc { |gs| gemspec = gs } data = File.read(filename) eval(data) gemspec ensure @@gather = nil end |
.normalize_yaml_input(input) ⇒ Object
Make sure the yaml specification is properly formatted with dashes.
461 462 463 464 465 |
# File 'lib/rubygems/specification.rb', line 461 def Specification.normalize_yaml_input(input) result = input.respond_to?(:read) ? input.read : input result = "--- " + result unless result =~ /^--- / result end |
.overwrite_accessor(name, &block) ⇒ Object
Some attributes require special behaviour when they are accessed. This allows for that.
187 188 189 190 |
# File 'lib/rubygems/specification.rb', line 187 def self.overwrite_accessor(name, &block) remove_method name define_method(name, &block) end |
.read_only(*names) ⇒ Object
Sometimes we don’t want the world to use a setter method for a particular attribute. read_only
makes it private so we can still use it internally.
171 172 173 174 175 |
# File 'lib/rubygems/specification.rb', line 171 def self.read_only(*names) names.each do |name| private "#{name}=" end end |
.required_attribute(*args) ⇒ Object
Same as attribute above, but also records this attribute as mandatory.
164 165 166 167 |
# File 'lib/rubygems/specification.rb', line 164 def self.required_attribute(*args) @@required_attributes << args.first attribute(*args) end |
.required_attribute?(name) ⇒ Boolean
111 112 113 |
# File 'lib/rubygems/specification.rb', line 111 def self.required_attribute?(name) @@required_attributes.include? name.to_sym end |
.required_attributes ⇒ Object
107 108 109 |
# File 'lib/rubygems/specification.rb', line 107 def self.required_attributes @@required_attributes.dup end |
Instance Method Details
#<=>(other) ⇒ Object
Compare specs (name then version).
534 535 536 |
# File 'lib/rubygems/specification.rb', line 534 def <=>(other) [@name, @version] <=> [other.name, other.version] end |
#==(other) ⇒ Object Also known as: eql?
Tests specs for equality (across all attributes).
539 540 541 |
# File 'lib/rubygems/specification.rb', line 539 def ==(other) # :nodoc: other.kind_of?(self.class) && same_attributes?(other) end |
#add_bindir(executables) ⇒ Object
354 355 356 357 358 359 360 361 362 363 364 365 366 |
# File 'lib/rubygems/specification.rb', line 354 def add_bindir(executables) if not defined? @executables || @executables.nil? return nil end if defined? @bindir and @bindir then @executables.map {|e| File.join(@bindir, e) } else @executables end rescue return nil end |
#add_dependency(gem, *requirements) ⇒ Object
Adds a dependency to this Gem. For example,
spec.add_dependency('jabber4r', '> 0.1', '<= 0.5')
- gem
- String or Gem::Dependency
-
The Gem name/dependency.
- requirements
- default=“> 0.0.0”
-
The version requirements.
482 483 484 485 486 487 488 489 |
# File 'lib/rubygems/specification.rb', line 482 def add_dependency(gem, *requirements) requirements = ['> 0.0.0'] if requirements.empty? requirements.flatten! unless gem.respond_to?(:name) && gem.respond_to?(:version_requirements) gem = Dependency.new(gem, requirements) end dependencies << gem end |
#dependent_gems ⇒ Object
Return a list of all gems that have a dependency on this gemspec. The list is structured with entries that conform to:
[depending_gem, dependency, [list_of_gems_that_satisfy_dependency]]
- return
- Array
- [dependent_gem, dependency, [list_of_satisfiers]]
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 |
# File 'lib/rubygems/specification.rb', line 639 def dependent_gems out = [] Gem.source_index.each do |name,gem| gem.dependencies.each do |dep| if self.satisfies_requirement?(dep) then sats = [] find_all_satisfiers(dep) do |sat| sats << sat end out << [gem, dep, sats] end end end out end |
#full_gem_path ⇒ Object
The full path to the gem (install path + full name).
- return
- String
-
the full gem path
507 508 509 |
# File 'lib/rubygems/specification.rb', line 507 def full_gem_path File.join(installation_path, "gems", full_name) end |
#full_name ⇒ Object
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).
495 496 497 498 499 500 501 |
# File 'lib/rubygems/specification.rb', line 495 def full_name if platform == Gem::Platform::RUBY || platform.nil? "#{@name}-#{@version}" else "#{@name}-#{@version}-#{platform}" end end |
#has_rdoc? ⇒ Boolean
396 |
# File 'lib/rubygems/specification.rb', line 396 def has_rdoc?; has_rdoc ? true : false ; end |
#has_unit_tests? ⇒ Boolean Also known as: has_test_suite?
397 |
# File 'lib/rubygems/specification.rb', line 397 def has_unit_tests?; not test_files.empty?; end |
#hash ⇒ Object
:nodoc:
553 554 555 556 557 558 |
# File 'lib/rubygems/specification.rb', line 553 def hash # :nodoc: @@attributes.inject(0) { |hash_code, (name, default_value)| n = self.send(name).hash hash_code + n } end |
#installation_path ⇒ Object
The root directory that the gem was installed into.
- return
- String
-
the installation path
515 516 517 518 |
# File 'lib/rubygems/specification.rb', line 515 def installation_path (File.dirname(@loaded_from).split(File::SEPARATOR)[0..-2]). join(File::SEPARATOR) end |
#loaded? ⇒ Boolean
Predicates —————————————————–
395 |
# File 'lib/rubygems/specification.rb', line 395 def loaded?; @loaded ? true : false ; end |
#mark_version ⇒ Object
Sets the rubygems_version to Gem::RubyGemsVersion.
471 472 473 |
# File 'lib/rubygems/specification.rb', line 471 def mark_version @rubygems_version = RubyGemsVersion end |
#normalize ⇒ Object
Normalize the list of files so that:
-
All file lists have redundancies removed.
-
Files referenced in the extra_rdoc_files are included in the package file list.
Also, the summary and description are converted to a normal format.
621 622 623 624 625 626 627 628 |
# File 'lib/rubygems/specification.rb', line 621 def normalize if defined? @extra_rdoc_files and @extra_rdoc_files then @extra_rdoc_files.uniq! @files ||= [] @files.concat(@extra_rdoc_files) end @files.uniq! if @files end |
#satisfies_requirement?(dependency) ⇒ Boolean
Checks if this Specification meets the requirement of the supplied dependency.
- dependency
- Gem::Dependency
-
the dependency to check
- return
- Boolean
-
true if dependency is met, otherwise false
526 527 528 529 |
# File 'lib/rubygems/specification.rb', line 526 def satisfies_requirement?(dependency) return @name == dependency.name && dependency.version_requirements.satisfied_by?(@version) end |
#test_suite_file ⇒ Object
DEPRECATED gemspec attributes ———————————-
269 270 271 272 |
# File 'lib/rubygems/specification.rb', line 269 def test_suite_file warn_deprecated(:test_suite_file, :test_files) test_files.first end |
#test_suite_file=(val) ⇒ Object
274 275 276 277 278 |
# File 'lib/rubygems/specification.rb', line 274 def test_suite_file=(val) warn_deprecated(:test_suite_file, :test_files) @test_files = [] unless defined? @test_files @test_files << val end |
#to_ruby ⇒ Object
Returns a Ruby code representation of this specification, such that it can be eval’ed and reconstruct the same specification later. Attributes that still have their default values are omitted.
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 |
# File 'lib/rubygems/specification.rb', line 574 def to_ruby mark_version result = "Gem::Specification.new do |s|\n" @@attributes.each do |name, default| # TODO better implementation of next line (read_only_attribute? ... something like that) next if name == :dependencies or name == :specification_version current_value = self.send(name) result << " s.#{name} = #{ruby_code(current_value)}\n" unless current_value == default end dependencies.each do |dep| version_reqs_param = dep.requirements_list.inspect result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})\n" end result << "end\n" end |
#to_s ⇒ Object
655 656 657 |
# File 'lib/rubygems/specification.rb', line 655 def to_s "#<Gem::Specification name=#{@name} version=#{@version}>" end |
#to_yaml_properties ⇒ Object
Returns an array of attribute names to be used when generating a YAML representation of this object. If an attribute still has its default value, it is omitted.
565 566 567 568 |
# File 'lib/rubygems/specification.rb', line 565 def to_yaml_properties mark_version @@attributes.map { |name, default| "@#{name}" } end |
#validate ⇒ Object
Checks that the specification contains all required fields, and does a very basic sanity check.
Raises InvalidSpecificationException if the spec does not pass the checks..
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 |
# File 'lib/rubygems/specification.rb', line 597 def validate normalize if rubygems_version != RubyGemsVersion raise InvalidSpecificationException.new(%[ Expected RubyGems Version #{RubyGemsVersion}, was #{rubygems_version} ].strip) end @@required_attributes.each do |symbol| unless self.send(symbol) raise InvalidSpecificationException.new("Missing value for attribute #{symbol}") end end if require_paths.empty? raise InvalidSpecificationException.new("Gem spec needs to have at least one require_path") end end |
#warn_deprecated(old, new) ⇒ Object
218 219 220 221 |
# File 'lib/rubygems/specification.rb', line 218 def warn_deprecated(old, new) # How (if at all) to implement this? We only want to warn when # a gem is being built, I should think. end |